metaforce/Runtime/MP1/CPlayerVisor.cpp

668 lines
26 KiB
C++

#include "Runtime/MP1/CPlayerVisor.hpp"
#include "Runtime/CSimplePool.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/GameGlobalObjects.hpp"
#include "Runtime/Camera/CGameCamera.hpp"
#include "Runtime/Graphics/CCubeRenderer.hpp"
#include "Runtime/Graphics/CModel.hpp"
#include "Runtime/GuiSys/CCompoundTargetReticle.hpp"
#include "Runtime/GuiSys/CTargetingManager.hpp"
#include "Runtime/World/CPlayer.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path
namespace metaforce::MP1 {
CPlayerVisor::CPlayerVisor(CStateManager&) {
xcc_scanFrameCorner = g_SimplePool->GetObj("CMDL_ScanFrameCorner");
xd8_scanFrameCenterSide = g_SimplePool->GetObj("CMDL_ScanFrameCenterSide");
xe4_scanFrameCenterTop = g_SimplePool->GetObj("CMDL_ScanFrameCenterTop");
xf0_scanFrameStretchSide = g_SimplePool->GetObj("CMDL_ScanFrameStretchSide");
xfc_scanFrameStretchTop = g_SimplePool->GetObj("CMDL_ScanFrameStretchTop");
x108_newScanPane = g_SimplePool->GetObj("CMDL_NewScanPane");
x114_scanShield = g_SimplePool->GetObj("CMDL_ScanShield");
x124_scanIconNoncritical = g_SimplePool->GetObj("CMDL_ScanIconNoncritical");
x130_scanIconCritical = g_SimplePool->GetObj("CMDL_ScanIconCritical");
x13c_scanTargets.resize(64);
x540_xrayPalette = g_SimplePool->GetObj("TXTR_XRayPalette");
x0_scanWindowSizes.push_back({});
x0_scanWindowSizes.push_back({g_tweakGui->GetScanWindowIdleWidth(), g_tweakGui->GetScanWindowIdleHeight()});
x0_scanWindowSizes.push_back({g_tweakGui->GetScanWindowActiveWidth(), g_tweakGui->GetScanWindowActiveHeight()});
}
CPlayerVisor::~CPlayerVisor() {
CSfxManager::SfxStop(x5c_visorLoopSfx);
CSfxManager::SfxStop(x60_scanningLoopSfx);
}
int CPlayerVisor::FindEmptyInactiveScanTarget() const {
for (size_t i = 0; i < x13c_scanTargets.size(); ++i) {
const SScanTarget& tgt = x13c_scanTargets[i];
if (tgt.x4_timer == 0.f)
return i;
}
return -1;
}
int CPlayerVisor::FindCachedInactiveScanTarget(TUniqueId uid) const {
for (size_t i = 0; i < x13c_scanTargets.size(); ++i) {
const SScanTarget& tgt = x13c_scanTargets[i];
if (tgt.x0_objId == uid && tgt.x4_timer > 0.f)
return i;
}
return -1;
}
bool CPlayerVisor::DrawScanObjectIndicators(const CStateManager& mgr) {
if (!x124_scanIconNoncritical.IsLoaded() || !x130_scanIconCritical.IsLoaded())
return false;
if (!x114_scanShield.IsLoaded())
return false;
CGraphics::SetDepthRange(DEPTH_WORLD, DEPTH_FAR);
g_Renderer->SetViewportOrtho(true, 0.f, 4096.f);
float vpScale = CGraphics::GetViewportHeight() / 448.f;
CGraphics::SetModelMatrix(zeus::CTransform::Scale(x48_interpWindowDims.x() * 17.f * vpScale, 1.f,
x48_interpWindowDims.y() * 17.f * vpScale));
x114_scanShield->Draw(CModelFlags(5, 0, 3, zeus::skClear));
const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr);
zeus::CTransform camMtx = mgr.GetCameraManager()->GetCurrentCameraTransform(mgr);
CGraphics::SetViewPointMatrix(camMtx);
zeus::CFrustum frustum;
frustum.updatePlanes(
camMtx, zeus::CProjection(zeus::SProjPersp(
cam->GetFov(), CGraphics::GetViewportWidth() / float(CGraphics::GetViewportHeight()), 1.f, 100.f)));
g_Renderer->SetClippingPlanes(frustum);
g_Renderer->SetPerspective(cam->GetFov(), CGraphics::GetViewportWidth(), CGraphics::GetViewportHeight(),
cam->GetNearClipDistance(), cam->GetFarClipDistance());
for (const SScanTarget& tgt : x13c_scanTargets) {
if (tgt.x4_timer == 0.f)
continue;
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(tgt.x0_objId)) {
if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable))
continue;
const CScannableObjectInfo* scanInfo = act->GetScannableObjectInfo();
CModel* useModel;
const zeus::CColor* useColor;
const zeus::CColor* useDimColor;
if (scanInfo->IsImportant()) {
useModel = x130_scanIconCritical.GetObj();
useColor = &g_tweakGuiColors->GetScanIconCriticalColor();
useDimColor = &g_tweakGuiColors->GetScanIconCriticalDimColor();
} else {
useModel = x124_scanIconNoncritical.GetObj();
useColor = &g_tweakGuiColors->GetScanIconNoncriticalColor();
useDimColor = &g_tweakGuiColors->GetScanIconNoncriticalDimColor();
}
zeus::CVector3f scanPos = act->GetScanObjectIndicatorPosition(mgr);
float scale = CCompoundTargetReticle::CalculateClampedScale(
scanPos, 1.f, g_tweakTargeting->GetScanTargetClampMin(), g_tweakTargeting->GetScanTargetClampMax(), mgr);
zeus::CTransform xf(zeus::CMatrix3f(scale) * camMtx.basis, scanPos);
float scanRange = g_tweakPlayer->GetScanningRange();
float farRange = g_tweakPlayer->GetScanMaxLockDistance() - scanRange;
float farT;
if (farRange <= 0.f)
farT = 1.f;
else
farT = zeus::clamp(0.f, 1.f - ((scanPos - camMtx.origin).magnitude() - scanRange) / farRange, 1.f);
zeus::CColor iconColor = zeus::CColor::lerp(*useColor, *useDimColor, tgt.x8_inRangeTimer);
float iconAlpha;
if (mgr.GetPlayerState()->GetScanTime(scanInfo->GetScannableObjectId()) == 1.f) {
iconAlpha = tgt.x4_timer * 0.25f;
} else {
float tmp = 1.f;
if (mgr.GetPlayer().GetOrbitTargetId() == tgt.x0_objId)
tmp = 0.75f * x2c_scanDimInterp + 0.25f;
iconAlpha = tgt.x4_timer * tmp;
}
CGraphics::SetModelMatrix(xf);
iconColor.a() *= iconAlpha * farT;
useModel->Draw(CModelFlags(7, 0, 1, iconColor));
}
}
CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN);
return true;
}
void CPlayerVisor::UpdateScanObjectIndicators(const CStateManager& mgr, float dt) {
bool inBoxExists = false;
float dt2 = dt * 2.f;
for (SScanTarget& tgt : x13c_scanTargets) {
tgt.x4_timer = std::max(0.f, tgt.x4_timer - dt);
if (mgr.GetPlayer().ObjectInScanningRange(tgt.x0_objId, mgr))
tgt.x8_inRangeTimer = std::max(0.f, tgt.x8_inRangeTimer - dt2);
else
tgt.x8_inRangeTimer = std::min(1.f, tgt.x8_inRangeTimer + dt2);
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(tgt.x0_objId)) {
const CGameCamera* cam = mgr.GetCameraManager()->GetCurrentCamera(mgr);
zeus::CVector3f orbitPos = act->GetOrbitPosition(mgr);
orbitPos = cam->ConvertToScreenSpace(orbitPos);
orbitPos.x() = orbitPos.x() * CGraphics::GetViewportWidth() / 2.f + CGraphics::GetViewportWidth() / 2.f;
orbitPos.y() = orbitPos.y() * CGraphics::GetViewportHeight() / 2.f + CGraphics::GetViewportHeight() / 2.f;
bool inBox = mgr.GetPlayer().WithinOrbitScreenBox(orbitPos, mgr.GetPlayer().GetOrbitZone(),
mgr.GetPlayer().GetOrbitType());
if (inBox != tgt.xc_inBox) {
tgt.xc_inBox = inBox;
if (inBox)
x550_scanFrameColorImpulseInterp = 1.f;
}
inBoxExists |= inBox;
}
}
if (inBoxExists)
x54c_scanFrameColorInterp = std::min(x54c_scanFrameColorInterp + dt2, 1.f);
else
x54c_scanFrameColorInterp = std::max(0.f, x54c_scanFrameColorInterp - dt2);
x550_scanFrameColorImpulseInterp = std::max(0.f, x550_scanFrameColorImpulseInterp - dt);
dt += FLT_EPSILON;
TAreaId playerArea = mgr.GetPlayer().GetAreaIdAlways();
for (TUniqueId id : mgr.GetPlayer().GetNearbyOrbitObjects()) {
if (TCastToConstPtr<CActor> act = mgr.GetObjectById(id)) {
if (act->GetAreaIdAlways() != playerArea)
continue;
if (!act->GetMaterialList().HasMaterial(EMaterialTypes::Scannable))
continue;
int target = FindCachedInactiveScanTarget(id);
if (target != -1) {
SScanTarget& sTarget = x13c_scanTargets[target];
sTarget.x4_timer = std::min(sTarget.x4_timer + dt2, 1.f);
continue;
}
target = FindEmptyInactiveScanTarget();
if (target != -1) {
SScanTarget& sTarget = x13c_scanTargets[target];
sTarget.x0_objId = id;
sTarget.x4_timer = dt;
sTarget.x8_inRangeTimer = 1.f;
sTarget.xc_inBox = false;
}
}
}
}
void CPlayerVisor::UpdateScanWindow(float dt, const CStateManager& mgr) {
UpdateScanObjectIndicators(mgr, dt);
if (mgr.GetPlayer().GetScanningState() == CPlayer::EPlayerScanState::Scanning) {
if (!x60_scanningLoopSfx)
x60_scanningLoopSfx =
CSfxManager::SfxStart(SFXui_scanning_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId);
} else {
CSfxManager::SfxStop(x60_scanningLoopSfx);
x60_scanningLoopSfx.reset();
}
EScanWindowState desiredState = GetDesiredScanWindowState(mgr);
switch (x34_nextState) {
case EScanWindowState::NotInScanVisor:
if (desiredState != EScanWindowState::NotInScanVisor) {
if (x30_prevState == EScanWindowState::NotInScanVisor)
x48_interpWindowDims = x0_scanWindowSizes[int(desiredState)];
x50_nextWindowDims = x0_scanWindowSizes[int(desiredState)];
x40_prevWindowDims = x48_interpWindowDims;
x30_prevState = x34_nextState;
x34_nextState = desiredState;
x38_windowInterpDuration =
(desiredState == EScanWindowState::Scan) ? g_tweakGui->GetScanSidesEndTime() - x3c_windowInterpTimer : 0.f;
x3c_windowInterpTimer = x38_windowInterpDuration;
}
break;
case EScanWindowState::Idle:
if (desiredState != EScanWindowState::Idle) {
x50_nextWindowDims = (desiredState == EScanWindowState::NotInScanVisor) ? x48_interpWindowDims
: x0_scanWindowSizes[int(desiredState)];
x40_prevWindowDims = x48_interpWindowDims;
x30_prevState = x34_nextState;
x34_nextState = desiredState;
x38_windowInterpDuration =
(desiredState == EScanWindowState::Scan) ? g_tweakGui->GetScanSidesEndTime() - x3c_windowInterpTimer : 0.f;
x3c_windowInterpTimer = x38_windowInterpDuration;
if (desiredState == EScanWindowState::Scan)
CSfxManager::SfxStart(SFXui_into_scan_window, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId);
}
break;
case EScanWindowState::Scan:
if (desiredState != EScanWindowState::Scan) {
x50_nextWindowDims = (desiredState == EScanWindowState::NotInScanVisor) ? x48_interpWindowDims
: x0_scanWindowSizes[int(desiredState)];
x40_prevWindowDims = x48_interpWindowDims;
x30_prevState = x34_nextState;
x34_nextState = desiredState;
x38_windowInterpDuration =
(desiredState == EScanWindowState::Idle) ? g_tweakGui->GetScanSidesEndTime() - x3c_windowInterpTimer : 0.f;
x3c_windowInterpTimer = x38_windowInterpDuration;
if (mgr.GetPlayerState()->GetVisorTransitionFactor() == 1.f)
CSfxManager::SfxStart(SFXui_outof_scan_window, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId);
}
break;
default:
break;
}
if (x30_prevState != x34_nextState) {
x3c_windowInterpTimer = std::max(0.f, x3c_windowInterpTimer - dt);
if (x3c_windowInterpTimer == 0.f)
x30_prevState = x34_nextState;
float t = 0.f;
if (x38_windowInterpDuration > 0.f) {
float scanSidesDuration = g_tweakGui->GetScanSidesDuration();
float scanSidesStart = g_tweakGui->GetScanSidesStartTime();
if (x34_nextState == EScanWindowState::Scan)
t = (x3c_windowInterpTimer < scanSidesDuration) ? 0.f
: (x3c_windowInterpTimer - scanSidesDuration) / scanSidesStart;
else
t = (x3c_windowInterpTimer > scanSidesStart) ? 1.f : x3c_windowInterpTimer / scanSidesStart;
}
x48_interpWindowDims = x50_nextWindowDims * (1.f - t) + x40_prevWindowDims * t;
}
}
CPlayerVisor::EScanWindowState CPlayerVisor::GetDesiredScanWindowState(const CStateManager& mgr) const {
if (mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::EPlayerVisor::Scan) {
switch (mgr.GetPlayer().GetScanningState()) {
case CPlayer::EPlayerScanState::Scanning:
case CPlayer::EPlayerScanState::ScanComplete:
return EScanWindowState::Scan;
default:
return EScanWindowState::Idle;
}
}
return EScanWindowState::NotInScanVisor;
}
void CPlayerVisor::LockUnlockAssets() {
if (x1c_curVisor == CPlayerState::EPlayerVisor::Scan) {
x120_assetLockCountdown = 2;
} else if (x120_assetLockCountdown > 0) {
--x120_assetLockCountdown;
}
if (x120_assetLockCountdown > 0) {
xcc_scanFrameCorner.Lock();
xd8_scanFrameCenterSide.Lock();
xe4_scanFrameCenterTop.Lock();
xf0_scanFrameStretchSide.Lock();
xfc_scanFrameStretchTop.Lock();
x108_newScanPane.Lock();
x114_scanShield.Lock();
x124_scanIconNoncritical.Lock();
x130_scanIconCritical.Lock();
} else {
xcc_scanFrameCorner.Unlock();
xd8_scanFrameCenterSide.Unlock();
xe4_scanFrameCenterTop.Unlock();
xf0_scanFrameStretchSide.Unlock();
xfc_scanFrameStretchTop.Unlock();
x108_newScanPane.Unlock();
x114_scanShield.Unlock();
x124_scanIconNoncritical.Unlock();
x130_scanIconCritical.Unlock();
}
}
void CPlayerVisor::DrawScanEffect(const CStateManager& mgr, CTargetingManager* tgtMgr) {
SCOPED_GRAPHICS_DEBUG_GROUP("CPlayerVisor::DrawScanEffect", zeus::skMagenta);
const bool indicatorsDrawn = DrawScanObjectIndicators(mgr);
if (tgtMgr && indicatorsDrawn) {
CGraphics::SetDepthRange(DEPTH_TARGET_MANAGER, DEPTH_TARGET_MANAGER);
tgtMgr->Draw(mgr, false);
CGraphics::SetDepthRange(DEPTH_SCREEN_ACTORS, DEPTH_GUN);
}
const float transFactor = mgr.GetPlayerState()->GetVisorTransitionFactor();
const float scanSidesDuration = g_tweakGui->GetScanSidesDuration();
const float scanSidesStart = g_tweakGui->GetScanSidesStartTime();
float t;
if (x34_nextState == EScanWindowState::Scan) {
t = 1.f - ((x3c_windowInterpTimer < scanSidesDuration)
? 0.f
: (x3c_windowInterpTimer - scanSidesDuration) / scanSidesStart);
} else {
t = (x3c_windowInterpTimer > scanSidesStart) ? 1.f : x3c_windowInterpTimer / scanSidesStart;
}
const float vpScale = CGraphics::GetViewportHeight() / 448.f;
float divisor = (transFactor * ((1.f - t) * x58_scanMagInterp + t * g_tweakGui->GetScanWindowScanningAspect()) +
(1.f - transFactor));
divisor = 1.f / divisor;
float vpW = 169.218f * x48_interpWindowDims.x() * divisor;
vpW = zeus::clamp(0.f, vpW, 640.f) * vpScale;
float vpH = 152.218f * x48_interpWindowDims.y() * divisor;
vpH = zeus::clamp(0.f, vpH, 448.f) * vpScale;
SClipScreenRect rect;
rect.x4_left = int((CGraphics::GetViewportWidth() - vpW) / 2.f);
rect.x8_top = int((CGraphics::GetViewportHeight() - vpH) / 2.f);
rect.xc_width = int(vpW);
rect.x10_height = int(vpH);
CGraphics::ResolveSpareTexture(rect, 0, GX_TF_RGB565);
{
SCOPED_GRAPHICS_DEBUG_GROUP("x64_scanDim Draw", zeus::skMagenta);
x64_scanDim.Draw();
}
g_Renderer->SetViewportOrtho(true, -1.f, 1.f);
const zeus::CTransform windowScale = zeus::CTransform::Scale(x48_interpWindowDims.x(), 1.f, x48_interpWindowDims.y());
const zeus::CTransform seventeenScale = zeus::CTransform::Scale(17.f * vpScale, 1.f, 17.f * vpScale);
const zeus::CTransform mm = seventeenScale * windowScale;
g_Renderer->SetModelMatrix(mm);
CGraphics::LoadDolphinSpareTexture(0, GX_TF_RGB565, GX_TEXMAP0);
if (x108_newScanPane) {
SCOPED_GRAPHICS_DEBUG_GROUP("x108_newScanPane Draw", zeus::skMagenta);
x108_newScanPane->Draw(CModelFlags{5, 0, 7, zeus::CColor{1.f, transFactor}});
}
CGraphics::SetCullMode(ERglCullMode::None);
zeus::CColor frameColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanFrameInactiveColor(),
g_tweakGuiColors->GetScanFrameActiveColor(), x54c_scanFrameColorInterp);
frameColor.a() = transFactor;
CModelFlags flags(5, 0, 0,
frameColor + g_tweakGuiColors->GetScanFrameImpulseColor() *
zeus::CColor(x550_scanFrameColorImpulseInterp, x550_scanFrameColorImpulseInterp));
const zeus::CTransform verticalFlip = zeus::CTransform::Scale(1.f, 1.f, -1.f);
const zeus::CTransform horizontalFlip = zeus::CTransform::Scale(-1.f, 1.f, 1.f);
if (xe4_scanFrameCenterTop.IsLoaded()) {
const zeus::CTransform modelXf =
seventeenScale * zeus::CTransform::Translate(windowScale * zeus::CVector3f(0.f, 0.f, 4.553f));
CGraphics::SetModelMatrix(modelXf);
xe4_scanFrameCenterTop->Draw(flags);
CGraphics::SetModelMatrix(verticalFlip * modelXf);
xe4_scanFrameCenterTop->Draw(flags);
}
if (xd8_scanFrameCenterSide.IsLoaded()) {
const zeus::CTransform modelXf =
seventeenScale * zeus::CTransform::Translate(windowScale * zeus::CVector3f(-5.f, 0.f, 0.f));
CGraphics::SetModelMatrix(modelXf);
xd8_scanFrameCenterSide->Draw(flags);
CGraphics::SetModelMatrix(horizontalFlip * modelXf);
xd8_scanFrameCenterSide->Draw(flags);
}
if (xcc_scanFrameCorner.IsLoaded()) {
const zeus::CTransform modelXf =
seventeenScale * zeus::CTransform::Translate(windowScale * zeus::CVector3f(-5.f, 0.f, 4.553f));
CGraphics::SetModelMatrix(modelXf);
xcc_scanFrameCorner->Draw(flags);
CGraphics::SetModelMatrix(horizontalFlip * modelXf);
xcc_scanFrameCorner->Draw(flags);
CGraphics::SetModelMatrix(verticalFlip * modelXf);
xcc_scanFrameCorner->Draw(flags);
CGraphics::SetModelMatrix(verticalFlip * horizontalFlip * modelXf);
xcc_scanFrameCorner->Draw(flags);
}
if (xfc_scanFrameStretchTop.IsLoaded()) {
const zeus::CTransform modelXf = seventeenScale *
zeus::CTransform::Translate(-1.f, 0.f, 4.553f * windowScale.basis[2][2]) *
zeus::CTransform::Scale(5.f * windowScale.basis[0][0] - 1.f - 1.884f, 1.f, 1.f);
CGraphics::SetModelMatrix(modelXf);
xfc_scanFrameStretchTop->Draw(flags);
CGraphics::SetModelMatrix(horizontalFlip * modelXf);
xfc_scanFrameStretchTop->Draw(flags);
CGraphics::SetModelMatrix(verticalFlip * modelXf);
xfc_scanFrameStretchTop->Draw(flags);
CGraphics::SetModelMatrix(verticalFlip * horizontalFlip * modelXf);
xfc_scanFrameStretchTop->Draw(flags);
}
if (xf0_scanFrameStretchSide.IsLoaded()) {
const zeus::CTransform modelXf = seventeenScale *
zeus::CTransform::Translate(-5.f * windowScale.basis[0][0], 0.f, 1.f) *
zeus::CTransform::Scale(1.f, 1.f, 4.553f * windowScale.basis[2][2] - 1.f - 1.886f);
CGraphics::SetModelMatrix(modelXf);
xf0_scanFrameStretchSide->Draw(flags);
CGraphics::SetModelMatrix(horizontalFlip * modelXf);
xf0_scanFrameStretchSide->Draw(flags);
CGraphics::SetModelMatrix(verticalFlip * modelXf);
xf0_scanFrameStretchSide->Draw(flags);
CGraphics::SetModelMatrix(verticalFlip * horizontalFlip * modelXf);
xf0_scanFrameStretchSide->Draw(flags);
}
CGraphics::SetCullMode(ERglCullMode::Front);
}
void CPlayerVisor::DrawXRayEffect(const CStateManager&) {
SCOPED_GRAPHICS_DEBUG_GROUP("CPlayerVisor::DrawXRayEffect", zeus::skMagenta);
x90_xrayBlur.Draw();
}
void CPlayerVisor::DrawThermalEffect(const CStateManager&) {
// Empty
}
void CPlayerVisor::UpdateCurrentVisor(float transFactor) {
switch (x1c_curVisor) {
case CPlayerState::EPlayerVisor::XRay:
x90_xrayBlur.SetBlur(EBlurType::Xray, 36.f * transFactor, 0.f, false);
break;
case CPlayerState::EPlayerVisor::Scan: {
zeus::CColor dimColor =
zeus::CColor::lerp(g_tweakGuiColors->GetScanVisorHudLightMultiply(), zeus::skWhite, 1.f - transFactor);
x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, dimColor, CAssetId());
break;
}
default:
break;
}
}
void CPlayerVisor::FinishTransitionIn() {
switch (x1c_curVisor) {
case CPlayerState::EPlayerVisor::Combat:
x90_xrayBlur.DisableBlur(0.f);
break;
case CPlayerState::EPlayerVisor::XRay:
x90_xrayBlur.SetBlur(EBlurType::Xray, 36.f, 0.f, false);
if (!x5c_visorLoopSfx)
x5c_visorLoopSfx =
CSfxManager::SfxStart(SFXui_visor_xray_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId);
break;
case CPlayerState::EPlayerVisor::Scan: {
zeus::CColor dimColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanVisorScreenDimColor(),
g_tweakGuiColors->GetScanVisorHudLightMultiply(), x2c_scanDimInterp);
x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, dimColor, {});
if (!x5c_visorLoopSfx)
x5c_visorLoopSfx =
CSfxManager::SfxStart(SFXui_visor_scan_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId);
break;
}
case CPlayerState::EPlayerVisor::Thermal:
if (!x5c_visorLoopSfx)
x5c_visorLoopSfx =
CSfxManager::SfxStart(SFXui_visor_thermal_lp, x24_visorSfxVol, 0.f, false, 0x7f, true, kInvalidAreaId);
break;
default:
break;
}
}
void CPlayerVisor::BeginTransitionIn(const CStateManager&) {
switch (x1c_curVisor) {
case CPlayerState::EPlayerVisor::XRay:
x90_xrayBlur.SetBlur(EBlurType::Xray, 0.f, 0.f, false);
xc4_vpScaleX = 0.9f;
xc8_vpScaleY = 0.9f;
CSfxManager::SfxStart(SFXui_into_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId);
break;
case CPlayerState::EPlayerVisor::Scan:
CSfxManager::SfxStart(SFXui_into_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId);
x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, zeus::skWhite, {});
break;
case CPlayerState::EPlayerVisor::Thermal:
CSfxManager::SfxStart(SFXui_into_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId);
break;
default:
break;
}
}
void CPlayerVisor::FinishTransitionOut(const CStateManager&) {
switch (x1c_curVisor) {
case CPlayerState::EPlayerVisor::XRay:
x90_xrayBlur.DisableBlur(0.f);
xc4_vpScaleX = 1.f;
xc8_vpScaleY = 1.f;
break;
case CPlayerState::EPlayerVisor::Scan:
x64_scanDim.DisableFilter(0.f);
x34_nextState = EScanWindowState::NotInScanVisor;
x30_prevState = EScanWindowState::NotInScanVisor;
break;
case CPlayerState::EPlayerVisor::Thermal:
x90_xrayBlur.DisableBlur(0.f);
break;
default:
break;
}
}
void CPlayerVisor::BeginTransitionOut() {
if (x5c_visorLoopSfx) {
CSfxManager::SfxStop(x5c_visorLoopSfx);
x5c_visorLoopSfx.reset();
}
switch (x1c_curVisor) {
case CPlayerState::EPlayerVisor::XRay:
CSfxManager::SfxStart(SFXui_outof_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId);
break;
case CPlayerState::EPlayerVisor::Scan:
if (x60_scanningLoopSfx) {
CSfxManager::SfxStop(x60_scanningLoopSfx);
x60_scanningLoopSfx.reset();
}
CSfxManager::SfxStart(SFXui_outof_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId);
break;
case CPlayerState::EPlayerVisor::Thermal:
CSfxManager::SfxStart(SFXui_outof_visor, x24_visorSfxVol, 0.f, false, 0x7f, false, kInvalidAreaId);
break;
default:
break;
}
}
void CPlayerVisor::Update(float dt, const CStateManager& mgr) {
x90_xrayBlur.Update(dt);
CPlayerState& playerState = *mgr.GetPlayerState();
CPlayerState::EPlayerVisor activeVisor = playerState.GetActiveVisor(mgr);
CPlayerState::EPlayerVisor curVisor = playerState.GetCurrentVisor();
CPlayerState::EPlayerVisor transVisor = playerState.GetTransitioningVisor();
bool visorTransitioning = playerState.GetIsVisorTransitioning();
UpdateScanWindow(dt, mgr);
if (x20_nextVisor != transVisor)
x20_nextVisor = transVisor;
LockUnlockAssets();
if (mgr.GetPlayer().GetScanningState() == CPlayer::EPlayerScanState::ScanComplete)
x2c_scanDimInterp = std::max(0.f, x2c_scanDimInterp - 2.f * dt);
else
x2c_scanDimInterp = std::min(x2c_scanDimInterp + 2.f * dt, 1.f);
if (visorTransitioning) {
if (!x25_24_visorTransitioning)
BeginTransitionOut();
if (x1c_curVisor != curVisor) {
FinishTransitionOut(mgr);
x1c_curVisor = curVisor;
BeginTransitionIn(mgr);
}
UpdateCurrentVisor(playerState.GetVisorTransitionFactor());
} else {
if (x25_24_visorTransitioning) {
FinishTransitionIn();
} else if (curVisor == CPlayerState::EPlayerVisor::Scan) {
zeus::CColor dimColor = zeus::CColor::lerp(g_tweakGuiColors->GetScanVisorScreenDimColor(),
g_tweakGuiColors->GetScanVisorHudLightMultiply(), x2c_scanDimInterp);
x64_scanDim.SetFilter(EFilterType::Multiply, EFilterShape::Fullscreen, 0.f, dimColor, {});
}
}
x25_24_visorTransitioning = visorTransitioning;
if (x1c_curVisor != activeVisor) {
if (x24_visorSfxVol != 0.f) {
x24_visorSfxVol = 0.f;
CSfxManager::SfxVolume(x5c_visorLoopSfx, x24_visorSfxVol);
CSfxManager::SfxVolume(x60_scanningLoopSfx, x24_visorSfxVol);
}
} else {
if (x24_visorSfxVol != 1.f) {
x24_visorSfxVol = 1.f;
CSfxManager::SfxVolume(x5c_visorLoopSfx, x24_visorSfxVol);
CSfxManager::SfxVolume(x60_scanningLoopSfx, x24_visorSfxVol);
}
}
float scanMag = g_tweakGui->GetScanWindowMagnification();
if (x58_scanMagInterp < scanMag)
x58_scanMagInterp = std::min(x58_scanMagInterp + 2.f * dt, scanMag);
else
x58_scanMagInterp = std::max(x58_scanMagInterp - 2.f * dt, scanMag);
}
void CPlayerVisor::Draw(const CStateManager& mgr, CTargetingManager* tgtManager) {
CGraphics::SetAmbientColor(zeus::skWhite);
CGraphics::DisableAllLights();
switch (mgr.GetPlayerState()->GetActiveVisor(mgr)) {
case CPlayerState::EPlayerVisor::XRay:
DrawXRayEffect(mgr);
break;
case CPlayerState::EPlayerVisor::Thermal:
DrawThermalEffect(mgr);
break;
case CPlayerState::EPlayerVisor::Scan:
DrawScanEffect(mgr, tgtManager);
break;
default:
break;
}
}
void CPlayerVisor::Touch() {
if (x124_scanIconNoncritical.IsLoaded())
x124_scanIconNoncritical->Touch(0);
if (x130_scanIconCritical.IsLoaded())
x130_scanIconCritical->Touch(0);
}
float CPlayerVisor::GetDesiredViewportScaleX(const CStateManager& mgr) const {
return mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Combat ? 1.f : xc4_vpScaleX;
}
float CPlayerVisor::GetDesiredViewportScaleY(const CStateManager& mgr) const {
return mgr.GetPlayerState()->GetActiveVisor(mgr) == CPlayerState::EPlayerVisor::Combat ? 1.f : xc8_vpScaleY;
}
} // namespace metaforce::MP1