* - add: Flash protection for wiz hardsuit helmet.

* - tweak: Cheaper wiz melee weapons.

* - add: Rework alt lightning.

* - fix: Timestop fixes.

* - add: Don't end round on midround wizard death.

* - tweak: Better shield.

* - fix: Some fixes.

* - fix: Fix wizard teleport pulling.

* - add: Improve arc.

* - add: Update knock.

* - add: Update knock desc.

* - add: Arcane Barrage.
This commit is contained in:
Aviu00
2024-06-22 12:55:50 +00:00
committed by GitHub
parent 5137493c4c
commit dccd8aab1a
41 changed files with 394 additions and 52 deletions

View File

@@ -205,7 +205,8 @@ public sealed partial class ExplosionSystem
MapCoordinates epicenter, MapCoordinates epicenter,
HashSet<EntityUid> processed, HashSet<EntityUid> processed,
string id, string id,
float? fireStacks) float? fireStacks,
bool ignoreResistances) // WD
{ {
var size = grid.Comp.TileSize; var size = grid.Comp.TileSize;
var gridBox = new Box2(tile * size, (tile + 1) * size); var gridBox = new Box2(tile * size, (tile + 1) * size);
@@ -224,7 +225,7 @@ public sealed partial class ExplosionSystem
// process those entities // process those entities
foreach (var (uid, xform) in list) foreach (var (uid, xform) in list)
{ {
ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks); ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks, ignoreResistances); // WD EDIT
} }
// process anchored entities // process anchored entities
@@ -234,7 +235,7 @@ public sealed partial class ExplosionSystem
foreach (var entity in _anchored) foreach (var entity in _anchored)
{ {
processed.Add(entity); processed.Add(entity);
ProcessEntity(entity, epicenter, damage, throwForce, id, null, fireStacks); ProcessEntity(entity, epicenter, damage, throwForce, id, null, fireStacks, ignoreResistances); // WD EDIT
} }
// Walls and reinforced walls will break into girders. These girders will also be considered turf-blocking for // Walls and reinforced walls will break into girders. These girders will also be considered turf-blocking for
@@ -270,7 +271,7 @@ public sealed partial class ExplosionSystem
{ {
// Here we only throw, no dealing damage. Containers n such might drop their entities after being destroyed, but // Here we only throw, no dealing damage. Containers n such might drop their entities after being destroyed, but
// they should handle their own damage pass-through, with their own damage reduction calculation. // they should handle their own damage pass-through, with their own damage reduction calculation.
ProcessEntity(uid, epicenter, null, throwForce, id, xform, null); ProcessEntity(uid, epicenter, null, throwForce, id, xform, null, ignoreResistances); // WD EDIT
} }
return !tileBlocked; return !tileBlocked;
@@ -306,7 +307,8 @@ public sealed partial class ExplosionSystem
MapCoordinates epicenter, MapCoordinates epicenter,
HashSet<EntityUid> processed, HashSet<EntityUid> processed,
string id, string id,
float? fireStacks) float? fireStacks,
bool ignoreResistances) // WD
{ {
var gridBox = Box2.FromDimensions(tile * DefaultTileSize, new Vector2(DefaultTileSize, DefaultTileSize)); var gridBox = Box2.FromDimensions(tile * DefaultTileSize, new Vector2(DefaultTileSize, DefaultTileSize));
var worldBox = spaceMatrix.TransformBox(gridBox); var worldBox = spaceMatrix.TransformBox(gridBox);
@@ -322,7 +324,7 @@ public sealed partial class ExplosionSystem
foreach (var (uid, xform) in state.Item1) foreach (var (uid, xform) in state.Item1)
{ {
processed.Add(uid); processed.Add(uid);
ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks); ProcessEntity(uid, epicenter, damage, throwForce, id, xform, fireStacks, ignoreResistances);
} }
if (throwForce <= 0) if (throwForce <= 0)
@@ -336,7 +338,7 @@ public sealed partial class ExplosionSystem
foreach (var (uid, xform) in list) foreach (var (uid, xform) in list)
{ {
ProcessEntity(uid, epicenter, null, throwForce, id, xform, fireStacks); ProcessEntity(uid, epicenter, null, throwForce, id, xform, fireStacks, ignoreResistances);
} }
} }
@@ -434,7 +436,8 @@ public sealed partial class ExplosionSystem
float throwForce, float throwForce,
string id, string id,
TransformComponent? xform, TransformComponent? xform,
float? fireStacksOnIgnite) float? fireStacksOnIgnite,
bool ignoreResistances) // WD
{ {
if (originalDamage != null) if (originalDamage != null)
{ {
@@ -442,7 +445,7 @@ public sealed partial class ExplosionSystem
foreach (var (entity, damage) in _toDamage) foreach (var (entity, damage) in _toDamage)
{ {
// TODO EXPLOSIONS turn explosions into entities, and pass the the entity in as the damage origin. // TODO EXPLOSIONS turn explosions into entities, and pass the the entity in as the damage origin.
_damageableSystem.TryChangeDamage(entity, damage, ignoreResistances: true); _damageableSystem.TryChangeDamage(entity, damage, ignoreResistances: ignoreResistances); // WD EDIT
} }
} }
@@ -827,7 +830,8 @@ sealed class Explosion
Epicenter, Epicenter,
ProcessedEntities, ProcessedEntities,
ExplosionType.ID, ExplosionType.ID,
ExplosionType.FireStacks); ExplosionType.FireStacks,
ExplosionType.IgnoreResistances); // WD
// If the floor is not blocked by some dense object, damage the floor tiles. // If the floor is not blocked by some dense object, damage the floor tiles.
if (canDamageFloor) if (canDamageFloor)
@@ -845,7 +849,8 @@ sealed class Explosion
Epicenter, Epicenter,
ProcessedEntities, ProcessedEntities,
ExplosionType.ID, ExplosionType.ID,
ExplosionType.FireStacks); ExplosionType.FireStacks,
ExplosionType.IgnoreResistances); // WD
} }
if (!MoveNext()) if (!MoveNext())

