diff --git a/Content.Server/_CP14/MagicSpell/CP14MagicSystem.cs b/Content.Server/_CP14/MagicSpell/CP14MagicSystem.cs index 8ae8a9f216..82f8e3d2e8 100644 --- a/Content.Server/_CP14/MagicSpell/CP14MagicSystem.cs +++ b/Content.Server/_CP14/MagicSpell/CP14MagicSystem.cs @@ -1,4 +1,6 @@ +using Content.Server._CP14.MagicEnergy; using Content.Server.Chat.Systems; +using Content.Shared._CP14.MagicEnergy.Components; using Content.Shared._CP14.MagicSpell; using Content.Shared._CP14.MagicSpell.Components; using Content.Shared._CP14.MagicSpell.Events; @@ -10,6 +12,7 @@ public sealed partial class CP14MagicSystem : CP14SharedMagicSystem { [Dependency] private readonly ChatSystem _chat = default!; [Dependency] private readonly TransformSystem _transform = default!; + [Dependency] private readonly CP14MagicEnergySystem _magicEnergy = default!; public override void Initialize() { @@ -19,6 +22,8 @@ public sealed partial class CP14MagicSystem : CP14SharedMagicSystem SubscribeLocalEvent(OnSpawnMagicVisualEffect); SubscribeLocalEvent(OnDespawnMagicVisualEffect); + + SubscribeLocalEvent(OnManaConsume); } private void OnSpellSpoken(Entity ent, ref CP14VerbalAspectSpeechEvent args) @@ -39,4 +44,33 @@ public sealed partial class CP14MagicSystem : CP14SharedMagicSystem QueueDel(ent.Comp.SpawnedEntity); ent.Comp.SpawnedEntity = null; } + + private void OnManaConsume(Entity ent, ref CP14MagicEffectConsumeResourceEvent args) + { + if (!TryComp(ent, out var magicEffect)) + return; + + var requiredMana = CalculateManacost(ent, args.Performer); + + if (magicEffect.SpellStorage is not null && + TryComp(magicEffect.SpellStorage, out var magicStorage)) + { + var spellEv = new CP14SpellFromSpellStorageUsedEvent(args.Performer, (ent, magicEffect), requiredMana); + RaiseLocalEvent(magicEffect.SpellStorage.Value, ref spellEv); + + if (magicStorage.Energy > 0) + { + //TODO: FIX THIS SHIT + var cashedEnergy = magicStorage.Energy; + _magicEnergy.TryConsumeEnergy(magicEffect.SpellStorage.Value, requiredMana, magicStorage, false); + requiredMana = MathF.Max(0, (float)(requiredMana - cashedEnergy)); + } + } + + if (requiredMana > 0 && + TryComp(args.Performer, out var playerMana)) + { + _magicEnergy.TryConsumeEnergy(args.Performer.Value, requiredMana, safe: false); + } + } } diff --git a/Content.Shared/Actions/SharedActionsSystem.cs b/Content.Shared/Actions/SharedActionsSystem.cs index 8945547b37..83763fb8d2 100644 --- a/Content.Shared/Actions/SharedActionsSystem.cs +++ b/Content.Shared/Actions/SharedActionsSystem.cs @@ -716,7 +716,7 @@ public abstract class SharedActionsSystem : EntitySystem action.Enabled = false; } - action.Cooldown = null; + //action.Cooldown = null; //CP14 - disabling auto cooldown after using if (action is { UseDelay: not null, Charges: null or < 1 }) { dirty = true; diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index a5c8a4b38d..472c387ad9 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -382,10 +382,13 @@ public sealed partial class StaminaSystem : EntitySystem } component.Critical = false; - component.StaminaDamage = 0f; + //CP14 Stamina edit + //component.StaminaDamage = 0f; + component.StaminaDamage = component.CritThreshold * 0.8f; + //CP14 stamina edit end component.NextUpdate = _timing.CurTime; SetStaminaAlert(uid, component); - RemComp(uid); + //RemComp(uid); //CP14 Dirty(uid, component); _adminLogger.Add(LogType.Stamina, LogImpact.Low, $"{ToPrettyString(uid):user} recovered from stamina crit"); } diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Aspects.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Aspects.cs deleted file mode 100644 index c1cd5cb9b4..0000000000 --- a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Aspects.cs +++ /dev/null @@ -1,68 +0,0 @@ -using Content.Shared._CP14.MagicSpell.Components; -using Content.Shared._CP14.MagicSpell.Events; -using Content.Shared.Hands.Components; -using Content.Shared.Speech.Muting; - -namespace Content.Shared._CP14.MagicSpell; - -public abstract partial class CP14SharedMagicSystem -{ - private void InitializeAspects() - { - SubscribeLocalEvent(OnSomaticAspectBeforeCast); - - SubscribeLocalEvent(OnVerbalAspectBeforeCast); - SubscribeLocalEvent(OnVerbalAspectStartCast); - SubscribeLocalEvent(OnVerbalAspectAfterCast); - } - - private void OnSomaticAspectBeforeCast(Entity ent, ref CP14CastMagicEffectAttemptEvent args) - { - if (TryComp(args.Performer, out var hands) || hands is not null) - { - var freeHand = 0; - foreach (var hand in hands.Hands) - { - if (hand.Value.IsEmpty) - freeHand++; - } - if (freeHand >= ent.Comp.FreeHandRequired) - return; - } - args.PushReason(Loc.GetString("cp14-magic-spell-need-somatic-component")); - args.Cancel(); - } - - private void OnVerbalAspectBeforeCast(Entity ent, ref CP14CastMagicEffectAttemptEvent args) - { - if (HasComp(args.Performer)) - { - args.PushReason(Loc.GetString("cp14-magic-spell-need-verbal-component")); - args.Cancel(); - } - } - - private void OnVerbalAspectStartCast(Entity ent, ref CP14StartCastMagicEffectEvent args) - { - var ev = new CP14VerbalAspectSpeechEvent - { - Performer = args.Performer, - Speech = ent.Comp.StartSpeech, - }; - RaiseLocalEvent(ent, ref ev); - } - - private void OnVerbalAspectAfterCast(Entity ent, ref CP14AfterCastMagicEffectEvent args) - { - if (_net.IsClient) - return; - - var ev = new CP14VerbalAspectSpeechEvent - { - Performer = args.Performer, - Speech = ent.Comp.EndSpeech, - }; - RaiseLocalEvent(ent, ref ev); - } - -} diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Checks.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Checks.cs new file mode 100644 index 0000000000..551953cab2 --- /dev/null +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Checks.cs @@ -0,0 +1,111 @@ +using Content.Shared._CP14.MagicSpell.Components; +using Content.Shared._CP14.MagicSpell.Events; +using Content.Shared.Damage.Components; +using Content.Shared.Hands.Components; +using Content.Shared.Popups; +using Content.Shared.Speech.Muting; + +namespace Content.Shared._CP14.MagicSpell; + +public abstract partial class CP14SharedMagicSystem +{ + private void InitializeChecks() + { + SubscribeLocalEvent(OnSomaticCheck); + SubscribeLocalEvent(OnVerbalCheck); + SubscribeLocalEvent(OnManaCheck); + SubscribeLocalEvent(OnStaminaCheck); + + //Verbal speaking + SubscribeLocalEvent(OnVerbalAspectStartCast); + SubscribeLocalEvent(OnVerbalAspectAfterCast); + } + + /// + /// Before using a spell, a mana check is made for the amount of mana to show warnings. + /// + private void OnManaCheck(Entity ent, ref CP14CastMagicEffectAttemptEvent args) + { + var requiredMana = CalculateManacost(ent, args.Performer); + + if (!_magicEffectQuery.TryComp(ent, out var magicEffect)) + return; + + if (magicEffect.SpellStorage is not null) + { + if (_magicContainerQuery.TryComp(magicEffect.SpellStorage, out var magicContainer)) // We have item that provides this spell + requiredMana = MathF.Max(0, (float)(requiredMana - magicContainer.Energy)); + } + + if (requiredMana > 0 && _magicContainerQuery.TryComp(args.Performer, out var playerMana)) + { + if (!_magicEnergy.HasEnergy(args.Performer, requiredMana, playerMana, true) && _net.IsServer) + { + _popup.PopupEntity(Loc.GetString("cp14-magic-spell-not-enough-mana-cast-warning-"+_random.Next(5)), args.Performer, args.Performer, PopupType.SmallCaution); + } + } + } + + private void OnStaminaCheck(Entity ent, ref CP14CastMagicEffectAttemptEvent args) + { + if (!TryComp(args.Performer, out var staminaComp)) + return; + + if (staminaComp.Critical) + { + args.PushReason(Loc.GetString("cp14-magic-spell-stamina-not-enough")); + args.Cancel(); + return; + } + } + + private void OnSomaticCheck(Entity ent, ref CP14CastMagicEffectAttemptEvent args) + { + if (TryComp(args.Performer, out var hands) || hands is not null) + { + var freeHand = 0; + foreach (var hand in hands.Hands) + { + if (hand.Value.IsEmpty) + freeHand++; + } + if (freeHand >= ent.Comp.FreeHandRequired) + return; + } + args.PushReason(Loc.GetString("cp14-magic-spell-need-somatic-component")); + args.Cancel(); + } + + private void OnVerbalCheck(Entity ent, ref CP14CastMagicEffectAttemptEvent args) + { + if (HasComp(args.Performer)) + { + args.PushReason(Loc.GetString("cp14-magic-spell-need-verbal-component")); + args.Cancel(); + } + } + + private void OnVerbalAspectStartCast(Entity ent, ref CP14StartCastMagicEffectEvent args) + { + var ev = new CP14VerbalAspectSpeechEvent + { + Performer = args.Performer, + Speech = ent.Comp.StartSpeech, + }; + RaiseLocalEvent(ent, ref ev); + } + + private void OnVerbalAspectAfterCast(Entity ent, ref CP14MagicEffectConsumeResourceEvent args) + { + if (_net.IsClient) + return; + + var ev = new CP14VerbalAspectSpeechEvent + { + Performer = args.Performer, + Speech = ent.Comp.EndSpeech, + }; + RaiseLocalEvent(ent, ref ev); + } + +} diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Actions.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs similarity index 53% rename from Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Actions.cs rename to Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs index 9e2408c54f..5d2339fe8b 100644 --- a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Actions.cs +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs @@ -1,13 +1,14 @@ using Content.Shared._CP14.MagicSpell.Components; using Content.Shared._CP14.MagicSpell.Events; using Content.Shared._CP14.MagicSpell.Spells; +using Content.Shared.DoAfter; using Robust.Shared.Map; namespace Content.Shared._CP14.MagicSpell; public abstract partial class CP14SharedMagicSystem { - private void InitializeActions() + private void InitializeDelayedActions() { SubscribeLocalEvent(OnInstantAction); SubscribeLocalEvent(OnEntityWorldTargetAction); @@ -18,6 +19,65 @@ public abstract partial class CP14SharedMagicSystem SubscribeLocalEvent(OnDelayedEntityTargetDoAfter); } + private bool TryStartDelayedAction(ICP14DelayedMagicEffect delayedEffect, DoAfterEvent doAfter, Entity action, EntityUid performer) + { + if (_doAfter.IsRunning(action.Comp.ActiveDoAfter)) + return false; + + var fromItem = action.Comp.SpellStorage is not null; + + var doAfterEventArgs = new DoAfterArgs(EntityManager, performer, MathF.Max(delayedEffect.CastDelay, 1f), doAfter, action, used: action.Comp.SpellStorage) + { + BreakOnMove = delayedEffect.BreakOnMove, + BreakOnDamage = delayedEffect.BreakOnDamage, + Hidden = delayedEffect.Hidden, + DistanceThreshold = 100f, + CancelDuplicate = true, + BlockDuplicate = true, + BreakOnDropItem = fromItem, + NeedHand = fromItem, + }; + + if (_doAfter.TryStartDoAfter(doAfterEventArgs, out var doAfterId)) + { + action.Comp.ActiveDoAfter = doAfterId; + return true; + } + + return false; + } + + private void EndDelayedAction(Entity action, EntityUid performer, float? cooldown = null) + { + var endEv = new CP14EndCastMagicEffectEvent(performer); + RaiseLocalEvent(action, ref endEv); + + if (cooldown is not null) + _action.CP14StartCustomDelay(action, TimeSpan.FromSeconds(cooldown.Value)); + } + + private void UseDelayedAction(ICP14DelayedMagicEffect delayedEffect, Entity action, DoAfterEvent doAfter, EntityUid performer) + { + if (!CanCastSpell(action, performer)) + return; + + if (_doAfter.IsRunning(action.Comp.ActiveDoAfter)) + _doAfter.Cancel(action.Comp.ActiveDoAfter); + else + { + if (TryStartDelayedAction(delayedEffect, doAfter, action, performer)) + { + var evStart = new CP14StartCastMagicEffectEvent(performer); + RaiseLocalEvent(action, ref evStart); + + var spellArgs = + new CP14SpellEffectBaseArgs(performer, action.Comp.SpellStorage, performer, Transform(performer).Coordinates); + + CastTelegraphy(action, spellArgs); + } + } + } + /// /// Instant action used from hotkey event /// @@ -32,28 +92,8 @@ public abstract partial class CP14SharedMagicSystem if (!TryComp(args.Action, out var magicEffect)) return; - Entity spell = (args.Action, magicEffect); - - if (!CanCastSpell(spell, args.Performer)) - return; - - if (args.CastDelay > 0) - { - var doAfter = new CP14DelayedInstantActionDoAfterEvent(args.Cooldown); - if (!TryCastSpellDelayed(delayedEffect, doAfter, (args.Action, magicEffect), args.Performer)) - return; - } - - var evStart = new CP14StartCastMagicEffectEvent( args.Performer); - RaiseLocalEvent(args.Action, ref evStart); - - var spellArgs = - new CP14SpellEffectBaseArgs(args.Performer, magicEffect.SpellStorage, args.Performer, Transform(args.Performer).Coordinates); - - CastTelegraphy((args.Action, magicEffect), spellArgs); - - if (args.CastDelay == 0) - CastSpell((args.Action, magicEffect), spellArgs, args.Cooldown); + var doAfter = new CP14DelayedInstantActionDoAfterEvent(args.Cooldown); + UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer); args.Handled = true; } @@ -72,33 +112,11 @@ public abstract partial class CP14SharedMagicSystem if (!TryComp(args.Action, out var magicEffect)) return; - Entity spell = (args.Action, magicEffect); - - if (!CanCastSpell(spell, args.Performer)) - return; - - - if (args.CastDelay > 0) - { - var doAfter = new CP14DelayedEntityWorldTargetActionDoAfterEvent( - EntityManager.GetNetCoordinates(args.Coords), - EntityManager.GetNetEntity(args.Entity), - args.Cooldown); - - if (!TryCastSpellDelayed(delayedEffect, doAfter, (args.Action, magicEffect), args.Performer)) - return; - } - - var evStart = new CP14StartCastMagicEffectEvent( args.Performer); - RaiseLocalEvent(args.Action, ref evStart); - - var spellArgs = - new CP14SpellEffectBaseArgs(args.Performer, magicEffect.SpellStorage, args.Entity, args.Coords); - - CastTelegraphy((args.Action, magicEffect), spellArgs); - - if (args.CastDelay <= 0) - CastSpell((args.Action, magicEffect), spellArgs, args.Cooldown); + var doAfter = new CP14DelayedEntityWorldTargetActionDoAfterEvent( + EntityManager.GetNetCoordinates(args.Coords), + EntityManager.GetNetEntity(args.Entity), + args.Cooldown); + UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer); args.Handled = true; } @@ -117,32 +135,8 @@ public abstract partial class CP14SharedMagicSystem if (!TryComp(args.Action, out var magicEffect)) return; - Entity spell = (args.Action, magicEffect); - - if (!CanCastSpell(spell, args.Performer)) - return; - - if (args.CastDelay > 0) - { - var doAfter = new CP14DelayedEntityTargetActionDoAfterEvent( - EntityManager.GetNetEntity(args.Target), - args.Cooldown); - - if (!TryCastSpellDelayed(delayedEffect, doAfter, (args.Action, magicEffect), args.Performer)) - return; - } - - var evStart = new CP14StartCastMagicEffectEvent( args.Performer); - RaiseLocalEvent(args.Action, ref evStart); - - var spellArgs = - new CP14SpellEffectBaseArgs(args.Performer, magicEffect.SpellStorage, args.Target, Transform(args.Target).Coordinates); - - CastTelegraphy((args.Action, magicEffect), spellArgs); - - //TODO: Bug! If CastDelay = 0, cooldown dont want apply to spell aftercast - if (args.CastDelay <= 0) - CastSpell((args.Action, magicEffect), spellArgs, args.Cooldown); + var doAfter = new CP14DelayedEntityTargetActionDoAfterEvent(EntityManager.GetNetEntity(args.Target), args.Cooldown); + UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer); args.Handled = true; } @@ -152,13 +146,12 @@ public abstract partial class CP14SharedMagicSystem /// private void OnDelayedInstantActionDoAfter(Entity ent, ref CP14DelayedInstantActionDoAfterEvent args) { - var endEv = new CP14EndCastMagicEffectEvent(args.User); - RaiseLocalEvent(ent, ref endEv); + EndDelayedAction(ent, args.User, args.Cooldown); if (args.Cancelled || args.Handled) return; - CastSpell(ent, new CP14SpellEffectBaseArgs(args.User, args.Used, args.User, Transform(args.User).Coordinates), args.Cooldown ?? 0); + CastSpell(ent, new CP14SpellEffectBaseArgs(args.User, args.Used, args.User, Transform(args.User).Coordinates)); args.Handled = true; } @@ -169,8 +162,7 @@ public abstract partial class CP14SharedMagicSystem private void OnDelayedEntityWorldTargetDoAfter(Entity ent, ref CP14DelayedEntityWorldTargetActionDoAfterEvent args) { - var endEv = new CP14EndCastMagicEffectEvent(args.User); - RaiseLocalEvent(ent, ref endEv); + EndDelayedAction(ent, args.User, args.Cooldown); if (args.Cancelled || args.Handled) return; @@ -178,7 +170,7 @@ public abstract partial class CP14SharedMagicSystem var targetPos = EntityManager.GetCoordinates(args.TargetPosition); EntityManager.TryGetEntity(args.TargetEntity, out var targetEnt); - CastSpell(ent, new CP14SpellEffectBaseArgs(args.User, args.Used, targetEnt, targetPos), args.Cooldown ?? 0); + CastSpell(ent, new CP14SpellEffectBaseArgs(args.User, args.Used, targetEnt, targetPos)); args.Handled = true; } @@ -188,8 +180,7 @@ public abstract partial class CP14SharedMagicSystem /// private void OnDelayedEntityTargetDoAfter(Entity ent, ref CP14DelayedEntityTargetActionDoAfterEvent args) { - var endEv = new CP14EndCastMagicEffectEvent(args.User); - RaiseLocalEvent(ent, ref endEv); + EndDelayedAction(ent, args.User, args.Cooldown); if (args.Cancelled || args.Handled) return; @@ -198,7 +189,7 @@ public abstract partial class CP14SharedMagicSystem EntityCoordinates? targetPos = null; if (targetEnt is not null) { targetPos = Transform(targetEnt.Value).Coordinates; } - CastSpell(ent, new CP14SpellEffectBaseArgs(args.User, args.Used, targetEnt, targetPos), args.Cooldown ?? 0); + CastSpell(ent, new CP14SpellEffectBaseArgs(args.User, args.Used, targetEnt, targetPos)); args.Handled = true; } diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.ToggleableActions.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.ToggleableActions.cs new file mode 100644 index 0000000000..a5353cc473 --- /dev/null +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.ToggleableActions.cs @@ -0,0 +1,186 @@ +using Content.Shared._CP14.MagicSpell.Components; +using Content.Shared._CP14.MagicSpell.Events; +using Content.Shared._CP14.MagicSpell.Spells; +using Content.Shared.DoAfter; +using Robust.Shared.Map; + +namespace Content.Shared._CP14.MagicSpell; + +public abstract partial class CP14SharedMagicSystem +{ + private void InitializeToggleableActions() + { + SubscribeLocalEvent(OnInstantAction); + SubscribeLocalEvent(OnEntityWorldTargetAction); + SubscribeLocalEvent(OnEntityTargetAction); + + SubscribeLocalEvent(OnToggleableInstantActionDoAfterEvent); + SubscribeLocalEvent(OnToggleableEntityWorldTargetActionDoAfterEvent); + SubscribeLocalEvent(OnToggleableEntityTargetActionDoAfterEvent); + } + + private void UpdateToggleableActions() + { + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var effect, out var toggled)) + { + if (toggled.NextTick > _timing.CurTime) + continue; + + if (toggled.Performer is null) + continue; + + toggled.NextTick = _timing.CurTime + TimeSpan.FromSeconds(toggled.Frequency); + + var spellArgs = + new CP14SpellEffectBaseArgs(toggled.Performer, effect.SpellStorage, toggled.EntityTarget, toggled.WorldTarget); + + if (!CanCastSpell((uid, effect), toggled.Performer.Value)) + { + if (_doAfter.IsRunning(toggled.DoAfterId)) + _doAfter.Cancel(toggled.DoAfterId); + continue; + } + + CastSpell((uid, effect), spellArgs); + } + } + + private void OnToggleableInstantActionDoAfterEvent(Entity ent, ref CP14ToggleableInstantActionDoAfterEvent args) + { + EndToggleableAction(ent, args.User, args.Cooldown); + } + + private void OnToggleableEntityWorldTargetActionDoAfterEvent(Entity ent, ref CP14ToggleableEntityWorldTargetActionDoAfterEvent args) + { + EndToggleableAction(ent, args.User, args.Cooldown); + } + + private void OnToggleableEntityTargetActionDoAfterEvent(Entity ent, ref CP14ToggleableEntityTargetActionDoAfterEvent args) + { + EndToggleableAction(ent, args.User, args.Cooldown); + } + + private void StartToggleableAction(ICP14ToggleableMagicEffect toggleable, DoAfterEvent doAfter, Entity action, EntityUid performer, EntityUid? entityTarget = null, EntityCoordinates? worldTarget = null) + { + if (_doAfter.IsRunning(action.Comp.ActiveDoAfter)) + return; + + var evStart = new CP14StartCastMagicEffectEvent(performer); + RaiseLocalEvent(action, ref evStart); + + var fromItem = action.Comp.SpellStorage is not null; + + var doAfterEventArgs = new DoAfterArgs(EntityManager, performer, toggleable.CastTime, doAfter, action, used: action.Comp.SpellStorage) + { + BreakOnMove = toggleable.BreakOnMove, + BreakOnDamage = toggleable.BreakOnDamage, + Hidden = toggleable.Hidden, + DistanceThreshold = 100f, + CancelDuplicate = true, + BlockDuplicate = true, + BreakOnDropItem = fromItem, + NeedHand = fromItem, + }; + + if (_doAfter.TryStartDoAfter(doAfterEventArgs, out var doAfterId)) + { + EnsureComp(action, out var toggled); + toggled.Frequency = toggleable.EffectFrequency; + toggled.Performer = performer; + toggled.DoAfterId = doAfterId; + toggled.Cooldown = toggleable.Cooldown; + + toggled.EntityTarget = entityTarget; + toggled.WorldTarget = worldTarget; + + action.Comp.ActiveDoAfter = doAfterId; + } + } + + private void EndToggleableAction(Entity action, EntityUid performer, float? cooldown = null) + { + if (cooldown is not null) + _action.CP14StartCustomDelay(action, TimeSpan.FromSeconds(cooldown.Value)); + RemCompDeferred(action); + + var endEv = new CP14EndCastMagicEffectEvent(performer); + RaiseLocalEvent(action, ref endEv); + } + + private void ToggleToggleableAction(ICP14ToggleableMagicEffect toggleable, DoAfterEvent doAfter, Entity action, EntityUid performer, EntityUid? entityTarget = null, EntityCoordinates? worldTarget = null) + { + if (!CanCastSpell(action, performer)) + return; + + if (_doAfter.IsRunning(action.Comp.ActiveDoAfter)) + _doAfter.Cancel(action.Comp.ActiveDoAfter); + else + StartToggleableAction(toggleable, doAfter, action, performer, entityTarget, worldTarget); + } + + /// + /// Instant action used from hotkey event + /// + private void OnInstantAction(CP14ToggleableInstantActionEvent args) + { + if (args.Handled) + return; + + if (args is not ICP14ToggleableMagicEffect toggleable) + return; + + if (!TryComp(args.Action, out var magicEffect)) + return; + + var doAfter = new CP14ToggleableInstantActionDoAfterEvent(args.Cooldown); + ToggleToggleableAction(toggleable, doAfter, (args.Action, magicEffect), args.Performer, args.Performer, Transform(args.Performer).Coordinates); + + args.Handled = true; + } + + /// + /// Target action used from hotkey event + /// + private void OnEntityWorldTargetAction(CP14ToggleableEntityWorldTargetActionEvent args) + { + if (args.Handled) + return; + + if (args is not ICP14ToggleableMagicEffect toggleable) + return; + + if (!TryComp(args.Action, out var magicEffect)) + return; + + var doAfter = new CP14ToggleableEntityWorldTargetActionDoAfterEvent( + EntityManager.GetNetCoordinates(args.Coords), + EntityManager.GetNetEntity(args.Entity), + args.Cooldown); + ToggleToggleableAction(toggleable, doAfter, (args.Action, magicEffect), args.Performer, args.Entity, args.Coords); + + args.Handled = true; + } + + /// + /// Entity target action used from hotkey event + /// + private void OnEntityTargetAction(CP14ToggleableEntityTargetActionEvent args) + { + if (args.Handled) + return; + + if (args is not ICP14ToggleableMagicEffect toggleable) + return; + + if (!TryComp(args.Action, out var magicEffect)) + return; + + var doAfter = new CP14ToggleableEntityTargetActionDoAfterEvent(EntityManager.GetNetEntity(args.Target), args.Cooldown); + ToggleToggleableAction(toggleable, doAfter, (args.Action, magicEffect), args.Performer, args.Target, Transform(args.Target).Coordinates); + + args.Handled = true; + } +} + diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.cs index b20fb431dc..9064f18faa 100644 --- a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.cs +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.cs @@ -6,6 +6,7 @@ using Content.Shared._CP14.MagicSpell.Events; using Content.Shared._CP14.MagicSpell.Spells; using Content.Shared._CP14.MagicSpellStorage; using Content.Shared.Actions; +using Content.Shared.Damage.Systems; using Content.Shared.DoAfter; using Content.Shared.FixedPoint; using Content.Shared.Movement.Systems; @@ -13,6 +14,7 @@ using Content.Shared.Popups; using Robust.Shared.Network; using Robust.Shared.Prototypes; using Robust.Shared.Random; +using Robust.Shared.Timing; namespace Content.Shared._CP14.MagicSpell; @@ -30,21 +32,34 @@ public abstract partial class CP14SharedMagicSystem : EntitySystem [Dependency] private readonly MetaDataSystem _meta = default!; [Dependency] private readonly SharedActionsSystem _action = default!; [Dependency] private readonly MovementSpeedModifierSystem _movement = default!; + [Dependency] private readonly StaminaSystem _stamina = default!; + [Dependency] private readonly IGameTiming _timing = default!; private EntityQuery _magicContainerQuery; + private EntityQuery _magicEffectQuery; + public override void Initialize() { base.Initialize(); - InitializeActions(); - InitializeAspects(); + InitializeDelayedActions(); + InitializeToggleableActions(); + InitializeChecks(); InitializeSlowdown(); _magicContainerQuery = GetEntityQuery(); + _magicEffectQuery = GetEntityQuery(); SubscribeLocalEvent(OnMagicEffectInit); - SubscribeLocalEvent(OnBeforeCastMagicEffect); + SubscribeLocalEvent(OnMagicEffectShutdown); - SubscribeLocalEvent(OnAfterCastMagicEffect); + SubscribeLocalEvent(OnStaminaConsume); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + UpdateToggleableActions(); } /// @@ -56,11 +71,20 @@ public abstract partial class CP14SharedMagicSystem : EntitySystem var sb = new StringBuilder(); sb.Append(meta.EntityDescription); - sb.Append($"\n\n {Loc.GetString("cp14-magic-manacost")}: [color=#5da9e8]{ent.Comp.ManaCost}[/color]"); + + if (TryComp(ent, out var manaCost) && manaCost.ManaCost > 0) + { + sb.Append($"\n\n{Loc.GetString("cp14-magic-manacost")}: [color=#5da9e8]{manaCost.ManaCost}[/color]"); + } + + if (TryComp(ent, out var staminaCost) && staminaCost.Stamina > 0) + { + sb.Append($"\n\n{Loc.GetString("cp14-magic-staminacost")}: [color=#3fba54]{staminaCost.Stamina}[/color]"); + } if (_proto.TryIndex(ent.Comp.MagicType, out var indexedMagic)) { - sb.Append($"\n {Loc.GetString("cp14-magic-magic-type")}: [color={indexedMagic.Color.ToHex()}]{Loc.GetString(indexedMagic.Name)}[/color]"); + sb.Append($"\n{Loc.GetString("cp14-magic-magic-type")}: [color={indexedMagic.Color.ToHex()}]{Loc.GetString(indexedMagic.Name)}[/color]"); } if (TryComp(ent, out var verbal)) @@ -76,6 +100,12 @@ public abstract partial class CP14SharedMagicSystem : EntitySystem _meta.SetEntityDescription(ent, sb.ToString()); } + private void OnMagicEffectShutdown(Entity ent, ref ComponentShutdown args) + { + if (_doAfter.IsRunning(ent.Comp.ActiveDoAfter)) + _doAfter.Cancel(ent.Comp.ActiveDoAfter); + } + /// /// Checking to see if the spell can be used at all /// @@ -90,36 +120,6 @@ public abstract partial class CP14SharedMagicSystem : EntitySystem return !ev.Cancelled; } - /// - /// Before using a spell, a mana check is made for the amount of mana to show warnings. - /// - private void OnBeforeCastMagicEffect(Entity ent, ref CP14CastMagicEffectAttemptEvent args) - { - var requiredMana = CalculateManacost(ent, args.Performer); - - if (ent.Comp.SpellStorage is not null) - { - if (_magicContainerQuery.TryComp(ent.Comp.SpellStorage, out var magicContainer)) // We have item that provides this spell - requiredMana = MathF.Max(0, (float)(requiredMana - magicContainer.Energy)); - - if (!ent.Comp.SpellStorage.Value.Comp.CanUseCasterMana && requiredMana > 0) - { - args.PushReason(Loc.GetString("cp14-magic-spell-not-enough-mana-item")); - args.Cancel(); - return; - } - } - - - if (requiredMana > 0 && _magicContainerQuery.TryComp(args.Performer, out var playerMana)) - { - if (!_magicEnergy.HasEnergy(args.Performer, requiredMana, playerMana, true) && _net.IsServer) - { - _popup.PopupEntity(Loc.GetString("cp14-magic-spell-not-enough-mana-cast-warning-"+_random.Next(5)), args.Performer, args.Performer, PopupType.SmallCaution); - } - } - } - private void CastTelegraphy(Entity ent, CP14SpellEffectBaseArgs args) { if (!_net.IsServer) @@ -131,28 +131,10 @@ public abstract partial class CP14SharedMagicSystem : EntitySystem } } - private bool TryCastSpellDelayed(ICP14DelayedMagicEffect delayedEffect, DoAfterEvent doAfter, Entity action, EntityUid performer) + private void CastSpell(Entity ent, CP14SpellEffectBaseArgs args) { - var fromItem = action.Comp.SpellStorage is not null; - - var doAfterEventArgs = new DoAfterArgs(EntityManager, performer, delayedEffect.CastDelay, doAfter, action, used: action.Comp.SpellStorage) - { - BreakOnMove = delayedEffect.BreakOnMove, - BreakOnDamage = delayedEffect.BreakOnDamage, - Hidden = delayedEffect.Hidden, - DistanceThreshold = 100f, - CancelDuplicate = true, - BlockDuplicate = true, - BreakOnDropItem = fromItem, - NeedHand = fromItem, - }; - - return _doAfter.TryStartDoAfter(doAfterEventArgs); - } - - private void CastSpell(Entity ent, CP14SpellEffectBaseArgs args, float cooldown) - { - _action.CP14StartCustomDelay(ent, TimeSpan.FromSeconds(cooldown)); + var ev = new CP14MagicEffectConsumeResourceEvent(args.User); + RaiseLocalEvent(ent, ref ev); if (_net.IsServer) { @@ -161,57 +143,33 @@ public abstract partial class CP14SharedMagicSystem : EntitySystem effect.Effect(EntityManager, args); } } - - var ev = new CP14AfterCastMagicEffectEvent(args.User); - RaiseLocalEvent(ent, ref ev); } - private void OnAfterCastMagicEffect(Entity ent, ref CP14AfterCastMagicEffectEvent args) - { - if (_net.IsClient) - return; - - var requiredMana = CalculateManacost(ent, args.Performer); - - if (ent.Comp.SpellStorage is not null && - _magicContainerQuery.TryComp(ent.Comp.SpellStorage, out var magicStorage)) - { - var spellEv = new CP14SpellFromSpellStorageUsedEvent(args.Performer, ent, requiredMana); - RaiseLocalEvent(ent.Comp.SpellStorage.Value, ref spellEv); - - if (magicStorage.Energy > 0) - { - //TODO: FIX THIS SHIT - var cashedEnergy = magicStorage.Energy; - _magicEnergy.TryConsumeEnergy(ent.Comp.SpellStorage.Value, requiredMana, magicStorage, false); - requiredMana = MathF.Max(0, (float)(requiredMana - cashedEnergy)); - } - } - - if (requiredMana > 0 && - _magicContainerQuery.TryComp(args.Performer, out var playerMana)) - { - _magicEnergy.TryConsumeEnergy(args.Performer.Value, requiredMana, safe: false); - } - } - - private FixedPoint2 CalculateManacost(Entity ent, EntityUid? caster) + protected FixedPoint2 CalculateManacost(Entity ent, EntityUid? caster) { var manaCost = ent.Comp.ManaCost; - if (ent.Comp.CanModifyManacost) + if (ent.Comp.CanModifyManacost && _magicEffectQuery.TryComp(ent, out var magicEffect)) { - var manaEv = new CP14CalculateManacostEvent(caster, ent.Comp.ManaCost, ent.Comp.MagicType); + var manaEv = new CP14CalculateManacostEvent(caster, ent.Comp.ManaCost, magicEffect.MagicType); if (caster is not null) RaiseLocalEvent(caster.Value, manaEv); - if (ent.Comp.SpellStorage is not null) - RaiseLocalEvent(ent.Comp.SpellStorage.Value, manaEv); + if (magicEffect.SpellStorage is not null) + RaiseLocalEvent(magicEffect.SpellStorage.Value, manaEv); manaCost = manaEv.GetManacost(); } return manaCost; } + + private void OnStaminaConsume(Entity ent, ref CP14MagicEffectConsumeResourceEvent args) + { + if (args.Performer is null) + return; + + _stamina.TakeStaminaDamage(args.Performer.Value, ent.Comp.Stamina, visual: false); + } } diff --git a/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectComponent.cs b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectComponent.cs index 6f72381ac3..8afff4cdd8 100644 --- a/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectComponent.cs +++ b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectComponent.cs @@ -1,13 +1,13 @@ using Content.Shared._CP14.MagicRitual.Prototypes; using Content.Shared._CP14.MagicSpell.Spells; using Content.Shared._CP14.MagicSpellStorage; -using Content.Shared.FixedPoint; +using Content.Shared.DoAfter; using Robust.Shared.Prototypes; namespace Content.Shared._CP14.MagicSpell.Components; /// -/// Restricts the use of this action, by spending mana or user requirements. +/// Stores the results and appearance of the magic effect /// [RegisterComponent, Access(typeof(CP14SharedMagicSystem), typeof(CP14SpellStorageSystem))] public sealed partial class CP14MagicEffectComponent : Component @@ -18,18 +18,9 @@ public sealed partial class CP14MagicEffectComponent : Component [DataField] public Entity? SpellStorage; - [DataField] - public FixedPoint2 ManaCost = 0f; - [DataField] public ProtoId? MagicType = null; - /// - /// Can the cost of casting this magic effect be changed from clothing or other sources? - /// - [DataField] - public bool CanModifyManacost = true; - /// /// Effects that will trigger at the beginning of the cast, before mana is spent. Should have no gameplay importance, just special effects, popups and sounds. /// @@ -38,4 +29,7 @@ public sealed partial class CP14MagicEffectComponent : Component [DataField] public List Effects = new(); + + [DataField] + public DoAfterId? ActiveDoAfter; } diff --git a/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectManaCostComponent.cs b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectManaCostComponent.cs new file mode 100644 index 0000000000..a67066e2cc --- /dev/null +++ b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectManaCostComponent.cs @@ -0,0 +1,20 @@ +using Content.Shared._CP14.MagicSpellStorage; +using Content.Shared.FixedPoint; + +namespace Content.Shared._CP14.MagicSpell.Components; + +/// +/// Restricts the use of this action, by spending mana or user requirements. +/// +[RegisterComponent, Access(typeof(CP14SharedMagicSystem), typeof(CP14SpellStorageSystem))] +public sealed partial class CP14MagicEffectManaCostComponent : Component +{ + [DataField] + public FixedPoint2 ManaCost = 0f; + + /// + /// Can the cost of casting this magic effect be changed from clothing or other sources? + /// + [DataField] + public bool CanModifyManacost = true; +} diff --git a/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectStaminaCostComponent.cs b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectStaminaCostComponent.cs new file mode 100644 index 0000000000..ae73e19e7d --- /dev/null +++ b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectStaminaCostComponent.cs @@ -0,0 +1,13 @@ +using Content.Shared._CP14.MagicSpellStorage; + +namespace Content.Shared._CP14.MagicSpell.Components; + +/// +/// Restricts the use of this action, by spending stamina. +/// +[RegisterComponent, Access(typeof(CP14SharedMagicSystem), typeof(CP14SpellStorageSystem))] +public sealed partial class CP14MagicEffectStaminaCostComponent : Component +{ + [DataField] + public float Stamina = 0f; +} diff --git a/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectToggledComponent.cs b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectToggledComponent.cs new file mode 100644 index 0000000000..2cd384b7ad --- /dev/null +++ b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectToggledComponent.cs @@ -0,0 +1,31 @@ +using Content.Shared.DoAfter; +using Robust.Shared.Map; + +namespace Content.Shared._CP14.MagicSpell.Components; + +/// +/// +/// +[RegisterComponent, AutoGenerateComponentPause, Access(typeof(CP14SharedMagicSystem))] +public sealed partial class CP14MagicEffectToggledComponent : Component +{ + [DataField] + public float Cooldown = 1f; + + [DataField, AutoPausedField] + public TimeSpan NextTick = TimeSpan.Zero; + + [DataField] + public float Frequency = 0f; + + [DataField] + public EntityUid? Performer; + + public DoAfterId? DoAfterId; + + [DataField] + public EntityUid? EntityTarget; + + [DataField] + public EntityCoordinates? WorldTarget; +} diff --git a/Content.Shared/_CP14/MagicSpell/Events/CP14CastMagicEffectEvent.cs b/Content.Shared/_CP14/MagicSpell/Events/CP14CastMagicEffectEvent.cs index 6025720365..ced1b61dc4 100644 --- a/Content.Shared/_CP14/MagicSpell/Events/CP14CastMagicEffectEvent.cs +++ b/Content.Shared/_CP14/MagicSpell/Events/CP14CastMagicEffectEvent.cs @@ -89,11 +89,11 @@ public sealed class CP14EndCastMagicEffectEvent : EntityEventArgs /// is invoked only if the spell has been successfully cast /// [ByRefEvent] -public sealed class CP14AfterCastMagicEffectEvent : EntityEventArgs +public sealed class CP14MagicEffectConsumeResourceEvent : EntityEventArgs { public EntityUid? Performer { get; init; } - public CP14AfterCastMagicEffectEvent(EntityUid? performer) + public CP14MagicEffectConsumeResourceEvent(EntityUid? performer) { Performer = performer; } diff --git a/Content.Shared/_CP14/MagicSpell/Events/CP14DelayedActionEvents.cs b/Content.Shared/_CP14/MagicSpell/Events/CP14DelayedActionEvents.cs index e76f94737e..e1a8590eaf 100644 --- a/Content.Shared/_CP14/MagicSpell/Events/CP14DelayedActionEvents.cs +++ b/Content.Shared/_CP14/MagicSpell/Events/CP14DelayedActionEvents.cs @@ -5,6 +5,21 @@ using Robust.Shared.Serialization; namespace Content.Shared._CP14.MagicSpell.Events; +public interface ICP14DelayedMagicEffect +{ + public float Cooldown { get; } + + public float CastDelay { get; } + + public bool BreakOnMove { get; } + + public bool BreakOnDamage { get; } + + public bool Hidden{ get; } + + public float EntityDistance { get; } +} + public sealed partial class CP14DelayedEntityWorldTargetActionEvent : EntityWorldTargetActionEvent, ICP14DelayedMagicEffect { diff --git a/Content.Shared/_CP14/MagicSpell/Events/CP14IDelayedMagicEffect.cs b/Content.Shared/_CP14/MagicSpell/Events/CP14IDelayedMagicEffect.cs deleted file mode 100644 index 983c00dd36..0000000000 --- a/Content.Shared/_CP14/MagicSpell/Events/CP14IDelayedMagicEffect.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Content.Shared._CP14.MagicSpell.Events; - -public interface ICP14DelayedMagicEffect -{ - public float Cooldown { get; } - - public float CastDelay { get; } - - public bool BreakOnMove { get; } - - public bool BreakOnDamage { get; } - - public bool Hidden{ get; } - - public float EntityDistance { get; } -} diff --git a/Content.Shared/_CP14/MagicSpell/Events/CP14ToggleableActionEvents.cs b/Content.Shared/_CP14/MagicSpell/Events/CP14ToggleableActionEvents.cs new file mode 100644 index 0000000000..1d3db4b69d --- /dev/null +++ b/Content.Shared/_CP14/MagicSpell/Events/CP14ToggleableActionEvents.cs @@ -0,0 +1,147 @@ +using Content.Shared.Actions; +using Content.Shared.DoAfter; +using Robust.Shared.Map; +using Robust.Shared.Serialization; + +namespace Content.Shared._CP14.MagicSpell.Events; + +public interface ICP14ToggleableMagicEffect +{ + public float EffectFrequency { get; } + + public float CastTime { get; } + + public float Cooldown { get; } + + public bool BreakOnMove { get; } + + public bool BreakOnDamage { get; } + + public bool Hidden{ get; } + + public float EntityDistance { get; } +} + +public sealed partial class CP14ToggleableInstantActionEvent : InstantActionEvent, ICP14ToggleableMagicEffect +{ + [DataField] + public float EffectFrequency { get; private set; } = 1f; + + [DataField] + public float Cooldown { get; private set; } = 3f; + + [DataField] + public float CastTime { get; private set; } = 10f; + + [DataField] + public bool BreakOnMove { get; private set; } = false; + + [DataField] + public bool BreakOnDamage { get; private set; } = true; + + [DataField] + public bool Hidden { get; private set; } = false; + + [DataField] + public float EntityDistance { get; private set; } = 100f; +} + +public sealed partial class CP14ToggleableEntityWorldTargetActionEvent : EntityWorldTargetActionEvent, ICP14ToggleableMagicEffect +{ + [DataField] + public float EffectFrequency { get; private set; } = 1f; + + [DataField] + public float Cooldown { get; private set; } = 3f; + + [DataField] + public float CastTime { get; private set; } = 10f; + + [DataField] + public bool BreakOnMove { get; private set; } = false; + + [DataField] + public bool BreakOnDamage { get; private set; } = true; + + [DataField] + public bool Hidden { get; private set; } = false; + + [DataField] + public float EntityDistance { get; private set; } = 100f; +} + +public sealed partial class CP14ToggleableEntityTargetActionEvent : EntityTargetActionEvent, ICP14ToggleableMagicEffect +{ + [DataField] + public float EffectFrequency { get; private set; } = 1f; + + [DataField] + public float Cooldown { get; private set; } = 3f; + + [DataField] + public float CastTime { get; private set; } = 10f; + + [DataField] + public bool BreakOnMove { get; private set; } = false; + + [DataField] + public bool BreakOnDamage { get; private set; } = true; + + [DataField] + public bool Hidden { get; private set; } = false; + + [DataField] + public float EntityDistance { get; private set; } = 100f; +} + +[Serializable, NetSerializable] +public sealed partial class CP14ToggleableInstantActionDoAfterEvent : DoAfterEvent +{ + [DataField] + public float? Cooldown; + + public CP14ToggleableInstantActionDoAfterEvent(float cooldown) + { + Cooldown = cooldown; + } + + public override DoAfterEvent Clone() => this; +} + +[Serializable, NetSerializable] +public sealed partial class CP14ToggleableEntityWorldTargetActionDoAfterEvent : DoAfterEvent +{ + [DataField] + public NetCoordinates? TargetPosition; + [DataField] + public NetEntity? TargetEntity; + [DataField] + public float? Cooldown; + + public CP14ToggleableEntityWorldTargetActionDoAfterEvent(NetCoordinates? targetPos, NetEntity? targetEntity, float cooldown) + { + TargetPosition = targetPos; + TargetEntity = targetEntity; + Cooldown = cooldown; + } + + public override DoAfterEvent Clone() => this; +} + + +[Serializable, NetSerializable] +public sealed partial class CP14ToggleableEntityTargetActionDoAfterEvent : DoAfterEvent +{ + [DataField] + public NetEntity? TargetEntity; + [DataField] + public float? Cooldown; + + public CP14ToggleableEntityTargetActionDoAfterEvent(NetEntity? targetEntity, float cooldown) + { + TargetEntity = targetEntity; + Cooldown = cooldown; + } + + public override DoAfterEvent Clone() => this; +} diff --git a/Content.Shared/_CP14/MagicSpellStorage/CP14SpellStorageComponent.cs b/Content.Shared/_CP14/MagicSpellStorage/CP14SpellStorageComponent.cs index 971f50b4c8..3aec79a052 100644 --- a/Content.Shared/_CP14/MagicSpellStorage/CP14SpellStorageComponent.cs +++ b/Content.Shared/_CP14/MagicSpellStorage/CP14SpellStorageComponent.cs @@ -19,10 +19,4 @@ public sealed partial class CP14SpellStorageComponent : Component /// [DataField] public List SpellEntities = new(); - - /// - /// allows you to use an caster's mana to create spells. - /// - [DataField] - public bool CanUseCasterMana = true; } diff --git a/Resources/Locale/en-US/_CP14/magicEnergy/magic-spells.ftl b/Resources/Locale/en-US/_CP14/magicEnergy/magic-spells.ftl index a709d3f4a0..7ce7c58826 100644 --- a/Resources/Locale/en-US/_CP14/magicEnergy/magic-spells.ftl +++ b/Resources/Locale/en-US/_CP14/magicEnergy/magic-spells.ftl @@ -1,6 +1,4 @@ cp14-magic-spell-not-enough-mana = Not enough mana! -cp14-magic-spell-not-enough-mana-item = Not enough mana in {$item}! - cp14-magic-spell-not-enough-mana-cast-warning-0 = Everything inside you starts to whine unpleasantly... cp14-magic-spell-not-enough-mana-cast-warning-1 = Your head starts to buzz... @@ -13,4 +11,7 @@ cp14-magic-energy-damage-overload = You can't hold that much mana! cp14-magic-energy-damage-burn-out-fall = You pass out from the intense pain! cp14-magic-spell-need-verbal-component = You can't cast the spell out loud. -cp14-magic-spell-need-somatic-component = You don't have your hands free. \ No newline at end of file +cp14-magic-spell-need-somatic-component = You don't have your hands free. + +cp14-magic-spell-stamina-not-enough = You don't have the energy to do it. +cp14-magic-staminacost = Stamina cost \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-spells.ftl b/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-spells.ftl index 36f1fbf213..50ce689bd0 100644 --- a/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-spells.ftl +++ b/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-spells.ftl @@ -1,5 +1,4 @@ cp14-magic-spell-not-enough-mana = Недостаточно магической энергии! -cp14-magic-spell-not-enough-mana-item = Недостаточно магической энергии в {$item}! cp14-magic-spell-not-enough-mana-cast-warning-0 = Внутри вас все начинает неприятно ныть... cp14-magic-spell-not-enough-mana-cast-warning-1 = Голова начинает шуметь... @@ -12,4 +11,7 @@ cp14-magic-energy-damage-overload = Вы не можете удержать ст cp14-magic-energy-damage-burn-out-fall = Вы теряете сознание от сильной боли! cp14-magic-spell-need-verbal-component = Вы не можете произнести заклинание вслух. -cp14-magic-spell-need-somatic-component = Вам не хватает свободных рук. \ No newline at end of file +cp14-magic-spell-need-somatic-component = Вам не хватает свободных рук. + +cp14-magic-spell-stamina-not-enough = Вам не хватает сил, чтобы сделать это. +cp14-magic-staminacost = Затраты энергии \ No newline at end of file diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Earth/T1_earth_wall.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Earth/T1_earth_wall.yml index d8be6fbde0..8ba09a32a1 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Earth/T1_earth_wall.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Earth/T1_earth_wall.yml @@ -8,9 +8,10 @@ state: earth_wall - type: CP14MagicEffectCastSlowdown speedMultiplier: 0.3 + - type: CP14MagicEffectManaCost + manaCost: 15 - type: CP14MagicEffect magicType: Earth - manaCost: 15 telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T0_flame_creation.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T0_flame_creation.yml index 79fd7ad0b2..bdfdaf441b 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T0_flame_creation.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T0_flame_creation.yml @@ -6,9 +6,10 @@ - type: Sprite sprite: _CP14/Effects/Magic/spells_icons.rsi state: flame_creation + - type: CP14MagicEffectManaCost + manaCost: 5 - type: CP14MagicEffect magicType: Fire - manaCost: 5 effects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T1_fireball.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T1_fireball.yml index 975d53dd0b..428647e6ba 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T1_fireball.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Fire/T1_fireball.yml @@ -8,9 +8,10 @@ state: fireball - type: CP14MagicEffectCastSlowdown speedMultiplier: 0.3 + - type: CP14MagicEffectManaCost + manaCost: 20 - type: CP14MagicEffect magicType: Fire - manaCost: 20 effects: - !type:CP14SpellSpawnEntityOnUser spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Gate/T2_shadow_step.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Gate/T2_shadow_step.yml index 302a2b5919..aa17fe2d74 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Gate/T2_shadow_step.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Gate/T2_shadow_step.yml @@ -8,9 +8,10 @@ state: shadow_step - type: CP14MagicEffectCastSlowdown speedMultiplier: 0.8 + - type: CP14MagicEffectManaCost + manaCost: 20 - type: CP14MagicEffect magicType: Gate - manaCost: 20 telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_heat.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_heat.yml index 2cd1b5e89b..93d55813e5 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_heat.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_heat.yml @@ -8,9 +8,10 @@ state: cure_burn - type: CP14MagicEffectCastSlowdown speedMultiplier: 0.5 + - type: CP14MagicEffectManaCost + manaCost: 10 - type: CP14MagicEffect magicType: Healing - manaCost: 10 telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_poison.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_poison.yml index 787b629f47..c3db395de2 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_poison.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_poison.yml @@ -8,9 +8,10 @@ state: cure_poison - type: CP14MagicEffectCastSlowdown speedMultiplier: 0.5 + - type: CP14MagicEffectManaCost + manaCost: 10 - type: CP14MagicEffect magicType: Healing - manaCost: 10 telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_wounds.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_wounds.yml index 63c05466bf..22d72cee4e 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_wounds.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Healing/T0_cure_wounds.yml @@ -8,9 +8,10 @@ state: cure_wounds - type: CP14MagicEffectCastSlowdown speedMultiplier: 0.5 + - type: CP14MagicEffectManaCost + manaCost: 10 - type: CP14MagicEffect magicType: Healing - manaCost: 10 telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/LightDarkness/T0_sphere_of_light.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/LightDarkness/T0_sphere_of_light.yml index 953d563aff..b54f21cc64 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/LightDarkness/T0_sphere_of_light.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/LightDarkness/T0_sphere_of_light.yml @@ -6,9 +6,10 @@ - type: Sprite sprite: _CP14/Effects/Magic/spells_icons.rsi state: sphere_of_light + - type: CP14MagicEffectManaCost + manaCost: 10 - type: CP14MagicEffect magicType: LightDarkness - manaCost: 10 effects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/LightDarkness/T1_flash_light.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/LightDarkness/T1_flash_light.yml index c6d85e0e4d..4552c73499 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/LightDarkness/T1_flash_light.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/LightDarkness/T1_flash_light.yml @@ -6,9 +6,10 @@ - type: Sprite sprite: _CP14/Effects/Magic/spells_icons.rsi state: flash_light + - type: CP14MagicEffectManaCost + manaCost: 10 - type: CP14MagicEffect magicType: LightDarkness - manaCost: 10 telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Meta/T0_mana_consume.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Meta/T0_mana_consume.yml index 6f47950e11..0209990fe2 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Meta/T0_mana_consume.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Meta/T0_mana_consume.yml @@ -8,8 +8,6 @@ state: mana_consume - type: CP14MagicEffect magicType: Meta - manaCost: 0 - canModifyManacost: false telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: @@ -34,9 +32,9 @@ icon: sprite: _CP14/Effects/Magic/spells_icons.rsi state: mana_consume - event: !type:CP14DelayedEntityTargetActionEvent - cooldown: 1 - castDelay: 2 + event: !type:CP14ToggleableEntityTargetActionEvent + cooldown: 5 + castTime: 10 breakOnMove: true - type: entity diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Meta/T0_mana_gift.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Meta/T0_mana_gift.yml index 101338222f..b9d85042fb 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Meta/T0_mana_gift.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Meta/T0_mana_gift.yml @@ -6,10 +6,11 @@ - type: Sprite sprite: _CP14/Effects/Magic/spells_icons.rsi state: mana_gift - - type: CP14MagicEffect - magicType: Meta + - type: CP14MagicEffectManaCost manaCost: 12 canModifyManacost: false + - type: CP14MagicEffect + magicType: Meta telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: @@ -39,9 +40,9 @@ icon: sprite: _CP14/Effects/Magic/spells_icons.rsi state: mana_gift - event: !type:CP14DelayedEntityTargetActionEvent - cooldown: 1 - castDelay: 1 + event: !type:CP14ToggleableEntityTargetActionEvent + cooldown: 5 + castTime: 10 - type: entity id: CP14RuneManaGift diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Movement/T0_shadow_grab.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Movement/T0_shadow_grab.yml index 7cf26e96c0..81424f1577 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Movement/T0_shadow_grab.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Movement/T0_shadow_grab.yml @@ -6,9 +6,10 @@ - type: Sprite sprite: _CP14/Effects/Magic/spells_icons.rsi state: shadow_grab + - type: CP14MagicEffectManaCost + manaCost: 10 - type: CP14MagicEffect magicType: Movement - manaCost: 10 telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Necromancy/T1_resurrection.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Necromancy/T1_resurrection.yml index 846dddf120..49a7b8919d 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Necromancy/T1_resurrection.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Necromancy/T1_resurrection.yml @@ -8,9 +8,10 @@ state: resurrection - type: CP14MagicEffectCastSlowdown speedMultiplier: 0.2 + - type: CP14MagicEffectManaCost + manaCost: 100 - type: CP14MagicEffect magicType: Necromancy - manaCost: 100 telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T0_water_creation.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T0_water_creation.yml index 12b2211370..57e1b91600 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T0_water_creation.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T0_water_creation.yml @@ -6,9 +6,10 @@ - type: Sprite sprite: _CP14/Effects/Magic/spells_icons.rsi state: water_creation + - type: CP14MagicEffectManaCost + manaCost: 10 - type: CP14MagicEffect magicType: Water - manaCost: 10 effects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T1_beer_creation.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T1_beer_creation.yml index 61717be8ea..742491d7a1 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T1_beer_creation.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T1_beer_creation.yml @@ -6,9 +6,10 @@ - type: Sprite sprite: _CP14/Effects/Magic/spells_icons.rsi state: beer_creation + - type: CP14MagicEffectManaCost + manaCost: 50 - type: CP14MagicEffect magicType: Water - manaCost: 50 effects: - !type:CP14SpellSpawnEntityOnTarget spawns: diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T1_ice_shards.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T1_ice_shards.yml index 103ca0380e..5a3cbf8b94 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T1_ice_shards.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Water/T1_ice_shards.yml @@ -8,9 +8,10 @@ state: ice_shards - type: CP14MagicEffectCastSlowdown speedMultiplier: 0.75 + - type: CP14MagicEffectManaCost + manaCost: 5 - type: CP14MagicEffect magicType: Water - manaCost: 5 effects: - !type:CP14SpellProjectile prototype: CP14IceShard