Initial CScriptDoor matches

This commit is contained in:
2025-12-01 16:32:29 -08:00
parent 9f0a697af2
commit 60219e550c
8 changed files with 322 additions and 4 deletions

View File

@@ -1891,7 +1891,7 @@ ForceClosed__11CScriptDoorFR13CStateManager = .text:0x8007E0BC; // type:function
IsConnectedToArea__11CScriptDoorCFRC13CStateManager7TAreaId = .text:0x8007E1C4; // type:function size:0xD8 scope:global
Think__11CScriptDoorFfR13CStateManager = .text:0x8007E29C; // type:function size:0x2B4 scope:global
AcceptScriptMsg__11CScriptDoorF20EScriptObjectMessage9TUniqueIdR13CStateManager = .text:0x8007E550; // type:function size:0x480 scope:global
SetDoorAnimation__11CScriptDoorFQ211CScriptDoor13EDoorAnimType = .text:0x8007E9D0; // type:function size:0x94 scope:global
SetDoorAnimation__11CScriptDoorFQ211CScriptDoor10EDoorState = .text:0x8007E9D0; // type:function size:0x94 scope:global
OpenDoor__11CScriptDoorF9TUniqueIdR13CStateManager = .text:0x8007EA64; // type:function size:0x2E8 scope:global
GetDoorOpenCondition__11CScriptDoorFR13CStateManager = .text:0x8007ED4C; // type:function size:0x308 scope:global
GetOrbitPosition__11CScriptDoorCFRC13CStateManager = .text:0x8007F054; // type:function size:0x34 scope:global
@@ -21626,8 +21626,8 @@ lbl_805A8E2C = .sbss:0x805A8E2C; // type:object size:0x4 data:4byte
lbl_805A8E30 = .sbss:0x805A8E30; // type:object size:0x8 data:byte
lbl_805A8E38 = .sbss:0x805A8E38; // type:object size:0x4 data:4byte
lbl_805A8E3C = .sbss:0x805A8E3C; // type:object size:0x4 data:4byte
lbl_805A8E40 = .sbss:0x805A8E40; // type:object size:0x4 data:4byte
lbl_805A8E44 = .sbss:0x805A8E44; // type:object size:0x1 data:byte
i$486 = .sbss:0x805A8E40; // type:object size:0x4 data:4byte
init$487 = .sbss:0x805A8E44; // type:object size:0x1 data:byte
kLineOfSightIncludeList = .sbss:0x805A8E48; // type:object size:0x4 scope:local data:4byte
lbl_805A8E4C = .sbss:0x805A8E4C; // type:object size:0x4 data:4byte
kLineOfSightExcludeList = .sbss:0x805A8E50; // type:object size:0x4 scope:local data:4byte

View File

@@ -1891,7 +1891,7 @@ ForceClosed__11CScriptDoorFR13CStateManager = .text:0x8007E138; // type:function
IsConnectedToArea__11CScriptDoorCFRC13CStateManager7TAreaId = .text:0x8007E240; // type:function size:0xD8 scope:global
Think__11CScriptDoorFfR13CStateManager = .text:0x8007E318; // type:function size:0x2B4 scope:global
AcceptScriptMsg__11CScriptDoorF20EScriptObjectMessage9TUniqueIdR13CStateManager = .text:0x8007E5CC; // type:function size:0x480 scope:global
SetDoorAnimation__11CScriptDoorFQ211CScriptDoor13EDoorAnimType = .text:0x8007EA4C; // type:function size:0x94 scope:global
SetDoorAnimation__11CScriptDoorFQ211CScriptDoor10EDoorState = .text:0x8007EA4C; // type:function size:0x94 scope:global
OpenDoor__11CScriptDoorF9TUniqueIdR13CStateManager = .text:0x8007EAE0; // type:function size:0x2E8 scope:global
GetDoorOpenCondition__11CScriptDoorFR13CStateManager = .text:0x8007EDC8; // type:function size:0x308 scope:global
GetOrbitPosition__11CScriptDoorCFRC13CStateManager = .text:0x8007F0D0; // type:function size:0x34 scope:global

View File

