diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Checks.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Checks.cs index b90c03a362..efa751e987 100644 --- a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Checks.cs +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.Checks.cs @@ -3,7 +3,8 @@ using Content.Shared._CP14.MagicSpell.Events; using Content.Shared.CombatMode.Pacification; using Content.Shared.Damage.Components; using Content.Shared.Hands.Components; -using Content.Shared.Instruments; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Speech.Muting; @@ -11,6 +12,8 @@ namespace Content.Shared._CP14.MagicSpell; public abstract partial class CP14SharedMagicSystem { + [Dependency] private readonly MobStateSystem _mobState = default!; + private void InitializeChecks() { SubscribeLocalEvent(OnSomaticCheck); @@ -18,6 +21,7 @@ public abstract partial class CP14SharedMagicSystem SubscribeLocalEvent(OnManaCheck); SubscribeLocalEvent(OnStaminaCheck); SubscribeLocalEvent(OnPacifiedCheck); + SubscribeLocalEvent(OnMobStateCheck); //Verbal speaking SubscribeLocalEvent(OnVerbalAspectStartCast); @@ -37,7 +41,8 @@ public abstract partial class CP14SharedMagicSystem //First - trying get mana from item if (_magicEffectQuery.TryComp(ent, out var magicEffect)) { - if (magicEffect.SpellStorage is not null && _magicContainerQuery.TryComp(magicEffect.SpellStorage, out var magicContainer)) + if (magicEffect.SpellStorage is not null && + _magicContainerQuery.TryComp(magicEffect.SpellStorage, out var magicContainer)) requiredMana = MathF.Max(0, (float)(requiredMana - magicContainer.Energy)); } @@ -53,22 +58,27 @@ public abstract partial class CP14SharedMagicSystem } 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); + _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) + 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(); - } + if (!staminaComp.Critical) + return; + + args.PushReason(Loc.GetString("cp14-magic-spell-stamina-not-enough")); + args.Cancel(); } - private void OnSomaticCheck(Entity ent, ref CP14CastMagicEffectAttemptEvent args) + private void OnSomaticCheck(Entity ent, + ref CP14CastMagicEffectAttemptEvent args) { if (TryComp(args.Performer, out var hands) || hands is not null) { @@ -78,32 +88,68 @@ public abstract partial class CP14SharedMagicSystem 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) + private void OnVerbalCheck(Entity ent, + ref CP14CastMagicEffectAttemptEvent args) { - if (HasComp(args.Performer)) + if (!HasComp(args.Performer)) + return; + + args.PushReason(Loc.GetString("cp14-magic-spell-need-verbal-component")); + args.Cancel(); + } + + private void OnPacifiedCheck(Entity ent, + ref CP14CastMagicEffectAttemptEvent args) + { + if (!HasComp(args.Performer)) + return; + + args.PushReason(Loc.GetString("cp14-magic-spell-pacified")); + args.Cancel(); + } + + private void OnMobStateCheck(Entity ent, + ref CP14CastMagicEffectAttemptEvent args) + { + if (args.Target is not { } target) + return; + + if (!TryComp(target, out var mobStateComp)) { - args.PushReason(Loc.GetString("cp14-magic-spell-need-verbal-component")); + args.PushReason(Loc.GetString("cp14-magic-spell-target-not-mob")); args.Cancel(); + return; + } + + if (!ent.Comp.Inverted) + { + if (_mobState.IsDead(target, mobStateComp)) + { + args.PushReason(Loc.GetString("cp14-magic-spell-target-dead")); + args.Cancel(); + } + } + else + { + if (!_mobState.IsDead(target, mobStateComp)) + { + args.PushReason(Loc.GetString("cp14-magic-spell-target-alive")); + args.Cancel(); + } } } - private void OnPacifiedCheck(Entity ent, ref CP14CastMagicEffectAttemptEvent args) - { - if (HasComp(args.Performer)) - { - args.PushReason(Loc.GetString("cp14-magic-spell-pacified")); - args.Cancel(); - } - } - - private void OnVerbalAspectStartCast(Entity ent, ref CP14StartCastMagicEffectEvent args) + private void OnVerbalAspectStartCast(Entity ent, + ref CP14StartCastMagicEffectEvent args) { var ev = new CP14SpellSpeechEvent { @@ -114,7 +160,8 @@ public abstract partial class CP14SharedMagicSystem RaiseLocalEvent(ent, ref ev); } - private void OnVerbalAspectAfterCast(Entity ent, ref CP14MagicEffectConsumeResourceEvent args) + private void OnVerbalAspectAfterCast(Entity ent, + ref CP14MagicEffectConsumeResourceEvent args) { if (_net.IsClient) return; diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs index e6a4c4dd6c..264964cece 100644 --- a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.DelayedActions.cs @@ -36,6 +36,7 @@ public abstract partial class CP14SharedMagicSystem BlockDuplicate = true, BreakOnDropItem = fromItem, NeedHand = fromItem, + RequireCanInteract = delayedEffect.RequireCanInteract, }; if (_doAfter.TryStartDoAfter(doAfterEventArgs, out var doAfterId)) @@ -56,31 +57,30 @@ public abstract partial class CP14SharedMagicSystem _action.CP14StartCustomDelay(action, TimeSpan.FromSeconds(cooldown.Value)); } - private void UseDelayedAction(ICP14DelayedMagicEffect delayedEffect, Entity action, DoAfterEvent doAfter, EntityUid performer, EntityUid? target = null, EntityCoordinates? worldTarget = null) + private bool UseDelayedAction(ICP14DelayedMagicEffect delayedEffect, Entity action, DoAfterEvent doAfter, EntityUid performer, EntityUid? target = null, EntityCoordinates? worldTarget = null) { - if (!CanCastSpell(action, performer)) - return; + // Event may return an empty entity with id = 0, which causes bugs + var currentTarget = target; + if (currentTarget is not null && currentTarget == EntityUid.Invalid) + currentTarget = null; - // event may return an empty entity with id = 0, which causes bugs - var _target = target; - if (_target is not null && _target.Value.Id == 0) - _target = null; + var spellArgs = new CP14SpellEffectBaseArgs(performer, action.Comp.SpellStorage, currentTarget, worldTarget); + if (!CanCastSpell(action, spellArgs)) + return false; if (_doAfter.IsRunning(action.Comp.ActiveDoAfter)) - _doAfter.Cancel(action.Comp.ActiveDoAfter); - else { - if (TryStartDelayedAction(delayedEffect, doAfter, action, _target, performer)) - { - var evStart = new CP14StartCastMagicEffectEvent(performer); - RaiseLocalEvent(action, ref evStart); - - var spellArgs = - new CP14SpellEffectBaseArgs(performer, action.Comp.SpellStorage, _target, worldTarget); - - CastTelegraphy(action, spellArgs); - } + _doAfter.Cancel(action.Comp.ActiveDoAfter); + return false; } + + if (!TryStartDelayedAction(delayedEffect, doAfter, action, currentTarget, performer)) + return false; + + var evStart = new CP14StartCastMagicEffectEvent(performer); + RaiseLocalEvent(action, ref evStart); + CastTelegraphy(action, spellArgs); + return true; } /// @@ -98,7 +98,9 @@ public abstract partial class CP14SharedMagicSystem return; var doAfter = new CP14DelayedInstantActionDoAfterEvent(args.Cooldown); - UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer, args.Performer); + + if (!UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer, args.Performer)) + return; args.Handled = true; } @@ -121,7 +123,9 @@ public abstract partial class CP14SharedMagicSystem EntityManager.GetNetCoordinates(args.Coords), EntityManager.GetNetEntity(args.Entity), args.Cooldown); - UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer, args.Entity, args.Coords); + + if (!UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer, args.Entity, args.Coords)) + return; args.Handled = true; } @@ -141,7 +145,9 @@ public abstract partial class CP14SharedMagicSystem return; var doAfter = new CP14DelayedEntityTargetActionDoAfterEvent(EntityManager.GetNetEntity(args.Target), args.Cooldown); - UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer, args.Target); + + if (!UseDelayedAction(delayedEffect, (args.Action, magicEffect), doAfter, args.Performer, args.Target)) + return; args.Handled = true; } diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.InstantActions.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.InstantActions.cs index acaba35e04..747f2ea102 100644 --- a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.InstantActions.cs +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.InstantActions.cs @@ -21,11 +21,10 @@ public abstract partial class CP14SharedMagicSystem if (!TryComp(args.Action, out var magicEffect)) return; - if (!CanCastSpell((args.Action, magicEffect), args.Performer)) - return; + var spellArgs = new CP14SpellEffectBaseArgs(args.Performer, magicEffect.SpellStorage, args.Performer, Transform(args.Performer).Coordinates); - var spellArgs = - new CP14SpellEffectBaseArgs(args.Performer, magicEffect.SpellStorage, args.Performer, Transform(args.Performer).Coordinates); + if (!CanCastSpell((args.Action, magicEffect), spellArgs)) + return; CastSpell((args.Action, magicEffect), spellArgs); _action.CP14StartCustomDelay(args.Action, args.Cooldown); @@ -39,11 +38,10 @@ public abstract partial class CP14SharedMagicSystem if (!TryComp(args.Action, out var magicEffect)) return; - if (!CanCastSpell((args.Action, magicEffect), args.Performer)) - return; + var spellArgs = new CP14SpellEffectBaseArgs(args.Performer, magicEffect.SpellStorage, args.Entity, args.Coords); - var spellArgs = - new CP14SpellEffectBaseArgs(args.Performer, magicEffect.SpellStorage, args.Entity, args.Coords); + if (!CanCastSpell((args.Action, magicEffect), spellArgs)) + return; CastSpell((args.Action, magicEffect), spellArgs); _action.CP14StartCustomDelay(args.Action, args.Cooldown); @@ -57,11 +55,10 @@ public abstract partial class CP14SharedMagicSystem if (!TryComp(args.Action, out var magicEffect)) return; - if (!CanCastSpell((args.Action, magicEffect), args.Performer)) - return; + var spellArgs = new CP14SpellEffectBaseArgs(args.Performer, magicEffect.SpellStorage, args.Target, Transform(args.Target).Coordinates); - var spellArgs = - new CP14SpellEffectBaseArgs(args.Performer, magicEffect.SpellStorage, args.Target, Transform(args.Target).Coordinates); + if (!CanCastSpell((args.Action, magicEffect), spellArgs)) + return; CastSpell((args.Action, magicEffect), spellArgs); _action.CP14StartCustomDelay(args.Action, args.Cooldown); diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.ToggleableActions.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.ToggleableActions.cs index b41266df25..9d251e60f0 100644 --- a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.ToggleableActions.cs +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.ToggleableActions.cs @@ -36,7 +36,7 @@ public abstract partial class CP14SharedMagicSystem var spellArgs = new CP14SpellEffectBaseArgs(toggled.Performer, effect.SpellStorage, toggled.EntityTarget, toggled.WorldTarget); - if (!CanCastSpell((uid, effect), toggled.Performer.Value)) + if (!CanCastSpell((uid, effect), spellArgs)) { if (_doAfter.IsRunning(toggled.DoAfterId)) _doAfter.Cancel(toggled.DoAfterId); @@ -116,7 +116,8 @@ public abstract partial class CP14SharedMagicSystem private void ToggleToggleableAction(ICP14ToggleableMagicEffect toggleable, DoAfterEvent doAfter, Entity action, EntityUid performer, EntityUid? entityTarget = null, EntityCoordinates? worldTarget = null) { - if (!CanCastSpell(action, performer)) + var spellArgs = new CP14SpellEffectBaseArgs(performer, entityTarget, entityTarget, worldTarget); + if (!CanCastSpell(action, spellArgs)) return; if (_doAfter.IsRunning(action.Comp.ActiveDoAfter)) diff --git a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.cs b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.cs index 039898ee54..e510101d6d 100644 --- a/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.cs +++ b/Content.Shared/_CP14/MagicSpell/CP14SharedMagicSystem.cs @@ -1,3 +1,4 @@ +using System.Linq; using System.Text; using Content.Shared._CP14.MagicEnergy; using Content.Shared._CP14.MagicEnergy.Components; @@ -118,7 +119,7 @@ public abstract partial class CP14SharedMagicSystem : EntitySystem 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-type")}: [color={indexedMagic.Color.ToHex()}]{Loc.GetString(indexedMagic.Name)}[/color]"); } if (TryComp(ent, out var verbal)) @@ -148,20 +149,23 @@ public abstract partial class CP14SharedMagicSystem : EntitySystem /// /// Checking to see if the spell can be used at all /// - private bool CanCastSpell(Entity ent, EntityUid performer) + private bool CanCastSpell(Entity ent, CP14SpellEffectBaseArgs args) { - var ev = new CP14CastMagicEffectAttemptEvent(performer); - RaiseLocalEvent(ent, ref ev); - if (ev.Reason != string.Empty && _net.IsServer) - { - _popup.PopupEntity(ev.Reason, performer, performer); - } + if (args.User is not { } performer) + return true; + + var ev = new CP14CastMagicEffectAttemptEvent(performer, args.Used, args.Target, args.Position); + RaiseLocalEvent(ent, ev); + + if (ev.Reason != string.Empty) + _popup.PopupPredicted(ev.Reason, performer, performer); + return !ev.Cancelled; } private void CastTelegraphy(Entity ent, CP14SpellEffectBaseArgs args) { - if (!_net.IsServer) + if (_net.IsClient) return; foreach (var effect in ent.Comp.TelegraphyEffects) @@ -175,12 +179,12 @@ public abstract partial class CP14SharedMagicSystem : EntitySystem var ev = new CP14MagicEffectConsumeResourceEvent(args.User); RaiseLocalEvent(ent, ref ev); - if (_net.IsServer) + if (_net.IsClient) + return; + + foreach (var effect in ent.Comp.Effects) { - foreach (var effect in ent.Comp.Effects) - { - effect.Effect(EntityManager, args); - } + effect.Effect(EntityManager, args); } } diff --git a/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectAliveTargetRequiredComponent.cs b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectAliveTargetRequiredComponent.cs new file mode 100644 index 0000000000..c1af631afd --- /dev/null +++ b/Content.Shared/_CP14/MagicSpell/Components/CP14MagicEffectAliveTargetRequiredComponent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared._CP14.MagicSpell.Components; + +/// +/// Allows you to limit the use of a spell based on the target's alive/dead status +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class CP14MagicEffectAliveTargetRequiredComponent : Component +{ + [DataField, AutoNetworkedField] + public bool Inverted = false; +} diff --git a/Content.Shared/_CP14/MagicSpell/Events/CP14CastMagicEffectEvent.cs b/Content.Shared/_CP14/MagicSpell/Events/CP14CastMagicEffectEvent.cs index ced1b61dc4..4206a7c5a5 100644 --- a/Content.Shared/_CP14/MagicSpell/Events/CP14CastMagicEffectEvent.cs +++ b/Content.Shared/_CP14/MagicSpell/Events/CP14CastMagicEffectEvent.cs @@ -1,7 +1,9 @@ using Content.Shared._CP14.MagicRitual.Prototypes; using Content.Shared._CP14.MagicSpell.Components; +using Content.Shared._CP14.MagicSpell.Spells; using Content.Shared.FixedPoint; using Content.Shared.Inventory; +using Robust.Shared.Map; using Robust.Shared.Prototypes; namespace Content.Shared._CP14.MagicSpell.Events; @@ -9,19 +11,24 @@ namespace Content.Shared._CP14.MagicSpell.Events; /// /// Called first to verify that all conditions are met and the spell can be performed. /// -[ByRefEvent] public sealed class CP14CastMagicEffectAttemptEvent : CancellableEntityEventArgs { /// /// The Performer of the event, to check if they meet the requirements. /// - public EntityUid Performer { get; init; } + public readonly EntityUid Performer; + public readonly EntityUid? Used; + public readonly EntityUid? Target; + public readonly EntityCoordinates? Position; public string Reason = string.Empty; - public CP14CastMagicEffectAttemptEvent(EntityUid performer) + public CP14CastMagicEffectAttemptEvent(EntityUid performer, EntityUid? used, EntityUid? target, EntityCoordinates? position) { Performer = performer; + Used = used; + Target = target; + Position = position; } public void PushReason(string reason) diff --git a/Content.Shared/_CP14/MagicSpell/Events/CP14DelayedActionEvents.cs b/Content.Shared/_CP14/MagicSpell/Events/CP14DelayedActionEvents.cs index 496d572a3e..d8b14220b1 100644 --- a/Content.Shared/_CP14/MagicSpell/Events/CP14DelayedActionEvents.cs +++ b/Content.Shared/_CP14/MagicSpell/Events/CP14DelayedActionEvents.cs @@ -17,7 +17,9 @@ public interface ICP14DelayedMagicEffect public float DistanceThreshold { get; } - public bool Hidden{ get; } + public bool Hidden { get; } + + public bool RequireCanInteract { get; } } public sealed partial class CP14DelayedEntityWorldTargetActionEvent : EntityWorldTargetActionEvent, @@ -40,6 +42,9 @@ public sealed partial class CP14DelayedEntityWorldTargetActionEvent : EntityWorl [DataField] public bool Hidden { get; private set; } = false; + + [DataField] + public bool RequireCanInteract { get; private set; } = true; } //Entity Target @@ -63,6 +68,9 @@ public sealed partial class CP14DelayedEntityTargetActionEvent : EntityTargetAct [DataField] public bool Hidden { get; private set; } = false; + + [DataField] + public bool RequireCanInteract { get; private set; } = true; } public sealed partial class CP14DelayedInstantActionEvent : InstantActionEvent, ICP14DelayedMagicEffect @@ -84,6 +92,9 @@ public sealed partial class CP14DelayedInstantActionEvent : InstantActionEvent, [DataField] public bool Hidden { get; private set; } = false; + + [DataField] + public bool RequireCanInteract { get; private set; } = true; } [Serializable, NetSerializable] diff --git a/Content.Shared/_CP14/MagicSpell/Spells/CP14SpellCasterSwap.cs b/Content.Shared/_CP14/MagicSpell/Spells/CP14SpellCasterSwap.cs new file mode 100644 index 0000000000..e90ea2818d --- /dev/null +++ b/Content.Shared/_CP14/MagicSpell/Spells/CP14SpellCasterSwap.cs @@ -0,0 +1,17 @@ +namespace Content.Shared._CP14.MagicSpell.Spells; + +public sealed partial class CP14SpellCasterSwap : CP14SpellEffect +{ + public override void Effect(EntityManager entManager, CP14SpellEffectBaseArgs args) + { + if (args.User is not { } user || args.Target is not { } target) + return; + + var transform = entManager.System(); + var userPosition = transform.GetMoverCoordinates(user); + var targetPosition = transform.GetMoverCoordinates(target); + + transform.SetCoordinates(user, targetPosition); + transform.SetCoordinates(target, userPosition); + } +} diff --git a/Content.Shared/_CP14/MagicSpell/Spells/CP14SpellEffect.cs b/Content.Shared/_CP14/MagicSpell/Spells/CP14SpellEffect.cs index 768badd03a..418e29d5b9 100644 --- a/Content.Shared/_CP14/MagicSpell/Spells/CP14SpellEffect.cs +++ b/Content.Shared/_CP14/MagicSpell/Spells/CP14SpellEffect.cs @@ -10,7 +10,7 @@ public abstract partial class CP14SpellEffect public abstract void Effect(EntityManager entManager, CP14SpellEffectBaseArgs args); } -public record class CP14SpellEffectBaseArgs +public record CP14SpellEffectBaseArgs { public EntityUid? User; public EntityUid? Used; diff --git a/Resources/Locale/en-US/_CP14/magicEnergy/magic-spells.ftl b/Resources/Locale/en-US/_CP14/magicEnergy/magic-spells.ftl index 376c1b3545..856cf0a331 100644 --- a/Resources/Locale/en-US/_CP14/magicEnergy/magic-spells.ftl +++ b/Resources/Locale/en-US/_CP14/magicEnergy/magic-spells.ftl @@ -8,6 +8,7 @@ cp14-magic-spell-not-enough-mana-cast-warning-2 = Your hands are shaking... cp14-magic-spell-not-enough-mana-cast-warning-3 = Your throat starts to lump... cp14-magic-spell-not-enough-mana-cast-warning-4 = Your head becomes heavy... +cp14-magic-type = Type cp14-magic-verbal-aspect = Requires the ability to speak cp14-magic-somatic-aspect = Requires a free hand: cp14-magic-music-aspect = You must play a musical instrument @@ -17,4 +18,8 @@ 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 -cp14-magic-spell-pacified = It could hurt someone! \ No newline at end of file +cp14-magic-spell-pacified = It could hurt someone! + +cp14-magic-spell-target-not-mob = The target must be a living thing! +cp14-magic-spell-target-dead = Can't be used on the dead! +cp14-magic-spell-target-alive = Can't be used on the living! \ No newline at end of file diff --git a/Resources/Locale/en-US/_CP14/magicEnergy/magic-types.ftl b/Resources/Locale/en-US/_CP14/magicEnergy/magic-types.ftl index 2ba3c95ea1..caa5e6cf69 100644 --- a/Resources/Locale/en-US/_CP14/magicEnergy/magic-types.ftl +++ b/Resources/Locale/en-US/_CP14/magicEnergy/magic-types.ftl @@ -22,4 +22,4 @@ cp14-essence-magic = Praecantatio cp14-magic-manacost = Manacost cp14-magic-essence = Magic type -cp14-magic-essence-title = From here, essences can be extracted: \ No newline at end of file +cp14-magic-essence-title = From here, essences can be extracted: diff --git a/Resources/Locale/en-US/_CP14/reagents/meta/thaumaturgy/essence.ftl b/Resources/Locale/en-US/_CP14/reagents/meta/thaumaturgy/essence.ftl index b5ec8288f3..e6d8f0c5dd 100644 --- a/Resources/Locale/en-US/_CP14/reagents/meta/thaumaturgy/essence.ftl +++ b/Resources/Locale/en-US/_CP14/reagents/meta/thaumaturgy/essence.ftl @@ -40,7 +40,7 @@ cp14-reagent-desc-essence-poison = The liquid embodiment of the elements of pois cp14-reagent-name-essence-void = Vacuos essence cp14-reagent-desc-essence-void = The liquid embodiment of the elements of emptiness, obscurity, and secrecy. - + cp14-reagent-name-essence-life = Victus essence cp14-reagent-desc-essence-life = The liquid embodiment of the elements of life, food, and sustenance. @@ -51,8 +51,3 @@ cp14-reagent-desc-essence-crystal = The liquid embodiment of the elements of gla cp14-reagent-name-essence-magic = Praecantatio essence cp14-reagent-desc-essence-magic = The liquid embodiment of the elements of magic, enchantment and sorcery. - - - - - diff --git a/Resources/Locale/en-US/_CP14/skill/skill_tree.ftl b/Resources/Locale/en-US/_CP14/skill/skill_tree.ftl index c4a72617b6..77a958a554 100644 --- a/Resources/Locale/en-US/_CP14/skill/skill_tree.ftl +++ b/Resources/Locale/en-US/_CP14/skill/skill_tree.ftl @@ -16,6 +16,9 @@ cp14-skill-tree-illusion-desc = Explore the nature of light to create illusions, cp14-skill-tree-healing-name = Lifecation cp14-skill-tree-healing-desc = Explore the ways in which magic affects living creatures. +cp14-skill-tree-dimension-name = Dimensium +cp14-skill-tree-dimension-desc = Immerse yourself in the nature of space and void. + # Body cp14-skill-tree-atlethic-name = Atlethic diff --git a/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-spells.ftl b/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-spells.ftl index 433beaa736..16299ddc79 100644 --- a/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-spells.ftl +++ b/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-spells.ftl @@ -8,6 +8,7 @@ cp14-magic-spell-not-enough-mana-cast-warning-2 = Ваши руки дрожат cp14-magic-spell-not-enough-mana-cast-warning-3 = К горлу подступает ком... cp14-magic-spell-not-enough-mana-cast-warning-4 = Голова наливается свинцом... +cp14-magic-type = Тип cp14-magic-verbal-aspect = Требуется возможность говорить cp14-magic-somatic-aspect = Требуются свободные руки: cp14-magic-music-aspect = Вы должны играть на музыкальном инструменте @@ -17,4 +18,8 @@ cp14-magic-spell-need-somatic-component = Вам не хватает свобо cp14-magic-spell-stamina-not-enough = Вам не хватает сил, чтобы сделать это. cp14-magic-staminacost = Затраты энергии -cp14-magic-spell-pacified = Это может навредить кому либо! \ No newline at end of file +cp14-magic-spell-pacified = Это может навредить кому либо! + +cp14-magic-spell-target-not-mob = Цель должна быть живым существом! +cp14-magic-spell-target-dead = Нельзя использовать на мертвых! +cp14-magic-spell-target-alive = Нельзя использовать на живых! \ No newline at end of file diff --git a/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-types.ftl b/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-types.ftl index c0166d6b3f..1ea00c1627 100644 --- a/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-types.ftl +++ b/Resources/Locale/ru-RU/_CP14/magicEnergy/magic-types.ftl @@ -22,4 +22,4 @@ cp14-essence-magic = Praecantatio cp14-magic-manacost = Затраты маны cp14-magic-essence = Тип магии -cp14-magic-essence-title = Отсюда можно извлечь эссенции: \ No newline at end of file +cp14-magic-essence-title = Отсюда можно извлечь эссенции: diff --git a/Resources/Locale/ru-RU/_CP14/reagents/meta/thaumaturgy/essence.ftl b/Resources/Locale/ru-RU/_CP14/reagents/meta/thaumaturgy/essence.ftl index de7a3f87ce..700fc97388 100644 --- a/Resources/Locale/ru-RU/_CP14/reagents/meta/thaumaturgy/essence.ftl +++ b/Resources/Locale/ru-RU/_CP14/reagents/meta/thaumaturgy/essence.ftl @@ -40,7 +40,7 @@ cp14-reagent-desc-essence-poison = Жидкое воплощение стихи cp14-reagent-name-essence-void = Эссенция Vacuos cp14-reagent-desc-essence-void = Жидкое воплощение стихии пустоты, неизвестности и скрытности. - + cp14-reagent-name-essence-life = Эссенция Victus cp14-reagent-desc-essence-life = Жидкое воплощение стихии жизни, еды и пропитания. @@ -50,4 +50,4 @@ cp14-reagent-desc-essence-crystal = Жидкое воплощение стихи # Complex tier 2 cp14-reagent-name-essence-magic = Эссенция Praecantatio -cp14-reagent-desc-essence-magic = Жидкое воплощение магии, чар и колдовства. \ No newline at end of file +cp14-reagent-desc-essence-magic = Жидкое воплощение магии, чар и колдовства. diff --git a/Resources/Locale/ru-RU/_CP14/skill/skill_tree.ftl b/Resources/Locale/ru-RU/_CP14/skill/skill_tree.ftl index 2c20e1c3d0..cb8c66c017 100644 --- a/Resources/Locale/ru-RU/_CP14/skill/skill_tree.ftl +++ b/Resources/Locale/ru-RU/_CP14/skill/skill_tree.ftl @@ -18,7 +18,10 @@ cp14-skill-tree-illusion-desc = Исследуйте природу света, cp14-skill-tree-healing-name = Жизнетворение cp14-skill-tree-healing-desc = Изучайте способы влияния магии на живые создания. +cp14-skill-tree-dimension-name = Дименсиум +cp14-skill-tree-dimension-desc = Погрузитесь в природу пространства и пустоты. + # Body cp14-skill-tree-atlethic-name = Атлетика -cp14-skill-tree-atlethic-desc = Развивайте свое тело, расширяя границы доступного. \ No newline at end of file +cp14-skill-tree-atlethic-desc = Развивайте свое тело, расширяя границы доступного. diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Death/T1_resurrection.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Death/T1_resurrection.yml index 6554c280d5..3fb0bbb5e1 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Death/T1_resurrection.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Death/T1_resurrection.yml @@ -10,6 +10,8 @@ speedMultiplier: 0.2 - type: CP14MagicEffectManaCost manaCost: 100 + - type: CP14MagicEffectAliveTargetRequired + inverted: true - type: CP14MagicEffect telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T0_demiplane_infiltration.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T0_demiplane_infiltration.yml index 73996a8291..ea3622a3a5 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T0_demiplane_infiltration.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T0_demiplane_infiltration.yml @@ -60,4 +60,4 @@ components: - type: CP14SpellStorage spells: - - CP14ActionSpellDemiplaneInfiltration \ No newline at end of file + - CP14ActionSpellDemiplaneInfiltration diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T0_monolith_warp.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T0_monolith_warp.yml index b2244cd553..ef0bb3852e 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T0_monolith_warp.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T0_monolith_warp.yml @@ -73,4 +73,4 @@ components: - type: CP14SpellStorage spells: - - CP14ActionSpellMonolithWarp \ No newline at end of file + - CP14ActionSpellMonolithWarp diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T1_shadow_grab.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T1_shadow_grab.yml index 590f384e57..5cb3a4eeab 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T1_shadow_grab.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T1_shadow_grab.yml @@ -7,7 +7,6 @@ sprite: _CP14/Actions/Spells/dimension.rsi state: shadow_grab - type: CP14MagicEffectManaCost - manaCost: 10 - type: CP14MagicEffect telegraphyEffects: - !type:CP14SpellSpawnEntityOnTarget @@ -58,4 +57,4 @@ components: - type: CP14SpellStorage spells: - - CP14ActionSpellShadowGrab \ No newline at end of file + - CP14ActionSpellShadowGrab diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T1_shadow_swap.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T1_shadow_swap.yml new file mode 100644 index 0000000000..5a1868c3d7 --- /dev/null +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T1_shadow_swap.yml @@ -0,0 +1,43 @@ +- type: entity + id: CP14ActionSpellShadowSwap + name: Shadow swap + description: A warp of space between two living beings + components: + - type: Sprite + sprite: _CP14/Actions/Spells/dimension.rsi + state: shadow_swap + - type: CP14MagicEffectCastSlowdown + speedMultiplier: 0.8 + - type: CP14MagicEffectManaCost + manaCost: 20 + - type: CP14MagicEffect + telegraphyEffects: + - !type:CP14SpellSpawnEntityOnUser + spawns: + - CP14ImpactEffectShadowStep + - !type:CP14SpellSpawnEntityOnTarget + spawns: + - CP14ImpactEffectShadowStep + effects: + - !type:CP14SpellCasterSwap + - type: CP14MagicEffectCastingVisual + proto: CP14ImpactEffectShadowStep + - type: CP14MagicEffectSomaticAspect + - type: CP14MagicEffectAliveTargetRequired + - type: EntityTargetAction + whitelist: + components: + - MobState + range: 5 + itemIconStyle: BigAction + interactOnMiss: false + sound: !type:SoundPathSpecifier + path: /Audio/Magic/rumble.ogg + icon: + sprite: _CP14/Actions/Spells/dimension.rsi + state: shadow_swap + event: !type:CP14DelayedEntityTargetActionEvent + cooldown: 45 + hidden: true + breakOnMove: false + requireCanInteract: false diff --git a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T2_shadow_step.yml b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T2_shadow_step.yml index f91349c525..d41c6188e2 100644 --- a/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T2_shadow_step.yml +++ b/Resources/Prototypes/_CP14/Entities/Actions/Spells/Dimension/T2_shadow_step.yml @@ -51,4 +51,4 @@ components: - type: CP14SpellStorage spells: - - CP14ActionSpellShadowStep \ No newline at end of file + - CP14ActionSpellShadowStep diff --git a/Resources/Prototypes/_CP14/Entities/Clothing/Cloak/sort_later.yml b/Resources/Prototypes/_CP14/Entities/Clothing/Cloak/sort_later.yml index 2a6d2bc14d..df2a3647c2 100644 --- a/Resources/Prototypes/_CP14/Entities/Clothing/Cloak/sort_later.yml +++ b/Resources/Prototypes/_CP14/Entities/Clothing/Cloak/sort_later.yml @@ -9,4 +9,4 @@ - type: Sprite sprite: _CP14/Clothing/Cloak/Roles/General/maid_apron.rsi - type: Clothing - sprite: _CP14/Clothing/Cloak/Roles/General/maid_apron.rsi \ No newline at end of file + sprite: _CP14/Clothing/Cloak/Roles/General/maid_apron.rsi diff --git a/Resources/Prototypes/_CP14/Entities/Clothing/Shirt/Roles/general.yml b/Resources/Prototypes/_CP14/Entities/Clothing/Shirt/Roles/general.yml index 8eb15206b9..2d3d26763b 100644 --- a/Resources/Prototypes/_CP14/Entities/Clothing/Shirt/Roles/general.yml +++ b/Resources/Prototypes/_CP14/Entities/Clothing/Shirt/Roles/general.yml @@ -276,7 +276,7 @@ id: CP14ClothingWarriorsGarbDress name: warrior's garb description: show your strength. - components: + components: - type: Sprite sprite: _CP14/Clothing/Shirt/Roles/General/Dress/warrior_garb.rsi - type: Clothing @@ -286,8 +286,8 @@ parent: CP14ClothingShirtBase id: CP14ClothinShirtMaidDress name: maid's dress - components: + components: - type: Sprite sprite: _CP14/Clothing/Shirt/Roles/General/Dress/maid_dress.rsi - type: Clothing - sprite: _CP14/Clothing/Shirt/Roles/General/Dress/maid_dress.rsi \ No newline at end of file + sprite: _CP14/Clothing/Shirt/Roles/General/Dress/maid_dress.rsi diff --git a/Resources/Prototypes/_CP14/Entities/Objects/Specific/Thaumaturgy/essence.yml b/Resources/Prototypes/_CP14/Entities/Objects/Specific/Thaumaturgy/essence.yml index b6d0b72236..cb0bd37830 100644 --- a/Resources/Prototypes/_CP14/Entities/Objects/Specific/Thaumaturgy/essence.yml +++ b/Resources/Prototypes/_CP14/Entities/Objects/Specific/Thaumaturgy/essence.yml @@ -286,4 +286,4 @@ maxVol: 1 reagents: - ReagentId: CP14EssenceMagic - Quantity: 1 \ No newline at end of file + Quantity: 1 diff --git a/Resources/Prototypes/_CP14/Entities/Objects/Weapons/Magic/twoHandedStaffs.yml b/Resources/Prototypes/_CP14/Entities/Objects/Weapons/Magic/twoHandedStaffs.yml index 8cf22922e9..545d98ea09 100644 --- a/Resources/Prototypes/_CP14/Entities/Objects/Weapons/Magic/twoHandedStaffs.yml +++ b/Resources/Prototypes/_CP14/Entities/Objects/Weapons/Magic/twoHandedStaffs.yml @@ -23,7 +23,7 @@ - type: Wieldable - type: IncreaseDamageOnWield damage: - types: + types: Blunt: 3 - type: Damageable damageContainer: Inorganic @@ -80,15 +80,16 @@ categories: [ DoNotMap ] suffix: Artifact components: - #- type: CP14MagicManacostModify - # modifiers: - # Dimension: 1.4 + # - type: CP14MagicManacostModify + # modifiers: + # tempus: 1.4 - type: CP14SpellStorage spells: - CP14ActionSpellShadowStep - CP14ActionSpellShadowGrab + - CP14ActionSpellShadowSwap - CP14ActionSpellDemiplaneInfiltration - type: Sprite sprite: _CP14/Objects/Weapons/Magic/TwoHandedStaff/shadow_staff.rsi - type: Clothing - sprite: _CP14/Objects/Weapons/Magic/TwoHandedStaff/shadow_staff.rsi \ No newline at end of file + sprite: _CP14/Objects/Weapons/Magic/TwoHandedStaff/shadow_staff.rsi diff --git a/Resources/Prototypes/_CP14/Loadouts/skill_tree.yml b/Resources/Prototypes/_CP14/Loadouts/skill_tree.yml index 9bacabc0de..8bb547fa34 100644 --- a/Resources/Prototypes/_CP14/Loadouts/skill_tree.yml +++ b/Resources/Prototypes/_CP14/Loadouts/skill_tree.yml @@ -10,8 +10,7 @@ - CP14SkillTreeIllusion - CP14SkillTreeHealing - CP14SkillTreeAtlethic - - + - CP14SkillTreeDimension - type: entity id: CP14SkillTreePyrokineticLoadoutDummy @@ -28,8 +27,6 @@ skillTree: Pyrokinetic: 2 - - - type: entity id: CP14SkillTreeHydrosophistryLoadoutDummy name: Hydrosophistry @@ -45,7 +42,6 @@ skillTree: Hydrosophistry: 2 - - type: entity id: CP14SkillTreeIllusionLoadoutDummy name: Illusion @@ -61,7 +57,6 @@ skillTree: Illusion: 2 - - type: entity id: CP14SkillTreeMetamagicLoadoutDummy name: Metamagic @@ -77,7 +72,6 @@ skillTree: Metamagic: 2 - - type: entity id: CP14SkillTreeHealingLoadoutDummy name: Healing @@ -93,7 +87,6 @@ skillTree: Healing: 2 - - type: entity id: CP14SkillTreeAtlethicLoadoutDummy name: Atlethic @@ -107,4 +100,20 @@ id: CP14SkillTreeAtlethic dummyEntity: CP14SkillTreeAtlethicLoadoutDummy skillTree: - Atlethic: 2 \ No newline at end of file + Atlethic: 2 + +- type: entity + id: CP14SkillTreeDimensionLoadoutDummy + name: Dimension + categories: [ HideSpawnMenu ] + components: + - type: Sprite + sprite: _CP14/Actions/skill_tree.rsi + state: dimension + +- type: loadout + id: CP14SkillTreeDimension + dummyEntity: CP14SkillTreeDimensionLoadoutDummy + skillTree: + Dimension: 2 + diff --git a/Resources/Prototypes/_CP14/Reagents/magic_essence.yml b/Resources/Prototypes/_CP14/Reagents/magic_essence.yml index f7e70252f1..3b414b59e8 100644 --- a/Resources/Prototypes/_CP14/Reagents/magic_essence.yml +++ b/Resources/Prototypes/_CP14/Reagents/magic_essence.yml @@ -190,4 +190,4 @@ color: "#5497d6" tileReactions: - !type:CreateEntityTileReaction - entity: CP14EssenceMagic \ No newline at end of file + entity: CP14EssenceMagic diff --git a/Resources/Prototypes/_CP14/Skill/dimension.yml b/Resources/Prototypes/_CP14/Skill/dimension.yml new file mode 100644 index 0000000000..b32bafa99f --- /dev/null +++ b/Resources/Prototypes/_CP14/Skill/dimension.yml @@ -0,0 +1,31 @@ +- type: cp14Skill + id: CP14ActionSpellShadowGrab + skillUiPosition: 0, 0 + tree: Dimension + icon: + sprite: _CP14/Actions/Spells/dimension.rsi + state: shadow_grab + effect: !type:AddAction + action: CP14ActionSpellShadowGrab + +- type: cp14Skill + id: CP14ActionSpellShadowSwap + skillUiPosition: 0, 2 + tree: Dimension + icon: + sprite: _CP14/Actions/Spells/dimension.rsi + state: shadow_swap + effect: !type:AddAction + action: CP14ActionSpellShadowSwap + +- type: cp14Skill + id: CP14ActionSpellShadowStep + skillUiPosition: 0, 4 + learnCost: 2 + tree: Dimension + icon: + sprite: _CP14/Actions/Spells/dimension.rsi + state: shadow_step + effect: !type:AddAction + action: CP14ActionSpellShadowStep + diff --git a/Resources/Prototypes/_CP14/Skill/skill_tree.yml b/Resources/Prototypes/_CP14/Skill/skill_tree.yml index 893f68e876..52f276c83a 100644 --- a/Resources/Prototypes/_CP14/Skill/skill_tree.yml +++ b/Resources/Prototypes/_CP14/Skill/skill_tree.yml @@ -50,4 +50,13 @@ color: "#b32e37" icon: sprite: _CP14/Actions/skill_tree.rsi - state: atlethic \ No newline at end of file + state: atlethic + +- type: cp14SkillTree + id: Dimension + name: cp14-skill-tree-dimension-name + desc: cp14-skill-tree-dimension-desc + color: "#ac66be" + icon: + sprite: _CP14/Actions/skill_tree.rsi + state: dimension diff --git a/Resources/Textures/_CP14/Actions/Spells/dimension.rsi/meta.json b/Resources/Textures/_CP14/Actions/Spells/dimension.rsi/meta.json index d32017451d..3fb91a8651 100644 --- a/Resources/Textures/_CP14/Actions/Spells/dimension.rsi/meta.json +++ b/Resources/Textures/_CP14/Actions/Spells/dimension.rsi/meta.json @@ -5,7 +5,7 @@ "y": 32 }, "license": "All right reserved", - "copyright": "Created by TheShuEd. Shadow step and Shadow grab created by .kreks.", + "copyright": "Created by TheShuEd. Shadow step and Shadow grab created by .kreks. Shadow swap created by TornadoTech.", "states": [ { "name": "demi_arrow" @@ -21,6 +21,9 @@ }, { "name": "shadow_step" + }, + { + "name": "shadow_swap" } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/_CP14/Actions/Spells/dimension.rsi/shadow_swap.png b/Resources/Textures/_CP14/Actions/Spells/dimension.rsi/shadow_swap.png new file mode 100644 index 0000000000..aec1dd4740 Binary files /dev/null and b/Resources/Textures/_CP14/Actions/Spells/dimension.rsi/shadow_swap.png differ diff --git a/Resources/Textures/_CP14/Actions/skill_tree.rsi/dimension.png b/Resources/Textures/_CP14/Actions/skill_tree.rsi/dimension.png new file mode 100644 index 0000000000..d7ab6151af Binary files /dev/null and b/Resources/Textures/_CP14/Actions/skill_tree.rsi/dimension.png differ diff --git a/Resources/Textures/_CP14/Actions/skill_tree.rsi/meta.json b/Resources/Textures/_CP14/Actions/skill_tree.rsi/meta.json index 9279964239..34934b3a38 100644 --- a/Resources/Textures/_CP14/Actions/skill_tree.rsi/meta.json +++ b/Resources/Textures/_CP14/Actions/skill_tree.rsi/meta.json @@ -10,6 +10,9 @@ { "name": "atlethic" }, + { + "name": "dimension" + }, { "name": "heal" }, @@ -26,4 +29,4 @@ "name": "water" } ] -} \ No newline at end of file +}