View File

@@ -10,6 +10,7 @@ using Content.Shared.Body.Components;
using Content.Shared.Coordinates.Helpers; using Content.Shared.Coordinates.Helpers;
using Content.Shared.Doors.Components; using Content.Shared.Doors.Components;
using Content.Shared.Doors.Systems; using Content.Shared.Doors.Systems;
using Content.Shared.Lock;
using Content.Shared.Magic; using Content.Shared.Magic;
using Content.Shared.Magic.Events; using Content.Shared.Magic.Events;
using Content.Shared.Maps; using Content.Shared.Maps;
@@ -46,6 +47,7 @@ public sealed class MagicSystem : EntitySystem
[Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly ChatSystem _chat = default!;
[Dependency] private readonly WizardSpellsSystem _wizardSpells = default!; [Dependency] private readonly WizardSpellsSystem _wizardSpells = default!;
[Dependency] private readonly LockSystem _lock = default!;
public override void Initialize() public override void Initialize()
{ {
@@ -177,6 +179,9 @@ public sealed class MagicSystem : EntitySystem
if (TryComp<DoorComponent>(entity, out var doorComp) && doorComp.State is not DoorState.Open) if (TryComp<DoorComponent>(entity, out var doorComp) && doorComp.State is not DoorState.Open)
_doorSystem.StartOpening(entity); _doorSystem.StartOpening(entity);
if (TryComp<LockComponent>(entity, out var lockComp) && lockComp.Locked)
_lock.Unlock(entity, null, lockComp);
} }
} }

View File

@@ -0,0 +1,20 @@
namespace Content.Server._White.Wizard.GravPulseOnStartup;
[RegisterComponent]
public sealed partial class GravPulseOnStartupComponent : Component
{
[DataField]
public float MaxRange;
[DataField]
public float MinRange;
[DataField]
public float BaseRadialAcceleration;
[DataField]
public float BaseTangentialAcceleration;
[DataField]
public float StunTime;
}

View File

@@ -0,0 +1,22 @@
using Content.Server.Singularity.EntitySystems;
namespace Content.Server._White.Wizard.GravPulseOnStartup;
public sealed class GravPulseOnStartupSystem : EntitySystem
{
[Dependency] private readonly GravityWellSystem _gravityWell = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<GravPulseOnStartupComponent, ComponentStartup>(OnStartup);
}
private void OnStartup(Entity<GravPulseOnStartupComponent> ent, ref ComponentStartup args)
{
var (uid, comp) = ent;
_gravityWell.GravPulse(Transform(uid).Coordinates, comp.MaxRange, comp.MinRange, comp.BaseRadialAcceleration,
comp.BaseTangentialAcceleration, comp.StunTime);
}
}

View File

@@ -1,4 +1,8 @@
namespace Content.Server._White.Wizard.Magic.TeslaProjectile; namespace Content.Server._White.Wizard.Magic.TeslaProjectile;
[RegisterComponent] [RegisterComponent]
public sealed partial class TeslaProjectileComponent : Component {} public sealed partial class TeslaProjectileComponent : Component
{
[ViewVariables]
public EntityUid? Caster;
}

View File

@@ -16,6 +16,6 @@ public sealed class TeslaProjectileSystem : EntitySystem
private void OnStartCollide(Entity<TeslaProjectileComponent> ent, ref ProjectileHitEvent args) private void OnStartCollide(Entity<TeslaProjectileComponent> ent, ref ProjectileHitEvent args)
{ {
_lightning.ShootRandomLightnings(ent, 2, 4, arcDepth:2); _lightning.ShootRandomLightnings(ent, 3, 4, "WizardLightning", 2, false, ent.Comp.Caster);
} }
} }

View File

