diff --git a/Content.Client/Damage/DamageVisualsSystem.cs b/Content.Client/Damage/DamageVisualsSystem.cs index 9e24a90e2a..6dbe8edc1c 100644 --- a/Content.Client/Damage/DamageVisualsSystem.cs +++ b/Content.Client/Damage/DamageVisualsSystem.cs @@ -54,7 +54,7 @@ public sealed class DamageVisualsSystem : VisualizerSystem { @@ -10,7 +10,7 @@ public sealed class DamageStateVisualizerSystem : VisualizerSystem false, - DamageState.Dead => false, + MobState.Critical => false, + MobState.Dead => false, _ => true }; } @@ -48,7 +48,7 @@ public sealed class DamageStateVisualizerSystem : VisualizerSystem (int) DrawDepth.FloorObjects) { diff --git a/Content.Client/MobState/DamageStateVisualsComponent.cs b/Content.Client/DamageState/DamageStateVisualsComponent.cs similarity index 64% rename from Content.Client/MobState/DamageStateVisualsComponent.cs rename to Content.Client/DamageState/DamageStateVisualsComponent.cs index 80ffdbb2c5..4152539bb5 100644 --- a/Content.Client/MobState/DamageStateVisualsComponent.cs +++ b/Content.Client/DamageState/DamageStateVisualsComponent.cs @@ -1,13 +1,13 @@ -using Content.Shared.MobState; +using Content.Shared.Mobs; -namespace Content.Client.MobState; +namespace Content.Client.DamageState; [RegisterComponent] public sealed class DamageStateVisualsComponent : Component { public int? OriginalDrawDepth; - [DataField("states")] public Dictionary> States = new(); + [DataField("states")] public Dictionary> States = new(); /// /// Should noRot be turned off when crit / dead. diff --git a/Content.Client/HealthOverlay/HealthOverlaySystem.cs b/Content.Client/HealthOverlay/HealthOverlaySystem.cs index f1339d3e9e..9e1b39aed2 100644 --- a/Content.Client/HealthOverlay/HealthOverlaySystem.cs +++ b/Content.Client/HealthOverlay/HealthOverlaySystem.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using Content.Client.HealthOverlay.UI; using Content.Shared.Damage; using Content.Shared.GameTicking; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using JetBrains.Annotations; using Robust.Client.GameObjects; using Robust.Client.Graphics; diff --git a/Content.Client/HealthOverlay/UI/HealthOverlayGui.cs b/Content.Client/HealthOverlay/UI/HealthOverlayGui.cs index 73d73d11e0..9598a97cf2 100644 --- a/Content.Client/HealthOverlay/UI/HealthOverlayGui.cs +++ b/Content.Client/HealthOverlay/UI/HealthOverlayGui.cs @@ -1,9 +1,10 @@ using Content.Client.IoC; -using Content.Client.MobState; using Content.Client.Resources; using Content.Shared.Damage; using Content.Shared.FixedPoint; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Client.Graphics; using Robust.Client.UserInterface.Controls; using Robust.Shared.Timing; @@ -84,11 +85,10 @@ namespace Content.Client.HealthOverlay.UI } var mobStateSystem = _entities.EntitySysManager.GetEntitySystem(); - FixedPoint2 threshold; - + var mobThresholdSystem = _entities.EntitySysManager.GetEntitySystem(); if (mobStateSystem.IsAlive(mobState.Owner, mobState)) { - if (!mobStateSystem.TryGetEarliestCriticalState(mobState, damageable.TotalDamage, out _, out threshold)) + if (!mobThresholdSystem.TryGetThresholdForState(Entity,MobState.Critical, out var threshold)) { CritBar.Visible = false; HealthBar.Visible = false; @@ -97,7 +97,7 @@ namespace Content.Client.HealthOverlay.UI CritBar.Ratio = 1; CritBar.Visible = true; - HealthBar.Ratio = 1 - (damageable.TotalDamage / threshold).Float(); + HealthBar.Ratio = 1 - ((FixedPoint2)(damageable.TotalDamage / threshold)).Float(); HealthBar.Visible = true; } else if (mobStateSystem.IsCritical(mobState.Owner, mobState)) @@ -105,8 +105,8 @@ namespace Content.Client.HealthOverlay.UI HealthBar.Ratio = 0; HealthBar.Visible = false; - if (!mobStateSystem.TryGetPreviousCriticalState(mobState, damageable.TotalDamage, out _, out var critThreshold) || - !mobStateSystem.TryGetEarliestDeadState(mobState, damageable.TotalDamage, out _, out var deadThreshold)) + if (!mobThresholdSystem.TryGetThresholdForState(Entity, MobState.Critical, out var critThreshold) || + !mobThresholdSystem.TryGetThresholdForState(Entity, MobState.Dead, out var deadThreshold)) { CritBar.Visible = false; return; @@ -115,7 +115,7 @@ namespace Content.Client.HealthOverlay.UI CritBar.Visible = true; CritBar.Ratio = 1 - ((damageable.TotalDamage - critThreshold) / - (deadThreshold - critThreshold)).Float(); + (deadThreshold - critThreshold)).Value.Float(); } else if (mobStateSystem.IsDead(mobState.Owner, mobState)) { diff --git a/Content.Client/MobState/MobStateSystem.cs b/Content.Client/MobState/MobStateSystem.cs deleted file mode 100644 index 64edff1ace..0000000000 --- a/Content.Client/MobState/MobStateSystem.cs +++ /dev/null @@ -1,146 +0,0 @@ -using Content.Shared.Damage; -using Content.Shared.FixedPoint; -using Content.Shared.Interaction.Events; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; -using Content.Shared.MobState.EntitySystems; -using Robust.Client.GameObjects; -using Robust.Client.Graphics; -using Robust.Client.Player; -using Robust.Shared.GameStates; - -namespace Content.Client.MobState; - -public sealed partial class MobStateSystem : SharedMobStateSystem -{ - [Dependency] private readonly IOverlayManager _overlayManager = default!; - [Dependency] private readonly IPlayerManager _playerManager = default!; - private Overlays.DamageOverlay _overlay = default!; - - public override void Initialize() - { - base.Initialize(); - - _overlay = new Overlays.DamageOverlay(); - _overlayManager.AddOverlay(_overlay); - - SubscribeLocalEvent(OnPlayerAttach); - SubscribeLocalEvent(OnPlayerDetach); - SubscribeLocalEvent(OnMobHandleState); - SubscribeLocalEvent(OnAttack); - } - - private void OnAttack(EntityUid uid, MobStateComponent component, AttackAttemptEvent args) - { - if (IsIncapacitated(uid, component)) - args.Cancel(); - } - - public override void Shutdown() - { - base.Shutdown(); - _overlayManager.RemoveOverlay(_overlay); - } - - private void OnMobHandleState(EntityUid uid, MobStateComponent component, ref ComponentHandleState args) - { - if (args.Current is not MobStateComponentState state) return; - - if (component.CurrentThreshold == state.CurrentThreshold) - return; - - if (state.CurrentThreshold == null) - { - RemoveState(component); - } - else - { - UpdateState(component, state.CurrentThreshold.Value); - } - } - - private void OnPlayerAttach(PlayerAttachedEvent ev) - { - if (TryComp(ev.Entity, out var mobState) && TryComp(ev.Entity, out var damageable)) - { - _overlay.DeadLevel = 0f; - SetLevel(mobState, damageable.TotalDamage); - } - else - { - ClearOverlay(); - } - } - - private void OnPlayerDetach(PlayerDetachedEvent ev) - { - ClearOverlay(); - } - - private void ClearOverlay() - { - _overlay.State = DamageState.Alive; - _overlay.BruteLevel = 0f; - _overlay.OxygenLevel = 0f; - _overlay.CritLevel = 0f; - } - - protected override void UpdateState(MobStateComponent component, DamageState? state, FixedPoint2 threshold) - { - base.UpdateState(component, state, threshold); - SetLevel(component, threshold); - } - - private void SetLevel(MobStateComponent stateComponent, FixedPoint2 threshold) - { - var uid = stateComponent.Owner; - - if (_playerManager.LocalPlayer?.ControlledEntity != uid) return; - - ClearOverlay(); - - if (!TryComp(uid, out var damageable)) - return; - - switch (stateComponent.CurrentState) - { - case DamageState.Dead: - _overlay.State = DamageState.Dead; - return; - } - - var bruteLevel = 0f; - var oxyLevel = 0f; - var critLevel = 0f; - - if (TryGetEarliestIncapacitatedState(stateComponent, threshold, out _, out var earliestThreshold) && damageable.TotalDamage != 0) - { - if (damageable.DamagePerGroup.TryGetValue("Brute", out var bruteDamage)) - { - bruteLevel = MathF.Min(1f, (bruteDamage / earliestThreshold).Float()); - } - - if (damageable.Damage.DamageDict.TryGetValue("Asphyxiation", out var oxyDamage)) - { - oxyLevel = MathF.Min(1f, (oxyDamage / earliestThreshold).Float()); - } - - if (threshold >= earliestThreshold && TryGetEarliestDeadState(stateComponent, threshold, out _, out var earliestDeadHold)) - { - critLevel = (float) Math.Clamp((damageable.TotalDamage - earliestThreshold).Double() / (earliestDeadHold - earliestThreshold).Double(), 0.1, 1); - } - } - - // Don't show damage overlay if they're near enough to max. - - if (bruteLevel < 0.05f) - { - bruteLevel = 0f; - } - - _overlay.State = critLevel > 0f ? DamageState.Critical : DamageState.Alive; - _overlay.BruteLevel = bruteLevel; - _overlay.OxygenLevel = oxyLevel; - _overlay.CritLevel = critLevel; - } -} diff --git a/Content.Client/Pointing/PointingSystem.cs b/Content.Client/Pointing/PointingSystem.cs index 53082c3d27..729f5f2ca4 100644 --- a/Content.Client/Pointing/PointingSystem.cs +++ b/Content.Client/Pointing/PointingSystem.cs @@ -1,5 +1,5 @@ using Content.Client.Pointing.Components; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Systems; using Content.Shared.Pointing; using Content.Shared.Verbs; using Robust.Client.Animations; @@ -12,7 +12,7 @@ namespace Content.Client.Pointing; public sealed class PointingSystem : SharedPointingSystem { [Dependency] private readonly AnimationPlayerSystem _player = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; private const string AnimationKey = "pointingarrow"; diff --git a/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs b/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs new file mode 100644 index 0000000000..989d523021 --- /dev/null +++ b/Content.Client/UserInterface/Systems/DamageOverlays/DamageOverlayUiController.cs @@ -0,0 +1,142 @@ +using Content.Client.Alerts; +using Content.Client.Gameplay; +using Content.Shared.Damage; +using Content.Shared.FixedPoint; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; +using JetBrains.Annotations; +using Robust.Client.GameObjects; +using Robust.Client.Graphics; +using Robust.Client.Player; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controllers; + +namespace Content.Client.UserInterface.Systems.DamageOverlays; + +[UsedImplicitly] +public sealed class DamageOverlayUiController : UIController, IOnStateChanged +{ + [Dependency] private readonly IOverlayManager _overlayManager = default!; + [Dependency] private readonly IPlayerManager _playerManager = default!; + + [UISystemDependency] private readonly ClientAlertsSystem _alertsSystem = default!; + [UISystemDependency] private readonly MobThresholdSystem _mobThresholdSystem = default!; + private Overlays.DamageOverlay _overlay = default!; + + public override void Initialize() + { + _overlay = new Overlays.DamageOverlay(); + SubscribeLocalEvent(OnPlayerAttach); + SubscribeLocalEvent(OnPlayerDetached); + SubscribeLocalEvent(OnMobStateChanged); + SubscribeLocalEvent(OnThresholdCheck); + } + + public void OnStateEntered(GameplayState state) + { + _overlayManager.AddOverlay(_overlay); + } + + public void OnStateExited(GameplayState state) + { + _overlayManager.RemoveOverlay(_overlay); + } + + private void OnPlayerAttach(PlayerAttachedEvent args) + { + ClearOverlay(); + if (!EntityManager.TryGetComponent(args.Entity, out var mobState)) + return; + if (mobState.CurrentState != MobState.Dead) + UpdateOverlays(args.Entity, mobState); + _overlayManager.AddOverlay(_overlay); + } + + private void OnPlayerDetached(PlayerDetachedEvent args) + { + _overlayManager.RemoveOverlay(_overlay); + ClearOverlay(); + } + + private void OnMobStateChanged(MobStateChangedEvent args) + { + if (args.Target != _playerManager.LocalPlayer?.ControlledEntity) + return; + + UpdateOverlays(args.Target, args.Component); + } + + private void OnThresholdCheck(ref MobThresholdChecked args) + { + + if (args.Target != _playerManager.LocalPlayer?.ControlledEntity) + return; + UpdateOverlays(args.Target, args.MobState, args.Damageable, args.Threshold); + } + + private void ClearOverlay() + { + _overlay.DeadLevel = 0f; + _overlay.CritLevel = 0f; + _overlay.BruteLevel = 0f; + _overlay.OxygenLevel = 0f; + } + + //TODO: Jezi: adjust oxygen and hp overlays to use appropriate systems once bodysim is implemented + private void UpdateOverlays(EntityUid entity, MobStateComponent? mobState, DamageableComponent? damageable = null, MobThresholdsComponent? thresholds = null) + { + if (mobState == null && !EntityManager.TryGetComponent(entity, out mobState) || + thresholds == null && !EntityManager.TryGetComponent(entity, out thresholds) || + damageable == null && !EntityManager.TryGetComponent(entity, out damageable)) + return; + + + if (!_mobThresholdSystem.TryGetIncapThreshold(entity, out var foundThreshold, thresholds)) + return; //this entity cannot die or crit!! + var critThreshold = foundThreshold.Value; + _overlay.State = mobState.CurrentState; + + switch (mobState.CurrentState) + { + case MobState.Alive: + { + if (damageable.DamagePerGroup.TryGetValue("Brute", out var bruteDamage)) + { + _overlay.BruteLevel = FixedPoint2.Min(1f, bruteDamage / critThreshold).Float(); + } + + if (damageable.DamagePerGroup.TryGetValue("Airloss", out var oxyDamage)) + { + _overlay.OxygenLevel = FixedPoint2.Min(1f, oxyDamage / critThreshold).Float(); + } + + if (_overlay.BruteLevel < 0.05f) // Don't show damage overlay if they're near enough to max. + { + _overlay.BruteLevel = 0; + } + + _overlay.CritLevel = 0; + _overlay.DeadLevel = 0; + break; + } + case MobState.Critical: + { + if (!_mobThresholdSystem.TryGetDeadPercentage(entity, + FixedPoint2.Max(0.0, damageable.TotalDamage), out var critLevel)) + return; + _overlay.CritLevel = critLevel.Value.Float(); + + _overlay.BruteLevel = 0; + _overlay.DeadLevel = 0; + break; + } + case MobState.Dead: + { + _overlay.BruteLevel = 0; + _overlay.CritLevel = 0; + break; + } + } + } +} diff --git a/Content.Client/MobState/Overlays/DamageOverlay.cs b/Content.Client/UserInterface/Systems/DamageOverlays/Overlays/DamageOverlay.cs similarity index 96% rename from Content.Client/MobState/Overlays/DamageOverlay.cs rename to Content.Client/UserInterface/Systems/DamageOverlays/Overlays/DamageOverlay.cs index 94e67dfb12..30608a986e 100644 --- a/Content.Client/MobState/Overlays/DamageOverlay.cs +++ b/Content.Client/UserInterface/Systems/DamageOverlays/Overlays/DamageOverlay.cs @@ -1,4 +1,4 @@ -using Content.Shared.MobState; +using Content.Shared.Mobs; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.Player; @@ -6,7 +6,7 @@ using Robust.Shared.Enums; using Robust.Shared.Prototypes; using Robust.Shared.Timing; -namespace Content.Client.MobState.Overlays; +namespace Content.Client.UserInterface.Systems.DamageOverlays.Overlays; public sealed class DamageOverlay : Overlay { @@ -21,7 +21,7 @@ public sealed class DamageOverlay : Overlay private readonly ShaderInstance _oxygenShader; private readonly ShaderInstance _bruteShader; - public DamageState State = DamageState.Alive; + public MobState State = MobState.Alive; /// /// Handles the red pulsing overlay @@ -79,7 +79,7 @@ public sealed class DamageOverlay : Overlay var lastFrameTime = (float) _timing.FrameTime.TotalSeconds; // If they just died then lerp out the white overlay. - if (State != DamageState.Dead) + if (State != MobState.Dead) { DeadLevel = 1f; } @@ -169,7 +169,7 @@ public sealed class DamageOverlay : Overlay _oldBruteLevel = BruteLevel; } - level = State != DamageState.Critical ? _oldOxygenLevel : 1f; + level = State != MobState.Critical ? _oldOxygenLevel : 1f; if (level > 0f) { @@ -215,7 +215,7 @@ public sealed class DamageOverlay : Overlay handle.DrawRect(viewport, Color.White); } - level = State != DamageState.Dead ? _oldCritLevel : DeadLevel; + level = State != MobState.Dead ? _oldCritLevel : DeadLevel; if (level > 0f) { diff --git a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs index dad14c3ac5..7b9f06c201 100644 --- a/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs +++ b/Content.Client/Weapons/Melee/MeleeWeaponSystem.cs @@ -1,7 +1,7 @@ using Content.Client.CombatMode; using Content.Client.Gameplay; using Content.Client.Hands; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Content.Shared.Weapons.Melee; using Content.Shared.Weapons.Melee.Events; using Content.Shared.StatusEffect; diff --git a/Content.IntegrationTests/Tests/Body/LungTest.cs b/Content.IntegrationTests/Tests/Body/LungTest.cs index 8742d105b3..18e2d7f5f8 100644 --- a/Content.IntegrationTests/Tests/Body/LungTest.cs +++ b/Content.IntegrationTests/Tests/Body/LungTest.cs @@ -25,8 +25,9 @@ namespace Content.IntegrationTests.Tests.Body - type: Body prototype: Human - type: MobState - thresholds: - 0: Alive + allowedStates: + - Alive + - type: Damageable - type: ThermalRegulator metabolismHeat: 5000 radiatedHeat: 400 diff --git a/Content.IntegrationTests/Tests/Commands/RejuvenateTest.cs b/Content.IntegrationTests/Tests/Commands/RejuvenateTest.cs index df47a8770f..1c72004920 100644 --- a/Content.IntegrationTests/Tests/Commands/RejuvenateTest.cs +++ b/Content.IntegrationTests/Tests/Commands/RejuvenateTest.cs @@ -3,7 +3,8 @@ using Content.Server.Administration.Commands; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using NUnit.Framework; using Robust.Shared.GameObjects; using Robust.Shared.Map; @@ -23,6 +24,7 @@ namespace Content.IntegrationTests.Tests.Commands - type: Damageable damageContainer: Biological - type: MobState + - type: MobThresholds thresholds: 0: Alive 100: Critical @@ -37,7 +39,7 @@ namespace Content.IntegrationTests.Tests.Commands var entManager = server.ResolveDependency(); var mapManager = server.ResolveDependency(); var prototypeManager = server.ResolveDependency(); - var mobStateSystem = entManager.EntitySysManager.GetEntitySystem(); + var mobStateSystem = entManager.EntitySysManager.GetEntitySystem(); var damSystem = entManager.EntitySysManager.GetEntitySystem(); await server.WaitAssertion(() => diff --git a/Content.IntegrationTests/Tests/Destructible/DestructibleThresholdActivationTest.cs b/Content.IntegrationTests/Tests/Destructible/DestructibleThresholdActivationTest.cs index 082292ff2a..a72d6e7e72 100644 --- a/Content.IntegrationTests/Tests/Destructible/DestructibleThresholdActivationTest.cs +++ b/Content.IntegrationTests/Tests/Destructible/DestructibleThresholdActivationTest.cs @@ -133,7 +133,7 @@ namespace Content.IntegrationTests.Tests.Destructible // Heal the entity for 40 damage, down to 60 sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage*-4, true); - // Thresholds don't work backwards + // ThresholdsLookup don't work backwards Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty); // Damage for 10, up to 70 @@ -145,7 +145,7 @@ namespace Content.IntegrationTests.Tests.Destructible // Heal by 30, down to 40 sDamageableSystem.TryChangeDamage(sDestructibleEntity, bluntDamage*-3, true); - // Thresholds don't work backwards + // ThresholdsLookup don't work backwards Assert.That(sTestThresholdListenerSystem.ThresholdsReached, Is.Empty); // Damage up to 50 again diff --git a/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs b/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs index f827e88271..e6f7d0effc 100644 --- a/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs +++ b/Content.IntegrationTests/Tests/Disposal/DisposalUnitTest.cs @@ -79,6 +79,11 @@ namespace Content.IntegrationTests.Tests.Disposal - type: Body prototype: Human - type: MobState + - type: MobThresholds + thresholds: + 0: Alive + 100: Critical + 200: Dead - type: Damageable damageContainer: Biological - type: Physics diff --git a/Content.Server/Abilities/Mime/MimePowersSystem.cs b/Content.Server/Abilities/Mime/MimePowersSystem.cs index b219826711..6bec9c908a 100644 --- a/Content.Server/Abilities/Mime/MimePowersSystem.cs +++ b/Content.Server/Abilities/Mime/MimePowersSystem.cs @@ -6,7 +6,7 @@ using Content.Shared.Alert; using Content.Shared.Physics; using Content.Shared.Doors.Components; using Content.Shared.Maps; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Robust.Shared.Player; using Robust.Shared.Physics; using Robust.Shared.Physics.Components; diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs index c5456b9e45..36971628d1 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Smites.cs @@ -1,4 +1,3 @@ -using System.Linq; using System.Threading; using Content.Server.Administration.Commands; using Content.Server.Administration.Components; @@ -6,7 +5,6 @@ using Content.Server.Atmos.Components; using Content.Server.Atmos.EntitySystems; using Content.Server.Body.Components; using Content.Server.Body.Systems; -using Content.Server.Clothing.Components; using Content.Server.Damage.Systems; using Content.Server.Disease; using Content.Server.Disease.Components; @@ -35,8 +33,9 @@ using Content.Shared.Disease; using Content.Shared.Electrocution; using Content.Shared.Interaction.Components; using Content.Shared.Inventory; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Movement.Components; using Content.Shared.Movement.Systems; using Content.Shared.Nutrition.Components; @@ -50,7 +49,6 @@ using Robust.Shared.Physics; using Robust.Shared.Physics.Components; using Robust.Shared.Player; using Robust.Shared.Random; -using Robust.Shared.Utility; using Timer = Robust.Shared.Timing.Timer; namespace Content.Server.Administration.Systems; @@ -70,6 +68,8 @@ public sealed partial class AdminVerbSystem [Dependency] private readonly GodmodeSystem _godmodeSystem = default!; [Dependency] private readonly InventorySystem _inventorySystem = default!; [Dependency] private readonly PolymorphableSystem _polymorphableSystem = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; [Dependency] private readonly TabletopSystem _tabletopSystem = default!; [Dependency] private readonly VomitSystem _vomitSystem = default!; @@ -218,19 +218,16 @@ public sealed partial class AdminVerbSystem Act = () => { int damageToDeal; - var critState = mobState._highestToLowestStates.Where(x => x.Value == DamageState.Critical).FirstOrNull(); - if (critState is null) - { + if (!_mobThresholdSystem.TryGetThresholdForState(args.Target, MobState.Critical, out var criticalThreshold)) { // We can't crit them so try killing them. - var deadState = mobState._highestToLowestStates.Where(x => x.Value == DamageState.Dead).FirstOrNull(); - if (deadState is null) - return; // whelp. - - damageToDeal = deadState.Value.Key - (int) damageable.TotalDamage; + if (!_mobThresholdSystem.TryGetThresholdForState(args.Target, MobState.Dead, + out var deadThreshold)) + return;// whelp. + damageToDeal = deadThreshold.Value.Int() - (int) damageable.TotalDamage; } else { - damageToDeal = critState.Value.Key - (int) damageable.TotalDamage; + damageToDeal = criticalThreshold.Value.Int() - (int) damageable.TotalDamage; } if (damageToDeal <= 0) diff --git a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.HighPressureDelta.cs b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.HighPressureDelta.cs index b18b30bbaf..6396d4b25b 100644 --- a/Content.Server/Atmos/EntitySystems/AtmosphereSystem.HighPressureDelta.cs +++ b/Content.Server/Atmos/EntitySystems/AtmosphereSystem.HighPressureDelta.cs @@ -1,7 +1,7 @@ using Content.Server.Atmos.Components; using Content.Shared.Atmos; using Content.Shared.Audio; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Content.Shared.Physics; using Robust.Shared.Audio; using Robust.Shared.Map; diff --git a/Content.Server/Atmos/Miasma/MiasmaSystem.cs b/Content.Server/Atmos/Miasma/MiasmaSystem.cs index 80a2ae29bd..d694e704fc 100644 --- a/Content.Server/Atmos/Miasma/MiasmaSystem.cs +++ b/Content.Server/Atmos/Miasma/MiasmaSystem.cs @@ -1,12 +1,12 @@ -using Content.Shared.MobState; using Content.Shared.Damage; using Content.Shared.Atmos; using Content.Server.Atmos.EntitySystems; using Content.Server.Temperature.Systems; using Content.Server.Body.Components; using Content.Shared.Examine; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Systems; using Content.Shared.Rejuvenate; -using Content.Shared.MobState.EntitySystems; using Robust.Server.GameObjects; using Robust.Shared.Containers; using Robust.Shared.Physics.Components; @@ -20,7 +20,7 @@ namespace Content.Server.Atmos.Miasma [Dependency] private readonly TransformSystem _transformSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly DamageableSystem _damageableSystem = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly MetaDataSystem _metaDataSystem = default!; [Dependency] private readonly IGameTiming _timing = default!; diff --git a/Content.Server/Bed/BedSystem.cs b/Content.Server/Bed/BedSystem.cs index f33cd7b147..dcf94dfded 100644 --- a/Content.Server/Bed/BedSystem.cs +++ b/Content.Server/Bed/BedSystem.cs @@ -2,7 +2,6 @@ using Content.Server.Actions; using Content.Server.Bed.Components; using Content.Server.Bed.Sleep; using Content.Server.Body.Systems; -using Content.Server.MobState; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; using Content.Shared.Actions.ActionTypes; @@ -13,6 +12,7 @@ using Content.Shared.Buckle.Components; using Content.Shared.Damage; using Content.Shared.Emag.Systems; using Content.Server.Construction; +using Content.Shared.Mobs.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Timing; diff --git a/Content.Server/Bed/Sleep/SleepingSystem.cs b/Content.Server/Bed/Sleep/SleepingSystem.cs index 2f44bee1f8..bb553e0544 100644 --- a/Content.Server/Bed/Sleep/SleepingSystem.cs +++ b/Content.Server/Bed/Sleep/SleepingSystem.cs @@ -8,8 +8,8 @@ using Content.Shared.Damage; using Content.Shared.Examine; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Content.Shared.Slippery; using Content.Shared.Stunnable; using Content.Shared.Verbs; @@ -112,14 +112,14 @@ namespace Content.Server.Bed.Sleep /// private void OnMobStateChanged(EntityUid uid, SleepingComponent component, MobStateChangedEvent args) { - if (args.CurrentMobState == DamageState.Dead) + if (args.NewMobState == MobState.Dead) { RemComp(uid); RemComp(uid); return; } if (TryComp(uid, out var spam)) - spam.Enabled = (args.CurrentMobState == DamageState.Alive) ? true : false; + spam.Enabled = (args.NewMobState == MobState.Alive) ? true : false; } private void AddWakeVerb(EntityUid uid, SleepingComponent component, GetVerbsEvent args) diff --git a/Content.Server/Bible/BibleSystem.cs b/Content.Server/Bible/BibleSystem.cs index 4d58761fec..62d092c6a1 100644 --- a/Content.Server/Bible/BibleSystem.cs +++ b/Content.Server/Bible/BibleSystem.cs @@ -1,21 +1,21 @@ -using Content.Shared.Interaction; -using Content.Shared.Inventory; -using Content.Shared.MobState; -using Content.Shared.Damage; -using Content.Shared.Verbs; -using Content.Shared.ActionBlocker; -using Content.Shared.Actions; using Content.Server.Bible.Components; -using Content.Server.MobState; -using Content.Server.Popups; using Content.Server.Ghost.Roles.Components; using Content.Server.Ghost.Roles.Events; +using Content.Server.Popups; +using Content.Shared.ActionBlocker; +using Content.Shared.Actions; +using Content.Shared.Damage; using Content.Shared.IdentityManagement; +using Content.Shared.Interaction; +using Content.Shared.Inventory; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Timing; -using Robust.Shared.Random; +using Content.Shared.Verbs; using Robust.Shared.Audio; using Robust.Shared.Player; +using Robust.Shared.Random; namespace Content.Server.Bible { @@ -192,7 +192,7 @@ namespace Content.Server.Bible /// private void OnFamiliarDeath(EntityUid uid, FamiliarComponent component, MobStateChangedEvent args) { - if (args.CurrentMobState != DamageState.Dead || component.Source == null) + if (args.NewMobState != MobState.Dead || component.Source == null) return; var source = component.Source; diff --git a/Content.Server/Body/Systems/BloodstreamSystem.cs b/Content.Server/Body/Systems/BloodstreamSystem.cs index 5dd004ffad..810e3642a0 100644 --- a/Content.Server/Body/Systems/BloodstreamSystem.cs +++ b/Content.Server/Body/Systems/BloodstreamSystem.cs @@ -3,7 +3,6 @@ using Content.Server.Chemistry.EntitySystems; using Content.Server.Chemistry.ReactionEffects; using Content.Server.Fluids.EntitySystems; using Content.Server.HealthExaminable; -using Content.Server.MobState; using Content.Server.Popups; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reaction; @@ -11,9 +10,10 @@ using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; using Content.Shared.IdentityManagement; -using Content.Shared.MobState.Components; using Content.Shared.Popups; using Content.Shared.Drunk; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Rejuvenate; using Robust.Shared.Audio; using Robust.Shared.Player; diff --git a/Content.Server/Body/Systems/BodySystem.cs b/Content.Server/Body/Systems/BodySystem.cs index f1a1e8cd6a..1aa4f78b5a 100644 --- a/Content.Server/Body/Systems/BodySystem.cs +++ b/Content.Server/Body/Systems/BodySystem.cs @@ -5,13 +5,13 @@ using Content.Server.GameTicking; using Content.Server.Humanoid; using Content.Server.Kitchen.Components; using Content.Server.Mind.Components; -using Content.Server.MobState; using Content.Shared.Body.Components; using Content.Shared.Body.Part; using Content.Shared.Body.Prototypes; using Content.Shared.Body.Systems; using Content.Shared.Coordinates; using Content.Shared.Humanoid; +using Content.Shared.Mobs.Systems; using Content.Shared.Movement.Events; using Content.Shared.Random.Helpers; using Robust.Shared.Audio; diff --git a/Content.Server/Body/Systems/MetabolizerSystem.cs b/Content.Server/Body/Systems/MetabolizerSystem.cs index 144f4987fb..1cf9eb3e93 100644 --- a/Content.Server/Body/Systems/MetabolizerSystem.cs +++ b/Content.Server/Body/Systems/MetabolizerSystem.cs @@ -2,14 +2,14 @@ using System.Linq; using Content.Server.Body.Components; using Content.Server.Chemistry.Components.SolutionManager; using Content.Server.Chemistry.EntitySystems; -using Content.Server.MobState; using Content.Shared.Administration.Logs; using Content.Shared.Body.Organ; using Content.Shared.Chemistry.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Database; using Content.Shared.FixedPoint; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using JetBrains.Annotations; using Robust.Shared.Prototypes; using Robust.Shared.Random; diff --git a/Content.Server/Body/Systems/RespiratorSystem.cs b/Content.Server/Body/Systems/RespiratorSystem.cs index b9899145fb..5bde141b54 100644 --- a/Content.Server/Body/Systems/RespiratorSystem.cs +++ b/Content.Server/Body/Systems/RespiratorSystem.cs @@ -8,7 +8,7 @@ using Content.Shared.Atmos; using Content.Shared.Body.Components; using Content.Shared.Damage; using Content.Shared.Database; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Systems; using JetBrains.Annotations; using Robust.Shared.Player; using Robust.Shared.Timing; @@ -26,7 +26,7 @@ namespace Content.Server.Body.Systems [Dependency] private readonly DamageableSystem _damageableSys = default!; [Dependency] private readonly LungSystem _lungSystem = default!; [Dependency] private readonly PopupSystem _popupSystem = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; public override void Initialize() { diff --git a/Content.Server/Buckle/Systems/BuckleSystem.Buckle.cs b/Content.Server/Buckle/Systems/BuckleSystem.Buckle.cs index 87b995d7fa..3e1135b1f5 100644 --- a/Content.Server/Buckle/Systems/BuckleSystem.Buckle.cs +++ b/Content.Server/Buckle/Systems/BuckleSystem.Buckle.cs @@ -9,7 +9,7 @@ using Content.Shared.DragDrop; using Content.Shared.Hands.Components; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Content.Shared.Pulling.Components; using Content.Shared.Stunnable; using Content.Shared.Vehicle.Components; @@ -360,8 +360,10 @@ public sealed partial class BuckleSystem _standing.Stand(buckleId); } - _mobState.EnterState(mobState, mobState?.CurrentState); - + if (_mobState.IsIncapacitated(buckleId, mobState)) + { + _standing.Down(buckleId); + } // Sync StrapComponent data _appearance.SetData(oldBuckledTo.Owner, StrapVisuals.State, false); if (oldBuckledTo.BuckledEntities.Remove(buckleId)) diff --git a/Content.Server/Buckle/Systems/BuckleSystem.cs b/Content.Server/Buckle/Systems/BuckleSystem.cs index e7b8ac5699..f550208e96 100644 --- a/Content.Server/Buckle/Systems/BuckleSystem.cs +++ b/Content.Server/Buckle/Systems/BuckleSystem.cs @@ -4,7 +4,7 @@ using Content.Server.Pulling; using Content.Shared.ActionBlocker; using Content.Shared.Alert; using Content.Shared.Buckle; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Systems; using JetBrains.Annotations; using Robust.Server.Containers; using Robust.Server.GameObjects; @@ -23,7 +23,7 @@ public sealed partial class BuckleSystem : SharedBuckleSystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly ContainerSystem _containers = default!; [Dependency] private readonly InteractionSystem _interactions = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly PopupSystem _popups = default!; [Dependency] private readonly PullingSystem _pulling = default!; [Dependency] private readonly Shared.Standing.StandingStateSystem _standing = default!; diff --git a/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs b/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs index b3ef320e72..8552b70cce 100644 --- a/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs +++ b/Content.Server/Cargo/Systems/CargoSystem.Shuttle.cs @@ -1,7 +1,6 @@ using System.Linq; using Content.Server.Cargo.Components; using Content.Server.Labels.Components; -using Content.Server.MobState; using Content.Server.Shuttles.Components; using Content.Server.Shuttles.Events; using Content.Server.UserInterface; @@ -16,7 +15,8 @@ using Content.Shared.Cargo.Prototypes; using Content.Shared.CCVar; using Content.Shared.Dataset; using Content.Shared.GameTicking; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Server.GameObjects; using Robust.Server.Maps; using Robust.Shared.Audio; diff --git a/Content.Server/Cargo/Systems/PricingSystem.cs b/Content.Server/Cargo/Systems/PricingSystem.cs index 677b5b290b..39bd51628c 100644 --- a/Content.Server/Cargo/Systems/PricingSystem.cs +++ b/Content.Server/Cargo/Systems/PricingSystem.cs @@ -3,13 +3,13 @@ using Content.Server.Administration; using Content.Server.Body.Systems; using Content.Server.Cargo.Components; using Content.Server.Chemistry.Components.SolutionManager; -using Content.Server.MobState; using Content.Server.Stack; using Content.Shared.Administration; using Content.Shared.Body.Components; using Content.Shared.Chemistry.Reagent; using Content.Shared.Materials; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Stacks; using Robust.Shared.Console; using Robust.Shared.Containers; diff --git a/Content.Server/Chat/SuicideSystem.cs b/Content.Server/Chat/SuicideSystem.cs index d1646f7e64..5d2df81584 100644 --- a/Content.Server/Chat/SuicideSystem.cs +++ b/Content.Server/Chat/SuicideSystem.cs @@ -1,13 +1,13 @@ using Content.Server.Administration.Logs; using Content.Server.Hands.Components; -using Content.Server.MobState; using Content.Server.Popups; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.Database; using Content.Shared.Interaction.Events; using Content.Shared.Item; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Tag; using Robust.Shared.Prototypes; diff --git a/Content.Server/Chat/Systems/ChatSystem.cs b/Content.Server/Chat/Systems/ChatSystem.cs index 5e6228819e..67b7d3645f 100644 --- a/Content.Server/Chat/Systems/ChatSystem.cs +++ b/Content.Server/Chat/Systems/ChatSystem.cs @@ -5,7 +5,6 @@ using Content.Server.Administration.Managers; using Content.Server.Chat.Managers; using Content.Server.GameTicking; using Content.Server.Ghost.Components; -using Content.Server.MobState; using Content.Server.Players; using Content.Server.Popups; using Content.Server.Station.Components; @@ -16,6 +15,7 @@ using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared.IdentityManagement; using Content.Shared.Inventory; +using Content.Shared.Mobs.Systems; using Content.Shared.Radio; using Robust.Server.GameObjects; using Robust.Server.Player; diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs index 5062dbc7c1..11d8b27727 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.Injector.cs @@ -11,10 +11,10 @@ using Content.Shared.Hands; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; -using Content.Shared.MobState.Components; using Robust.Shared.GameStates; using Robust.Shared.Player; using System.Threading; +using Content.Shared.Mobs.Components; using Content.Shared.Verbs; using Robust.Server.GameObjects; using Content.Shared.Popups; diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs index 8be0926fb7..6efb96b55b 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystem.cs @@ -5,7 +5,7 @@ using Content.Server.Interaction; using Content.Server.Popups; using Content.Shared.CombatMode; using Content.Shared.Chemistry; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Systems; namespace Content.Server.Chemistry.EntitySystems; @@ -19,7 +19,7 @@ public sealed partial class ChemistrySystem : EntitySystem [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly ReactiveSystem _reactiveSystem = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedCombatModeSystem _combat = default!; [Dependency] private readonly SolutionContainerSystem _solutions = default!; diff --git a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs b/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs index 317a3c26ab..06fd29813b 100644 --- a/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs +++ b/Content.Server/Chemistry/EntitySystems/ChemistrySystemHypospray.cs @@ -9,7 +9,7 @@ using Content.Shared.FixedPoint; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Content.Shared.Weapons.Melee.Events; using Robust.Shared.Player; diff --git a/Content.Server/Cloning/CloningConsoleSystem.cs b/Content.Server/Cloning/CloningConsoleSystem.cs index a2cb0adf98..5efb34f3d6 100644 --- a/Content.Server/Cloning/CloningConsoleSystem.cs +++ b/Content.Server/Cloning/CloningConsoleSystem.cs @@ -8,8 +8,6 @@ using Content.Server.Mind.Components; using Content.Server.MachineLinking.System; using Content.Server.MachineLinking.Events; using Content.Server.UserInterface; -using Content.Server.MobState; -using Content.Shared.MobState.Components; using Content.Server.Power.EntitySystems; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -17,6 +15,8 @@ using Content.Shared.Cloning.CloningConsole; using Content.Shared.Cloning; using Content.Shared.MachineLinking.Events; using Content.Shared.IdentityManagement; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; namespace Content.Server.Cloning { diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index 322b092bfe..76460153de 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -12,7 +12,6 @@ using Content.Server.EUI; using Content.Server.Humanoid; using Content.Server.MachineLinking.System; using Content.Server.MachineLinking.Events; -using Content.Server.MobState; using Content.Shared.Chemistry.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.Chat.Systems; @@ -22,6 +21,7 @@ using Content.Server.Stack; using Content.Server.Jobs; using Content.Shared.Humanoid; using Content.Shared.Humanoid.Prototypes; +using Content.Shared.Mobs.Systems; using Robust.Server.GameObjects; using Robust.Server.Containers; using Robust.Server.Player; diff --git a/Content.Server/Contests/ContestsSystem.cs b/Content.Server/Contests/ContestsSystem.cs index 01b6ac7a88..acc7d372b4 100644 --- a/Content.Server/Contests/ContestsSystem.cs +++ b/Content.Server/Contests/ContestsSystem.cs @@ -1,8 +1,7 @@ using Content.Shared.Damage; -using Content.Shared.MobState.EntitySystems; -using Content.Shared.MobState.Components; -using Content.Server.Damage.Components; using Content.Shared.Damage.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Systems; using Robust.Shared.Physics.Components; namespace Content.Server.Contests @@ -16,10 +15,11 @@ namespace Content.Server.Contests /// <1 = Advantage to target /// Roller should be the entity with an advantage from being bigger/healthier/more skilled, etc. /// + /// public sealed class ContestsSystem : EntitySystem { - [Dependency] private readonly SharedMobStateSystem _mobStateSystem = default!; - + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!; /// /// Returns the roller's mass divided by the target's. /// @@ -46,20 +46,37 @@ namespace Content.Server.Contests return 1f; // First, we'll see what health they go into crit at. - float rollerThreshold = 100f; - float targetThreshold = 100f; - - if (TryComp(roller, out var rollerState) && - _mobStateSystem.TryGetEarliestIncapacitatedState(rollerState, 10000, out _, out var rollerCritThreshold)) - rollerThreshold = (float) rollerCritThreshold; - - if (TryComp(target, out var targetState) && - _mobStateSystem.TryGetEarliestIncapacitatedState(targetState, 10000, out _, out var targetCritThreshold)) - targetThreshold = (float) targetCritThreshold; + //TODO: refactor this entire system.... Why does this exist, this shouldn't be calculated off health + var rollerThreshold = 100f; + if (!_mobThresholdSystem.TryGetThresholdForState(roller, MobState.Critical, out var rollerCritThreshold)) + { + if (_mobThresholdSystem.TryGetThresholdForState(roller, MobState.Critical, + out var rollerdeadThreshold)) + { + rollerThreshold = rollerdeadThreshold.Value.Float(); + } + } + else + { + rollerThreshold = rollerCritThreshold.Value.Float(); + } + var targetThreshold = 100f; + if (!_mobThresholdSystem.TryGetThresholdForState(roller, MobState.Critical, out var targetCritThreshold)) + { + if (_mobThresholdSystem.TryGetThresholdForState(roller, MobState.Critical, + out var targetdeadThreshold)) + { + targetThreshold = targetdeadThreshold.Value.Float(); + } + } + else + { + targetThreshold = targetCritThreshold.Value.Float(); + } // Next, we'll see how their damage compares - float rollerDamageScore = (float) rollerDamage.TotalDamage / rollerThreshold; - float targetDamageScore = (float) targetDamage.TotalDamage / targetThreshold; + var rollerDamageScore = (float) rollerDamage.TotalDamage / rollerThreshold; + var targetDamageScore = (float) targetDamage.TotalDamage / targetThreshold; return DamageThresholdConverter(rollerDamageScore) / DamageThresholdConverter(targetDamageScore); } diff --git a/Content.Server/Cuffs/CuffableSystem.cs b/Content.Server/Cuffs/CuffableSystem.cs index 6142ce769f..741e18cc4c 100644 --- a/Content.Server/Cuffs/CuffableSystem.cs +++ b/Content.Server/Cuffs/CuffableSystem.cs @@ -13,7 +13,7 @@ using Content.Shared.Interaction; using Robust.Shared.Audio; using Robust.Shared.Containers; using Content.Server.Hands.Systems; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Systems; namespace Content.Server.Cuffs { @@ -23,7 +23,7 @@ namespace Content.Server.Cuffs [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; [Dependency] private readonly HandVirtualItemSystem _virtualSystem = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; public override void Initialize() diff --git a/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs b/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs index ae404779db..5e3c1dcdfd 100644 --- a/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs +++ b/Content.Server/Damage/Systems/DamageOtherOnHitSystem.cs @@ -2,7 +2,7 @@ using Content.Server.Administration.Logs; using Content.Server.Damage.Components; using Content.Shared.Damage; using Content.Shared.Database; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Content.Shared.Throwing; namespace Content.Server.Damage.Systems diff --git a/Content.Server/Disease/DiseaseSystem.cs b/Content.Server/Disease/DiseaseSystem.cs index 702219fec4..f057f890b6 100644 --- a/Content.Server/Disease/DiseaseSystem.cs +++ b/Content.Server/Disease/DiseaseSystem.cs @@ -3,7 +3,6 @@ using Content.Server.Body.Systems; using Content.Server.Chat.Systems; using Content.Server.Disease.Components; using Content.Server.DoAfter; -using Content.Server.MobState; using Content.Server.Nutrition.EntitySystems; using Content.Server.Popups; using Content.Shared.Clothing.Components; @@ -16,7 +15,8 @@ using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Inventory; using Content.Shared.Inventory.Events; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Rejuvenate; using Robust.Shared.Audio; using Robust.Server.GameObjects; diff --git a/Content.Server/DoAfter/DoAfterSystem.cs b/Content.Server/DoAfter/DoAfterSystem.cs index 4606ff8d08..84ad75092a 100644 --- a/Content.Server/DoAfter/DoAfterSystem.cs +++ b/Content.Server/DoAfter/DoAfterSystem.cs @@ -2,7 +2,7 @@ using System.Linq; using System.Threading.Tasks; using Content.Shared.Damage; using Content.Shared.DoAfter; -using Content.Shared.MobState; +using Content.Shared.Mobs; using JetBrains.Annotations; using Robust.Shared.GameStates; @@ -90,7 +90,7 @@ namespace Content.Server.DoAfter private void OnStateChanged(EntityUid uid, DoAfterComponent component, MobStateChangedEvent args) { - if (!args.CurrentMobState.IsIncapacitated()) + if (args.NewMobState == MobState.Alive) return; foreach (var (doAfter, _) in component.DoAfters) diff --git a/Content.Server/Doors/Components/FirelockComponent.cs b/Content.Server/Doors/Components/FirelockComponent.cs index cde4aa7692..249a413023 100644 --- a/Content.Server/Doors/Components/FirelockComponent.cs +++ b/Content.Server/Doors/Components/FirelockComponent.cs @@ -1,3 +1,4 @@ +using Content.Server.Atmos.Monitor.Components; using Content.Shared.Doors.Components; namespace Content.Server.Doors.Components diff --git a/Content.Server/Dragon/DragonSystem.cs b/Content.Server/Dragon/DragonSystem.cs index 035b96615b..a7ba11a3c6 100644 --- a/Content.Server/Dragon/DragonSystem.cs +++ b/Content.Server/Dragon/DragonSystem.cs @@ -3,14 +3,13 @@ using Content.Server.DoAfter; using Content.Server.Popups; using Content.Shared.Actions; using Content.Shared.Chemistry.Components; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; using Robust.Shared.Containers; using Robust.Shared.Player; using System.Threading; using Content.Server.Chat.Systems; using Content.Server.GameTicking; using Content.Server.GameTicking.Rules; +using Content.Server.Humanoid; using Content.Server.NPC; using Content.Shared.Damage; using Content.Shared.Dragon; @@ -22,6 +21,8 @@ using Robust.Shared.Map; using Robust.Shared.Random; using Content.Server.NPC.Systems; using Content.Shared.Humanoid; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; namespace Content.Server.Dragon { @@ -275,7 +276,7 @@ namespace Content.Server.Dragon { //Empties the stomach upon death //TODO: Do this when the dragon gets butchered instead - if (args.CurrentMobState == DamageState.Dead) + if (args.NewMobState == MobState.Dead) { if (component.SoundDeath != null) _audioSystem.PlayPvs(component.SoundDeath, uid, component.SoundDeath.Params); @@ -365,8 +366,8 @@ namespace Content.Server.Dragon { switch (targetState.CurrentState) { - case DamageState.Critical: - case DamageState.Dead: + case MobState.Critical: + case MobState.Dead: component.CancelToken = new CancellationTokenSource(); _doAfterSystem.DoAfter(new DoAfterEventArgs(uid, component.DevourTime, component.CancelToken.Token, target) diff --git a/Content.Server/Drone/DroneSystem.cs b/Content.Server/Drone/DroneSystem.cs index f2cc53c71c..bcbf246305 100644 --- a/Content.Server/Drone/DroneSystem.cs +++ b/Content.Server/Drone/DroneSystem.cs @@ -3,7 +3,6 @@ using Content.Server.Drone.Components; using Content.Server.Ghost.Components; using Content.Server.Ghost.Roles.Components; using Content.Server.Mind.Components; -using Content.Server.MobState; using Content.Server.Popups; using Content.Server.Tools.Innate; using Content.Server.UserInterface; @@ -15,8 +14,9 @@ using Content.Shared.IdentityManagement; using Content.Shared.Interaction.Components; using Content.Shared.Interaction.Events; using Content.Shared.Item; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Tag; using Content.Shared.Throwing; @@ -82,7 +82,7 @@ namespace Content.Server.Drone private void OnMobStateChanged(EntityUid uid, DroneComponent drone, MobStateChangedEvent args) { - if (args.CurrentMobState == DamageState.Dead) + if (args.NewMobState == MobState.Dead) { if (TryComp(uid, out var innate)) _innateToolSystem.Cleanup(uid, innate); diff --git a/Content.Server/Explosion/Components/OnUseTimerTriggerComponent.cs b/Content.Server/Explosion/Components/OnUseTimerTriggerComponent.cs index ae7dd95815..be66d23f9d 100644 --- a/Content.Server/Explosion/Components/OnUseTimerTriggerComponent.cs +++ b/Content.Server/Explosion/Components/OnUseTimerTriggerComponent.cs @@ -1,4 +1,3 @@ -using Content.Shared.MobState; using Robust.Shared.Audio; namespace Content.Server.Explosion.Components diff --git a/Content.Server/Explosion/Components/TriggerOnMobstateChangeComponent.cs b/Content.Server/Explosion/Components/TriggerOnMobstateChangeComponent.cs index 657de34ffe..3117c956b5 100644 --- a/Content.Server/Explosion/Components/TriggerOnMobstateChangeComponent.cs +++ b/Content.Server/Explosion/Components/TriggerOnMobstateChangeComponent.cs @@ -1,4 +1,4 @@ -using Content.Shared.MobState; +using Content.Shared.Mobs; namespace Content.Server.Explosion.Components; @@ -13,7 +13,7 @@ public sealed class TriggerOnMobstateChangeComponent : Component /// [ViewVariables] [DataField("mobState", required: true)] - public DamageState MobState = DamageState.Alive; + public MobState MobState = MobState.Alive; /// /// If true, prevents suicide attempts for the trigger to prevent cheese. diff --git a/Content.Server/Explosion/EntitySystems/TriggerSystem.Mobstate.cs b/Content.Server/Explosion/EntitySystems/TriggerSystem.Mobstate.cs index 824cdca8b3..793cac830f 100644 --- a/Content.Server/Explosion/EntitySystems/TriggerSystem.Mobstate.cs +++ b/Content.Server/Explosion/EntitySystems/TriggerSystem.Mobstate.cs @@ -1,6 +1,6 @@ using Content.Server.Explosion.Components; using Content.Shared.Interaction.Events; -using Content.Shared.MobState; +using Content.Shared.Mobs; using Robust.Shared.Player; namespace Content.Server.Explosion.EntitySystems; @@ -15,7 +15,7 @@ public sealed partial class TriggerSystem private void OnMobStateChanged(EntityUid uid, TriggerOnMobstateChangeComponent component, MobStateChangedEvent args) { - if (component.MobState < args.CurrentMobState) + if (component.MobState < args.NewMobState) return; //This chains Mobstate Changed triggers with OnUseTimerTrigger if they have it diff --git a/Content.Server/GameTicking/GameTicker.GamePreset.cs b/Content.Server/GameTicking/GameTicker.GamePreset.cs index 3fdb165112..cedc88cba4 100644 --- a/Content.Server/GameTicking/GameTicker.GamePreset.cs +++ b/Content.Server/GameTicking/GameTicker.GamePreset.cs @@ -3,12 +3,12 @@ using System.Linq; using Content.Server.GameTicking.Presets; using Content.Server.GameTicking.Rules; using Content.Server.Ghost.Components; -using Content.Server.MobState; using Content.Shared.CCVar; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.Database; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Server.Player; namespace Content.Server.GameTicking @@ -17,6 +17,8 @@ namespace Content.Server.GameTicking { public const float PresetFailedCooldownIncrease = 30f; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + public GamePresetPrototype? Preset { get; private set; } private bool StartPreset(IPlayerSession[] origReadyPlayers, bool force) @@ -193,7 +195,7 @@ namespace Content.Server.GameTicking if (canReturnGlobal && TryComp(playerEntity, out MobStateComponent? mobState)) { - if (_mobState.IsCritical(playerEntity.Value, mobState)) + if (_mobStateSystem.IsCritical(playerEntity.Value, mobState)) { canReturn = true; diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index ed2c0f3665..97f07cb1d4 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -13,7 +13,7 @@ using Content.Server.Station.Systems; using Content.Shared.Chat; using Content.Shared.Damage; using Content.Shared.GameTicking; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Systems; using Content.Shared.Roles; using Robust.Server; using Robust.Server.GameObjects; @@ -35,7 +35,7 @@ namespace Content.Server.GameTicking public sealed partial class GameTicker : SharedGameTicker { [Dependency] private readonly MapLoaderSystem _map = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [ViewVariables] private bool _initialized; diff --git a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs index 2cdda7ea6d..c4c61480db 100644 --- a/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/DeathMatchRuleSystem.cs @@ -1,9 +1,9 @@ using Content.Server.Chat.Managers; using Content.Server.GameTicking.Rules.Configurations; -using Content.Server.MobState; using Content.Shared.CCVar; using Content.Shared.Damage; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Server.Player; using Robust.Shared.Configuration; using Robust.Shared.Enums; diff --git a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs index 6b50d287d7..6e2b70cf71 100644 --- a/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/NukeopsRuleSystem.cs @@ -19,8 +19,8 @@ using Content.Server.Station.Components; using Content.Server.Station.Systems; using Content.Server.Traitor; using Content.Shared.Dataset; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Content.Shared.Nuke; using Content.Shared.Preferences; using Content.Shared.Roles; @@ -310,7 +310,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem var allAlive = true; foreach (var (_, state) in EntityQuery()) { - if (state.CurrentState is DamageState.Alive) + if (state.CurrentState is MobState.Alive) { continue; } @@ -415,7 +415,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem .Where(ent => ent.Item3.MapID == shuttleMapId || ent.Item3.MapID == targetStationMap) - .Any(ent => ent.Item2.CurrentState == DamageState.Alive && ent.Item1.Running); + .Any(ent => ent.Item2.CurrentState == MobState.Alive && ent.Item1.Running); if (operativesAlive) return; // There are living operatives than can access the shuttle, or are still on the station's map. @@ -446,7 +446,7 @@ public sealed class NukeopsRuleSystem : GameRuleSystem private void OnMobStateChanged(EntityUid uid, NukeOperativeComponent component, MobStateChangedEvent ev) { - if(ev.CurrentMobState == DamageState.Dead) + if(ev.NewMobState == MobState.Dead) CheckRoundShouldEnd(); } diff --git a/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs b/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs index 8a6598434f..942d1640a9 100644 --- a/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/SuspicionRuleSystem.cs @@ -2,7 +2,6 @@ using System.Linq; using System.Threading; using Content.Server.Chat.Managers; using Content.Server.GameTicking.Rules.Configurations; -using Content.Server.MobState; using Content.Server.Players; using Content.Server.Roles; using Content.Server.Station.Components; @@ -14,7 +13,8 @@ using Content.Shared.Doors.Systems; using Content.Shared.EntityList; using Content.Shared.GameTicking; using Content.Shared.Maps; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Roles; using Content.Shared.Suspicion; using Robust.Server.GameObjects; diff --git a/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs index 5df12de47b..f1bb0c1ee7 100644 --- a/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorDeathMatchRuleSystem.cs @@ -3,7 +3,6 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.Chat.Managers; using Content.Server.GameTicking.Rules.Configurations; using Content.Server.Hands.Components; -using Content.Server.MobState; using Content.Server.PDA; using Content.Server.Players; using Content.Server.Spawners.Components; @@ -16,7 +15,8 @@ using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; using Content.Shared.Inventory; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.PDA; using Content.Shared.Roles; using Robust.Server.GameObjects; diff --git a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs index 694455f1e9..e6fa3ad1c9 100644 --- a/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/TraitorRuleSystem.cs @@ -5,10 +5,10 @@ using Content.Server.Players; using Content.Server.Roles; using Content.Server.Traitor; using Content.Server.Traitor.Uplink; -using Content.Server.MobState; using Content.Server.NPC.Systems; using Content.Shared.CCVar; using Content.Shared.Dataset; +using Content.Shared.Mobs.Systems; using Content.Shared.Roles; using Robust.Server.Player; using Robust.Shared.Audio; diff --git a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs index dc1821d5d6..a6e90ab450 100644 --- a/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ZombieRuleSystem.cs @@ -3,8 +3,8 @@ using Content.Server.Actions; using Content.Server.Chat.Managers; using Content.Server.Disease; using Content.Server.Disease.Components; +using Content.Server.Humanoid; using Content.Server.Mind.Components; -using Content.Server.MobState; using Content.Server.Players; using Content.Server.Popups; using Content.Server.Preferences.Managers; @@ -14,8 +14,9 @@ using Content.Server.Zombies; using Content.Shared.Actions.ActionTypes; using Content.Shared.CCVar; using Content.Shared.Humanoid; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Preferences; using Content.Shared.Roles; using Content.Shared.Zombies; @@ -129,7 +130,7 @@ public sealed class ZombieRuleSystem : GameRuleSystem { if (!RuleAdded) return; - CheckRoundEnd(ev.Entity); + CheckRoundEnd(ev.Target); } private void OnEntityZombified(EntityZombifiedEvent ev) diff --git a/Content.Server/Ghost/GhostSystem.cs b/Content.Server/Ghost/GhostSystem.cs index 43ab43585a..a38b973edf 100644 --- a/Content.Server/Ghost/GhostSystem.cs +++ b/Content.Server/Ghost/GhostSystem.cs @@ -3,7 +3,6 @@ using Content.Server.GameTicking; using Content.Server.Ghost.Components; using Content.Server.Mind; using Content.Server.Mind.Components; -using Content.Server.MobState; using Content.Server.Players; using Content.Server.Storage.Components; using Content.Server.Visible; @@ -13,7 +12,8 @@ using Content.Shared.Administration; using Content.Shared.Examine; using Content.Shared.Follower; using Content.Shared.Ghost; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Movement.Events; using JetBrains.Annotations; using Robust.Server.GameObjects; diff --git a/Content.Server/Ghost/Roles/GhostRoleSystem.cs b/Content.Server/Ghost/Roles/GhostRoleSystem.cs index c4be8c8610..00f53c27fa 100644 --- a/Content.Server/Ghost/Roles/GhostRoleSystem.cs +++ b/Content.Server/Ghost/Roles/GhostRoleSystem.cs @@ -11,7 +11,7 @@ using Content.Shared.Follower; using Content.Shared.GameTicking; using Content.Shared.Ghost; using Content.Shared.Ghost.Roles; -using Content.Shared.MobState; +using Content.Shared.Mobs; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Server.Player; @@ -56,16 +56,16 @@ namespace Content.Server.Ghost.Roles private void OnMobStateChanged(EntityUid uid, GhostRoleComponent component, MobStateChangedEvent args) { - switch (args.CurrentMobState) + switch (args.NewMobState) { - case DamageState.Alive: + case MobState.Alive: { if (!component.Taken) RegisterGhostRole(component); break; } - case DamageState.Critical: - case DamageState.Dead: + case MobState.Critical: + case MobState.Dead: UnregisterGhostRole(component); break; } diff --git a/Content.Server/Guardian/GuardianSystem.cs b/Content.Server/Guardian/GuardianSystem.cs index 72678c488f..bad11e1da8 100644 --- a/Content.Server/Guardian/GuardianSystem.cs +++ b/Content.Server/Guardian/GuardianSystem.cs @@ -7,7 +7,7 @@ using Content.Shared.Examine; using Content.Shared.Hands.EntitySystems; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; -using Content.Shared.MobState; +using Content.Shared.Mobs; using Content.Shared.Popups; using Robust.Server.GameObjects; using Robust.Shared.Audio; @@ -224,12 +224,12 @@ namespace Content.Server.Guardian { if (component.HostedGuardian == null) return; - if (args.CurrentMobState.IsCritical()) + if (args.NewMobState == MobState.Critical) { _popupSystem.PopupEntity(Loc.GetString("guardian-critical-warn"), component.HostedGuardian.Value, component.HostedGuardian.Value); SoundSystem.Play("/Audio/Effects/guardian_warn.ogg", Filter.Pvs(component.HostedGuardian.Value), component.HostedGuardian.Value); } - else if (args.CurrentMobState.IsDead()) + else if (args.NewMobState == MobState.Dead) { SoundSystem.Play("/Audio/Voice/Human/malescream_guardian.ogg", Filter.Pvs(uid), uid, AudioHelpers.WithVariation(0.20f)); EntityManager.RemoveComponent(uid); diff --git a/Content.Server/Implants/ImplanterSystem.cs b/Content.Server/Implants/ImplanterSystem.cs index be0fb789ca..369070041a 100644 --- a/Content.Server/Implants/ImplanterSystem.cs +++ b/Content.Server/Implants/ImplanterSystem.cs @@ -7,7 +7,7 @@ using Content.Shared.IdentityManagement; using Content.Shared.Implants; using Content.Shared.Implants.Components; using Content.Shared.Interaction; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Content.Shared.Popups; using Robust.Shared.Containers; using Robust.Shared.GameStates; diff --git a/Content.Server/Implants/SubdermalImplantSystem.cs b/Content.Server/Implants/SubdermalImplantSystem.cs index 095a115804..5df9720fa8 100644 --- a/Content.Server/Implants/SubdermalImplantSystem.cs +++ b/Content.Server/Implants/SubdermalImplantSystem.cs @@ -2,7 +2,7 @@ using Content.Shared.Implants; using Content.Shared.Implants.Components; using Content.Shared.Interaction.Events; -using Content.Shared.MobState; +using Content.Shared.Mobs; using Robust.Shared.Containers; namespace Content.Server.Implants; @@ -34,19 +34,28 @@ public sealed class SubdermalImplantSystem : SharedSubdermalImplantSystem #region Relays - //Relays from the implanted to the implant - private void RelayToImplantEvent(EntityUid uid, ImplantedComponent component, T args) where T : EntityEventArgs + private void RelayToImplantEvent(EntityUid uid, ImplantedComponent component, T args) where T: notnull { if (!_container.TryGetContainer(uid, ImplanterComponent.ImplantSlotId, out var implantContainer)) return; - foreach (var implant in implantContainer.ContainedEntities) { RaiseLocalEvent(implant, args); } } + //Relays from the implanted to the implant + private void RelayToImplantEventByRef(EntityUid uid, ImplantedComponent component, ref T args) where T: notnull + { + if (!_container.TryGetContainer(uid, ImplanterComponent.ImplantSlotId, out var implantContainer)) + return; + foreach (var implant in implantContainer.ContainedEntities) + { + RaiseLocalEvent(implant,ref args); + } + } + //Relays from the implant to the implanted private void RelayToImplantedEvent(EntityUid uid, SubdermalImplantComponent component, T args) where T : EntityEventArgs { @@ -56,5 +65,13 @@ public sealed class SubdermalImplantSystem : SharedSubdermalImplantSystem } } + private void RelayToImplantedEventByRef(EntityUid uid, SubdermalImplantComponent component, ref T args) where T : EntityEventArgs + { + if (component.ImplantedEntity != null) + { + RaiseLocalEvent(component.ImplantedEntity.Value, ref args); + } + } + #endregion } diff --git a/Content.Server/Interaction/InteractionPopupSystem.cs b/Content.Server/Interaction/InteractionPopupSystem.cs index aad73eca22..ca14b28433 100644 --- a/Content.Server/Interaction/InteractionPopupSystem.cs +++ b/Content.Server/Interaction/InteractionPopupSystem.cs @@ -1,10 +1,10 @@ using Content.Server.Interaction.Components; -using Content.Server.MobState; using Content.Server.Popups; using Content.Shared.Bed.Sleep; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Shared.Audio; using Robust.Shared.Player; using Robust.Shared.Random; diff --git a/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs b/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs index 4bf145dd51..540de18e43 100644 --- a/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/KitchenSpikeSystem.cs @@ -1,7 +1,6 @@ using Content.Server.Administration.Logs; using Content.Server.DoAfter; using Content.Server.Kitchen.Components; -using Content.Server.MobState; using Content.Server.Nutrition.Components; using Content.Server.Popups; using Content.Shared.Administration.Logs; @@ -9,7 +8,6 @@ using Content.Shared.Database; using Content.Shared.DragDrop; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; -using Content.Shared.MobState.Components; using Content.Shared.Nutrition.Components; using Robust.Shared.Audio; using Robust.Shared.Player; @@ -17,6 +15,8 @@ using Content.Shared.Storage; using Robust.Shared.Random; using static Content.Shared.Kitchen.Components.SharedKitchenSpikeComponent; using Content.Shared.Interaction.Events; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Popups; namespace Content.Server.Kitchen.EntitySystems diff --git a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs index 87043994bc..21022bb629 100644 --- a/Content.Server/Kitchen/EntitySystems/SharpSystem.cs +++ b/Content.Server/Kitchen/EntitySystems/SharpSystem.cs @@ -1,15 +1,15 @@ using Content.Server.Body.Systems; using Content.Server.DoAfter; using Content.Server.Kitchen.Components; -using Content.Server.MobState; using Content.Shared.Body.Components; using Content.Shared.Interaction; -using Content.Shared.MobState.Components; using Content.Shared.Nutrition.Components; using Content.Shared.Popups; using Content.Shared.Storage; using Content.Shared.Verbs; using Content.Shared.Destructible; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Server.Containers; using Robust.Shared.Player; using Robust.Shared.Random; diff --git a/Content.Server/Light/Components/UnpoweredFlashlightComponent.cs b/Content.Server/Light/Components/UnpoweredFlashlightComponent.cs index 72f057fb6a..83ab63f623 100644 --- a/Content.Server/Light/Components/UnpoweredFlashlightComponent.cs +++ b/Content.Server/Light/Components/UnpoweredFlashlightComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Actions.ActionTypes; +using Content.Shared.Light; using Robust.Shared.Audio; namespace Content.Server.Light.Components diff --git a/Content.Server/Mech/Equipment/EntitySystems/MechGrabberSystem.cs b/Content.Server/Mech/Equipment/EntitySystems/MechGrabberSystem.cs index a947d99e93..a580944ea6 100644 --- a/Content.Server/Mech/Equipment/EntitySystems/MechGrabberSystem.cs +++ b/Content.Server/Mech/Equipment/EntitySystems/MechGrabberSystem.cs @@ -7,7 +7,7 @@ using Content.Server.Mech.Systems; using Content.Shared.Interaction; using Content.Shared.Mech; using Content.Shared.Mech.Equipment.Components; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Content.Shared.Wall; using Robust.Shared.Containers; using Robust.Shared.Map; diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs index 4fdb37909a..375a236a88 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs @@ -1,5 +1,4 @@ using System.Threading; -using Content.Shared.MobState.Components; using Content.Shared.Interaction; using Content.Shared.Audio; using Content.Shared.Jittering; @@ -10,7 +9,6 @@ using Content.Shared.Nutrition.Components; using Content.Shared.Administration.Logs; using Content.Shared.CCVar; using Content.Shared.Database; -using Content.Server.MobState; using Content.Server.Power.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.Body.Components; @@ -21,6 +19,8 @@ using Content.Server.Materials; using Content.Server.Mind.Components; using Content.Shared.Humanoid; using Content.Shared.Interaction.Events; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Robust.Shared.Random; using Robust.Shared.Configuration; diff --git a/Content.Server/Medical/HealingSystem.cs b/Content.Server/Medical/HealingSystem.cs index d24c0ac082..4fbcfb0833 100644 --- a/Content.Server/Medical/HealingSystem.cs +++ b/Content.Server/Medical/HealingSystem.cs @@ -4,13 +4,14 @@ using Content.Server.Body.Systems; using Content.Server.DoAfter; using Content.Server.Medical.Components; using Content.Server.Stack; -using Content.Server.MobState; using Content.Shared.Audio; using Content.Shared.Damage; using Content.Shared.Database; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Stacks; using Robust.Shared.Random; @@ -27,6 +28,7 @@ public sealed class HealingSystem : EntitySystem [Dependency] private readonly StackSystem _stacks = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!; public override void Initialize() { @@ -175,10 +177,15 @@ public sealed class HealingSystem : EntitySystem public float GetScaledHealingPenalty(EntityUid uid, HealingComponent component) { var output = component.Delay; - if (!TryComp(uid, out var mobState) || !TryComp(uid, out var damageable)) + if (!TryComp(uid, out var mobThreshold) || !TryComp(uid, out var damageable)) return output; - _mobStateSystem.TryGetEarliestCriticalState(mobState, 0, out var _, out var amount); + + if (!_mobThresholdSystem.TryGetThresholdForState(uid, MobState.Critical, out var amount, + mobThreshold)) + { + return 1; + } var percentDamage = (float) (damageable.TotalDamage / amount); //basically make it scale from 1 to the multiplier. var modifier = percentDamage * (component.SelfHealPenaltyMultiplier - 1) + 1; diff --git a/Content.Server/Medical/HealthAnalyzerSystem.cs b/Content.Server/Medical/HealthAnalyzerSystem.cs index 22f0ac174f..0f5f1d0959 100644 --- a/Content.Server/Medical/HealthAnalyzerSystem.cs +++ b/Content.Server/Medical/HealthAnalyzerSystem.cs @@ -6,7 +6,7 @@ using Content.Server.Popups; using Content.Shared.Damage; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Content.Shared.Audio; using Robust.Server.GameObjects; using Robust.Shared.Player; diff --git a/Content.Server/Medical/MedicalScannerSystem.cs b/Content.Server/Medical/MedicalScannerSystem.cs index 52dc5b4b8e..90decea66b 100644 --- a/Content.Server/Medical/MedicalScannerSystem.cs +++ b/Content.Server/Medical/MedicalScannerSystem.cs @@ -5,7 +5,6 @@ using Content.Server.Power.Components; using Content.Shared.Destructible; using Content.Shared.ActionBlocker; using Content.Shared.DragDrop; -using Content.Shared.MobState.Components; using Content.Shared.Movement.Events; using Content.Shared.Verbs; using Robust.Shared.Containers; @@ -13,7 +12,8 @@ using Content.Server.MachineLinking.System; using Content.Server.MachineLinking.Events; using Content.Server.Cloning.Components; using Content.Server.Construction; -using Content.Server.MobState; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Server.Containers; using static Content.Shared.MedicalScanner.SharedMedicalScannerComponent; /// Hmm... diff --git a/Content.Server/Medical/Stethoscope/StethoscopeSystem.cs b/Content.Server/Medical/Stethoscope/StethoscopeSystem.cs index be691d9e64..3ce39c4e1a 100644 --- a/Content.Server/Medical/Stethoscope/StethoscopeSystem.cs +++ b/Content.Server/Medical/Stethoscope/StethoscopeSystem.cs @@ -7,11 +7,11 @@ using Content.Shared.Clothing.Components; using Content.Shared.Damage; using Content.Shared.FixedPoint; using Content.Shared.Inventory.Events; -using Content.Shared.MobState.Components; using Content.Shared.Verbs; using Robust.Shared.Player; using System.Threading; -using Content.Server.MobState; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; namespace Content.Server.Medical { diff --git a/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs b/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs index e6bb6d0ebf..e512489dac 100644 --- a/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs +++ b/Content.Server/Medical/SuitSensors/SuitSensorSystem.cs @@ -2,13 +2,13 @@ using Content.Server.Access.Systems; using Content.Server.DeviceNetwork; using Content.Server.DeviceNetwork.Components; using Content.Server.DeviceNetwork.Systems; -using Content.Server.MobState; using Content.Server.Popups; using Content.Shared.Damage; using Content.Shared.Examine; using Content.Shared.Inventory.Events; using Content.Shared.Medical.SuitSensor; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Verbs; using Robust.Shared.Containers; using Robust.Shared.Map; diff --git a/Content.Server/Mind/Mind.cs b/Content.Server/Mind/Mind.cs index 770a6f0311..7924b370bf 100644 --- a/Content.Server/Mind/Mind.cs +++ b/Content.Server/Mind/Mind.cs @@ -4,12 +4,12 @@ using Content.Server.Administration.Logs; using Content.Server.GameTicking; using Content.Server.Ghost.Components; using Content.Server.Mind.Components; -using Content.Server.MobState; using Content.Server.Objectives; using Content.Server.Players; using Content.Server.Roles; using Content.Shared.Database; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Server.GameObjects; using Robust.Server.Player; using Robust.Shared.Network; diff --git a/Content.Server/Mind/MindSystem.cs b/Content.Server/Mind/MindSystem.cs index 232170d368..099a682b01 100644 --- a/Content.Server/Mind/MindSystem.cs +++ b/Content.Server/Mind/MindSystem.cs @@ -2,9 +2,9 @@ using Content.Server.GameTicking; using Content.Server.Ghost; using Content.Server.Ghost.Components; using Content.Server.Mind.Components; -using Content.Server.MobState; using Content.Shared.Examine; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Shared.Map; using Robust.Shared.Timing; diff --git a/Content.Server/MobState/MobStateSystem.Crit.cs b/Content.Server/MobState/MobStateSystem.Crit.cs deleted file mode 100644 index e77015fd9e..0000000000 --- a/Content.Server/MobState/MobStateSystem.Crit.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Content.Shared.StatusEffect; - -namespace Content.Server.MobState; - -public sealed partial class MobStateSystem -{ - public override void EnterCritState(EntityUid uid) - { - base.EnterCritState(uid); - - if (HasComp(uid)) - { - Status.TryRemoveStatusEffect(uid, "Stun"); - } - } -} diff --git a/Content.Server/MobState/MobStateSystem.Dead.cs b/Content.Server/MobState/MobStateSystem.Dead.cs deleted file mode 100644 index 4a4cc09b69..0000000000 --- a/Content.Server/MobState/MobStateSystem.Dead.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Content.Shared.Alert; -using Content.Shared.StatusEffect; - -namespace Content.Server.MobState; - -public sealed partial class MobStateSystem -{ - public override void EnterDeadState(EntityUid uid) - { - base.EnterDeadState(uid); - - Alerts.ShowAlert(uid, AlertType.HumanDead); - - if (HasComp(uid)) - { - Status.TryRemoveStatusEffect(uid, "Stun"); - } - } -} diff --git a/Content.Server/MobState/MobStateSystem.Norm.cs b/Content.Server/MobState/MobStateSystem.Norm.cs deleted file mode 100644 index 605d446ed2..0000000000 --- a/Content.Server/MobState/MobStateSystem.Norm.cs +++ /dev/null @@ -1,29 +0,0 @@ -using Content.Shared.Alert; -using Content.Shared.Damage; -using Content.Shared.FixedPoint; -using Content.Shared.MobState.Components; - -namespace Content.Server.MobState; - -public sealed partial class MobStateSystem -{ - public override void UpdateNormState(EntityUid entity, FixedPoint2 threshold) - { - base.UpdateNormState(entity, threshold); - - if (!TryComp(entity, out var damageable)) - return; - - if (!TryComp(entity, out var stateComponent)) - return; - - short modifier = 0; - - if (TryGetEarliestIncapacitatedState(stateComponent, threshold, out _, out var earliestThreshold) && damageable.TotalDamage != 0) - { - modifier = (short)(damageable.TotalDamage / (earliestThreshold / 5) + 1); - } - - Alerts.ShowAlert(entity, AlertType.HumanHealth, modifier); - } -} diff --git a/Content.Server/MobState/MobStateSystem.cs b/Content.Server/MobState/MobStateSystem.cs deleted file mode 100644 index 9036e04368..0000000000 --- a/Content.Server/MobState/MobStateSystem.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Content.Shared.MobState.Components; -using Content.Shared.MobState.EntitySystems; -using Robust.Shared.GameStates; - -namespace Content.Server.MobState; - -public sealed partial class MobStateSystem : SharedMobStateSystem -{ - public override void Initialize() - { - base.Initialize(); - SubscribeLocalEvent(OnMobGetState); - } - - private void OnMobGetState(EntityUid uid, MobStateComponent component, ref ComponentGetState args) - { - args.State = new MobStateComponentState(component.CurrentThreshold); - } -} diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Melee/MeleeOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Melee/MeleeOperator.cs index 634672ec5d..80516d944d 100644 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Melee/MeleeOperator.cs +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Melee/MeleeOperator.cs @@ -1,8 +1,8 @@ using System.Threading; using System.Threading.Tasks; using Content.Server.NPC.Components; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Melee; @@ -23,7 +23,7 @@ public sealed class MeleeOperator : HTNOperator /// Minimum damage state that the target has to be in for us to consider attacking. /// [DataField("targetState")] - public DamageState TargetState = DamageState.Alive; + public MobState TargetState = MobState.Alive; // Like movement we add a component and pass it off to the dedicated system. diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/NPCCombatOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/NPCCombatOperator.cs index a556c8ccb3..b0b6b8d785 100644 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/NPCCombatOperator.cs +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/NPCCombatOperator.cs @@ -5,8 +5,8 @@ using Content.Server.NPC.Pathfinding; using Content.Server.NPC.Systems; using Content.Shared.Examine; using Content.Shared.Interaction; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Robust.Shared.Map; namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators; @@ -91,7 +91,7 @@ public abstract class NPCCombatOperator : HTNOperator .GetNearbyHostiles(owner, radius)) { if (mobQuery.TryGetComponent(target, out var mobState) && - mobState.CurrentState > DamageState.Alive || + mobState.CurrentState > MobState.Alive || target == existingTarget || target == owner) { diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Ranged/RangedOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Ranged/RangedOperator.cs index fa6976abf2..c4e2fb3afd 100644 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Ranged/RangedOperator.cs +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Ranged/RangedOperator.cs @@ -1,8 +1,8 @@ using System.Threading; using System.Threading.Tasks; using Content.Server.NPC.Components; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Robust.Shared.Audio; namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Ranged; @@ -21,7 +21,7 @@ public sealed class RangedOperator : HTNOperator /// Minimum damage state that the target has to be in for us to consider attacking. /// [DataField("targetState")] - public DamageState TargetState = DamageState.Alive; + public MobState TargetState = MobState.Alive; // Like movement we add a component and pass it off to the dedicated system. diff --git a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/PickNearbyInjectableOperator.cs b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/PickNearbyInjectableOperator.cs index 0da6c092fc..0712ea24b4 100644 --- a/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/PickNearbyInjectableOperator.cs +++ b/Content.Server/NPC/HTN/PrimitiveTasks/Operators/Specific/PickNearbyInjectableOperator.cs @@ -5,7 +5,7 @@ using Content.Server.NPC.Components; using Content.Server.NPC.Pathfinding; using Content.Shared.Damage; using Content.Shared.Interaction; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; namespace Content.Server.NPC.HTN.PrimitiveTasks.Operators.Specific; diff --git a/Content.Server/NPC/Systems/NPCSystem.cs b/Content.Server/NPC/Systems/NPCSystem.cs index 1f753de767..0689d5fdf4 100644 --- a/Content.Server/NPC/Systems/NPCSystem.cs +++ b/Content.Server/NPC/Systems/NPCSystem.cs @@ -1,8 +1,8 @@ -using Content.Server.MobState; using Content.Server.NPC.Components; using Content.Server.NPC.HTN; using Content.Shared.CCVar; -using Content.Shared.MobState; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Systems; using JetBrains.Annotations; using Robust.Server.GameObjects; using Robust.Shared.Configuration; @@ -131,13 +131,13 @@ namespace Content.Server.NPC.Systems if (HasComp(uid)) return; - switch (args.CurrentMobState) + switch (args.NewMobState) { - case DamageState.Alive: + case MobState.Alive: WakeNPC(uid, component); break; - case DamageState.Critical: - case DamageState.Dead: + case MobState.Critical: + case MobState.Dead: SleepNPC(uid, component); break; } diff --git a/Content.Server/Nuke/NukeComponent.cs b/Content.Server/Nuke/NukeComponent.cs index d92b9c7b17..16cfc3919d 100644 --- a/Content.Server/Nuke/NukeComponent.cs +++ b/Content.Server/Nuke/NukeComponent.cs @@ -1,4 +1,5 @@ using System.Threading; +using Content.Server.Explosion.EntitySystems; using Content.Shared.Containers.ItemSlots; using Content.Shared.Explosion; using Content.Shared.Nuke; diff --git a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs index 49883f93bd..1681d351b4 100644 --- a/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/DrinkSystem.cs @@ -5,7 +5,6 @@ using Content.Server.Chemistry.Components.SolutionManager; using Content.Server.Chemistry.EntitySystems; using Content.Server.DoAfter; using Content.Server.Fluids.EntitySystems; -using Content.Server.MobState; using Content.Server.Nutrition.Components; using Content.Server.Popups; using Content.Shared.Administration.Logs; @@ -17,7 +16,8 @@ using Content.Shared.FixedPoint; using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Nutrition.Components; using Content.Shared.Throwing; using Content.Shared.Verbs; diff --git a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs index 76488ab09a..bb28d02f6e 100644 --- a/Content.Server/Nutrition/EntitySystems/FoodSystem.cs +++ b/Content.Server/Nutrition/EntitySystems/FoodSystem.cs @@ -4,7 +4,6 @@ using Content.Server.Body.Systems; using Content.Server.Chemistry.EntitySystems; using Content.Server.DoAfter; using Content.Server.Hands.Components; -using Content.Server.MobState; using Content.Server.Nutrition.Components; using Content.Server.Popups; using Content.Shared.Administration.Logs; @@ -17,7 +16,8 @@ using Content.Shared.IdentityManagement; using Content.Shared.Interaction; using Content.Shared.Interaction.Events; using Content.Shared.Inventory; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Verbs; using Robust.Shared.Audio; using Robust.Shared.Player; diff --git a/Content.Server/Objectives/Conditions/KillPersonCondition.cs b/Content.Server/Objectives/Conditions/KillPersonCondition.cs index b87b538a8e..2ae101f40f 100644 --- a/Content.Server/Objectives/Conditions/KillPersonCondition.cs +++ b/Content.Server/Objectives/Conditions/KillPersonCondition.cs @@ -1,5 +1,5 @@ -using Content.Server.MobState; using Content.Server.Objectives.Interfaces; +using Content.Shared.Mobs.Systems; using Robust.Shared.Utility; namespace Content.Server.Objectives.Conditions diff --git a/Content.Server/Objectives/Conditions/KillRandomPersonCondition.cs b/Content.Server/Objectives/Conditions/KillRandomPersonCondition.cs index ed08937dc6..5cdef407dd 100644 --- a/Content.Server/Objectives/Conditions/KillRandomPersonCondition.cs +++ b/Content.Server/Objectives/Conditions/KillRandomPersonCondition.cs @@ -1,7 +1,7 @@ using System.Linq; using Content.Server.Mind.Components; using Content.Server.Objectives.Interfaces; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using JetBrains.Annotations; using Robust.Shared.Random; diff --git a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs index 5ecaaed4cb..1ff9eeee49 100644 --- a/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs +++ b/Content.Server/Players/PlayTimeTracking/PlayTimeTrackingSystem.cs @@ -5,8 +5,8 @@ using Content.Server.GameTicking; using Content.Server.Roles; using Content.Shared.CCVar; using Content.Shared.GameTicking; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Content.Shared.Players.PlayTimeTracking; using Content.Shared.Roles; using Robust.Server.GameObjects; @@ -74,7 +74,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem if (!TryComp(attached, out var state)) return false; - return state.CurrentState is DamageState.Alive or DamageState.Critical; + return state.CurrentState is MobState.Alive or MobState.Critical; } public IEnumerable GetTimedRoles(Mind.Mind mind) @@ -142,7 +142,7 @@ public sealed class PlayTimeTrackingSystem : EntitySystem private void OnMobStateChanged(MobStateChangedEvent ev) { - if (!TryComp(ev.Entity, out ActorComponent? actor)) + if (!TryComp(ev.Target, out ActorComponent? actor)) return; _tracking.QueueRefreshTrackers(actor.PlayerSession); diff --git a/Content.Server/Pointing/EntitySystems/PointingSystem.cs b/Content.Server/Pointing/EntitySystems/PointingSystem.cs index 31a7e59cb0..28ea433dc9 100644 --- a/Content.Server/Pointing/EntitySystems/PointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/PointingSystem.cs @@ -1,4 +1,3 @@ -using System; using System.Linq; using Content.Server.Administration.Logs; using Content.Server.Ghost.Components; @@ -11,7 +10,7 @@ using Content.Shared.IdentityManagement; using Content.Shared.Input; using Content.Shared.Interaction; using Content.Shared.Interaction.Helpers; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Systems; using Content.Shared.Pointing; using Content.Shared.Popups; using JetBrains.Annotations; @@ -36,7 +35,7 @@ namespace Content.Server.Pointing.EntitySystems [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; [Dependency] private readonly RotateToFaceSystem _rotateToFaceSystem = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly VisibilitySystem _visibilitySystem = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; diff --git a/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs b/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs index 45ccb0cefb..e82ccd67b6 100644 --- a/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs +++ b/Content.Server/Pointing/EntitySystems/RoguePointingSystem.cs @@ -1,7 +1,6 @@ using System.Linq; using Content.Server.Explosion.EntitySystems; using Content.Server.Pointing.Components; -using Content.Shared.MobState.Components; using Content.Shared.Pointing.Components; using JetBrains.Annotations; using Robust.Server.GameObjects; diff --git a/Content.Server/Polymorph/Systems/PolymorphableSystem.cs b/Content.Server/Polymorph/Systems/PolymorphableSystem.cs index a7c6914601..7008bfb28d 100644 --- a/Content.Server/Polymorph/Systems/PolymorphableSystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphableSystem.cs @@ -9,6 +9,7 @@ using Content.Shared.Actions; using Content.Shared.Actions.ActionTypes; using Content.Shared.Damage; using Content.Shared.Hands.EntitySystems; +using Content.Shared.Mobs.Systems; using Content.Shared.Polymorph; using Robust.Server.Containers; using Robust.Shared.Containers; @@ -29,6 +30,7 @@ namespace Content.Server.Polymorph.Systems [Dependency] private readonly ServerInventorySystem _inventory = default!; [Dependency] private readonly SharedHandsSystem _sharedHands = default!; [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!; [Dependency] private readonly IMapManager _mapManager = default!; [Dependency] private readonly HumanoidSystem _humanoid = default!; [Dependency] private readonly ContainerSystem _container = default!; @@ -114,7 +116,7 @@ namespace Content.Server.Polymorph.Systems //Transfers all damage from the original to the new one if (proto.TransferDamage && TryComp(child, out var damageParent) && - _damageable.GetScaledDamage(target, child, out var damage) && + _mobThresholdSystem.GetScaledDamage(target, child, out var damage) && damage != null) { _damageable.SetDamage(damageParent, damage); diff --git a/Content.Server/Polymorph/Systems/PolymorphedEntitySystem.cs b/Content.Server/Polymorph/Systems/PolymorphedEntitySystem.cs index fb58ac2135..965a053638 100644 --- a/Content.Server/Polymorph/Systems/PolymorphedEntitySystem.cs +++ b/Content.Server/Polymorph/Systems/PolymorphedEntitySystem.cs @@ -1,7 +1,6 @@ using Content.Server.Actions; using Content.Server.Inventory; using Content.Server.Mind.Components; -using Content.Server.MobState; using Content.Server.Polymorph.Components; using Content.Server.Popups; using Content.Shared.Actions; @@ -9,7 +8,8 @@ using Content.Shared.Actions.ActionTypes; using Content.Shared.Damage; using Content.Shared.Hands.EntitySystems; using Content.Shared.IdentityManagement; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Polymorph; using Robust.Server.Containers; using Robust.Shared.Containers; @@ -23,6 +23,7 @@ namespace Content.Server.Polymorph.Systems [Dependency] private readonly IPrototypeManager _proto = default!; [Dependency] private readonly ActionsSystem _actions = default!; [Dependency] private readonly DamageableSystem _damageable = default!; + [Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!; [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly ServerInventorySystem _inventory = default!; [Dependency] private readonly SharedHandsSystem _sharedHands = default!; @@ -75,7 +76,7 @@ namespace Content.Server.Polymorph.Systems if (proto.TransferDamage && TryComp(component.Parent, out var damageParent) && - _damageable.GetScaledDamage(uid, component.Parent, out var damage) && + _mobThresholdSystem.GetScaledDamage(uid, component.Parent, out var damage) && damage != null) { _damageable.SetDamage(damageParent, damage); diff --git a/Content.Server/Revenant/EntitySystems/EssenceSystem.cs b/Content.Server/Revenant/EntitySystems/EssenceSystem.cs index facbd1ba5a..a466573344 100644 --- a/Content.Server/Revenant/EntitySystems/EssenceSystem.cs +++ b/Content.Server/Revenant/EntitySystems/EssenceSystem.cs @@ -1,8 +1,8 @@ using Content.Server.Mind.Components; using Content.Server.Revenant.Components; using Content.Shared.Examine; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Content.Shared.Revenant.Components; using Robust.Shared.Random; @@ -20,13 +20,18 @@ public sealed class EssenceSystem : EntitySystem { base.Initialize(); - SubscribeLocalEvent(UpdateEssenceAmount); - SubscribeLocalEvent(UpdateEssenceAmount); - SubscribeLocalEvent(UpdateEssenceAmount); - SubscribeLocalEvent(UpdateEssenceAmount); + SubscribeLocalEvent(OnEssenceEventReceived); + SubscribeLocalEvent(OnMobstateChanged); + SubscribeLocalEvent(OnEssenceEventReceived); + SubscribeLocalEvent(OnEssenceEventReceived); SubscribeLocalEvent(OnExamine); } + private void OnMobstateChanged(EntityUid uid, EssenceComponent component, MobStateChangedEvent args) + { + UpdateEssenceAmount(uid, component); + } + private void OnExamine(EntityUid uid, EssenceComponent component, ExaminedEvent args) { if (!component.SearchComplete || !HasComp(args.Examiner)) @@ -49,23 +54,28 @@ public sealed class EssenceSystem : EntitySystem args.PushMarkup(Loc.GetString(message, ("target", uid))); } - private void UpdateEssenceAmount(EntityUid uid, EssenceComponent component, EntityEventArgs args) + private void OnEssenceEventReceived(EntityUid uid, EssenceComponent component, EntityEventArgs args) + { + UpdateEssenceAmount(uid, component); + } + + private void UpdateEssenceAmount(EntityUid uid, EssenceComponent component) { if (!TryComp(uid, out var mob)) return; switch (mob.CurrentState) { - case DamageState.Alive: + case MobState.Alive: if (TryComp(uid, out var mind) && mind.Mind != null) component.EssenceAmount = _random.NextFloat(75f, 100f); else component.EssenceAmount = _random.NextFloat(45f, 70f); break; - case DamageState.Critical: + case MobState.Critical: component.EssenceAmount = _random.NextFloat(35f, 50f); break; - case DamageState.Dead: + case MobState.Dead: component.EssenceAmount = _random.NextFloat(15f, 20f); break; } diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs index b2b8c04bf8..c48e744fca 100644 --- a/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs +++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.Abilities.cs @@ -1,10 +1,8 @@ using Content.Shared.Popups; using Content.Shared.Damage; -using Content.Shared.MobState.Components; using Content.Server.DoAfter; using Content.Shared.Revenant; using Robust.Shared.Random; -using Robust.Shared.Player; using Robust.Shared.Map; using Content.Shared.Tag; using Content.Shared.Maps; @@ -19,7 +17,6 @@ using Content.Server.Disease; using Content.Server.Disease.Components; using Content.Shared.Item; using Content.Shared.Bed.Sleep; -using Content.Shared.MobState; using System.Linq; using Content.Server.Beam; using Content.Server.Emag; @@ -29,6 +26,9 @@ using Content.Server.Revenant.Components; using Content.Server.Store.Components; using Content.Shared.FixedPoint; using Content.Shared.Humanoid; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Revenant.Components; using Robust.Shared.Physics.Components; using Robust.Shared.Utility; @@ -43,6 +43,7 @@ public sealed partial class RevenantSystem [Dependency] private readonly DiseaseSystem _disease = default!; [Dependency] private readonly EmagSystem _emag = default!; [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly MobThresholdSystem _mobThresholdSystem = default!; [Dependency] private readonly GhostSystem _ghost = default!; [Dependency] private readonly TileSystem _tile = default!; @@ -143,7 +144,7 @@ public sealed partial class RevenantSystem return; } - if (TryComp(target, out var mobstate) && mobstate.CurrentState == DamageState.Alive && !HasComp(target)) + if (TryComp(target, out var mobstate) && mobstate.CurrentState == MobState.Alive && !HasComp(target)) { _popup.PopupEntity(Loc.GetString("revenant-soul-too-powerful"), target, uid); return; @@ -197,8 +198,8 @@ public sealed partial class RevenantSystem } //KILL THEMMMM - var damage = _mobState.GetEarliestDeadState(mobstate, 0)?.threshold; - if (damage == null) + + if (!_mobThresholdSystem.TryGetThresholdForState(args.Target, MobState.Dead, out var damage)) return; DamageSpecifier dspec = new(); dspec.DamageDict.Add("Poison", damage.Value); diff --git a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs index 29cccb95dc..8b1529ea42 100644 --- a/Content.Server/Revenant/EntitySystems/RevenantSystem.cs +++ b/Content.Server/Revenant/EntitySystems/RevenantSystem.cs @@ -10,7 +10,6 @@ using Content.Shared.Revenant; using Robust.Server.GameObjects; using Robust.Shared.Random; using Content.Shared.StatusEffect; -using Content.Server.MobState; using Content.Server.Visible; using Content.Shared.Examine; using Robust.Shared.Prototypes; @@ -21,6 +20,7 @@ using Content.Server.Store.Systems; using Content.Shared.FixedPoint; using Robust.Shared.Player; using Content.Shared.Maps; +using Content.Shared.Mobs.Systems; using Content.Shared.Physics; using Content.Shared.Revenant.Components; diff --git a/Content.Server/Salvage/SalvageMobRestrictionsSystem.cs b/Content.Server/Salvage/SalvageMobRestrictionsSystem.cs index 76b7d2dbed..c176d9684a 100644 --- a/Content.Server/Salvage/SalvageMobRestrictionsSystem.cs +++ b/Content.Server/Salvage/SalvageMobRestrictionsSystem.cs @@ -1,7 +1,7 @@ using Content.Server.Body.Systems; -using Content.Server.MobState; using Content.Shared.Body.Components; using Content.Shared.Damage; +using Content.Shared.Mobs.Systems; namespace Content.Server.Salvage; diff --git a/Content.Server/StationEvents/Events/DiseaseOutbreak.cs b/Content.Server/StationEvents/Events/DiseaseOutbreak.cs index 30fe26f31e..3c829ddfab 100644 --- a/Content.Server/StationEvents/Events/DiseaseOutbreak.cs +++ b/Content.Server/StationEvents/Events/DiseaseOutbreak.cs @@ -1,9 +1,8 @@ using Content.Server.Disease; using Content.Server.Disease.Components; -using Content.Server.MobState; -using Content.Server.Station.Systems; using Content.Shared.Disease; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Robust.Shared.Random; namespace Content.Server.StationEvents.Events; diff --git a/Content.Server/Storage/Components/SecretStashComponent.cs b/Content.Server/Storage/Components/SecretStashComponent.cs index 79f3c985bc..1d7c75ae3e 100644 --- a/Content.Server/Storage/Components/SecretStashComponent.cs +++ b/Content.Server/Storage/Components/SecretStashComponent.cs @@ -1,6 +1,7 @@ using Content.Server.Storage.EntitySystems; using Content.Shared.Containers.ItemSlots; using Content.Shared.Item; +using Content.Shared.Toilet; using Robust.Shared.Containers; namespace Content.Server.Storage.Components diff --git a/Content.Server/Suspicion/SuspicionRoleComponent.cs b/Content.Server/Suspicion/SuspicionRoleComponent.cs index db22d76366..59964254c8 100644 --- a/Content.Server/Suspicion/SuspicionRoleComponent.cs +++ b/Content.Server/Suspicion/SuspicionRoleComponent.cs @@ -1,10 +1,10 @@ using System.Linq; using Content.Server.GameTicking.Rules; using Content.Server.Mind.Components; -using Content.Server.MobState; using Content.Server.Roles; using Content.Server.Suspicion.Roles; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Suspicion; namespace Content.Server.Suspicion @@ -13,7 +13,6 @@ namespace Content.Server.Suspicion public sealed class SuspicionRoleComponent : SharedSuspicionRoleComponent { [Dependency] private readonly IEntityManager _entMan = default!; - private Role? _role; [ViewVariables] private readonly HashSet _allies = new(); diff --git a/Content.Server/Vehicle/VehicleSystem.Rider.cs b/Content.Server/Vehicle/VehicleSystem.Rider.cs index b79ef3a047..eb835e3b9c 100644 --- a/Content.Server/Vehicle/VehicleSystem.Rider.cs +++ b/Content.Server/Vehicle/VehicleSystem.Rider.cs @@ -1,6 +1,6 @@ using Content.Server.Standing; using Content.Shared.Hands; -using Content.Shared.MobState; +using Content.Shared.Mobs; using Content.Shared.Vehicle.Components; using Robust.Shared.GameStates; @@ -48,7 +48,7 @@ namespace Content.Server.Vehicle /// private void OnMobStateChanged(EntityUid uid, RiderComponent rider, MobStateChangedEvent args) { - if (args.CurrentMobState is DamageState.Critical or DamageState.Dead) + if (args.NewMobState is MobState.Critical or MobState.Dead) { UnbuckleFromVehicle(uid); } diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/ShuffleArtifactSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/ShuffleArtifactSystem.cs index 93b01d68da..ed1eda92c3 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/ShuffleArtifactSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Effects/Systems/ShuffleArtifactSystem.cs @@ -1,6 +1,6 @@ using Content.Server.Xenoarchaeology.XenoArtifacts.Effects.Components; using Content.Server.Xenoarchaeology.XenoArtifacts.Events; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Robust.Shared.Map; using Robust.Shared.Random; diff --git a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactDeathTriggerSystem.cs b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactDeathTriggerSystem.cs index b3b5528244..4fa21535a4 100644 --- a/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactDeathTriggerSystem.cs +++ b/Content.Server/Xenoarchaeology/XenoArtifacts/Triggers/Systems/ArtifactDeathTriggerSystem.cs @@ -1,5 +1,5 @@ using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components; -using Content.Shared.MobState; +using Content.Shared.Mobs; namespace Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Systems; @@ -15,10 +15,10 @@ public sealed class ArtifactDeathTriggerSystem : EntitySystem private void OnMobStateChanged(MobStateChangedEvent ev) { - if (ev.CurrentMobState != DamageState.Dead) + if (ev.NewMobState != MobState.Dead) return; - var deathXform = Transform(ev.Entity); + var deathXform = Transform(ev.Target); var toActivate = new List(); foreach (var (trigger, xform) in EntityQuery()) diff --git a/Content.Server/Zombies/ZombieSystem.cs b/Content.Server/Zombies/ZombieSystem.cs index 28e61cac04..c1be8c5975 100644 --- a/Content.Server/Zombies/ZombieSystem.cs +++ b/Content.Server/Zombies/ZombieSystem.cs @@ -13,8 +13,8 @@ using Content.Shared.Bed.Sleep; using Content.Shared.Damage; using Content.Shared.Disease.Events; using Content.Shared.Inventory; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Content.Shared.Weapons.Melee.Events; using Content.Shared.Zombies; using Robust.Shared.Prototypes; @@ -52,7 +52,7 @@ namespace Content.Server.Zombies private void OnMobState(EntityUid uid, ZombieComponent component, MobStateChangedEvent args) { - if (args.CurrentMobState == DamageState.Alive) + if (args.NewMobState == MobState.Alive) EnsureComp(uid); else RemComp(uid); @@ -126,13 +126,13 @@ namespace Content.Server.Zombies if (HasComp(entity)) args.BonusDamage = -args.BaseDamage * zombieComp.OtherZombieDamageCoefficient; - if ((mobState.CurrentState == DamageState.Dead || mobState.CurrentState == DamageState.Critical) + if ((mobState.CurrentState == MobState.Dead || mobState.CurrentState == MobState.Critical) && !HasComp(entity)) { _zombify.ZombifyEntity(entity); args.BonusDamage = -args.BaseDamage; } - else if (mobState.CurrentState == DamageState.Alive) //heals when zombies bite live entities + else if (mobState.CurrentState == MobState.Alive) //heals when zombies bite live entities { var healingSolution = new Solution(); healingSolution.AddReagent("Bicaridine", 1.00); //if OP, reduce/change chem diff --git a/Content.Server/Zombies/ZombifyOnDeathSystem.cs b/Content.Server/Zombies/ZombifyOnDeathSystem.cs index 042ff30a71..31fa840d9b 100644 --- a/Content.Server/Zombies/ZombifyOnDeathSystem.cs +++ b/Content.Server/Zombies/ZombifyOnDeathSystem.cs @@ -17,7 +17,6 @@ using Content.Server.Hands.Components; using Content.Server.Mind.Commands; using Content.Server.Temperature.Components; using Content.Shared.Movement.Components; -using Content.Shared.MobState; using Robust.Shared.Prototypes; using Content.Shared.Roles; using Content.Server.Traitor; @@ -27,6 +26,7 @@ using Content.Server.Atmos.Miasma; using Content.Server.Humanoid; using Content.Server.IdentityManagement; using Content.Shared.Humanoid; +using Content.Shared.Mobs; using Content.Shared.Movement.Systems; using Content.Shared.Weapons.Melee; using Robust.Shared.Audio; @@ -64,8 +64,8 @@ namespace Content.Server.Zombies /// private void OnDamageChanged(EntityUid uid, ZombifyOnDeathComponent component, MobStateChangedEvent args) { - if (args.CurrentMobState == DamageState.Dead || - args.CurrentMobState == DamageState.Critical) + if (args.NewMobState == MobState.Dead || + args.NewMobState == MobState.Critical) { ZombifyEntity(uid); } diff --git a/Content.Shared/Alert/AlertsSystem.cs b/Content.Shared/Alert/AlertsSystem.cs index 1969ed6f01..5ba0bf3bcd 100644 --- a/Content.Shared/Alert/AlertsSystem.cs +++ b/Content.Shared/Alert/AlertsSystem.cs @@ -7,7 +7,6 @@ namespace Content.Shared.Alert; public abstract class AlertsSystem : EntitySystem { [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - private readonly Dictionary _typeToAlert = new(); public IReadOnlyDictionary? GetActiveAlerts(EntityUid euid) @@ -17,6 +16,16 @@ public abstract class AlertsSystem : EntitySystem : null; } + public short GetMaxSeverity(AlertType alertType) + { + return _typeToAlert[alertType].MaxSeverity; + } + + public short GetMinSeverity(AlertType alertType) + { + return _typeToAlert[alertType].MinSeverity; + } + public bool IsShowingAlert(EntityUid euid, AlertType alertType) { if (!EntityManager.TryGetComponent(euid, out AlertsComponent? alertsComponent)) diff --git a/Content.Shared/Blocking/BlockingSystem.cs b/Content.Shared/Blocking/BlockingSystem.cs index 3bb4f08cb7..923c75e02d 100644 --- a/Content.Shared/Blocking/BlockingSystem.cs +++ b/Content.Shared/Blocking/BlockingSystem.cs @@ -8,7 +8,7 @@ using Content.Shared.Hands.EntitySystems; using Content.Shared.IdentityManagement; using Content.Shared.Interaction.Events; using Content.Shared.Maps; -using Content.Shared.MobState.Components; +using Content.Shared.Mobs.Components; using Content.Shared.Physics; using Content.Shared.Popups; using Content.Shared.Toggleable; diff --git a/Content.Shared/Damage/Systems/DamageableSystem.cs b/Content.Shared/Damage/Systems/DamageableSystem.cs index 3e33d113d6..7b4b0b2d2d 100644 --- a/Content.Shared/Damage/Systems/DamageableSystem.cs +++ b/Content.Shared/Damage/Systems/DamageableSystem.cs @@ -2,8 +2,6 @@ using System.Linq; using Content.Shared.Damage.Prototypes; using Content.Shared.FixedPoint; using Content.Shared.Inventory; -using Content.Shared.MobState; -using Content.Shared.MobState.Components; using Content.Shared.Radiation.Events; using Content.Shared.Rejuvenate; using Robust.Shared.GameStates; @@ -283,45 +281,6 @@ namespace Content.Shared.Damage DamageChanged(component, delta); } } - - /// - /// Takes the damage from one entity and scales it relative to the health of another - /// - /// The entity whose damage will be scaled - /// The entity whose health the damage will scale to - /// The newly scaled damage. Can be null - public bool GetScaledDamage(EntityUid ent1, EntityUid ent2, out DamageSpecifier? damage) - { - damage = null; - - if (!TryComp(ent1, out var olddamage)) - return false; - - if (!TryComp(ent1, out var oldstate) || - !TryComp(ent2, out var newstate)) - return false; - - int ent1DeadState = 0; - foreach (var state in oldstate._highestToLowestStates) - { - if (state.Value == DamageState.Dead) - { - ent1DeadState = state.Key; - } - } - - int ent2DeadState = 0; - foreach (var state in newstate._highestToLowestStates) - { - if (state.Value == DamageState.Dead) - { - ent2DeadState = state.Key; - } - } - - damage = (olddamage.Damage / ent1DeadState) * ent2DeadState; - return true; - } } /// diff --git a/Content.Shared/Disposal/SharedDisposalUnitSystem.cs b/Content.Shared/Disposal/SharedDisposalUnitSystem.cs index 3fc690a0e7..e0312a7af3 100644 --- a/Content.Shared/Disposal/SharedDisposalUnitSystem.cs +++ b/Content.Shared/Disposal/SharedDisposalUnitSystem.cs @@ -2,8 +2,8 @@ using Content.Shared.Disposal.Components; using Content.Shared.DragDrop; using Content.Shared.Item; -using Content.Shared.MobState.Components; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Throwing; using JetBrains.Annotations; using Robust.Shared.Physics.Components; @@ -16,7 +16,7 @@ namespace Content.Shared.Disposal public abstract class SharedDisposalUnitSystem : EntitySystem { [Dependency] protected readonly IGameTiming GameTiming = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; protected static TimeSpan ExitAttemptDelay = TimeSpan.FromSeconds(0.5); diff --git a/Content.Shared/Examine/ExamineSystemShared.cs b/Content.Shared/Examine/ExamineSystemShared.cs index e80b50541d..385ef88880 100644 --- a/Content.Shared/Examine/ExamineSystemShared.cs +++ b/Content.Shared/Examine/ExamineSystemShared.cs @@ -1,9 +1,9 @@ using System.Linq; using Content.Shared.DragDrop; using Content.Shared.Interaction; -using Content.Shared.MobState.Components; using Content.Shared.Eye.Blinding; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using JetBrains.Annotations; using Robust.Shared.Containers; using Robust.Shared.Map; @@ -17,7 +17,7 @@ namespace Content.Shared.Examine { [Dependency] private readonly SharedContainerSystem _containerSystem = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; - [Dependency] protected readonly SharedMobStateSystem MobStateSystem = default!; + [Dependency] protected readonly MobStateSystem MobStateSystem = default!; public const float MaxRaycastRange = 100; diff --git a/Content.Shared/Interaction/RotateToFaceSystem.cs b/Content.Shared/Interaction/RotateToFaceSystem.cs index 2f0ae4a416..4bd388f595 100644 --- a/Content.Shared/Interaction/RotateToFaceSystem.cs +++ b/Content.Shared/Interaction/RotateToFaceSystem.cs @@ -1,8 +1,8 @@ using Content.Shared.ActionBlocker; using Content.Shared.Buckle.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Rotatable; using JetBrains.Annotations; -using Content.Shared.MobState.EntitySystems; namespace Content.Shared.Interaction { @@ -16,7 +16,7 @@ namespace Content.Shared.Interaction public sealed class RotateToFaceSystem : EntitySystem { [Dependency] private readonly ActionBlockerSystem _actionBlockerSystem = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; /// diff --git a/Content.Shared/Medical/Cryogenics/SharedCryoPodSystem.cs b/Content.Shared/Medical/Cryogenics/SharedCryoPodSystem.cs index b9829f2ec6..d29f6c277e 100644 --- a/Content.Shared/Medical/Cryogenics/SharedCryoPodSystem.cs +++ b/Content.Shared/Medical/Cryogenics/SharedCryoPodSystem.cs @@ -1,8 +1,7 @@ using Content.Server.Medical.Components; -using Content.Shared.Destructible; using Content.Shared.Emag.Systems; -using Content.Shared.MobState.Components; -using Content.Shared.MobState.EntitySystems; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Popups; using Content.Shared.Standing; using Content.Shared.Stunnable; @@ -16,7 +15,7 @@ public abstract partial class SharedCryoPodSystem: EntitySystem { [Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!; [Dependency] private readonly StandingStateSystem _standingStateSystem = default!; - [Dependency] private readonly SharedMobStateSystem _mobStateSystem = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedContainerSystem _containerSystem = default!; diff --git a/Content.Shared/MobState/Components/MobStateComponent.cs b/Content.Shared/MobState/Components/MobStateComponent.cs deleted file mode 100644 index 25f2749384..0000000000 --- a/Content.Shared/MobState/Components/MobStateComponent.cs +++ /dev/null @@ -1,39 +0,0 @@ -using System.Linq; -using Content.Shared.Damage; -using Content.Shared.FixedPoint; -using Content.Shared.MobState.EntitySystems; -using Robust.Shared.GameStates; - -namespace Content.Shared.MobState.Components -{ - /// - /// When attached to an , - /// this component will handle critical and death behaviors for mobs. - /// Additionally, it handles sending effects to clients - /// (such as blur effect for unconsciousness) and managing the health HUD. - /// - [RegisterComponent] - [NetworkedComponent] - [Access(typeof(SharedMobStateSystem))] - public sealed class MobStateComponent : Component - { - /// - /// States that this mapped to - /// the amount of damage at which they are triggered. - /// A threshold is reached when the total damage of an entity is equal - /// to or higher than the int key, but lower than the next threshold. - /// Ordered from lowest to highest. - /// - [DataField("thresholds")] - public readonly SortedDictionary _lowestToHighestStates = new(); - - // TODO Remove Nullability? - [ViewVariables] - public DamageState? CurrentState { get; set; } - - [ViewVariables] - public FixedPoint2? CurrentThreshold { get; set; } - - public IEnumerable> _highestToLowestStates => _lowestToHighestStates.Reverse(); - } -} diff --git a/Content.Shared/MobState/DamageStateHelpers.cs b/Content.Shared/MobState/DamageStateHelpers.cs deleted file mode 100644 index 2b512f0c76..0000000000 --- a/Content.Shared/MobState/DamageStateHelpers.cs +++ /dev/null @@ -1,23 +0,0 @@ -namespace Content.Shared.MobState -{ - public static class DamageStateHelpers - { - /// - /// Enumerates over , returning them in order - /// of alive to dead. - /// - /// An enumerable of . - public static IEnumerable AliveToDead() - { - foreach (DamageState state in Enum.GetValues(typeof(DamageState))) - { - if (state == DamageState.Invalid) - { - continue; - } - - yield return state; - } - } - } -} diff --git a/Content.Shared/MobState/DamageStateVisuals.cs b/Content.Shared/MobState/DamageStateVisuals.cs deleted file mode 100644 index a5ef1d9835..0000000000 --- a/Content.Shared/MobState/DamageStateVisuals.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Robust.Shared.Serialization; - -namespace Content.Shared.MobState -{ - [Serializable, NetSerializable] - public enum DamageStateVisuals : byte - { - State - } - - /// - /// Defines what state an is in. - /// - /// Ordered from most alive to least alive. - /// To enumerate them in this way see - /// . - /// - [Serializable, NetSerializable] - public enum DamageState : byte - { - Invalid = 0, - Alive = 1, - Critical = 2, - Dead = 3 - } -} diff --git a/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.Crit.cs b/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.Crit.cs deleted file mode 100644 index 36e9624233..0000000000 --- a/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.Crit.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Content.Shared.Alert; -using Content.Shared.FixedPoint; - -namespace Content.Shared.MobState.EntitySystems; - -public abstract partial class SharedMobStateSystem -{ - public virtual void EnterCritState(EntityUid uid) - { - Alerts.ShowAlert(uid, AlertType.HumanCrit); - _standing.Down(uid); - _appearance.SetData(uid, DamageStateVisuals.State, DamageState.Critical); - } - - public virtual void ExitCritState(EntityUid uid) - { - _standing.Stand(uid); - } - - public virtual void UpdateCritState(EntityUid entity, FixedPoint2 threshold) {} -} diff --git a/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.Dead.cs b/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.Dead.cs deleted file mode 100644 index 477c510514..0000000000 --- a/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.Dead.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Content.Shared.FixedPoint; -using Robust.Shared.Physics.Components; - -namespace Content.Shared.MobState.EntitySystems; - -public abstract partial class SharedMobStateSystem -{ - public virtual void EnterDeadState(EntityUid uid) - { - EnsureComp(uid); - _standing.Down(uid); - - if (_standing.IsDown(uid) && TryComp(uid, out var physics)) - { - _physics.SetCanCollide(physics, false); - } - - _appearance.SetData(uid, DamageStateVisuals.State, DamageState.Dead); - } - - public virtual void ExitDeadState(EntityUid uid) - { - RemComp(uid); - - _standing.Stand(uid); - - if (!_standing.IsDown(uid) && TryComp(uid, out var physics)) - { - _physics.SetCanCollide(physics, true); - } - } - - public virtual void UpdateDeadState(EntityUid entity, FixedPoint2 threshold) {} -} diff --git a/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.Norm.cs b/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.Norm.cs deleted file mode 100644 index c24937db6f..0000000000 --- a/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.Norm.cs +++ /dev/null @@ -1,16 +0,0 @@ -using Content.Shared.FixedPoint; - -namespace Content.Shared.MobState.EntitySystems; - -public abstract partial class SharedMobStateSystem -{ - public virtual void EnterNormState(EntityUid uid) - { - _standing.Stand(uid); - _appearance.SetData(uid, DamageStateVisuals.State, DamageState.Alive); - } - - public virtual void UpdateNormState(EntityUid entity, FixedPoint2 threshold) {} - - public virtual void ExitNormState(EntityUid uid) {} -} diff --git a/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.cs b/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.cs deleted file mode 100644 index 3e98da62ea..0000000000 --- a/Content.Shared/MobState/EntitySystems/SharedMobStateSystem.cs +++ /dev/null @@ -1,512 +0,0 @@ -using System.Diagnostics.CodeAnalysis; -using Content.Shared.ActionBlocker; -using Content.Shared.Administration.Logs; -using Content.Shared.Alert; -using Content.Shared.Bed.Sleep; -using Content.Shared.Damage; -using Content.Shared.Database; -using Content.Shared.Disease.Events; -using Content.Shared.DragDrop; -using Content.Shared.Emoting; -using Content.Shared.FixedPoint; -using Content.Shared.Interaction.Events; -using Content.Shared.Inventory.Events; -using Content.Shared.Item; -using Content.Shared.MobState.Components; -using Content.Shared.Movement.Events; -using Content.Shared.Pulling.Events; -using Content.Shared.Speech; -using Content.Shared.Standing; -using Content.Shared.StatusEffect; -using Content.Shared.Strip.Components; -using Content.Shared.Throwing; -using Robust.Shared.Physics.Systems; -using Robust.Shared.Serialization; - -namespace Content.Shared.MobState.EntitySystems -{ - public abstract partial class SharedMobStateSystem : EntitySystem - { - [Dependency] protected readonly AlertsSystem Alerts = default!; - [Dependency] private readonly ActionBlockerSystem _blocker = default!; - [Dependency] private readonly SharedAppearanceSystem _appearance = default!; - [Dependency] private readonly SharedPhysicsSystem _physics = default!; - [Dependency] protected readonly StatusEffectsSystem Status = default!; - [Dependency] private readonly StandingStateSystem _standing = default!; - [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; - - public override void Initialize() - { - base.Initialize(); - - SubscribeLocalEvent(OnMobShutdown); - SubscribeLocalEvent(OnMobStartup); - - SubscribeLocalEvent(OnGettingStripped); - - SubscribeLocalEvent(OnChangeDirectionAttempt); - SubscribeLocalEvent(OnUseAttempt); - SubscribeLocalEvent(OnInteractAttempt); - SubscribeLocalEvent(OnThrowAttempt); - SubscribeLocalEvent(OnSpeakAttempt); - SubscribeLocalEvent(OnEquipAttempt); - SubscribeLocalEvent(OnEmoteAttempt); - SubscribeLocalEvent(OnUnequipAttempt); - SubscribeLocalEvent(OnDropAttempt); - SubscribeLocalEvent(OnPickupAttempt); - SubscribeLocalEvent(OnStartPullAttempt); - SubscribeLocalEvent(UpdateState); - SubscribeLocalEvent(OnMoveAttempt); - SubscribeLocalEvent(OnStandAttempt); - SubscribeLocalEvent(OnSleepAttempt); - SubscribeLocalEvent(OnSneezeAttempt); - SubscribeLocalEvent(OnStateChanged); - // Note that there's no check for Down attempts because if a mob's in crit or dead, they can be downed... - } - - private void OnSleepAttempt(EntityUid uid, MobStateComponent component, ref TryingToSleepEvent args) - { - if(IsDead(uid, component)) - args.Cancelled = true; - } - - private void OnSneezeAttempt(EntityUid uid, MobStateComponent component, ref AttemptSneezeCoughEvent args) - { - if(IsDead(uid, component)) - args.Cancelled = true; - } - - private void OnGettingStripped(EntityUid uid, MobStateComponent component, BeforeGettingStrippedEvent args) - { - // Incapacitated or dead targets get stripped two or three times as fast. Makes stripping corpses less tedious. - if (IsDead(uid, component)) - args.Multiplier /= 3; - else if (IsCritical(uid, component)) - args.Multiplier /= 2; - } - - private void OnMobStartup(EntityUid uid, MobStateComponent component, ComponentStartup args) - { - if (component.CurrentState != null && component.CurrentThreshold != null) - { - // Initialize with given states - SetMobState(component, null, (component.CurrentState.Value, component.CurrentThreshold.Value)); - } - else - { - // Initialize with some amount of damage, defaulting to 0. - UpdateState(component, CompOrNull(uid)?.TotalDamage ?? FixedPoint2.Zero); - } - } - - private void OnMobShutdown(EntityUid uid, MobStateComponent component, ComponentShutdown args) - { - Alerts.ClearAlert(uid, AlertType.HumanHealth); - } - - public bool IsAlive(EntityUid uid, MobStateComponent? component = null) - { - if (!Resolve(uid, ref component, false)) return false; - return component.CurrentState == DamageState.Alive; - } - - public bool IsCritical(EntityUid uid, MobStateComponent? component = null) - { - if (!Resolve(uid, ref component, false)) return false; - return component.CurrentState == DamageState.Critical; - } - - public bool IsDead(EntityUid uid, MobStateComponent? component = null) - { - if (!Resolve(uid, ref component, false)) return false; - return component.CurrentState == DamageState.Dead; - } - - public bool IsIncapacitated(EntityUid uid, MobStateComponent? component = null) - { - if (!Resolve(uid, ref component, false)) return false; - return component.CurrentState is DamageState.Critical or DamageState.Dead; - } - - #region ActionBlocker - private void OnStateChanged(MobStateChangedEvent ev) - { - _blocker.UpdateCanMove(ev.Entity); - } - - private void CheckAct(EntityUid uid, MobStateComponent component, CancellableEntityEventArgs args) - { - switch (component.CurrentState) - { - case DamageState.Dead: - case DamageState.Critical: - args.Cancel(); - break; - } - } - - private void OnChangeDirectionAttempt(EntityUid uid, MobStateComponent component, ChangeDirectionAttemptEvent args) - { - CheckAct(uid, component, args); - } - - private void OnUseAttempt(EntityUid uid, MobStateComponent component, UseAttemptEvent args) - { - CheckAct(uid, component, args); - } - - private void OnInteractAttempt(EntityUid uid, MobStateComponent component, InteractionAttemptEvent args) - { - CheckAct(uid, component, args); - } - - private void OnThrowAttempt(EntityUid uid, MobStateComponent component, ThrowAttemptEvent args) - { - CheckAct(uid, component, args); - } - - private void OnSpeakAttempt(EntityUid uid, MobStateComponent component, SpeakAttemptEvent args) - { - CheckAct(uid, component, args); - } - - private void OnEquipAttempt(EntityUid uid, MobStateComponent component, IsEquippingAttemptEvent args) - { - // is this a self-equip, or are they being stripped? - if (args.Equipee == uid) - CheckAct(uid, component, args); - } - - private void OnEmoteAttempt(EntityUid uid, MobStateComponent component, EmoteAttemptEvent args) - { - CheckAct(uid, component, args); - } - - private void OnUnequipAttempt(EntityUid uid, MobStateComponent component, IsUnequippingAttemptEvent args) - { - // is this a self-equip, or are they being stripped? - if (args.Unequipee == uid) - CheckAct(uid, component, args); - } - - private void OnDropAttempt(EntityUid uid, MobStateComponent component, DropAttemptEvent args) - { - CheckAct(uid, component, args); - } - - private void OnPickupAttempt(EntityUid uid, MobStateComponent component, PickupAttemptEvent args) - { - CheckAct(uid, component, args); - } - - #endregion - - private void OnStartPullAttempt(EntityUid uid, MobStateComponent component, StartPullAttemptEvent args) - { - if (IsIncapacitated(uid, component)) - args.Cancel(); - } - - public void UpdateState(EntityUid _, MobStateComponent component, DamageChangedEvent args) - { - UpdateState(component, args.Damageable.TotalDamage, args.Origin); - } - - private void OnMoveAttempt(EntityUid uid, MobStateComponent component, UpdateCanMoveEvent args) - { - switch (component.CurrentState) - { - case DamageState.Critical: - case DamageState.Dead: - args.Cancel(); - return; - default: - return; - } - } - - private void OnStandAttempt(EntityUid uid, MobStateComponent component, StandAttemptEvent args) - { - if (IsIncapacitated(uid, component)) - args.Cancel(); - } - - public virtual void RemoveState(MobStateComponent component) - { - var old = component.CurrentState; - component.CurrentState = null; - component.CurrentThreshold = null; - - SetMobState(component, old, null); - } - - public virtual void EnterState(MobStateComponent? component, DamageState? state) - { - // TODO: Thanks buckle - if (component == null) return; - - switch (state) - { - case DamageState.Alive: - EnterNormState(component.Owner); - break; - case DamageState.Critical: - EnterCritState(component.Owner); - break; - case DamageState.Dead: - EnterDeadState(component.Owner); - break; - case null: - break; - default: - throw new NotImplementedException(); - } - } - - protected virtual void UpdateState(MobStateComponent component, DamageState? state, FixedPoint2 threshold) - { - switch (state) - { - case DamageState.Alive: - UpdateNormState(component.Owner, threshold); - break; - case DamageState.Critical: - UpdateCritState(component.Owner, threshold); - break; - case DamageState.Dead: - UpdateDeadState(component.Owner, threshold); - break; - case null: - break; - default: - throw new NotImplementedException(); - } - } - - protected virtual void ExitState(MobStateComponent component, DamageState? state) - { - switch (state) - { - case DamageState.Alive: - ExitNormState(component.Owner); - break; - case DamageState.Critical: - ExitCritState(component.Owner); - break; - case DamageState.Dead: - ExitDeadState(component.Owner); - break; - case null: - break; - default: - throw new NotImplementedException(); - } - } - - /// - /// Updates the mob state.. - /// - public void UpdateState(MobStateComponent component, FixedPoint2 damage, EntityUid? origin = null) - { - if (!TryGetState(component, damage, out var newState, out var threshold)) - { - return; - } - - SetMobState(component, component.CurrentState, (newState.Value, threshold), origin); - } - - /// - /// Sets the mob state and marks the component as dirty. - /// - private void SetMobState(MobStateComponent component, DamageState? old, (DamageState state, FixedPoint2 threshold)? current, EntityUid? origin = null) - { - //if it got deleted instantly in a nuke or something - if (!Exists(component.Owner) || Deleted(component.Owner)) - return; - - if (!current.HasValue) - { - ExitState(component, old); - return; - } - - var (state, threshold) = current.Value; - - component.CurrentThreshold = threshold; - - if (state == old) - { - UpdateState(component, state, threshold); - return; - } - - ExitState(component, old); - - component.CurrentState = state; - _adminLogger.Add(LogType.Damaged, state == DamageState.Alive ? LogImpact.Low : LogImpact.Medium, $"{ToPrettyString(component.Owner):user} state changed from {old} to {state}"); - - EnterState(component, state); - UpdateState(component, state, threshold); - - var message = new MobStateChangedEvent(component, old, state, origin); - RaiseLocalEvent(component.Owner, message, true); - Dirty(component); - } - - public (DamageState state, FixedPoint2 threshold)? GetState(MobStateComponent component, FixedPoint2 damage) - { - foreach (var (threshold, state) in component._highestToLowestStates) - { - if (damage >= threshold) - { - return (state, threshold); - } - } - - return null; - } - - public bool TryGetState( - MobStateComponent component, - FixedPoint2 damage, - [NotNullWhen(true)] out DamageState? state, - out FixedPoint2 threshold) - { - var highestState = GetState(component, damage); - - if (highestState == null) - { - state = default; - threshold = default; - return false; - } - - (state, threshold) = highestState.Value; - return true; - } - - private (DamageState state, FixedPoint2 threshold)? GetEarliestState(MobStateComponent component, FixedPoint2 minimumDamage, Predicate predicate) - { - foreach (var (threshold, state) in component._lowestToHighestStates) - { - if (threshold < minimumDamage || - !predicate(state)) - { - continue; - } - - return (state, threshold); - } - - return null; - } - - private (DamageState state, FixedPoint2 threshold)? GetPreviousState(MobStateComponent component, FixedPoint2 maximumDamage, Predicate predicate) - { - foreach (var (threshold, state) in component._highestToLowestStates) - { - if (threshold > maximumDamage || - !predicate(state)) - { - continue; - } - - return (state, threshold); - } - - return null; - } - - public (DamageState state, FixedPoint2 threshold)? GetEarliestCriticalState(MobStateComponent component, FixedPoint2 minimumDamage) - { - return GetEarliestState(component, minimumDamage, s => s == DamageState.Critical); - } - - public (DamageState state, FixedPoint2 threshold)? GetEarliestIncapacitatedState(MobStateComponent component, FixedPoint2 minimumDamage) - { - return GetEarliestState(component, minimumDamage, s => s is DamageState.Critical or DamageState.Dead); - } - - public (DamageState state, FixedPoint2 threshold)? GetEarliestDeadState(MobStateComponent component, FixedPoint2 minimumDamage) - { - return GetEarliestState(component, minimumDamage, s => s == DamageState.Dead); - } - - public (DamageState state, FixedPoint2 threshold)? GetPreviousCriticalState(MobStateComponent component, FixedPoint2 minimumDamage) - { - return GetPreviousState(component, minimumDamage, s => s == DamageState.Critical); - } - - private bool TryGetState( - (DamageState state, FixedPoint2 threshold)? tuple, - [NotNullWhen(true)] out DamageState? state, - out FixedPoint2 threshold) - { - if (tuple == null) - { - state = default; - threshold = default; - return false; - } - - (state, threshold) = tuple.Value; - return true; - } - - public bool TryGetEarliestCriticalState( - MobStateComponent component, - FixedPoint2 minimumDamage, - [NotNullWhen(true)] out DamageState? state, - out FixedPoint2 threshold) - { - var earliestState = GetEarliestCriticalState(component, minimumDamage); - - return TryGetState(earliestState, out state, out threshold); - } - - public bool TryGetEarliestIncapacitatedState( - MobStateComponent component, - FixedPoint2 minimumDamage, - [NotNullWhen(true)] out DamageState? state, - out FixedPoint2 threshold) - { - var earliestState = GetEarliestIncapacitatedState(component, minimumDamage); - - return TryGetState(earliestState, out state, out threshold); - } - - public bool TryGetEarliestDeadState( - MobStateComponent component, - FixedPoint2 minimumDamage, - [NotNullWhen(true)] out DamageState? state, - out FixedPoint2 threshold) - { - var earliestState = GetEarliestDeadState(component, minimumDamage); - - return TryGetState(earliestState, out state, out threshold); - } - - public bool TryGetPreviousCriticalState( - MobStateComponent component, - FixedPoint2 maximumDamage, - [NotNullWhen(true)] out DamageState? state, - out FixedPoint2 threshold) - { - var earliestState = GetPreviousCriticalState(component, maximumDamage); - - return TryGetState(earliestState, out state, out threshold); - } - - [Serializable, NetSerializable] - protected sealed class MobStateComponentState : ComponentState - { - public readonly FixedPoint2? CurrentThreshold; - - public MobStateComponentState(FixedPoint2? currentThreshold) - { - CurrentThreshold = currentThreshold; - } - } - } -} diff --git a/Content.Shared/MobState/MobStateChangedEvent.cs b/Content.Shared/MobState/MobStateChangedEvent.cs deleted file mode 100644 index 783714cca3..0000000000 --- a/Content.Shared/MobState/MobStateChangedEvent.cs +++ /dev/null @@ -1,56 +0,0 @@ -using Content.Shared.MobState.Components; - -namespace Content.Shared.MobState -{ - public sealed class MobStateChangedEvent : EntityEventArgs - { - public MobStateChangedEvent( - MobStateComponent component, - DamageState? oldMobState, - DamageState currentMobState, - EntityUid? origin) - { - Component = component; - OldMobState = oldMobState; - CurrentMobState = currentMobState; - Origin = origin; - } - - public EntityUid Entity => Component.Owner; - - public MobStateComponent Component { get; } - - public DamageState? OldMobState { get; } - - public DamageState CurrentMobState { get; } - - public EntityUid? Origin { get; } - } - - public static class A - { - [Obsolete("Just check for the enum value instead")] - public static bool IsAlive(this DamageState state) - { - return state == DamageState.Alive; - } - - [Obsolete("Just check for the enum value instead")] - public static bool IsCritical(this DamageState state) - { - return state == DamageState.Critical; - } - - [Obsolete("Just check for the enum value instead")] - public static bool IsDead(this DamageState state) - { - return state == DamageState.Dead; - } - - [Obsolete("Just check for the enum value instead")] - public static bool IsIncapacitated(this DamageState state) - { - return state is DamageState.Dead or DamageState.Critical; - } - } -} diff --git a/Content.Shared/Mobs/Components/MobStateComponent.cs b/Content.Shared/Mobs/Components/MobStateComponent.cs new file mode 100644 index 0000000000..091c56f0eb --- /dev/null +++ b/Content.Shared/Mobs/Components/MobStateComponent.cs @@ -0,0 +1,42 @@ +using Content.Shared.Damage; +using Content.Shared.Mobs.Systems; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Mobs.Components +{ + /// + /// When attached to an , + /// this component will handle critical and death behaviors for mobs. + /// Additionally, it handles sending effects to clients + /// (such as blur effect for unconsciousness) and managing the health HUD. + /// + [RegisterComponent] + [NetworkedComponent] + [Access(typeof(MobStateSystem), typeof(MobThresholdSystem))] + public sealed class MobStateComponent : Component + { + //default mobstate is always the lowest state level + [ViewVariables] public MobState CurrentState { get; set; } = MobState.Alive; + + [DataField("allowedStates")] public HashSet AllowedStates = new() + { + MobState.Alive, + MobState.Critical, + MobState.Dead + }; + } + + [Serializable, NetSerializable] + public sealed class MobStateComponentState : ComponentState + { + public readonly MobState CurrentState; + public readonly HashSet AllowedStates; + + public MobStateComponentState(MobState currentState, HashSet allowedStates) + { + CurrentState = currentState; + AllowedStates = allowedStates; + } + } +} diff --git a/Content.Shared/Mobs/Components/MobThresholdsComponent.cs b/Content.Shared/Mobs/Components/MobThresholdsComponent.cs new file mode 100644 index 0000000000..c69c3dac10 --- /dev/null +++ b/Content.Shared/Mobs/Components/MobThresholdsComponent.cs @@ -0,0 +1,31 @@ +using Content.Shared.FixedPoint; +using Content.Shared.Mobs.Systems; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Mobs.Components; + +[RegisterComponent, NetworkedComponent] +[Access(typeof(MobThresholdSystem))] +public sealed class MobThresholdsComponent : Component +{ + [DataField("thresholds", required:true)]public SortedDictionary Thresholds = new(); + + [DataField("triggersAlerts")] public bool TriggersAlerts = true; + + public MobState CurrentThresholdState; +} + +[Serializable, NetSerializable] +public sealed class MobThresholdComponentState : ComponentState +{ + public Dictionary Thresholds; + public MobState CurrentThresholdState; + public MobThresholdComponentState(MobState currentThresholdState, + Dictionary thresholds) + { + CurrentThresholdState = currentThresholdState; + Thresholds = thresholds; + } + +} diff --git a/Content.Shared/Mobs/MobState.cs b/Content.Shared/Mobs/MobState.cs new file mode 100644 index 0000000000..1846232f4e --- /dev/null +++ b/Content.Shared/Mobs/MobState.cs @@ -0,0 +1,43 @@ +using Content.Shared.Mobs.Components; +using Robust.Shared.Serialization; + +namespace Content.Shared.Mobs; + +/// +/// Defines what state an is in. +/// +/// Ordered from most alive to least alive. +/// To enumerate them in this way see +/// . +/// +[Serializable, NetSerializable] +public enum MobState : byte +{ + Invalid = 0, + Alive = 1, + Critical = 2, + Dead = 3 +} + +/// +/// Event that is raised whenever a MobState changes on an entity +/// +/// The Entity whose MobState is changing +/// The MobState Component owned by the Target entity +/// The previous MobState +/// The new MobState +/// The Entity that caused this state change +public record struct MobStateChangedEvent(EntityUid Target, MobStateComponent Component, MobState OldMobState, + MobState NewMobState, EntityUid? Origin = null); + +public static class A +{ + //^.^ +} + +//This is dumb and I hate it but I don't feel like refactoring this garbage +[Serializable, NetSerializable] +public enum MobStateVisuals : byte +{ + State +} diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs b/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs new file mode 100644 index 0000000000..38dcd33909 --- /dev/null +++ b/Content.Shared/Mobs/Systems/MobStateSystem.StateMachine.cs @@ -0,0 +1,130 @@ +using Content.Shared.Database; +using Content.Shared.Mobs.Components; + +namespace Content.Shared.Mobs.Systems; + +public partial class MobStateSystem +{ + #region Public API + + /// + /// Check if an Entity can be set to a particular MobState + /// + /// Target Entity + /// MobState to check + /// MobState Component owned by the target + /// If the entity can be set to that MobState + public bool HasState(EntityUid entity, MobState mobState, MobStateComponent? component = null) + { + return Resolve(entity, ref component, false) && component.AllowedStates.Contains(mobState); + } + + /// + /// Run a MobState update check. This will trigger update events if the state has been changed. + /// + /// Target Entity we want to change the MobState of + /// MobState Component attached to the entity + /// Entity that caused the state update (if applicable) + public void UpdateMobState(EntityUid entity, MobStateComponent? component = null, EntityUid? origin = null) + { + if (!Resolve(entity, ref component)) + return; + + var ev = new UpdateMobStateEvent {Target = entity, Component = component, Origin = origin}; + RaiseLocalEvent(entity, ref ev); + ChangeState(entity, component, ev.State); + } + + /// + /// Change the MobState and trigger MobState update events + /// + /// Target Entity we want to change the MobState of + /// The new MobState we want to set + /// MobState Component attached to the entity + /// Entity that caused the state update (if applicable) + public void ChangeMobState(EntityUid entity, MobState mobState, MobStateComponent? component = null, + EntityUid? origin = null) + { + if (!Resolve(entity, ref component)) + return; + + var ev = new UpdateMobStateEvent {Target = entity, Component = component, Origin = origin}; + RaiseLocalEvent(entity, ref ev); + ChangeState(entity, component, ev.State); + } + + #endregion + + #region Virtual API + + /// + /// Called when a new MobState is entered. + /// + /// The owner of the MobState Component + /// MobState Component owned by the target + /// The new MobState + protected virtual void OnEnterState(EntityUid entity, MobStateComponent component, MobState state) + { + OnStateEnteredSubscribers(entity, component, state); + } + + /// + /// Called when this entity changes MobState + /// + /// The owner of the MobState Component + /// MobState Component owned by the target + /// The previous MobState + /// The new MobState + protected virtual void OnStateChanged(EntityUid entity, MobStateComponent component, MobState oldState, + MobState newState) + { + } + + /// + /// Called when a new MobState is exited. + /// + /// The owner of the MobState Component + /// MobState Component owned by the target + /// The old MobState + protected virtual void OnExitState(EntityUid entity, MobStateComponent component, MobState state) + { + OnStateExitSubscribers(entity, component, state); + } + + #endregion + + #region Private Implementation + + //Actually change the MobState + private void ChangeState(EntityUid target, MobStateComponent component, MobState newState, EntityUid? origin = null) + { + var oldState = component.CurrentState; + //make sure we are allowed to enter the new state + if (oldState == newState || !component.AllowedStates.Contains(newState)) + return; + + OnExitState(target, component, oldState); + component.CurrentState = newState; + OnEnterState(target, component, newState); + + var ev = new MobStateChangedEvent(target, component, oldState, newState, origin); + OnStateChanged(target, component, oldState, newState); + RaiseLocalEvent(target, ev, true); + _adminLogger.Add(LogType.Damaged, oldState == MobState.Alive ? LogImpact.Low : LogImpact.Medium, + $"{ToPrettyString(component.Owner):user} state changed from {oldState} to {newState}"); + Dirty(component); + } + + #endregion +} + +/// +/// Event that gets triggered when we want to update the mobstate. This allows for systems to override MobState changes +/// +/// The Entity whose MobState is changing +/// The MobState Component owned by the Target +/// The new MobState we want to set +/// Entity that caused the state update (if applicable) +[ByRefEvent] +public record struct UpdateMobStateEvent(EntityUid Target, MobStateComponent Component, MobState State, + EntityUid? Origin = null); diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs new file mode 100644 index 0000000000..6f56dfb584 --- /dev/null +++ b/Content.Shared/Mobs/Systems/MobStateSystem.Subscribers.cs @@ -0,0 +1,152 @@ +using Content.Shared.Bed.Sleep; +using Content.Shared.Disease.Events; +using Content.Shared.DragDrop; +using Content.Shared.Emoting; +using Content.Shared.Interaction.Events; +using Content.Shared.Inventory.Events; +using Content.Shared.Item; +using Content.Shared.Mobs.Components; +using Content.Shared.Movement.Events; +using Content.Shared.Pulling.Events; +using Content.Shared.Speech; +using Content.Shared.Standing; +using Content.Shared.Strip.Components; +using Content.Shared.Throwing; +using Robust.Shared.Physics.Components; + +namespace Content.Shared.Mobs.Systems; + +public partial class MobStateSystem +{ + //General purpose event subscriptions. If you can avoid it register these events inside their own systems + private void SubscribeEvents() + { + SubscribeLocalEvent(OnGettingStripped); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(OnEquipAttempt); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(OnUnequipAttempt); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(CheckAct); + SubscribeLocalEvent(OnSleepAttempt); + SubscribeLocalEvent(OnSneezeAttempt); + } + + private void OnStateExitSubscribers(EntityUid target, MobStateComponent component, MobState state) + { + var uid = component.Owner; + switch (state) + { + case MobState.Alive: + //unused + break; + case MobState.Critical: + _standing.Stand(uid); + break; + case MobState.Dead: + RemComp(uid); + _standing.Stand(uid); + if (!_standing.IsDown(uid) && TryComp(uid, out var physics)) + { + _physics.SetCanCollide(physics, true); + } + + break; + case MobState.Invalid: + //unused + break; + default: + throw new NotImplementedException(); + } + } + + private void OnStateEnteredSubscribers(EntityUid target, MobStateComponent component, MobState state) + { + var uid = component.Owner; + _blocker.UpdateCanMove(uid); //update movement anytime a state changes + switch (state) + { + case MobState.Alive: + _standing.Stand(uid); + _appearance.SetData(uid, MobStateVisuals.State, MobState.Alive); + break; + case MobState.Critical: + _standing.Down(uid); + _appearance.SetData(uid, MobStateVisuals.State, MobState.Critical); + break; + case MobState.Dead: + EnsureComp(uid); + _standing.Down(uid); + + if (_standing.IsDown(uid) && TryComp(uid, out var physics)) + { + _physics.SetCanCollide(physics, false); + } + + _appearance.SetData(uid, MobStateVisuals.State, MobState.Dead); + break; + case MobState.Invalid: + //unused; + break; + default: + throw new NotImplementedException(); + } + } + + #region Event Subscribers + + private void OnSleepAttempt(EntityUid target, MobStateComponent component, ref TryingToSleepEvent args) + { + if (IsDead(target, component)) + args.Cancelled = true; + } + + private void OnSneezeAttempt(EntityUid target, MobStateComponent component, ref AttemptSneezeCoughEvent args) + { + if (IsDead(target, component)) + args.Cancelled = true; + } + + private void OnGettingStripped(EntityUid target, MobStateComponent component, BeforeGettingStrippedEvent args) + { + // Incapacitated or dead targets get stripped two or three times as fast. Makes stripping corpses less tedious. + if (IsDead(target, component)) + args.Multiplier /= 3; + else if (IsCritical(target, component)) + args.Multiplier /= 2; + } + + private void CheckAct(EntityUid target, MobStateComponent component, CancellableEntityEventArgs args) + { + switch (component.CurrentState) + { + case MobState.Dead: + case MobState.Critical: + args.Cancel(); + break; + } + } + + private void OnEquipAttempt(EntityUid target, MobStateComponent component, IsEquippingAttemptEvent args) + { + // is this a self-equip, or are they being stripped? + if (args.Equipee == target) + CheckAct(target, component, args); + } + + private void OnUnequipAttempt(EntityUid target, MobStateComponent component, IsUnequippingAttemptEvent args) + { + // is this a self-equip, or are they being stripped? + if (args.Unequipee == target) + CheckAct(target, component, args); + } + + #endregion +} diff --git a/Content.Shared/Mobs/Systems/MobStateSystem.cs b/Content.Shared/Mobs/Systems/MobStateSystem.cs new file mode 100644 index 0000000000..4be7715a98 --- /dev/null +++ b/Content.Shared/Mobs/Systems/MobStateSystem.cs @@ -0,0 +1,116 @@ +using Content.Shared.ActionBlocker; +using Content.Shared.Administration.Logs; +using Content.Shared.Mobs.Components; +using Content.Shared.Standing; +using Robust.Shared.GameStates; +using Robust.Shared.Physics.Systems; + +namespace Content.Shared.Mobs.Systems; + +[Virtual] +public partial class MobStateSystem : EntitySystem +{ + [Dependency] private readonly ActionBlockerSystem _blocker = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + [Dependency] private readonly SharedPhysicsSystem _physics = default!; + [Dependency] private readonly StandingStateSystem _standing = default!; + [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; + [Dependency] private readonly ILogManager _logManager = default!; + private ISawmill _sawmill = default!; + + public override void Initialize() + { + _sawmill = _logManager.GetSawmill("MobState"); + base.Initialize(); + SubscribeEvents(); + SubscribeLocalEvent(OnGetComponentState); + SubscribeLocalEvent(OnHandleComponentState); + } + + #region Public API + + /// + /// Check if a Mob is Alive + /// + /// Target Entity + /// The MobState component owned by the target + /// If the entity is alive + public bool IsAlive(EntityUid target, MobStateComponent? component = null) + { + if (!Resolve(target, ref component, false)) + return false; + return component.CurrentState == MobState.Alive; + } + + /// + /// Check if a Mob is Critical + /// + /// Target Entity + /// The MobState component owned by the target + /// If the entity is Critical + public bool IsCritical(EntityUid target, MobStateComponent? component = null) + { + if (!Resolve(target, ref component, false)) + return false; + return component.CurrentState == MobState.Critical; + } + + /// + /// Check if a Mob is Dead + /// + /// Target Entity + /// The MobState component owned by the target + /// If the entity is Dead + public bool IsDead(EntityUid target, MobStateComponent? component = null) + { + if (!Resolve(target, ref component, false)) + return false; + return component.CurrentState == MobState.Dead; + } + + /// + /// Check if a Mob is Critical or Dead + /// + /// Target Entity + /// The MobState component owned by the target + /// If the entity is Critical or Dead + public bool IsIncapacitated(EntityUid target, MobStateComponent? component = null) + { + if (!Resolve(target, ref component, false)) + return false; + return component.CurrentState is MobState.Critical or MobState.Dead; + } + + /// + /// Check if a Mob is in an Invalid state + /// + /// Target Entity + /// The MobState component owned by the target + /// If the entity is in an Invalid State + public bool IsInvalidState(EntityUid target, MobStateComponent? component = null) + { + if (!Resolve(target, ref component, false)) + return false; + return component.CurrentState is MobState.Invalid; + } + + #endregion + + #region Private Implementation + + private void OnHandleComponentState(EntityUid uid, MobStateComponent component, ref ComponentHandleState args) + { + if (args.Current is not MobStateComponentState state) + return; + + component.CurrentState = state.CurrentState; + component.AllowedStates = new HashSet(state.AllowedStates); + } + + private void OnGetComponentState(EntityUid uid, MobStateComponent component, ref ComponentGetState args) + { + args.State = new MobStateComponentState(component.CurrentState, component.AllowedStates); + } + + #endregion +} diff --git a/Content.Shared/Mobs/Systems/MobThresholdSystem.cs b/Content.Shared/Mobs/Systems/MobThresholdSystem.cs new file mode 100644 index 0000000000..0560c3eabd --- /dev/null +++ b/Content.Shared/Mobs/Systems/MobThresholdSystem.cs @@ -0,0 +1,394 @@ +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Content.Shared.Alert; +using Content.Shared.Damage; +using Content.Shared.FixedPoint; +using Content.Shared.Mobs.Components; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Shared.Mobs.Systems; + +public sealed class MobThresholdSystem : EntitySystem +{ + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; + [Dependency] private readonly AlertsSystem _alerts = default!; + + public override void Initialize() + { + SubscribeLocalEvent(MobThresholdMapInit); + SubscribeLocalEvent(MobThresholdShutdown); + SubscribeLocalEvent(OnDamaged); + SubscribeLocalEvent(OnGetComponentState); + SubscribeLocalEvent(OnHandleComponentState); + SubscribeLocalEvent(OnUpdateMobState); + } + + #region Public API + + /// + /// Get the Damage Threshold for the appropriate state if it exists + /// + /// Target Entity + /// MobState we want the Damage Threshold of + /// Threshold Component Owned by the target + /// the threshold or 0 if it doesn't exist + public FixedPoint2 GetThresholdForState(EntityUid target, MobState mobState, + MobThresholdsComponent? thresholdComponent = null) + { + if (!Resolve(target, ref thresholdComponent)) + return FixedPoint2.Zero; + + foreach (var pair in thresholdComponent.Thresholds) + { + if (pair.Value == mobState) + { + return pair.Key; + } + } + + return FixedPoint2.Zero; + } + + /// + /// Try to get the Damage Threshold for the appropriate state if it exists + /// + /// Target Entity + /// MobState we want the Damage Threshold of + /// The damage Threshold for the given state + /// Threshold Component Owned by the target + /// true if successfully retrieved a threshold + public bool TryGetThresholdForState(EntityUid target, MobState mobState, + [NotNullWhen(true)] out FixedPoint2? threshold, + MobThresholdsComponent? thresholdComponent = null) + { + threshold = null; + if (!Resolve(target, ref thresholdComponent)) + return false; + + foreach (var pair in thresholdComponent.Thresholds) + { + if (pair.Value == mobState) + { + threshold = pair.Key; + return true; + } + } + + return false; + } + + /// + /// Try to get the a percentage of the Damage Threshold for the appropriate state if it exists + /// + /// Target Entity + /// MobState we want the Damage Threshold of + /// The Damage being applied + /// Percentage of Damage compared to the Threshold + /// Threshold Component Owned by the target + /// true if successfully retrieved a percentage + public bool TryGetPercentageForState(EntityUid target, MobState mobState, FixedPoint2 damage, + [NotNullWhen(true)] out FixedPoint2? percentage, + MobThresholdsComponent? thresholdComponent = null) + { + percentage = null; + if (!TryGetThresholdForState(target, mobState, out var threshold, thresholdComponent)) + return false; + + percentage = damage / threshold; + return true; + } + + /// + /// Try to get the Damage Threshold for crit or death. Outputs the first found threshold. + /// + /// Target Entity + /// The Damage Threshold for incapacitation + /// Threshold Component owned by the target + /// true if successfully retrieved incapacitation threshold + public bool TryGetIncapThreshold(EntityUid target, [NotNullWhen(true)] out FixedPoint2? threshold, + MobThresholdsComponent? thresholdComponent = null) + { + threshold = null; + if (!Resolve(target, ref thresholdComponent)) + return false; + + return TryGetThresholdForState(target, MobState.Critical, out threshold, thresholdComponent) + || TryGetThresholdForState(target, MobState.Dead, out threshold, thresholdComponent); + } + + /// + /// Try to get a percentage of the Damage Threshold for crit or death. Outputs the first found percentage. + /// + /// Target Entity + /// The damage being applied + /// Percentage of Damage compared to the Incapacitation Threshold + /// Threshold Component Owned by the target + /// true if successfully retrieved incapacitation percentage + public bool TryGetIncapPercentage(EntityUid target, FixedPoint2 damage, + [NotNullWhen(true)] out FixedPoint2? percentage, + MobThresholdsComponent? thresholdComponent = null) + { + percentage = null; + if (!TryGetIncapThreshold(target, out var threshold, thresholdComponent)) + return false; + + if (damage == 0) + { + percentage = 0; + return true; + } + + percentage = FixedPoint2.Min(1.0f, damage / threshold.Value); + return true; + } + + /// + /// Try to get the Damage Threshold for death + /// + /// Target Entity + /// The Damage Threshold for death + /// Threshold Component owned by the target + /// true if successfully retrieved incapacitation threshold + public bool TryGetDeadThreshold(EntityUid target, [NotNullWhen(true)] out FixedPoint2? threshold, + MobThresholdsComponent? thresholdComponent = null) + { + threshold = null; + if (!Resolve(target, ref thresholdComponent)) + return false; + + return TryGetThresholdForState(target, MobState.Dead, out threshold, thresholdComponent); + } + + /// + /// Try to get a percentage of the Damage Threshold for death + /// + /// Target Entity + /// The damage being applied + /// Percentage of Damage compared to the Death Threshold + /// Threshold Component Owned by the target + /// true if successfully retrieved death percentage + public bool TryGetDeadPercentage(EntityUid target, FixedPoint2 damage, + [NotNullWhen(true)] out FixedPoint2? percentage, + MobThresholdsComponent? thresholdComponent = null) + { + percentage = null; + if (!TryGetDeadThreshold(target, out var threshold, thresholdComponent)) + return false; + + if (damage == 0) + { + percentage = 0; + return true; + } + + percentage = FixedPoint2.Min(1.0f, damage / threshold.Value); + return true; + } + + /// + /// Takes the damage from one entity and scales it relative to the health of another + /// + /// The entity whose damage will be scaled + /// The entity whose health the damage will scale to + /// The newly scaled damage. Can be null + public bool GetScaledDamage(EntityUid target1, EntityUid target2, out DamageSpecifier? damage) + { + damage = null; + + if (!TryComp(target1, out var oldDamage)) + return false; + + if (!TryComp(target1, out var threshold1) || + !TryComp(target2, out var threshold2)) + return false; + + if (!TryGetThresholdForState(target1, MobState.Dead, out var ent1DeadThreshold, threshold1)) + ent1DeadThreshold = 0; + + if (!TryGetThresholdForState(target2, MobState.Dead, out var ent2DeadThreshold, threshold2)) + ent2DeadThreshold = 0; + + damage = (oldDamage.Damage / ent1DeadThreshold.Value) * ent2DeadThreshold.Value; + return true; + } + + /// + /// Set a MobState Threshold or create a new one if it doesn't exist + /// + /// Target Entity + /// Damageable Component owned by the target + /// MobState Component owned by the target + /// MobThreshold Component owned by the target + public void SetMobStateThreshold(EntityUid target, FixedPoint2 damage, MobState mobState, + MobThresholdsComponent? threshold = null) + { + if (!Resolve(target, ref threshold)) + return; + + threshold.Thresholds[damage] = mobState; + VerifyThresholds(target, threshold); + } + + /// + /// Checks to see if we should change states based on thresholds. + /// Call this if you change the amount of damagable without triggering a damageChangedEvent or if you change + /// + /// Target Entity + /// Threshold Component owned by the Target + /// MobState Component owned by the Target + /// Damageable Component owned by the Target + public void VerifyThresholds(EntityUid target, MobThresholdsComponent? threshold = null, + MobStateComponent? mobState = null, DamageableComponent? damageable = null) + { + if (!Resolve(target, ref mobState, ref threshold, ref damageable)) + return; + + CheckThresholds(target, mobState, threshold, damageable); + } + + #endregion + + #region Private Implementation + + private void CheckThresholds(EntityUid target, MobStateComponent mobStateComponent, + MobThresholdsComponent thresholdsComponent, DamageableComponent damageableComponent) + { + foreach (var (threshold, mobState) in thresholdsComponent.Thresholds) + { + if (damageableComponent.TotalDamage < threshold) + continue; + + TriggerThreshold(target, thresholdsComponent.CurrentThresholdState, mobState, mobStateComponent, + thresholdsComponent); + } + + var ev = new MobThresholdChecked(target, mobStateComponent, thresholdsComponent, damageableComponent); + RaiseLocalEvent(target, ref ev, true); + UpdateAlerts(target, mobStateComponent.CurrentState, thresholdsComponent, damageableComponent); + } + + private void TriggerThreshold( + EntityUid target, + MobState oldState, + MobState newState, + MobStateComponent? mobState = null, + MobThresholdsComponent? thresholds = null) + { + if (oldState == newState || + !Resolve(target, ref mobState, ref thresholds)) + { + return; + } + + thresholds.CurrentThresholdState = newState; + _mobStateSystem.UpdateMobState(target, mobState); + + Dirty(target); + } + + private void UpdateAlerts(EntityUid target, MobState currentMobState, MobThresholdsComponent? threshold = null, + DamageableComponent? damageable = null) + { + if (!Resolve(target, ref threshold, ref damageable)) + return; + + // don't handle alerts if they are managed by another system... BobbySim (soon TM) + if (!threshold.TriggersAlerts) + return; + + switch (currentMobState) + { + case MobState.Alive: + { + var severity = _alerts.GetMinSeverity(AlertType.HumanHealth); + if (TryGetIncapPercentage(target, damageable.TotalDamage, out var percentage)) + { + severity = (short) MathF.Floor(percentage.Value.Float() * + _alerts.GetMaxSeverity(AlertType.HumanHealth)); + } + + _alerts.ShowAlert(target, AlertType.HumanHealth, severity); + break; + } + case MobState.Critical: + { + _alerts.ShowAlert(target, AlertType.HumanCrit); + break; + } + case MobState.Dead: + { + _alerts.ShowAlert(target, AlertType.HumanDead); + break; + } + case MobState.Invalid: + default: + throw new ArgumentOutOfRangeException(nameof(currentMobState), currentMobState, null); + } + } + + private void OnDamaged(EntityUid target, MobThresholdsComponent mobThresholdsComponent, DamageChangedEvent args) + { + var mobStateComp = EnsureComp(target); + CheckThresholds(target, mobStateComp, mobThresholdsComponent, args.Damageable); + } + + private void OnHandleComponentState(EntityUid target, MobThresholdsComponent component, + ref ComponentHandleState args) + { + if (args.Current is not MobThresholdComponentState state) + return; + + component.Thresholds = new SortedDictionary(state.Thresholds); + component.CurrentThresholdState = state.CurrentThresholdState; + } + + private void OnGetComponentState(EntityUid target, MobThresholdsComponent component, ref ComponentGetState args) + { + args.State = new MobThresholdComponentState(component.CurrentThresholdState, + new Dictionary(component.Thresholds)); + } + + private void MobThresholdMapInit(EntityUid target, MobThresholdsComponent component, MapInitEvent args) + { + // TODO remove when body sim is implemented + EnsureComp(target); + EnsureComp(target); + + if (!component.Thresholds.TryFirstOrNull(out var newState)) + return; + + component.CurrentThresholdState = newState.Value.Value; + + TriggerThreshold(target, MobState.Invalid, newState.Value.Value, thresholds: component); + UpdateAlerts(target, newState.Value.Value, component); + } + + private void MobThresholdShutdown(EntityUid target, MobThresholdsComponent component, ComponentShutdown args) + { + if (component.TriggersAlerts) + _alerts.ClearAlertCategory(target, AlertCategory.Health); + } + + private void OnUpdateMobState(EntityUid target, MobThresholdsComponent component, ref UpdateMobStateEvent args) + { + if (component.CurrentThresholdState != MobState.Invalid) + args.State = component.CurrentThresholdState; + } + + #endregion +} + +/// +/// Event that triggers when an entity with a mob threshold is checked +/// +/// Target entity +/// Threshold Component owned by the Target +/// MobState Component owned by the Target +/// Damageable Component owned by the Target +[ByRefEvent] +public readonly record struct MobThresholdChecked(EntityUid Target, MobStateComponent MobState, + MobThresholdsComponent Threshold, DamageableComponent Damageable) +{ +} diff --git a/Content.Shared/Movement/Systems/SharedMoverController.cs b/Content.Shared/Movement/Systems/SharedMoverController.cs index 66a716487d..e79a67ea34 100644 --- a/Content.Shared/Movement/Systems/SharedMoverController.cs +++ b/Content.Shared/Movement/Systems/SharedMoverController.cs @@ -3,7 +3,6 @@ using Content.Shared.Friction; using Content.Shared.Gravity; using Content.Shared.Inventory; using Content.Shared.Maps; -using Content.Shared.MobState.EntitySystems; using Content.Shared.Movement.Components; using Content.Shared.Movement.Events; using Content.Shared.Pulling.Components; @@ -17,7 +16,7 @@ using Robust.Shared.Physics.Controllers; using Robust.Shared.Timing; using Robust.Shared.Utility; using System.Diagnostics.CodeAnalysis; -using Content.Shared.Mech.Components; +using Content.Shared.Mobs.Systems; using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; @@ -36,7 +35,7 @@ namespace Content.Shared.Movement.Systems [Dependency] private readonly InventorySystem _inventory = default!; [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedGravitySystem _gravity = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedTransformSystem _transform = default!; [Dependency] private readonly TagSystem _tags = default!; diff --git a/Content.Shared/Pulling/Systems/SharedPullableSystem.cs b/Content.Shared/Pulling/Systems/SharedPullableSystem.cs index ea3cd0fb79..3dab476337 100644 --- a/Content.Shared/Pulling/Systems/SharedPullableSystem.cs +++ b/Content.Shared/Pulling/Systems/SharedPullableSystem.cs @@ -1,6 +1,6 @@ using Content.Shared.ActionBlocker; +using Content.Shared.Mobs.Systems; using Content.Shared.Pulling.Components; -using Content.Shared.MobState.EntitySystems; using Content.Shared.Movement.Events; namespace Content.Shared.Pulling.Systems @@ -8,7 +8,7 @@ namespace Content.Shared.Pulling.Systems public sealed class SharedPullableSystem : EntitySystem { [Dependency] private readonly ActionBlockerSystem _blocker = default!; - [Dependency] private readonly SharedMobStateSystem _mobState = default!; + [Dependency] private readonly MobStateSystem _mobState = default!; [Dependency] private readonly SharedPullingSystem _pullSystem = default!; public override void Initialize() diff --git a/Content.Shared/StatusEffect/StatusEffectsSystem.cs b/Content.Shared/StatusEffect/StatusEffectsSystem.cs index 333b328284..0cab536e19 100644 --- a/Content.Shared/StatusEffect/StatusEffectsSystem.cs +++ b/Content.Shared/StatusEffect/StatusEffectsSystem.cs @@ -1,5 +1,8 @@ using System.Diagnostics.CodeAnalysis; using Content.Shared.Alert; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Rejuvenate; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; @@ -13,6 +16,7 @@ namespace Content.Shared.StatusEffect [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IComponentFactory _componentFactory = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; [Dependency] private readonly AlertsSystem _alertsSystem = default!; public override void Initialize() diff --git a/Content.Shared/Stunnable/SharedStunSystem.cs b/Content.Shared/Stunnable/SharedStunSystem.cs index eee8e2a2fb..530b0252be 100644 --- a/Content.Shared/Stunnable/SharedStunSystem.cs +++ b/Content.Shared/Stunnable/SharedStunSystem.cs @@ -8,6 +8,9 @@ using Content.Shared.Inventory.Events; using Content.Shared.Item; using Content.Shared.Bed.Sleep; using Content.Shared.Database; +using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; +using Content.Shared.Mobs.Systems; using Content.Shared.Movement.Events; using Content.Shared.Movement.Systems; using Content.Shared.Standing; @@ -28,6 +31,7 @@ namespace Content.Shared.Stunnable [Dependency] private readonly StatusEffectsSystem _statusEffectSystem = default!; [Dependency] private readonly MovementSpeedModifierSystem _movementSpeedModifierSystem = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; + [Dependency] private readonly MobStateSystem _mobStateSystem = default!; [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!; /// @@ -71,6 +75,38 @@ namespace Content.Shared.Stunnable SubscribeLocalEvent(OnAttempt); SubscribeLocalEvent(OnEquipAttempt); SubscribeLocalEvent(OnUnequipAttempt); + SubscribeLocalEvent(OnMobStateChanged); + } + + + + private void OnMobStateChanged(EntityUid uid, MobStateComponent component, MobStateChangedEvent args) + { + if (!TryComp(uid, out var status)) + { + return; + } + switch (args.NewMobState) + { + case MobState.Alive: + { + break; + } + case MobState.Critical: + { + _statusEffectSystem.TryRemoveStatusEffect(uid, "Stun"); + break; + } + case MobState.Dead: + { + _statusEffectSystem.TryRemoveStatusEffect(uid, "Stun"); + break; + } + case MobState.Invalid: + default: + return; + } + } private void UpdateCanMove(EntityUid uid, StunnedComponent component, EntityEventArgs args) diff --git a/Content.Shared/Verbs/Verb.cs b/Content.Shared/Verbs/Verb.cs index a47af80856..e66f4ed570 100644 --- a/Content.Shared/Verbs/Verb.cs +++ b/Content.Shared/Verbs/Verb.cs @@ -1,6 +1,7 @@ using Robust.Shared.Serialization; using Robust.Shared.Utility; using Content.Shared.Database; +using Content.Shared.Interaction.Events; namespace Content.Shared.Verbs { diff --git a/Resources/Prototypes/Body/Parts/skeleton.yml b/Resources/Prototypes/Body/Parts/skeleton.yml index dc9d1ac1cd..ad07d69043 100644 --- a/Resources/Prototypes/Body/Parts/skeleton.yml +++ b/Resources/Prototypes/Body/Parts/skeleton.yml @@ -63,8 +63,8 @@ - type: Examiner - type: DoAfter - type: MobState - thresholds: - 0: Alive + allowedStates: + - Alive - type: Tag tags: - MindTransferTarget diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 5eaa51ce66..c64c0d0222 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -96,6 +96,7 @@ layer: - FlyingMobLayer - type: MobState + - type: MobThresholds thresholds: 0: Alive 5: Critical @@ -326,6 +327,7 @@ layer: - FlyingMobLayer - type: MobState + - type: MobThresholds thresholds: 0: Alive 5: Critical @@ -775,6 +777,7 @@ layer: - SmallMobLayer - type: MobState + - type: MobThresholds thresholds: 0: Alive 10: Critical @@ -1937,6 +1940,7 @@ layer: - SmallMobLayer - type: MobState + - type: MobThresholds thresholds: 0: Alive 40: Critical diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/bear.yml b/Resources/Prototypes/Entities/Mobs/NPCs/bear.yml index 0058bc19c8..8f863717c7 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/bear.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/bear.yml @@ -29,6 +29,10 @@ - MobLayer - type: MovementAlwaysTouching - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 150: Dead diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml index d8c7bb85c9..357e7e9719 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/carp.yml @@ -36,6 +36,7 @@ layer: - MobLayer - type: MobState + - type: MobThresholds thresholds: 0: Alive 50: Critical diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml index 357ad78cad..e3cc555eff 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/regalrat.yml @@ -36,6 +36,7 @@ layer: - SmallMobLayer - type: MobState + - type: MobThresholds thresholds: 0: Alive 150: Critical @@ -145,6 +146,7 @@ - map: ["enum.DamageStateVisualLayers.Base"] state: regalrat - type: MobState + - type: MobThresholds thresholds: 0: Alive 300: Critical @@ -214,6 +216,7 @@ layer: - SmallMobLayer - type: MobState + - type: MobThresholds thresholds: 0: Alive 40: Critical diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml index 9444735289..ace5fd81ec 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/revenant.yml @@ -62,7 +62,6 @@ interfaces: - key: enum.StoreUiKey.Key type: StoreBoundUserInterface - - type: MobState - type: Visibility layer: 2 #ghost vis layer - type: Store diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml index 98229a10dd..9267be8d23 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/silicon.yml @@ -73,6 +73,10 @@ - DoorBumpOpener - ShoesRequiredStepTriggerImmune - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 120: Dead diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml index 2e3ceae3a8..6b8112f820 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml @@ -90,6 +90,7 @@ types: Heat : 0.1 #per second, scales with temperature & other constants - type: MobState + - type: MobThresholds thresholds: 0: Alive 50: Critical diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml b/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml index ca8d4d51e5..76235ff429 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/spacetick.yml @@ -31,6 +31,10 @@ layer: - SmallMobLayer - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 15: Dead diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml index cb9b40d9db..31fade648f 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/xeno.yml @@ -54,6 +54,10 @@ layer: - MobLayer - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 200: Dead @@ -129,6 +133,10 @@ - map: ["enum.DamageStateVisualLayers.Base"] state: running - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 300: Dead @@ -161,6 +169,10 @@ - map: ["enum.DamageStateVisualLayers.Base"] state: running - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 200: Dead @@ -196,6 +208,10 @@ - map: ["enum.DamageStateVisualLayers.Base"] state: running - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 1500: Dead @@ -236,6 +252,10 @@ - map: ["enum.DamageStateVisualLayers.Base"] state: running - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 550: Dead @@ -276,6 +296,10 @@ - map: ["enum.DamageStateVisualLayers.Base"] state: running - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 250: Dead @@ -326,6 +350,10 @@ - map: ["enum.DamageStateVisualLayers.Base"] state: running - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 300: Dead diff --git a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml index cb25102821..f897fc3024 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/dragon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/dragon.yml @@ -66,6 +66,7 @@ layer: - FlyingMobLayer - type: MobState + - type: MobThresholds thresholds: 0: Alive 450: Critical diff --git a/Resources/Prototypes/Entities/Mobs/Player/familiars.yml b/Resources/Prototypes/Entities/Mobs/Player/familiars.yml index d3f6505ad8..88b26536ed 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/familiars.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/familiars.yml @@ -57,6 +57,7 @@ interactSuccessString: petting-success-corrupted-corgi interactFailureString: petting-failure-corrupted-corgi - type: MobState + - type: MobThresholds thresholds: 0: Alive 80: Critical diff --git a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml index bd89a53a2d..34303467f4 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/guardian.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/guardian.yml @@ -69,8 +69,8 @@ - type: Damageable damageContainer: Biological - type: MobState - thresholds: - 0: Alive + allowedStates: + - Alive - type: HeatResistance - type: CombatMode - type: Internals diff --git a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml index ab45665dba..9283281398 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/silicon.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/silicon.yml @@ -98,6 +98,10 @@ baseWalkSpeed : 5 baseSprintSpeed : 5 - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 60: Dead @@ -192,6 +196,10 @@ baseWalkSpeed : 3 baseSprintSpeed : 2 - type: MobState + allowedStates: + - Alive + - Dead + - type: MobThresholds thresholds: 0: Alive 1000: Dead diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 74383554a9..2ac1577bea 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -191,6 +191,7 @@ thermalRegulationTemperatureThreshold: 25 - type: Internals - type: MobState + - type: MobThresholds thresholds: 0: Alive 100: Critical @@ -371,6 +372,7 @@ - type: Damageable damageContainer: Biological - type: MobState + - type: MobThresholds thresholds: 0: Alive 100: Critical diff --git a/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml b/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml index 1faf9a31a5..80bf91f230 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/skeleton.yml @@ -31,6 +31,7 @@ types: Bloodloss: 0 - type: MobState + - type: MobThresholds thresholds: 0: Alive 100: Critical diff --git a/Resources/Prototypes/Entities/Objects/Fun/pai.yml b/Resources/Prototypes/Entities/Objects/Fun/pai.yml index 7b1679fe89..c5c4035cfb 100644 --- a/Resources/Prototypes/Entities/Objects/Fun/pai.yml +++ b/Resources/Prototypes/Entities/Objects/Fun/pai.yml @@ -47,8 +47,8 @@ # so they can ghost and come back. # Note that the personal AI never "dies". - type: MobState - thresholds: - 0: Alive + allowedStates: + - Alive - type: Appearance visuals: - type: GenericEnumVisualizer