2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-10 08:27:43 +00:00

Additional HUD work

This commit is contained in:
Jack Andersen
2017-04-08 10:40:36 -10:00
parent 4a8bae2351
commit e070844e8a
25 changed files with 1049 additions and 94 deletions

View File

@@ -33,6 +33,7 @@ CSamusHud::CSamusHud(CStateManager& stateMgr)
x5d8_guiLights.resize(4);
x7ac_.resize(15);
UpdateStateTransition(1.f, stateMgr);
g_SamusHud = this;
for (int i=0 ; i<16 ; ++i)
x5ec_camFovTweaks[i] = 5.f * i + 40.f;
@@ -46,12 +47,12 @@ CSamusHud::CSamusHud(CStateManager& stateMgr)
x2a0_helmetIntf = std::make_unique<CHudHelmetInterface>(*x264_loadedFrmeHelmet);
rstl::prereserved_vector<bool, 4> hasVisors = BuildPlayerHasVisors(stateMgr);
x2a4_visorMenu = std::make_unique<CHudVisorBeamMenu>(x274_loadedFrmeBaseHud,
x2a4_visorMenu = std::make_unique<CHudVisorBeamMenu>(*x274_loadedFrmeBaseHud,
CHudVisorBeamMenu::EHudVisorBeamMenu::Visor,
hasVisors);
rstl::prereserved_vector<bool, 4> hasBeams = BuildPlayerHasBeams(stateMgr);
x2a8_beamMenu = std::make_unique<CHudVisorBeamMenu>(x274_loadedFrmeBaseHud,
x2a8_beamMenu = std::make_unique<CHudVisorBeamMenu>(*x274_loadedFrmeBaseHud,
CHudVisorBeamMenu::EHudVisorBeamMenu::Beam,
hasBeams);
@@ -63,6 +64,13 @@ CSamusHud::CSamusHud(CStateManager& stateMgr)
UpdateBallMode(stateMgr, true);
}
CSamusHud::~CSamusHud()
{
if (x3a4_damageSfx)
CSfxManager::RemoveEmitter(x3a4_damageSfx);
g_SamusHud = nullptr;
}
rstl::prereserved_vector<bool, 4> CSamusHud::BuildPlayerHasVisors(const CStateManager& mgr)
{
rstl::prereserved_vector<bool, 4> ret;
@@ -120,22 +128,385 @@ void CSamusHud::InitializeFrameGluePermanent(const CStateManager& mgr)
void CSamusHud::InitializeFrameGlueMutable(const CStateManager& mgr)
{
float lastTankEnergy = std::fmod(x2d0_playerHealth, CPlayerState::GetEnergyTankCapacity());
u32 tanksFilled = x2d0_playerHealth / CPlayerState::GetEnergyTankCapacity();
CPlayer& player = mgr.GetPlayer();
CPlayerState& playerState = *mgr.GetPlayerState();
CPlayerGun& gun = *player.GetPlayerGun();
float chargeFactor = gun.IsCharging() ? gun.GetChargeBeamFactor() : 0.f;
bool missilesActive = gun.GetMissleMode() == CPlayerGun::EMissleMode::Active;
bool lockedOnObj = player.GetLockonObjectId() != kInvalidUniqueId;
switch (x2bc_nextState)
{
case EHudState::Combat:
{
x2b4_bossEnergyIntf = std::make_unique<CHudBossEnergyInterface>(*x288_loadedSelectedHud);
x28c_energyIntf = std::make_unique<CHudEnergyInterface>(*x288_loadedSelectedHud, lastTankEnergy,
x2d4_totalEnergyTanks, tanksFilled,
bool(x2e0_27_energyLow), EHudType::Combat);
if (!x290_threatIntf)
x290_threatIntf = std::make_unique<CHudThreatInterface>(*x288_loadedSelectedHud, EHudType::Combat,
9999.f);
else
x290_threatIntf->SetIsVisibleGame(true);
if (!x294_missileIntf)
x294_missileIntf = std::make_unique<CHudMissileInterface>(*x288_loadedSelectedHud, x2dc_missileCapacity,
x2d8_missileAmount, chargeFactor, missilesActive,
EHudType::Combat, mgr);
else
x294_missileIntf->SetIsVisibleGame(true, mgr);
if (!x298_freeLookIntf)
x298_freeLookIntf = std::make_unique<CHudFreeLookInterface>(*x288_loadedSelectedHud, EHudType::Combat,
bool(x2e0_24_inFreeLook), bool(x2e0_25_lookControlHeld),
lockedOnObj);
else
x298_freeLookIntf->SetIsVisibleGame(true);
if (!x29c_decoIntf)
x29c_decoIntf = std::make_unique<CHudDecoInterfaceCombat>(*x288_loadedSelectedHud);
else
x29c_decoIntf->SetIsVisibleGame(true);
x2ac_radarIntf->SetIsVisibleGame(true);
x2a4_visorMenu->SetIsVisibleGame(true);
x2a8_beamMenu->SetIsVisibleGame(true);
InitializeDamageLight();
UpdateEnergy(0.f, mgr, true);
break;
}
case EHudState::Ball:
{
u32 numPBs = playerState.GetItemAmount(CPlayerState::EItemType::PowerBombs);
u32 pbCap = playerState.GetItemCapacity(CPlayerState::EItemType::PowerBombs);
u32 bombsAvailable;
if (gun.IsBombReady())
bombsAvailable = gun.GetBombCount();
else
bombsAvailable = 0;
x2b0_ballIntf = std::make_unique<CHudBallInterface>(*x288_loadedSelectedHud, numPBs, pbCap,
bombsAvailable, gun.IsPowerBombReady() &&
player.GetMorphballTransitionState() ==
CPlayer::EPlayerMorphBallState::Morphed,
playerState.HasPowerUp(
CPlayerState::EItemType::MorphBallBombs));
x28c_energyIntf = std::make_unique<CHudEnergyInterface>(*x288_loadedSelectedHud, lastTankEnergy,
x2d4_totalEnergyTanks, tanksFilled,
bool(x2e0_27_energyLow), EHudType::Ball);
x290_threatIntf.reset();
x294_missileIntf.reset();
x298_freeLookIntf.reset();
x29c_decoIntf.reset();
x3d4_damageLight = nullptr;
x2ac_radarIntf->SetIsVisibleGame(false);
x2a4_visorMenu->SetIsVisibleGame(false);
x2a8_beamMenu->SetIsVisibleGame(false);
UpdateEnergy(0.f, mgr, true);
break;
}
case EHudState::Scan:
{
x2b4_bossEnergyIntf.reset();
x28c_energyIntf = std::make_unique<CHudEnergyInterface>(*x288_loadedSelectedHud, lastTankEnergy,
x2d4_totalEnergyTanks, tanksFilled,
bool(x2e0_27_energyLow), EHudType::Scan);
x290_threatIntf.reset();
x294_missileIntf.reset();
x298_freeLookIntf = std::make_unique<CHudFreeLookInterface>(*x288_loadedSelectedHud, EHudType::Scan,
bool(x2e0_24_inFreeLook), bool(x2e0_25_lookControlHeld),
lockedOnObj);
x29c_decoIntf = std::make_unique<CHudDecoInterfaceScan>(*x288_loadedSelectedHud);
InitializeDamageLight();
UpdateEnergy(0.f, mgr, true);
break;
}
case EHudState::XRay:
{
x2b4_bossEnergyIntf = std::make_unique<CHudBossEnergyInterface>(*x288_loadedSelectedHud);
x28c_energyIntf = std::make_unique<CHudEnergyInterface>(*x288_loadedSelectedHud, lastTankEnergy,
x2d4_totalEnergyTanks, tanksFilled,
bool(x2e0_27_energyLow), EHudType::XRay);
x290_threatIntf = std::make_unique<CHudThreatInterface>(*x288_loadedSelectedHud, EHudType::XRay,
9999.f);
x294_missileIntf = std::make_unique<CHudMissileInterface>(*x288_loadedSelectedHud, x2dc_missileCapacity,
x2d8_missileAmount, chargeFactor, missilesActive,
EHudType::XRay, mgr);
x298_freeLookIntf = std::make_unique<CHudFreeLookInterfaceXRay>(*x288_loadedSelectedHud,
bool(x2e0_24_inFreeLook), bool(x2e0_25_lookControlHeld),
lockedOnObj);
x29c_decoIntf = std::make_unique<CHudDecoInterfaceXRay>(*x288_loadedSelectedHud);
InitializeDamageLight();
x2a4_visorMenu->SetIsVisibleGame(true);
x2a8_beamMenu->SetIsVisibleGame(true);
UpdateEnergy(0.f, mgr, true);
break;
}
case EHudState::Thermal:
{
x2b4_bossEnergyIntf = std::make_unique<CHudBossEnergyInterface>(*x288_loadedSelectedHud);
x28c_energyIntf = std::make_unique<CHudEnergyInterface>(*x288_loadedSelectedHud, lastTankEnergy,
x2d4_totalEnergyTanks, tanksFilled,
bool(x2e0_27_energyLow), EHudType::Thermal);
x290_threatIntf = std::make_unique<CHudThreatInterface>(*x288_loadedSelectedHud, EHudType::Thermal,
9999.f);
x294_missileIntf = std::make_unique<CHudMissileInterface>(*x288_loadedSelectedHud, x2dc_missileCapacity,
x2d8_missileAmount, chargeFactor, missilesActive,
EHudType::Thermal, mgr);
x298_freeLookIntf = std::make_unique<CHudFreeLookInterface>(*x288_loadedSelectedHud, EHudType::Thermal,
bool(x2e0_24_inFreeLook), bool(x2e0_25_lookControlHeld),
lockedOnObj);
x29c_decoIntf = std::make_unique<CHudDecoInterfaceThermal>(*x288_loadedSelectedHud);
InitializeDamageLight();
x2a4_visorMenu->SetIsVisibleGame(true);
x2a8_beamMenu->SetIsVisibleGame(true);
UpdateEnergy(0.f, mgr, true);
break;
}
case EHudState::None:
UninitializeFrameGlueMutable();
default: break;
}
}
void CSamusHud::UninitializeFrameGlueMutable()
{
x2b4_bossEnergyIntf.reset();
x28c_energyIntf.reset();
x29c_decoIntf.reset();
x290_threatIntf.reset();
x294_missileIntf.reset();
x298_freeLookIntf.reset();
x2b0_ballIntf.reset();
x3d4_damageLight = nullptr;
}
void CSamusHud::InitializeDamageLight()
{
s16 lightId = x288_loadedSelectedHud->GetWidgetIdDB().AddWidget("DamageSpotLight");
s16 parentId = x288_loadedSelectedHud->FindWidget("basewidget_pivot")->GetSelfId();
CGuiWidget::CGuiWidgetParms parms(x288_loadedSelectedHud, false, lightId,
parentId, true, true, false,
g_tweakGuiColors->GetHudDamageLightColor(),
CGuiWidget::EGuiModelDrawFlags::Alpha, false, false);
std::shared_ptr<CGuiLight> light = std::make_shared<CGuiLight>(
parms, CLight::BuildSpot(zeus::CVector3f::skZero, zeus::CVector3f::skForward,
zeus::CColor::skWhite, g_tweakGui->GetHudDamageLightSpotAngle()));
x3d4_damageLight = light.get();
x3d4_damageLight->SetColor(zeus::CColor::skWhite);
zeus::CColor lightColor = g_tweakGuiColors->GetHudFrameColor();
lightColor.r *= lightColor.a;
lightColor.g *= lightColor.a;
lightColor.b *= lightColor.a;
lightColor.a = 1.f;
x3d4_damageLight->SetColor(lightColor);
x3d4_damageLight->SetDistC(1.f);
x3d4_damageLight->SetDistL(0.f);
x3d4_damageLight->SetAngleC(g_tweakGui->GetDamageLightAngleC());
x3d4_damageLight->SetAngleL(g_tweakGui->GetDamageLightAngleL());
x3d4_damageLight->SetAngleQ(g_tweakGui->GetDamageLightAngleQ());
x3d4_damageLight->SetLoadedIdx(4);
x3d4_damageLight->SetLocalTransform(zeus::CTransform::Identity());
x288_loadedSelectedHud->RegisterLight(std::move(light));
x288_loadedSelectedHud->FindWidget(parentId)->AddChildWidget(x3d4_damageLight, false, true);
x288_loadedSelectedHud->AddLight(x3d4_damageLight);
zeus::CTransform lightXf = zeus::CTransform::Translate(g_tweakGui->GetDamageLightPreTranslate());
x3d8_lightTransforms.clear();
x3d8_lightTransforms.reserve(10);
zeus::CTransform negX = zeus::CTransform::RotateX(zeus::degToRad(-g_tweakGui->GetDamageLightXfXAngle()));
zeus::CTransform posX = zeus::CTransform::RotateX(zeus::degToRad(g_tweakGui->GetDamageLightXfXAngle()));
zeus::CTransform negZ = zeus::CTransform::RotateZ(zeus::degToRad(-g_tweakGui->GetDamageLightXfZAngle()));
zeus::CTransform posZ = zeus::CTransform::RotateZ(zeus::degToRad(g_tweakGui->GetDamageLightXfZAngle()));
x3d8_lightTransforms.push_back(lightXf);
x3d8_lightTransforms.push_back(zeus::CTransform::Translate(g_tweakGui->GetDamageLightCenterTranslate()) * lightXf);
x3d8_lightTransforms.push_back(posX * lightXf);
x3d8_lightTransforms.push_back(posX * negZ * lightXf);
x3d8_lightTransforms.push_back(negZ * lightXf);
x3d8_lightTransforms.push_back(negX * negZ * lightXf);
x3d8_lightTransforms.push_back(negX * lightXf);
x3d8_lightTransforms.push_back(negX * posZ * lightXf);
x3d8_lightTransforms.push_back(posZ * lightXf);
x3d8_lightTransforms.push_back(posX * posZ * lightXf);
}
void CSamusHud::UpdateEnergy(float dt, const CStateManager& mgr, bool init)
{
CPlayer& player = mgr.GetPlayer();
CPlayerState& playerState = *mgr.GetPlayerState();
float energy = std::max(0.f, std::ceil(playerState.GetHealthInfo().GetHP()));
u32 numEnergyTanks = playerState.GetItemCapacity(CPlayerState::EItemType::EnergyTanks);
x2e0_27_energyLow = player.IsEnergyLow(mgr);
if (init || energy != x2d0_playerHealth || numEnergyTanks != x2d4_totalEnergyTanks)
{
float lastTankEnergy = energy;
u32 filledTanks = 0;
while (lastTankEnergy > CPlayerState::GetBaseHealthCapacity())
{
++filledTanks;
lastTankEnergy -= CPlayerState::GetEnergyTankCapacity();
}
if (x2bc_nextState != EHudState::None)
{
if (x28c_energyIntf)
{
float curLastTankEnergy = x2d0_playerHealth;
while (curLastTankEnergy > CPlayerState::GetBaseHealthCapacity())
curLastTankEnergy -= CPlayerState::GetEnergyTankCapacity();
x28c_energyIntf->SetCurrEnergy(lastTankEnergy, curLastTankEnergy < lastTankEnergy);
}
x2d0_playerHealth = energy;
if (x28c_energyIntf)
{
x28c_energyIntf->SetNumTotalEnergyTanks(numEnergyTanks);
x28c_energyIntf->SetNumFilledEnergyTanks(filledTanks);
x28c_energyIntf->SetEnergyLow(x2e0_27_energyLow);
}
x2d4_totalEnergyTanks = numEnergyTanks;
}
}
if (x2b4_bossEnergyIntf)
{
const CEntity* bossEnt = mgr.GetObjectById(mgr.GetBossId());
if (TCastToConstPtr<CActor> act = bossEnt)
{
if (const CHealthInfo* hInfo = act->GetHealthInfo())
{
float bossEnergy = std::ceil(hInfo->GetHP());
x2b4_bossEnergyIntf->SetBossParams(true, g_MainStringTable->GetString(mgr.GetBossStringIdx()),
bossEnergy, mgr.GetTotalBossEnergy());
}
else
{
x2b4_bossEnergyIntf->SetBossParams(false, u"", 0.f, 0.f);
}
}
else
{
x2b4_bossEnergyIntf->SetBossParams(false, u"", 0.f, 0.f);
}
}
}
void CSamusHud::UpdateFreeLook(float dt, const CStateManager& mgr)
{
TCastToConstPtr<CFirstPersonCamera> fpCam = mgr.GetCameraManager()->GetCurrentCamera(mgr);
CPlayer& player = mgr.GetPlayer();
bool inFreeLook = player.IsInFreeLook() && fpCam;
bool lookControlHeld = player.IsLookControlHeld();
if (x2e0_24_inFreeLook != inFreeLook)
{
if (inFreeLook)
CSfxManager::SfxStart(1392, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
else
CSfxManager::SfxStart(1390, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
x2e0_24_inFreeLook = inFreeLook;
}
float deltaFrames = 60.f * dt * 0.999999f;
float oldLookDeltaDot = x574_lookDeltaDot;
zeus::CVector3f fpCamDir;
if (!fpCam)
fpCamDir = x568_fpCamDir;
else
fpCamDir = fpCam->GetTransform().basis[1];
bool lookAdj = inFreeLook ? lookControlHeld : false;
if (lookAdj)
{
x574_lookDeltaDot = fpCamDir.dot(x568_fpCamDir);
if (std::fabs(x574_lookDeltaDot) > 1.f)
x574_lookDeltaDot = (x574_lookDeltaDot >= 0.f) ? 1.f : -1.f;
}
else
{
x574_lookDeltaDot = 1.f;
}
x568_fpCamDir = fpCamDir;
if ((oldLookDeltaDot >= deltaFrames && x574_lookDeltaDot < deltaFrames) ||
(oldLookDeltaDot < deltaFrames && x574_lookDeltaDot >= deltaFrames))
{
x578_freeLookSfxCycleTimer = 0.f;
}
else if (x578_freeLookSfxCycleTimer < 0.05f)
{
x578_freeLookSfxCycleTimer = std::min(x578_freeLookSfxCycleTimer + dt, 0.05f);
if (x578_freeLookSfxCycleTimer == 0.05f)
{
if (x574_lookDeltaDot < deltaFrames)
{
if (!x564_freeLookSfx)
x564_freeLookSfx = CSfxManager::SfxStart(1394, 1.f, 0.f, true, 0x7f, true, kInvalidAreaId);
}
else
{
CSfxManager::SfxStop(x564_freeLookSfx);
x564_freeLookSfx.reset();
}
}
}
if (fpCam)
{
zeus::CMatrix3f camRot = fpCam->GetTransform().buildMatrix3f();
zeus::CVector3f camDir(camRot[1]);
zeus::CUnitVector3f camDirNoZ(camDir.x, camDir.y, 0.f);
float offHorizonDot = camDir.dot(camDirNoZ);
if (std::fabs(offHorizonDot) > 1.f)
offHorizonDot = (offHorizonDot >= 0.f) ? 1.f : -1.f;
float offHorizonAngle = std::fabs(std::acos(offHorizonDot));
if (camDir.z < 0.f)
offHorizonAngle = -offHorizonAngle;
if (x298_freeLookIntf)
x298_freeLookIntf->SetFreeLookState(inFreeLook, lookControlHeld,
player.GetLockonObjectId() != kInvalidUniqueId,
offHorizonAngle);
if (x564_freeLookSfx)
{
float pitch = offHorizonAngle * (g_tweakGui->GetFreeLookSfxPitchScale() / 8192.f) / (M_PIF / 2.f);
if (!g_tweakGui->GetNoAbsoluteFreeLookSfxPitch())
pitch = std::fabs(pitch);
CSfxManager::PitchBend(x564_freeLookSfx, pitch);
}
}
}
void CSamusHud::UpdateMissile(float dt, const CStateManager& mgr, bool init)
@@ -479,8 +850,8 @@ void CSamusHud::Update(float dt, const CStateManager& mgr,
x288_loadedSelectedHud->Update(dt);
if (x2b4_bossEnergyIntf)
x2b4_bossEnergyIntf->Update(dt);
if (x28c_ballEnergyIntf)
x28c_ballEnergyIntf->Update(dt, x580_energyLowPulse);
if (x28c_energyIntf)
x28c_energyIntf->Update(dt, x580_energyLowPulse);
if (x290_threatIntf)
x290_threatIntf->Update(dt);
if (x294_missileIntf)