From 1c430f894db558a6ffc7f6fdec1553cc598f1e42 Mon Sep 17 00:00:00 2001 From: Mikhail Thompson Date: Mon, 10 Jun 2024 14:58:05 +0200 Subject: [PATCH] Begin LegoRace class (#1014) * Begin LegoRace * Match functions --------- Co-authored-by: Christian Semmler --- LEGO1/lego/legoomni/include/carrace.h | 14 +- LEGO1/lego/legoomni/include/jetskirace.h | 12 +- LEGO1/lego/legoomni/include/legorace.h | 67 +++++---- LEGO1/lego/legoomni/include/legoworld.h | 2 +- .../legoomni/src/common/legogamestate.cpp | 2 +- LEGO1/lego/legoomni/src/entity/legoworld.cpp | 8 +- LEGO1/lego/legoomni/src/race/carrace.cpp | 10 +- LEGO1/lego/legoomni/src/race/jetskirace.cpp | 6 +- LEGO1/lego/legoomni/src/race/legorace.cpp | 129 +++++++++++------- 9 files changed, 151 insertions(+), 99 deletions(-) diff --git a/LEGO1/lego/legoomni/include/carrace.h b/LEGO1/lego/legoomni/include/carrace.h index 67332197..30b2cf76 100644 --- a/LEGO1/lego/legoomni/include/carrace.h +++ b/LEGO1/lego/legoomni/include/carrace.h @@ -44,13 +44,13 @@ class CarRace : public LegoRace { return !strcmp(p_name, CarRace::ClassName()) || LegoRace::IsA(p_name); } - MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void ReadyWorld() override; // vtable+0x50 - MxBool Escape() override; // vtable+0x64 - undefined4 VTable0x6c(undefined4) override; // vtable+0x6c - undefined4 VTable0x70(undefined4) override; // vtable+0x70 - undefined4 VTable0x74(undefined4) override; // vtable+0x74 - undefined4 VTable0x78(undefined4) override; // vtable+0x78 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool Escape() override; // vtable+0x64 + MxLong HandleClick(LegoEventNotificationParam&) override; // vtable+0x6c + MxLong HandleType19Notification(MxType19NotificationParam&) override; // vtable+0x70 + MxLong HandleEndAction(MxEndActionNotificationParam&) override; // vtable+0x74 + MxLong HandleType0Notification(MxNotificationParam&) override; // vtable+0x78 // SYNTHETIC: LEGO1 0x10016c70 // CarRace::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/jetskirace.h b/LEGO1/lego/legoomni/include/jetskirace.h index b51496c4..1fe28293 100644 --- a/LEGO1/lego/legoomni/include/jetskirace.h +++ b/LEGO1/lego/legoomni/include/jetskirace.h @@ -48,12 +48,12 @@ class JetskiRace : public LegoRace { return !strcmp(p_name, JetskiRace::ClassName()) || LegoRace::IsA(p_name); } - MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void ReadyWorld() override; // vtable+0x50 - MxBool Escape() override; // vtable+0x64 - undefined4 VTable0x6c(undefined4) override; // vtable+0x6c - undefined4 VTable0x70(undefined4) override; // vtable+0x70 - undefined4 VTable0x74(undefined4) override; // vtable+0x74 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool Escape() override; // vtable+0x64 + MxLong HandleClick(LegoEventNotificationParam&) override; // vtable+0x6c + MxLong HandleType19Notification(MxType19NotificationParam&) override; // vtable+0x70 + MxLong HandleEndAction(MxEndActionNotificationParam&) override; // vtable+0x74 }; // SYNTHETIC: LEGO1 0x1000f530 diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h index 76282d0b..3d41633d 100644 --- a/LEGO1/lego/legoomni/include/legorace.h +++ b/LEGO1/lego/legoomni/include/legorace.h @@ -2,11 +2,19 @@ #define LEGORACE_H #include "decomp.h" +#include "legogamestate.h" #include "legostate.h" #include "legoworld.h" #include "mxrect32.h" #include "mxtypes.h" +class Act1State; +class LegoEventNotificationParam; +class LegoPathActor; +class MxEndActionNotificationParam; +class MxNotificationParam; +class MxType19NotificationParam; + // VTABLE: LEGO1 0x100d5e30 // SIZE 0x2c class RaceState : public LegoState { @@ -86,39 +94,42 @@ class LegoRace : public LegoWorld { } MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - MxBool VTable0x5c() override; // vtable+0x5c - MxBool Escape() override; // vtable+0x64 - void Enable(MxBool p_enable) override; // vtable+0x68 - virtual undefined4 VTable0x6c(undefined4) = 0; // vtable+0x6c - virtual undefined4 VTable0x70(undefined4); // vtable+0x70 - virtual undefined4 VTable0x74(undefined4); // vtable+0x74 - virtual undefined4 VTable0x78(undefined4); // vtable+0x78 - virtual void VTable0x7c(undefined4, undefined4); // vtable+0x7c + + // FUNCTION: LEGO1 0x1000dae0 + MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c + + MxBool Escape() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + virtual MxLong HandleClick(LegoEventNotificationParam&) = 0; // vtable+0x6c + virtual MxLong HandleType19Notification(MxType19NotificationParam&); // vtable+0x70 + virtual MxLong HandleEndAction(MxEndActionNotificationParam&); // vtable+0x74 + + // FUNCTION: LEGO1 0x1000dab0 + virtual MxLong HandleType0Notification(MxNotificationParam&) { return 0; } // vtable+0x78 + + // STUB: LEGO1 0x1000dac0 + virtual void VTable0x7c(undefined4, undefined4) {} // vtable+0x7c // SYNTHETIC: LEGO1 0x10015cc0 // LegoRace::`scalar deleting destructor' -private: - undefined4 m_unk0xf8; // 0xf8 - undefined4 m_unk0xfc; // 0xfc - undefined4 m_unk0x100; // 0x100 - undefined4 m_unk0x104; // 0x104 - undefined4 m_unk0x108; // 0x108 - undefined4 m_unk0x10c; // 0x10c - undefined4 m_unk0x110; // 0x110 - undefined4 m_unk0x114; // 0x114 - undefined4 m_unk0x118; // 0x118 - undefined4 m_unk0x11c; // 0x11c - undefined4 m_unk0x120; // 0x120 - undefined4 m_unk0x124; // 0x124 - undefined4 m_unk0x128; // 0x128 - undefined4 m_unk0x12c; // 0x12c - protected: - MxRect32 m_unk0x130; // 0x130 - -private: - undefined4 m_unk0x140; // 0x140 + undefined4 m_unk0xf8; // 0xf8 + undefined4 m_unk0xfc; // 0xfc + undefined4 m_unk0x100; // 0x100 + undefined4 m_unk0x104; // 0x104 + undefined4 m_unk0x108; // 0x108 + undefined4 m_unk0x10c; // 0x10c + undefined4 m_unk0x110; // 0x110 + undefined4 m_unk0x114; // 0x114 + undefined4 m_unk0x118; // 0x118 + LegoGameState::Area m_destLocation; // 0x11c + LegoPathActor* m_pathActor; // 0x120 + Act1State* m_act1State; // 0x124 + undefined4 m_unk0x128; // 0x128 + undefined4 m_unk0x12c; // 0x12c + MxRect32 m_unk0x130; // 0x130 + undefined4 m_unk0x140; // 0x140 }; #endif // LEGORACE_H diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index 766d5ca5..f1de12c9 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -91,7 +91,7 @@ class LegoWorld : public LegoEntity { inline LegoCameraController* GetCamera() { return m_cameraController; } inline LegoEntityList* GetEntityList() { return m_entityList; } inline MxS32 GetScriptIndex() { return m_scriptIndex; } - inline MxCoreSet& GetUnknown0xd0() { return m_set0xd0; } + inline MxBool GetUnknown0xd0Empty() { return m_set0xd0.empty(); } inline list& GetROIList() { return m_roiList; } inline LegoHideAnimPresenter* GetHideAnimPresenter() { return m_hideAnimPresenter; } diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index b7882a3c..5e1fcdeb 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -780,7 +780,7 @@ inline void LoadIsle() { LegoWorld* world = FindWorld(*g_isleScript, 0); if (world != NULL) { - if (!world->GetUnknown0xd0().empty()) { + if (!world->GetUnknown0xd0Empty()) { NotificationManager()->Send(world, MxNotificationParam(c_notificationType20, NULL)); } } diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index e2d54b72..d19a854a 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -225,19 +225,21 @@ void LegoWorld::Destroy(MxBool p_fromDestructor) // FUNCTION: LEGO1 0x1001f5e0 MxLong LegoWorld::Notify(MxParam& p_param) { - MxLong ret = 0; + MxLong result = 0; + switch (((MxNotificationParam&) p_param).GetNotification()) { case c_notificationEndAction: { MxPresenter* presenter = (MxPresenter*) ((MxEndActionNotificationParam&) p_param).GetSender(); Remove(presenter); - ret = 1; + result = 1; break; } case c_notificationNewPresenter: TickleManager()->RegisterClient(this, 100); break; } - return ret; + + return result; } // FUNCTION: LEGO1 0x1001f630 diff --git a/LEGO1/lego/legoomni/src/race/carrace.cpp b/LEGO1/lego/legoomni/src/race/carrace.cpp index 418a74c5..5140250e 100644 --- a/LEGO1/lego/legoomni/src/race/carrace.cpp +++ b/LEGO1/lego/legoomni/src/race/carrace.cpp @@ -1,5 +1,7 @@ #include "carrace.h" +#include "mxactionnotificationparam.h" + DECOMP_SIZE_ASSERT(CarRace, 0x154) // FUNCTION: LEGO1 0x10016a90 @@ -23,28 +25,28 @@ void CarRace::ReadyWorld() } // STUB: LEGO1 0x10016f60 -undefined4 CarRace::VTable0x74(undefined4) +MxLong CarRace::HandleEndAction(MxEndActionNotificationParam&) { // TODO return 0; } // STUB: LEGO1 0x100170e0 -undefined4 CarRace::VTable0x70(undefined4) +MxLong CarRace::HandleType19Notification(MxType19NotificationParam&) { // TODO return 0; } // STUB: LEGO1 0x10017650 -undefined4 CarRace::VTable0x6c(undefined4) +MxLong CarRace::HandleClick(LegoEventNotificationParam&) { // TODO return 0; } // STUB: LEGO1 0x100177e0 -undefined4 CarRace::VTable0x78(undefined4) +MxLong CarRace::HandleType0Notification(MxNotificationParam&) { // TODO return 0; diff --git a/LEGO1/lego/legoomni/src/race/jetskirace.cpp b/LEGO1/lego/legoomni/src/race/jetskirace.cpp index 37fc198d..eeaed23a 100644 --- a/LEGO1/lego/legoomni/src/race/jetskirace.cpp +++ b/LEGO1/lego/legoomni/src/race/jetskirace.cpp @@ -14,19 +14,19 @@ void JetskiRace::ReadyWorld() } // STUB: LEGO1 0x10016520 -undefined4 JetskiRace::VTable0x74(undefined4) +MxLong JetskiRace::HandleEndAction(MxEndActionNotificationParam&) { return 0; } // STUB: LEGO1 0x100165a0 -undefined4 JetskiRace::VTable0x6c(undefined4) +MxLong JetskiRace::HandleClick(LegoEventNotificationParam&) { return 0; } // STUB: LEGO1 0x100166a0 -undefined4 JetskiRace::VTable0x70(undefined4) +MxLong JetskiRace::HandleType19Notification(MxType19NotificationParam&) { return 0; } diff --git a/LEGO1/lego/legoomni/src/race/legorace.cpp b/LEGO1/lego/legoomni/src/race/legorace.cpp index a2204345..7430f922 100644 --- a/LEGO1/lego/legoomni/src/race/legorace.cpp +++ b/LEGO1/lego/legoomni/src/race/legorace.cpp @@ -1,60 +1,48 @@ #include "legorace.h" +#include "isle.h" +#include "legocontrolmanager.h" +#include "legonavcontroller.h" +#include "misc.h" #include "mxmisc.h" #include "mxnotificationmanager.h" DECOMP_SIZE_ASSERT(LegoRace, 0x144) DECOMP_SIZE_ASSERT(RaceState::Entry, 0x06) -// TODO: Must be 0x2c but current structure is incorrect -// DECOMP_SIZE_ASSERT(RaceState, 0x2c) +DECOMP_SIZE_ASSERT(RaceState, 0x2c) -// FUNCTION: LEGO1 0x1000dab0 -undefined4 LegoRace::VTable0x78(undefined4) -{ - return 0; -} - -// STUB: LEGO1 0x1000dac0 -void LegoRace::VTable0x7c(undefined4, undefined4) -{ - // TODO -} - -// FUNCTION: LEGO1 0x1000dae0 -MxBool LegoRace::VTable0x5c() -{ - return TRUE; -} +// Defined in legopathstruct.cpp +extern MxBool g_unk0x100f119c; // FUNCTION: LEGO1 0x10015aa0 LegoRace::LegoRace() { - this->m_unk0xf8 = 0; - this->m_unk0xfc = 0; - this->m_unk0x100 = 0; - this->m_unk0x104 = 0; - this->m_unk0x108 = 0; - this->m_unk0x10c = 0; - this->m_unk0x140 = 0; - this->m_unk0x110 = 0; - this->m_unk0x114 = 0; - this->m_unk0x118 = 0; - this->m_unk0x128 = 0; - this->m_unk0x12c = 0; - this->m_unk0x120 = 0; - this->m_unk0x124 = 0; - this->m_unk0x11c = 0; + m_unk0xf8 = 0; + m_unk0xfc = 0; + m_unk0x100 = 0; + m_unk0x104 = 0; + m_unk0x108 = 0; + m_unk0x10c = 0; + m_unk0x140 = 0; + m_unk0x110 = 0; + m_unk0x114 = 0; + m_unk0x118 = 0; + m_unk0x128 = 0; + m_unk0x12c = 0; + m_pathActor = 0; + m_act1State = NULL; + m_destLocation = LegoGameState::e_undefined; NotificationManager()->Register(this); } // FUNCTION: LEGO1 0x10015b70 -undefined4 LegoRace::VTable0x70(undefined4) +MxLong LegoRace::HandleType19Notification(MxType19NotificationParam&) { return 0; } // FUNCTION: LEGO1 0x10015b80 -undefined4 LegoRace::VTable0x74(undefined4) +MxLong LegoRace::HandleEndAction(MxEndActionNotificationParam&) { return 0; } @@ -65,30 +53,79 @@ MxBool LegoRace::Escape() return FALSE; } -// STUB: LEGO1 0x10015ce0 +// FUNCTION: LEGO1 0x10015ce0 MxResult LegoRace::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + MxResult result = LegoWorld::Create(p_dsAction); + + if (result == SUCCESS) { + m_act1State = (Act1State*) GameState()->GetState("Act1State"); + ControlManager()->Register(this); + m_pathActor = CurrentActor(); + m_pathActor->SetWorldSpeed(0); + SetCurrentActor(NULL); + } + + return result; } -// STUB: LEGO1 0x10015d40 +// FUNCTION: LEGO1 0x10015d40 LegoRace::~LegoRace() { - // TODO + g_unk0x100f119c = FALSE; + if (m_pathActor) { + SetCurrentActor(m_pathActor); + NavController()->ResetMaxLinearVel(m_pathActor->GetMaxLinearVel()); + m_pathActor = NULL; + } + + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x10015e00 +// FUNCTION: LEGO1 0x10015e00 +// FUNCTION: BETA10 0x100c7b3d MxLong LegoRace::Notify(MxParam& p_param) { - // TODO - return 0; + LegoWorld::Notify(p_param); + + MxLong result = 0; + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetNotification()) { + case c_notificationType0: + HandleType0Notification((MxNotificationParam&) p_param); + break; + case c_notificationEndAction: + result = HandleEndAction((MxEndActionNotificationParam&) p_param); + break; + case c_notificationClick: + result = HandleClick((LegoEventNotificationParam&) p_param); + break; + case c_notificationType19: + result = HandleType19Notification((MxType19NotificationParam&) p_param); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(m_destLocation); + break; + } + } + + return result; } -// STUB: LEGO1 0x10015ed0 +// FUNCTION: LEGO1 0x10015ed0 +// FUNCTION: BETA10 0x100c7c3f void LegoRace::Enable(MxBool p_enable) { - // TODO + if (GetUnknown0xd0Empty() != p_enable && !p_enable) { + Remove(CurrentActor()); + + MxU8 oldActorId = GameState()->GetActorId(); + GameState()->RemoveActor(); + GameState()->SetActorId(oldActorId); + } + + LegoWorld::Enable(p_enable); } // STUB: LEGO1 0x10015f30