Code/Demos/ComposableHud/PlayerHealth.cs
using System;
using Sandbox;

namespace Sandbox.ComposableHud;

// Demo health store for the composable HUD. Attach to the player GameObject (which needs a Collider) and engine TriggerHurt volumes will damage it through Component.IDamageable; TriggerHurt calls OnDamage on IDamageable components it finds via GetComponentsInParent. PlayerHealthView reads this component each frame and renders the main HP bar in realtime.
[Title( "Player Health (Demo)" ), Category( "UI/Demo" ), Icon( "favorite" )]
public sealed class PlayerHealth : Component, Component.IDamageable
{
    [Property] public float MaxHealth      { get; set; } = 100f;
    [Property] public float Health         { get; set; } = 100f;
    [Property] public float RegenPerSecond { get; set; } = 2.5f;

    // Latest damage event, read by DamageIndicatorView to point a wedge at the source.
    // DamageEvents increments on every hit so the HUD can edge-detect new damage.
    public int     DamageEvents     { get; private set; }
    public Vector3 LastDamageOrigin { get; private set; }
    public float   LastDamageAmount { get; private set; }

    protected override void OnEnabled() => Health = MaxHealth;

    public void OnDamage( in DamageInfo damage )
    {
        Health = Math.Clamp( Health - damage.Damage, 0f, MaxHealth );
        LastDamageOrigin = damage.Origin;
        LastDamageAmount = damage.Damage;
        DamageEvents++;
    }

    protected override void OnUpdate()
    {
        if ( RegenPerSecond > 0f && Health < MaxHealth )
            Health = Math.Clamp( Health + RegenPerSecond * Time.Delta, 0f, MaxHealth );
    }
}