A UI Razor component that draws a 2D Hype Meter for the ChainReactionGame. It renders animated bubbles and a fill bar, subscribes to game state changes, updates on screen-shake changes, and computes fill percentage and CSS class based on game hype values.
@using Sandbox;
@using Sandbox.UI;
@inherits PanelComponent
@namespace Sandbox
<root>
@if (Game?.IsRunning == true @*&& (Game?.HypeMeter ?? 0f) > 0.01f*@)
{
<div class="hype-wrap @_currentShake">
<div class="hype-track">
@for (int i = 0; i < 6; i++)
{
float bBottom = (i * 16f) % 90f;
float bDur = 1.5f + (i * 0.25f) % 1.0f;
float bDelay = (i * 0.3f) % 2.0f;
<div class="hype-bubble"
style="bottom:@bBottom.ToString("F1")%;animation-duration:@bDur.ToString("F1")s;animation-delay:@bDelay.ToString("F1")s;">
</div>
}
<div class="hype-fill @GetFillClass()" style="height:@GetFillPct()%;">
@if ((Game?.HypeMeter ?? 0f) >= 0.2f)
{
<div class="hype-mult-label">
@(Game?.HypeMaxActive == true ? "🔥" : "▲")
</div>
}
</div>
</div>
</div>
}
</root>
@code {
ChainReactionGame Game => ChainReactionGame.Instance;
bool _sub = false;
string _currentShake = "";
protected override void OnTreeFirstBuilt() => TrySub();
void TrySub()
{
var g = Game;
if (g == null || _sub) return;
g.OnStateChanged += StateHasChanged;
_sub = true;
}
protected override void OnUpdate()
{
if (!_sub) TrySub();
// Screen Shake - everytime we call StateHasChanged() it rebuilds state
// and it plays the shake in the html code (since the _currentShake != "" but now has a class)
var shakeClass = ScreenShaker.Instance?.ShakeClass ?? "";
if (shakeClass != _currentShake)
{
_currentShake = shakeClass;
StateHasChanged();
}
}
float GetFillPct() => (Game?.HypeMeter ?? 0f) * 100f;
string GetFillClass()
{
float h = Game?.HypeMeter ?? 0f;
if (Game?.HypeMaxActive == true) return "hype-fill-max";
if (h >= 0.8f) return "hype-fill-high";
if (h >= 0.5f) return "hype-fill-mid";
if (h >= 0.2f) return "hype-fill-low";
return "hype-fill-empty";
}
protected override int BuildHash() =>
System.HashCode.Combine(Game?.IsRunning, Game?.HypeMeter, Game?.HypeMaxActive, _currentShake);
}