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