@@ -4,6 +4,7 @@ using Content.Server._White.Cult;
using Content.Server._White.IncorporealSystem; using Content.Server._White.IncorporealSystem;
using Content.Server._White.Wizard.Magic.Amaterasu; using Content.Server._White.Wizard.Magic.Amaterasu;
using Content.Server._White.Wizard.Magic.Other; using Content.Server._White.Wizard.Magic.Other;
using Content.Server._White.Wizard.Magic.TeslaProjectile;
using Content.Server._White.Wizard.Teleport; using Content.Server._White.Wizard.Teleport;
using Content.Server.Abilities.Mime; using Content.Server.Abilities.Mime;
using Content.Server.Administration.Commands; using Content.Server.Administration.Commands;
@@ -86,6 +87,7 @@ public sealed class WizardSpellsSystem : EntitySystem
{ {
base.Initialize(); base.Initialize();
SubscribeLocalEvent<ArcaneBarrageSpellEvent>(OnArcaneBarrage);
SubscribeLocalEvent<StopTimeSpellEvent>(OnTimeStop); SubscribeLocalEvent<StopTimeSpellEvent>(OnTimeStop);
SubscribeLocalEvent<MindswapSpellEvent>(OnMindswapSpell); SubscribeLocalEvent<MindswapSpellEvent>(OnMindswapSpell);
SubscribeLocalEvent<TeleportSpellEvent>(OnTeleportSpell); SubscribeLocalEvent<TeleportSpellEvent>(OnTeleportSpell);
@@ -105,6 +107,29 @@ public sealed class WizardSpellsSystem : EntitySystem
SubscribeLocalEvent<MagicComponent, BeforeCastSpellEvent>(OnBeforeCastSpell); SubscribeLocalEvent<MagicComponent, BeforeCastSpellEvent>(OnBeforeCastSpell);
} }
#region Arcane Barrage
private void OnArcaneBarrage(ArcaneBarrageSpellEvent msg)
{
if (!CanCast(msg))
return;
var uid = msg.Performer;
var entity = Spawn(msg.Prototype, Transform(uid).Coordinates);
if (!_handsSystem.TryPickupAnyHand(uid, entity))
{
_popupSystem.PopupEntity(Loc.GetString("arcane-barrage-no-empty-hand"), uid, uid);
QueueDel(entity);
_actions.SetCooldown(msg.Action, TimeSpan.FromSeconds(1));
return;
}
msg.Handled = true;
}
#endregion
#region Timestop #region Timestop
private void OnTimeStop(StopTimeSpellEvent msg) private void OnTimeStop(StopTimeSpellEvent msg)
@@ -803,6 +828,7 @@ public sealed class WizardSpellsSystem : EntitySystem
userVelocity = physics.LinearVelocity; userVelocity = physics.LinearVelocity;
var ent = Spawn(msg.Prototype, spawnCoords); var ent = Spawn(msg.Prototype, spawnCoords);
EnsureComp<TeslaProjectileComponent>(ent).Caster = msg.Performer;
var direction = msg.Target.ToMapPos(EntityManager, _transformSystem) - var direction = msg.Target.ToMapPos(EntityManager, _transformSystem) -
spawnCoords.ToMapPos(EntityManager, _transformSystem); spawnCoords.ToMapPos(EntityManager, _transformSystem);
_gunSystem.ShootProjectile(ent, direction, userVelocity, msg.Performer, msg.Performer); _gunSystem.ShootProjectile(ent, direction, userVelocity, msg.Performer, msg.Performer);

View File

@@ -2,6 +2,8 @@
using Content.Server.Popups; using Content.Server.Popups;
using Content.Shared._White.Wizard.Teleport; using Content.Shared._White.Wizard.Teleport;
using Content.Shared.Eui; using Content.Shared.Eui;
using Content.Shared.Movement.Pulling.Components;
using Content.Shared.Movement.Pulling.Systems;
using Robust.Shared.Timing; using Robust.Shared.Timing;
namespace Content.Server._White.Wizard.Teleport; namespace Content.Server._White.Wizard.Teleport;
@@ -11,6 +13,7 @@ public sealed class WizardTeleportSpellEui : BaseEui
[Dependency] private readonly EntityManager _entityManager = default!; [Dependency] private readonly EntityManager _entityManager = default!;
private readonly SharedTransformSystem _transformSystem; private readonly SharedTransformSystem _transformSystem;
private readonly TeleportLocationSystem _teleportLocation; private readonly TeleportLocationSystem _teleportLocation;
private readonly PullingSystem _pulling;
private readonly PopupSystem _popupSystem; private readonly PopupSystem _popupSystem;
private readonly EntityUid _performer; private readonly EntityUid _performer;
@@ -22,6 +25,7 @@ public sealed class WizardTeleportSpellEui : BaseEui
IoCManager.InjectDependencies(this); IoCManager.InjectDependencies(this);
_transformSystem = _entityManager.System<SharedTransformSystem>(); _transformSystem = _entityManager.System<SharedTransformSystem>();
_pulling = _entityManager.System<PullingSystem>();
_teleportLocation = _entityManager.System<TeleportLocationSystem>(); _teleportLocation = _entityManager.System<TeleportLocationSystem>();
_popupSystem = _entityManager.System<PopupSystem>(); _popupSystem = _entityManager.System<PopupSystem>();
@@ -82,6 +86,19 @@ public sealed class WizardTeleportSpellEui : BaseEui
_used = true; _used = true;
// break pulls before portal enter so we dont break shit
if (_entityManager.TryGetComponent<PullableComponent>(_performer, out var pullable) && pullable.BeingPulled)
{
_pulling.TryStopPull(_performer, pullable);
}
if (_entityManager.TryGetComponent<PullerComponent>(_performer, out var pulling)
&& pulling.Pulling != null
&& _entityManager.TryGetComponent<PullableComponent>(pulling.Pulling.Value, out var subjectPulling))
{
_pulling.TryStopPull(pulling.Pulling.Value, subjectPulling);
}
var coords = locationTransform.Coordinates; var coords = locationTransform.Coordinates;
_transformSystem.SetCoordinates(_performer, coords); _transformSystem.SetCoordinates(_performer, coords);

View File

@@ -4,4 +4,6 @@ namespace Content.Server._White.Wizard;
[RegisterComponent] [RegisterComponent]
public sealed partial class WizardComponent : Component public sealed partial class WizardComponent : Component
{ {
[ViewVariables(VVAccess.ReadWrite)]
public bool EndRoundOnDeath;
} }

View File

