Damage masks (#9402)
This commit is contained in:
132
Content.Client/MobState/MobStateSystem.cs
Normal file
132
Content.Client/MobState/MobStateSystem.cs
Normal file
@@ -0,0 +1,132 @@
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.FixedPoint;
|
||||
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 IPlayerManager _playerManager = default!;
|
||||
private Overlays.DamageOverlay _overlay = default!;
|
||||
|
||||
public const short Levels = 7;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_overlay = new Overlays.DamageOverlay();
|
||||
IoCManager.Resolve<IOverlayManager>().AddOverlay(_overlay);
|
||||
|
||||
SubscribeLocalEvent<PlayerAttachedEvent>(OnPlayerAttach);
|
||||
SubscribeLocalEvent<PlayerDetachedEvent>(OnPlayerDetach);
|
||||
SubscribeLocalEvent<MobStateComponent, ComponentHandleState>(OnMobHandleState);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
IoCManager.Resolve<IOverlayManager>().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<MobStateComponent>(ev.Entity, out var mobState) && TryComp<DamageableComponent>(ev.Entity, out var damageable))
|
||||
{
|
||||
SetLevel(mobState, damageable.TotalDamage);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPlayerDetach(PlayerDetachedEvent ev)
|
||||
{
|
||||
_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;
|
||||
|
||||
_overlay.State = DamageState.Alive;
|
||||
_overlay.BruteLevel = 0f;
|
||||
_overlay.OxygenLevel = 0f;
|
||||
_overlay.CritLevel = 0f;
|
||||
|
||||
if (!TryComp<DamageableComponent>(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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user