A UI Razor component for spectator and results HUD. It shows current spectated player with input glyphs for prev/next, and when match results are active it shows the winner name and a countdown to lobby return.
@using Sandbox.UI;
@inherits PanelComponent
<root>
@if (isSpectating)
{
<div class="spectator">
<div class="spectator-target">Spectating: @(spectatingName ?? "...")</div>
<div class="spectator-hints">
<span class="hint hint-prev">
Prev
<Image class="glyph" [email protected]("Attack1", InputGlyphSize.Medium, GlyphStyle.Light) />
</span>
<span class="hint hint-next">
<Image class="glyph" [email protected]("Attack2", InputGlyphSize.Medium, GlyphStyle.Light) /> Next
</span>
</div>
</div>
}
@if (isShowingResults)
{
<div class="results">
<div class="results-name">@(winnerName ?? "...")</div>
<div class="results-wins">WINS!</div>
<div class="results-countdown">Returning to lobby in @resultsSecondsRemaining…</div>
</div>
}
</root>
@code {
[Property] public GameManager GameManager { get; set; }
[Property] public VictoryManager VictoryManager { get; set; }
private bool isSpectating;
private string spectatingName;
private bool isShowingResults;
private string winnerName;
private int resultsSecondsRemaining;
protected override void OnUpdate()
{
isShowingResults = VictoryManager?.IsShowingResults ?? false;
if (isShowingResults)
{
GameObject winnerGameObject = VictoryManager.Winner;
winnerName = winnerGameObject.IsValid()
? winnerGameObject.Network?.Owner?.DisplayName ?? "Winner"
: "Nobody";
resultsSecondsRemaining = System.Math.Max(0, (int)System.Math.Ceiling((float)VictoryManager.ResultsTimer));
}
else
{
winnerName = null;
resultsSecondsRemaining = 0;
}
SpectatorMode spectator = SpectatorMode.Current;
isSpectating = !isShowingResults && spectator != null && spectator.IsActive;
spectatingName = isSpectating ? spectator.SpectatingName : null;
}
protected override int BuildHash() => System.HashCode.Combine(isSpectating, spectatingName,
isShowingResults, winnerName, resultsSecondsRemaining, Input.UsingController);
}