using Content.Shared._CP14.MagicSpell.Components; using Content.Shared._CP14.MagicSpell.Events; using Content.Shared.CombatMode.Pacification; using Content.Shared.Damage.Components; using Content.Shared.Hands.Components; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Speech.Muting; namespace Content.Shared._CP14.MagicSpell; public abstract partial class CP14SharedMagicSystem { [Dependency] private readonly MobStateSystem _mobState = default!; private void InitializeChecks() { SubscribeLocalEvent(OnSomaticCheck); SubscribeLocalEvent(OnVerbalCheck); SubscribeLocalEvent(OnManaCheck); SubscribeLocalEvent(OnStaminaCheck); SubscribeLocalEvent(OnPacifiedCheck); SubscribeLocalEvent(OnMobStateCheck); //Verbal speaking SubscribeLocalEvent(OnVerbalAspectStartCast); SubscribeLocalEvent(OnVerbalAspectAfterCast); SubscribeLocalEvent(OnEmoteStartCast); SubscribeLocalEvent(OnEmoteEndCast); } /// /// 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) { //Total man required var requiredMana = CalculateManacost(ent, args.Performer); //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)) requiredMana = MathF.Max(0, (float)(requiredMana - magicContainer.Energy)); } if (requiredMana <= 0) return; //Second - trying get mana from performer if (!_magicContainerQuery.TryComp(args.Performer, out var playerMana)) { args.PushReason(Loc.GetString("cp14-magic-spell-no-mana-component")); args.Cancel(); return; } 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) return; args.PushReason(Loc.GetString("cp14-magic-spell-stamina-not-enough")); args.Cancel(); } 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)) 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-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 OnVerbalAspectStartCast(Entity ent, ref CP14StartCastMagicEffectEvent args) { var ev = new CP14SpellSpeechEvent { Performer = args.Performer, Speech = Loc.GetString(ent.Comp.StartSpeech), Emote = false, }; RaiseLocalEvent(ent, ref ev); } private void OnVerbalAspectAfterCast(Entity ent, ref CP14MagicEffectConsumeResourceEvent args) { if (_net.IsClient) return; var ev = new CP14SpellSpeechEvent { Performer = args.Performer, Speech = Loc.GetString(ent.Comp.EndSpeech), Emote = false }; RaiseLocalEvent(ent, ref ev); } private void OnEmoteStartCast(Entity ent, ref CP14StartCastMagicEffectEvent args) { var ev = new CP14SpellSpeechEvent { Performer = args.Performer, Speech = Loc.GetString(ent.Comp.StartEmote), Emote = true, }; RaiseLocalEvent(ent, ref ev); } private void OnEmoteEndCast(Entity ent, ref CP14MagicEffectConsumeResourceEvent args) { if (_net.IsClient) return; var ev = new CP14SpellSpeechEvent { Performer = args.Performer, Speech = Loc.GetString(ent.Comp.EndEmote), Emote = true }; RaiseLocalEvent(ent, ref ev); } }