diff --git a/Content.Client/UserInterface/Systems/Actions/ChargeActionSystem.cs b/Content.Client/UserInterface/Systems/Actions/ChargeActionSystem.cs
index d14c075c29..69660882a6 100644
--- a/Content.Client/UserInterface/Systems/Actions/ChargeActionSystem.cs
+++ b/Content.Client/UserInterface/Systems/Actions/ChargeActionSystem.cs
@@ -2,6 +2,8 @@
using Content.Shared._White.Wizard;
using Content.Shared._White.Wizard.Charging;
using Content.Shared.Actions;
+using Content.Shared.Mobs.Systems;
+using Content.Shared.StatusEffect;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Input;
@@ -24,6 +26,8 @@ public sealed class ChargeActionSystem : SharedChargingSystem
[Dependency] private readonly SharedTransformSystem _transformSystem = default!;
[Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IInputManager _inputManager = default!;
+ [Dependency] private readonly MobStateSystem _mobState = default!;
+ [Dependency] private readonly StatusEffectsSystem _statusEffects = default!;
private ActionUIController? _controller;
@@ -55,6 +59,9 @@ public sealed class ChargeActionSystem : SharedChargingSystem
if (_playerManager.LocalEntity is not { } user)
return;
+ if (!_mobState.IsAlive(user) || _statusEffects.HasStatusEffect(user, "Incorporeal"))
+ return;
+
if (!_timing.IsFirstTimePredicted || _controller == null || _controller.SelectingTargetFor is not { } actionId)
return;
diff --git a/Content.Server/Beam/BeamSystem.cs b/Content.Server/Beam/BeamSystem.cs
index 33f2f252d9..a3e5c75e26 100644
--- a/Content.Server/Beam/BeamSystem.cs
+++ b/Content.Server/Beam/BeamSystem.cs
@@ -1,5 +1,6 @@
using System.Numerics;
using Content.Server.Beam.Components;
+using Content.Server.Electrocution;
using Content.Shared.Beam;
using Content.Shared.Beam.Components;
using Content.Shared.Physics;
@@ -65,7 +66,7 @@ public sealed class BeamSystem : SharedBeamSystem
/// The virtual beam controller that this beam will use. If one doesn't exist it will be created here.
/// Optional sprite state for the if it needs a dynamic one
/// Optional shader for the and if it needs something other than default
- private void CreateBeam(string prototype,
+ private IEnumerable CreateBeam(string prototype,
Angle userAngle,
Vector2 calculatedDistance,
MapCoordinates beamStartPos,
@@ -78,8 +79,10 @@ public sealed class BeamSystem : SharedBeamSystem
var ent = Spawn(prototype, beamSpawnPos);
var shape = new EdgeShape(distanceCorrection, new Vector2(0,0));
+ yield return ent;
+
if (!TryComp(ent, out var physics) || !TryComp(ent, out var beam))
- return;
+ yield break;
FixturesComponent? manager = null;
_fixture.TryCreateFixture(
@@ -120,6 +123,7 @@ public sealed class BeamSystem : SharedBeamSystem
{
beamSpawnPos = beamSpawnPos.Offset(calculatedDistance.Normalized());
var newEnt = Spawn(prototype, beamSpawnPos);
+ yield return newEnt;
var ev = new BeamVisualizerEvent(GetNetEntity(newEnt), distanceLength, userAngle, bodyState, shader);
RaiseNetworkEvent(ev);
@@ -139,10 +143,10 @@ public sealed class BeamSystem : SharedBeamSystem
/// Optional sprite state for the if a default one is not given
/// Optional shader for the if a default one is not given
///
- public void TryCreateBeam(EntityUid user, EntityUid target, string bodyPrototype, string? bodyState = null, string shader = "unshaded", EntityUid? controller = null)
+ public IEnumerable TryCreateBeam(EntityUid user, EntityUid target, string bodyPrototype, string? bodyState = null, string shader = "unshaded", EntityUid? controller = null)
{
if (Deleted(user) || Deleted(target))
- return;
+ yield break;
var userMapPos = Transform(user).MapPosition;
var targetMapPos = Transform(target).MapPosition;
@@ -152,14 +156,14 @@ public sealed class BeamSystem : SharedBeamSystem
var userAngle = calculatedDistance.ToWorldAngle();
if (userMapPos.MapId != targetMapPos.MapId)
- return;
+ yield break;
//Where the start of the beam will spawn
var beamStartPos = userMapPos.Offset(calculatedDistance.Normalized());
//Don't divide by zero
if (calculatedDistance.Length() == 0)
- return;
+ yield break;
if (controller != null && TryComp(controller, out var controllerBeamComp))
{
@@ -169,7 +173,12 @@ public sealed class BeamSystem : SharedBeamSystem
var distanceCorrection = calculatedDistance - calculatedDistance.Normalized();
- CreateBeam(bodyPrototype, userAngle, calculatedDistance, beamStartPos, distanceCorrection, controller, bodyState, shader);
+ var ents = CreateBeam(bodyPrototype, userAngle, calculatedDistance, beamStartPos, distanceCorrection, controller, bodyState, shader);
+
+ foreach (var ent in ents)
+ {
+ yield return ent;
+ }
var ev = new CreateBeamSuccessEvent(user, target);
RaiseLocalEvent(user, ev);
diff --git a/Content.Server/Electrocution/Components/ElectrifiedComponent.cs b/Content.Server/Electrocution/Components/ElectrifiedComponent.cs
index 65a539eb08..6b281ebb8d 100644
--- a/Content.Server/Electrocution/Components/ElectrifiedComponent.cs
+++ b/Content.Server/Electrocution/Components/ElectrifiedComponent.cs
@@ -85,4 +85,11 @@ public sealed partial class ElectrifiedComponent : Component
[DataField("shockVolume")]
public float ShockVolume = 20;
+
+ // WD EDIT START
+ [DataField]
+ public bool IgnoreInsulation;
+
+ public EntityUid? Caster;
+ // WD EDIT END
}
diff --git a/Content.Server/Electrocution/ElectrocutionSystem.cs b/Content.Server/Electrocution/ElectrocutionSystem.cs
index f61e586de4..48f503c68a 100644
--- a/Content.Server/Electrocution/ElectrocutionSystem.cs
+++ b/Content.Server/Electrocution/ElectrocutionSystem.cs
@@ -219,7 +219,7 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
_appearance.SetData(uid, ElectrifiedVisuals.IsPowered, true);
siemens *= electrified.SiemensCoefficient;
- if (!DoCommonElectrocutionAttempt(targetUid, uid, ref siemens) || siemens <= 0)
+ if (targetUid != electrified.Caster && !DoCommonElectrocutionAttempt(targetUid, uid, ref siemens, electrified.IgnoreInsulation) || siemens <= 0) // WD EDIT
return false; // If electrocution would fail, do nothing.
var targets = new List<(EntityUid entity, int depth)>();
@@ -230,13 +230,19 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
for (var i = targets.Count - 1; i >= 0; i--)
{
var (entity, depth) = targets[i];
+
+ if (entity == electrified.Caster) // WD
+ continue;
+
lastRet = TryDoElectrocution(
entity,
uid,
(int) (electrified.ShockDamage * MathF.Pow(RecursiveDamageMultiplier, depth)),
TimeSpan.FromSeconds(electrified.ShockTime * MathF.Pow(RecursiveTimeMultiplier, depth)),
true,
- electrified.SiemensCoefficient
+ electrified.SiemensCoefficient,
+ null, // WD EDIT START
+ electrified.IgnoreInsulation // WD EDIT END
);
}
@@ -518,4 +524,4 @@ public sealed class ElectrocutionSystem : SharedElectrocutionSystem
_audio.PlayPvs(electrified.ShockNoises, targetUid, AudioParams.Default.WithVolume(electrified.ShockVolume));
}
-}
\ No newline at end of file
+}
diff --git a/Content.Server/Lightning/LightningSystem.cs b/Content.Server/Lightning/LightningSystem.cs
index 6f5a86b0bb..2286555325 100644
--- a/Content.Server/Lightning/LightningSystem.cs
+++ b/Content.Server/Lightning/LightningSystem.cs
@@ -1,6 +1,7 @@
using System.Linq;
using Content.Server.Beam;
using Content.Server.Beam.Components;
+using Content.Server.Electrocution;
using Content.Server.Lightning.Components;
using Content.Shared.Lightning;
using Robust.Shared.Random;
@@ -45,10 +46,16 @@ public sealed class LightningSystem : SharedLightningSystem
/// Where the lightning fires to
/// The prototype for the lightning to be created
/// if the lightnings being fired should trigger lightning events.
- public void ShootLightning(EntityUid user, EntityUid target, string lightningPrototype = "Lightning", bool triggerLightningEvents = true)
+ public void ShootLightning(EntityUid user, EntityUid target, string lightningPrototype = "Lightning", bool triggerLightningEvents = true, EntityUid? caster = null) // WD EDIT
{
var spriteState = LightningRandomizer();
- _beam.TryCreateBeam(user, target, lightningPrototype, spriteState);
+ var ents = _beam.TryCreateBeam(user, target, lightningPrototype, spriteState); // WD EDIT START
+ foreach (var ent in ents)
+ {
+ if (TryComp(ent, out ElectrifiedComponent? electrified))
+ electrified.Caster = caster;
+ }
+ // WD EDIT END
if (triggerLightningEvents) // we don't want certain prototypes to trigger lightning level events
{
@@ -66,7 +73,7 @@ public sealed class LightningSystem : SharedLightningSystem
/// The prototype for the lightning to be created
/// how many times to recursively fire lightning bolts from the target points of the first shot.
/// if the lightnings being fired should trigger lightning events.
- public void ShootRandomLightnings(EntityUid user, float range, int boltCount, string lightningPrototype = "Lightning", int arcDepth = 0, bool triggerLightningEvents = true)
+ public void ShootRandomLightnings(EntityUid user, float range, int boltCount, string lightningPrototype = "Lightning", int arcDepth = 0, bool triggerLightningEvents = true, EntityUid? caster = null) // WD EDIT
{
//To Do: add support to different priority target tablem for different lightning types
//To Do: Remove Hardcode LightningTargetComponent (this should be a parameter of the SharedLightningComponent)
@@ -89,10 +96,10 @@ public sealed class LightningSystem : SharedLightningSystem
if (!_random.Prob(curTarget.HitProbability)) //Chance to ignore target
continue;
- ShootLightning(user, targets[count].Owner, lightningPrototype, triggerLightningEvents);
+ ShootLightning(user, targets[count].Owner, lightningPrototype, triggerLightningEvents, caster); // WD EDIT
if (arcDepth - targets[count].LightningResistance > 0)
{
- ShootRandomLightnings(targets[count].Owner, range, 1, lightningPrototype, arcDepth - targets[count].LightningResistance, triggerLightningEvents);
+ ShootRandomLightnings(targets[count].Owner, range, 1, lightningPrototype, arcDepth - targets[count].LightningResistance, triggerLightningEvents, caster); // WD EDIT
}
shootCount++;
}
diff --git a/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs b/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs
index f1d0af6f90..d66d78abfd 100644
--- a/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs
+++ b/Content.Server/Singularity/EntitySystems/GravityWellSystem.cs
@@ -1,5 +1,6 @@
using Content.Server.Atmos.Components;
using Content.Server.Singularity.Components;
+using Content.Server.Stunnable;
using Content.Shared.Ghost;
using Content.Shared.Singularity.EntitySystems;
using Robust.Shared.Map;
@@ -24,6 +25,7 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
[Dependency] private readonly EntityLookupSystem _lookup = default!;
[Dependency] private readonly SharedPhysicsSystem _physics = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly StunSystem _stun = default!; // WD EDIT
#endregion Dependencies
///
@@ -141,10 +143,10 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
/// The base radial velocity that will be added to entities within range towards the center of the gravitational pulse.
/// The base tangential velocity that will be added to entities within countrclockwise around the center of the gravitational pulse.
/// (optional) The transform of the entity at the epicenter of the gravitational pulse.
- public void GravPulse(EntityUid uid, float maxRange, float minRange, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f, TransformComponent? xform = null)
+ public void GravPulse(EntityUid uid, float maxRange, float minRange, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f, TransformComponent? xform = null, float stunTime = 0f, List? ignore = null)
{
if (Resolve(uid, ref xform))
- GravPulse(xform.Coordinates, maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV);
+ GravPulse(xform.Coordinates, maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV, stunTime, ignore);
}
///
@@ -165,8 +167,8 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
/// The minimum distance at which entities can be affected by the gravity pulse.
/// The base radial velocity that will be added to entities within range towards the center of the gravitational pulse.
/// The base tangential velocity that will be added to entities within countrclockwise around the center of the gravitational pulse.
- public void GravPulse(EntityCoordinates entityPos, float maxRange, float minRange, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f)
- => GravPulse(entityPos.ToMap(EntityManager, _transform), maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV);
+ public void GravPulse(EntityCoordinates entityPos, float maxRange, float minRange, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f, float stunTime = 0f, List? ignore = null)
+ => GravPulse(entityPos.ToMap(EntityManager, _transform), maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV, stunTime, ignore);
///
/// Causes a gravitational pulse, shoving around all entities within some distance of an epicenter.
@@ -175,7 +177,7 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
/// The maximum distance at which entities can be affected by the gravity pulse.
/// The minimum distance at which entities can be affected by the gravity pulse. Exists to prevent div/0 errors.
/// The base velocity added to any entities within affected by the gravity pulse scaled by the displacement of those entities from the epicenter.
- public void GravPulse(MapCoordinates mapPos, float maxRange, float minRange, in Matrix3 baseMatrixDeltaV)
+ public void GravPulse(MapCoordinates mapPos, float maxRange, float minRange, in Matrix3 baseMatrixDeltaV, float stunTime = 0f, List? ignore = null)
{
if (mapPos == MapCoordinates.Nullspace)
return; // No gravpulses in nullspace please.
@@ -187,6 +189,9 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
foreach(var entity in _lookup.GetEntitiesInRange(mapPos.MapId, epicenter, maxRange, flags: LookupFlags.Dynamic | LookupFlags.Sundries))
{
+ if (ignore?.Contains(entity) is true)
+ continue;
+
if (!bodyQuery.TryGetComponent(entity, out var physics)
|| physics.BodyType == BodyType.Static)
{
@@ -206,6 +211,8 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
var scaling = (1f / distance2) * physics.Mass; // TODO: Variable falloff gradiants.
_physics.ApplyLinearImpulse(entity, (displacement * baseMatrixDeltaV) * scaling, body: physics);
+ if (stunTime > 0f)
+ _stun.TryParalyze(entity, TimeSpan.FromSeconds(stunTime), true);
}
}
@@ -217,12 +224,12 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
/// The minimum distance at which entities can be affected by the gravity pulse. Exists to prevent div/0 errors.
/// The base amount of velocity that will be added to entities in range towards the epicenter of the pulse.
/// The base amount of velocity that will be added to entities in range counterclockwise relative to the epicenter of the pulse.
- public void GravPulse(MapCoordinates mapPos, float maxRange, float minRange = 0.0f, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f)
+ public void GravPulse(MapCoordinates mapPos, float maxRange, float minRange = 0.0f, float baseRadialDeltaV = 0.0f, float baseTangentialDeltaV = 0.0f, float stunTime = 0f, List? ignore = null)
=> GravPulse(mapPos, maxRange, minRange, new Matrix3(
baseRadialDeltaV, +baseTangentialDeltaV, 0.0f,
-baseTangentialDeltaV, baseRadialDeltaV, 0.0f,
0.0f, 0.0f, 1.0f
- ));
+ ), stunTime, ignore);
#endregion GravPulse
diff --git a/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs b/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs
index eed87e0d7d..2b717366aa 100644
--- a/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs
+++ b/Content.Server/_White/Wizard/Magic/WizardSpellsSystem.cs
@@ -1,4 +1,4 @@
-using System.Linq;
+using System.Linq;
using System.Numerics;
using Content.Server._White.IncorporealSystem;
using Content.Server._White.Wizard.Magic.Amaterasu;
@@ -12,6 +12,7 @@ using Content.Server.Emp;
using Content.Server.Lightning;
using Content.Server.Magic;
using Content.Server.Singularity.EntitySystems;
+using Content.Server.Standing;
using Content.Server.Weapons.Ranged.Systems;
using Content.Shared._White.Wizard;
using Content.Shared._White.Wizard.Magic;
@@ -62,6 +63,7 @@ public sealed class WizardSpellsSystem : EntitySystem
[Dependency] private readonly InventorySystem _inventory = default!;
[Dependency] private readonly EmpSystem _empSystem = default!;
[Dependency] private readonly SharedActionsSystem _actions = default!;
+ [Dependency] private readonly StandingStateSystem _standing = default!;
#endregion
@@ -89,7 +91,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnInstantRecallSpell(InstantRecallSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
if (!TryComp(msg.Performer, out var handsComponent))
@@ -110,11 +112,13 @@ public sealed class WizardSpellsSystem : EntitySystem
}
recallComponent.Item = handsComponent.ActiveHandEntity.Value;
- _popupSystem.PopupEntity($"Сопряжено с {MetaData(handsComponent.ActiveHandEntity.Value).EntityName}", msg.Performer, msg.Performer);
+ _popupSystem.PopupEntity($"Сопряжено с {MetaData(handsComponent.ActiveHandEntity.Value).EntityName}",
+ msg.Performer, msg.Performer);
return;
}
- if (handsComponent.ActiveHandEntity == null && recallComponent.Item != null)
+ if (handsComponent.ActiveHandEntity == null && recallComponent.Item != null &&
+ Exists(recallComponent.Item.Value))
{
var coordsItem = Transform(recallComponent.Item.Value).Coordinates;
var coordsPerformer = Transform(msg.Performer).Coordinates;
@@ -139,12 +143,12 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnMimeTouchSpell(MimeTouchSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
if (!HasComp(msg.Target))
{
- _popupSystem.PopupEntity("Работает только на людях!", msg.Performer, msg.Performer);
+ _popupSystem.PopupEntity("Работает только на людях!", msg.Performer, msg.Performer);
return;
}
@@ -164,7 +168,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnBananaTouchSpell(BananaTouchSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
if (!HasComp(msg.Target))
@@ -188,7 +192,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnCluwneCurseSpell(CluwneCurseSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
if (!HasComp(msg.Target))
@@ -197,8 +201,7 @@ public sealed class WizardSpellsSystem : EntitySystem
return;
}
- var cluwne = EnsureComp(msg.Target);
- cluwne.KnockChance = 0.2f;
+ EnsureComp(msg.Target);
Spawn("AdminInstantEffectSmoke3", Transform(msg.Target).Coordinates);
@@ -212,7 +215,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnEmpSpell(EmpSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
var coords = _transformSystem.ToMapCoordinates(Transform(msg.Performer).Coordinates);
@@ -229,7 +232,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnJauntSpell(EtherealJauntSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
if (_statusEffectsSystem.HasStatusEffect(msg.Performer, "Incorporeal"))
@@ -240,7 +243,8 @@ public sealed class WizardSpellsSystem : EntitySystem
Spawn("AdminInstantEffectSmoke10", Transform(msg.Performer).Coordinates);
- _statusEffectsSystem.TryAddStatusEffect(msg.Performer, "Incorporeal", TimeSpan.FromSeconds(10), false);
+ _statusEffectsSystem.TryAddStatusEffect(msg.Performer, "Incorporeal",
+ TimeSpan.FromSeconds(10), false);
msg.Handled = true;
Speak(msg);
@@ -252,7 +256,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnBlinkSpell(BlinkSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
var transform = Transform(msg.Performer);
@@ -291,8 +295,8 @@ public sealed class WizardSpellsSystem : EntitySystem
_audio.PlayPvs("/Audio/White/Cult/veilin.ogg", coords);
_audio.PlayPvs("/Audio/White/Cult/veilout.ogg", oldCoords);
- Spawn("AdminInstantEffectSmoke10", oldCoords);
- Spawn("AdminInstantEffectSmoke10", coords);
+ Spawn("AdminInstantEffectSmoke3", oldCoords);
+ Spawn("AdminInstantEffectSmoke3", coords);
msg.Handled = true;
Speak(msg);
@@ -304,7 +308,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnForcewallSpell(ForceWallSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
switch (msg.ActionUseType)
@@ -372,7 +376,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnCardsSpell(CardsSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
var result = true;
@@ -413,7 +417,8 @@ public sealed class WizardSpellsSystem : EntitySystem
var ent = Spawn(msg.Prototype, spawnCoords);
- var direction = msg.Target.ToMapPos(EntityManager, _transformSystem) - spawnCoords.ToMapPos(EntityManager, _transformSystem);
+ var direction = msg.Target.ToMapPos(EntityManager, _transformSystem) -
+ spawnCoords.ToMapPos(EntityManager, _transformSystem);
var randomizedDirection = direction + new Vector2(_random.Next(-2, 2), _random.Next(-2, 2));
_throwingSystem.TryThrow(ent, randomizedDirection, 60, msg.Performer);
@@ -425,14 +430,15 @@ public sealed class WizardSpellsSystem : EntitySystem
{
var xform = Transform(msg.Performer);
- var count = 10 * msg.ChargeLevel;
+ var count = 10 + 10 * msg.ChargeLevel;
var angleStep = 360f / count;
for (var i = 0; i < count; i++)
{
var angle = i * angleStep;
- var direction = new Vector2(MathF.Cos(MathHelper.DegreesToRadians(angle)), MathF.Sin(MathHelper.DegreesToRadians(angle)));
+ var direction = new Vector2(MathF.Cos(MathHelper.DegreesToRadians(angle)),
+ MathF.Sin(MathHelper.DegreesToRadians(angle)));
foreach (var pos in _magicSystem.GetSpawnPositions(xform, msg.Pos))
{
@@ -453,7 +459,7 @@ public sealed class WizardSpellsSystem : EntitySystem
{
if (!HasComp(msg.TargetUid))
{
- _popupSystem.PopupEntity("Работает только на предметах.", msg.Performer, msg.Performer);
+ _popupSystem.PopupEntity("В карту можно превратить только предметы.", msg.Performer, msg.Performer);
return false;
}
@@ -470,7 +476,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnFireballSpell(FireballSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
var result = true;
@@ -513,7 +519,8 @@ public sealed class WizardSpellsSystem : EntitySystem
userVelocity = physics.LinearVelocity;
var ent = Spawn(msg.Prototype, spawnCoords);
- var direction = msg.Target.ToMapPos(EntityManager, _transformSystem) - spawnCoords.ToMapPos(EntityManager, _transformSystem);
+ var direction = msg.Target.ToMapPos(EntityManager, _transformSystem) -
+ spawnCoords.ToMapPos(EntityManager, _transformSystem);
_gunSystem.ShootProjectile(ent, direction, userVelocity, msg.Performer, msg.Performer);
}
}
@@ -554,9 +561,11 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnForceSpell(ForceSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
+ var result = true;
+
switch (msg.ActionUseType)
{
case ActionUseType.Default:
@@ -566,28 +575,41 @@ public sealed class WizardSpellsSystem : EntitySystem
ForceSpellCharge(msg);
break;
case ActionUseType.AltUse:
- ForceSpellAlt(msg);
+ result = ForceSpellAlt(msg);
break;
}
+ if (!result)
+ return;
+
SetCooldown(msg.Action, msg.ActionUseType);
msg.Handled = true;
Speak(msg);
}
- private void ForceSpellDefault(ForceSpellEvent msg)
+ private bool ForceSpellAlt(ForceSpellEvent msg)
{
- Spawn("AdminInstantEffectMinusGravityWell", msg.Target);
+ if (!HasComp(msg.TargetUid) || !HasComp(msg.TargetUid))
+ {
+ _popupSystem.PopupEntity("Невозможно это притянуть!", msg.Performer, msg.Performer);
+ return false;
+ }
+
+ _throwingSystem.TryThrow(msg.TargetUid, Transform(msg.Performer).Coordinates, 5f);
+ _standing.TryLieDown(msg.TargetUid);
+
+ return true;
}
private void ForceSpellCharge(ForceSpellEvent msg)
{
- _gravityWell.GravPulse(msg.Performer, 15, 0, -80 * msg.ChargeLevel, -2 * msg.ChargeLevel);
+ _gravityWell.GravPulse(msg.Performer, 15, 0, -80 * msg.ChargeLevel, -2 * msg.ChargeLevel, null, msg.ChargeLevel,
+ new() {msg.Performer});
}
- private void ForceSpellAlt(ForceSpellEvent msg)
+ private void ForceSpellDefault(ForceSpellEvent msg)
{
- _gravityWell.GravPulse(msg.Target, 10, 0, 200, 10);
+ _gravityWell.GravPulse(msg.Target, 10, 0, 200, 10, 2f, new() {msg.Performer});
}
#endregion
@@ -596,7 +618,7 @@ public sealed class WizardSpellsSystem : EntitySystem
private void OnArcSpell(ArcSpellEvent msg)
{
- if (msg.Handled || !CheckRequirements(msg.Action, msg.Performer))
+ if (!CanCast(msg))
return;
var result = true;
@@ -632,7 +654,7 @@ public sealed class WizardSpellsSystem : EntitySystem
var entityUids = entitiesToHit.ToList();
foreach (var entity in entityUids)
{
- _lightning.ShootLightning(msg.Performer, entity);
+ _lightning.ShootLightning(msg.Performer, entity, "WizardLightning", true, msg.Performer);
}
return entityUids.Count != 0;
@@ -640,7 +662,8 @@ public sealed class WizardSpellsSystem : EntitySystem
private void ArcSpellCharge(ArcSpellEvent msg)
{
- _lightning.ShootRandomLightnings(msg.Performer, 2 * msg.ChargeLevel, msg.ChargeLevel * 2, arcDepth: 2);
+ _lightning.ShootRandomLightnings(msg.Performer, 2f * msg.ChargeLevel, msg.ChargeLevel * 2, "WizardLightning", 1,
+ caster: msg.Performer);
}
private void ArcSpellAlt(ArcSpellEvent msg)
@@ -660,7 +683,8 @@ public sealed class WizardSpellsSystem : EntitySystem
userVelocity = physics.LinearVelocity;
var ent = Spawn(msg.Prototype, spawnCoords);
- var direction = msg.Target.ToMapPos(EntityManager, _transformSystem) - spawnCoords.ToMapPos(EntityManager, _transformSystem);
+ var direction = msg.Target.ToMapPos(EntityManager, _transformSystem) -
+ spawnCoords.ToMapPos(EntityManager, _transformSystem);
_gunSystem.ShootProjectile(ent, direction, userVelocity, msg.Performer, msg.Performer);
}
}
@@ -669,6 +693,12 @@ public sealed class WizardSpellsSystem : EntitySystem
#region Helpers
+ private bool CanCast(BaseActionEvent msg)
+ {
+ return !msg.Handled && CheckRequirements(msg.Action, msg.Performer) &&
+ !_statusEffectsSystem.HasStatusEffect(msg.Performer, "Incorporeal");
+ }
+
private void Speak(BaseActionEvent args)
{
if (args is not ISpeakSpell speak || string.IsNullOrWhiteSpace(speak.Speech))
@@ -743,7 +773,7 @@ public sealed class WizardSpellsSystem : EntitySystem
if (!hasReqs)
{
args.Cancelled = true;
- _popupSystem.PopupEntity("Missing Requirements! You need to wear your robe and hat!", args.Performer, args.Performer);
+ _popupSystem.PopupEntity(Loc.GetString("magic-component-missing-req"), args.Performer, args.Performer);
}
}
diff --git a/Resources/Locale/en-US/_white/wizard.ftl b/Resources/Locale/en-US/_white/wizard.ftl
new file mode 100644
index 0000000000..1b9f41348a
--- /dev/null
+++ b/Resources/Locale/en-US/_white/wizard.ftl
@@ -0,0 +1 @@
+magic-component-missing-req = Missing Requirements! You need to wear your robe and hat!
diff --git a/Resources/Locale/ru-RU/_white/wizard.ftl b/Resources/Locale/ru-RU/_white/wizard.ftl
index 833d76c8e8..e0f380e29f 100644
--- a/Resources/Locale/ru-RU/_white/wizard.ftl
+++ b/Resources/Locale/ru-RU/_white/wizard.ftl
@@ -15,3 +15,5 @@ wizard-welcome = Вы - космический волшебник. Федера
wizard-no-more-threat-announcement-shuttle-call = Судя по данным наших датчиков дальнего действия, магическая угроза была устранена. Эвакуационный шаттл скоро прибудет. Время прибытия: {$time} {$units}. Вы можете отозвать его, чтобы продлить смену.
wizard-no-more-threat-announcement = Судя по данным наших датчиков дальнего действия, магическая угроза была устранена. Шаттл уже вызван.
+
+magic-component-missing-req = Недостающие требования! Вам необходимо надеть мантию и шляпу!
diff --git a/Resources/Prototypes/Entities/Effects/lightning.yml b/Resources/Prototypes/Entities/Effects/lightning.yml
index 7afd1c07a0..11e6c6c0f0 100644
--- a/Resources/Prototypes/Entities/Effects/lightning.yml
+++ b/Resources/Prototypes/Entities/Effects/lightning.yml
@@ -1,4 +1,4 @@
-- type: entity
+- type: entity
name: lightning
id: BaseLightning
abstract: true
@@ -60,6 +60,9 @@
castShadows: false
- type: Lightning
canArc: false
+ - type: Electrified
+ requirePower: false
+ ignoreInsulation: true
shockDamage: 30
- type: entity
@@ -159,3 +162,17 @@
softness: 1
autoRot: true
castShadows: false
+
+- type: entity
+ name: wizard lightning
+ id: WizardLightning
+ parent: BaseLightning
+ noSpawn: true
+ components:
+ - type: Electrified
+ requirePower: false
+ ignoreInsulation: true
+ shockDamage: 40
+ - type: Lightning
+ canArc: true
+ lightningPrototype: WizardLightning
diff --git a/Resources/Prototypes/Magic/knock_spell.yml b/Resources/Prototypes/Magic/knock_spell.yml
index 131fbb8910..612e7b175f 100644
--- a/Resources/Prototypes/Magic/knock_spell.yml
+++ b/Resources/Prototypes/Magic/knock_spell.yml
@@ -4,8 +4,10 @@
description: This spell opens nearby doors.
noSpawn: true
components:
+ - type: Magic
+ requiresClothes: false
- type: InstantAction
- useDelay: 10
+ useDelay: 8
itemIconStyle: BigAction
checkCanInteract: false
icon:
diff --git a/Resources/Prototypes/Magic/white.yml b/Resources/Prototypes/Magic/white.yml
index 1be2773391..d44b9a4da8 100644
--- a/Resources/Prototypes/Magic/white.yml
+++ b/Resources/Prototypes/Magic/white.yml
@@ -38,8 +38,6 @@
name: Force
noSpawn: true
components:
- - type: Magic
- requiresClothes: true
- type: WorldTargetAction
itemIconStyle: BigAction
useDelay: 60
@@ -63,8 +61,8 @@
speech: "EL DRITCH!"
- type: VariableUseDelay
useDelay: 6
- altUseDelay: 12
- chargeUseDelay: 40
+ altUseDelay: 2
+ chargeUseDelay: 20
- type: entity
id: ActionFireballSpell
@@ -93,8 +91,8 @@
posData: !type:TargetCasterPos
speech: action-speech-spell-fireball
- type: VariableUseDelay
- useDelay: 6
- altUseDelay: 12
+ useDelay: 5
+ altUseDelay: 10
chargeUseDelay: 40
- type: entity
@@ -102,8 +100,6 @@
name: Cards
noSpawn: true
components:
- - type: Magic
- requiresClothes: true
- type: WorldTargetAction
itemIconStyle: BigAction
useDelay: 60
@@ -128,7 +124,7 @@
posData: !type:TargetCasterPos
speech: "SHIZO NERO!"
- type: VariableUseDelay
- useDelay: 6
+ useDelay: 4
altUseDelay: 1
chargeUseDelay: 40
@@ -220,12 +216,10 @@
name: Cluwne Curse
noSpawn: true
components:
- - type: Magic
- requiresClothes: true
- type: EntityTargetAction
canTargetSelf: false
- range: 2
- useDelay: 400
+ range: 3
+ useDelay: 60
itemIconStyle: BigAction
icon:
sprite: Objects/Magic/magicactions.rsi
@@ -238,12 +232,10 @@
name: Banana Touch
noSpawn: true
components:
- - type: Magic
- requiresClothes: true
- type: EntityTargetAction
canTargetSelf: false
- range: 2
- useDelay: 200
+ range: 3
+ useDelay: 30
itemIconStyle: BigAction
icon:
sprite: Objects/Magic/magicactions.rsi
@@ -256,12 +248,10 @@
name: Mime Touch
noSpawn: true
components:
- - type: Magic
- requiresClothes: true
- type: EntityTargetAction
canTargetSelf: false
- range: 2
- useDelay: 200
+ range: 3
+ useDelay: 30
itemIconStyle: BigAction
icon:
sprite: Objects/Magic/magicactions.rsi
@@ -275,8 +265,6 @@
noSpawn: true
components:
- type: InstantRecall
- - type: Magic
- requiresClothes: true
- type: InstantAction
useDelay: 10
itemIconStyle: BigAction
diff --git a/Resources/Prototypes/_White/Objects/Scrolls/scrolls.yml b/Resources/Prototypes/_White/Objects/Scrolls/scrolls.yml
index 3e334f0e16..951bf29e77 100644
--- a/Resources/Prototypes/_White/Objects/Scrolls/scrolls.yml
+++ b/Resources/Prototypes/_White/Objects/Scrolls/scrolls.yml
@@ -1,4 +1,4 @@
-- type: entity
+- type: entity
id: BaseScroll
parent: BaseItem
name: "Magic Scroll"
@@ -11,6 +11,7 @@
layers:
- state: scroll
- type: Scroll
+ learnTime: 1
useSound:
path: /Audio/White/Items/scroll/use.ogg
afterUseSound: