From 4ff1475f0e7e3b2ca9aff4ac1ae6ea5f8ae337b0 Mon Sep 17 00:00:00 2001 From: Jack Andersen Date: Thu, 4 May 2017 08:56:20 -1000 Subject: [PATCH] Work on CSamusDoll --- Runtime/AutoMapper/CAutoMapper.cpp | 30 +- Runtime/Character/CAnimData.hpp | 1 + Runtime/Collision/CollisionUtil.cpp | 21 ++ Runtime/Collision/CollisionUtil.hpp | 1 + Runtime/GuiSys/CHudRadarInterface.cpp | 4 +- Runtime/MP1/CInventoryScreen.cpp | 71 ++++- Runtime/MP1/CInventoryScreen.hpp | 16 ++ Runtime/MP1/CPauseScreen.cpp | 10 +- Runtime/MP1/CPauseScreen.hpp | 2 +- Runtime/MP1/CPauseScreenBase.cpp | 113 +++++++- Runtime/MP1/CPauseScreenBase.hpp | 15 +- Runtime/MP1/CSamusDoll.cpp | 398 ++++++++++++++++++++++++++ Runtime/MP1/CSamusDoll.hpp | 77 ++++- specter | 2 +- 14 files changed, 715 insertions(+), 46 deletions(-) diff --git a/Runtime/AutoMapper/CAutoMapper.cpp b/Runtime/AutoMapper/CAutoMapper.cpp index 556040685..b0a1994e8 100644 --- a/Runtime/AutoMapper/CAutoMapper.cpp +++ b/Runtime/AutoMapper/CAutoMapper.cpp @@ -584,36 +584,22 @@ void CAutoMapper::ProcessMapRotateInput(const CFinalInput& input, const CStateMa float deltaFrames = input.DeltaTime() * 60.f; SetShouldRotatingSoundBePlaying(true); zeus::CEulerAngles eulers(xa8_renderStates[0].x8_camOrientation); - float angX = eulers.x - std::floor(eulers.x / (2.f * M_PIF)) * 2.f * M_PIF; - if (angX < 0.f) - angX += 2.f * M_PIF; - float angZ = eulers.z - std::floor(eulers.z / (2.f * M_PIF)) * 2.f * M_PIF; - if (angZ < 0.f) - angZ += 2.f * M_PIF; + zeus::CRelAngle angX(eulers.x); + zeus::CRelAngle angZ(eulers.z); float dt = deltaFrames * g_tweakAutoMapper->GetCamRotateDegreesPerFrame(); angZ -= zeus::degToRad(dt * dirs[2]); - if (angZ - std::floor(angZ / (2.f * M_PIF)) * 2.f * M_PIF < 0.f) - angZ += 2.f * M_PIF; angZ += zeus::degToRad(dt * dirs[3]); - if (angZ - std::floor(angZ / (2.f * M_PIF)) * 2.f * M_PIF < 0.f) - angZ += 2.f * M_PIF; angX -= zeus::degToRad(dt * dirs[0]); - if (angX - std::floor(angX / (2.f * M_PIF)) * 2.f * M_PIF < 0.f) - angX += 2.f * M_PIF; angX += zeus::degToRad(dt * dirs[1]); - if (angX - std::floor(angX / (2.f * M_PIF)) * 2.f * M_PIF < 0.f) - angX += 2.f * M_PIF; - angX = zeus::radToDeg(angX); - if (angX > 180.f) - angX -= 360.f; - angX = zeus::degToRad(zeus::clamp(g_tweakAutoMapper->GetMinCamRotateX(), angX, + float angXDeg = angX.asDegrees(); + if (angXDeg > 180.f) + angXDeg -= 360.f; + angX = zeus::degToRad(zeus::clamp(g_tweakAutoMapper->GetMinCamRotateX(), angXDeg, g_tweakAutoMapper->GetMaxCamRotateX())); - if (angX - std::floor(angX / (2.f * M_PIF)) * 2.f * M_PIF < 0.f) - angX += 2.f * M_PIF; zeus::CQuaternion quat; quat.rotateZ(angZ); @@ -1573,9 +1559,7 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo float func = zeus::clamp(0.f, 0.5f * (1.f + std::sin(5.f * CGraphics::GetSecondsMod900() - (M_PIF / 2.f))), 1.f); float scale = std::min(0.6f * g_tweakAutoMapper->GetMaxCamDist() / g_tweakAutoMapper->GetMinCamDist(), objectScale); zeus::CEulerAngles eulers(mgr.GetCameraManager()->GetCurrentCameraTransform(mgr)); - float angle = eulers.z - std::floor(eulers.z / (2.f * M_PIF)) * 2.f * M_PIF; - if (angle < 0.f) - angle += 2.f * M_PIF; + zeus::CRelAngle angle(eulers.z); zeus::CTransform playerXf(zeus::CMatrix3f::RotateZ(angle), CMapArea::GetAreaPostTranslate(*x24_world, mgr.GetNextAreaId()) + mgr.GetPlayer().GetTranslation()); CGraphics::SetModelMatrix(mapXf * playerXf * zeus::CTransform::Scale(scale * (0.25f * func + 0.75f))); diff --git a/Runtime/Character/CAnimData.hpp b/Runtime/Character/CAnimData.hpp index b08cb4fb7..5c06144cb 100644 --- a/Runtime/Character/CAnimData.hpp +++ b/Runtime/Character/CAnimData.hpp @@ -206,6 +206,7 @@ public: void AdvanceAnim(CCharAnimTime& time, zeus::CVector3f&, zeus::CQuaternion&); void SetXRayModel(const TLockedToken& model, const TLockedToken& skinRules); void SetInfraModel(const TLockedToken& model, const TLockedToken& skinRules); + const TCachedToken& GetModelData() const { return xd8_modelData; } static void PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose, const CModelFlags& drawFlags, diff --git a/Runtime/Collision/CollisionUtil.cpp b/Runtime/Collision/CollisionUtil.cpp index c04319456..388abcff0 100644 --- a/Runtime/Collision/CollisionUtil.cpp +++ b/Runtime/Collision/CollisionUtil.cpp @@ -21,5 +21,26 @@ u32 RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f &, return 0; } +bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir, + float mag, float& T, zeus::CVector3f& point) +{ + zeus::CVector3f rayToSphere = sphere.position - pos; + float magSq = rayToSphere.magSquared(); + float dirDot = rayToSphere.dot(dir); + float radSq = sphere.radius * sphere.radius; + if (dirDot < 0.f && magSq > radSq) + return false; + float intersectSq = radSq - (magSq - dirDot * dirDot); + if (intersectSq < 0.f) + return false; + T = magSq > radSq ? dirDot - std::sqrt(intersectSq) : dirDot + std::sqrt(intersectSq); + if (T < mag || mag == 0.f) + { + point = pos + T * dir; + return true; + } + return false; +} + } } diff --git a/Runtime/Collision/CollisionUtil.hpp b/Runtime/Collision/CollisionUtil.hpp index 6e2e68f4c..7a859786f 100644 --- a/Runtime/Collision/CollisionUtil.hpp +++ b/Runtime/Collision/CollisionUtil.hpp @@ -11,6 +11,7 @@ namespace CollisionUtil bool LineIntersectsOBBox(const zeus::COBBox&, const zeus::CMRay&, float&); u32 RayAABoxIntersection(const zeus::CMRay&, const zeus::CAABox&, const zeus::CVector3f&, float&); u32 RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f&, const zeus::CVector3f&, double&); +bool RaySphereIntersection(const zeus::CSphere&, const zeus::CVector3f&, const zeus::CVector3f&, float, float&, zeus::CVector3f&); } } #endif // __URDE_COLLISIONUTIL_HPP__ diff --git a/Runtime/GuiSys/CHudRadarInterface.cpp b/Runtime/GuiSys/CHudRadarInterface.cpp index e545f8831..91d27bb78 100644 --- a/Runtime/GuiSys/CHudRadarInterface.cpp +++ b/Runtime/GuiSys/CHudRadarInterface.cpp @@ -118,9 +118,7 @@ void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) const float camZ = zeus::CEulerAngles(zeus::CQuaternion( mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis)).z; - float angleZ = camZ - std::floor(camZ / (2.f * M_PIF)) * 2.f * M_PIF; - if (angleZ < 0.f) - angleZ += 2.f * M_PIF; + zeus::CRelAngle angleZ(camZ); drawParms.xc_preTranslate = zeus::CTransform::RotateY(angleZ); drawParms.x3c_postTranslate = x40_BaseWidget_RadarStuff->GetWorldTransform(); float enemyRadius = g_tweakGui->GetRadarEnemyPaintRadius(); diff --git a/Runtime/MP1/CInventoryScreen.cpp b/Runtime/MP1/CInventoryScreen.cpp index 92889e650..534c6fe99 100644 --- a/Runtime/MP1/CInventoryScreen.cpp +++ b/Runtime/MP1/CInventoryScreen.cpp @@ -9,12 +9,53 @@ CInventoryScreen::CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, c const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp) : CPauseScreenBase(mgr, frame, pauseStrg) { + CPlayerState& playerState = *mgr.GetPlayerState(); + x19c_samusDoll = std::make_unique(suitDgrp, ballDgrp, + CPlayerState::EPlayerSuit(int(playerState.GetCurrentSuit()) + + playerState.IsFusionEnabled() * 4), + playerState.GetCurrentBeam(), + playerState.HasPowerUp(CPlayerState::EItemType::SpiderBall), + playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam)); +} +bool CInventoryScreen::InputDisabled() const +{ + return false; +} + +void CInventoryScreen::TransitioningAway() +{ + +} + +void CInventoryScreen::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) +{ + +} + +void CInventoryScreen::Touch() +{ + +} + +void CInventoryScreen::ProcessControllerInput(const CFinalInput& input) +{ + +} + +void CInventoryScreen::Draw(float transInterp, float totalAlpha, float yOff) +{ + +} + +float CInventoryScreen::GetCameraYBias() const +{ + return 0.f; } bool CInventoryScreen::VReady() const { - return true; + return false; } void CInventoryScreen::VActivate() const @@ -22,10 +63,38 @@ void CInventoryScreen::VActivate() const } +void CInventoryScreen::ChangedMode() +{ + +} + +void CInventoryScreen::UpdateRightTable() +{ + +} + u32 CInventoryScreen::GetRightTableCount() const { return 0; } +bool CInventoryScreen::IsRightLogDynamic() const +{ + return false; +} + +void CInventoryScreen::UpdateRightLogColors(bool active, const zeus::CColor& activeColor, + const zeus::CColor& inactiveColor) +{ + +} + +void CInventoryScreen::UpdateRightLogHighlight(bool active, int idx, + const zeus::CColor& activeColor, + const zeus::CColor& inactiveColor) +{ + +} + } } diff --git a/Runtime/MP1/CInventoryScreen.hpp b/Runtime/MP1/CInventoryScreen.hpp index 64ab51a63..f5a72f90e 100644 --- a/Runtime/MP1/CInventoryScreen.hpp +++ b/Runtime/MP1/CInventoryScreen.hpp @@ -15,13 +15,29 @@ namespace MP1 class CInventoryScreen : public CPauseScreenBase { std::unique_ptr x19c_samusDoll; + float x1a0_ = 0.f; + float x1a4_ = 0.f; + u32 x1a8_ = 0; + bool x1ac_ = false; public: CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg, const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp); + bool InputDisabled() const; + void TransitioningAway(); + void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue); + void Touch(); + void ProcessControllerInput(const CFinalInput& input); + void Draw(float transInterp, float totalAlpha, float yOff); + float GetCameraYBias() const; bool VReady() const; void VActivate() const; + void ChangedMode(); + void UpdateRightTable(); u32 GetRightTableCount() const; + bool IsRightLogDynamic() const; + void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor); + void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor); }; } diff --git a/Runtime/MP1/CPauseScreen.cpp b/Runtime/MP1/CPauseScreen.cpp index 6e40589f8..f1c928aab 100644 --- a/Runtime/MP1/CPauseScreen.cpp +++ b/Runtime/MP1/CPauseScreen.cpp @@ -177,7 +177,7 @@ void CPauseScreen::ProcessControllerInput(const CStateManager& mgr, const CFinal bool bExits = false; if (std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]) { - if (curScreen->GetMode() == CPauseScreenBase::EMode::Zero) + if (curScreen->GetMode() == CPauseScreenBase::EMode::LeftTable) bExits = true; curScreen->ProcessControllerInput(input); } @@ -233,12 +233,12 @@ void CPauseScreen::Update(float dt, const CStateManager& mgr, CRandom16& rand, C if (x8_curSubscreen != xc_nextSubscreen) { - x10_interp = std::max(0.f, x10_interp - dt); + x10_alphaInterp = std::max(0.f, x10_alphaInterp - dt); if (!curScreen || !curScreen->InputDisabled()) { if (!otherScreen || otherScreen->IsReady()) { - if (x10_interp == 0.f) + if (x10_alphaInterp == 0.f) TransitionComplete(); } } @@ -248,7 +248,7 @@ void CPauseScreen::Update(float dt, const CStateManager& mgr, CRandom16& rand, C { curScreen->Update(dt, rand, archQueue); zeus::CColor color = zeus::CColor::skWhite; - color.a = std::min(curScreen->GetAlpha(), x8_curSubscreen != xc_nextSubscreen ? x10_interp / 0.5f : 1.f); + color.a = std::min(curScreen->GetAlpha(), x8_curSubscreen != xc_nextSubscreen ? x10_alphaInterp / 0.5f : 1.f); x40_textpane_a->SetColor(color); x44_textpane_b->SetColor(color); } @@ -273,7 +273,7 @@ void CPauseScreen::Draw() std::unique_ptr& curScreen = x7c_screens[x78_activeIdx]; if (curScreen && curScreen->CanDraw()) { - float useInterp = x10_interp == 0.f ? 1.f : x10_interp / 0.5f; + float useInterp = x10_alphaInterp == 0.f ? 1.f : x10_alphaInterp / 0.5f; float initInterp = std::min(curScreen->GetAlpha(), useInterp); if (xc_nextSubscreen == ESubScreen::Invalid) totalAlpha = useInterp; diff --git a/Runtime/MP1/CPauseScreen.hpp b/Runtime/MP1/CPauseScreen.hpp index 9e1525b2a..6f19cf176 100644 --- a/Runtime/MP1/CPauseScreen.hpp +++ b/Runtime/MP1/CPauseScreen.hpp @@ -28,7 +28,7 @@ private: u32 x4_ = 2; ESubScreen x8_curSubscreen = ESubScreen::Invalid; ESubScreen xc_nextSubscreen = ESubScreen::Invalid; - float x10_interp = 0.f; + float x10_alphaInterp = 0.f; TLockedToken x14_strgPauseScreen; const CDependencyGroup& x20_suitDgrp; const CDependencyGroup& x24_ballDgrp; diff --git a/Runtime/MP1/CPauseScreenBase.cpp b/Runtime/MP1/CPauseScreenBase.cpp index 4688e60aa..b671ca42e 100644 --- a/Runtime/MP1/CPauseScreenBase.cpp +++ b/Runtime/MP1/CPauseScreenBase.cpp @@ -7,6 +7,7 @@ #include "GuiSys/CAuiImagePane.hpp" #include "GuiSys/CGuiWidgetDrawParms.hpp" #include "GameGlobalObjects.hpp" +#include "Audio/CSfxManager.hpp" namespace urde { @@ -78,7 +79,7 @@ bool CPauseScreenBase::IsReady() if (x198_24_ready) { VActivate(); - Activate(EMode::Zero); + ChangeMode(EMode::LeftTable); UpdateSideTable(x70_tablegroup_leftlog); UpdateRightTable(); return true; @@ -86,14 +87,113 @@ bool CPauseScreenBase::IsReady() return false; } -void CPauseScreenBase::Activate(EMode mode) +void CPauseScreenBase::ChangeMode(EMode mode) { + if (x10_mode == mode) + return; + EMode oldMode = x10_mode; + zeus::CColor color = g_tweakGuiColors->GetPauseItemAmberColor(); + zeus::CColor colorDim = color; + colorDim.a = 0.5f; + + switch (x10_mode) + { + case EMode::LeftTable: + x6c_basewidget_leftlog->SetColor(colorDim); + x70_tablegroup_leftlog->SetIsActive(false); + break; + case EMode::Invalid: + case EMode::RightTable: + if (IsRightLogDynamic()) + UpdateRightLogColors(false, color, colorDim); + else + x80_basewidget_rightlog->SetColor(colorDim); + x84_tablegroup_rightlog->SetIsActive(false); + break; + case EMode::TextScroll: + CSfxManager::SfxStart(1431, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + break; + default: break; + } + + x10_mode = mode; + + switch (x10_mode) + { + case EMode::LeftTable: + if (oldMode == EMode::RightTable) + CSfxManager::SfxStart(1431, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + x6c_basewidget_leftlog->SetColor(color); + x70_tablegroup_leftlog->SetIsActive(true); + UpdateSideTable(x70_tablegroup_leftlog); + x18_ = 0; + x1c_ = 0; + x84_tablegroup_rightlog->SetUserSelection(1); + UpdateSideTable(x84_tablegroup_rightlog); + break; + case EMode::RightTable: + if (IsRightLogDynamic()) + UpdateRightLogColors(true, color, colorDim); + else + x80_basewidget_rightlog->SetColor(colorDim); + x84_tablegroup_rightlog->SetIsActive(true); + UpdateSideTable(x84_tablegroup_rightlog); + break; + case EMode::TextScroll: + x6c_basewidget_leftlog->SetColor(colorDim); + if (IsRightLogDynamic()) + UpdateRightLogColors(true, color, colorDim); + else + x80_basewidget_rightlog->SetColor(colorDim); + x70_tablegroup_leftlog->SetIsActive(false); + x84_tablegroup_rightlog->SetIsActive(false); + break; + default: break; + } + + ChangedMode(); } void CPauseScreenBase::UpdateSideTable(CGuiTableGroup* table) { + if (!table) + return; + zeus::CColor selColor = zeus::CColor::skWhite; + zeus::CColor deselColor = {1.f, 1.f, 1.f, 0.5f}; + + bool tableActive = true; + if (table == x84_tablegroup_rightlog && x10_mode != EMode::RightTable) + tableActive = false; + + table->SetColors(selColor, deselColor); + + if (table == x84_tablegroup_rightlog) + { + int sel = x1c_ - x18_; + x8c_model_righthighlight->SetLocalTransform( + x8c_model_righthighlight->GetTransform() * zeus::CTransform::Translate(0.f, 0.f, x38_ * sel)); + x8c_model_righthighlight->SetVisibility(x10_mode == EMode::RightTable, ETraversalMode::Children); + int selInView = x1c_ % 5; + if (IsRightLogDynamic()) + { + UpdateRightLogHighlight(tableActive, selInView, selColor, deselColor); + } + else + { + for (int i=0 ; iSetColor((i == selInView && tableActive) ? selColor : deselColor); + } + } + else + { + int sel = x70_tablegroup_leftlog->GetUserSelection(); + x78_model_lefthighlight->SetLocalTransform( + x78_model_lefthighlight->GetTransform() * zeus::CTransform::Translate(0.f, 0.f, x38_ * sel)); + for (int i=0 ; iSetColor(i == sel ? selColor : deselColor); + } } void CPauseScreenBase::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue) @@ -103,8 +203,8 @@ void CPauseScreenBase::Update(float dt, CRandom16& rand, CArchitectureQueue& arc x14_alpha = std::min(2.f * dt + x14_alpha, 1.f); u32 rightCount = GetRightTableCount(); - bool pulseRightUp = x10_mode == EMode::One && x18_ > 0; - bool pulseRightDown = x10_mode == EMode::One && x18_ + 5 < rightCount; + bool pulseRightUp = x10_mode == EMode::RightTable && x18_ > 0; + bool pulseRightDown = x10_mode == EMode::RightTable && x18_ + 5 < rightCount; float rightUpT = pulseRightUp ? CGraphics::GetSecondsMod900() : 0.f; float rightDownT = pulseRightDown ? CGraphics::GetSecondsMod900() : 0.f; @@ -148,7 +248,10 @@ void CPauseScreenBase::Draw(float mainAlpha, float frameAlpha, float yOff) void CPauseScreenBase::UpdateRightTable() { - + x18_ = 0; + x1c_ = 0; + x84_tablegroup_rightlog->SetUserSelection(1); + UpdateSideTable(x84_tablegroup_rightlog); } static const char* PaneSuffixes[] = diff --git a/Runtime/MP1/CPauseScreenBase.hpp b/Runtime/MP1/CPauseScreenBase.hpp index da8c86a49..c587acdfe 100644 --- a/Runtime/MP1/CPauseScreenBase.hpp +++ b/Runtime/MP1/CPauseScreenBase.hpp @@ -27,11 +27,11 @@ public: enum class EMode { Invalid = -1, - Zero = 0, - One = 1, - Two = 2 + LeftTable = 0, + RightTable = 1, + TextScroll = 2 }; -private: +protected: const CStateManager& x4_mgr; CGuiFrame& x8_frame; const CStringTable& xc_pauseStrg; @@ -93,8 +93,7 @@ private: }; void InitializeFrameGlue(); static std::string GetImagePaneName(u32 i); -protected: - void Activate(EMode mode); + void ChangeMode(EMode mode); void UpdateSideTable(CGuiTableGroup* table); public: CPauseScreenBase(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg); @@ -115,8 +114,12 @@ public: virtual float GetCameraYBias() const { return 0.f; } virtual bool VReady() const=0; virtual void VActivate() const=0; + virtual void ChangedMode() {} virtual void UpdateRightTable(); virtual u32 GetRightTableCount() const=0; + virtual bool IsRightLogDynamic() const { return false; } + virtual void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, zeus::CColor& inactiveColor) {} + virtual void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, zeus::CColor& inactiveColor) {} }; } diff --git a/Runtime/MP1/CSamusDoll.cpp b/Runtime/MP1/CSamusDoll.cpp index 5038e8e75..d5a5f191c 100644 --- a/Runtime/MP1/CSamusDoll.cpp +++ b/Runtime/MP1/CSamusDoll.cpp @@ -1,16 +1,414 @@ #include "CSamusDoll.hpp" +#include "GameGlobalObjects.hpp" +#include "CSimplePool.hpp" +#include "CDependencyGroup.hpp" +#include "zeus/CEulerAngles.hpp" +#include "Collision/CollisionUtil.hpp" namespace urde { namespace MP1 { +const zeus::CVector3f CSamusDoll::skInitialOffset = {0.f, 0.f, 0.8f}; + +static const std::pair SpiderBallGlassModels[] = +{ + {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 1}, + {"SamusPhazonBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 0}, + {"SamusSpiderBallGlassCMDL", 1}, + {"SamusPhazonBallGlassCMDL", 0}, +}; + +static const std::pair SpiderBallCharacters[] = +{ + {"SamusSpiderBallANCS", 0}, + {"SamusSpiderBallANCS", 0}, + {"SamusSpiderBallANCS", 1}, + {"SamusPhazonBallANCS", 0}, + {"SamusFusionBallANCS", 0}, + {"SamusFusionBallANCS", 2}, + {"SamusFusionBallANCS", 1}, + {"SamusFusionBallANCS", 3}, +}; + +static const std::pair BallCharacters[] = +{ + {"SamusBallANCS", 0}, + {"SamusBallANCS", 0}, + {"SamusBallANCS", 1}, + {"SamusBallANCS", 0}, + {"SamusFusionBallANCS", 0}, + {"SamusFusionBallANCS", 2}, + {"SamusFusionBallANCS", 1}, + {"SamusFusionBallANCS", 3}, +}; + +static const u32 SpiderBallGlowColorIdxs[] = +{ + 3, 3, 2, 4, 5, 7, 6, 8 +}; + +static const u32 BallGlowColorIdxs[] = +{ + 0, 0, 1, 0, 5, 7, 6, 8 +}; + +static const char* BeamModels[] = +{ + "CMDL_InvPowerBeam", + "CMDL_InvIceBeam", + "CMDL_InvWaveBeam", + "CMDL_InvPlasmaBeam", + "CMDL_InvPowerBeam" +}; + +static const char* VisorModels[] = +{ + "CMDL_InvVisor", + "CMDL_InvGravityVisor", + "CMDL_InvVisor", + "CMDL_InvPhazonVisor", + "CMDL_InvFusionVisor", + "CMDL_InvFusionVisor", + "CMDL_InvFusionVisor", + "CMDL_InvFusionVisor" +}; + +static const char* FinModels[] = +{ + "CMDL_InvPowerFins", + "CMDL_InvPowerFins", + "CMDL_InvPowerFins", + "CMDL_InvPowerFins", + "CMDL_InvPowerFins", + "CMDL_InvVariaFins", + "CMDL_InvGravityFins", + "CMDL_InvPhazonFins" +}; + +static const u32 Character1Idxs[8] = +{ + 0, 6, 2, 10, 16, 24, 20, 28 +}; + +static const u32 CharacterBootsIdxs[8] = +{ + 1, 7, 3, 11, 17, 25, 21, 29 +}; + +static const u32 Character2and3Idxs[8][2] = +{ + {14, 15}, + {8, 9}, + {4, 5}, + {12, 13}, + {18, 19}, + {26, 27}, + {22, 23}, + {30, 31} +}; + CSamusDoll::CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp, CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam, bool hasSpiderBall, bool hasGrappleBeam) +: x44_suit(suit), x48_beam(beam) +{ + x1d4_spiderBallGlass = g_SimplePool->GetObj(SpiderBallGlassModels[int(suit)].first); + x1e0_ballMatIdx = hasSpiderBall ? SpiderBallCharacters[int(suit)].second : BallCharacters[int(suit)].second; + x1e4_glassMatIdx = SpiderBallGlassModels[int(suit)].second; + x1e8_ballGlowColorIdx = hasSpiderBall ? SpiderBallGlowColorIdxs[int(suit)] : BallGlowColorIdxs[int(suit)]; + x1ec_itemScreenSamus = g_SimplePool->GetObj("ANCS_ItemScreenSamus"); + x1f4_invBeam = g_SimplePool->GetObj(BeamModels[int(beam)]); + x200_invVisor = g_SimplePool->GetObj(VisorModels[int(suit)]); + x20c_invGrappleBeam = g_SimplePool->GetObj("CMDL_InvGrappleBeam"); + x218_invFins = g_SimplePool->GetObj(FinModels[int(suit)]); + x224_ballInnerGlow = g_SimplePool->GetObj("BallInnerGlow"); + x22c_ballInnerGlowGen = std::make_unique(x224_ballInnerGlow, + CElementGen::EModelOrientationType::Normal, + CElementGen::EOptionalSystemFlags::One); + x230_ballTransitionFlash = g_SimplePool->GetObj("MorphBallTransitionFlash"); + x23c_lights.push_back(CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skWhite)); + x24c_actorLights = std::make_unique(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f); + x270_24_hasSpiderBall = hasSpiderBall; + x270_25_hasGrappleBeam = hasGrappleBeam; + x22c_ballInnerGlowGen->SetGlobalScale(zeus::CVector3f(0.625f)); + x0_depToks.reserve(suitDgrp.GetObjectTagVector().size() + ballDgrp.GetObjectTagVector().size()); + for (const SObjectTag& tag : suitDgrp.GetObjectTagVector()) + { + x0_depToks.push_back(g_SimplePool->GetObj(tag)); + x0_depToks.back().Lock(); + } + for (const SObjectTag& tag : ballDgrp.GetObjectTagVector()) + { + x0_depToks.push_back(g_SimplePool->GetObj(tag)); + x0_depToks.back().Lock(); + } +} + +bool CSamusDoll::IsLoaded() const +{ + if (x270_31_loaded) + return true; + if (!x1ec_itemScreenSamus.IsLoaded()) + return false; + if (!x1f4_invBeam.IsLoaded()) + return false; + if (!x200_invVisor.IsLoaded()) + return false; + if (!x20c_invGrappleBeam.IsLoaded()) + return false; + if (!x1d4_spiderBallGlass.IsLoaded()) + return false; + if (x218_invFins && !x218_invFins.IsLoaded()) + return false; + return xc8_suitModel1.operator bool(); +} + +CModelData CSamusDoll::BuildSuitModelData1(CPlayerState::EPlayerSuit suit) +{ + CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, + Character1Idxs[int(suit)], zeus::CVector3f::skOne, 2, true)); + CAnimPlaybackParms parms(2, -1, 1.f, true); + ret.AnimationData()->SetAnimation(parms, false); + return ret; +} + +CModelData CSamusDoll::BuildSuitModelDataBoots(CPlayerState::EPlayerSuit suit) +{ + CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, + CharacterBootsIdxs[int(suit)], zeus::CVector3f::skOne, 2, true)); + CAnimPlaybackParms parms(2, -1, 1.f, true); + ret.AnimationData()->SetAnimation(parms, false); + return ret; +} + +bool CSamusDoll::CheckLoadComplete() +{ + if (IsLoaded()) + return true; + + for (const CToken& tok : x0_depToks) + if (!tok.IsLoaded()) + return false; + + xc8_suitModel1.emplace(BuildSuitModelData1(x44_suit)); + for (int i=0 ; i<2 ; ++i) + { + CAnimRes res(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id, + Character2and3Idxs[int(x44_suit)][i], + zeus::CVector3f::skOne, 2, true); + CModelData mData(res); + x118_suitModel1and2.push_back(mData.GetAnimationData()->GetModelData()); + x118_suitModel1and2.back().Lock(); + } + x134_suitModelBoots.emplace(BuildSuitModelDataBoots(x44_suit)); + + CAnimRes res(g_ResFactory->GetResourceIdByName(x270_24_hasSpiderBall ? + SpiderBallCharacters[int(x44_suit)].first : + BallCharacters[int(x44_suit)].first)->id, + 0, zeus::CVector3f::skOne, 0, true); + x184_ballModelData.emplace(res); + x1e0_ballMatIdx = x270_24_hasSpiderBall ? + SpiderBallCharacters[int(x44_suit)].second : + BallCharacters[int(x44_suit)].second; + x270_31_loaded = true; + return true; +} + +void CSamusDoll::Update(float dt, CRandom16& rand) { } +void CSamusDoll::Draw(const CStateManager& mgr, float alpha) +{ + +} + +void CSamusDoll::Touch() +{ + if (!CheckLoadComplete()) + return; + xc8_suitModel1->AnimationData()->PreRender(); + x134_suitModelBoots->AnimationData()->PreRender(); + x184_ballModelData->AnimationData()->PreRender(); + xc8_suitModel1->Touch(CModelData::EWhichModel::Normal, 0); + x134_suitModelBoots->Touch(CModelData::EWhichModel::Normal, 0); + x184_ballModelData->Touch(CModelData::EWhichModel::Normal, 0); +} + +void CSamusDoll::SetupLights() +{ + x23c_lights[0] = CLight::BuildDirectional(xb0_rot.toTransform().basis[1], zeus::CColor(0.75f, 1.f)); + x24c_actorLights->BuildFakeLightList(x23c_lights, zeus::CColor::skBlack); +} + +void CSamusDoll::CheckTransition(bool morphballComplete) +{ + if (x54_ > 0.f) + return; + if (x4d_morphballComplete == morphballComplete) + return; + x4d_morphballComplete = morphballComplete; + SetTransitionAnimation(); +} + +void CSamusDoll::SetTransitionAnimation() +{ + if (!x4c_intoBallComplete) + { + xc8_suitModel1->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); + x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false); + x50_ = x54_ = xc8_suitModel1->GetAnimationData()->GetAnimationDuration(0); + } + else if (!x4d_morphballComplete) + { + xc8_suitModel1->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); + x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false); + x50_ = x54_ = xc8_suitModel1->GetAnimationData()->GetAnimationDuration(1); + } +} + +void CSamusDoll::SetRotationSfxPlaying(bool playing) +{ + if (playing) + { + if (x268_rotateSfx) + return; + x268_rotateSfx = CSfxManager::SfxStart(1375, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } + else + { + CSfxManager::SfxStop(x268_rotateSfx); + x268_rotateSfx.reset(); + } +} + +void CSamusDoll::SetOffsetSfxPlaying(bool playing) +{ + if (playing) + { + if (x264_offsetSfx) + return; + x264_offsetSfx = CSfxManager::SfxStart(1406, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } + else + { + CSfxManager::SfxStop(x264_offsetSfx); + x264_offsetSfx.reset(); + } +} + +void CSamusDoll::SetZoomSfxPlaying(bool playing) +{ + if (playing) + { + if (x26c_zoomSfx) + return; + x26c_zoomSfx = CSfxManager::SfxStart(1376, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId); + } + else + { + CSfxManager::SfxStop(x26c_zoomSfx); + x26c_zoomSfx.reset(); + } +} + +void CSamusDoll::SetRotation(float xDelta, float zDelta, float f3) +{ + if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) + return; + SetRotationSfxPlaying(xDelta != 0.f || zDelta != 0.f); + zeus::CEulerAngles angles(xb0_rot); + + zeus::CRelAngle angX(angles.x); + zeus::CRelAngle angZ(angles.z); + + angX += xDelta; + angZ += zDelta; + + float angXCenter = angX; + if (angXCenter > M_PIF) + angXCenter -= 2.f * M_PIF; + angX = zeus::clamp(-M_PIF / 2.f, angXCenter, M_PIF / 2.f); + + float angZCenter = angZ; + if (angZCenter > M_PIF) + angZCenter -= 2.f * M_PIF; + angZ = zeus::clamp(-M_PIF / 2.f, angZCenter, M_PIF / 2.f); + + zeus::CQuaternion quat; + quat.rotateZ(angZ); + quat.rotateX(angX); + xb0_rot = quat; +} + +void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float sfxThreshold) +{ + if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f) + return; + zeus::CVector3f oldOffset = xa4_offset; + zeus::CMatrix3f rotMtx = xb0_rot.toTransform().basis; + xa4_offset += rotMtx * zeus::CVector3f(offset.x, 0.f, offset.z); + SetOffsetSfxPlaying((oldOffset - xa4_offset).magnitude() > sfxThreshold); + float oldZoom = xc0_zoom; + xc0_zoom = zeus::clamp(-4.f, xc0_zoom + offset.y, -2.2f); + bool zoomSfx = std::fabs(xc0_zoom - oldZoom) > sfxThreshold; + float zoomDelta = offset.y - (xc0_zoom - oldZoom); + zeus::CVector3f newOffset = rotMtx[1] * zoomDelta + xa4_offset; + zeus::CVector3f delta = newOffset - xa4_offset; + oldOffset = xa4_offset; + if (!delta.isZero()) + { + zeus::CSphere sphere(skInitialOffset, 1.f); + float T; + zeus::CVector3f point; + if (CollisionUtil::RaySphereIntersection(sphere, xa4_offset, delta.normalized(), 0.f, T, point)) + { + if ((point - xa4_offset).magnitude() < std::fabs(zoomDelta)) + xa4_offset = point; + else + xa4_offset = newOffset; + } + else + { + xa4_offset = newOffset; + } + } + if ((oldOffset - xa4_offset).magnitude() > sfxThreshold) + zoomSfx = true; + SetZoomSfxPlaying(zoomSfx); + delta = xa4_offset - skInitialOffset; + if (delta.magnitude() > 1.f) + xa4_offset = delta.normalized() + skInitialOffset; +} + +void CSamusDoll::BeginViewInterpolate(bool zoomOut) +{ + if (xc4_viewInterp == 0.f) + { + CSfxManager::SfxStart(1440, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + else + { + SetOffsetSfxPlaying(false); + SetZoomSfxPlaying(false); + SetRotationSfxPlaying(false); + CSfxManager::SfxStart(1441, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId); + } + + xc4_viewInterp = zoomOut ? FLT_EPSILON : (-1.f + FLT_EPSILON); + x84_interpStartOffset = xa4_offset; + x90_interpStartRot = xb0_rot; + xa0_interpStartZoom = xc0_zoom; + + x80_ = zoomOut ? -2.2f : -3.6f; +} + } } diff --git a/Runtime/MP1/CSamusDoll.hpp b/Runtime/MP1/CSamusDoll.hpp index 6f6e67c6e..32ccb7906 100644 --- a/Runtime/MP1/CSamusDoll.hpp +++ b/Runtime/MP1/CSamusDoll.hpp @@ -4,6 +4,10 @@ #include "CPlayerState.hpp" #include "CToken.hpp" #include "Character/CModelData.hpp" +#include "Character/CAnimCharacterSet.hpp" +#include "Particle/CElementGen.hpp" +#include "Character/CActorLights.hpp" +#include "Audio/CSfxManager.hpp" namespace urde { @@ -19,14 +23,85 @@ class CSamusDoll CPlayerState::EPlayerSuit x44_suit; CPlayerState::EBeamId x48_beam; bool x4c_intoBallComplete = false; - bool x4d_morphball = false; + bool x4d_morphballComplete = false; + float x50_ = 1.f; + float x54_ = 0.f; + float x58_ = 0.f; + float x5c_ = 0.f; + float x60_ = 0.f; + float x64_ = 0.f; + float x68_ = 0.f; + float x6c_ = 0.f; + zeus::CQuaternion x70_; + float x80_ = -3.6f; + zeus::CVector3f x84_interpStartOffset = skInitialOffset; + zeus::CQuaternion x90_interpStartRot; + float xa0_interpStartZoom = -3.6f; + zeus::CVector3f xa4_offset = skInitialOffset; + zeus::CQuaternion xb0_rot; + float xc0_zoom = -3.6f; + float xc4_viewInterp = 0.f; std::experimental::optional xc8_suitModel1; rstl::reserved_vector, 2> x118_suitModel1and2; std::experimental::optional x134_suitModelBoots; + std::experimental::optional x184_ballModelData; + bool x1d0_ = false; + TLockedToken x1d4_spiderBallGlass; + u32 x1e0_ballMatIdx; + u32 x1e4_glassMatIdx; + u32 x1e8_ballGlowColorIdx; + TLockedToken x1ec_itemScreenSamus; + TLockedToken x1f4_invBeam; + TLockedToken x200_invVisor; + TLockedToken x20c_invGrappleBeam; + TLockedToken x218_invFins; + TLockedToken x224_ballInnerGlow; + std::unique_ptr x22c_ballInnerGlowGen; + TLockedToken x230_ballTransitionFlash; + std::vector x23c_lights; + std::unique_ptr x24c_actorLights; + bool x25c_ = false; + float x260_ = 0.f; + CSfxHandle x264_offsetSfx; + CSfxHandle x268_rotateSfx; + CSfxHandle x26c_zoomSfx; + union + { + struct + { + bool x270_24_hasSpiderBall : 1; + bool x270_25_hasGrappleBeam : 1; + bool x270_26_ : 1; + bool x270_27_ : 1; + bool x270_28_ : 1; + bool x270_29_ : 1; + bool x270_30_ : 1; + bool x270_31_loaded : 1; + }; + u32 _dummy = 0; + }; + + static const zeus::CVector3f skInitialOffset; + static CModelData BuildSuitModelData1(CPlayerState::EPlayerSuit suit); + static CModelData BuildSuitModelDataBoots(CPlayerState::EPlayerSuit suit); + void SetupLights(); + void SetTransitionAnimation(); + void SetRotationSfxPlaying(bool playing); + void SetOffsetSfxPlaying(bool playing); + void SetZoomSfxPlaying(bool playing); public: CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp, CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam, bool hasSpiderBall, bool hasGrappleBeam); + bool IsLoaded() const; + bool CheckLoadComplete(); + void Update(float dt, CRandom16& rand); + void Draw(const CStateManager& mgr, float alpha); + void Touch(); + void CheckTransition(bool morphballComplete); + void SetRotation(float xDelta, float zDelta, float); + void SetOffset(const zeus::CVector3f& offset, float sfxThreshold); + void BeginViewInterpolate(bool zoomOut); }; } diff --git a/specter b/specter index 07daf4082..f5f78fdee 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit 07daf408244c41188e90bbf3e7a78be37a1d0dce +Subproject commit f5f78fdeefd8a0d1a708ca31df8dc2cb2adc8482