@@ -125,7 +125,7 @@ public sealed class WizardRuleSystem : GameRuleSystem<WizardRuleComponent>
private void OnMobStateChanged(EntityUid uid, WizardComponent component, MobStateChangedEvent ev) private void OnMobStateChanged(EntityUid uid, WizardComponent component, MobStateChangedEvent ev)
{ {
if (ev.NewMobState == MobState.Dead) if (ev.NewMobState == MobState.Dead && component.EndRoundOnDeath)
CheckAnnouncement(); CheckAnnouncement();
} }
@@ -149,7 +149,7 @@ public sealed class WizardRuleSystem : GameRuleSystem<WizardRuleComponent>
return; return;
} }
SetupWizardEntity(uid, wizardSpawner.Points, gear, profile); SetupWizardEntity(uid, gear, profile, false);
} }
private void OnMindAdded(EntityUid uid, WizardComponent component, MindAddedMessage args) private void OnMindAdded(EntityUid uid, WizardComponent component, MindAddedMessage args)
@@ -280,11 +280,11 @@ public sealed class WizardRuleSystem : GameRuleSystem<WizardRuleComponent>
private void SetupWizardEntity( private void SetupWizardEntity(
EntityUid mob, EntityUid mob,
int points,
StartingGearPrototype gear, StartingGearPrototype gear,
HumanoidCharacterProfile? profile) HumanoidCharacterProfile? profile,
bool endRoundOnDeath)
{ {
EnsureComp<WizardComponent>(mob); EnsureComp<WizardComponent>(mob).EndRoundOnDeath = endRoundOnDeath;
profile ??= HumanoidCharacterProfile.RandomWithSpecies(); profile ??= HumanoidCharacterProfile.RandomWithSpecies();
@@ -346,7 +346,7 @@ public sealed class WizardRuleSystem : GameRuleSystem<WizardRuleComponent>
return; return;
} }
SetupWizardEntity(mob, component.Points, gear, profile); SetupWizardEntity(mob, gear, profile, true);
var newMind = _mind.CreateMind(session.UserId, name); var newMind = _mind.CreateMind(session.UserId, name);
_mind.SetUserId(newMind, session.UserId); _mind.SetUserId(newMind, session.UserId);

View File

@@ -10,9 +10,6 @@ public sealed partial class WizardSpawnerComponent : Component
[DataField("name")] [DataField("name")]
public string Name = "Ololo The Balls' Twister"; public string Name = "Ololo The Balls' Twister";
[DataField("points")]
public int Points = 10;
[DataField("startingGear")] [DataField("startingGear")]
public ProtoId<StartingGearPrototype> StartingGear = "WizardGear"; public ProtoId<StartingGearPrototype> StartingGear = "WizardGear";

View File

@@ -110,6 +110,11 @@ public sealed partial class ExplosionPrototype : IPrototype
[DataField("fireStates")] [DataField("fireStates")]
public int FireStates = 3; public int FireStates = 3;
// WD START
[DataField]
public bool IgnoreResistances = true;
// WD END
/// <summary> /// <summary>
/// Basic function for linear interpolation of the _tileBreakChance and _tileBreakIntensity arrays /// Basic function for linear interpolation of the _tileBreakChance and _tileBreakIntensity arrays
/// </summary> /// </summary>

View File

