diff --git a/asm/MetroidPrime/ScriptLoader.s b/asm/MetroidPrime/ScriptLoader.s index e53da06a..fc6608f3 100644 --- a/asm/MetroidPrime/ScriptLoader.s +++ b/asm/MetroidPrime/ScriptLoader.s @@ -16902,7 +16902,7 @@ lbl_800D4710: /* 800D475C 000D16BC B0 01 00 0C */ sth r0, 0xc(r1) /* 800D4760 000D16C0 38 81 00 0C */ addi r4, r1, 0xc /* 800D4764 000D16C4 38 A1 00 10 */ addi r5, r1, 0x10 -/* 800D4768 000D16C8 48 00 DB A9 */ bl "__ct__12CScriptRelayF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfofb" +/* 800D4768 000D16C8 48 00 DB A9 */ bl "__ct__12CScriptRelayF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfob" /* 800D476C 000D16CC 7C 7F 1B 78 */ mr r31, r3 lbl_800D4770: /* 800D4770 000D16D0 38 61 00 10 */ addi r3, r1, 0x10 diff --git a/asm/MetroidPrime/ScriptObjects/CScriptRelay.s b/asm/MetroidPrime/ScriptObjects/CScriptRelay.s index ea93ffcd..5f9dcd4c 100644 --- a/asm/MetroidPrime/ScriptObjects/CScriptRelay.s +++ b/asm/MetroidPrime/ScriptObjects/CScriptRelay.s @@ -3,8 +3,8 @@ .section .data .balign 8 -.global lbl_803DF830 -lbl_803DF830: +.global __vt__12CScriptRelay +__vt__12CScriptRelay: # ROM: 0x3DC830 .4byte 0 .4byte 0 @@ -27,9 +27,9 @@ __dt__12CScriptRelayFv: /* 800E207C 000DEFDC 93 C1 00 08 */ stw r30, 8(r1) /* 800E2080 000DEFE0 7C 7E 1B 79 */ or. r30, r3, r3 /* 800E2084 000DEFE4 41 82 00 28 */ beq lbl_800E20AC -/* 800E2088 000DEFE8 3C A0 80 3E */ lis r5, lbl_803DF830@ha +/* 800E2088 000DEFE8 3C A0 80 3E */ lis r5, __vt__12CScriptRelay@ha /* 800E208C 000DEFEC 38 80 00 00 */ li r4, 0 -/* 800E2090 000DEFF0 38 05 F8 30 */ addi r0, r5, lbl_803DF830@l +/* 800E2090 000DEFF0 38 05 F8 30 */ addi r0, r5, __vt__12CScriptRelay@l /* 800E2094 000DEFF4 90 1E 00 00 */ stw r0, 0(r30) /* 800E2098 000DEFF8 4B F6 F1 DD */ bl __dt__7CEntityFv /* 800E209C 000DEFFC 7F E0 07 35 */ extsh. r0, r31 @@ -217,8 +217,8 @@ lbl_800E22F8: /* 800E2308 000DF268 38 21 00 20 */ addi r1, r1, 0x20 /* 800E230C 000DF26C 4E 80 00 20 */ blr -.global "__ct__12CScriptRelayF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfofb" -"__ct__12CScriptRelayF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfofb": +.global "__ct__12CScriptRelayF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfob" +"__ct__12CScriptRelayF9TUniqueIdRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>RC11CEntityInfob": /* 800E2310 000DF270 94 21 FF E0 */ stwu r1, -0x20(r1) /* 800E2314 000DF274 7C 08 02 A6 */ mflr r0 /* 800E2318 000DF278 90 01 00 24 */ stw r0, 0x24(r1) @@ -232,9 +232,9 @@ lbl_800E22F8: /* 800E2338 000DF298 7C 87 23 78 */ mr r7, r4 /* 800E233C 000DF29C 38 81 00 08 */ addi r4, r1, 8 /* 800E2340 000DF2A0 4B F6 EF E5 */ bl "__ct__7CEntityF9TUniqueIdRC11CEntityInfobRCQ24rstl66basic_string,Q24rstl17rmemory_allocator>" -/* 800E2344 000DF2A4 3C 60 80 3E */ lis r3, lbl_803DF830@ha +/* 800E2344 000DF2A4 3C 60 80 3E */ lis r3, __vt__12CScriptRelay@ha /* 800E2348 000DF2A8 38 00 00 00 */ li r0, 0 -/* 800E234C 000DF2AC 38 83 F8 30 */ addi r4, r3, lbl_803DF830@l +/* 800E234C 000DF2AC 38 83 F8 30 */ addi r4, r3, __vt__12CScriptRelay@l /* 800E2350 000DF2B0 7F E3 FB 78 */ mr r3, r31 /* 800E2354 000DF2B4 90 9F 00 00 */ stw r4, 0(r31) /* 800E2358 000DF2B8 A0 8D A3 8C */ lhz r4, kInvalidUniqueId@sda21(r13) diff --git a/configure.py b/configure.py index f4832029..964be856 100755 --- a/configure.py +++ b/configure.py @@ -132,7 +132,7 @@ LIBS = [ "MetroidPrime/Weapons/CWaveBeam", "MetroidPrime/Weapons/CIceBeam", "MetroidPrime/CScriptMailbox", - "MetroidPrime/ScriptObjects/CScriptRelay", + ["MetroidPrime/ScriptObjects/CScriptRelay", True], "MetroidPrime/ScriptObjects/CScriptSpawnPoint", "MetroidPrime/ScriptObjects/CScriptRandomRelay", "MetroidPrime/Enemies/CBeetle", diff --git a/include/MetroidPrime/CStateManager.hpp b/include/MetroidPrime/CStateManager.hpp index aa45b0bc..c32c08bb 100644 --- a/include/MetroidPrime/CStateManager.hpp +++ b/include/MetroidPrime/CStateManager.hpp @@ -192,6 +192,10 @@ public: return xf90_deferredTransition == kSMT_MessageScreen; } + void SetLastRelayId(const TUniqueId& uid) { xf76_lastRelay = uid; } + TUniqueId* GetLastRelayIdPtr() { return &xf76_lastRelay; } + TUniqueId GetLastRelayId() const { return xf76_lastRelay; } + void SetEnergyBarActorInfo(TUniqueId bossId, float maxEnergy, uint stringIdx); void SetPendingOnScreenTex(CAssetId texId, const CVector2i& origin, const CVector2i& extent); /* { xef4_pendingScreenTex.x0_id = texId; diff --git a/include/MetroidPrime/ScriptObjects/CScriptRelay.hpp b/include/MetroidPrime/ScriptObjects/CScriptRelay.hpp index 283782e1..1ae3f78c 100644 --- a/include/MetroidPrime/ScriptObjects/CScriptRelay.hpp +++ b/include/MetroidPrime/ScriptObjects/CScriptRelay.hpp @@ -4,7 +4,18 @@ #include "MetroidPrime/CEntity.hpp" class CScriptRelay : public CEntity { + TUniqueId x34_nextRelay; + int x38_sendCount; + public: + CScriptRelay(TUniqueId, const rstl::string&, const CEntityInfo&, bool); + + void UpdateObjectRef(CStateManager& stateMgr); + void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr) override; + void Think(float, CStateManager& stateMgr) override; + void Accept(IVisitor& visitor) override; + + ~CScriptRelay(); }; #endif // _CSCRIPTRELAY diff --git a/include/MetroidPrime/TGameTypes.hpp b/include/MetroidPrime/TGameTypes.hpp index 0fd3805f..8ed8c521 100644 --- a/include/MetroidPrime/TGameTypes.hpp +++ b/include/MetroidPrime/TGameTypes.hpp @@ -47,6 +47,7 @@ struct TUniqueId { ushort value; TUniqueId(ushort version, ushort id) : value(((version & 0x3F) << 10) | (id & 0x3FF)) {} + ushort Value() const { return value & 0x3FF; } ushort Version() const { return (value >> 10) & 0x3F; } diff --git a/obj_files.mk b/obj_files.mk index f950561b..0859bea9 100644 --- a/obj_files.mk +++ b/obj_files.mk @@ -99,7 +99,7 @@ METROIDPRIME :=\ $(BUILD_DIR)/asm/MetroidPrime/Weapons/CWaveBeam.o\ $(BUILD_DIR)/asm/MetroidPrime/Weapons/CIceBeam.o\ $(BUILD_DIR)/asm/MetroidPrime/CScriptMailbox.o\ - $(BUILD_DIR)/asm/MetroidPrime/ScriptObjects/CScriptRelay.o\ + $(BUILD_DIR)/src/MetroidPrime/ScriptObjects/CScriptRelay.o\ $(BUILD_DIR)/asm/MetroidPrime/ScriptObjects/CScriptSpawnPoint.o\ $(BUILD_DIR)/asm/MetroidPrime/ScriptObjects/CScriptRandomRelay.o\ $(BUILD_DIR)/asm/MetroidPrime/Enemies/CBeetle.o\ diff --git a/src/MetroidPrime/ScriptObjects/CScriptRelay.cpp b/src/MetroidPrime/ScriptObjects/CScriptRelay.cpp new file mode 100644 index 00000000..c077b824 --- /dev/null +++ b/src/MetroidPrime/ScriptObjects/CScriptRelay.cpp @@ -0,0 +1,71 @@ +#include "MetroidPrime/ScriptObjects/CScriptRelay.hpp" + +CScriptRelay::CScriptRelay(TUniqueId uid, const rstl::string& name, const CEntityInfo& info, + bool active) +: CEntity(uid, info, active, name), x34_nextRelay(kInvalidUniqueId), x38_sendCount(0) {} + +void CScriptRelay::UpdateObjectRef(CStateManager& stateMgr) { + TUniqueId* tmp = stateMgr.GetLastRelayIdPtr(); + while (tmp != nullptr && *tmp != kInvalidUniqueId) { + if (*tmp == GetUniqueId()) { + *tmp = x34_nextRelay; + return; + } + CScriptRelay* obj = static_cast(stateMgr.ObjectById(*tmp)); + if (obj == nullptr) { + return; + } + tmp = &obj->x34_nextRelay; + } +} + +void CScriptRelay::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, + CStateManager& stateMgr) override { + CEntity::AcceptScriptMsg(msg, objId, stateMgr); + + switch (msg) { + case kSM_SetToZero: + if (!x30_24_active) { + return; + } + + x38_sendCount++; + TUniqueId tmp = stateMgr.GetLastRelayId(); + while (tmp != GetUniqueId() && tmp != kInvalidUniqueId) { + CEntity* obj = stateMgr.ObjectById(tmp); + if (!obj) { + tmp = kInvalidUniqueId; + break; + } + + tmp = static_cast< const CScriptRelay* >(obj)->x34_nextRelay; + } + + if (tmp == kInvalidUniqueId) { + x34_nextRelay = stateMgr.GetLastRelayId(); + stateMgr.SetLastRelayId(GetUniqueId()); + } + break; + + case kSM_Deleted: + UpdateObjectRef(stateMgr); + break; + } +} + +void CScriptRelay::Think(float, CStateManager& stateMgr) override { + switch (x38_sendCount) { + default: + while (x38_sendCount != 0) { + x38_sendCount--; + SendScriptMsgs(kSS_Zero, stateMgr, kSM_None); + } + UpdateObjectRef(stateMgr); + case 0: + return; + } +} + +void CScriptRelay::Accept(IVisitor& visitor) override { visitor.Visit(*this); } + +CScriptRelay::~CScriptRelay() {}