More magic (#338)
* - tweak: Magic tweaks. * - add: Rework some spells. * - fix: Some bugfixes. * - tweak: Less requirements. * - add: Loc.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
||||
@@ -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
|
||||
/// <param name="controller"> The virtual beam controller that this beam will use. If one doesn't exist it will be created here.</param>
|
||||
/// <param name="bodyState">Optional sprite state for the <see cref="prototype"/> if it needs a dynamic one</param>
|
||||
/// <param name="shader">Optional shader for the <see cref="prototype"/> and <see cref="bodyState"/> if it needs something other than default</param>
|
||||
private void CreateBeam(string prototype,
|
||||
private IEnumerable<EntityUid> 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<PhysicsComponent>(ent, out var physics) || !TryComp<BeamComponent>(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
|
||||
/// <param name="bodyState">Optional sprite state for the <see cref="bodyPrototype"/> if a default one is not given</param>
|
||||
/// <param name="shader">Optional shader for the <see cref="bodyPrototype"/> if a default one is not given</param>
|
||||
/// <param name="controller"></param>
|
||||
public void TryCreateBeam(EntityUid user, EntityUid target, string bodyPrototype, string? bodyState = null, string shader = "unshaded", EntityUid? controller = null)
|
||||
public IEnumerable<EntityUid> 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<BeamComponent>(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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
/// <param name="target">Where the lightning fires to</param>
|
||||
/// <param name="lightningPrototype">The prototype for the lightning to be created</param>
|
||||
/// <param name="triggerLightningEvents">if the lightnings being fired should trigger lightning events.</param>
|
||||
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
|
||||
/// <param name="lightningPrototype">The prototype for the lightning to be created</param>
|
||||
/// <param name="arcDepth">how many times to recursively fire lightning bolts from the target points of the first shot.</param>
|
||||
/// <param name="triggerLightningEvents">if the lightnings being fired should trigger lightning events.</param>
|
||||
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++;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
/// <summary>
|
||||
@@ -141,10 +143,10 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
|
||||
/// <param name="baseRadialDeltaV">The base radial velocity that will be added to entities within range towards the center of the gravitational pulse.</param>
|
||||
/// <param name="baseTangentialDeltaV">The base tangential velocity that will be added to entities within countrclockwise around the center of the gravitational pulse.</param>
|
||||
/// <param name="xform">(optional) The transform of the entity at the epicenter of the gravitational pulse.</param>
|
||||
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<EntityUid>? ignore = null)
|
||||
{
|
||||
if (Resolve(uid, ref xform))
|
||||
GravPulse(xform.Coordinates, maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV);
|
||||
GravPulse(xform.Coordinates, maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV, stunTime, ignore);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -165,8 +167,8 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
|
||||
/// <param name="minRange">The minimum distance at which entities can be affected by the gravity pulse.</param>
|
||||
/// <param name="baseRadialDeltaV">The base radial velocity that will be added to entities within range towards the center of the gravitational pulse.</param>
|
||||
/// <param name="baseTangentialDeltaV">The base tangential velocity that will be added to entities within countrclockwise around the center of the gravitational pulse.</param>
|
||||
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<EntityUid>? ignore = null)
|
||||
=> GravPulse(entityPos.ToMap(EntityManager, _transform), maxRange, minRange, baseRadialDeltaV, baseTangentialDeltaV, stunTime, ignore);
|
||||
|
||||
/// <summary>
|
||||
/// Causes a gravitational pulse, shoving around all entities within some distance of an epicenter.
|
||||
@@ -175,7 +177,7 @@ public sealed class GravityWellSystem : SharedGravityWellSystem
|
||||
/// <param name="maxRange">The maximum distance at which entities can be affected by the gravity pulse.</param>
|
||||
/// <param name="minRange">The minimum distance at which entities can be affected by the gravity pulse. Exists to prevent div/0 errors.</param>
|
||||
/// <param name="baseMatrixDeltaV">The base velocity added to any entities within affected by the gravity pulse scaled by the displacement of those entities from the epicenter.</param>
|
||||
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<EntityUid>? 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
|
||||
/// <param name="minRange">The minimum distance at which entities can be affected by the gravity pulse. Exists to prevent div/0 errors.</param>
|
||||
/// <param name="baseRadialDeltaV">The base amount of velocity that will be added to entities in range towards the epicenter of the pulse.</param>
|
||||
/// <param name="baseTangentialDeltaV">The base amount of velocity that will be added to entities in range counterclockwise relative to the epicenter of the pulse.</param>
|
||||
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<EntityUid>? 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
|
||||
|
||||
|
||||
@@ -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<HandsComponent>(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<HumanoidAppearanceComponent>(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<HumanoidAppearanceComponent>(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<HumanoidAppearanceComponent>(msg.Target))
|
||||
@@ -197,8 +201,7 @@ public sealed class WizardSpellsSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
var cluwne = EnsureComp<CluwneComponent>(msg.Target);
|
||||
cluwne.KnockChance = 0.2f;
|
||||
EnsureComp<CluwneComponent>(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<IncorporealComponent>(msg.Performer, "Incorporeal", TimeSpan.FromSeconds(10), false);
|
||||
_statusEffectsSystem.TryAddStatusEffect<IncorporealComponent>(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<ItemComponent>(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<TransformComponent>(msg.TargetUid) || !HasComp<PhysicsComponent>(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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
1
Resources/Locale/en-US/_white/wizard.ftl
Normal file
1
Resources/Locale/en-US/_white/wizard.ftl
Normal file
@@ -0,0 +1 @@
|
||||
magic-component-missing-req = Missing Requirements! You need to wear your robe and hat!
|
||||
@@ -15,3 +15,5 @@ wizard-welcome = Вы - космический волшебник. Федера
|
||||
|
||||
wizard-no-more-threat-announcement-shuttle-call = Судя по данным наших датчиков дальнего действия, магическая угроза была устранена. Эвакуационный шаттл скоро прибудет. Время прибытия: {$time} {$units}. Вы можете отозвать его, чтобы продлить смену.
|
||||
wizard-no-more-threat-announcement = Судя по данным наших датчиков дальнего действия, магическая угроза была устранена. Шаттл уже вызван.
|
||||
|
||||
magic-component-missing-req = Недостающие требования! Вам необходимо надеть мантию и шляпу!
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user