@@ -540,6 +540,10 @@ public abstract partial class SharedGunSystem : EntitySystem
gun.UseKey = useKey; gun.UseKey = useKey;
} }
public void SetClumsyProof(GunComponent gun, bool clumsyProof)
{
gun.ClumsyProof = clumsyProof;
}
public void SetProjectileSpeed(EntityUid weapon, float projectileSpeed) public void SetProjectileSpeed(EntityUid weapon, float projectileSpeed)
{ {
if(!TryComp<GunComponent>(weapon, out var gunComponent)) if(!TryComp<GunComponent>(weapon, out var gunComponent))

View File

@@ -27,7 +27,7 @@ public sealed class BoltBarrageSystem : EntitySystem
SubscribeLocalEvent<BoltBarrageComponent, AttemptShootEvent>(OnShootAttempt); SubscribeLocalEvent<BoltBarrageComponent, AttemptShootEvent>(OnShootAttempt);
SubscribeLocalEvent<BoltBarrageComponent, GunShotEvent>(OnGunShot); SubscribeLocalEvent<BoltBarrageComponent, GunShotEvent>(OnGunShot);
SubscribeLocalEvent<BoltBarrageComponent, DroppedEvent>(OnDrop); SubscribeLocalEvent<BoltBarrageComponent, DroppedEvent>(OnDrop);
SubscribeLocalEvent<BoltBarrageComponent, UnequippedHandEvent>(OnUnequipHand); SubscribeLocalEvent<BoltBarrageComponent, GotUnequippedHandEvent>(OnUnequipHand);
SubscribeLocalEvent<BoltBarrageComponent, ContainerGettingRemovedAttemptEvent>(OnRemoveAttempt); SubscribeLocalEvent<BoltBarrageComponent, ContainerGettingRemovedAttemptEvent>(OnRemoveAttempt);
SubscribeLocalEvent<BoltBarrageComponent, OnEmptyGunShotEvent>(OnEmptyShot); SubscribeLocalEvent<BoltBarrageComponent, OnEmptyGunShotEvent>(OnEmptyShot);
SubscribeLocalEvent<BoltBarrageComponent, ExaminedEvent>(OnExamine); SubscribeLocalEvent<BoltBarrageComponent, ExaminedEvent>(OnExamine);
@@ -38,7 +38,7 @@ public sealed class BoltBarrageSystem : EntitySystem
args.PushMarkup(Loc.GetString("bolt-barrage-component-extra-desc")); args.PushMarkup(Loc.GetString("bolt-barrage-component-extra-desc"));
} }
private void OnUnequipHand(Entity<BoltBarrageComponent> ent, ref UnequippedHandEvent args) private void OnUnequipHand(Entity<BoltBarrageComponent> ent, ref GotUnequippedHandEvent args)
{ {
if (_net.IsServer && ent.Comp.Unremoveable) if (_net.IsServer && ent.Comp.Unremoveable)
QueueDel(ent); QueueDel(ent);
@@ -82,12 +82,12 @@ public sealed class BoltBarrageSystem : EntitySystem
private void OnShootAttempt(Entity<BoltBarrageComponent> ent, ref AttemptShootEvent args) private void OnShootAttempt(Entity<BoltBarrageComponent> ent, ref AttemptShootEvent args)
{ {
if (!HasComp<CultistComponent>(args.User) && !HasComp<GhostComponent>(args.User)) /*if (!HasComp<CultistComponent>(args.User) && !HasComp<GhostComponent>(args.User))
{ {
args.Cancelled = true; args.Cancelled = true;
args.Message = Loc.GetString("bolt-barrage-component-not-cultist"); args.Message = Loc.GetString("bolt-barrage-component-not-cultist");
return; return;
} }*/
if (_hands.EnumerateHands(args.User).Any(hand => hand.IsEmpty)) if (_hands.EnumerateHands(args.User).Any(hand => hand.IsEmpty))
return; return;

View File

@@ -102,6 +102,7 @@ public abstract class SharedSpellBladeSystem : EntitySystem
{ {
var gun = EnsureComp<GunComponent>(uid); var gun = EnsureComp<GunComponent>(uid);
_gun.SetUseKey(gun, false); _gun.SetUseKey(gun, false);
_gun.SetClumsyProof(gun, true);
_gun.SetSound(uid, new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/Magic/staff_healing.ogg")); _gun.SetSound(uid, new SoundPathSpecifier("/Audio/Weapons/Guns/Gunshots/Magic/staff_healing.ogg"));
_gun.SetFireRate(uid, 1.2f); _gun.SetFireRate(uid, 1.2f);
var ammoProvider = EnsureComp<BasicEntityAmmoProviderComponent>(uid); var ammoProvider = EnsureComp<BasicEntityAmmoProviderComponent>(uid);

View File

@@ -8,6 +8,7 @@ using Content.Shared.Inventory.Events;
using Content.Shared.Item; using Content.Shared.Item;
using Content.Shared.Movement.Events; using Content.Shared.Movement.Events;
using Content.Shared.Speech; using Content.Shared.Speech;
using Content.Shared.Standing.Systems;
using Content.Shared.Throwing; using Content.Shared.Throwing;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Physics; using Robust.Shared.Physics;
@@ -30,11 +31,14 @@ public sealed class FreezeContactsSystem : EntitySystem
SubscribeLocalEvent<FreezeContactsComponent, StartCollideEvent>(OnEntityEnter); SubscribeLocalEvent<FreezeContactsComponent, StartCollideEvent>(OnEntityEnter);
SubscribeLocalEvent<FreezeContactsComponent, EndCollideEvent>(OnEntityExit); SubscribeLocalEvent<FreezeContactsComponent, EndCollideEvent>(OnEntityExit);
SubscribeLocalEvent<FrozenComponent, ComponentInit>(OnInit); SubscribeLocalEvent<FrozenComponent, ComponentInit>(OnInit);
SubscribeLocalEvent<FrozenComponent, ComponentRemove>(OnRemove); SubscribeLocalEvent<FrozenComponent, ComponentRemove>(OnRemove);
SubscribeLocalEvent<FrozenComponent, PreventCollideEvent>(OnPreventCollide); SubscribeLocalEvent<FrozenComponent, PreventCollideEvent>(OnPreventCollide);
SubscribeLocalEvent<FrozenComponent, EntGotInsertedIntoContainerMessage>(OnGetInserted); SubscribeLocalEvent<FrozenComponent, EntGotInsertedIntoContainerMessage>(OnGetInserted);
SubscribeLocalEvent<FrozenComponent, StandAttemptEvent>(OnAttempt);
SubscribeLocalEvent<FrozenComponent, DownAttemptEvent>(OnAttempt);
SubscribeLocalEvent<FrozenComponent, SpeakAttemptEvent>(OnAttempt); SubscribeLocalEvent<FrozenComponent, SpeakAttemptEvent>(OnAttempt);
SubscribeLocalEvent<FrozenComponent, EmoteAttemptEvent>(OnAttempt); SubscribeLocalEvent<FrozenComponent, EmoteAttemptEvent>(OnAttempt);
SubscribeLocalEvent<FrozenComponent, ChangeDirectionAttemptEvent>(OnAttempt); SubscribeLocalEvent<FrozenComponent, ChangeDirectionAttemptEvent>(OnAttempt);
@@ -152,21 +156,25 @@ public sealed class FreezeContactsSystem : EntitySystem
private void OnEntityEnter(Entity<FreezeContactsComponent> ent, ref StartCollideEvent args) private void OnEntityEnter(Entity<FreezeContactsComponent> ent, ref StartCollideEvent args)
{ {
var hadFrozen = HasComp<FrozenComponent>(args.OtherEntity); FreezeEm(args.OtherEntity, ent);
var frozen = EnsureComp<FrozenComponent>(args.OtherEntity); }
if (!TryComp(ent, out TimedDespawnComponent? timedDespawn)) private void FreezeEm(EntityUid uid, EntityUid freezeContact)
{
if (HasComp<FrozenComponent>(uid))
return;
var frozen = EnsureComp<FrozenComponent>(uid);
if (!TryComp(freezeContact, out TimedDespawnComponent? timedDespawn))
return; return;
frozen.Lifetime = timedDespawn.Lifetime; frozen.Lifetime = timedDespawn.Lifetime;
if (TryComp(args.OtherEntity, out TimedDespawnComponent? otherTimedDespawn)) if (TryComp(uid, out TimedDespawnComponent? otherTimedDespawn))
otherTimedDespawn.Lifetime += timedDespawn.Lifetime; otherTimedDespawn.Lifetime += timedDespawn.Lifetime;
if (hadFrozen) if (!TryComp(uid, out ThrownItemComponent? thrownItem))
return;
if (!TryComp(args.OtherEntity, out ThrownItemComponent? thrownItem))
return; return;
if (thrownItem.LandTime != null) if (thrownItem.LandTime != null)

View File

@@ -193,4 +193,13 @@ public sealed partial class StopTimeSpellEvent : InstantActionEvent, ISpeakSpell
public string? Speech { get; private set; } public string? Speech { get; private set; }
} }
public sealed partial class ArcaneBarrageSpellEvent : InstantActionEvent, ISpeakSpell
{
[DataField("prototype", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string Prototype = default!;
[DataField("speech")]
public string? Speech { get; private set; }
}
#endregion #endregion

View File

@@ -18,6 +18,7 @@ scroll-component-teleport = телепортацию
scroll-component-smite = кару scroll-component-smite = кару
scroll-component-mindswap = подмену сознания scroll-component-mindswap = подмену сознания
scroll-component-timestop = остановку времени scroll-component-timestop = остановку времени
scroll-component-barrage = магический залп
ent-BaseScroll = магический свиток ent-BaseScroll = магический свиток
.desc = Этот древний пергамент, ставший реликвией в арканных преданиях, хранит в себе бесчисленные мистические заклятия и забытые заклинания. .desc = Этот древний пергамент, ставший реликвией в арканных преданиях, хранит в себе бесчисленные мистические заклятия и забытые заклинания.
@@ -55,3 +56,5 @@ ent-ScrollMindswap = свиток подмены сознания
.desc = { ent-BaseScroll.desc } .desc = { ent-BaseScroll.desc }
ent-ScrollTimestop = свиток остановки времени ent-ScrollTimestop = свиток остановки времени
.desc = { ent-BaseScroll.desc } .desc = { ent-BaseScroll.desc }
ent-ScrollArcaneBarrage = свиток магического залпа
.desc = { ent-BaseScroll.desc }

View File

@@ -46,6 +46,9 @@ spellbook-mindswap-desc = { ent-ActionMindswapSpell.desc }
spellbook-timestop-name = { ent-ActionTimestopSpell } spellbook-timestop-name = { ent-ActionTimestopSpell }
spellbook-timestop-desc = { ent-ActionTimestopSpell.desc } spellbook-timestop-desc = { ent-ActionTimestopSpell.desc }
spellbook-barrage-name = { ent-ActionArcaneBarrageSpell }
spellbook-barrage-desc = { ent-ActionArcaneBarrageSpell.desc }
spellbook-hardsuit-name = Скафандр волшебника spellbook-hardsuit-name = Скафандр волшебника
spellbook-hardsuit-desc = Украшенный магическими драгоценными камнями скафандр, функционирующий так же, как и обычная мантия волшебника, но в то же время является пригодным для использования в космосе и бронированным. Небольшое замедление. Теперь вы можете произносить заклинания в космосе и местах с низкой температурой! Имеет функцию энергетического щита,который защищает от всех снарядов. Щит разряжается при получении урона и автоматически заряжается. spellbook-hardsuit-desc = Украшенный магическими драгоценными камнями скафандр, функционирующий так же, как и обычная мантия волшебника, но в то же время является пригодным для использования в космосе и бронированным. Небольшое замедление. Теперь вы можете произносить заклинания в космосе и местах с низкой температурой! Имеет функцию энергетического щита,который защищает от всех снарядов. Щит разряжается при получении урона и автоматически заряжается.

View File

@@ -38,7 +38,7 @@ ent-ActionTeleportSpell = Телепортация
.desc = Позволяет телепортироваться в любое место на станции! Переносит вас в выбранное место. .desc = Позволяет телепортироваться в любое место на станции! Переносит вас в выбранное место.
ent-ActionKnock = Стук ent-ActionKnock = Стук
.desc = Открывает все двери и шлюзы в радиусе 4 тайлов. .desc = Открывает все двери, шлюзы и шкафы в радиусе 5 тайлов.
ent-ActionSmite = Кара ent-ActionSmite = Кара
.desc = Заряжает вашу руку мерзкой энергией, которую можно использовать для взрыва жертв. Заклинание требует, чтобы вы коснулись своей цели, поэтому вы не сможете использовать его в наручниках или будучи оглушённым. Не работает без волшебной мантии и шляпы. .desc = Заряжает вашу руку мерзкой энергией, которую можно использовать для взрыва жертв. Заклинание требует, чтобы вы коснулись своей цели, поэтому вы не сможете использовать его в наручниках или будучи оглушённым. Не работает без волшебной мантии и шляпы.
@@ -48,3 +48,6 @@ ent-ActionMindswapSpell = Подмена сознания
ent-ActionTimestopSpell = Остановка времени ent-ActionTimestopSpell = Остановка времени
.desc = Останавливает время в радиусе вокруг вас. Находящиеся под воздействием существа не смогут двигаться, а пролетающие мимо снаряды будут остановлены до окончания остановки времени. Не работает без волшебной мантии и шляпы. .desc = Останавливает время в радиусе вокруг вас. Находящиеся под воздействием существа не смогут двигаться, а пролетающие мимо снаряды будут остановлены до окончания остановки времени. Не работает без волшебной мантии и шляпы.
ent-ActionArcaneBarrageSpell = Магический залп
.desc = Выстрелите потоком магической энергии в ваших врагов с помощью этого мощного заклинания. Для использования требуются обе свободные руки. Не работает без волшебной мантии и шляпы.

View File

@@ -36,6 +36,11 @@ ent-ClothingOuterRealWizardFancy = мантия волшебника
ent-ClothingHeadHelmetWizardHelmArmored = шлем мага ent-ClothingHeadHelmetWizardHelmArmored = шлем мага
.desc = Странный головной убор, который наверняка принадлежит настоящему магу. Не обладает свойствами волшебной шляпы. .desc = Странный головной убор, который наверняка принадлежит настоящему магу. Не обладает свойствами волшебной шляпы.
ent-ArcaneBarrage = магический залп
.desc = Пиу Пиу Пиу.
arcane-barrage-no-empty-hand = Вам нужна свободная рука для использования заклинания!
mindswap-success = Ваш разум подменили! mindswap-success = Ваш разум подменили!
mindswap-borer-failed = Его разумом кто-то управляет. mindswap-borer-failed = Его разумом кто-то управляет.

View File

@@ -15,7 +15,7 @@
Blunt: 0.5 Blunt: 0.5
Slash: 0.5 Slash: 0.5
Piercing: 0.5 Piercing: 0.5
Shock: 1.2 Shock: 0 # for lightning explosions
Structural: 0.5 Structural: 0.5
flatReductions: flatReductions:
Blunt: 10 Blunt: 10
@@ -26,7 +26,7 @@
- type: damageModifierSet - type: damageModifierSet
id: StructuralMetallic id: StructuralMetallic
coefficients: coefficients:
Shock: 1.2 Shock: 0 # for lightning explosions
Heat: 1.2 Heat: 1.2
flatReductions: flatReductions:
Blunt: 10 Blunt: 10
@@ -42,6 +42,7 @@
Slash: 0.25 Slash: 0.25
Piercing: 0.75 Piercing: 0.75
Heat: 0.9 Heat: 0.9
Shock: 0 # for lightning explosions
flatReductions: flatReductions:
Blunt: 5 Blunt: 5
@@ -50,7 +51,7 @@
coefficients: coefficients:
Blunt: 2 Blunt: 2
Piercing: 0.2 Piercing: 0.2
Shock: 0.6 Shock: 0 # for lightning explosions
flatReductions: flatReductions:
Piercing: 10 Piercing: 10

View File

@@ -546,6 +546,8 @@
Piercing: 0.9 Piercing: 0.9
Heat: 0.9 Heat: 0.9
- type: WizardClothes - type: WizardClothes
- type: FlashImmunity
- type: EyeProtection
#Organic Space Suit #Organic Space Suit
- type: entity - type: entity

View File

@@ -697,7 +697,7 @@
- PowerCell - PowerCell
- PowerCellSmall - PowerCellSmall
- type: EnergyDomeGenerator - type: EnergyDomeGenerator
damageEnergyDraw: 20 damageEnergyDraw: 15
domePrototype: EnergyDomeSmallPink domePrototype: EnergyDomeSmallPink
- type: ClothingSpeedModifier - type: ClothingSpeedModifier
walkModifier: 0.9 walkModifier: 0.9

View File

@@ -220,21 +220,21 @@
- type: Projectile - type: Projectile
damage: damage:
types: types:
Caustic: 10 Shock: 10
- type: Sprite - type: Sprite
sprite: Structures/Power/Generation/Tesla/energy_miniball.rsi sprite: Structures/Power/Generation/Tesla/energy_miniball.rsi
layers: layers:
- state: tesla_projectile - state: tesla_projectile
shader: unshaded shader: unshaded
- type: Explosive - type: Explosive
explosionType: Default explosionType: Shock
maxIntensity: 100 maxIntensity: 40
intensitySlope: 0.1 intensitySlope: 6
totalIntensity: 0.3 totalIntensity: 200
maxTileBreak: 0 maxTileBreak: 0
- type: StunOnCollide - type: StunOnCollide
stunAmount: 2 stunAmount: 6
knockdownAmount: 2 knockdownAmount: 6
- type: TeslaProjectile - type: TeslaProjectile
- type: entity - type: entity
@@ -276,4 +276,3 @@
- 0, 0, 1, 0.4 - 0, 0, 1, 0.4
- 1, 0, 1, 0.25 - 1, 0, 1, 0.25
- 1, 0, 0, 0.1 - 1, 0, 0, 0.1
optionsConcealable: true

View File

@@ -1441,4 +1441,45 @@
- type: Projectile - type: Projectile
damage: damage:
types: types:
Piercing: 20 Piercing: 25
- type: entity
name: arcane bolt
id: ArcaneBolt
parent: BaseBullet
noSpawn: true
components:
- type: Sprite
sprite: White/Objects/Weapons/arcane_barrage.rsi
state: bullet
- type: Ammo
muzzleFlash: null
- type: Projectile
damage:
types:
Heat: 25
- type: Fixtures
fixtures:
projectile:
shape:
!type:PhysShapeAabb
bounds: "-0.2,-0.2,0.2,0.2"
hard: false
mask:
- Opaque
fly-by: *flybyfixture
- type: Trail
splineIteratorType: Linear
splineRendererType: Continuous
creationMethod: OnMove
scale: 0.05, 0.0
lifetime: 0.5
randomWalk: 0.001, 0.001
gravity: 0, 0
gradient:
- 1, 0, 0.75, 1
- 1, 0, 0.75, 0
- type: PointLight
radius: 1.7
color: purple
energy: 0.7

View File

@@ -15,4 +15,5 @@
sprite: Objects/Magic/magicactions.rsi sprite: Objects/Magic/magicactions.rsi
state: knock state: knock
event: !type:KnockSpellEvent event: !type:KnockSpellEvent
range: 5
speech: action-speech-spell-knock speech: action-speech-spell-knock

View File

@@ -29,8 +29,8 @@
prototype: ProjectileTeslaBall prototype: ProjectileTeslaBall
posData: !type:TargetCasterPos posData: !type:TargetCasterPos
- type: VariableUseDelay - type: VariableUseDelay
useDelay: 6 useDelay: 5
altUseDelay: 12 altUseDelay: 5
chargeUseDelay: 30 chargeUseDelay: 30
- type: entity - type: entity
@@ -361,3 +361,19 @@
event: !type:StopTimeSpellEvent event: !type:StopTimeSpellEvent
prototype: Timestop prototype: Timestop
speech: "TOKI YO TOMARE!" speech: "TOKI YO TOMARE!"
- type: entity
id: ActionArcaneBarrageSpell
name: Arcane barrage
noSpawn: true
components:
- type: Magic
requiresClothes: true
- type: InstantAction
useDelay: 75
itemIconStyle: BigAction
icon:
sprite: Objects/Magic/magicactions.rsi
state: arcane_barrage
event: !type:ArcaneBarrageSpellEvent
prototype: ArcaneBarrage

View File

@@ -25,6 +25,8 @@
capacity: 25 capacity: 25
- type: BoltBarrage - type: BoltBarrage
- type: GiftIgnore - type: GiftIgnore
- type: CultItem
canPickUp: false
- type: cultistFactoryProduction - type: cultistFactoryProduction
id: FactoryCultBloodBarrage id: FactoryCultBloodBarrage

View File

@@ -29,3 +29,6 @@
- type: TimedDespawn - type: TimedDespawn
lifetime: 10 lifetime: 10
- type: FreezeContacts - type: FreezeContacts
- type: GravPulseOnStartup # Because physics sucks
maxRange: 2.5
baseRadialAcceleration: 0.1

View File

@@ -169,3 +169,12 @@
- type: Scroll - type: Scroll
actionId: ActionTimestopSpell actionId: ActionTimestopSpell
learnPopup: scroll-component-timestop learnPopup: scroll-component-timestop
- type: entity
id: ScrollArcaneBarrage
parent: BaseScroll
name: "Arcane barrage scroll"
components:
- type: Scroll
actionId: ActionArcaneBarrageSpell
learnPopup: scroll-component-barrage

View File

@@ -104,3 +104,31 @@
Structural: 80 Structural: 80
- type: ChangeThrowForce - type: ChangeThrowForce
throwForce: 20 throwForce: 20
- type: entity
name: arcane barrage
parent: BaseItem
id: ArcaneBarrage
description: Pew Pew Pew.
components:
- type: Sprite
sprite: White/Objects/Weapons/arcane_barrage.rsi
state: icon
- type: Item
size: Ginormous
sprite: White/Objects/Weapons/arcane_barrage.rsi
- type: AmmoCounter
- type: Gun
fireRate: 4
selectedMode: SemiAuto
availableModes:
- SemiAuto
soundEmpty: null
soundGunshot:
path: /Audio/Weapons/emitter.ogg
clumsyProof: true
- type: BasicEntityAmmoProvider
proto: ArcaneBolt
capacity: 30
- type: BoltBarrage
- type: GiftIgnore

View File

@@ -110,6 +110,22 @@
- !type:ListingLimitedStockCondition - !type:ListingLimitedStockCondition
stock: 1 stock: 1
- type: listing
id: SpellBookArcaneBarrage
name: spellbook-barrage-name
description: spellbook-barrage-desc
icon:
sprite: Objects/Magic/magicactions.rsi
state: arcane_barrage
productEntity: ScrollArcaneBarrage
cost:
SpellPoint: 2
categories:
- AttackSpells
conditions:
- !type:ListingLimitedStockCondition
stock: 1
- type: listing - type: listing
id: SpellBookBlink id: SpellBookBlink
name: spellbook-blink-name name: spellbook-blink-name
@@ -273,7 +289,7 @@
description: spellbook-hfrequency-desc description: spellbook-hfrequency-desc
productEntity: HighFrequencyBlade productEntity: HighFrequencyBlade
cost: cost:
SpellPoint: 2 SpellPoint: 1
categories: categories:
- MagicItems - MagicItems
conditions: conditions:
@@ -286,7 +302,7 @@
description: spellbook-spellblade-desc description: spellbook-spellblade-desc
productEntity: SpellBlade productEntity: SpellBlade
cost: cost:
SpellPoint: 2 SpellPoint: 1
categories: categories:
- MagicItems - MagicItems
conditions: conditions:

View File

@@ -150,3 +150,16 @@
fireColor: Green fireColor: Green
texturePath: /Textures/Effects/fire_greyscale.rsi texturePath: /Textures/Effects/fire_greyscale.rsi
fireStates: 3 fireStates: 3
- type: explosion
id: Shock
damagePerIntensity:
types:
Shock: 15
tileBreakChance: [0]
tileBreakIntensity: [0]
lightColor: "#B3CEFF"
fireColor: "#B3CEFF"
texturePath: /Textures/Effects/fire_greyscale.rsi
fireStates: 3
ignoreResistances: false

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

View File

@@ -63,6 +63,9 @@
}, },
{ {
"name": "time" "name": "time"
},
{
"name": "arcane_barrage"
} }
] ]
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 370 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 667 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 799 B

View File

@@ -0,0 +1,69 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
"copyright": "Taken from tgstation",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "inhand-left",
"directions": 4,
"delays": [
[
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1
]
]
},
{
"name": "inhand-right",
"directions": 4,
"delays": [
[
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1
],
[
0.1,
0.1,
0.1
]
]
},
{
"name": "bullet"
}
]
}