@@ -7,6 +7,7 @@ class CMapWorldInfo {
public:
bool IsAreaVisible(const TAreaId areaId) const;
bool IsDoorVisited(const TEditorId eid) const;
void SetDoorVisited(TEditorId eid, const bool visited);
};
#endif // _CMAPWORLDINFO

View File

@@ -291,6 +291,7 @@ public:
bool GetInMapScreen() const { return xf94_27_inMapScreen; }
void SetIsFullThreat(bool v) { xf94_30_fullThreat = v; }
uint GetInputFrameIdx() const { return x8d4_inputFrameIdx; }
CMapWorldInfo* MapWorldInfo() const { return x8c0_mapWorldInfo.GetPtr(); }
private:
enum EInitPhase { kIP_LoadWorld, kIP_LoadFirstArea, kIP_Done };

View File

@@ -143,6 +143,9 @@ public:
static CGameArea::CConstChainIterator GetAliveAreasEnd();
void StopGlobalSound(ushort soundId);
int GetNumAreas() const { return x18_areas.size(); }
bool AreSkyNeedsMet() const;
private:
enum Phase {
kP_Loading,

View File

@@ -168,6 +168,8 @@ public:
void SetClampVelTimer(float v) { x470_clampVelTimer = v; }
void SetClampVelRange(float v) { x474_clampVelRange = v; }
void DoorClosing(TUniqueId uid);
private:
struct SFailsafeState {
CTransform4f x0_playerXf;

View File

@@ -0,0 +1,63 @@
#ifndef _CSCRIPTDOOR
#define _CSCRIPTDOOR
#include "MetroidPrime/CPhysicsActor.hpp"
class CScriptDoor : public CPhysicsActor {
public:
enum EDoorState {
kDS_Open,
kDS_Close,
kDS_Ready,
};
enum EDoorOpenCondition {
kDOC_NotReady,
kDOC_Loading,
kDOC_Ready,
};
CScriptDoor(TUniqueId uid, const rstl::string& name, const CEntityInfo& info,
const CTransform4f& xf, const CModelData& modelData,
const CActorParameters& actorParameters, const CVector3f& orbitPosition,
const CAABox& bounds, bool active, bool open, bool projectilesCollide,
float animationLength, bool ballDoor);
void SetDoorAnimation(EDoorState state);
rstl::optional_object< CAABox > GetTouchBounds() const override;
rstl::optional_object< CAABox > GetProjectileBounds() const;
CVector3f GetOrbitPosition(const CStateManager& mgr) const override;
EDoorOpenCondition GetDoorOpenCondition(CStateManager& mgr);
void OpenDoor(TUniqueId uid, CStateManager& mgr);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId other, CStateManager& mgr) override;
const TUniqueId GetDockID() const { return mDockId; }
bool IsOpen() const { return mIsOpen; }
void SetDoClose(const bool close) { mDoClose = close; }
private:
float mAnimLength;
float mAnimTime;
EDoorState mDoorState;
CAABox x264_;
TUniqueId mPartner1;
TUniqueId mPartner2;
TUniqueId mPrevDoor;
TUniqueId mDockId;
CAABox mModelBounds;
CVector3f mOrbitPos;
bool mClosing : 1;
bool mWasOpen : 1;
bool mIsOpen : 1;
bool mConditionsMet : 1;
bool mProjectilesCollide : 1;
bool mBallDoor : 1;
bool mDoClose : 1;
};
#endif // _CSCRIPTDOOR

View File

@@ -0,0 +1,248 @@
#include "MetroidPrime/ScriptObjects/CScriptDoor.hpp"
#include "MetroidPrime/CAnimData.hpp"
#include "MetroidPrime/CAnimPlaybackParms.hpp"
#include "MetroidPrime/CEntity.hpp"
#include "MetroidPrime/CEntityInfo.hpp"
#include "MetroidPrime/CGameArea.hpp"
#include "MetroidPrime/CMapWorldInfo.hpp"
#include "MetroidPrime/CObjectList.hpp"
#include "MetroidPrime/CPhysicsActor.hpp"
#include "MetroidPrime/CWorld.hpp"
#include "MetroidPrime/Cameras/CBallCamera.hpp"
#include "MetroidPrime/Cameras/CCameraManager.hpp"
#include "MetroidPrime/ScriptObjects/CScriptDock.hpp"
#include "MetroidPrime/TCastTo.hpp"
#include "MetroidPrime/TGameTypes.hpp"
CScriptDoor::CScriptDoor(TUniqueId uid, const rstl::string& name, const CEntityInfo& info,
const CTransform4f& xf, const CModelData& modelData,
const CActorParameters& actorParameters, const CVector3f& orbitPosition,
const CAABox& bounds, const bool active, const bool open,
const bool projectilesCollide, const float animationLength,
const bool ballDoor)
: CPhysicsActor(uid, active, name, info, xf, modelData,
open ? CMaterialList(kMT_Solid, kMT_Immovable, kMT_Orbit)
: CMaterialList(kMT_Solid, kMT_Immovable, kMT_Orbit, kMT_Occluder),
bounds, SMoverData(1.f), actorParameters, 0.3f, 0.1f)
, mAnimLength(animationLength)
, mAnimTime(0.f)
, mDoorState(kDS_Open)
, x264_(GetBoundingBox())
, mPartner1(kInvalidUniqueId)
, mPartner2(kInvalidUniqueId)
, mPrevDoor(kInvalidUniqueId)
, mDockId(kInvalidUniqueId)
, mModelBounds(modelData.GetBounds(xf.GetRotation()))
, mOrbitPos(orbitPosition)
, mClosing(false)
, mWasOpen(open)
, mIsOpen(open)
, mConditionsMet(false)
, mProjectilesCollide(projectilesCollide)
, mBallDoor(ballDoor)
, mDoClose(false) {
SetThermalFlags(kTF_Cold);
if (open) {
SetDoorAnimation(kDS_Open);
}
SetMass(0.f);
}
rstl::optional_object< CAABox > CScriptDoor::GetTouchBounds() const {
if (GetActive() && GetMaterialList().HasMaterial(kMT_Solid)) {
return CPhysicsActor::GetBoundingBox();
}
return rstl::optional_object_null();
}
rstl::optional_object< CAABox > CScriptDoor::GetProjectileBounds() const {
if (mProjectilesCollide) {
return CAABox(mModelBounds.GetMinPoint() + GetTranslation(),
mModelBounds.GetMaxPoint() + GetTranslation());
}
return rstl::optional_object_null();
}
CVector3f CScriptDoor::GetOrbitPosition(const CStateManager& mgr) const {
return GetTranslation() + mOrbitPos;
}
CScriptDoor::EDoorOpenCondition CScriptDoor::GetDoorOpenCondition(CStateManager& mgr) {
return kDOC_Loading;
}
void CScriptDoor::OpenDoor(TUniqueId uid, CStateManager& mgr) {
mgr.MapWorldInfo()->SetDoorVisited(mgr.GetEditorIdForUniqueId(uid), true);
mIsOpen = true;
mWasOpen = true;
mConditionsMet = false;
mPartner1 = kInvalidUniqueId;
mPartner2 = kInvalidUniqueId;
if (const CScriptDoor* door = TCastToConstPtr< CScriptDoor >(mgr.GetObjectById(uid))) {
mPartner1 = door->GetUniqueId();
}
SetDoorAnimation(kDS_Open);
if (mPartner1 != kInvalidUniqueId) {
SendScriptMsgs(kSS_MaxReached, mgr, kSM_None);
} else {
SendScriptMsgs(kSS_Open, mgr, kSM_None);
}
if (const CScriptDock* dock1 = TCastToConstPtr< CScriptDock >(mgr.GetObjectById(mDockId))) {
CObjectList& list = mgr.ObjectListById(kOL_PlatformAndDoor);
for (int idx = list.GetFirstObjectIndex(); idx != -1; idx = list.GetNextObjectIndex(idx)) {
if (CScriptDoor* door = TCastToPtr< CScriptDoor >(list[idx])) {
if (door->GetUniqueId() == uid) {
continue;
}
if (const CScriptDock* dock2 =
TCastToConstPtr< CScriptDock >(mgr.GetObjectById(door->GetDockID()))) {
if (dock2->GetAreaId() == dock1->GetCurrentConnectedAreaId(mgr) &&
dock2->GetCurrentConnectedAreaId(mgr) == dock1->GetAreaId()) {
mPartner2 = door->GetUniqueId();
mgr.DeliverScriptMsg(door, GetUniqueId(), kSM_Open);
break;
}
}
}
}
}
if (mPartner1 == kInvalidUniqueId && mPartner2 == kInvalidUniqueId) {
rstl::vector< SConnection >::const_iterator it = GetConnectionList().begin();
for (; it != GetConnectionList().end(); ++it) {
if (it->x4_msg != kSM_Open) {
continue;
}
if (const CScriptDoor* door =
TCastToConstPtr< CScriptDoor >(mgr.GetObjectById(mgr.GetIdForScript(it->x8_objId)))) {
mPartner2 = door->GetUniqueId();
break;
}
}
}
}
void CScriptDoor::SetDoorAnimation(EDoorState state) {
mDoorState = state;
if (HasAnimation()) {
AnimationData()->SetAnimation(CAnimPlaybackParms(static_cast< int >(state), -1, 1.f, true),
false);
}
}
void CScriptDoor::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
switch (msg) {
case kSM_Close: {
if (!GetActive()) {
return;
}
if (mPartner1 == kInvalidUniqueId || mPartner1 == uid) {
if (mIsOpen) {
if (mPartner2 != kInvalidUniqueId) {
// lol, this is its actual name
static int i = 0;
if (CEntity* ent = mgr.ObjectById(mPartner2)) {
++i;
mgr.DeliverScriptMsg(ent, GetUniqueId(), kSM_Close);
--i;
}
}
mIsOpen = false;
SetDoorAnimation(kDS_Close);
mgr.GetCameraManager()->BallCamera()->DoorClosing(GetUniqueId());
} else if (mConditionsMet) {
mConditionsMet = false;
SendScriptMsgs(kSS_Closed, mgr, kSM_None);
}
}
break;
}
case kSM_Action: {
if (mPartner1 != kInvalidUniqueId) {
if (CScriptDoor* door = TCastToPtr< CScriptDoor >(mgr.ObjectById(mPartner1))) {
if (door->IsOpen()) {
mDoClose = true;
mgr.DeliverScriptMsg(door, GetUniqueId(), kSM_Close);
door->SetDoClose(true);
}
}
} else if (mIsOpen) {
mDoClose = true;
if (CScriptDoor* door = TCastToPtr< CScriptDoor >(mgr.ObjectById(mPartner2))) {
mgr.DeliverScriptMsg(door, GetUniqueId(), kSM_Close);
door->SetDoClose(true);
}
mIsOpen = false;
SetDoorAnimation(kDS_Close);
mgr.GetCameraManager()->BallCamera()->DoorClosing(GetUniqueId());
}
break;
}
case kSM_Open: {
if (!GetActive()) {
return;
}
if (!mIsOpen) {
const EDoorOpenCondition cond = TCastToConstPtr< CScriptDoor >(mgr.GetObjectById(uid))
? kDOC_Ready
: GetDoorOpenCondition(mgr);
switch (cond) {
case kDOC_Loading:
mConditionsMet = true;
mPrevDoor = uid;
break;
case kDOC_Ready:
OpenDoor(uid, mgr);
break;
case kDOC_NotReady:
default:
mWasOpen = false;
mClosing = true;
break;
}
}
break;
}
case kSM_InitializedInArea: {
rstl::vector< SConnection >::const_iterator it = GetConnectionList().begin();
for (; it != GetConnectionList().end(); ++it) {
if (it->x4_msg != kSM_Increment) {
continue;
}
if (const CScriptDock* dock =
TCastToConstPtr< CScriptDock >(mgr.GetObjectById(mgr.GetIdForScript(it->x8_objId)))) {
mDockId = dock->GetUniqueId();
break;
}
}
break;
}
case kSM_SetToZero:
mProjectilesCollide = true;
mgr.MapWorldInfo()->SetDoorVisited(mgr.GetEditorIdForUniqueId(GetUniqueId()), true);
break;
case kSM_SetToMax:
mProjectilesCollide = false;
break;
default:
CPhysicsActor::AcceptScriptMsg(msg, uid, mgr);
break;
}
}