UI/PowerupTimerHud.razor

A UI Razor component that displays active timed powerups as icons with countdown seconds. It enumerates NZombies.ActivePowerups.All(), shows each powerup icon and remaining time, and uses a hashed BuildHash based on whole-second remaining times and HUD theme to optimize redraws.

Http Calls
@using Sandbox;
@using Sandbox.UI;
@using System.Linq;
@using NZombies;
@inherits PanelComponent

@*
    POWERUP TIMERS — icon plus countdown for whatever is running.

    ⚠️ Only TIMED powerups appear. Max Ammo, Bonus Points and Nuke are instant
    (`duration = 0` in the original) and announce themselves with the banner instead;
    membership of `ActivePowerups.Durations` is what decides, so there is no second
    list here to fall out of step with it.

    ⛔ The original gives each powerup a FIXED slot index (`powerup_poses`, seven
    positions offset from centre, with a second row above). That matters once several
    can run at once — a slot that slides sideways when a neighbour expires is worse
    than a gap. With two powerups a centred row reads fine; the fixed-slot layout is
    the right build when there are more.
*@

<root class="pw-timers @HudTheme.Class">
    @if ( Any )
    {
        <div class="row">
            @foreach ( var (kind, remaining) in NZombies.ActivePowerups.All() )
            {
                <div class="slot @(remaining <= 5f ? "ending" : "")">
                    <img class="icon" [email protected]( kind ) />
                    <div class="time">@remaining.CeilToInt()</div>
                </div>
            }
        </div>
    }
</root>

@code
{
    bool Any => NZombies.ActivePowerups.All().Any();

    /// <summary>
    /// ⚠️ Hashes the WHOLE ROW as a string, bucketed to whole seconds. Hashing the
    /// raw remaining floats rebuilds every frame for thirty seconds per powerup; the
    /// display only ever shows integers, so a second is the smallest change that can
    /// possibly matter.
    /// </summary>
    protected override int BuildHash()
    {
        var key = string.Join( ",", NZombies.ActivePowerups.All()
            .Select( p => $"{p.kind}:{p.remaining.CeilToInt()}" ) );

        return System.HashCode.Combine( key, HudTheme.Class );
    }
}