diff --git a/asm/MetroidPrime/ScriptLoader.s b/asm/MetroidPrime/ScriptLoader.s index dd979a71..e5df7bdc 100644 --- a/asm/MetroidPrime/ScriptLoader.s +++ b/asm/MetroidPrime/ScriptLoader.s @@ -21084,7 +21084,7 @@ lbl_800D84B4: /* 800D84F0 000D5450 38 A1 00 30 */ addi r5, r1, 0x30 /* 800D84F4 000D5454 38 E1 00 40 */ addi r7, r1, 0x40 /* 800D84F8 000D5458 39 01 00 70 */ addi r8, r1, 0x70 -/* 800D84FC 000D545C 48 00 A1 C1 */ bl "__ct__17CScriptSpawnPointF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fQ24rstl21reserved_vectorbbb" +/* 800D84FC 000D545C 48 00 A1 C1 */ bl "__ct__17CScriptSpawnPointF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fRCQ24rstl21reserved_vectorbbb" /* 800D8500 000D5460 7C 7F 1B 78 */ mr r31, r3 lbl_800D8504: /* 800D8504 000D5464 7F 00 07 75 */ extsb. r0, r24 diff --git a/asm/MetroidPrime/ScriptObjects/CScriptSpawnPoint.s b/asm/MetroidPrime/ScriptObjects/CScriptSpawnPoint.s index 4369eb36..b37e6ec5 100644 --- a/asm/MetroidPrime/ScriptObjects/CScriptSpawnPoint.s +++ b/asm/MetroidPrime/ScriptObjects/CScriptSpawnPoint.s @@ -3,8 +3,8 @@ .section .data .balign 8 -.global lbl_803DF850 -lbl_803DF850: +.global __vt__17CScriptSpawnPoint +__vt__17CScriptSpawnPoint: # ROM: 0x3DC850 .4byte 0 .4byte 0 @@ -212,9 +212,9 @@ __dt__17CScriptSpawnPointFv: /* 800E2610 000DF570 93 C1 00 08 */ stw r30, 8(r1) /* 800E2614 000DF574 7C 7E 1B 79 */ or. r30, r3, r3 /* 800E2618 000DF578 41 82 00 88 */ beq lbl_800E26A0 -/* 800E261C 000DF57C 3C 60 80 3E */ lis r3, lbl_803DF850@ha +/* 800E261C 000DF57C 3C 60 80 3E */ lis r3, __vt__17CScriptSpawnPoint@ha /* 800E2620 000DF580 34 1E 00 64 */ addic. r0, r30, 0x64 -/* 800E2624 000DF584 38 03 F8 50 */ addi r0, r3, lbl_803DF850@l +/* 800E2624 000DF584 38 03 F8 50 */ addi r0, r3, __vt__17CScriptSpawnPoint@l /* 800E2628 000DF588 90 1E 00 00 */ stw r0, 0(r30) /* 800E262C 000DF58C 41 82 00 58 */ beq lbl_800E2684 /* 800E2630 000DF590 80 BE 00 64 */ lwz r5, 0x64(r30) @@ -259,8 +259,8 @@ lbl_800E26A0: /* 800E26B4 000DF614 38 21 00 10 */ addi r1, r1, 0x10 /* 800E26B8 000DF618 4E 80 00 20 */ blr -.global "__ct__17CScriptSpawnPointF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fQ24rstl21reserved_vectorbbb" -"__ct__17CScriptSpawnPointF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fQ24rstl21reserved_vectorbbb": +.global "__ct__17CScriptSpawnPointF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fRCQ24rstl21reserved_vectorbbb" +"__ct__17CScriptSpawnPointF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfoRC12CTransform4fRCQ24rstl21reserved_vectorbbb": /* 800E26BC 000DF61C 94 21 FF D0 */ stwu r1, -0x30(r1) /* 800E26C0 000DF620 7C 08 02 A6 */ mflr r0 /* 800E26C4 000DF624 90 01 00 34 */ stw r0, 0x34(r1) @@ -278,9 +278,9 @@ lbl_800E26A0: /* 800E26F4 000DF654 7C 87 23 78 */ mr r7, r4 /* 800E26F8 000DF658 38 81 00 08 */ addi r4, r1, 8 /* 800E26FC 000DF65C 4B F6 EC 29 */ bl "__ct__7CEntityF9TUniqueIdRC11CEntityInfobRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>" -/* 800E2700 000DF660 3C 60 80 3E */ lis r3, lbl_803DF850@ha +/* 800E2700 000DF660 3C 60 80 3E */ lis r3, __vt__17CScriptSpawnPoint@ha /* 800E2704 000DF664 7F 64 DB 78 */ mr r4, r27 -/* 800E2708 000DF668 38 03 F8 50 */ addi r0, r3, lbl_803DF850@l +/* 800E2708 000DF668 38 03 F8 50 */ addi r0, r3, __vt__17CScriptSpawnPoint@l /* 800E270C 000DF66C 38 7F 00 34 */ addi r3, r31, 0x34 /* 800E2710 000DF670 90 1F 00 00 */ stw r0, 0(r31) /* 800E2714 000DF674 48 23 04 61 */ bl __ct__12CTransform4fFRC12CTransform4f diff --git a/include/MetroidPrime/CGameArea.hpp b/include/MetroidPrime/CGameArea.hpp index bde43c39..888f8171 100644 --- a/include/MetroidPrime/CGameArea.hpp +++ b/include/MetroidPrime/CGameArea.hpp @@ -49,6 +49,7 @@ public: bool IsActive() const { return xf0_25_active; } void SetAreaAttributes(const CScriptAreaAttributes* areaAttributes); + bool TryTakingOutOfARAM(); private: enum EPhase { @@ -79,6 +80,22 @@ private: bool xf0_28_validated : 1; EPhase xf4_phase; rstl::list< rstl::rc_ptr< IDvdRequest > > xf8_loadTransactions; + +public: + enum EOcclusionState { kOS_Occluded, kOS_Visible }; + + struct CPostConstructed { + uchar x0_pad[0x10dc]; + EOcclusionState x10dc_occlusionState; + }; + + EOcclusionState GetOcclusionState() const { return x12c_postConstructed->x10dc_occlusionState; } + +private: + uchar x110_pad[0x1c]; + rstl::single_ptr x12c_postConstructed; + + }; #endif // _CGAMEAREA diff --git a/include/MetroidPrime/CStateManager.hpp b/include/MetroidPrime/CStateManager.hpp index 293ea630..06fbc2cf 100644 --- a/include/MetroidPrime/CStateManager.hpp +++ b/include/MetroidPrime/CStateManager.hpp @@ -123,6 +123,7 @@ public: TUniqueId GetIdForScript(TEditorId eid) const; TIdListResult GetIdListForScript(TEditorId) const; + void SetActorAreaId(CActor& actor, TAreaId); TAreaId GetNextAreaId() const { return x8cc_nextAreaId; } void SetCurrentAreaId(TAreaId); diff --git a/include/MetroidPrime/CWorld.hpp b/include/MetroidPrime/CWorld.hpp index a6c4eb41..81f42e61 100644 --- a/include/MetroidPrime/CWorld.hpp +++ b/include/MetroidPrime/CWorld.hpp @@ -7,6 +7,7 @@ #include "MetroidPrime/TGameTypes.hpp" #include "Kyoto/IObjectStore.hpp" +#include "Kyoto/Audio/CSfxHandle.hpp" #include "rstl/string.hpp" @@ -66,6 +67,8 @@ public: CAssetId GetWorldAssetId() const { return x8_mlvlId; } TAreaId GetAreaIdForSaveId(int saveId) const; + static void PropogateAreaChain(CGameArea::EOcclusionState occlusionState, CGameArea* area, CWorld* world); + private: enum Phase { kP_Loading, diff --git a/include/MetroidPrime/Player/CPlayer.hpp b/include/MetroidPrime/Player/CPlayer.hpp index 8efa2247..6d7e755d 100644 --- a/include/MetroidPrime/Player/CPlayer.hpp +++ b/include/MetroidPrime/Player/CPlayer.hpp @@ -184,6 +184,9 @@ public: EGunHolsterState GetGunHolsterState() const { return x498_gunHolsterState; } NPlayer::EPlayerMovementState GetPlayerMovementState() const { return x258_movementState; } + void Teleport(const CTransform4f& xf, CStateManager& mgr, bool resetBallCam); + void SetSpawnedMorphBallState(EPlayerMorphBallState state, CStateManager& mgr); + private: struct CVisorSteam { float x0_curTargetAlpha; diff --git a/include/MetroidPrime/ScriptObjects/CScriptSpawnPoint.hpp b/include/MetroidPrime/ScriptObjects/CScriptSpawnPoint.hpp new file mode 100644 index 00000000..df5f2e28 --- /dev/null +++ b/include/MetroidPrime/ScriptObjects/CScriptSpawnPoint.hpp @@ -0,0 +1,29 @@ +#ifndef _CSCRIPTSPAWNPOINT +#define _CSCRIPTSPAWNPOINT + +#include "MetroidPrime/CEntity.hpp" + +#include "MetroidPrime/Player/CPlayerState.hpp" + +#include "Kyoto/Math/CTransform4f.hpp" + +class CScriptSpawnPoint : public CEntity { + CTransform4f x34_xf; + rstl::reserved_vector< int, int(CPlayerState::kIT_Max) > x64_itemCounts; + bool x10c_24_firstSpawn : 1; + bool x10c_25_morphed : 1; + +public: + CScriptSpawnPoint(TUniqueId, const rstl::string& name, const CEntityInfo& info, + const CTransform4f& xf, + const rstl::reserved_vector< int, int(CPlayerState::kIT_Max) >& itemCounts, + bool, bool, bool); + ~CScriptSpawnPoint(); + + const CTransform4f& GetTransform() const; + int GetPowerup(const CPlayerState::EItemType&) const; + void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); + void Accept(IVisitor&); +}; + +#endif // _CSCRIPTSPAWNPOINT diff --git a/src/MetroidPrime/ScriptObjects/CScriptSpawnPoint.cpp b/src/MetroidPrime/ScriptObjects/CScriptSpawnPoint.cpp new file mode 100644 index 00000000..e48c3840 --- /dev/null +++ b/src/MetroidPrime/ScriptObjects/CScriptSpawnPoint.cpp @@ -0,0 +1,82 @@ +#include "MetroidPrime/ScriptObjects/CScriptSpawnPoint.hpp" + +#include "MetroidPrime/CGameArea.hpp" +#include "MetroidPrime/CStateManager.hpp" +#include "MetroidPrime/CWorld.hpp" +#include "MetroidPrime/Player/CPlayer.hpp" + +CScriptSpawnPoint::CScriptSpawnPoint( + TUniqueId uid, const rstl::string& name, const CEntityInfo& info, const CTransform4f& xf, + const rstl::reserved_vector< int, int(CPlayerState::kIT_Max) >& itemCounts, bool defaultSpawn, + bool active, bool morphed) +: CEntity(uid, info, active, name) +, x34_xf(xf) +, x64_itemCounts(itemCounts) +, x10c_24_firstSpawn(defaultSpawn) +, x10c_25_morphed(morphed) {} + +CScriptSpawnPoint::~CScriptSpawnPoint() {} + +const CTransform4f& CScriptSpawnPoint::GetTransform() const { return x34_xf; } + +int CScriptSpawnPoint::GetPowerup(const CPlayerState::EItemType& type) const { + if (CPlayerState::kIT_Max <= type || type < 0) { + return x64_itemCounts.front(); + } + return x64_itemCounts[type]; +} + +void CScriptSpawnPoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, + CStateManager& stateMgr) { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); + + switch (msg) { + case kSM_Reset: + for (int i = 0; i < CPlayerState::kIT_Max; ++i) { + CPlayerState::EItemType e = CPlayerState::EItemType(i); + stateMgr.PlayerState()->ReInitializePowerUp(CPlayerState::EItemType(i), GetPowerup(e)); + stateMgr.PlayerState()->ResetAndIncrPickUp(CPlayerState::EItemType(i), GetPowerup(e)); + } + + case kSM_SetToZero: + if (GetActive()) { + CPlayer* player = stateMgr.Player(); + TAreaId thisAreaId = x4_areaId; + TAreaId nextAreaId = stateMgr.GetNextAreaId(); + + if (thisAreaId != nextAreaId) { + bool propagateAgain = false; + + CGameArea* area = stateMgr.World()->Area(thisAreaId); + CGameArea::EOcclusionState occlusionState = + area->IsLoaded() ? area->GetOcclusionState() : CGameArea::kOS_Occluded; + + if (occlusionState == CGameArea::kOS_Occluded) { + while (!area->TryTakingOutOfARAM()) { + } + CWorld::PropogateAreaChain(CGameArea::kOS_Visible, area, stateMgr.World()); + propagateAgain = true; + } + + stateMgr.SetCurrentAreaId(thisAreaId); + stateMgr.SetActorAreaId(*player, thisAreaId); + player->Teleport(x34_xf, stateMgr, true); + player->SetSpawnedMorphBallState( + x10c_25_morphed ? CPlayer::kMS_Morphed : CPlayer::kMS_Unmorphed, stateMgr); + + if (propagateAgain) { + CWorld::PropogateAreaChain(CGameArea::kOS_Occluded, stateMgr.World()->Area(nextAreaId), + stateMgr.World()); + } + + } else { + player->Teleport(x34_xf, stateMgr, true); + player->SetSpawnedMorphBallState( + x10c_25_morphed ? CPlayer::kMS_Morphed : CPlayer::kMS_Unmorphed, stateMgr); + } + CEntity::SendScriptMsgs(kSS_Zero, stateMgr, kSM_None); + } + } +} + +void CScriptSpawnPoint::Accept(IVisitor& visitor) { visitor.Visit(*this); }