Razor UI component for the player HUD health display. It renders current health (with overheal icon), temporary heal/damage floating numbers, and updates visibility/timers each Tick. It exposes Instance and handlers OnHealing and OnDamage to update screen number elements.
@namespace KOTH.UI
@inherits Panel
@attribute [StyleSheet]
@if ( !Player.IsValid() )
return;
<root>
@if (Player.DamageComponent.IsOverhealed())
{
<img class="hp-img" src="/ui/koth/hp.png"/>
}
<label class="hp" style="color: white;">@(Player.DamageComponent.GetHealthString() ?? "∞")</label>
@if (CurrentHealthElement.IsVisable)
{
<label class="hp-noti">@(CurrentHealthElement)</label>
}
@* we aint got else ifs? *@
@if (!CurrentHealthElement.IsVisable && CurrentDamageElement.IsVisable)
{
<label class="dmg-noti">@(CurrentDamageElement)</label>
}
</root>
@code
{
public static Health Instance { get; set; }
public Health()
{
Instance = this;
}
public PlayerPawn Player => PlayerState.Local.PlayerPawn;
FScreenNumberElement CurrentHealthElement = new()
{
IsDamage = false,
IsVisable = false,
};
FScreenNumberElement CurrentDamageElement = new()
{
IsDamage = true,
IsVisable = false,
};
public override void Tick()
{
base.Tick();
if (CurrentHealthElement.DisplayedTime < -1)
{
CurrentHealthElement.IsVisable = false;
}
if (CurrentDamageElement.DisplayedTime < -1)
{
CurrentDamageElement.IsVisable = false;
}
}
protected override int BuildHash()
{
if (!Player.IsValid())
return 0;
return HashCode.Combine(Time.Now);
}
public void OnHealing(FHealingReceived HealingDone)
{
if (HealingDone.Heals < 0.05f || HealingDone.HealingType == EHealingType.Continuous)
{
return;
}
if (!CurrentHealthElement.IsVisable)
{
CurrentHealthElement.Damage = 0;
CurrentHealthElement.IsVisable = true;
}
CurrentHealthElement.DisplayedTime = 0;
CurrentHealthElement.AddDamage(HealingDone.Heals);
}
public void OnDamage(FDamageTaken DamageTaken)
{
if (DamageTaken.Damage < 0.05f)
{
return;
}
if (!CurrentDamageElement.IsVisable)
{
CurrentDamageElement.Damage = 0;
CurrentDamageElement.IsVisable = true;
}
CurrentDamageElement.DisplayedTime = 0;
CurrentDamageElement.AddDamage(DamageTaken.Damage);
}
}