From 8c59ace5fe3e768e3fe4273ecf5d6e5c29ac3080 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 16 Sep 2019 14:41:10 -0400 Subject: [PATCH 1/3] CMorphBall: Clean up includes --- Runtime/World/CMorphBall.cpp | 35 ++++++++++++++++++----------------- Runtime/World/CMorphBall.hpp | 31 +++++++++++++++++-------------- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/Runtime/World/CMorphBall.cpp b/Runtime/World/CMorphBall.cpp index 1c2b6eff6..0d0fe5387 100644 --- a/Runtime/World/CMorphBall.cpp +++ b/Runtime/World/CMorphBall.cpp @@ -1,20 +1,21 @@ -#include "GameGlobalObjects.hpp" -#include "CDependencyGroup.hpp" -#include "CMorphBall.hpp" -#include "CPlayer.hpp" -#include "CSimplePool.hpp" -#include "CGameLight.hpp" -#include "World/CWorld.hpp" -#include "World/CScriptAreaAttributes.hpp" -#include "TCastTo.hpp" -#include "Camera/CGameCamera.hpp" -#include "Collision/CGameCollision.hpp" -#include "CScriptSpiderBallAttractionSurface.hpp" -#include "CScriptSpiderBallWaypoint.hpp" -#include "CScriptWater.hpp" -#include "Graphics/CSkinnedModel.hpp" -#include "MP1/World/CMetroidBeta.hpp" -#include "Input/ControlMapper.hpp" +#include "Runtime/World/CMorphBall.hpp" + +#include "Runtime/CDependencyGroup.hpp" +#include "Runtime/CSimplePool.hpp" +#include "Runtime/TCastTo.hpp" +#include "Runtime/Camera/CGameCamera.hpp" +#include "Runtime/Collision/CGameCollision.hpp" +#include "Runtime/GameGlobalObjects.hpp" +#include "Runtime/Graphics/CSkinnedModel.hpp" +#include "Runtime/Input/ControlMapper.hpp" +#include "Runtime/MP1/World/CMetroidBeta.hpp" +#include "Runtime/World/CGameLight.hpp" +#include "Runtime/World/CPlayer.hpp" +#include "Runtime/World/CScriptAreaAttributes.hpp" +#include "Runtime/World/CScriptSpiderBallAttractionSurface.hpp" +#include "Runtime/World/CScriptSpiderBallWaypoint.hpp" +#include "Runtime/World/CScriptWater.hpp" +#include "Runtime/World/CWorld.hpp" namespace urde { diff --git a/Runtime/World/CMorphBall.hpp b/Runtime/World/CMorphBall.hpp index b3d7d77f6..8e8136f48 100644 --- a/Runtime/World/CMorphBall.hpp +++ b/Runtime/World/CMorphBall.hpp @@ -1,26 +1,29 @@ #pragma once -#include "World/CActor.hpp" -#include "World/ScriptObjectSupport.hpp" -#include "zeus/CVector3f.hpp" -#include "Collision/CCollidableSphere.hpp" -#include "RetroTypes.hpp" -#include "Character/CAnimCharacterSet.hpp" -#include "Particle/CParticleSwoosh.hpp" -#include "Particle/CElementGen.hpp" -#include "CWorldShadow.hpp" -#include "Graphics/CRainSplashGenerator.hpp" -#include "CMorphBallShadow.hpp" -#include "Collision/CCollisionInfoList.hpp" +#include "Runtime/RetroTypes.hpp" +#include "Runtime/Collision/CCollidableSphere.hpp" +#include "Runtime/Collision/CCollisionInfoList.hpp" +#include "Runtime/Graphics/CRainSplashGenerator.hpp" +#include "Runtime/Particle/CElementGen.hpp" +#include "Runtime/Particle/CParticleSwoosh.hpp" +#include "Runtime/World/CActor.hpp" +#include "Runtime/World/CMorphBallShadow.hpp" +#include "Runtime/World/CWorldShadow.hpp" +#include "Runtime/World/ScriptObjectSupport.hpp" + +#include +#include +#include namespace urde { class CActorLights; -class CPlayer; class CDamageInfo; -struct CFinalInput; +class CPlayer; class CScriptWater; class CStateManager; +struct CFinalInput; + class CMorphBall { public: enum class EBallBoostState { BoostAvailable, BoostDisabled }; From e4b22ea9d81374b2c57cfa34227caa19c48eb3a1 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 16 Sep 2019 14:51:17 -0400 Subject: [PATCH 2/3] CMorphBall: Place internally linked data within an anonymous namespace Keeps all internal data within one place and also prevents any potential ODR violations from occurring in relation to any of these. --- Runtime/World/CMorphBall.cpp | 233 +++++++++++++++++++---------------- 1 file changed, 126 insertions(+), 107 deletions(-) diff --git a/Runtime/World/CMorphBall.cpp b/Runtime/World/CMorphBall.cpp index 0d0fe5387..8d4f1ade5 100644 --- a/Runtime/World/CMorphBall.cpp +++ b/Runtime/World/CMorphBall.cpp @@ -18,8 +18,133 @@ #include "Runtime/World/CWorld.hpp" namespace urde { +namespace { +float kSpiderBallCollisionRadius; -static float kSpiderBallCollisionRadius; +constexpr std::pair kBallCharacterTable[] = { + {"SamusBallANCS", 0}, {"SamusBallANCS", 0}, {"SamusBallANCS", 1}, {"SamusBallANCS", 0}, + {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}, +}; + +constexpr std::pair kBallLowPolyTable[] = { + {"SamusBallLowPolyCMDL", 0}, {"SamusBallLowPolyCMDL", 0}, {"SamusBallLowPolyCMDL", 1}, + {"SamusBallLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 2}, + {"SamusBallFusionLowPolyCMDL", 1}, {"SamusBallFusionLowPolyCMDL", 3}, +}; + +constexpr std::pair kSpiderBallLowPolyTable[] = { + {"SamusSpiderBallLowPolyCMDL", 0}, {"SamusSpiderBallLowPolyCMDL", 0}, {"SamusSpiderBallLowPolyCMDL", 1}, + {"SamusSpiderBallLowPolyCMDL", 2}, {"SamusBallFusionLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 2}, + {"SamusBallFusionLowPolyCMDL", 1}, {"SamusBallFusionLowPolyCMDL", 3}, +}; + +constexpr std::pair kSpiderBallCharacterTable[] = { + {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 1}, {"SamusPhazonBallANCS", 0}, + {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}, +}; + +constexpr std::pair kSpiderBallGlassTable[] = { + {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 1}, + {"SamusPhazonBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 1}, {"SamusPhazonBallGlassCMDL", 0}, +}; + +constexpr u32 kSpiderBallGlowColorIdxTable[] = { + 3, 3, 2, 4, 5, 7, 6, 8, +}; + +constexpr u32 kBallGlowColorIdxTable[] = { + 0, 0, 1, 0, 5, 7, 6, 8, +}; + +/* Maps material index to effect in generator array */ +constexpr s32 skWakeEffectMap[32] = { + -1, -1, -1, -1, -1, -1, -1, + 0, // Phazon + 2, // Dirt + 3, // Lava + -1, + 4, // Snow + 5, // MudSlow + -1, -1, -1, -1, + 6, // Sand + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, +}; + +constexpr u16 skBallRollSfx[] = { + 0xFFFF, + SFXsam_ballroll_stone, + SFXsam_ballroll_metal, + SFXsam_ballroll_grass, + SFXice_ballroll_ice, + 0xFFFF, + SFXsam_ballroll_grate, + SFXsam_ballroll_phazon, + SFXsam_ballroll_dirt, + SFXlav_ballroll_lava, + SFXsam_ballroll_lavastone, + SFXice_ballroll_snow, + SFXsam_ballroll_mud, + 0xFFFF, + SFXsam_ballroll_org, + SFXsam_ballroll_metal, + SFXsam_ballroll_metal, + SFXsam_ballroll_dirt, + 0xFFFF, + 0xFFFF, + 0xFFFF, + 0xFFFF, + SFXsam_ballroll_wood, + SFXsam_ballroll_org, +}; + +constexpr u16 skBallLandSfx[] = { + 0xFFFF, + SFXsam_ballland_stone, + SFXsam_ballland_metal, + SFXsam_ballland_grass, + SFXsam_ballland_ice, + 0xFFFF, + SFXsam_ballland_grate, + SFXsam_ballland_phazon, + SFXsam_landdirt_00, + SFXsam_ballland_lava, + SFXsam_ballland_lava, + SFXsam_ballland_snow, + SFXsam_ballland_mud, + 0xFFFF, + SFXsam_ballland_org, + SFXsam_ballland_metal, + SFXsam_ballland_metal, + SFXsam_landdirt_00, + 0xFFFF, + 0xFFFF, + 0xFFFF, + 0xFFFF, + SFXsam_ballland_wood, + SFXsam_ballland_org, +}; + +constexpr u8 skBallInnerGlowColors[9][3] = { + {0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x60, 0xff, 0x90}, {0x33, 0x33, 0xff}, {0xff, 0x80, 0x80}, + {0x0, 0x9d, 0xb6}, {0xd3, 0xf1, 0x0}, {0x60, 0x33, 0xff}, {0xfb, 0x98, 0x21}, +}; + +constexpr u8 BallSwooshColors[9][3] = { + {0xC2, 0x8F, 0x17}, {0x70, 0xD4, 0xFF}, {0x6A, 0xFF, 0x8A}, {0x3D, 0x4D, 0xFF}, {0xC0, 0x00, 0x00}, + {0x00, 0xBE, 0xDC}, {0xDF, 0xFF, 0x00}, {0xC4, 0x9E, 0xFF}, {0xFF, 0x9A, 0x22}, +}; + +constexpr u8 BallSwooshColorsCharged[9][3] = { + {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0x80, 0x20}, + {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, +}; + +constexpr u8 BallSwooshColorsJaggy[9][3] = { + {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xD5, 0x19}, + {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, +}; +} // Anonymous namespace const u8 CMorphBall::BallGlowColors[9][3] = { {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xd5, 0x19}, @@ -96,18 +221,6 @@ void CMorphBall::LoadAnimationTokens(std::string_view ancsName) { } } -/* Maps material index to effect in generator array */ -static const s32 skWakeEffectMap[32] = {-1, -1, -1, -1, -1, -1, -1, - 0, // Phazon - 2, // Dirt - 3, // Lava - -1, - 4, // Snow - 5, // MudSlow - -1, -1, -1, -1, - 6, // Sand - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1}; - void CMorphBall::InitializeWakeEffects() { TToken nullParticle = CToken(TObjOwnerDerivedFromIObj::GetNewDerivedObject(std::make_unique())); @@ -200,56 +313,6 @@ void CMorphBall::RenderToShadowTex(CStateManager& mgr) { } } -static const u16 skBallRollSfx[] = {0xFFFF, - SFXsam_ballroll_stone, - SFXsam_ballroll_metal, - SFXsam_ballroll_grass, - SFXice_ballroll_ice, - 0xFFFF, - SFXsam_ballroll_grate, - SFXsam_ballroll_phazon, - SFXsam_ballroll_dirt, - SFXlav_ballroll_lava, - SFXsam_ballroll_lavastone, - SFXice_ballroll_snow, - SFXsam_ballroll_mud, - 0xFFFF, - SFXsam_ballroll_org, - SFXsam_ballroll_metal, - SFXsam_ballroll_metal, - SFXsam_ballroll_dirt, - 0xFFFF, - 0xFFFF, - 0xFFFF, - 0xFFFF, - SFXsam_ballroll_wood, - SFXsam_ballroll_org}; - -static const u16 skBallLandSfx[] = {0xFFFF, - SFXsam_ballland_stone, - SFXsam_ballland_metal, - SFXsam_ballland_grass, - SFXsam_ballland_ice, - 0xFFFF, - SFXsam_ballland_grate, - SFXsam_ballland_phazon, - SFXsam_landdirt_00, - SFXsam_ballland_lava, - SFXsam_ballland_lava, - SFXsam_ballland_snow, - SFXsam_ballland_mud, - 0xFFFF, - SFXsam_ballland_org, - SFXsam_ballland_metal, - SFXsam_ballland_metal, - SFXsam_landdirt_00, - 0xFFFF, - 0xFFFF, - 0xFFFF, - 0xFFFF, - SFXsam_ballland_wood, - SFXsam_ballland_org}; - void CMorphBall::SelectMorphBallSounds(const CMaterialList& mat) { u16 rollSfx; if (x0_player.x9c5_30_selectFluidBallSound) { @@ -1004,10 +1067,6 @@ void CMorphBall::LeaveMorphBallState(CStateManager& mgr) { StopEffects(); } -static const u8 skBallInnerGlowColors[9][3] = {{0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x60, 0xff, 0x90}, - {0x33, 0x33, 0xff}, {0xff, 0x80, 0x80}, {0x0, 0x9d, 0xb6}, - {0xd3, 0xf1, 0x0}, {0x60, 0x33, 0xff}, {0xfb, 0x98, 0x21}}; - void CMorphBall::UpdateEffects(float dt, CStateManager& mgr) { zeus::CTransform swooshToWorld = GetSwooshToWorld(); x19b8_slowBlueTailSwooshGen->SetTranslation(swooshToWorld.rotate({0.1f, 0.f, 0.f}) + swooshToWorld.origin); @@ -1394,19 +1453,6 @@ void CMorphBall::PointGenerator(void* ctx, const std::vector(ctx)->GeneratePoints(vn); } -static const u8 BallSwooshColors[9][3] = { - {0xC2, 0x8F, 0x17}, {0x70, 0xD4, 0xFF}, {0x6A, 0xFF, 0x8A}, {0x3D, 0x4D, 0xFF}, {0xC0, 0x00, 0x00}, - {0x00, 0xBE, 0xDC}, {0xDF, 0xFF, 0x00}, {0xC4, 0x9E, 0xFF}, {0xFF, 0x9A, 0x22}, -}; - -static const u8 BallSwooshColorsCharged[9][3] = {{0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, - {0xFF, 0xE6, 0x00}, {0xFF, 0x80, 0x20}, {0xFF, 0xE6, 0x00}, - {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}}; - -static const u8 BallSwooshColorsJaggy[9][3] = {{0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, - {0xFF, 0xCC, 0x00}, {0xFF, 0xD5, 0x19}, {0xFF, 0xCC, 0x00}, - {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}}; - void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) const { SCOPED_GRAPHICS_DEBUG_GROUP("CPlayer::Render", zeus::skPurple); zeus::CTransform ballToWorld = GetBallToWorld(); @@ -1951,33 +1997,6 @@ void CMorphBall::FluidFXThink(CActor::EFluidState state, CScriptWater& water, CS } } -static const std::pair kBallCharacterTable[] = { - {"SamusBallANCS", 0}, {"SamusBallANCS", 0}, {"SamusBallANCS", 1}, {"SamusBallANCS", 0}, - {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}}; - -static const std::pair kBallLowPolyTable[] = { - {"SamusBallLowPolyCMDL", 0}, {"SamusBallLowPolyCMDL", 0}, {"SamusBallLowPolyCMDL", 1}, - {"SamusBallLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 2}, - {"SamusBallFusionLowPolyCMDL", 1}, {"SamusBallFusionLowPolyCMDL", 3}}; - -static const std::pair kSpiderBallLowPolyTable[] = { - {"SamusSpiderBallLowPolyCMDL", 0}, {"SamusSpiderBallLowPolyCMDL", 0}, {"SamusSpiderBallLowPolyCMDL", 1}, - {"SamusSpiderBallLowPolyCMDL", 2}, {"SamusBallFusionLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 2}, - {"SamusBallFusionLowPolyCMDL", 1}, {"SamusBallFusionLowPolyCMDL", 3}}; - -static const std::pair kSpiderBallCharacterTable[] = { - {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 1}, {"SamusPhazonBallANCS", 0}, - {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}}; - -static const std::pair kSpiderBallGlassTable[] = { - {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 1}, - {"SamusPhazonBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 1}, {"SamusPhazonBallGlassCMDL", 0}}; - -static const u32 kSpiderBallGlowColorIdxTable[] = {3, 3, 2, 4, 5, 7, 6, 8}; - -static const u32 kBallGlowColorIdxTable[] = {0, 0, 1, 0, 5, 7, 6, 8}; - void CMorphBall::LoadMorphBallModel(CStateManager& mgr) { bool spiderBall = mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall); From 96f035f24b6953973d2d53b2db6bb545eded8fb3 Mon Sep 17 00:00:00 2001 From: Lioncash Date: Mon, 16 Sep 2019 15:04:22 -0400 Subject: [PATCH 3/3] CMorphBall: Use std::array where applicable Makes the arrays strongly-typed and impervious to implicit array->pointer decay. This also uncovered an out of bounds memory read within UpdateEffects cause by said array->pointer decay. --- Runtime/MP1/CSamusDoll.cpp | 42 +++++-- Runtime/World/CMorphBall.cpp | 237 ++++++++++++++++++++++++----------- Runtime/World/CMorphBall.hpp | 10 +- 3 files changed, 204 insertions(+), 85 deletions(-) diff --git a/Runtime/MP1/CSamusDoll.cpp b/Runtime/MP1/CSamusDoll.cpp index 82105b920..e84fdd867 100644 --- a/Runtime/MP1/CSamusDoll.cpp +++ b/Runtime/MP1/CSamusDoll.cpp @@ -468,20 +468,35 @@ void CSamusDoll::Draw(const CStateManager& mgr, float alpha) { flags.x4_color.a() = x6c_ballPulseFactor * alpha * itemPulse; x184_ballModelData->Render(mgr, x10_ballXf, x24c_actorLights.get(), flags); - const u8* c = CMorphBall::BallGlowColors[x1e8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; - x22c_ballInnerGlowGen->SetModulationColor(color); + const CMorphBall::ColorArray ballGlowColorData = CMorphBall::BallGlowColors[x1e8_ballGlowColorIdx]; + const zeus::CColor ballGlowColor{ + float(ballGlowColorData[0]) / 255.f, + float(ballGlowColorData[1]) / 255.f, + float(ballGlowColorData[2]) / 255.f, + alpha, + }; + x22c_ballInnerGlowGen->SetModulationColor(ballGlowColor); if (alpha > 0.f) { if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 0) { - const u8* c = CMorphBall::BallTransFlashColors[x1e8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; - x22c_ballInnerGlowGen->GetActiveChildParticle(0).SetModulationColor(color); + const CMorphBall::ColorArray transFlashColorData = CMorphBall::BallTransFlashColors[x1e8_ballGlowColorIdx]; + const zeus::CColor transFlashColor{ + float(transFlashColorData[0]) / 255.f, + float(transFlashColorData[1]) / 255.f, + float(transFlashColorData[2]) / 255.f, + alpha, + }; + x22c_ballInnerGlowGen->GetActiveChildParticle(0).SetModulationColor(transFlashColor); if (x22c_ballInnerGlowGen->GetNumActiveChildParticles() > 1) { - const u8* c = CMorphBall::BallAuxGlowColors[x1e8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, alpha}; - x22c_ballInnerGlowGen->GetActiveChildParticle(1).SetModulationColor(color); + const CMorphBall::ColorArray auxColorData = CMorphBall::BallAuxGlowColors[x1e8_ballGlowColorIdx]; + const zeus::CColor auxColor{ + float(auxColorData[0]) / 255.f, + float(auxColorData[1]) / 255.f, + float(auxColorData[2]) / 255.f, + alpha, + }; + x22c_ballInnerGlowGen->GetActiveChildParticle(1).SetModulationColor(auxColor); } } x22c_ballInnerGlowGen->Render(); @@ -510,8 +525,13 @@ void CSamusDoll::Draw(const CStateManager& mgr, float alpha) { } if (x238_ballTransitionFlashGen) { - const u8* c = CMorphBall::BallTransFlashColors[x1e8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; + const CMorphBall::ColorArray c = CMorphBall::BallTransFlashColors[x1e8_ballGlowColorIdx]; + const zeus::CColor color{ + float(c[0]) / 255.f, + float(c[1]) / 255.f, + float(c[2]) / 255.f, + 1.f, + }; x238_ballTransitionFlashGen->SetModulationColor(color); x238_ballTransitionFlashGen->Render(); } diff --git a/Runtime/World/CMorphBall.cpp b/Runtime/World/CMorphBall.cpp index 8d4f1ade5..7109ac53b 100644 --- a/Runtime/World/CMorphBall.cpp +++ b/Runtime/World/CMorphBall.cpp @@ -1,5 +1,7 @@ #include "Runtime/World/CMorphBall.hpp" +#include + #include "Runtime/CDependencyGroup.hpp" #include "Runtime/CSimplePool.hpp" #include "Runtime/TCastTo.hpp" @@ -21,44 +23,71 @@ namespace urde { namespace { float kSpiderBallCollisionRadius; -constexpr std::pair kBallCharacterTable[] = { - {"SamusBallANCS", 0}, {"SamusBallANCS", 0}, {"SamusBallANCS", 1}, {"SamusBallANCS", 0}, - {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}, -}; +constexpr std::array, 8> kBallCharacterTable{{ + {"SamusBallANCS", 0}, + {"SamusBallANCS", 0}, + {"SamusBallANCS", 1}, + {"SamusBallANCS", 0}, + {"SamusFusionBallANCS", 0}, + {"SamusFusionBallANCS", 2}, + {"SamusFusionBallANCS", 1}, + {"SamusFusionBallANCS", 3}, +}}; -constexpr std::pair kBallLowPolyTable[] = { - {"SamusBallLowPolyCMDL", 0}, {"SamusBallLowPolyCMDL", 0}, {"SamusBallLowPolyCMDL", 1}, - {"SamusBallLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 2}, - {"SamusBallFusionLowPolyCMDL", 1}, {"SamusBallFusionLowPolyCMDL", 3}, -}; +constexpr std::array, 8> kBallLowPolyTable{{ + {"SamusBallLowPolyCMDL", 0}, + {"SamusBallLowPolyCMDL", 0}, + {"SamusBallLowPolyCMDL", 1}, + {"SamusBallLowPolyCMDL", 0}, + {"SamusBallFusionLowPolyCMDL", 0}, + {"SamusBallFusionLowPolyCMDL", 2}, + {"SamusBallFusionLowPolyCMDL", 1}, + {"SamusBallFusionLowPolyCMDL", 3}, +}}; -constexpr std::pair kSpiderBallLowPolyTable[] = { - {"SamusSpiderBallLowPolyCMDL", 0}, {"SamusSpiderBallLowPolyCMDL", 0}, {"SamusSpiderBallLowPolyCMDL", 1}, - {"SamusSpiderBallLowPolyCMDL", 2}, {"SamusBallFusionLowPolyCMDL", 0}, {"SamusBallFusionLowPolyCMDL", 2}, - {"SamusBallFusionLowPolyCMDL", 1}, {"SamusBallFusionLowPolyCMDL", 3}, -}; +constexpr std::array, 8> kSpiderBallLowPolyTable{{ + {"SamusSpiderBallLowPolyCMDL", 0}, + {"SamusSpiderBallLowPolyCMDL", 0}, + {"SamusSpiderBallLowPolyCMDL", 1}, + {"SamusSpiderBallLowPolyCMDL", 2}, + {"SamusBallFusionLowPolyCMDL", 0}, + {"SamusBallFusionLowPolyCMDL", 2}, + {"SamusBallFusionLowPolyCMDL", 1}, + {"SamusBallFusionLowPolyCMDL", 3}, +}}; -constexpr std::pair kSpiderBallCharacterTable[] = { - {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 0}, {"SamusSpiderBallANCS", 1}, {"SamusPhazonBallANCS", 0}, - {"SamusFusionBallANCS", 0}, {"SamusFusionBallANCS", 2}, {"SamusFusionBallANCS", 1}, {"SamusFusionBallANCS", 3}, -}; +constexpr std::array, 8> kSpiderBallCharacterTable{{ + {"SamusSpiderBallANCS", 0}, + {"SamusSpiderBallANCS", 0}, + {"SamusSpiderBallANCS", 1}, + {"SamusPhazonBallANCS", 0}, + {"SamusFusionBallANCS", 0}, + {"SamusFusionBallANCS", 2}, + {"SamusFusionBallANCS", 1}, + {"SamusFusionBallANCS", 3}, +}}; -constexpr std::pair kSpiderBallGlassTable[] = { - {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 1}, - {"SamusPhazonBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, {"SamusSpiderBallGlassCMDL", 0}, - {"SamusSpiderBallGlassCMDL", 1}, {"SamusPhazonBallGlassCMDL", 0}, -}; +constexpr std::array, 8> kSpiderBallGlassTable{{ + {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 1}, + {"SamusPhazonBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 1}, + {"SamusPhazonBallGlassCMDL", 0}, +}}; -constexpr u32 kSpiderBallGlowColorIdxTable[] = { +constexpr std::array kSpiderBallGlowColorIdxTable{ 3, 3, 2, 4, 5, 7, 6, 8, }; -constexpr u32 kBallGlowColorIdxTable[] = { +constexpr std::array kBallGlowColorIdxTable{ 0, 0, 1, 0, 5, 7, 6, 8, }; /* Maps material index to effect in generator array */ -constexpr s32 skWakeEffectMap[32] = { +constexpr std::array skWakeEffectMap{ -1, -1, -1, -1, -1, -1, -1, 0, // Phazon 2, // Dirt @@ -71,7 +100,7 @@ constexpr s32 skWakeEffectMap[32] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, }; -constexpr u16 skBallRollSfx[] = { +constexpr std::array skBallRollSfx{ 0xFFFF, SFXsam_ballroll_stone, SFXsam_ballroll_metal, @@ -98,7 +127,7 @@ constexpr u16 skBallRollSfx[] = { SFXsam_ballroll_org, }; -constexpr u16 skBallLandSfx[] = { +constexpr std::array skBallLandSfx{ 0xFFFF, SFXsam_ballland_stone, SFXsam_ballland_metal, @@ -125,39 +154,90 @@ constexpr u16 skBallLandSfx[] = { SFXsam_ballland_org, }; -constexpr u8 skBallInnerGlowColors[9][3] = { - {0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x60, 0xff, 0x90}, {0x33, 0x33, 0xff}, {0xff, 0x80, 0x80}, - {0x0, 0x9d, 0xb6}, {0xd3, 0xf1, 0x0}, {0x60, 0x33, 0xff}, {0xfb, 0x98, 0x21}, -}; +constexpr std::array skBallInnerGlowColors{{ + {0xc2, 0x7e, 0x10}, + {0x66, 0xc4, 0xff}, + {0x60, 0xff, 0x90}, + {0x33, 0x33, 0xff}, + {0xff, 0x80, 0x80}, + {0x0, 0x9d, 0xb6}, + {0xd3, 0xf1, 0x0}, + {0x60, 0x33, 0xff}, + {0xfb, 0x98, 0x21}, +}}; -constexpr u8 BallSwooshColors[9][3] = { - {0xC2, 0x8F, 0x17}, {0x70, 0xD4, 0xFF}, {0x6A, 0xFF, 0x8A}, {0x3D, 0x4D, 0xFF}, {0xC0, 0x00, 0x00}, - {0x00, 0xBE, 0xDC}, {0xDF, 0xFF, 0x00}, {0xC4, 0x9E, 0xFF}, {0xFF, 0x9A, 0x22}, -}; +constexpr std::array BallSwooshColors{{ + {0xC2, 0x8F, 0x17}, + {0x70, 0xD4, 0xFF}, + {0x6A, 0xFF, 0x8A}, + {0x3D, 0x4D, 0xFF}, + {0xC0, 0x00, 0x00}, + {0x00, 0xBE, 0xDC}, + {0xDF, 0xFF, 0x00}, + {0xC4, 0x9E, 0xFF}, + {0xFF, 0x9A, 0x22}, +}}; -constexpr u8 BallSwooshColorsCharged[9][3] = { - {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0x80, 0x20}, - {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, {0xFF, 0xE6, 0x00}, -}; +constexpr std::array BallSwooshColorsCharged{{ + {0xFF, 0xE6, 0x00}, + {0xFF, 0xE6, 0x00}, + {0xFF, 0xE6, 0x00}, + {0xFF, 0xE6, 0x00}, + {0xFF, 0x80, 0x20}, + {0xFF, 0xE6, 0x00}, + {0xFF, 0xE6, 0x00}, + {0xFF, 0xE6, 0x00}, + {0xFF, 0xE6, 0x00}, +}}; -constexpr u8 BallSwooshColorsJaggy[9][3] = { - {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xD5, 0x19}, - {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, {0xFF, 0xCC, 0x00}, -}; +constexpr std::array BallSwooshColorsJaggy{{ + {0xFF, 0xCC, 0x00}, + {0xFF, 0xCC, 0x00}, + {0xFF, 0xCC, 0x00}, + {0xFF, 0xCC, 0x00}, + {0xFF, 0xD5, 0x19}, + {0xFF, 0xCC, 0x00}, + {0xFF, 0xCC, 0x00}, + {0xFF, 0xCC, 0x00}, + {0xFF, 0xCC, 0x00}, +}}; } // Anonymous namespace -const u8 CMorphBall::BallGlowColors[9][3] = { - {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xd5, 0x19}, - {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, {0xff, 0xff, 0xff}, -}; +const std::array CMorphBall::BallGlowColors{{ + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xd5, 0x19}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, + {0xff, 0xff, 0xff}, +}}; -const u8 CMorphBall::BallTransFlashColors[9][3] = {{0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x60, 0xff, 0x90}, - {0x33, 0x33, 0xff}, {0xff, 0x20, 0x20}, {0x0, 0x9d, 0xb6}, - {0xd3, 0xf1, 0x0}, {0xa6, 0x86, 0xd8}, {0xfb, 0x98, 0x21}}; +const std::array CMorphBall::BallTransFlashColors{{ + {0xc2, 0x7e, 0x10}, + {0x66, 0xc4, 0xff}, + {0x60, 0xff, 0x90}, + {0x33, 0x33, 0xff}, + {0xff, 0x20, 0x20}, + {0x0, 0x9d, 0xb6}, + {0xd3, 0xf1, 0x0}, + {0xa6, 0x86, 0xd8}, + {0xfb, 0x98, 0x21}, +}}; -const u8 CMorphBall::BallAuxGlowColors[9][3] = {{0xc2, 0x7e, 0x10}, {0x66, 0xc4, 0xff}, {0x6c, 0xff, 0x61}, - {0x33, 0x33, 0xff}, {0xff, 0x20, 0x20}, {0x0, 0x9d, 0xb6}, - {0xd3, 0xf1, 0x0}, {0xa6, 0x86, 0xd8}, {0xfb, 0x98, 0x21}}; +const std::array CMorphBall::BallAuxGlowColors{{ + {0xc2, 0x7e, 0x10}, + {0x66, 0xc4, 0xff}, + {0x6c, 0xff, 0x61}, + {0x33, 0x33, 0xff}, + {0xff, 0x20, 0x20}, + {0x0, 0x9d, 0xb6}, + {0xd3, 0xf1, 0x0}, + {0xa6, 0x86, 0xd8}, + {0xfb, 0x98, 0x21}, +}}; CMorphBall::CMorphBall(CPlayer& player, float radius) : x0_player(player) @@ -321,7 +401,7 @@ void CMorphBall::SelectMorphBallSounds(const CMaterialList& mat) { else rollSfx = 1481; } else { - rollSfx = CPlayer::SfxIdFromMaterial(mat, skBallRollSfx, 24, 0xffff); + rollSfx = CPlayer::SfxIdFromMaterial(mat, skBallRollSfx.data(), 24, 0xffff); } x0_player.x9c5_30_selectFluidBallSound = false; @@ -333,7 +413,7 @@ void CMorphBall::SelectMorphBallSounds(const CMaterialList& mat) { x1e34_rollSfx = rollSfx; } - x1e36_landSfx = CPlayer::SfxIdFromMaterial(mat, skBallLandSfx, 24, 0xffff); + x1e36_landSfx = CPlayer::SfxIdFromMaterial(mat, skBallLandSfx.data(), 24, 0xffff); } void CMorphBall::UpdateMorphBallSounds(float dt) { @@ -1142,29 +1222,37 @@ void CMorphBall::UpdateEffects(float dt, CStateManager& mgr) { if (x1c10_ballInnerGlowLight != kInvalidUniqueId) { if (TCastToPtr light = mgr.ObjectById(x1c10_ballInnerGlowLight)) { light->SetTranslation(swooshToWorld.origin + zeus::CVector3f(0.f, 0.f, GetBallRadius())); + std::optional lObj; - if (IsMorphBallTransitionFlashValid() && x19dc_morphBallTransitionFlashGen->SystemHasLight()) + if (IsMorphBallTransitionFlashValid() && x19dc_morphBallTransitionFlashGen->SystemHasLight()) { lObj.emplace(x19dc_morphBallTransitionFlashGen->GetLight()); - else if (x19d0_ballInnerGlowGen->SystemHasLight()) + } else if (x19d0_ballInnerGlowGen->SystemHasLight()) { lObj.emplace(x19d0_ballInnerGlowGen->GetLight()); + } + if (lObj) { - const u8* c = skBallInnerGlowColors[x8_ballGlowColorIdx]; - zeus::CColor color(c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f); - lObj->SetColor(lObj->GetColor() * c); + const auto c = skBallInnerGlowColors[x8_ballGlowColorIdx]; + const zeus::CColor color(c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f); + lObj->SetColor(lObj->GetColor() * color); + if (x0_player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Unmorphing) { float t = 0.f; - if (x0_player.x578_morphDuration != 0.f) + if (x0_player.x578_morphDuration != 0.f) { t = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); + } lObj->SetColor(zeus::CColor::lerp(lObj->GetColor(), zeus::skBlack, t)); } else if (x0_player.GetMorphballTransitionState() == CPlayer::EPlayerMorphBallState::Morphing) { float t = 0.f; - if (x0_player.x578_morphDuration != 0.f) + if (x0_player.x578_morphDuration != 0.f) { t = zeus::clamp(0.f, x0_player.x574_morphTime / x0_player.x578_morphDuration, 1.f); - if (t < 0.5f) + } + if (t < 0.5f) { lObj->SetColor(zeus::CColor::lerp(zeus::skBlack, lObj->GetColor(), std::min(2.f * t, 1.f))); + } } else { lObj->SetColor(zeus::CColor::lerp(lObj->GetColor(), zeus::skWhite, x1c34_boostLightFactor)); } + light->SetLight(*lObj); } } @@ -1513,7 +1601,7 @@ void CMorphBall::Render(const CStateManager& mgr, const CActorLights* lights) co } } - const u8* c = BallSwooshColors[x8_ballGlowColorIdx]; + ColorArray c = BallSwooshColors[x8_ballGlowColorIdx]; float swooshAlpha = x1c20_tireFactor / x1c24_maxTireFactor; zeus::CColor color0 = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, swooshAlpha}; c = BallSwooshColorsCharged[x8_ballGlowColorIdx]; @@ -1615,12 +1703,19 @@ void CMorphBall::UpdateMorphBallTransitionFlash(float dt) { } void CMorphBall::RenderMorphBallTransitionFlash(const CStateManager&) const { - if (x19dc_morphBallTransitionFlashGen) { - const u8* c = BallTransFlashColors[x8_ballGlowColorIdx]; - zeus::CColor color = {c[0] / 255.f, c[1] / 255.f, c[2] / 255.f, 1.f}; - x19dc_morphBallTransitionFlashGen->SetModulationColor(color); - x19dc_morphBallTransitionFlashGen->Render(); + if (x19dc_morphBallTransitionFlashGen == nullptr) { + return; } + + const auto colorData = BallTransFlashColors[x8_ballGlowColorIdx]; + const zeus::CColor color = { + float(colorData[0]) / 255.f, + float(colorData[1]) / 255.f, + float(colorData[2]) / 255.f, + 1.f, + }; + x19dc_morphBallTransitionFlashGen->SetModulationColor(color); + x19dc_morphBallTransitionFlashGen->Render(); } void CMorphBall::UpdateIceBreakEffect(float dt) { @@ -1767,7 +1862,7 @@ void CMorphBall::CollidedWith(TUniqueId id, const CCollisionInfoList& list, CSta wakeMaterial = tmpMaterial; if (tmpMaterial != EMaterialTypes::NoStepLogic) { - int mappedIdx = skWakeEffectMap[int(tmpMaterial)]; + int mappedIdx = skWakeEffectMap[size_t(tmpMaterial)]; if (mappedIdx == 0) // Phazon { const CGameArea* area = mgr.GetWorld()->GetAreaAlways(mgr.GetNextAreaId()); diff --git a/Runtime/World/CMorphBall.hpp b/Runtime/World/CMorphBall.hpp index 8e8136f48..c0f7e8b90 100644 --- a/Runtime/World/CMorphBall.hpp +++ b/Runtime/World/CMorphBall.hpp @@ -1,5 +1,7 @@ #pragma once +#include + #include "Runtime/RetroTypes.hpp" #include "Runtime/Collision/CCollidableSphere.hpp" #include "Runtime/Collision/CCollisionInfoList.hpp" @@ -282,9 +284,11 @@ public: bool IsInBoost() const { return x1de4_24_inBoost; } float GetBoostChargeTime() const { return x1de8_boostChargeTime; } - static const u8 BallGlowColors[9][3]; - static const u8 BallTransFlashColors[9][3]; - static const u8 BallAuxGlowColors[9][3]; + // Contains red, green, and blue channel values + using ColorArray = std::array; + static const std::array BallGlowColors; + static const std::array BallTransFlashColors; + static const std::array BallAuxGlowColors; }; } // namespace urde