#include "Runtime/GuiSys/CHudThreatInterface.hpp" #include #include "Runtime/GameGlobalObjects.hpp" #include "Runtime/GuiSys/CAuiEnergyBarT01.hpp" #include "Runtime/GuiSys/CGuiFrame.hpp" #include "Runtime/GuiSys/CGuiModel.hpp" #include "Runtime/GuiSys/CGuiTextPane.hpp" #include "Runtime/GuiSys/CStringTable.hpp" #include "Runtime/Audio/CSfxManager.hpp" namespace metaforce { constexpr std::array CoordFuncs{ CHudThreatInterface::CombatThreatBarCoordFunc, nullptr, CHudThreatInterface::XRayThreatBarCoordFunc, CHudThreatInterface::ThermalThreatBarCoordFunc, nullptr, }; constexpr std::array IconTranslateRanges{ 6.05f, 0.f, 0.f, 8.4f, 0.f, }; CHudThreatInterface::CHudThreatInterface(CGuiFrame& selHud, EHudType hudType, float threatDist) : x4_hudType(hudType), x10_threatDist(threatDist) { x58_basewidget_threatstuff = selHud.FindWidget("basewidget_threatstuff"); x5c_basewidget_threaticon = selHud.FindWidget("basewidget_threaticon"); x60_model_threatarrowup = static_cast(selHud.FindWidget("model_threatarrowup")); x64_model_threatarrowdown = static_cast(selHud.FindWidget("model_threatarrowdown")); x68_textpane_threatwarning = static_cast(selHud.FindWidget("textpane_threatwarning")); x6c_energybart01_threatbar = static_cast(selHud.FindWidget("energybart01_threatbar")); x70_textpane_threatdigits = static_cast(selHud.FindWidget("textpane_threatdigits")); if (x70_textpane_threatdigits) { x70_textpane_threatdigits->TextSupport().SetFontColor(g_tweakGuiColors->GetThreatDigitsFont()); x70_textpane_threatdigits->TextSupport().SetOutlineColor(g_tweakGuiColors->GetThreatDigitsOutline()); } x54_26_hasArrows = x60_model_threatarrowup && x64_model_threatarrowdown; x54_27_notXRay = hudType != EHudType::XRay; x5c_basewidget_threaticon->SetColor(g_tweakGuiColors->GetThreatIconColor()); x18_threatIconXf = x5c_basewidget_threaticon->GetLocalTransform(); x6c_energybart01_threatbar->SetFilledColor(g_tweakGuiColors->GetThreatBarFilled()); x6c_energybart01_threatbar->SetShadowColor(g_tweakGuiColors->GetThreatBarShadow()); x6c_energybart01_threatbar->SetEmptyColor(g_tweakGuiColors->GetThreatBarEmpty()); x6c_energybart01_threatbar->SetCoordFunc(CoordFuncs[size_t(hudType)]); x6c_energybart01_threatbar->SetTesselation(hudType == EHudType::Combat ? 1.f : 0.1f); x6c_energybart01_threatbar->SetMaxEnergy(g_tweakGui->GetThreatRange()); x6c_energybart01_threatbar->SetFilledDrainSpeed(9999.f); x6c_energybart01_threatbar->SetShadowDrainSpeed(9999.f); x6c_energybart01_threatbar->SetShadowDrainDelay(0.f); x6c_energybart01_threatbar->SetIsAlwaysResetTimer(false); if (x68_textpane_threatwarning) { x68_textpane_threatwarning->TextSupport().SetFontColor(g_tweakGuiColors->GetThreatWarningFont()); x68_textpane_threatwarning->TextSupport().SetOutlineColor(g_tweakGuiColors->GetThreatWarningOutline()); } } void CHudThreatInterface::SetThreatDistance(float threatDist) { x10_threatDist = threatDist; } void CHudThreatInterface::SetIsVisibleDebug(bool v) { x54_24_visibleDebug = v; UpdateVisibility(); } void CHudThreatInterface::SetIsVisibleGame(bool v) { x54_25_visibleGame = v; UpdateVisibility(); } void CHudThreatInterface::UpdateVisibility() { bool vis = x54_24_visibleDebug && x54_25_visibleGame; x58_basewidget_threatstuff->SetVisibility(vis, ETraversalMode::Children); if (vis) SetThreatDistance(0.f); } void CHudThreatInterface::Update(float dt) { zeus::CColor warningColor = zeus::CColor::lerp(g_tweakGuiColors->GetThreatIconColor(), g_tweakGuiColors->GetThreatIconWarningColor(), x50_warningColorLerp); float maxThreatEnergy = g_tweakGui->GetThreatRange(); if (x70_textpane_threatdigits) { if (x10_threatDist < maxThreatEnergy) { x70_textpane_threatdigits->SetIsVisible(true); x70_textpane_threatdigits->TextSupport().SetText( fmt::format(FMT_STRING("{:01.1f}"), std::max(0.f, x10_threatDist))); } else { x70_textpane_threatdigits->SetIsVisible(false); } } if (x54_26_hasArrows) { if (x14_arrowTimer > 0.f) { x60_model_threatarrowup->SetIsVisible(true); x14_arrowTimer = std::max(0.f, x14_arrowTimer - dt); zeus::CColor color = warningColor; color.a() = x14_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); x60_model_threatarrowup->SetColor(color); x64_model_threatarrowdown->SetIsVisible(false); } else if (x14_arrowTimer < 0.f) { x64_model_threatarrowdown->SetIsVisible(true); x14_arrowTimer = std::min(0.f, x14_arrowTimer + dt); zeus::CColor color = warningColor; color.a() = -x14_arrowTimer / g_tweakGui->GetMissileArrowVisTime(); x64_model_threatarrowdown->SetColor(color); x60_model_threatarrowup->SetIsVisible(false); } else { x60_model_threatarrowup->SetIsVisible(false); x64_model_threatarrowdown->SetIsVisible(false); } } if (x10_threatDist <= maxThreatEnergy) { float tmp = x10_threatDist - (maxThreatEnergy - x6c_energybart01_threatbar->GetSetEnergy()); if (tmp < -0.01f) x14_arrowTimer = g_tweakGui->GetMissileArrowVisTime(); else if (tmp > 0.01f) x14_arrowTimer = -g_tweakGui->GetMissileArrowVisTime(); } else { x14_arrowTimer = 0.f; } if (x10_threatDist <= maxThreatEnergy) { x6c_energybart01_threatbar->SetCurrEnergy(x6c_energybart01_threatbar->GetMaxEnergy() - x10_threatDist, CAuiEnergyBarT01::ESetMode::Normal); x5c_basewidget_threaticon->SetColor(warningColor); } else { x6c_energybart01_threatbar->SetCurrEnergy(0.f, CAuiEnergyBarT01::ESetMode::Normal); x5c_basewidget_threaticon->SetColor(g_tweakGuiColors->GetThreatIconSafeColor()); } if (x54_27_notXRay) { x5c_basewidget_threaticon->SetLocalTransform( x18_threatIconXf * zeus::CTransform::Translate(0.f, 0.f, std::max(0.f, maxThreatEnergy - x10_threatDist) * IconTranslateRanges[size_t(x4_hudType)] / maxThreatEnergy)); } if (x68_textpane_threatwarning) { if (x6c_energybart01_threatbar->GetActualFraction() > g_tweakGui->GetThreatWarningFraction()) x68_textpane_threatwarning->SetIsVisible(true); else x68_textpane_threatwarning->SetIsVisible(false); EThreatStatus newStatus; if (maxThreatEnergy == x6c_energybart01_threatbar->GetSetEnergy()) newStatus = EThreatStatus::Damage; else if (x6c_energybart01_threatbar->GetActualFraction() > g_tweakGui->GetThreatWarningFraction()) newStatus = EThreatStatus::Warning; else newStatus = EThreatStatus::Normal; if (x4c_threatStatus != newStatus) { std::u16string string; if (newStatus == EThreatStatus::Warning) string = g_MainStringTable->GetString(10); else if (newStatus == EThreatStatus::Damage) string = g_MainStringTable->GetString(11); x68_textpane_threatwarning->TextSupport().SetText(string); if (x4c_threatStatus == EThreatStatus::Normal && newStatus == EThreatStatus::Warning) CSfxManager::SfxStart(SFXui_threat_warning, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); else if (newStatus == EThreatStatus::Damage) CSfxManager::SfxStart(SFXui_threat_damage, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); x4c_threatStatus = newStatus; } } float oldX8 = x8_damagePulseTimer; x8_damagePulseTimer = std::fmod(x8_damagePulseTimer + dt, 0.5f); if (x8_damagePulseTimer < 0.25f) xc_damagePulse = x8_damagePulseTimer / 0.25f; else xc_damagePulse = (0.5f - x8_damagePulseTimer) / 0.25f; if (x4c_threatStatus == EThreatStatus::Damage && x8_damagePulseTimer < oldX8) CSfxManager::SfxStart(SFXui_threat_damage, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); if (x68_textpane_threatwarning) { if (x4c_threatStatus != EThreatStatus::Normal) { x48_warningLerpAlpha = std::min(x48_warningLerpAlpha + 2.f * dt, 1.f); zeus::CColor color = zeus::skWhite; color.a() = x48_warningLerpAlpha * xc_damagePulse; x68_textpane_threatwarning->SetColor(color); } else { x48_warningLerpAlpha = std::max(0.f, x48_warningLerpAlpha - 2.f * dt); zeus::CColor color = zeus::skWhite; color.a() = x48_warningLerpAlpha * xc_damagePulse; x68_textpane_threatwarning->SetColor(color); } if (x68_textpane_threatwarning->GetGeometryColor().a() > 0.f) x68_textpane_threatwarning->SetIsVisible(true); else x68_textpane_threatwarning->SetIsVisible(false); } if (x4c_threatStatus == EThreatStatus::Damage) x50_warningColorLerp = std::min(x50_warningColorLerp + 2.f * dt, 1.f); else x50_warningColorLerp = std::max(0.f, x50_warningColorLerp - 2.f * dt); } std::pair CHudThreatInterface::CombatThreatBarCoordFunc(float t) { const float z = IconTranslateRanges[size_t(EHudType::Combat)] * t; return {zeus::CVector3f(-0.3f, 0.f, z), zeus::CVector3f(0.f, 0.f, z)}; } std::pair CHudThreatInterface::XRayThreatBarCoordFunc(float t) { const float theta = 0.8f * (t - 0.5f); const float x = -9.55f * std::cos(theta); const float z = 9.55f * std::sin(theta); return {zeus::CVector3f(0.4f + x, 0.f, z), zeus::CVector3f(x, 0.f, z)}; } std::pair CHudThreatInterface::ThermalThreatBarCoordFunc(float t) { const float transRange = IconTranslateRanges[size_t(EHudType::Thermal)]; const float a = 0.08f * transRange; const float b = t * transRange; float c; if (b < a) { c = b / a; } else if (b < transRange - a) { c = 1.f; } else { c = 1.f - (b - (transRange - a)) / a; } return {zeus::CVector3f(0.1f, 0.f, b), zeus::CVector3f(0.5f * c + 0.1f, 0.f, b)}; } } // namespace metaforce