From 4469a78241376c2cd4c28dba7bca0b4867c5a1fe Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Mon, 1 Dec 2025 17:47:08 -0800 Subject: [PATCH] Nearly match CScriptDoor --- config/GM8E01_00/symbols.txt | 18 +-- config/GM8E01_01/symbols.txt | 2 +- include/MetroidPrime/CModelData.hpp | 3 + include/MetroidPrime/Cameras/CBallCamera.hpp | 1 + .../ScriptObjects/CScriptDoor.hpp | 10 +- .../ScriptObjects/CScriptDoor.cpp | 113 +++++++++++++++++- 6 files changed, 132 insertions(+), 15 deletions(-) diff --git a/config/GM8E01_00/symbols.txt b/config/GM8E01_00/symbols.txt index bac8230e..5f763c19 100644 --- a/config/GM8E01_00/symbols.txt +++ b/config/GM8E01_00/symbols.txt @@ -5715,7 +5715,7 @@ __ct__Q210IAllocator8SMetricsFRCQ210IAllocator8SMetrics = .text:0x800C364C; // t GetCurrentConnectedAreaId__11CScriptDockCFRC13CStateManager = .text:0x800C3700; // type:function size:0x9C scope:global UpdateAreaActivateFlags__11CScriptDockFR13CStateManager = .text:0x800C379C; // type:function size:0xFC scope:global SetDockReference__11CScriptDockFR13CStateManageri = .text:0x800C3898; // type:function size:0x6C scope:global -GetDockReference__11CScriptDockCFv = .text:0x800C3904; // type:function size:0x4C scope:global +GetDockReference__11CScriptDockCFRC13CStateManager = .text:0x800C3904; // type:function size:0x4C scope:global Accept__11CScriptDockFR8IVisitor = .text:0x800C3950; // type:function size:0x38 scope:global GetPlane__11CScriptDockCFRC13CStateManager = .text:0x800C3988; // type:function size:0x8C scope:global HasPointCrossedDock__11CScriptDockCFRC13CStateManagerRC9CVector3f = .text:0x800C3A14; // type:function size:0xA4 scope:global @@ -18124,7 +18124,7 @@ __vt__15CBCKnockBackCmd = .data:0x803DAA44; // type:object size:0xC scope:global __vt__15CBCKnockDownCmd = .data:0x803DAA50; // type:object size:0xC scope:global __vt__12CBCHurledCmd = .data:0x803DAA5C; // type:object size:0xC scope:global __vt__13CBodyStateCmd = .data:0x803DAA68; // type:object size:0x10 scope:global -lbl_803DAA78 = .data:0x803DAA78; // type:object size:0x84 +__vt__11CScriptDoor = .data:0x803DAA78; // type:object size:0x84 jumptable_803DAAFC = .data:0x803DAAFC; // type:object size:0x84 scope:local __vt__35TObjOwnerDerivedFromIObj<8CMapArea> = .data:0x803DAB80; // type:object size:0xC scope:weak __vt__11CBallCamera = .data:0x803DAB90; // type:object size:0x74 scope:global @@ -19821,13 +19821,13 @@ lbl_805A6FE0 = .sdata:0x805A6FE0; // type:object size:0x4 data:4byte lbl_805A6FE4 = .sdata:0x805A6FE4; // type:object size:0x4 data:4byte lbl_805A6FE8 = .sdata:0x805A6FE8; // type:object size:0x4 data:4byte lbl_805A6FEC = .sdata:0x805A6FEC; // type:object size:0x4 data:4byte -lbl_805A6FF0 = .sdata:0x805A6FF0; // type:object size:0x4 data:4byte -lbl_805A6FF4 = .sdata:0x805A6FF4; // type:object size:0x4 data:4byte -lbl_805A6FF8 = .sdata:0x805A6FF8; // type:object size:0x4 data:4byte -lbl_805A6FFC = .sdata:0x805A6FFC; // type:object size:0x4 data:4byte -lbl_805A7000 = .sdata:0x805A7000; // type:object size:0x4 data:4byte -lbl_805A7004 = .sdata:0x805A7004; // type:object size:0x4 data:4byte -lbl_805A7008 = .sdata:0x805A7008; // type:object size:0x8 data:4byte +@338 = .sdata:0x805A6FF0; // type:object size:0x4 data:4byte +@339 = .sdata:0x805A6FF4; // type:object size:0x4 data:4byte +@340 = .sdata:0x805A6FF8; // type:object size:0x4 data:4byte +@341 = .sdata:0x805A6FFC; // type:object size:0x4 data:4byte +@342 = .sdata:0x805A7000; // type:object size:0x4 data:4byte +@343 = .sdata:0x805A7004; // type:object size:0x4 data:4byte +@344 = .sdata:0x805A7008; // type:object size:0x8 data:4byte gHackAssetId = .sdata:0x805A7010; // type:object size:0x4 scope:local data:4byte lbl_805A7018 = .sdata:0x805A7018; // type:object size:0x4 lbl_805A701C = .sdata:0x805A701C; // type:object size:0x4 diff --git a/config/GM8E01_01/symbols.txt b/config/GM8E01_01/symbols.txt index 7fdff567..72686a2e 100644 --- a/config/GM8E01_01/symbols.txt +++ b/config/GM8E01_01/symbols.txt @@ -5715,7 +5715,7 @@ __ct__Q210IAllocator8SMetricsFRCQ210IAllocator8SMetrics = .text:0x800C36C8; // t GetCurrentConnectedAreaId__11CScriptDockCFRC13CStateManager = .text:0x800C377C; // type:function size:0x9C scope:global UpdateAreaActivateFlags__11CScriptDockFR13CStateManager = .text:0x800C3818; // type:function size:0xFC scope:global SetDockReference__11CScriptDockFR13CStateManageri = .text:0x800C3914; // type:function size:0x6C scope:global -GetDockReference__11CScriptDockCFv = .text:0x800C3980; // type:function size:0x4C scope:global +GetDockReference__11CScriptDockCFRC13CStateManager = .text:0x800C3980; // type:function size:0x4C scope:global Accept__11CScriptDockFR8IVisitor = .text:0x800C39CC; // type:function size:0x38 scope:global GetPlane__11CScriptDockCFRC13CStateManager = .text:0x800C3A04; // type:function size:0x8C scope:global HasPointCrossedDock__11CScriptDockCFRC13CStateManagerRC9CVector3f = .text:0x800C3A90; // type:function size:0xA4 scope:global diff --git a/include/MetroidPrime/CModelData.hpp b/include/MetroidPrime/CModelData.hpp index be2bb7cc..56d6e826 100644 --- a/include/MetroidPrime/CModelData.hpp +++ b/include/MetroidPrime/CModelData.hpp @@ -116,6 +116,9 @@ public: void EnableLooping(bool enable); static CModelData CModelDataNull(); static EWhichModel GetRenderingModel(const CStateManager& mgr); + float GetAnimationDuration(int anim) const; + + bool IsAnimating() const; private: CVector3f x0_scale; diff --git a/include/MetroidPrime/Cameras/CBallCamera.hpp b/include/MetroidPrime/Cameras/CBallCamera.hpp index 0c85cf21..1d9bf03d 100644 --- a/include/MetroidPrime/Cameras/CBallCamera.hpp +++ b/include/MetroidPrime/Cameras/CBallCamera.hpp @@ -169,6 +169,7 @@ public: void SetClampVelRange(float v) { x474_clampVelRange = v; } void DoorClosing(TUniqueId uid); + void DoorClosed(TUniqueId uid); private: struct SFailsafeState { diff --git a/include/MetroidPrime/ScriptObjects/CScriptDoor.hpp b/include/MetroidPrime/ScriptObjects/CScriptDoor.hpp index bff7f8e2..e73ce25f 100644 --- a/include/MetroidPrime/ScriptObjects/CScriptDoor.hpp +++ b/include/MetroidPrime/ScriptObjects/CScriptDoor.hpp @@ -34,11 +34,19 @@ public: void OpenDoor(TUniqueId uid, CStateManager& mgr); void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) override; + void Think(float dt, CStateManager& mgr) override; - const TUniqueId GetDockID() const { return mDockId; } + const TUniqueId GetConnectedDockID() const { return mDockId; } bool IsOpen() const { return mIsOpen; } void SetDoClose(const bool close) { mDoClose = close; } + bool IsConnectedToArea(const CStateManager& mgr, TAreaId area) const; + void ForceClosed(CStateManager& mgr); + + void AddToRenderer(const CFrustumPlanes& /*frustum*/, const CStateManager& mgr) const override; + void Render(const CStateManager& mgr) const override; + void Accept(IVisitor& visitor) override; + private: float mAnimLength; float mAnimTime; diff --git a/src/MetroidPrime/ScriptObjects/CScriptDoor.cpp b/src/MetroidPrime/ScriptObjects/CScriptDoor.cpp index 49ed9b05..e215f25d 100644 --- a/src/MetroidPrime/ScriptObjects/CScriptDoor.cpp +++ b/src/MetroidPrime/ScriptObjects/CScriptDoor.cpp @@ -1,5 +1,7 @@ #include "MetroidPrime/ScriptObjects/CScriptDoor.hpp" +#include "Collision/CMaterialList.hpp" +#include "Kyoto/Math/CFrustumPlanes.hpp" #include "MetroidPrime/CAnimData.hpp" #include "MetroidPrime/CAnimPlaybackParms.hpp" #include "MetroidPrime/CEntity.hpp" @@ -8,9 +10,11 @@ #include "MetroidPrime/CMapWorldInfo.hpp" #include "MetroidPrime/CObjectList.hpp" #include "MetroidPrime/CPhysicsActor.hpp" +#include "MetroidPrime/CStateManager.hpp" #include "MetroidPrime/CWorld.hpp" #include "MetroidPrime/Cameras/CBallCamera.hpp" #include "MetroidPrime/Cameras/CCameraManager.hpp" +#include "MetroidPrime/Player/CPlayerState.hpp" #include "MetroidPrime/ScriptObjects/CScriptDock.hpp" #include "MetroidPrime/TCastTo.hpp" #include "MetroidPrime/TGameTypes.hpp" @@ -77,7 +81,7 @@ CScriptDoor::EDoorOpenCondition CScriptDoor::GetDoorOpenCondition(CStateManager& } void CScriptDoor::OpenDoor(TUniqueId uid, CStateManager& mgr) { - mgr.MapWorldInfo()->SetDoorVisited(mgr.GetEditorIdForUniqueId(uid), true); + mgr.MapWorldInfo()->SetDoorVisited(mgr.GetEditorIdForUniqueId(GetUniqueId()), true); mIsOpen = true; mWasOpen = true; mConditionsMet = false; @@ -105,7 +109,7 @@ void CScriptDoor::OpenDoor(TUniqueId uid, CStateManager& mgr) { } if (const CScriptDock* dock2 = - TCastToConstPtr< CScriptDock >(mgr.GetObjectById(door->GetDockID()))) { + TCastToConstPtr< CScriptDock >(mgr.GetObjectById(door->GetConnectedDockID()))) { if (dock2->GetAreaId() == dock1->GetCurrentConnectedAreaId(mgr) && dock2->GetCurrentConnectedAreaId(mgr) == dock1->GetAreaId()) { mPartner2 = door->GetUniqueId(); @@ -119,8 +123,8 @@ void CScriptDoor::OpenDoor(TUniqueId uid, CStateManager& mgr) { if (mPartner1 == kInvalidUniqueId && mPartner2 == kInvalidUniqueId) { - rstl::vector< SConnection >::const_iterator it = GetConnectionList().begin(); - for (; it != GetConnectionList().end(); ++it) { + for (rstl::vector< SConnection >::const_iterator it = GetConnectionList().begin(); + it != GetConnectionList().end(); ++it) { if (it->x4_msg != kSM_Open) { continue; } @@ -246,3 +250,104 @@ void CScriptDoor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStat break; } } + +void CScriptDoor::Think(float dt, CStateManager& mgr) { + if (!GetActive()) { + return; + } + + if (!mIsOpen && mAnimTime < 0.5f) { + mAnimTime += dt; + } + + if (mConditionsMet && GetDoorOpenCondition(mgr) == kDOC_Ready) { + mConditionsMet = false; + OpenDoor(mPrevDoor, mgr); + } + + if (mClosing) { + mWasOpen = false; + mgr.GetCameraManager()->BallCamera()->DoorClosed(GetUniqueId()); + mProjectilesCollide = false; + mClosing = false; + SendScriptMsgs(kSS_Closed, mgr, kSM_Decrement); + mAnimTime = 0.f; + mDoClose = false; + } + + if (mIsOpen && !GetModelData()->IsAnimating()) { + RemoveMaterial(kMT_Solid, kMT_Occluder, kMT_Orbit, kMT_Scannable, mgr); + } else { + if (mWasOpen && !GetModelData()->IsAnimating()) { + mWasOpen = false; + mgr.GetCameraManager()->BallCamera()->DoorClosed(GetUniqueId()); + mProjectilesCollide = false; + mConditionsMet = false; + SendScriptMsgs(kSS_Closed, mgr, kSM_None); + mAnimTime = 0.f; + mDoClose = false; + } + + if (GetScannableObjectInfo()) { + AddMaterial(kMT_Solid, kMT_Metal, kMT_Occluder, kMT_Orbit, kMT_Scannable, mgr); + } else { + AddMaterial(kMT_Solid, kMT_Metal, kMT_Occluder, kMT_Orbit, mgr); + } + } + + if (GetModelData()->IsAnimating()) { + float len = GetModelData()->GetAnimationDuration(static_cast< int >(mDoorState)); + len /= mAnimLength; + UpdateAnimation(len * dt, mgr, true); + } + SetTargetable(mgr.GetPlayerState()->GetCurrentVisor() == CPlayerState::kPV_Scan); +} + +bool CScriptDoor::IsConnectedToArea(const CStateManager& mgr, TAreaId areaId) const { + const CScriptDock* dockEnt = TCastToConstPtr< CScriptDock >(mgr.GetObjectById(mDockId)); + if (dockEnt) { + if (dockEnt->GetAreaId() == areaId) { + return true; + } + + const CWorld* world = mgr.GetWorld(); + const CGameArea& area = world->GetAreaAlways(dockEnt->GetAreaId()); + const CGameArea::Dock& dock = area.GetDock(dockEnt->GetDockId()); + if (dock.GetConnectedAreaId(dockEnt->GetDockReference(mgr)) == areaId) { + return true; + } + } + return false; +} + +void CScriptDoor::ForceClosed(CStateManager& mgr) { + if (mIsOpen) { + mIsOpen = false; + mWasOpen = false; + + mgr.GetCameraManager()->BallCamera()->DoorClosing(GetUniqueId()); + mgr.GetCameraManager()->BallCamera()->DoorClosed(GetUniqueId()); + + SetDoorAnimation(kDS_Close); + SendScriptMsgs(kSS_Closed, mgr, kSM_None); + mConditionsMet = false; + mAnimTime = 0.f; + mDoClose = false; + } else if (mConditionsMet) { + mConditionsMet = false; + mDoClose = false; + SendScriptMsgs(kSS_Closed, mgr, kSM_None); + } +} + +void CScriptDoor::AddToRenderer(const CFrustumPlanes& /*frustum*/, const CStateManager& mgr) const { + if (GetPreRenderClipped()) { + return; + } + + CPhysicsActor::Render(mgr); +} + +void CScriptDoor::Render(const CStateManager& mgr) const {} + +void CScriptDoor::Accept(IVisitor& visitor) { visitor.Visit(*this); }