A Razor UI component for the powerup banner shown center-screen when a player picks up a powerup. It renders the banner text while showing and computes an opacity that holds at full for 60% of the duration then fades, and throttles rebuilds by bucketing the fade into 20 steps in BuildHash.
@using Sandbox;
@using Sandbox.UI;
@using NZombies;
@inherits PanelComponent
@*
POWERUP BANNER — the name of what you just picked up, centre screen.
⚠️ ITS OWN PanelComponent rather than a block inside SurvivalHud. The HUD hides
itself in creative and behind the lobby (see its `Visible`), and a powerup
collected in creative should still tell you it worked — that is most of how this
gets tested. Keeping it separate also means its fade cannot be throttled by the
HUD's deliberately coarse BuildHash.
⛔ The original shows TIMED powerups as a row of icons with countdowns
(cl_hud.lua's `powerup_poses`, seven slots offset from centre). Max Ammo is
INSTANT and never appears there — what it shows is the name. That row is the
right thing to build when the first timed powerup exists; this is not it.
*@
<root class="@HudTheme.Class">
@if ( PowerupBannerState.Showing )
{
<div class="banner" style="opacity: @Fade">@PowerupBannerState.Text</div>
}
</root>
@code
{
/// <summary>
/// Fades over the last part of its life.
///
/// ⚠️ HOLDS AT FULL, THEN FADES — it does not fade the whole time. A banner that
/// starts dimming the instant it appears is never seen at full strength, and this
/// one has to be readable in a firefight.
/// </summary>
float Fade
{
get
{
var d = PowerupBannerState.Duration;
var t = PowerupBannerState.Elapsed;
// Full for the first 60%, then out.
var holdUntil = d * 0.6f;
if ( t <= holdUntil ) return 1f;
var remaining = MathX.Clamp( (d - t) / System.MathF.Max( d - holdUntil, 0.01f ), 0f, 1f );
return remaining;
}
}
/// <summary>
/// ⚠️ REBUILDS ON THE FADE, bucketed to 20 steps. The opacity is inline, so the
/// tree has to rebuild for it to move — but hashing the raw float rebuilds every
/// frame for 2.5s. Twenty steps is smooth at this size and costs a twentieth of
/// the rebuilds.
/// </summary>
protected override int BuildHash() => System.HashCode.Combine(
PowerupBannerState.Showing, PowerupBannerState.Text, (int)(Fade * 20f), HudTheme.Class );
}