diff --git a/Content.Shared/Mobs/Systems/MobThresholdSystem.cs b/Content.Shared/Mobs/Systems/MobThresholdSystem.cs index 1cb32543eb..f34240d8fe 100644 --- a/Content.Shared/Mobs/Systems/MobThresholdSystem.cs +++ b/Content.Shared/Mobs/Systems/MobThresholdSystem.cs @@ -5,7 +5,6 @@ using Content.Shared.Damage; using Content.Shared.FixedPoint; using Content.Shared.Mobs.Components; using Robust.Shared.GameStates; -using Robust.Shared.Utility; namespace Content.Shared.Mobs.Systems; @@ -52,6 +51,38 @@ public sealed class MobThresholdSystem : EntitySystem #region Public API + /// + /// Gets the next available state for a mob. + /// + /// Target entity + /// Supplied MobState + /// The following MobState. Can be null if there isn't one. + /// Threshold Component Owned by the target + /// True if the next mob state exists + public bool TryGetNextState( + EntityUid target, + MobState mobState, + [NotNullWhen(true)] out MobState? nextState, + MobThresholdsComponent? thresholdsComponent = null) + { + nextState = null; + if (!Resolve(target, ref thresholdsComponent)) + return false; + + MobState? min = null; + foreach (var state in thresholdsComponent.Thresholds.Values) + { + if (state <= mobState) + continue; + + if (min == null || state < min) + min = state; + } + + nextState = min; + return nextState != null; + } + /// /// Get the Damage Threshold for the appropriate state if it exists /// @@ -261,7 +292,7 @@ public sealed class MobThresholdSystem : EntitySystem threshold.Thresholds.Remove(damageThreshold); } threshold.Thresholds[damage] = mobState; - Dirty(threshold); + Dirty(target, threshold); VerifyThresholds(target, threshold); } @@ -291,7 +322,7 @@ public sealed class MobThresholdSystem : EntitySystem if (!Resolve(uid, ref component, false)) return; component.AllowRevives = val; - Dirty(component); + Dirty(uid, component); VerifyThresholds(uid, component); } @@ -344,42 +375,37 @@ public sealed class MobThresholdSystem : EntitySystem if (!threshold.TriggersAlerts) return; - var dict = threshold.StateAlertDict; - var healthAlert = AlertType.HumanHealth; - var critAlert = AlertType.HumanCrit; - var deadAlert = AlertType.HumanDead; - - dict.TryGetValue(MobState.Alive, out healthAlert); - dict.TryGetValue(MobState.Critical, out critAlert); - dict.TryGetValue(MobState.Dead, out deadAlert); - - switch (currentMobState) + if (!threshold.StateAlertDict.TryGetValue(currentMobState, out var currentAlert)) { - case MobState.Alive: + Log.Error($"No alert alert for mob state {currentMobState} for entity {ToPrettyString(target)}"); + return; + } + + if (!_alerts.TryGet(currentAlert, out var alertPrototype)) + { + Log.Error($"Invalid alert type {currentAlert}"); + return; + } + + if (alertPrototype.SupportsSeverity) + { + var severity = _alerts.GetMinSeverity(currentAlert); + if (TryGetNextState(target, currentMobState, out var nextState, threshold) && + TryGetPercentageForState(target, nextState.Value, damageable.TotalDamage, out var percentage)) { - var severity = _alerts.GetMinSeverity(healthAlert); - if (TryGetIncapPercentage(target, damageable.TotalDamage, out var percentage)) - { - severity = (short) MathF.Floor(percentage.Value.Float() * - _alerts.GetSeverityRange(healthAlert)); - severity += _alerts.GetMinSeverity(healthAlert); - } - _alerts.ShowAlert(target, healthAlert, severity); - break; + percentage = FixedPoint2.Clamp(percentage.Value, 0, 1); + + severity = (short) MathF.Round( + MathHelper.Lerp( + _alerts.GetMinSeverity(currentAlert), + _alerts.GetMaxSeverity(currentAlert), + percentage.Value.Float())); } - case MobState.Critical: - { - _alerts.ShowAlert(target, critAlert); - break; - } - case MobState.Dead: - { - _alerts.ShowAlert(target, deadAlert); - break; - } - case MobState.Invalid: - default: - throw new ArgumentOutOfRangeException(nameof(currentMobState), currentMobState, null); + _alerts.ShowAlert(target, currentAlert, severity); + } + else + { + _alerts.ShowAlert(target, currentAlert); } } diff --git a/Resources/Textures/Interface/Alerts/human_alive.rsi/health0.png b/Resources/Textures/Interface/Alerts/human_alive.rsi/health0.png index cce1b027b6..6c9b54e52e 100644 Binary files a/Resources/Textures/Interface/Alerts/human_alive.rsi/health0.png and b/Resources/Textures/Interface/Alerts/human_alive.rsi/health0.png differ diff --git a/Resources/Textures/Interface/Alerts/human_alive.rsi/health1.png b/Resources/Textures/Interface/Alerts/human_alive.rsi/health1.png index 2ec0eb6551..186d07386e 100644 Binary files a/Resources/Textures/Interface/Alerts/human_alive.rsi/health1.png and b/Resources/Textures/Interface/Alerts/human_alive.rsi/health1.png differ diff --git a/Resources/Textures/Interface/Alerts/human_alive.rsi/health2.png b/Resources/Textures/Interface/Alerts/human_alive.rsi/health2.png index 4fa9ffeccc..6463eb386f 100644 Binary files a/Resources/Textures/Interface/Alerts/human_alive.rsi/health2.png and b/Resources/Textures/Interface/Alerts/human_alive.rsi/health2.png differ diff --git a/Resources/Textures/Interface/Alerts/human_alive.rsi/health3.png b/Resources/Textures/Interface/Alerts/human_alive.rsi/health3.png index 0daa1136c4..d7b8d559ef 100644 Binary files a/Resources/Textures/Interface/Alerts/human_alive.rsi/health3.png and b/Resources/Textures/Interface/Alerts/human_alive.rsi/health3.png differ diff --git a/Resources/Textures/Interface/Alerts/human_alive.rsi/health4.png b/Resources/Textures/Interface/Alerts/human_alive.rsi/health4.png index ea55a429b2..9ae49ead79 100644 Binary files a/Resources/Textures/Interface/Alerts/human_alive.rsi/health4.png and b/Resources/Textures/Interface/Alerts/human_alive.rsi/health4.png differ