From: Kara Date: Thu, 23 Mar 2023 18:57:15 +0000 (-0700) Subject: Godmode refactor (#14651) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=48cefca4e49b64023016a7ae1079358452e94b97;p=space-station-14.git Godmode refactor (#14651) --- diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs index 173a0b36f4..1f8a25fd85 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Tools.cs @@ -6,6 +6,7 @@ using Content.Server.Atmos; using Content.Server.Atmos.Components; using Content.Server.Cargo.Components; using Content.Server.Cargo.Systems; +using Content.Server.Damage.Components; using Content.Server.Doors.Components; using Content.Server.Doors.Systems; using Content.Server.Hands.Components; @@ -123,7 +124,7 @@ public sealed partial class AdminVerbSystem args.Verbs.Add(rejuvenate); } - if (!_godmodeSystem.HasGodmode(args.Target)) + if (!HasComp(args.Target)) { Verb makeIndestructible = new() { diff --git a/Content.Server/Damage/Components/GodmodeComponent.cs b/Content.Server/Damage/Components/GodmodeComponent.cs new file mode 100644 index 0000000000..65ebec2e3d --- /dev/null +++ b/Content.Server/Damage/Components/GodmodeComponent.cs @@ -0,0 +1,14 @@ +using Content.Server.Damage.Systems; +using Content.Shared.Damage; + +namespace Content.Server.Damage.Components; + +/// +/// +/// +[RegisterComponent, Access(typeof(GodmodeSystem))] +public sealed class GodmodeComponent : Component +{ + public bool WasMovedByPressure; + public DamageSpecifier? OldDamage = null; +} diff --git a/Content.Server/Damage/Systems/GodmodeSystem.cs b/Content.Server/Damage/Systems/GodmodeSystem.cs index 38b06cad0b..d7c6b800ae 100644 --- a/Content.Server/Damage/Systems/GodmodeSystem.cs +++ b/Content.Server/Damage/Systems/GodmodeSystem.cs @@ -1,6 +1,10 @@ using Content.Server.Atmos.Components; +using Content.Server.Damage.Components; using Content.Shared.Damage; -using Content.Shared.GameTicking; +using Content.Shared.Damage.Systems; +using Content.Shared.FixedPoint; +using Content.Shared.Rejuvenate; +using Content.Shared.StatusEffect; using JetBrains.Annotations; namespace Content.Server.Damage.Systems @@ -8,108 +12,85 @@ namespace Content.Server.Damage.Systems [UsedImplicitly] public sealed class GodmodeSystem : EntitySystem { - private readonly Dictionary _entities = new(); - [Dependency] private readonly DamageableSystem _damageableSystem = default!; + [Dependency] private readonly DamageableSystem _damageable = default!; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(Reset); + SubscribeLocalEvent(OnBeforeDamageChanged); + SubscribeLocalEvent(OnBeforeStatusEffect); + SubscribeLocalEvent(OnBeforeStaminaDamage); } - public void Reset(RoundRestartCleanupEvent ev) + private void OnBeforeDamageChanged(EntityUid uid, GodmodeComponent component, ref BeforeDamageChangedEvent args) { - _entities.Clear(); + args.Cancelled = true; } - public bool EnableGodmode(EntityUid entity) + private void OnBeforeStatusEffect(EntityUid uid, GodmodeComponent component, ref BeforeStatusEffectAddedEvent args) { - if (_entities.ContainsKey(entity)) - { - return false; - } + args.Cancelled = true; + } + + private void OnBeforeStaminaDamage(EntityUid uid, GodmodeComponent component, ref BeforeStaminaDamageEvent args) + { + args.Cancelled = true; + } - _entities[entity] = new OldEntityInformation(entity, EntityManager); + public void EnableGodmode(EntityUid uid) + { + var godmode = EnsureComp(uid); - if (EntityManager.TryGetComponent(entity, out MovedByPressureComponent? moved)) + if (TryComp(uid, out var moved)) { + godmode.WasMovedByPressure = moved.Enabled; moved.Enabled = false; } - if (EntityManager.TryGetComponent(entity, out DamageableComponent? damageable)) + if (TryComp(uid, out var damageable)) { - _damageableSystem.SetDamage(entity, damageable, new DamageSpecifier()); + godmode.OldDamage = new(damageable.Damage); } - return true; + // Rejuv to cover other stuff + RaiseLocalEvent(uid, new RejuvenateEvent()); } - public bool HasGodmode(EntityUid entity) + public void DisableGodmode(EntityUid uid) { - return _entities.ContainsKey(entity); - } + if (!TryComp(uid, out var godmode)) + return; - public bool DisableGodmode(EntityUid entity) - { - if (!_entities.Remove(entity, out var old)) + if (TryComp(uid, out var moved)) { - return false; + moved.Enabled = godmode.WasMovedByPressure; } - if (EntityManager.TryGetComponent(entity, out MovedByPressureComponent? moved)) - { - moved.Enabled = old.MovedByPressure; - } + if (!TryComp(uid, out var damageable)) + return; - if (EntityManager.TryGetComponent(entity, out DamageableComponent? damageable)) + if (godmode.OldDamage != null) { - if (old.Damage != null) - { - _damageableSystem.SetDamage(entity, damageable, old.Damage); - } + _damageable.SetDamage(uid, damageable, godmode.OldDamage); } - - return true; } /// /// Toggles godmode for a given entity. /// - /// The entity to toggle godmode for. + /// The entity to toggle godmode for. /// true if enabled, false if disabled. - public bool ToggleGodmode(EntityUid entity) + public bool ToggleGodmode(EntityUid uid) { - if (HasGodmode(entity)) + if (HasComp(uid)) { - DisableGodmode(entity); + DisableGodmode(uid); return false; } - else - { - EnableGodmode(entity); - return true; - } - } - public sealed class OldEntityInformation - { - public OldEntityInformation(EntityUid entity, IEntityManager entityManager) - { - Entity = entity; - MovedByPressure = entityManager.HasComponent(entity); - - if (entityManager.TryGetComponent(entity, out DamageableComponent? damageable)) - { - Damage = damageable.Damage; - } - } - - public EntityUid Entity { get; } - - public bool MovedByPressure { get; } - - public DamageSpecifier? Damage { get; } + EnableGodmode(uid); + return true; } } } diff --git a/Content.Shared/Damage/Systems/DamageableSystem.cs b/Content.Shared/Damage/Systems/DamageableSystem.cs index 9e7f9cb09f..e7eda3bb1b 100644 --- a/Content.Shared/Damage/Systems/DamageableSystem.cs +++ b/Content.Shared/Damage/Systems/DamageableSystem.cs @@ -159,6 +159,12 @@ namespace Content.Shared.Damage return damage; } + var before = new BeforeDamageChangedEvent(damage); + RaiseLocalEvent(uid.Value, ref before); + + if (before.Cancelled) + return null; + // Apply resistances if (!ignoreResistances) { @@ -283,6 +289,12 @@ namespace Content.Shared.Damage } } + /// + /// Raised before damage is done, so stuff can cancel it if necessary. + /// + [ByRefEvent] + public record struct BeforeDamageChangedEvent(DamageSpecifier Delta, bool Cancelled=false); + /// /// Raised on an entity when damage is about to be dealt, /// in case anything else needs to modify it other than the base diff --git a/Content.Shared/Damage/Systems/StaminaSystem.cs b/Content.Shared/Damage/Systems/StaminaSystem.cs index 561f945458..332bc65e60 100644 --- a/Content.Shared/Damage/Systems/StaminaSystem.cs +++ b/Content.Shared/Damage/Systems/StaminaSystem.cs @@ -7,6 +7,7 @@ using Content.Shared.Damage.Events; using Content.Shared.Database; using Content.Shared.IdentityManagement; using Content.Shared.Popups; +using Content.Shared.Rejuvenate; using Content.Shared.Rounding; using Content.Shared.Stunnable; using Content.Shared.Weapons.Melee.Events; @@ -45,6 +46,7 @@ public sealed class StaminaSystem : EntitySystem SubscribeLocalEvent(OnStamGetState); SubscribeLocalEvent(OnStamHandleState); SubscribeLocalEvent(OnDisarmed); + SubscribeLocalEvent(OnRejuvenate); SubscribeLocalEvent(OnCollide); SubscribeLocalEvent(OnHit); } @@ -111,6 +113,18 @@ public sealed class StaminaSystem : EntitySystem return MathF.Max(0f, component.StaminaDamage - MathF.Max(0f, (float) (curTime - (component.NextUpdate + pauseTime)).TotalSeconds * component.Decay)); } + private void OnRejuvenate(EntityUid uid, StaminaComponent component, RejuvenateEvent args) + { + if (component.StaminaDamage >= component.CritThreshold) + { + ExitStamCrit(uid, component); + } + + component.StaminaDamage = 0; + RemComp(uid); + Dirty(component); + } + private void OnDisarmed(EntityUid uid, StaminaComponent component, DisarmedEvent args) { if (args.Handled || !_random.Prob(args.PushProbability)) @@ -209,7 +223,16 @@ public sealed class StaminaSystem : EntitySystem public void TakeStaminaDamage(EntityUid uid, float value, StaminaComponent? component = null, EntityUid? source = null, EntityUid? with = null) { - if (!Resolve(uid, ref component, false) || component.Critical) + if (!Resolve(uid, ref component, false)) + return; + + var ev = new BeforeStaminaDamageEvent(value); + RaiseLocalEvent(uid, ref ev); + if (ev.Cancelled) + return; + + // Have we already reached the point of max stamina damage? + if (component.Critical) return; var oldDamage = component.StaminaDamage; @@ -356,4 +379,11 @@ public sealed class StaminaSystem : EntitySystem public float CritThreshold; public TimeSpan LastUpdate; } + } + +/// +/// Raised before stamina damage is dealt to allow other systems to cancel it. +/// +[ByRefEvent] +public record struct BeforeStaminaDamageEvent(float Value, bool Cancelled=false); diff --git a/Content.Shared/StatusEffect/StatusEffectsSystem.cs b/Content.Shared/StatusEffect/StatusEffectsSystem.cs index 0cab536e19..23d18eb903 100644 --- a/Content.Shared/StatusEffect/StatusEffectsSystem.cs +++ b/Content.Shared/StatusEffect/StatusEffectsSystem.cs @@ -346,6 +346,12 @@ namespace Content.Shared.StatusEffect // don't log since stuff calling this prolly doesn't care if we don't actually have it if (!Resolve(uid, ref status, false)) return false; + + var ev = new BeforeStatusEffectAddedEvent(key); + RaiseLocalEvent(uid, ref ev); + if (ev.Cancelled) + return false; + if (!_prototypeManager.TryIndex(key, out var proto)) return false; if (!status.AllowedEffects.Contains(key) && !proto.AlwaysAllowed) @@ -465,6 +471,12 @@ namespace Content.Shared.StatusEffect } } + /// + /// Raised on an entity before a status effect is added to determine if adding it should be cancelled. + /// + [ByRefEvent] + public record struct BeforeStatusEffectAddedEvent(string Key, bool Cancelled=false); + public readonly struct StatusEffectAddedEvent { public readonly EntityUid Uid;