//#define HEATBUFFER_INDICATOR_DEBUG // Uncomment for heat buffer indicator debug logs
class IngameHudHeatBuffer
{
protected Widget m_Root;
protected float m_CurrentValue;
protected bool m_IsActive;
protected int m_CurrentDirection; // -1 = none | 0 = decreasing | 1 = increasing
protected int m_PreviousDirection; // -1 = none | 0 = decreasing | 1 = increasing
protected bool m_Update;
protected PlayerBase m_Player;
protected float m_EffectTime;
protected float m_EffectDuration;
protected bool m_FadeIn;
protected float m_FlashingTime;
protected int m_FlashingStage;
protected ref map<int, float> m_FlashingThresholds;
void IngameHudHeatBuffer(Widget root, notnull PlayerBase player)
{
m_Root = root;
m_Player = player;
player.GetOnDeathStart().Insert(OnPlayerNegativeCondition);
player.GetOnUnconsciousStart().Insert(OnPlayerNegativeCondition);
player.GetOnUnconsciousStop().Insert(OnPlayerConditionChanged);
m_CurrentDirection = -1;
m_PreviousDirection = -1;
m_Update = true;
m_FlashingStage = -1;
m_FlashingThresholds = new map<int, float>;
m_FlashingThresholds.Insert(1, 0.002);
m_FlashingThresholds.Insert(2, 0.332);
m_FlashingThresholds.Insert(3, 0.662);
}
void OnPlayerNegativeCondition(PlayerBase player)
{
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("IngameHudHeatBuffer::OnPlayerNegativeCondition");
#endif
if (player == m_Player)
m_Update = false;
}
void OnPlayerConditionChanged(PlayerBase player)
{
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("IngameHudHeatBuffer::OnPlayerConditionChanged");
#endif
if (player == m_Player)
m_Update = true;
}
bool CanUpdate()
{
return m_Player && m_Update;
}
void Update(float timeslice)
{
int heatBufferStage = m_Player.GetHeatBufferStage();
float heatBufferVal = m_Player.GetStatHeatBuffer().Get();
float heatBufferDynMax = m_Player.GetHeatBufferDynamicMax();
float heatBufferPercent = heatBufferVal / m_Player.GetStatHeatBuffer().GetMax();
float heatBufferDiff = heatBufferVal - m_CurrentValue;
m_CurrentValue = heatBufferVal;
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("-----------------------------------------------------------------------");
Print("Buff stage=" + heatBufferStage);
Print("Buff value=" + heatBufferVal);
Print("Buff percent=" + heatBufferPercent);
Print("Buff dynamic max=" + heatBufferDynMax);
Print("Effect active=" + m_IsActive);
Print("Last buff value=" + m_CurrentValue);
Print("Buff differance=" + heatBufferDiff);
Print("Prev Heat buffer direction=" + m_PreviousDirection);
Print("Flashing time=" + m_FlashingTime);
Print("Flashing stage=" + m_FlashingStage);
#endif
for (int i = 1; i < HeatBufferMdfr.NUMBER_OF_STAGES; ++i)
{
Widget hbw = m_Root.FindAnyWidget("HeatBuffer" + i);
if (!hbw)
continue;
float stageThreshold = HeatBufferMdfr.STAGE_THRESHOLDS[i];
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("Stage treshold=" + stageThreshold);
#endif
// Determine heat buffer direction.
// When heat buffer percentage value is higher the the heat buffer dynamic max value we prevent increasing for the indactor logic.
// Heat buffer Dynamic max value determines the max value the character can currently reach with his current heat insolation
if (heatBufferDiff > 0)
{
// If heat buffer percentage value is below or at current heat buffer dynamic max range value the direction cant change
if (heatBufferPercent < heatBufferDynMax)
{
m_CurrentDirection = 1;
}
else
{
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("HEAT BUFFER - DYNAMIC MAX REACHED - DONT CHANGE DIRECTION");
#endif
m_CurrentDirection = -1;
}
}
else if (heatBufferDiff < 0)
{
m_CurrentDirection = 0;
}
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("Heat buffer direction=" + m_CurrentDirection);
#endif
// Hide visibility of flashing stages
if (heatBufferStage < i && m_FlashingStage != i || m_FlashingStage == i && m_FlashingTime >= 2.9)
{
if (m_FlashingStage == i)
{
m_IsActive = false;
m_FlashingTime = 0;
m_FlashingStage = -1;
}
hbw.SetAlpha(0);
hbw.Show(false);
}
// Handle widget visibility and alpha based on stage and buffer percent
if (heatBufferStage >= i)
{
hbw.Show(true);
if (heatBufferPercent < stageThreshold)
{
if (m_CurrentDirection == 1)
{
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("HEAT BUFFER - STAGE " + i + " - INCREASING");
hbw.SetColor(ARGB(hbw.GetAlpha() * 255, 220, 220, 0)); // COLOR SET ON INDICATOR IS ONLY HERE FOR DEBUG TESTING FOR NOW
#endif
SetBaseAlpha(hbw, heatBufferPercent, stageThreshold);
if (m_PreviousDirection == 0 && m_IsActive)
{
m_IsActive = false;
m_FlashingTime = 0;
m_FlashingStage = -1;
}
UpdateEffect(hbw, 2.0, timeslice);
}
else if (m_CurrentDirection == 0)
{
#ifdef HEATBUFFER_IND ICATOR_DEBUG
Print("HEAT BUFFER - STAGE " + i + " - DECREASING");
#endif
SetBaseAlpha(hbw, heatBufferPercent, stageThreshold);
if (m_PreviousDirection == 1 && m_IsActive)
{
m_IsActive = false;
}
float flashingThreshold = m_FlashingThresholds.Get(i);
if (heatBufferDynMax < 0.5)
{
flashingThreshold = flashingThreshold + 0.002;
}
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("HEAT BUFFER - STAGE " + i + " - DECREASING - Flashing threshold=" + flashingThreshold);
hbw.SetColor(ARGB(hbw.GetAlpha() * 255, 0, 206, 209)); // COLOR SET ON INDICATOR IS ONLY HERE FOR DEBUG TESTING FOR NOW
#endif
if (heatBufferPercent <= flashingThreshold)
{
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("HEAT BUFFER - STAGE " + i + " - FLASHING");
#endif
#ifdef HEATBUFFER_INDICATOR_DEBUG
hbw.SetColor(ARGB(hbw.GetAlpha() * 255, 255, 0, 0)); // COLOR SET ON INDICATOR IS ONLY HERE FOR DEBUG TESTING FOR NOW
#endif
UpdateEffect(hbw, 0.25, timeslice);
m_FlashingTime += timeslice;
if (m_FlashingTime >= 2.9)
{
m_IsActive = false;
m_FlashingTime = 0;
m_FlashingStage = -1;
hbw.SetAlpha(0);
hbw.Show(false);
}
}
}
else if (m_CurrentDirection == -1)
{
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("HEAT BUFFER - STAGE " + i + " - STAL");
#endif
SetBaseAlpha(hbw, heatBufferPercent, stageThreshold);
}
}
else
{
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("HEAT BUFFER - STAGE " + i + " - MAXED");
#endif
hbw.SetAlpha(1.0);
#ifdef HEATBUFFER_INDICATOR_DEBUG
hbw.SetColor(ARGB(hbw.GetAlpha() * 255, 220, 220, 220)); // COLOR SET ON INDICATOR IS ONLY HERE FOR DEBUG TESTING FOR NOW
#endif
}
}
}
if (m_PreviousDirection != m_CurrentDirection)
m_PreviousDirection = m_CurrentDirection;
}
// Function that calculates and sets the base alpha value for the current heat buffer widget depending on the given heat buffer percentage value and stage threshold
void SetBaseAlpha(Widget hbw, float valuePercent, float stageThreshold)
{
float baseAlpha = Math.Lerp(0.05, 1.00, (valuePercent / stageThreshold));
baseAlpha = Math.Floor(baseAlpha * 100) / 100;
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("HEAT BUFFER - Set base alpha=" + baseAlpha + " | Widget=" + hbw.GetName());
#endif
hbw.SetAlpha(baseAlpha); // Set the current alpha to the base alpha
}
void UpdateEffect(Widget hbw, float duration, float timeslice)
{
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("HEAT BUFFER - EFFECT - Widget=" + hbw.GetName());
#endif
float baseAlpha = hbw.GetAlpha();
float opacity;
m_EffectDuration = duration;
// Initialize the effect if it's not already active
if (!m_IsActive)
{
m_EffectTime = 0;
m_FadeIn = true;
m_IsActive = true;
}
// Update the effect time
m_EffectTime += timeslice;
// Calculate the time fraction
float timeFraction = m_EffectTime / m_EffectDuration;
// Calculate opacity
if (m_FadeIn)
{
opacity = Math.Lerp(0.0, 1.0, timeFraction);
if (timeFraction >= 1.0)
{
m_FadeIn = false;
m_EffectTime = 0; // Reset for fade-out
}
}
else
{
opacity = Math.Lerp(1.0, 0.0, timeFraction);
if (timeFraction >= 1.0)
{
m_FadeIn = true;
m_EffectTime = 0; // Reset for fade-in
}
}
// Clamp the opacity to ensure it's within the valid range
opacity = Math.Clamp(opacity, 0.0, 1.0);
// Set the widget's alpha (opacity)
hbw.SetAlpha(opacity);
// Debug print statements
#ifdef HEATBUFFER_INDICATOR_DEBUG
Print("HEAT BUFFER - EFFECT - Opacity=" + opacity + " | Time Fraction=" + timeFraction + " | FadeIn=" + m_FadeIn + " | Effect time=" + m_EffectTime + " | Effect duration=" + m_EffectDuration);
#endif
}
}