From 2b9d8f1fba2f55bd30f9a8a17385b5357c3ce380 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sat, 26 Oct 2024 09:34:43 -0700 Subject: [PATCH 01/17] Implement/match Pizza::FUN_100382b0 and Pizza::StopActions (#1118) --- LEGO1/lego/legoomni/include/pizza.h | 47 +++++++-------- LEGO1/lego/legoomni/include/skateboard.h | 3 +- LEGO1/lego/legoomni/src/actors/pizza.cpp | 57 +++++++++++++++---- LEGO1/lego/legoomni/src/actors/skateboard.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/isle.cpp | 4 +- 5 files changed, 74 insertions(+), 39 deletions(-) diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index e8bd71c9..45cfe968 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -1,6 +1,7 @@ #ifndef PIZZA_H #define PIZZA_H +#include "actionsfwd.h" #include "decomp.h" #include "isleactor.h" #include "legostate.h" @@ -13,7 +14,7 @@ class SkateBoard; class PizzaMissionState : public LegoState { public: // SIZE 0x20 - struct Entry { + struct Mission { public: MxResult WriteToFile(LegoFile* p_file) { @@ -33,16 +34,16 @@ class PizzaMissionState : public LegoState { return SUCCESS; } - undefined2 m_unk0x00; // 0x00 - MxU8 m_id; // 0x02 - undefined m_unk0x03[3]; // 0x03 - MxS16 m_unk0x06; // 0x06 - undefined m_unk0x08[8]; // 0x08 - undefined4 m_unk0x10; // 0x10 - MxS16 m_unk0x14; // 0x14 - MxS16 m_unk0x16; // 0x16 - MxS16 m_score; // 0x18 - undefined m_unk0x1a[6]; // 0x1a + MxS16 m_numActions; // 0x00 + MxU8 m_id; // 0x02 + undefined m_unk0x03[3]; // 0x03 + MxS16 m_unk0x06; // 0x06 + undefined m_unk0x08[8]; // 0x08 + MxLong m_startTime; // 0x10 + MxS16 m_unk0x14; // 0x14 + MxS16 m_unk0x16; // 0x16 + MxS16 m_score; // 0x18 + IsleScript::Script* m_actions; // 0x1c }; PizzaMissionState(); @@ -67,11 +68,11 @@ class PizzaMissionState : public LegoState { // SYNTHETIC: LEGO1 0x10039350 // PizzaMissionState::`scalar deleting destructor' - Entry* GetState(MxU8 p_id); + Mission* GetState(MxU8 p_id); undefined4 m_unk0x08; // 0x08 undefined4 m_unk0x0c; // 0x0c - Entry m_state[5]; // 0x10 + Mission m_state[5]; // 0x10 undefined4 m_unk0xb0; // 0xb0 }; @@ -105,23 +106,23 @@ class Pizza : public IsleActor { void CreateState(); void FUN_10038220(MxU32 p_objectId); void FUN_100382b0(); - void FUN_10038380(); + void StopActions(); void FUN_10038fe0(MxU32 p_objectId, MxBool); - void SetSkateboard(SkateBoard* p_skateboard) { m_skateboard = p_skateboard; } + void SetSkateboard(SkateBoard* p_skateBoard) { m_skateBoard = p_skateBoard; } // SYNTHETIC: LEGO1 0x100380e0 // Pizza::`scalar deleting destructor' private: - PizzaMissionState* m_state; // 0x7c - PizzaMissionState::Entry* m_entry; // 0x80 - SkateBoard* m_skateboard; // 0x84 - Act1State* m_act1state; // 0x88 - undefined4 m_unk0x8c; // 0x8c - undefined4 m_unk0x90; // 0x90 - undefined4 m_unk0x94; // 0x94 - undefined m_unk0x98; // 0x98 + PizzaMissionState* m_state; // 0x7c + PizzaMissionState::Mission* m_mission; // 0x80 + SkateBoard* m_skateBoard; // 0x84 + Act1State* m_act1state; // 0x88 + undefined4 m_unk0x8c; // 0x8c + undefined4 m_unk0x90; // 0x90 + undefined4 m_unk0x94; // 0x94 + undefined m_unk0x98; // 0x98 }; #endif // PIZZA_H diff --git a/LEGO1/lego/legoomni/include/skateboard.h b/LEGO1/lego/legoomni/include/skateboard.h index a85ed26e..0bf691c1 100644 --- a/LEGO1/lego/legoomni/include/skateboard.h +++ b/LEGO1/lego/legoomni/include/skateboard.h @@ -35,13 +35,12 @@ class SkateBoard : public IslePathActor { void SetUnknown0x160(MxBool p_unk0x160) { m_unk0x160 = p_unk0x160; } void ActivateSceneActions(); + void EnableScenePresentation(MxBool p_enable); // SYNTHETIC: LEGO1 0x1000ff60 // SkateBoard::`scalar deleting destructor' private: - void EnableScenePresentation(MxBool p_enable); - MxBool m_unk0x160; // 0x160 Act1State* m_act1state; // 0x164 }; diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index 593d7f74..ac47ea53 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -4,14 +4,17 @@ #include "isle_actions.h" #include "legoanimationmanager.h" #include "legogamestate.h" +#include "legoutils.h" #include "legoworld.h" #include "misc.h" +#include "mxbackgroundaudiomanager.h" #include "mxmisc.h" #include "mxticklemanager.h" +#include "skateboard.h" DECOMP_SIZE_ASSERT(Pizza, 0x9c) DECOMP_SIZE_ASSERT(PizzaMissionState, 0xb4) -DECOMP_SIZE_ASSERT(PizzaMissionState::Entry, 0x20) +DECOMP_SIZE_ASSERT(PizzaMissionState::Mission, 0x20) // Flags used in isle.cpp extern MxU32 g_isleFlags; @@ -20,12 +23,12 @@ extern MxU32 g_isleFlags; Pizza::Pizza() { m_state = NULL; - m_entry = NULL; - m_skateboard = NULL; + m_mission = NULL; + m_skateBoard = NULL; m_act1state = NULL; m_unk0x8c = -1; m_unk0x98 = 0; - m_unk0x90 = 0x80000000; + m_unk0x90 = INT_MIN; } // FUNCTION: LEGO1 0x10038100 @@ -41,13 +44,14 @@ MxResult Pizza::Create(MxDSAction& p_dsAction) if (result == SUCCESS) { CreateState(); - m_skateboard = (SkateBoard*) m_world->Find(m_atomId, IsleScript::c_SkateBoard_Actor); + m_skateBoard = (SkateBoard*) m_world->Find(m_atomId, IsleScript::c_SkateBoard_Actor); } return result; } // FUNCTION: LEGO1 0x100381b0 +// FUNCTION: BETA10 0x100edaec void Pizza::CreateState() { m_state = (PizzaMissionState*) GameState()->GetState("PizzaMissionState"); @@ -62,13 +66,14 @@ void Pizza::CreateState() } // FUNCTION: LEGO1 0x10038220 +// FUNCTION: BETA10 0x100edb81 void Pizza::FUN_10038220(MxU32 p_objectId) { AnimationManager()->FUN_10064740(NULL); - m_entry = m_state->GetState(GameState()->GetActorId()); + m_mission = m_state->GetState(GameState()->GetActorId()); m_state->m_unk0x0c = 1; m_act1state->m_unk0x018 = 3; - m_entry->m_unk0x10 = 0x80000000; + m_mission->m_startTime = INT_MIN; g_isleFlags &= ~Isle::c_playMusic; AnimationManager()->EnableCamAnims(FALSE); AnimationManager()->FUN_1005f6d0(FALSE); @@ -76,14 +81,44 @@ void Pizza::FUN_10038220(MxU32 p_objectId) m_unk0x8c = -1; } -// STUB: LEGO1 0x100382b0 +// FUNCTION: LEGO1 0x100382b0 void Pizza::FUN_100382b0() { + if (m_state->m_unk0x0c != 8) { + if (m_unk0x8c != -1) { + InvokeAction(Extra::e_stop, *g_isleScript, m_unk0x8c, NULL); + } + + m_act1state->m_unk0x018 = 0; + m_state->m_unk0x0c = 0; + UserActor()->SetState(0); + g_isleFlags |= Isle::c_playMusic; + AnimationManager()->EnableCamAnims(TRUE); + AnimationManager()->FUN_1005f6d0(TRUE); + m_mission->m_startTime = INT_MIN; + m_mission = NULL; + m_unk0x98 = 0; + m_unk0x8c = -1; + BackgroundAudioManager()->RaiseVolume(); + TickleManager()->UnregisterClient(this); + m_unk0x90 = INT_MIN; + m_skateBoard->EnableScenePresentation(FALSE); + m_skateBoard->SetUnknown0x160(FALSE); + } } -// STUB: LEGO1 0x10038380 -void Pizza::FUN_10038380() +// FUNCTION: LEGO1 0x10038380 +void Pizza::StopActions() { + InvokeAction(Extra::e_stop, *g_isleScript, IsleScript::c_pns050p1_RunAnim, NULL); + InvokeAction(Extra::e_stop, *g_isleScript, IsleScript::c_wns050p1_RunAnim, NULL); + + PizzaMissionState::Mission* mission = m_mission; + if (mission != NULL) { + for (MxS32 i = 0; i < mission->m_numActions; i++) { + InvokeAction(Extra::e_stop, *g_isleScript, mission->m_actions[i], NULL); + } + } } // STUB: LEGO1 0x100383f0 @@ -146,7 +181,7 @@ MxResult PizzaMissionState::Serialize(LegoFile* p_file) } // FUNCTION: LEGO1 0x10039510 -PizzaMissionState::Entry* PizzaMissionState::GetState(MxU8 p_id) +PizzaMissionState::Mission* PizzaMissionState::GetState(MxU8 p_id) { for (MxS16 i = 0; i < 5; i++) { if (m_state[i].m_id == p_id) { diff --git a/LEGO1/lego/legoomni/src/actors/skateboard.cpp b/LEGO1/lego/legoomni/src/actors/skateboard.cpp index b2d00f94..cc577c30 100644 --- a/LEGO1/lego/legoomni/src/actors/skateboard.cpp +++ b/LEGO1/lego/legoomni/src/actors/skateboard.cpp @@ -58,7 +58,7 @@ void SkateBoard::Exit() { if (m_act1state->m_unk0x018 == 3) { Pizza* pizza = (Pizza*) CurrentWorld()->Find(*g_isleScript, IsleScript::c_Pizza_Actor); - pizza->FUN_10038380(); + pizza->StopActions(); pizza->FUN_100382b0(); m_unk0x160 = FALSE; } diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index 13ea3cbf..fd739d87 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -1190,7 +1190,7 @@ MxBool Isle::Escape() switch (m_act1state->m_unk0x018) { case 3: if (UserActor() != NULL) { - m_pizza->FUN_10038380(); + m_pizza->StopActions(); m_pizza->FUN_100382b0(); } break; @@ -1257,7 +1257,7 @@ void Isle::FUN_10033350() if (m_act1state->m_unk0x018 == 3) { if (UserActor() != NULL) { - m_pizza->FUN_10038380(); + m_pizza->StopActions(); m_pizza->FUN_100382b0(); } } From b3ce98a2ec9215d7f2cd2e6681afa0d889a9b726 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sat, 26 Oct 2024 10:34:16 -0700 Subject: [PATCH 02/17] Implement/match Pizza::HandleClick (#1119) --- LEGO1/lego/legoomni/include/pizza.h | 10 +++-- LEGO1/lego/legoomni/include/pizzeria.h | 1 + LEGO1/lego/legoomni/src/actors/pizza.cpp | 45 ++++++++++++++++++++- LEGO1/lego/legoomni/src/actors/pizzeria.cpp | 6 +++ 4 files changed, 56 insertions(+), 6 deletions(-) diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index 45cfe968..0f9a9503 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -7,6 +7,7 @@ #include "legostate.h" class Act1State; +class PizzeriaState; class SkateBoard; // VTABLE: LEGO1 0x100d7408 @@ -69,11 +70,12 @@ class PizzaMissionState : public LegoState { // PizzaMissionState::`scalar deleting destructor' Mission* GetState(MxU8 p_id); + MxS16 FUN_10039540(); - undefined4 m_unk0x08; // 0x08 - undefined4 m_unk0x0c; // 0x0c - Mission m_state[5]; // 0x10 - undefined4 m_unk0xb0; // 0xb0 + PizzeriaState* m_pizzeriaState; // 0x08 + undefined4 m_unk0x0c; // 0x0c + Mission m_state[5]; // 0x10 + undefined4 m_unk0xb0; // 0xb0 }; // VTABLE: LEGO1 0x100d7380 diff --git a/LEGO1/lego/legoomni/include/pizzeria.h b/LEGO1/lego/legoomni/include/pizzeria.h index 028b2993..9544a071 100644 --- a/LEGO1/lego/legoomni/include/pizzeria.h +++ b/LEGO1/lego/legoomni/include/pizzeria.h @@ -40,6 +40,7 @@ class PizzeriaState : public LegoState { // SYNTHETIC: LEGO1 0x10017ce0 // PizzeriaState::`scalar deleting destructor' + MxS16 FUN_10017d50(); MxU32 FUN_10017d70(); // TODO: Most likely getters/setters are not used according to BETA. diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index ac47ea53..fa538f5a 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -2,6 +2,7 @@ #include "isle.h" #include "isle_actions.h" +#include "jukebox_actions.h" #include "legoanimationmanager.h" #include "legogamestate.h" #include "legoutils.h" @@ -10,6 +11,8 @@ #include "mxbackgroundaudiomanager.h" #include "mxmisc.h" #include "mxticklemanager.h" +#include "mxtimer.h" +#include "pizzeria.h" #include "skateboard.h" DECOMP_SIZE_ASSERT(Pizza, 0x9c) @@ -121,10 +124,42 @@ void Pizza::StopActions() } } -// STUB: LEGO1 0x100383f0 +// FUNCTION: LEGO1 0x100383f0 MxLong Pizza::HandleClick() { - // TODO + if (m_state->m_unk0x0c == 1) { + m_state->m_unk0x0c = 2; + m_mission->m_startTime = Timer()->GetTime(); + TickleManager()->RegisterClient(this, 200); + AnimationManager()->FUN_10061010(FALSE); + } + + if (m_state->m_unk0x0c == 2) { + m_act1state->m_unk0x018 = 3; + + if (m_skateBoard == NULL) { + m_skateBoard = (SkateBoard*) m_world->Find(m_atomId, IsleScript::c_SkateBoard_Actor); + } + + IsleScript::Script action; + + switch (m_state->FUN_10039540()) { + case 0: + action = m_mission->m_actions[m_mission->m_numActions + 3]; + break; + case 1: + action = m_mission->m_actions[m_mission->m_numActions + 4]; + break; + default: + action = m_mission->m_actions[m_mission->m_numActions + 5]; + } + + FUN_10038fe0(action, TRUE); + m_state->m_unk0x0c = 3; + PlayMusic(JukeboxScript::c_PizzaMission_Music); + return 1; + } + return 0; } @@ -191,3 +226,9 @@ PizzaMissionState::Mission* PizzaMissionState::GetState(MxU8 p_id) return NULL; } + +// FUNCTION: LEGO1 0x10039540 +MxS16 PizzaMissionState::FUN_10039540() +{ + return m_pizzeriaState->FUN_10017d50(); +} diff --git a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp index 3b61ddb7..c706fb90 100644 --- a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp @@ -70,6 +70,12 @@ PizzeriaState::PizzeriaState() // TODO } +// STUB: LEGO1 0x10017d50 +MxS16 PizzeriaState::FUN_10017d50() +{ + return 0; +} + // STUB: LEGO1 0x10017d70 MxU32 PizzeriaState::FUN_10017d70() { From 139da3162887077fca7851d3262ac345cb997c6a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 27 Oct 2024 11:54:01 -0700 Subject: [PATCH 03/17] Implement/match PizzaMissionState::PizzaMissionState (#1121) * Implement/match PizzaMissionState::PizzaMissionState * Fix naming --- LEGO1/lego/legoomni/include/pizza.h | 70 +++++++++++++++---- LEGO1/lego/legoomni/src/actors/pizza.cpp | 88 +++++++++++++++++++++--- 2 files changed, 135 insertions(+), 23 deletions(-) diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index 0f9a9503..ac1091f9 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -16,7 +16,49 @@ class PizzaMissionState : public LegoState { public: // SIZE 0x20 struct Mission { - public: + // FUNCTION: LEGO1 0x10039220 + // FUNCTION: BETA10 0x100ef880 + Mission() {} + + // FUNCTION: BETA10 0x100ef8a0 + Mission( + MxU8 p_actorId, + undefined2 p_unk0x04, + MxLong* p_finishTimes, + IsleScript::Script* p_actions, + MxS16 p_numActions + ) + { + m_numActions = p_numActions; + m_actorId = p_actorId; + m_unk0x04 = p_unk0x04; + m_unk0x06 = 1; + m_unk0x08 = 1; + m_finishTimes = p_finishTimes; + m_startTime = INT_MIN; + m_unk0x14 = 1; + m_unk0x16 = 0; + m_score = 0; + m_actions = p_actions; + } + + // FUNCTION: LEGO1 0x10039230 + Mission& operator=(const Mission& p_mission) + { + m_actorId = p_mission.m_actorId; + m_unk0x04 = p_mission.m_unk0x04; + m_unk0x06 = p_mission.m_unk0x06; + m_unk0x08 = p_mission.m_unk0x08; + m_finishTimes = p_mission.m_finishTimes; + m_startTime = p_mission.m_startTime; + m_unk0x14 = p_mission.m_unk0x14; + m_unk0x16 = p_mission.m_unk0x16; + m_score = p_mission.m_score; + m_actions = p_mission.m_actions; + m_numActions = p_mission.m_numActions; + return *this; + } + MxResult WriteToFile(LegoFile* p_file) { Write(p_file, m_unk0x06); @@ -36,10 +78,11 @@ class PizzaMissionState : public LegoState { } MxS16 m_numActions; // 0x00 - MxU8 m_id; // 0x02 - undefined m_unk0x03[3]; // 0x03 + MxU8 m_actorId; // 0x02 + undefined2 m_unk0x04; // 0x04 MxS16 m_unk0x06; // 0x06 - undefined m_unk0x08[8]; // 0x08 + undefined m_unk0x08; // 0x08 + MxLong* m_finishTimes; // 0x0c MxLong m_startTime; // 0x10 MxS16 m_unk0x14; // 0x14 MxS16 m_unk0x16; // 0x16 @@ -64,17 +107,20 @@ class PizzaMissionState : public LegoState { MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c - MxS16 GetHighScore(MxU8 p_id) { return GetState(p_id)->m_score; } + // FUNCTION: BETA10 0x100ef470 + void SetUnknown0xb0(undefined4 p_unk0xb0) { m_unk0xb0 = p_unk0xb0; } + + MxS16 GetHighScore(MxU8 p_actorId) { return GetMission(p_actorId)->m_score; } // SYNTHETIC: LEGO1 0x10039350 // PizzaMissionState::`scalar deleting destructor' - Mission* GetState(MxU8 p_id); + Mission* GetMission(MxU8 p_actorId); MxS16 FUN_10039540(); PizzeriaState* m_pizzeriaState; // 0x08 undefined4 m_unk0x0c; // 0x0c - Mission m_state[5]; // 0x10 + Mission m_missions[5]; // 0x10 undefined4 m_unk0xb0; // 0xb0 }; @@ -100,10 +146,10 @@ class Pizza : public IsleActor { return !strcmp(p_name, Pizza::ClassName()) || IsleActor::IsA(p_name); } - MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - MxLong HandleClick() override; // vtable+0x68 - MxLong HandleEndAction(MxEndActionNotificationParam&) override; // vtable+0x74 - MxLong HandlePathStruct(LegoPathStructNotificationParam&) override; // vtable+0x80 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + MxLong HandleClick() override; // vtable+0x68 + MxLong HandleEndAction(MxEndActionNotificationParam&) override; // vtable+0x74 + MxLong HandlePathStruct(LegoPathStructNotificationParam& p_param) override; // vtable+0x80 void CreateState(); void FUN_10038220(MxU32 p_objectId); @@ -124,7 +170,7 @@ class Pizza : public IsleActor { undefined4 m_unk0x8c; // 0x8c undefined4 m_unk0x90; // 0x90 undefined4 m_unk0x94; // 0x94 - undefined m_unk0x98; // 0x98 + MxBool m_unk0x98; // 0x98 }; #endif // PIZZA_H diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index fa538f5a..111fccc8 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -5,6 +5,7 @@ #include "jukebox_actions.h" #include "legoanimationmanager.h" #include "legogamestate.h" +#include "legopathstruct.h" #include "legoutils.h" #include "legoworld.h" #include "misc.h" @@ -22,6 +23,61 @@ DECOMP_SIZE_ASSERT(PizzaMissionState::Mission, 0x20) // Flags used in isle.cpp extern MxU32 g_isleFlags; +// GLOBAL: LEGO1 0x100f3a80 +IsleScript::Script g_pepperActions[] = { + IsleScript::c_pnsx48pr_RunAnim, + IsleScript::c_pnsx69pr_RunAnim, + IsleScript::c_pns125ni_RunAnim, + IsleScript::c_pns122pr_RunAnim +}; + +// GLOBAL: LEGO1 0x100f3ab8 +MxLong g_pepperFinishTimes[] = {100000, 200000, 300000, 350000}; + +// GLOBAL: LEGO1 0x100f3ac8 +IsleScript::Script g_lauraActions[] = { + IsleScript::c_pns096pr_RunAnim, + IsleScript::c_pns097pr_RunAnim, + IsleScript::c_pns098pr_RunAnim, + IsleScript::c_pns099pr_RunAnim +}; + +// GLOBAL: LEGO1 0x100f3b00 +MxLong g_lauraFinishTimes[] = {100000, 200000, 300000, 350000}; + +// GLOBAL: LEGO1 0x100f3b10 +IsleScript::Script g_nickActions[] = { + IsleScript::c_pns042bm_RunAnim, + IsleScript::c_pns043en_RunAnim, + IsleScript::c_pns045p1_RunAnim, + IsleScript::c_pns048pr_RunAnim +}; + +// GLOBAL: LEGO1 0x100f3b48 +MxLong g_nickFinishTimes[] = {100000, 200000, 300000, 350000}; + +// GLOBAL: LEGO1 0x100f3b58 +IsleScript::Script g_mamaActions[] = { + IsleScript::c_pns022pr_RunAnim, + IsleScript::c_pns021dl_RunAnim, + IsleScript::c_pns018rd_RunAnim, + IsleScript::c_pns019pr_RunAnim +}; + +// GLOBAL: LEGO1 0x100f3b90 +MxLong g_mamaFinishTimes[] = {100000, 200000, 300000, 350000}; + +// GLOBAL: LEGO1 0x100f3ba0 +IsleScript::Script g_papaActions[] = { + IsleScript::c_pns065rd_RunAnim, + IsleScript::c_pns066db_RunAnim, + IsleScript::c_pns067gd_RunAnim, + IsleScript::c_pns069pr_RunAnim +}; + +// GLOBAL: LEGO1 0x100f3bd8 +MxLong g_papaFinishTimes[] = {100000, 200000, 300000, 350000}; + // FUNCTION: LEGO1 0x10037ef0 Pizza::Pizza() { @@ -30,7 +86,7 @@ Pizza::Pizza() m_skateBoard = NULL; m_act1state = NULL; m_unk0x8c = -1; - m_unk0x98 = 0; + m_unk0x98 = FALSE; m_unk0x90 = INT_MIN; } @@ -73,7 +129,7 @@ void Pizza::CreateState() void Pizza::FUN_10038220(MxU32 p_objectId) { AnimationManager()->FUN_10064740(NULL); - m_mission = m_state->GetState(GameState()->GetActorId()); + m_mission = m_state->GetMission(GameState()->GetActorId()); m_state->m_unk0x0c = 1; m_act1state->m_unk0x018 = 3; m_mission->m_startTime = INT_MIN; @@ -100,7 +156,7 @@ void Pizza::FUN_100382b0() AnimationManager()->FUN_1005f6d0(TRUE); m_mission->m_startTime = INT_MIN; m_mission = NULL; - m_unk0x98 = 0; + m_unk0x98 = FALSE; m_unk0x8c = -1; BackgroundAudioManager()->RaiseVolume(); TickleManager()->UnregisterClient(this); @@ -125,6 +181,7 @@ void Pizza::StopActions() } // FUNCTION: LEGO1 0x100383f0 +// FUNCTION: BETA10 0x100edd10 MxLong Pizza::HandleClick() { if (m_state->m_unk0x0c == 1) { @@ -164,7 +221,8 @@ MxLong Pizza::HandleClick() } // STUB: LEGO1 0x100384f0 -MxLong Pizza::HandlePathStruct(LegoPathStructNotificationParam&) +// FUNCTION: BETA10 0x100ede53 +MxLong Pizza::HandlePathStruct(LegoPathStructNotificationParam& p_param) { // TODO return 0; @@ -190,10 +248,18 @@ void Pizza::FUN_10038fe0(MxU32 p_objectId, MxBool) // TODO } -// STUB: LEGO1 0x10039030 +// FUNCTION: LEGO1 0x10039030 +// FUNCTION: BETA10 0x100eea25 PizzaMissionState::PizzaMissionState() { - // TODO + m_unk0x0c = 0; + m_missions[0] = Mission(LegoActor::c_pepper, 2, g_pepperFinishTimes, g_pepperActions, sizeOfArray(g_pepperActions)); + m_missions[1] = Mission(LegoActor::c_mama, 2, g_mamaFinishTimes, g_mamaActions, sizeOfArray(g_mamaActions)); + m_missions[2] = Mission(LegoActor::c_papa, 2, g_papaFinishTimes, g_papaActions, sizeOfArray(g_papaActions)); + m_missions[3] = Mission(LegoActor::c_nick, 2, g_nickFinishTimes, g_nickActions, sizeOfArray(g_nickActions)); + m_missions[4] = Mission(LegoActor::c_laura, 2, g_lauraFinishTimes, g_lauraActions, sizeOfArray(g_lauraActions)); + m_pizzeriaState = (PizzeriaState*) GameState()->GetState("PizzeriaState"); + m_unk0xb0 = -1; } // FUNCTION: LEGO1 0x100393c0 @@ -203,12 +269,12 @@ MxResult PizzaMissionState::Serialize(LegoFile* p_file) if (p_file->IsReadMode()) { for (MxS16 i = 0; i < 5; i++) { - m_state[i].ReadFromFile(p_file); + m_missions[i].ReadFromFile(p_file); } } else if (p_file->IsWriteMode()) { for (MxS16 i = 0; i < 5; i++) { - m_state[i].WriteToFile(p_file); + m_missions[i].WriteToFile(p_file); } } @@ -216,11 +282,11 @@ MxResult PizzaMissionState::Serialize(LegoFile* p_file) } // FUNCTION: LEGO1 0x10039510 -PizzaMissionState::Mission* PizzaMissionState::GetState(MxU8 p_id) +PizzaMissionState::Mission* PizzaMissionState::GetMission(MxU8 p_actorId) { for (MxS16 i = 0; i < 5; i++) { - if (m_state[i].m_id == p_id) { - return m_state + i; + if (m_missions[i].m_actorId == p_actorId) { + return m_missions + i; } } From 2fa2ab4a9685e3f48694159560d78f15fd0d0e27 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 28 Oct 2024 08:53:09 -0700 Subject: [PATCH 04/17] Implement/match Pizza::HandlePathStruct (#1122) --- LEGO1/lego/legoomni/include/pizza.h | 44 +++++-- LEGO1/lego/legoomni/src/actors/pizza.cpp | 159 ++++++++++++++++++++--- 2 files changed, 178 insertions(+), 25 deletions(-) diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index ac1091f9..addbc5e3 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -37,8 +37,8 @@ class PizzaMissionState : public LegoState { m_finishTimes = p_finishTimes; m_startTime = INT_MIN; m_unk0x14 = 1; - m_unk0x16 = 0; - m_score = 0; + m_score = LegoState::e_grey; + m_hiScore = LegoState::e_grey; m_actions = p_actions; } @@ -52,19 +52,43 @@ class PizzaMissionState : public LegoState { m_finishTimes = p_mission.m_finishTimes; m_startTime = p_mission.m_startTime; m_unk0x14 = p_mission.m_unk0x14; - m_unk0x16 = p_mission.m_unk0x16; m_score = p_mission.m_score; + m_hiScore = p_mission.m_hiScore; m_actions = p_mission.m_actions; m_numActions = p_mission.m_numActions; return *this; } + // FUNCTION: BETA10 0x100ef610 + IsleScript::Script GetRedFinishAction() { return m_actions[m_numActions + 6]; } + + // FUNCTION: BETA10 0x100ef640 + IsleScript::Script GetBlueFinishAction() { return m_actions[m_numActions + 7]; } + + // FUNCTION: BETA10 0x100ef670 + IsleScript::Script GetYellowFinishAction() { return m_actions[m_numActions + 8]; } + + // FUNCTION: BETA10 0x100ef6a0 + MxLong GetRedFinishTime() { return m_finishTimes[0]; } + + // FUNCTION: BETA10 0x100ef6d0 + MxLong GetBlueFinishTime() { return m_finishTimes[1]; } + + // FUNCTION: BETA10 0x100ef700 + void UpdateScore(ScoreColor p_score) + { + m_score = p_score; + if (m_hiScore < p_score) { + m_hiScore = p_score; + } + } + MxResult WriteToFile(LegoFile* p_file) { Write(p_file, m_unk0x06); Write(p_file, m_unk0x14); - Write(p_file, m_unk0x16); Write(p_file, m_score); + Write(p_file, m_hiScore); return SUCCESS; } @@ -72,8 +96,8 @@ class PizzaMissionState : public LegoState { { Read(p_file, &m_unk0x06); Read(p_file, &m_unk0x14); - Read(p_file, &m_unk0x16); Read(p_file, &m_score); + Read(p_file, &m_hiScore); return SUCCESS; } @@ -85,8 +109,8 @@ class PizzaMissionState : public LegoState { MxLong* m_finishTimes; // 0x0c MxLong m_startTime; // 0x10 MxS16 m_unk0x14; // 0x14 - MxS16 m_unk0x16; // 0x16 - MxS16 m_score; // 0x18 + MxS16 m_score; // 0x16 + MxS16 m_hiScore; // 0x18 IsleScript::Script* m_actions; // 0x1c }; @@ -110,7 +134,7 @@ class PizzaMissionState : public LegoState { // FUNCTION: BETA10 0x100ef470 void SetUnknown0xb0(undefined4 p_unk0xb0) { m_unk0xb0 = p_unk0xb0; } - MxS16 GetHighScore(MxU8 p_actorId) { return GetMission(p_actorId)->m_score; } + MxS16 GetHighScore(MxU8 p_actorId) { return GetMission(p_actorId)->m_hiScore; } // SYNTHETIC: LEGO1 0x10039350 // PizzaMissionState::`scalar deleting destructor' @@ -155,7 +179,7 @@ class Pizza : public IsleActor { void FUN_10038220(MxU32 p_objectId); void FUN_100382b0(); void StopActions(); - void FUN_10038fe0(MxU32 p_objectId, MxBool); + void PlayAction(MxU32 p_objectId, MxBool); void SetSkateboard(SkateBoard* p_skateBoard) { m_skateBoard = p_skateBoard; } @@ -168,7 +192,7 @@ class Pizza : public IsleActor { SkateBoard* m_skateBoard; // 0x84 Act1State* m_act1state; // 0x88 undefined4 m_unk0x8c; // 0x8c - undefined4 m_unk0x90; // 0x90 + MxLong m_unk0x90; // 0x90 undefined4 m_unk0x94; // 0x94 MxBool m_unk0x98; // 0x98 }; diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index 111fccc8..9ef8792c 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -28,7 +28,16 @@ IsleScript::Script g_pepperActions[] = { IsleScript::c_pnsx48pr_RunAnim, IsleScript::c_pnsx69pr_RunAnim, IsleScript::c_pns125ni_RunAnim, - IsleScript::c_pns122pr_RunAnim + IsleScript::c_pns122pr_RunAnim, + IsleScript::c_noneIsle, + IsleScript::c_noneIsle, + IsleScript::c_ppz120pa_RunAnim, + IsleScript::c_ppz117ma_RunAnim, + IsleScript::c_ppz118ma_RunAnim, + IsleScript::c_ppz119ma_RunAnim, + IsleScript::c_nja001pr_RunAnim, + IsleScript::c_nja001pr_RunAnim, + IsleScript::c_nja001pr_RunAnim }; // GLOBAL: LEGO1 0x100f3ab8 @@ -39,7 +48,16 @@ IsleScript::Script g_lauraActions[] = { IsleScript::c_pns096pr_RunAnim, IsleScript::c_pns097pr_RunAnim, IsleScript::c_pns098pr_RunAnim, - IsleScript::c_pns099pr_RunAnim + IsleScript::c_pns099pr_RunAnim, + IsleScript::c_noneIsle, + IsleScript::c_ppz086bs_RunAnim, + IsleScript::c_ppz090ma_RunAnim, + IsleScript::c_ppz088ma_RunAnim, + IsleScript::c_ppz089ma_RunAnim, + IsleScript::c_ppz095pe_RunAnim, + IsleScript::c_pho104re_RunAnim, + IsleScript::c_pho105re_RunAnim, + IsleScript::c_pho106re_RunAnim }; // GLOBAL: LEGO1 0x100f3b00 @@ -50,7 +68,16 @@ IsleScript::Script g_nickActions[] = { IsleScript::c_pns042bm_RunAnim, IsleScript::c_pns043en_RunAnim, IsleScript::c_pns045p1_RunAnim, - IsleScript::c_pns048pr_RunAnim + IsleScript::c_pns048pr_RunAnim, + IsleScript::c_ppz029rd_RunAnim, + IsleScript::c_noneIsle, + IsleScript::c_ppz038ma_RunAnim, + IsleScript::c_ppz037ma_RunAnim, + IsleScript::c_ppz037ma_RunAnim, + IsleScript::c_ppz037ma_RunAnim, + IsleScript::c_pgs050nu_RunAnim, + IsleScript::c_pgs051nu_RunAnim, + IsleScript::c_pgs052nu_RunAnim }; // GLOBAL: LEGO1 0x100f3b48 @@ -61,7 +88,16 @@ IsleScript::Script g_mamaActions[] = { IsleScript::c_pns022pr_RunAnim, IsleScript::c_pns021dl_RunAnim, IsleScript::c_pns018rd_RunAnim, - IsleScript::c_pns019pr_RunAnim + IsleScript::c_pns019pr_RunAnim, + IsleScript::c_ppz008rd_RunAnim, + IsleScript::c_noneIsle, + IsleScript::c_ppz013pa_RunAnim, + IsleScript::c_ppz010pa_RunAnim, + IsleScript::c_ppz011pa_RunAnim, + IsleScript::c_ppz016pe_RunAnim, + IsleScript::c_pps025ni_RunAnim, + IsleScript::c_pps026ni_RunAnim, + IsleScript::c_pps027ni_RunAnim }; // GLOBAL: LEGO1 0x100f3b90 @@ -72,7 +108,16 @@ IsleScript::Script g_papaActions[] = { IsleScript::c_pns065rd_RunAnim, IsleScript::c_pns066db_RunAnim, IsleScript::c_pns067gd_RunAnim, - IsleScript::c_pns069pr_RunAnim + IsleScript::c_pns069pr_RunAnim, + IsleScript::c_noneIsle, + IsleScript::c_noneIsle, + IsleScript::c_ppz061ma_RunAnim, + IsleScript::c_ppz059ma_RunAnim, + IsleScript::c_ppz060ma_RunAnim, + IsleScript::c_ppz064ma_RunAnim, + IsleScript::c_prt072sl_RunAnim, + IsleScript::c_prt073sl_RunAnim, + IsleScript::c_prt074sl_RunAnim }; // GLOBAL: LEGO1 0x100f3bd8 @@ -136,7 +181,7 @@ void Pizza::FUN_10038220(MxU32 p_objectId) g_isleFlags &= ~Isle::c_playMusic; AnimationManager()->EnableCamAnims(FALSE); AnimationManager()->FUN_1005f6d0(FALSE); - FUN_10038fe0(p_objectId, FALSE); + PlayAction(p_objectId, FALSE); m_unk0x8c = -1; } @@ -211,7 +256,7 @@ MxLong Pizza::HandleClick() action = m_mission->m_actions[m_mission->m_numActions + 5]; } - FUN_10038fe0(action, TRUE); + PlayAction(action, TRUE); m_state->m_unk0x0c = 3; PlayMusic(JukeboxScript::c_PizzaMission_Music); return 1; @@ -220,11 +265,95 @@ MxLong Pizza::HandleClick() return 0; } -// STUB: LEGO1 0x100384f0 +// FUNCTION: LEGO1 0x100384f0 // FUNCTION: BETA10 0x100ede53 MxLong Pizza::HandlePathStruct(LegoPathStructNotificationParam& p_param) { - // TODO + if (m_state->m_unk0x0c == 4) { + MxLong time = Timer()->GetTime() - m_mission->m_startTime; + + if (p_param.GetTrigger() == LegoPathStruct::c_s && p_param.GetData() == 0x12e && + GameState()->GetActorId() == LegoActor::c_pepper) { + m_state->m_unk0x0c = 5; + m_state->SetUnknown0xb0(0x12e); + + if (time < m_mission->GetRedFinishTime()) { + m_mission->UpdateScore(LegoState::e_red); + } + else if (time < m_mission->GetBlueFinishTime()) { + m_mission->UpdateScore(LegoState::e_blue); + } + else { + m_mission->UpdateScore(LegoState::e_yellow); + } + } + else if ((p_param.GetTrigger() == LegoPathStruct::c_camAnim && ( + ((p_param.GetData() == 0x24 || p_param.GetData() == 0x22) && GameState()->GetActorId() == LegoActor::c_mama) || + (p_param.GetData() == 0x33 && GameState()->GetActorId() == LegoActor::c_papa) || + ((p_param.GetData() == 0x08 || p_param.GetData() == 0x09) && GameState()->GetActorId() == LegoActor::c_nick) || + (p_param.GetData() == 0x0b && GameState()->GetActorId() == LegoActor::c_laura) + )) || (p_param.GetTrigger() == LegoPathStruct::c_w && p_param.GetData() == 0x169 && GameState()->GetActorId() == LegoActor::c_nick)) { + IsleScript::Script action; + + if (time < m_mission->GetRedFinishTime()) { + action = m_mission->GetRedFinishAction(); + m_mission->UpdateScore(LegoState::e_red); + } + else if (time < m_mission->GetBlueFinishTime()) { + action = m_mission->GetBlueFinishAction(); + m_mission->UpdateScore(LegoState::e_blue); + } + else { + action = m_mission->GetYellowFinishAction(); + m_mission->UpdateScore(LegoState::e_yellow); + } + + StopActions(); + + switch (action) { + case IsleScript::c_pps025ni_RunAnim: + case IsleScript::c_pps026ni_RunAnim: + case IsleScript::c_pps027ni_RunAnim: + m_unk0x90 = Timer()->GetTime(); + m_unk0x94 = 3800; + break; + case IsleScript::c_pgs050nu_RunAnim: + case IsleScript::c_pgs051nu_RunAnim: + case IsleScript::c_pgs052nu_RunAnim: + m_unk0x90 = Timer()->GetTime(); + m_unk0x94 = 6400; + break; + case IsleScript::c_prt072sl_RunAnim: + case IsleScript::c_prt073sl_RunAnim: + case IsleScript::c_prt074sl_RunAnim: + m_unk0x90 = Timer()->GetTime(); + m_unk0x94 = 7000; + break; + case IsleScript::c_pho104re_RunAnim: + case IsleScript::c_pho105re_RunAnim: + case IsleScript::c_pho106re_RunAnim: + m_unk0x90 = Timer()->GetTime(); + m_unk0x94 = 6500; + break; + } + + m_state->m_unk0x0c = 5; + PlayAction(action, TRUE); + } + else if (p_param.GetTrigger() == LegoPathStruct::c_w) { + if (p_param.GetData() == 0x15e && GameState()->GetActorId() == LegoActor::c_pepper) { + if (!m_unk0x98) { + m_unk0x98 = TRUE; + InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_pns050p1_RunAnim, NULL); + } + } + else if (p_param.GetData() == 0x15f && GameState()->GetActorId() == LegoActor::c_papa && !m_unk0x98) { + m_unk0x98 = TRUE; + InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_wns050p1_RunAnim, NULL); + } + } + } + return 0; } @@ -243,7 +372,7 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam&) } // STUB: LEGO1 0x10038fe0 -void Pizza::FUN_10038fe0(MxU32 p_objectId, MxBool) +void Pizza::PlayAction(MxU32 p_objectId, MxBool) { // TODO } @@ -253,11 +382,11 @@ void Pizza::FUN_10038fe0(MxU32 p_objectId, MxBool) PizzaMissionState::PizzaMissionState() { m_unk0x0c = 0; - m_missions[0] = Mission(LegoActor::c_pepper, 2, g_pepperFinishTimes, g_pepperActions, sizeOfArray(g_pepperActions)); - m_missions[1] = Mission(LegoActor::c_mama, 2, g_mamaFinishTimes, g_mamaActions, sizeOfArray(g_mamaActions)); - m_missions[2] = Mission(LegoActor::c_papa, 2, g_papaFinishTimes, g_papaActions, sizeOfArray(g_papaActions)); - m_missions[3] = Mission(LegoActor::c_nick, 2, g_nickFinishTimes, g_nickActions, sizeOfArray(g_nickActions)); - m_missions[4] = Mission(LegoActor::c_laura, 2, g_lauraFinishTimes, g_lauraActions, sizeOfArray(g_lauraActions)); + m_missions[0] = Mission(LegoActor::c_pepper, 2, g_pepperFinishTimes, g_pepperActions, 4); + m_missions[1] = Mission(LegoActor::c_mama, 2, g_mamaFinishTimes, g_mamaActions, 4); + m_missions[2] = Mission(LegoActor::c_papa, 2, g_papaFinishTimes, g_papaActions, 4); + m_missions[3] = Mission(LegoActor::c_nick, 2, g_nickFinishTimes, g_nickActions, 4); + m_missions[4] = Mission(LegoActor::c_laura, 2, g_lauraFinishTimes, g_lauraActions, 4); m_pizzeriaState = (PizzeriaState*) GameState()->GetState("PizzeriaState"); m_unk0xb0 = -1; } From ad353b7f3edee52cf71bc2a1754469188b5fffe9 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 28 Oct 2024 09:25:54 -0700 Subject: [PATCH 05/17] Implement/match Pizza::PlayAction (#1123) * Implement/match Pizza::PlayAction * Remove unused header --- .../legoomni/include/legoanimationmanager.h | 3 +- LEGO1/lego/legoomni/include/pizza.h | 10 +++---- LEGO1/lego/legoomni/src/actors/pizza.cpp | 28 ++++++++++++------- LEGO1/lego/legoomni/src/actors/pizzeria.cpp | 2 +- .../src/common/legoanimationmanager.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/isle.cpp | 1 + 6 files changed, 27 insertions(+), 19 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index 3d181985..c568663e 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -1,7 +1,6 @@ #ifndef LEGOANIMATIONMANAGER_H #define LEGOANIMATIONMANAGER_H -#include "actionsfwd.h" #include "decomp.h" #include "legolocations.h" #include "legostate.h" @@ -161,7 +160,7 @@ class LegoAnimationManager : public MxCore { void FUN_10060570(MxBool p_unk0x1a); MxResult StartEntityAction(MxDSAction& p_dsAction, LegoEntity* p_entity); MxResult FUN_10060dc0( - IsleScript::Script p_objectId, + MxU32 p_objectId, MxMatrix* p_matrix, MxBool p_param3, MxBool p_param4, diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index addbc5e3..961d5923 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -132,7 +132,7 @@ class PizzaMissionState : public LegoState { MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c // FUNCTION: BETA10 0x100ef470 - void SetUnknown0xb0(undefined4 p_unk0xb0) { m_unk0xb0 = p_unk0xb0; } + void SetUnknown0xb0(MxU32 p_unk0xb0) { m_unk0xb0 = p_unk0xb0; } MxS16 GetHighScore(MxU8 p_actorId) { return GetMission(p_actorId)->m_hiScore; } @@ -145,7 +145,7 @@ class PizzaMissionState : public LegoState { PizzeriaState* m_pizzeriaState; // 0x08 undefined4 m_unk0x0c; // 0x0c Mission m_missions[5]; // 0x10 - undefined4 m_unk0xb0; // 0xb0 + MxU32 m_unk0xb0; // 0xb0 }; // VTABLE: LEGO1 0x100d7380 @@ -176,10 +176,10 @@ class Pizza : public IsleActor { MxLong HandlePathStruct(LegoPathStructNotificationParam& p_param) override; // vtable+0x80 void CreateState(); - void FUN_10038220(MxU32 p_objectId); + void FUN_10038220(IsleScript::Script p_objectId); void FUN_100382b0(); void StopActions(); - void PlayAction(MxU32 p_objectId, MxBool); + void PlayAction(MxU32 p_objectId, MxBool p_param7); void SetSkateboard(SkateBoard* p_skateBoard) { m_skateBoard = p_skateBoard; } @@ -191,7 +191,7 @@ class Pizza : public IsleActor { PizzaMissionState::Mission* m_mission; // 0x80 SkateBoard* m_skateBoard; // 0x84 Act1State* m_act1state; // 0x88 - undefined4 m_unk0x8c; // 0x8c + IsleScript::Script m_unk0x8c; // 0x8c MxLong m_unk0x90; // 0x90 undefined4 m_unk0x94; // 0x94 MxBool m_unk0x98; // 0x98 diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index 9ef8792c..490068d3 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -15,6 +15,7 @@ #include "mxtimer.h" #include "pizzeria.h" #include "skateboard.h" +#include "sndanim_actions.h" DECOMP_SIZE_ASSERT(Pizza, 0x9c) DECOMP_SIZE_ASSERT(PizzaMissionState, 0xb4) @@ -130,7 +131,7 @@ Pizza::Pizza() m_mission = NULL; m_skateBoard = NULL; m_act1state = NULL; - m_unk0x8c = -1; + m_unk0x8c = IsleScript::c_noneIsle; m_unk0x98 = FALSE; m_unk0x90 = INT_MIN; } @@ -171,7 +172,7 @@ void Pizza::CreateState() // FUNCTION: LEGO1 0x10038220 // FUNCTION: BETA10 0x100edb81 -void Pizza::FUN_10038220(MxU32 p_objectId) +void Pizza::FUN_10038220(IsleScript::Script p_objectId) { AnimationManager()->FUN_10064740(NULL); m_mission = m_state->GetMission(GameState()->GetActorId()); @@ -182,14 +183,14 @@ void Pizza::FUN_10038220(MxU32 p_objectId) AnimationManager()->EnableCamAnims(FALSE); AnimationManager()->FUN_1005f6d0(FALSE); PlayAction(p_objectId, FALSE); - m_unk0x8c = -1; + m_unk0x8c = IsleScript::c_noneIsle; } // FUNCTION: LEGO1 0x100382b0 void Pizza::FUN_100382b0() { if (m_state->m_unk0x0c != 8) { - if (m_unk0x8c != -1) { + if (m_unk0x8c != IsleScript::c_noneIsle) { InvokeAction(Extra::e_stop, *g_isleScript, m_unk0x8c, NULL); } @@ -202,7 +203,7 @@ void Pizza::FUN_100382b0() m_mission->m_startTime = INT_MIN; m_mission = NULL; m_unk0x98 = FALSE; - m_unk0x8c = -1; + m_unk0x8c = IsleScript::c_noneIsle; BackgroundAudioManager()->RaiseVolume(); TickleManager()->UnregisterClient(this); m_unk0x90 = INT_MIN; @@ -275,7 +276,7 @@ MxLong Pizza::HandlePathStruct(LegoPathStructNotificationParam& p_param) if (p_param.GetTrigger() == LegoPathStruct::c_s && p_param.GetData() == 0x12e && GameState()->GetActorId() == LegoActor::c_pepper) { m_state->m_unk0x0c = 5; - m_state->SetUnknown0xb0(0x12e); + m_state->SetUnknown0xb0(SndanimScript::c_TRS302_OpenJailDoor); if (time < m_mission->GetRedFinishTime()) { m_mission->UpdateScore(LegoState::e_red); @@ -371,10 +372,17 @@ MxLong Pizza::HandleEndAction(MxEndActionNotificationParam&) return 0; } -// STUB: LEGO1 0x10038fe0 -void Pizza::PlayAction(MxU32 p_objectId, MxBool) +// FUNCTION: LEGO1 0x10038fe0 +// FUNCTION: BETA10 0x100ef520 +void Pizza::PlayAction(MxU32 p_objectId, MxBool p_param7) { - // TODO + m_state->SetUnknown0xb0(p_objectId); + + if (m_unk0x8c != IsleScript::c_noneIsle) { + InvokeAction(Extra::e_stop, *g_isleScript, m_unk0x8c, NULL); + } + + AnimationManager()->FUN_10060dc0(p_objectId, NULL, TRUE, FALSE, NULL, FALSE, p_param7, TRUE, TRUE); } // FUNCTION: LEGO1 0x10039030 @@ -388,7 +396,7 @@ PizzaMissionState::PizzaMissionState() m_missions[3] = Mission(LegoActor::c_nick, 2, g_nickFinishTimes, g_nickActions, 4); m_missions[4] = Mission(LegoActor::c_laura, 2, g_lauraFinishTimes, g_lauraActions, 4); m_pizzeriaState = (PizzeriaState*) GameState()->GetState("PizzeriaState"); - m_unk0xb0 = -1; + m_unk0xb0 = IsleScript::c_noneIsle; } // FUNCTION: LEGO1 0x100393c0 diff --git a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp index c706fb90..c9135eb1 100644 --- a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp @@ -58,7 +58,7 @@ MxLong Pizzeria::HandleClick() AnimationManager()->FUN_10061010(FALSE); Pizza* pizza = (Pizza*) CurrentWorld()->Find(*g_isleScript, IsleScript::c_Pizza_Actor); - pizza->FUN_10038220(m_pizzeriaState->FUN_10017d70()); + pizza->FUN_10038220((IsleScript::Script) m_pizzeriaState->FUN_10017d70()); } return 1; diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index fa42d032..fc7431f8 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -1108,7 +1108,7 @@ MxResult LegoAnimationManager::StartEntityAction(MxDSAction& p_dsAction, LegoEnt // FUNCTION: LEGO1 0x10060dc0 // FUNCTION: BETA10 0x10041f2c MxResult LegoAnimationManager::FUN_10060dc0( - IsleScript::Script p_objectId, + MxU32 p_objectId, MxMatrix* p_matrix, MxBool p_param3, MxBool p_param4, diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index fd739d87..66e7a559 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -33,6 +33,7 @@ #include "mxvariabletable.h" #include "pizza.h" #include "pizzeria.h" +#include "racecar.h" #include "scripts.h" #include "skateboard.h" #include "towtrack.h" From 5f822dabc71bed5a0ce6b4c3f852b6b611666f9a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 28 Oct 2024 10:32:55 -0700 Subject: [PATCH 06/17] Implement/match PizzeriaState::PizzeriaState (#1124) --- LEGO1/lego/legoomni/include/legostate.h | 19 ++++++----- LEGO1/lego/legoomni/include/pizzeria.h | 13 ++----- LEGO1/lego/legoomni/src/actors/pizzeria.cpp | 34 +++++++++++++++++-- LEGO1/lego/legoomni/src/actors/radio.cpp | 18 +++++----- LEGO1/lego/legoomni/src/worlds/infocenter.cpp | 19 ++++++----- 5 files changed, 63 insertions(+), 40 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index 9aabc4da..23a8599e 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -27,6 +27,7 @@ class LegoState : public MxCore { }; // FUNCTION: LEGO1 0x10017c00 + // FUNCTION: BETA10 0x10031dc0 Playlist() { m_objectIds = NULL; @@ -35,28 +36,30 @@ class LegoState : public MxCore { m_nextIndex = 0; } - Playlist(MxU32* p_objectIds, MxS16 p_length) + // FUNCTION: BETA10 0x10031e10 + Playlist(MxU32* p_objectIds, MxS16 p_length, MxS16 p_mode) { m_objectIds = p_objectIds; m_length = p_length; - m_mode = e_loop; + m_mode = p_mode; m_nextIndex = 0; } // FUNCTION: LEGO1 0x10071800 - Playlist& operator=(const Playlist& p_shuffle) + // FUNCTION: BETA10 0x10031e70 + Playlist& operator=(const Playlist& p_playlist) { - m_objectIds = p_shuffle.m_objectIds; - m_length = p_shuffle.m_length; - m_nextIndex = p_shuffle.m_nextIndex; - m_mode = p_shuffle.m_mode; + m_objectIds = p_playlist.m_objectIds; + m_length = p_playlist.m_length; + m_nextIndex = p_playlist.m_nextIndex; + m_mode = p_playlist.m_mode; return *this; } MxU32 Next(); MxBool Contains(MxU32 p_objectId); - void SetUnknown0x08(MxS16 p_unk0x08) { m_nextIndex = p_unk0x08; } + void SetNextIndex(MxS16 p_nextIndex) { m_nextIndex = p_nextIndex; } MxResult ReadFromFile(LegoFile* p_file) { diff --git a/LEGO1/lego/legoomni/include/pizzeria.h b/LEGO1/lego/legoomni/include/pizzeria.h index 9544a071..69ea1b9d 100644 --- a/LEGO1/lego/legoomni/include/pizzeria.h +++ b/LEGO1/lego/legoomni/include/pizzeria.h @@ -11,15 +11,6 @@ class PizzaMissionState; // SIZE 0x58 class PizzeriaState : public LegoState { public: - // SIZE 0x14 - struct StateStruct { - undefined4 m_unk0x00; // 0x00 - undefined4 m_unk0x04; // 0x04 - undefined4 m_unk0x08; // 0x08 - undefined4 m_unk0x0c; // 0x0c - undefined4 m_unk0x10; // 0x10 - }; - PizzeriaState(); // FUNCTION: LEGO1 0x10017c20 @@ -45,8 +36,8 @@ class PizzeriaState : public LegoState { // TODO: Most likely getters/setters are not used according to BETA. - Playlist m_unk0x08[5]; // 0x08 - StateStruct m_unk0x44; // 0x44 + Playlist m_unk0x08[5]; // 0x08 + undefined4 m_unk0x44[5]; // 0x44 }; // VTABLE: LEGO1 0x100d5520 diff --git a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp index c9135eb1..2f8e2642 100644 --- a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp @@ -13,7 +13,26 @@ DECOMP_SIZE_ASSERT(Pizzeria, 0x84) DECOMP_SIZE_ASSERT(PizzeriaState, 0x58) -DECOMP_SIZE_ASSERT(PizzeriaState::StateStruct, 0x14) + +// GLOBAL: LEGO1 0x100f0ce8 +IsleScript::Script g_unk0x100f0ce8[] = + {IsleScript::c_ppz107ma_RunAnim, IsleScript::c_ppz114pa_RunAnim, IsleScript::c_ppz114pa_RunAnim}; + +// GLOBAL: LEGO1 0x100f0cf8 +IsleScript::Script g_unk0x100f0cf8[] = + {IsleScript::c_ppz001pe_RunAnim, IsleScript::c_ppz006pa_RunAnim, IsleScript::c_ppz007pa_RunAnim}; + +// GLOBAL: LEGO1 0x100f0d08 +IsleScript::Script g_unk0x100f0d08[] = + {IsleScript::c_ppz054ma_RunAnim, IsleScript::c_ppz055ma_RunAnim, IsleScript::c_ppz056ma_RunAnim}; + +// GLOBAL: LEGO1 0x100f0d18 +IsleScript::Script g_unk0x100f0d18[] = + {IsleScript::c_ppz031ma_RunAnim, IsleScript::c_ppz035pa_RunAnim, IsleScript::c_ppz036pa_RunAnim}; + +// GLOBAL: LEGO1 0x100f0d28 +IsleScript::Script g_unk0x100f0d28[] = + {IsleScript::c_ppz075pa_RunAnim, IsleScript::c_ppz082pa_RunAnim, IsleScript::c_ppz084pa_RunAnim}; // FUNCTION: LEGO1 0x100179c0 MxResult Pizzeria::Create(MxDSAction& p_dsAction) @@ -28,6 +47,7 @@ MxResult Pizzeria::Create(MxDSAction& p_dsAction) } // FUNCTION: LEGO1 0x100179f0 +// FUNCTION: BETA10 0x100efbfc void Pizzeria::CreateState() { LegoGameState* gameState = GameState(); @@ -46,6 +66,7 @@ void Pizzeria::CreateState() } // FUNCTION: LEGO1 0x10017a50 +// FUNCTION: BETA10 0x100efc91 MxLong Pizzeria::HandleClick() { if (FUN_1003ef60() && m_pizzaMissionState->m_unk0x0c == 0) { @@ -64,10 +85,16 @@ MxLong Pizzeria::HandleClick() return 1; } -// STUB: LEGO1 0x10017af0 +// FUNCTION: LEGO1 0x10017af0 +// FUNCTION: BETA10 0x100efd14 PizzeriaState::PizzeriaState() { - // TODO + m_unk0x08[0] = Playlist((MxU32*) g_unk0x100f0ce8, sizeOfArray(g_unk0x100f0ce8), Playlist::e_once); + m_unk0x08[1] = Playlist((MxU32*) g_unk0x100f0cf8, sizeOfArray(g_unk0x100f0cf8), Playlist::e_once); + m_unk0x08[2] = Playlist((MxU32*) g_unk0x100f0d08, sizeOfArray(g_unk0x100f0d08), Playlist::e_once); + m_unk0x08[3] = Playlist((MxU32*) g_unk0x100f0d18, sizeOfArray(g_unk0x100f0d18), Playlist::e_once); + m_unk0x08[4] = Playlist((MxU32*) g_unk0x100f0d28, sizeOfArray(g_unk0x100f0d28), Playlist::e_once); + memset(m_unk0x44, -1, sizeof(m_unk0x44)); } // STUB: LEGO1 0x10017d50 @@ -77,6 +104,7 @@ MxS16 PizzeriaState::FUN_10017d50() } // STUB: LEGO1 0x10017d70 +// FUNCTION: BETA10 0x100effc0 MxU32 PizzeriaState::FUN_10017d70() { return 0; diff --git a/LEGO1/lego/legoomni/src/actors/radio.cpp b/LEGO1/lego/legoomni/src/actors/radio.cpp index 4704ca29..3a22ed16 100644 --- a/LEGO1/lego/legoomni/src/actors/radio.cpp +++ b/LEGO1/lego/legoomni/src/actors/radio.cpp @@ -18,7 +18,7 @@ DECOMP_SIZE_ASSERT(Radio, 0x10) DECOMP_SIZE_ASSERT(RadioState, 0x30) // GLOBAL: LEGO1 0x100f3218 -JukeboxScript::Script g_unk0x100f3218[6] = { +JukeboxScript::Script g_unk0x100f3218[] = { JukeboxScript::c_sns002ra_Audio, JukeboxScript::c_sns001ja_Audio, JukeboxScript::c_snsc01js_Audio, @@ -28,7 +28,7 @@ JukeboxScript::Script g_unk0x100f3218[6] = { }; // GLOBAL: LEGO1 0x100f3230 -JukeboxScript::Script g_unk0x100f3230[14] = { +JukeboxScript::Script g_unk0x100f3230[] = { JukeboxScript::c_ham035ra_Audio, JukeboxScript::c_ham039ra_Audio, JukeboxScript::c_sns005ra_Audio, @@ -46,7 +46,7 @@ JukeboxScript::Script g_unk0x100f3230[14] = { }; // GLOBAL: LEGO1 0x100f3268 -JukeboxScript::Script g_unk0x100f3268[9] = { +JukeboxScript::Script g_unk0x100f3268[] = { JukeboxScript::c_CentralRoads_Music, JukeboxScript::c_BeachBlvd_Music, JukeboxScript::c_ResidentalArea_Music, @@ -214,14 +214,14 @@ RadioState::RadioState() MxS32 random = rand(); m_unk0x2c = random % 3; - m_unk0x08[0] = LegoState::Playlist((MxU32*) g_unk0x100f3218, sizeof(g_unk0x100f3218) / sizeof(g_unk0x100f3218[0])); - m_unk0x08[0].SetUnknown0x08(rand() % (sizeof(g_unk0x100f3218) / sizeof(g_unk0x100f3218[0]))); + m_unk0x08[0] = Playlist((MxU32*) g_unk0x100f3218, sizeOfArray(g_unk0x100f3218), Playlist::e_loop); + m_unk0x08[0].SetNextIndex(rand() % sizeOfArray(g_unk0x100f3218)); - m_unk0x08[1] = LegoState::Playlist((MxU32*) g_unk0x100f3230, sizeof(g_unk0x100f3230) / sizeof(g_unk0x100f3230[0])); - m_unk0x08[1].SetUnknown0x08(rand() % (sizeof(g_unk0x100f3230) / sizeof(g_unk0x100f3230[0]))); + m_unk0x08[1] = Playlist((MxU32*) g_unk0x100f3230, sizeOfArray(g_unk0x100f3230), Playlist::e_loop); + m_unk0x08[1].SetNextIndex(rand() % sizeOfArray(g_unk0x100f3230)); - m_unk0x08[2] = LegoState::Playlist((MxU32*) g_unk0x100f3268, sizeof(g_unk0x100f3268) / sizeof(g_unk0x100f3268[0])); - m_unk0x08[2].SetUnknown0x08(rand() % (sizeof(g_unk0x100f3268) / sizeof(g_unk0x100f3268[0]))); + m_unk0x08[2] = Playlist((MxU32*) g_unk0x100f3268, sizeOfArray(g_unk0x100f3268), Playlist::e_loop); + m_unk0x08[2].SetNextIndex(rand() % sizeOfArray(g_unk0x100f3268)); m_active = FALSE; } diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp index 48e04d38..8e882e75 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp @@ -1549,28 +1549,29 @@ void Infocenter::StopBookAnimation() // FUNCTION: LEGO1 0x10071600 InfocenterState::InfocenterState() { - m_exitDialogueAct1 = LegoState::Playlist((MxU32*) g_exitDialogueAct1, sizeOfArray(g_exitDialogueAct1)); - m_exitDialogueAct23 = LegoState::Playlist((MxU32*) g_exitDialogueAct23, sizeOfArray(g_exitDialogueAct23) - 1); + m_exitDialogueAct1 = Playlist((MxU32*) g_exitDialogueAct1, sizeOfArray(g_exitDialogueAct1), Playlist::e_loop); + m_exitDialogueAct23 = + Playlist((MxU32*) g_exitDialogueAct23, sizeOfArray(g_exitDialogueAct23) - 1, Playlist::e_loop); m_returnDialogue[LegoGameState::e_act1] = - LegoState::Playlist((MxU32*) g_returnDialogueAct1, sizeOfArray(g_returnDialogueAct1) - 1); + Playlist((MxU32*) g_returnDialogueAct1, sizeOfArray(g_returnDialogueAct1) - 1, Playlist::e_loop); m_returnDialogue[LegoGameState::e_act2] = - LegoState::Playlist((MxU32*) g_returnDialogueAct2, sizeOfArray(g_returnDialogueAct2) - 1); + Playlist((MxU32*) g_returnDialogueAct2, sizeOfArray(g_returnDialogueAct2) - 1, Playlist::e_loop); m_returnDialogue[LegoGameState::e_act3] = - LegoState::Playlist((MxU32*) g_returnDialogueAct3, sizeOfArray(g_returnDialogueAct3)); + Playlist((MxU32*) g_returnDialogueAct3, sizeOfArray(g_returnDialogueAct3), Playlist::e_loop); m_leaveDialogue[LegoGameState::e_act1] = - LegoState::Playlist((MxU32*) g_leaveDialogueAct1, sizeOfArray(g_leaveDialogueAct1)); + Playlist((MxU32*) g_leaveDialogueAct1, sizeOfArray(g_leaveDialogueAct1), Playlist::e_loop); m_leaveDialogue[LegoGameState::e_act2] = - LegoState::Playlist((MxU32*) g_leaveDialogueAct2, sizeOfArray(g_leaveDialogueAct2)); + Playlist((MxU32*) g_leaveDialogueAct2, sizeOfArray(g_leaveDialogueAct2), Playlist::e_loop); m_leaveDialogue[LegoGameState::e_act3] = - LegoState::Playlist((MxU32*) g_leaveDialogueAct3, sizeOfArray(g_leaveDialogueAct3) - 1); + Playlist((MxU32*) g_leaveDialogueAct3, sizeOfArray(g_leaveDialogueAct3) - 1, Playlist::e_loop); - m_bricksterDialogue = LegoState::Playlist((MxU32*) g_bricksterDialogue, sizeOfArray(g_bricksterDialogue)); + m_bricksterDialogue = Playlist((MxU32*) g_bricksterDialogue, sizeOfArray(g_bricksterDialogue), Playlist::e_loop); memset(m_letters, 0, sizeof(m_letters)); } From 115343f6e52bd45a6bb318269e4d88bda708aefa Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 28 Oct 2024 11:04:08 -0700 Subject: [PATCH 07/17] Implement/match PizzeriaState::NextAction (#1125) * Implement/match PizzeriaState::NextAction * Name globals * Refactor globals into class statics * Remove TODO --- LEGO1/lego/legoomni/include/pizza.h | 12 +++++++ LEGO1/lego/legoomni/include/pizzeria.h | 13 ++++--- LEGO1/lego/legoomni/src/actors/pizza.cpp | 20 +++++------ LEGO1/lego/legoomni/src/actors/pizzeria.cpp | 38 ++++++++++++--------- 4 files changed, 53 insertions(+), 30 deletions(-) diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index 961d5923..629020cf 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -146,6 +146,18 @@ class PizzaMissionState : public LegoState { undefined4 m_unk0x0c; // 0x0c Mission m_missions[5]; // 0x10 MxU32 m_unk0xb0; // 0xb0 + + static IsleScript::Script g_pepperActions[]; + static IsleScript::Script g_mamaActions[]; + static IsleScript::Script g_papaActions[]; + static IsleScript::Script g_nickActions[]; + static IsleScript::Script g_lauraActions[]; + + static MxLong g_pepperFinishTimes[]; + static MxLong g_mamaFinishTimes[]; + static MxLong g_papaFinishTimes[]; + static MxLong g_nickFinishTimes[]; + static MxLong g_lauraFinishTimes[]; }; // VTABLE: LEGO1 0x100d7380 diff --git a/LEGO1/lego/legoomni/include/pizzeria.h b/LEGO1/lego/legoomni/include/pizzeria.h index 69ea1b9d..52bb9827 100644 --- a/LEGO1/lego/legoomni/include/pizzeria.h +++ b/LEGO1/lego/legoomni/include/pizzeria.h @@ -1,6 +1,7 @@ #ifndef PIZZERIA_H #define PIZZERIA_H +#include "actionsfwd.h" #include "decomp.h" #include "isleactor.h" #include "legostate.h" @@ -32,12 +33,16 @@ class PizzeriaState : public LegoState { // PizzeriaState::`scalar deleting destructor' MxS16 FUN_10017d50(); - MxU32 FUN_10017d70(); + MxU32 NextAction(); - // TODO: Most likely getters/setters are not used according to BETA. + Playlist m_unk0x08[5]; // 0x08 + MxS32 m_unk0x44[5]; // 0x44 - Playlist m_unk0x08[5]; // 0x08 - undefined4 m_unk0x44[5]; // 0x44 + static IsleScript::Script g_pepperActions[]; + static IsleScript::Script g_mamaActions[]; + static IsleScript::Script g_papaActions[]; + static IsleScript::Script g_nickActions[]; + static IsleScript::Script g_lauraActions[]; }; // VTABLE: LEGO1 0x100d5520 diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index 490068d3..82589946 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -25,7 +25,7 @@ DECOMP_SIZE_ASSERT(PizzaMissionState::Mission, 0x20) extern MxU32 g_isleFlags; // GLOBAL: LEGO1 0x100f3a80 -IsleScript::Script g_pepperActions[] = { +IsleScript::Script PizzaMissionState::g_pepperActions[] = { IsleScript::c_pnsx48pr_RunAnim, IsleScript::c_pnsx69pr_RunAnim, IsleScript::c_pns125ni_RunAnim, @@ -42,10 +42,10 @@ IsleScript::Script g_pepperActions[] = { }; // GLOBAL: LEGO1 0x100f3ab8 -MxLong g_pepperFinishTimes[] = {100000, 200000, 300000, 350000}; +MxLong PizzaMissionState::g_pepperFinishTimes[] = {100000, 200000, 300000, 350000}; // GLOBAL: LEGO1 0x100f3ac8 -IsleScript::Script g_lauraActions[] = { +IsleScript::Script PizzaMissionState::g_lauraActions[] = { IsleScript::c_pns096pr_RunAnim, IsleScript::c_pns097pr_RunAnim, IsleScript::c_pns098pr_RunAnim, @@ -62,10 +62,10 @@ IsleScript::Script g_lauraActions[] = { }; // GLOBAL: LEGO1 0x100f3b00 -MxLong g_lauraFinishTimes[] = {100000, 200000, 300000, 350000}; +MxLong PizzaMissionState::g_lauraFinishTimes[] = {100000, 200000, 300000, 350000}; // GLOBAL: LEGO1 0x100f3b10 -IsleScript::Script g_nickActions[] = { +IsleScript::Script PizzaMissionState::g_nickActions[] = { IsleScript::c_pns042bm_RunAnim, IsleScript::c_pns043en_RunAnim, IsleScript::c_pns045p1_RunAnim, @@ -82,10 +82,10 @@ IsleScript::Script g_nickActions[] = { }; // GLOBAL: LEGO1 0x100f3b48 -MxLong g_nickFinishTimes[] = {100000, 200000, 300000, 350000}; +MxLong PizzaMissionState::g_nickFinishTimes[] = {100000, 200000, 300000, 350000}; // GLOBAL: LEGO1 0x100f3b58 -IsleScript::Script g_mamaActions[] = { +IsleScript::Script PizzaMissionState::g_mamaActions[] = { IsleScript::c_pns022pr_RunAnim, IsleScript::c_pns021dl_RunAnim, IsleScript::c_pns018rd_RunAnim, @@ -102,10 +102,10 @@ IsleScript::Script g_mamaActions[] = { }; // GLOBAL: LEGO1 0x100f3b90 -MxLong g_mamaFinishTimes[] = {100000, 200000, 300000, 350000}; +MxLong PizzaMissionState::g_mamaFinishTimes[] = {100000, 200000, 300000, 350000}; // GLOBAL: LEGO1 0x100f3ba0 -IsleScript::Script g_papaActions[] = { +IsleScript::Script PizzaMissionState::g_papaActions[] = { IsleScript::c_pns065rd_RunAnim, IsleScript::c_pns066db_RunAnim, IsleScript::c_pns067gd_RunAnim, @@ -122,7 +122,7 @@ IsleScript::Script g_papaActions[] = { }; // GLOBAL: LEGO1 0x100f3bd8 -MxLong g_papaFinishTimes[] = {100000, 200000, 300000, 350000}; +MxLong PizzaMissionState::g_papaFinishTimes[] = {100000, 200000, 300000, 350000}; // FUNCTION: LEGO1 0x10037ef0 Pizza::Pizza() diff --git a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp index 2f8e2642..a7681f87 100644 --- a/LEGO1/lego/legoomni/src/actors/pizzeria.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizzeria.cpp @@ -15,23 +15,23 @@ DECOMP_SIZE_ASSERT(Pizzeria, 0x84) DECOMP_SIZE_ASSERT(PizzeriaState, 0x58) // GLOBAL: LEGO1 0x100f0ce8 -IsleScript::Script g_unk0x100f0ce8[] = +IsleScript::Script PizzeriaState::g_pepperActions[] = {IsleScript::c_ppz107ma_RunAnim, IsleScript::c_ppz114pa_RunAnim, IsleScript::c_ppz114pa_RunAnim}; // GLOBAL: LEGO1 0x100f0cf8 -IsleScript::Script g_unk0x100f0cf8[] = +IsleScript::Script PizzeriaState::g_mamaActions[] = {IsleScript::c_ppz001pe_RunAnim, IsleScript::c_ppz006pa_RunAnim, IsleScript::c_ppz007pa_RunAnim}; // GLOBAL: LEGO1 0x100f0d08 -IsleScript::Script g_unk0x100f0d08[] = +IsleScript::Script PizzeriaState::g_papaActions[] = {IsleScript::c_ppz054ma_RunAnim, IsleScript::c_ppz055ma_RunAnim, IsleScript::c_ppz056ma_RunAnim}; // GLOBAL: LEGO1 0x100f0d18 -IsleScript::Script g_unk0x100f0d18[] = +IsleScript::Script PizzeriaState::g_nickActions[] = {IsleScript::c_ppz031ma_RunAnim, IsleScript::c_ppz035pa_RunAnim, IsleScript::c_ppz036pa_RunAnim}; // GLOBAL: LEGO1 0x100f0d28 -IsleScript::Script g_unk0x100f0d28[] = +IsleScript::Script PizzeriaState::g_lauraActions[] = {IsleScript::c_ppz075pa_RunAnim, IsleScript::c_ppz082pa_RunAnim, IsleScript::c_ppz084pa_RunAnim}; // FUNCTION: LEGO1 0x100179c0 @@ -79,7 +79,7 @@ MxLong Pizzeria::HandleClick() AnimationManager()->FUN_10061010(FALSE); Pizza* pizza = (Pizza*) CurrentWorld()->Find(*g_isleScript, IsleScript::c_Pizza_Actor); - pizza->FUN_10038220((IsleScript::Script) m_pizzeriaState->FUN_10017d70()); + pizza->FUN_10038220((IsleScript::Script) m_pizzeriaState->NextAction()); } return 1; @@ -89,25 +89,31 @@ MxLong Pizzeria::HandleClick() // FUNCTION: BETA10 0x100efd14 PizzeriaState::PizzeriaState() { - m_unk0x08[0] = Playlist((MxU32*) g_unk0x100f0ce8, sizeOfArray(g_unk0x100f0ce8), Playlist::e_once); - m_unk0x08[1] = Playlist((MxU32*) g_unk0x100f0cf8, sizeOfArray(g_unk0x100f0cf8), Playlist::e_once); - m_unk0x08[2] = Playlist((MxU32*) g_unk0x100f0d08, sizeOfArray(g_unk0x100f0d08), Playlist::e_once); - m_unk0x08[3] = Playlist((MxU32*) g_unk0x100f0d18, sizeOfArray(g_unk0x100f0d18), Playlist::e_once); - m_unk0x08[4] = Playlist((MxU32*) g_unk0x100f0d28, sizeOfArray(g_unk0x100f0d28), Playlist::e_once); + m_unk0x08[0] = Playlist((MxU32*) g_pepperActions, sizeOfArray(g_pepperActions), Playlist::e_once); + m_unk0x08[1] = Playlist((MxU32*) g_mamaActions, sizeOfArray(g_mamaActions), Playlist::e_once); + m_unk0x08[2] = Playlist((MxU32*) g_papaActions, sizeOfArray(g_papaActions), Playlist::e_once); + m_unk0x08[3] = Playlist((MxU32*) g_nickActions, sizeOfArray(g_nickActions), Playlist::e_once); + m_unk0x08[4] = Playlist((MxU32*) g_lauraActions, sizeOfArray(g_lauraActions), Playlist::e_once); memset(m_unk0x44, -1, sizeof(m_unk0x44)); } -// STUB: LEGO1 0x10017d50 +// FUNCTION: LEGO1 0x10017d50 MxS16 PizzeriaState::FUN_10017d50() { - return 0; + return m_unk0x44[GameState()->GetActorId() - 1]; } -// STUB: LEGO1 0x10017d70 +// FUNCTION: LEGO1 0x10017d70 // FUNCTION: BETA10 0x100effc0 -MxU32 PizzeriaState::FUN_10017d70() +MxU32 PizzeriaState::NextAction() { - return 0; + MxU8 actorId = GameState()->GetActorId(); + + if (m_unk0x44[actorId - 1] < 2) { + m_unk0x44[actorId - 1]++; + } + + return m_unk0x08[actorId - 1].Next(); } // FUNCTION: LEGO1 0x10017da0 From 4c0aae720b3a65a8033d53a98fd26a4bf101e267 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Fri, 1 Nov 2024 17:21:15 +0100 Subject: [PATCH 08/17] Implement `LegoCarBuild::FUN_10024890()` and others, refactor (#1126) * Commit finished code changes * Add enum data type * Refactor away GetCurrentArea, SetCurrentArea * Clean up and add FUN_10024890 * Add `SetPartObjectIdByName()` * Fix naming error * Address review comments, part 1 * Address review comments, part 2 --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/legocarbuild.h | 16 +- .../legoomni/include/legocarbuildpresenter.h | 25 +- LEGO1/lego/legoomni/include/legogamestate.h | 2 - .../lego/legoomni/include/legoinputmanager.h | 2 + .../legoomni/include/mxtransitionmanager.h | 21 +- LEGO1/lego/legoomni/src/actors/bike.cpp | 2 +- LEGO1/lego/legoomni/src/actors/helicopter.cpp | 4 +- .../lego/legoomni/src/build/legocarbuild.cpp | 363 ++++++++++++++++-- .../src/build/legocarbuildpresenter.cpp | 25 ++ LEGO1/lego/legoomni/src/common/legoutils.cpp | 1 + LEGO1/lego/legoomni/src/common/misc.cpp | 2 + .../src/common/mxtransitionmanager.cpp | 25 +- .../src/control/legocontrolmanager.cpp | 1 + .../legoomni/src/input/legoinputmanager.cpp | 1 + .../legoomni/src/video/legovideomanager.cpp | 2 +- .../legoomni/src/worlds/elevatorbottom.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/gasstation.cpp | 2 +- .../lego/legoomni/src/worlds/historybook.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/hospital.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/infocenter.cpp | 10 +- .../legoomni/src/worlds/infocenterdoor.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/isle.cpp | 4 +- LEGO1/lego/legoomni/src/worlds/jukebox.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/police.cpp | 2 +- .../legoomni/src/worlds/registrationbook.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/score.cpp | 2 +- LEGO1/library_msvc.h | 1 + LEGO1/mxgeometry/mxgeometry3d.h | 1 + LEGO1/mxgeometry/mxmatrix.h | 1 + .../omni/src/notify/mxnotificationmanager.cpp | 1 + LEGO1/realtime/orientableroi.h | 1 + LEGO1/realtime/vector.h | 9 +- 32 files changed, 445 insertions(+), 93 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index 0afb0824..a18082db 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -6,6 +6,7 @@ #include "legoworld.h" class LegoCarBuildAnimPresenter; +class LegoControlManagerNotificationParam; class LegoEventNotificationParam; class MxControlPresenter; class MxStillPresenter; @@ -21,6 +22,7 @@ class LegoVehicleBuildState : public LegoState { e_entering = 1, e_unknown2 = 2, e_cutscene = 3, + e_unknown4 = 4, e_exiting = 6 }; @@ -71,6 +73,11 @@ typedef LegoVehicleBuildState LegoJetskiBuildState; // SIZE 0x34c class LegoCarBuild : public LegoWorld { public: + enum Unknown0xf8 { + c_unknownminusone = -1, + c_unknown8 = 8 + }; + LegoCarBuild(); ~LegoCarBuild() override; @@ -117,14 +124,16 @@ class LegoCarBuild : public LegoWorld { undefined4 FUN_100244e0(MxLong p_x, MxLong p_y); undefined4 FUN_100246e0(MxLong p_x, MxLong p_y); MxS32 FUN_10024850(MxLong p_x, MxLong p_y); - undefined4 FUN_10024890(LegoEventNotificationParam* p_param); + undefined4 FUN_10024890(MxParam* p_param); undefined4 FUN_10024c20(LegoEventNotificationParam* p_param); void FUN_10024ef0(); + void FUN_10024f30(); void FUN_10024f50(); void FUN_10024f70(MxBool p_enabled); void SetPresentersEnabled(MxBool p_enabled); void TogglePresentersEnabled(); void FUN_100250e0(MxBool p_param); + void FUN_10025350(MxS32 p_param); void FUN_10025450(); undefined4 FUN_10025720(undefined4 p_param1); MxS32 FUN_10025d70(); @@ -139,7 +148,7 @@ class LegoCarBuild : public LegoWorld { // LegoCarBuild::`scalar deleting destructor' private: - undefined4 m_unk0xf8; // 0xf8 + Unknown0xf8 m_unk0xf8; // 0xf8 MxS16 m_unk0xfc; // 0xfc undefined m_unk0xfe[2]; // 0xfe MxS32 m_unk0x100; // 0x100 @@ -197,7 +206,8 @@ class LegoCarBuild : public LegoWorld { // variable name verified by BETA10 0x1006b219 LegoVehicleBuildState* m_buildState; // 0x32c - undefined4 m_unk0x330; // 0x330 + // variable name verified by BETA10 0x1006d742 + undefined4 m_carId; // 0x330 // variable name verified by BETA10 0x1006cba7 LegoGameState::Area m_destLocation; // 0x334 diff --git a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h index b1233ada..2e61b1e5 100644 --- a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h +++ b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h @@ -21,7 +21,7 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { { m_name = NULL; m_wiredName = NULL; - m_unk0x08 = 0; + m_objectId = 0; } // variable name verified by BETA10 0x10071b56 @@ -30,7 +30,8 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { // variable name verified by BETA10 0x100719f0 LegoChar* m_wiredName; // 0x04 - undefined2 m_unk0x08; // 0x08 + // variable name guessed based on the setter at LEGO1 0x0x10079dc0 and its use in LEGO1 0x10024890 + MxS16 m_objectId; // 0x08 }; LegoCarBuildAnimPresenter(); @@ -77,15 +78,33 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { MxBool StringEqualsShelf(const LegoChar* p_string); MxBool StringEndsOnY(const LegoChar* p_string); MxBool StringEndsOnZero(const LegoChar* p_string); + const LegoChar* GetWiredNameByPartName(const LegoChar* p_name); + void SetPartObjectIdByName(const LegoChar* p_name, MxS16 p_objectId); // FUNCTION: BETA10 0x10070180 void SetUnknown0xbc(undefined2 p_unk0xbc) { m_unk0xbc = p_unk0xbc; } + // FUNCTION: BETA10 0x100703b0 + MxMatrix& GetUnknown0xe0() { return m_unk0xe0; } + MxBool StringEndsOnW(LegoChar* p_param); MxBool StringEndsOnYOrN(const LegoChar* p_string); const BoundingSphere& FUN_10079e20(); + // FUNCTION: BETA10 0x100703e0 + const LegoChar* GetWiredNameOfLastPlacedPart() { return m_parts[m_placedPartCount].m_wiredName; } + + MxS16 GetNumberOfParts() { return m_numberOfParts; } + MxS16 GetPlacedPartCount() { return m_placedPartCount; } + + // FUNCTION: BETA10 0x10070270 + MxBool AllPartsPlaced() + { + // this function differs in BETA10 + return m_placedPartCount == m_numberOfParts; + } + // SYNTHETIC: LEGO1 0x10078660 // LegoCarBuildAnimPresenter::`scalar deleting destructor' @@ -118,8 +137,6 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { // name verified by BETA10 0x10070d63 LegoChar* m_mainSourceId; // 0x14c - - friend class LegoCarBuild; }; #endif // LEGOCARBUILDPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 5e818cc7..dc26f8c3 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -172,13 +172,11 @@ class LegoGameState { Act GetCurrentAct() { return m_currentAct; } Act GetLoadedAct() { return m_loadedAct; } - Area GetCurrentArea() { return m_currentArea; } Area GetPreviousArea() { return m_previousArea; } Area GetUnknown0x42c() { return m_unk0x42c; } History* GetHistory() { return &m_history; } void SetDirty(MxBool p_isDirty) { m_isDirty = p_isDirty; } - void SetCurrentArea(Area p_currentArea) { m_currentArea = p_currentArea; } void SetPreviousArea(Area p_previousArea) { m_previousArea = p_previousArea; } void SetActorId(MxU8 p_actorId) { m_actorId = p_actorId; } void SetUnknown0x42c(Area p_unk0x42c) { m_unk0x42c = p_unk0x42c; } diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 859d1a64..8f2b0693 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -121,7 +121,9 @@ class LegoInputManager : public MxPresenter { // FUNCTION: BETA10 0x10031ba0 LegoControlManager* GetControlManager() { return m_controlManager; } + // FUNCTION: BETA10 0x10017870 LegoWorld* GetWorld() { return m_world; } + LegoCameraController* GetCamera() { return m_camera; } void ProcessEvents(); diff --git a/LEGO1/lego/legoomni/include/mxtransitionmanager.h b/LEGO1/lego/legoomni/include/mxtransitionmanager.h index 0af65db5..178b114a 100644 --- a/LEGO1/lego/legoomni/include/mxtransitionmanager.h +++ b/LEGO1/lego/legoomni/include/mxtransitionmanager.h @@ -34,7 +34,7 @@ class MxTransitionManager : public MxCore { virtual MxResult GetDDrawSurfaceFromVideoManager(); // vtable+0x14 enum TransitionType { - e_notTransitioning = 0, + e_idle = 0, // name verified by BETA10 0x100ec4e6 e_noAnimation, e_dissolve, e_mosaic, @@ -45,7 +45,7 @@ class MxTransitionManager : public MxCore { MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim); - TransitionType GetTransitionType() { return m_transitionType; } + TransitionType GetTransitionType() { return m_mode; } // SYNTHETIC: LEGO1 0x1004b9e0 // MxTransitionManager::`scalar deleting destructor' @@ -68,13 +68,16 @@ class MxTransitionManager : public MxCore { FlagBitfield m_copyFlags; // 0x20 undefined4 m_unk0x24; // 0x24 FlagBitfield m_unk0x28; // 0x28 - TransitionType m_transitionType; // 0x2c - LPDIRECTDRAWSURFACE m_ddSurface; // 0x30 - MxU16 m_animationTimer; // 0x34 - MxU16 m_columnOrder[640]; // 0x36 - MxU16 m_randomShift[480]; // 0x536 - MxULong m_systemTime; // 0x8f8 - MxS32 m_animationSpeed; // 0x8fc + + // name verified by BETA10 0x100ec4e6 + TransitionType m_mode; // 0x2c + + LPDIRECTDRAWSURFACE m_ddSurface; // 0x30 + MxU16 m_animationTimer; // 0x34 + MxU16 m_columnOrder[640]; // 0x36 + MxU16 m_randomShift[480]; // 0x536 + MxULong m_systemTime; // 0x8f8 + MxS32 m_animationSpeed; // 0x8fc }; #endif // MXTRANSITIONMANAGER_H diff --git a/LEGO1/lego/legoomni/src/actors/bike.cpp b/LEGO1/lego/legoomni/src/actors/bike.cpp index 0c5420be..4793a2a2 100644 --- a/LEGO1/lego/legoomni/src/actors/bike.cpp +++ b/LEGO1/lego/legoomni/src/actors/bike.cpp @@ -40,7 +40,7 @@ MxResult Bike::Create(MxDSAction& p_dsAction) void Bike::Exit() { IslePathActor::Exit(); - GameState()->SetCurrentArea(LegoGameState::Area::e_bike); + GameState()->m_currentArea = LegoGameState::Area::e_bike; RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_BikeDashboard_Bitmap); RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_BikeArms_Ctl); RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_BikeHorn_Ctl); diff --git a/LEGO1/lego/legoomni/src/actors/helicopter.cpp b/LEGO1/lego/legoomni/src/actors/helicopter.cpp index 1626f7be..3aff5575 100644 --- a/LEGO1/lego/legoomni/src/actors/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/actors/helicopter.cpp @@ -76,7 +76,7 @@ void Helicopter::Exit() IslePathActor::Exit(); if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { - GameState()->SetCurrentArea(LegoGameState::e_copter); + GameState()->m_currentArea = LegoGameState::e_copter; if (UserActor() && UserActor()->IsA("IslePathActor")) { ((IslePathActor*) UserActor()) ->SpawnPlayer( @@ -180,7 +180,7 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) break; } Exit(); - GameState()->SetCurrentArea(LegoGameState::e_unk66); + GameState()->m_currentArea = LegoGameState::e_unk66; ret = 1; break; case IsleScript::c_Helicopter_TakeOff_Ctl: { diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 48e6bb03..d03e4f09 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -1,8 +1,11 @@ #include "legocarbuild.h" +#include "copter_actions.h" #include "dunebuggy.h" +#include "dunecar_actions.h" #include "helicopter.h" #include "jetski.h" +#include "jetski_actions.h" #include "jukebox_actions.h" #include "legocarbuildpresenter.h" #include "legocontrolmanager.h" @@ -21,11 +24,19 @@ #include "mxticklemanager.h" #include "mxtransitionmanager.h" #include "racecar.h" +#include "racecar_actions.h" #include "scripts.h" #include #include +// Names and values verified by BETA10 0x1006d742. +// Note that these were probably hard-coded numbers in the original. +#define Helicopter_Actor CopterScript::c_Helicopter_Actor +#define DuneBugy_Actor DunecarScript::c_DuneBugy_Actor +#define Jetski_Actor JetskiScript::c_Jetski_Actor +#define RaceCar_Actor RacecarScript::c_RaceCar_Actor + DECOMP_SIZE_ASSERT(LegoCarBuild, 0x34c) DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50) @@ -44,7 +55,7 @@ LegoCarBuild::LegoCarBuild() { m_unk0x100 = 0; m_unk0x110 = 0; - m_unk0xf8 = 0xffffffff; + m_unk0xf8 = c_unknownminusone; m_unk0x2d4 = FALSE; m_unk0x258 = 0; m_ColorBook_Bitmap = NULL; @@ -87,12 +98,27 @@ MxBool LegoCarBuild::VTable0x5c() return TRUE; } -// STUB: LEGO1 0x10022a80 -// STUB: BETA10 0x1006aea3 +// FUNCTION: LEGO1 0x10022a80 +// FUNCTION: BETA10 0x1006aea3 LegoCarBuild::~LegoCarBuild() { - // TODO - // ... + m_unk0x100 = 0; + m_unk0x110 = NULL; + + if (m_unk0x258) { + m_unk0x258->SetUnknown0xbc(0); + m_unk0x258->SetTickleState(MxPresenter::e_idle); + m_unk0x258 = NULL; + } + + ControlManager()->Unregister(this); + TickleManager()->UnregisterClient(this); + + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + + InputManager()->UnRegister(this); NotificationManager()->Unregister(this); } @@ -116,23 +142,23 @@ MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) if (m_atomId == *g_copterScript) { buildStateClassName = "LegoCopterBuildState"; - GameState()->SetCurrentArea(LegoGameState::e_copterbuild); - m_unk0x330 = 1; + GameState()->m_currentArea = LegoGameState::e_copterbuild; + m_carId = Helicopter_Actor; } else if (m_atomId == *g_dunecarScript) { buildStateClassName = "LegoDuneCarBuildState"; - GameState()->SetCurrentArea(LegoGameState::e_dunecarbuild); - m_unk0x330 = 2; + GameState()->m_currentArea = LegoGameState::e_dunecarbuild; + m_carId = DuneBugy_Actor; } else if (m_atomId == *g_jetskiScript) { buildStateClassName = "LegoJetskiBuildState"; - GameState()->SetCurrentArea(LegoGameState::e_jetskibuild); - m_unk0x330 = 3; + GameState()->m_currentArea = LegoGameState::e_jetskibuild; + m_carId = Jetski_Actor; } else if (m_atomId == *g_racecarScript) { buildStateClassName = "LegoRaceCarBuildState"; - GameState()->SetCurrentArea(LegoGameState::e_racecarbuild); - m_unk0x330 = 4; + GameState()->m_currentArea = LegoGameState::e_racecarbuild; + m_carId = Helicopter_Actor; } LegoGameState* gameState = GameState(); @@ -409,7 +435,7 @@ MxResult LegoCarBuild::Tickle() return SUCCESS; } - if (m_unk0xf8 == 8) { + if (m_unk0xf8 == c_unknown8) { if (m_unk0xfc == 1) { FUN_10024f50(); } @@ -429,7 +455,7 @@ MxResult LegoCarBuild::Tickle() DWORD time = timeGetTime(); DWORD dTime = (time - m_unk0x10c) / 100; - if (m_unk0x330 == 4) { + if (m_carId == Helicopter_Actor) { switch (m_unk0x10a) { // TODO: Work out constants case 500: @@ -452,7 +478,7 @@ MxResult LegoCarBuild::Tickle() return SUCCESS; } } - else if (m_unk0x330 == 3) { + else if (m_carId == Jetski_Actor) { switch (m_unk0x10a) { case 500: LEGOCARBUILD_TICKLE_CASE(291, 291, 311, "Exit_Ctl") @@ -473,7 +499,7 @@ MxResult LegoCarBuild::Tickle() // return SUCCESS; } } - else if (m_unk0x330 == 2) { + else if (m_carId == DuneBugy_Actor) { switch (m_unk0x10a) { case 500: LEGOCARBUILD_TICKLE_CASE(155, 155, 175, "Exit_Ctl") @@ -490,7 +516,7 @@ MxResult LegoCarBuild::Tickle() return SUCCESS; } } - else if (m_unk0x330 == 1) { + else if (m_carId == Helicopter_Actor) { switch (m_unk0x10a) { case 500: LEGOCARBUILD_TICKLE_CASE(185, 185, 205, "Exit_Ctl") @@ -575,7 +601,7 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) break; case c_notificationControl: - result = FUN_10024890((LegoEventNotificationParam*) &p_param); + result = FUN_10024890(&p_param); if (result == 1) { m_unk0x109 = 0; @@ -624,7 +650,7 @@ void LegoCarBuild::ReadyWorld() InitPresenters(); if (BackgroundAudioManager()->GetEnabled()) { - InvokeAction(Extra::ActionType::e_start, *g_jukeboxScript, FUN_10025ee0(m_unk0x330), NULL); + InvokeAction(Extra::ActionType::e_start, *g_jukeboxScript, FUN_10025ee0(m_carId), NULL); m_buildState->m_animationState = LegoVehicleBuildState::e_unknown2; NotificationManager()->Send(this, MxNotificationParam()); } @@ -636,8 +662,8 @@ void LegoCarBuild::ReadyWorld() // FUNCTION: LEGO1 0x100243a0 void LegoCarBuild::FUN_100243a0() { - switch (m_unk0x330) { - case 1: + switch (m_carId) { + case Helicopter_Actor: if (GameState()->GetCurrentAct() == LegoGameState::Act::e_act2) { m_destLocation = LegoGameState::Area::e_act3script; TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); @@ -648,15 +674,15 @@ void LegoCarBuild::FUN_100243a0() TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); break; } - case 2: + case DuneBugy_Actor: m_destLocation = LegoGameState::Area::e_garadoor; TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); break; - case 3: + case Jetski_Actor: m_destLocation = LegoGameState::Area::e_unk17; TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); break; - case 4: + case RaceCar_Actor: m_destLocation = LegoGameState::Area::e_unk20; TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); } @@ -771,14 +797,207 @@ MxS32 LegoCarBuild::FUN_10024850(MxLong p_x, MxLong p_y) return result; } -// STUB: LEGO1 0x10024890 -// STUB: BETA10 0x1006d512 -undefined4 LegoCarBuild::FUN_10024890(LegoEventNotificationParam* p_param) +#ifdef NDEBUG + +// FUNCTION: LEGO1 0x10024890 +undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) { - // TODO - return 0; + undefined4 result = 0; + LegoControlManagerNotificationParam* param = (LegoControlManagerNotificationParam*) p_param; + assert(m_buildState); + + if (param->m_unk0x28) { + switch (param->m_clickedObjectId) { + // The enum values are all identical between CopterScript, DunecarScript, JetskiScript, and RacecarScript + case CopterScript::c_Info_Ctl: + if (m_buildState->m_animationState != LegoVehicleBuildState::e_unknown4 && + m_buildState->m_animationState != LegoVehicleBuildState::e_unknown2 && + m_buildState->m_animationState != LegoVehicleBuildState::e_exiting && + GameState()->GetCurrentAct() != LegoGameState::e_act2) { + if (m_unk0x108 > 0) { + DeleteObjects(&m_atomId, 500, 510); + } + + m_unk0x258->SetUnknown0xbc(0); + m_destLocation = LegoGameState::e_infomain; + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + result = 1; + } + + break; + case CopterScript::c_Exit_Ctl: + if (m_buildState->m_animationState != LegoVehicleBuildState::e_exiting && + m_buildState->m_animationState != LegoVehicleBuildState::e_unknown4) { + if (m_unk0x108 > 0) { + DeleteObjects(&m_atomId, 500, 510); + } + + m_unk0x258->SetUnknown0xbc(0); + + if (GameState()->GetCurrentAct() == LegoGameState::e_act2) { + FUN_100243a0(); + } + else if (m_unk0x258->AllPartsPlaced() || m_buildState->m_unk0x4d) { + m_buildState->m_unk0x4d = TRUE; + InvokeAction(Extra::e_start, m_atomId, m_carId, NULL); + + NotificationManager()->Send(this, MxNotificationParam()); + + m_buildState->m_animationState = LegoVehicleBuildState::e_unknown4; + } + else { + FUN_10025720(4); + m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; + } + + result = 1; + } + break; + case CopterScript::c_ShelfUp_Ctl: + FUN_10024f30(); + m_Shelf_Sound->Enable(FALSE); + m_Shelf_Sound->Enable(TRUE); + result = 1; + break; + case CopterScript::c_Platform_Ctl: + FUN_10024f50(); + m_unk0xf8 = c_unknown8; + m_unk0xfc = param->m_unk0x28; + result = 1; + break; + default: + if ((m_Decals_Ctl && m_Decals_Ctl->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl1 && m_Decals_Ctl1->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl2 && m_Decals_Ctl2->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl3 && m_Decals_Ctl3->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl4 && m_Decals_Ctl4->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl5 && m_Decals_Ctl5->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl6 && m_Decals_Ctl6->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl7 && m_Decals_Ctl7->GetAction()->GetObjectId() == param->m_clickedObjectId)) { + m_unk0x258->SetPartObjectIdByName(m_unk0x110->GetName(), param->m_clickedObjectId); + m_Decal_Sound->Enable(FALSE); + m_Decal_Sound->Enable(TRUE); + } + else { + FUN_10025350(param->m_clickedObjectId); + } + + result = 1; + } + } + else { + m_unk0xf8 = c_unknownminusone; + m_unk0xfc = -1; + } + + // It is a bit unexpected that LEGO1 and BETA10 match so well with the `return 1` + // and ignoring the `result` variable, but the match is hard to argue with + return 1; } +#else + +// FUNCTION: BETA10 0x1006d512 +undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) +{ + undefined4 result = 0; + LegoControlManagerNotificationParam* param = (LegoControlManagerNotificationParam*) p_param; + assert(m_buildState); + + if (param->m_unk0x28) { + switch (param->m_clickedObjectId) { + case CopterScript::c_Info_Ctl: + m_unk0x258->SetUnknown0xbc(0); + m_destLocation = LegoGameState::e_infomain; + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + result = 1; + break; + case CopterScript::c_Exit_Ctl: + if (m_buildState->m_animationState != LegoVehicleBuildState::e_exiting) { + m_unk0x258->SetUnknown0xbc(0); + + if (m_unk0x258->AllPartsPlaced() || m_buildState->m_unk0x4d) { + m_buildState->m_unk0x4d = TRUE; + + // GameState()->GetCurrentAct() returns an MxS16 in BETA10 + if (GameState()->GetCurrentAct() == 0) { + InvokeAction(Extra::e_start, m_atomId, m_carId, NULL); + + NotificationManager()->Send(this, MxNotificationParam()); + + assert(m_buildState); + m_buildState->m_animationState = LegoVehicleBuildState::e_unknown4; + } + + else { + FUN_10025720(5); + m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; + } + } + else { + FUN_10025720(4); + m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; + } + + switch (GameState()->m_currentArea) { + case LegoGameState::e_copterbuild: + assert(m_carId == Helicopter_Actor); + break; + case LegoGameState::e_dunecarbuild: + assert(m_carId == DuneBugy_Actor); + break; + case LegoGameState::e_jetskibuild: + assert(m_carId == Jetski_Actor); + break; + case LegoGameState::e_racecarbuild: + assert(m_carId == RaceCar_Actor); + break; + } + + result = 1; + } + break; + case CopterScript::c_ShelfUp_Ctl: + FUN_10024f30(); + m_Shelf_Sound->Enable(FALSE); + m_Shelf_Sound->Enable(TRUE); + result = 1; + break; + case CopterScript::c_Platform_Ctl: + FUN_10024f50(); + m_unk0xf8 = c_unknown8; + m_unk0xfc = param->m_unk0x28; + result = 1; + break; + default: + if ((m_Decals_Ctl && m_Decals_Ctl->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl1 && m_Decals_Ctl1->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl2 && m_Decals_Ctl2->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl3 && m_Decals_Ctl3->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl4 && m_Decals_Ctl4->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl5 && m_Decals_Ctl5->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl6 && m_Decals_Ctl6->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl7 && m_Decals_Ctl7->GetAction()->GetObjectId() == param->m_clickedObjectId)) { + m_unk0x258->SetPartObjectIdByName(m_unk0x110->GetName(), param->m_clickedObjectId); + m_Decal_Sound->Enable(FALSE); + m_Decal_Sound->Enable(TRUE); + } + else { + FUN_10025350(param->m_clickedObjectId); + } + result = 1; + } + } + else { + m_unk0xf8 = c_unknownminusone; + m_unk0xfc = -1; + } + + return 1; +} + +#endif + // FUNCTION: LEGO1 0x10024c20 // FUNCTION: BETA10 0x1006db21 undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) @@ -788,7 +1007,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) switch (m_buildState->m_animationState) { case 4: - entity = (LegoEntity*) Find(m_atomId, m_unk0x330); + entity = (LegoEntity*) Find(m_atomId, m_carId); if (entity && entity->GetROI()) { @@ -799,7 +1018,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) Act1State* gameState = (Act1State*) GameState()->GetState("Act1State"); - switch (GameState()->GetCurrentArea()) { + switch (GameState()->m_currentArea) { case LegoGameState::e_copterbuild: if (gameState->m_helicopter) { delete gameState->m_helicopter; @@ -837,7 +1056,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) assert(destWorld); m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; - if (m_unk0x258->m_numberOfParts != m_unk0x258->m_placedPartCount) { + if (m_unk0x258->AllPartsPlaced()) { FUN_100243a0(); } else { @@ -852,17 +1071,17 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) case 2: MxU32 jukeboxScript; - switch (m_unk0x330) { - case 1: + switch (m_carId) { + case Helicopter_Actor: jukeboxScript = JukeboxScript::c_HelicopterBuild_Music; break; - case 2: + case DuneBugy_Actor: jukeboxScript = JukeboxScript::c_DuneCarBuild_Music; break; - case 3: + case Jetski_Actor: jukeboxScript = JukeboxScript::c_JetskiBuild_Music; break; - case 4: + case RaceCar_Actor: jukeboxScript = JukeboxScript::c_RaceCarBuild_Music; } @@ -893,6 +1112,14 @@ void LegoCarBuild::FUN_10024ef0() FUN_10015820(FALSE, 7); } +// FUNCTION: LEGO1 0x10024f30 +// FUNCTION: BETA10 0x1006dfa0 +void LegoCarBuild::FUN_10024f30() +{ + FUN_10022f30(); + m_unk0x258->SetUnknown0xbc(2); +} + // FUNCTION: LEGO1 0x10024f50 // FUNCTION: BETA10 0x1006dfce void LegoCarBuild::FUN_10024f50() @@ -973,13 +1200,64 @@ void LegoCarBuild::FUN_100250e0(MxBool p_enabled) } } -// STUB: LEGO1 0x10025450 -// STUB: BETA10 0x1006e599 -void LegoCarBuild::FUN_10025450() +// STUB: LEGO1 0x10025350 +// STUB: BETA10 0x1006e3c0 +void LegoCarBuild::FUN_10025350(MxS32 p_param) { // TODO } +// FUNCTION: LEGO1 0x10025450 +// FUNCTION: BETA10 0x1006e599 +void LegoCarBuild::FUN_10025450() +{ + m_unk0x12c = m_unk0x110->GetLocal2World(); + m_unk0x1c0 = m_unk0x12c; + + Vector3 lastColumnOfUnk0x1c0(m_unk0x1c0[3]); + lastColumnOfUnk0x1c0 = Vector3(m_unk0x258->GetUnknown0xe0()[3]); + + // This looks odd, but it improves the LEGO1 match while breaking the BETA10 match. + // I don't know whether this is due to compiler entropy. + // Feel free to replace unk0x178 -> m_unk0x178 and remove this variable if it improves the LEGO1 match + // in the future. + MxMatrix* unk0x178 = &m_unk0x178; + *unk0x178 = m_unk0x12c; + + if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) { + m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition()); + + if (!m_unk0x2d4) { + m_unk0x2bc = m_unk0x2a4; + + m_unk0x208 = m_unk0x12c; + m_unk0x2a4[0] += m_unk0x1c0[3][0] - m_unk0x208[3][0]; + m_unk0x2a4[1] += m_unk0x1c0[3][1] - m_unk0x208[3][1]; + m_unk0x2a4[2] += m_unk0x1c0[3][2] - m_unk0x208[3][2]; + } + + *unk0x178 = m_unk0x1c0; + } + else { + const LegoChar* wiredName; + + if (!m_unk0x258->FUN_10079c30(m_unk0x110->GetName())) { + wiredName = m_unk0x258->GetWiredNameByPartName(m_unk0x110->GetName()); + } + else { + wiredName = m_unk0x258->GetWiredNameOfLastPlacedPart(); + } + + LegoROI* parentROI = (LegoROI*) m_unk0x110->GetParentROI(); + m_unk0x208 = parentROI->FindChildROI(wiredName, parentROI)->GetLocal2World(); + m_unk0x2bc = Vector4(parentROI->FindChildROI(wiredName, parentROI)->GetWorldPosition()); + m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition()); + + m_unk0x2a4[2] += (m_unk0x1c0[3][2] - m_unk0x12c[3][2]); + m_unk0x178[3][2] = m_unk0x1c0[3][2]; + } +} + // FUNCTION: LEGO1 0x100256c0 // FUNCTION: BETA10 0x1006e96c void LegoCarBuild::Enable(MxBool p_enable) @@ -999,6 +1277,7 @@ void LegoCarBuild::Enable(MxBool p_enable) } // STUB: LEGO1 0x10025720 +// STUB: BETA10 0x1006e9df undefined4 LegoCarBuild::FUN_10025720(undefined4 p_param1) { // TODO @@ -1057,7 +1336,7 @@ void LegoCarBuild::FUN_10025e40() MxBool LegoCarBuild::Escape() { BackgroundAudioManager()->Init(); - MxS32 targetEntityId = FUN_10025ee0(m_unk0x330); + MxS32 targetEntityId = FUN_10025ee0(m_carId); InvokeAction(Extra::ActionType::e_stop, *g_jukeboxScript, targetEntityId, NULL); DeleteObjects(&m_atomId, 500, 999); diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp index 28cfbc53..546aac67 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp @@ -627,6 +627,31 @@ MxBool LegoCarBuildAnimPresenter::StringEndsOnZero(const LegoChar* p_string) return (p_string[strlen(p_string) - 2] != '0'); } +// FUNCTION: LEGO1 0x10079d60 +// FUNCTION: BETA10 0x1007284c +const LegoChar* LegoCarBuildAnimPresenter::GetWiredNameByPartName(const LegoChar* p_name) +{ + for (MxS16 i = 0; i < m_numberOfParts; i++) { + if (strcmpi(p_name, m_parts[i].m_name) == 0) { + return m_parts[i].m_wiredName; + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x10079dc0 +// FUNCTION: BETA10 0x100728d1 +void LegoCarBuildAnimPresenter::SetPartObjectIdByName(const LegoChar* p_name, MxS16 p_objectId) +{ + for (MxS16 i = 0; i < m_numberOfParts; i++) { + if (strcmpi(p_name, m_parts[i].m_name) == 0) { + m_parts[i].m_objectId = p_objectId; + return; + } + } +} + // FUNCTION: LEGO1 0x10079e20 // FUNCTION: BETA10 0x10072959 const BoundingSphere& LegoCarBuildAnimPresenter::FUN_10079e20() diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index d90e655e..34248163 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -238,6 +238,7 @@ MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_enti void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender); // FUNCTION: LEGO1 0x1003e430 +// FUNCTION: BETA10 0x100d3fda void InvokeAction(Extra::ActionType p_actionId, const MxAtomId& p_pAtom, MxS32 p_targetEntityId, LegoEntity* p_sender) { MxDSAction action; diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index f9c78e5d..2acc4be2 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -188,8 +188,10 @@ void SetCurrentWorld(LegoWorld* p_world) } // FUNCTION: LEGO1 0x10015900 +// FUNCTION: BETA10 0x100e4f02 MxTransitionManager* TransitionManager() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetTransitionManager(); } diff --git a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp index bb252592..566468e5 100644 --- a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp @@ -21,7 +21,7 @@ RECT g_fullScreenRect = {0, 0, 640, 480}; MxTransitionManager::MxTransitionManager() { m_animationTimer = 0; - m_transitionType = e_notTransitioning; + m_mode = e_idle; m_ddSurface = NULL; m_waitIndicator = NULL; m_copyBuffer = NULL; @@ -47,20 +47,20 @@ MxTransitionManager::~MxTransitionManager() MxResult MxTransitionManager::GetDDrawSurfaceFromVideoManager() // vtable+0x14 { LegoVideoManager* videoManager = VideoManager(); - this->m_ddSurface = videoManager->GetDisplaySurface()->GetDirectDrawSurface2(); + m_ddSurface = videoManager->GetDisplaySurface()->GetDirectDrawSurface2(); return SUCCESS; } // FUNCTION: LEGO1 0x1004bac0 MxResult MxTransitionManager::Tickle() { - if (this->m_animationSpeed + this->m_systemTime > timeGetTime()) { + if (m_animationSpeed + m_systemTime > timeGetTime()) { return SUCCESS; } - this->m_systemTime = timeGetTime(); + m_systemTime = timeGetTime(); - switch (this->m_transitionType) { + switch (m_mode) { case e_noAnimation: NoTransition(); break; @@ -84,6 +84,7 @@ MxResult MxTransitionManager::Tickle() } // FUNCTION: LEGO1 0x1004bb70 +// FUNCTION: BETA10 0x100ec4c1 MxResult MxTransitionManager::StartTransition( TransitionType p_animationType, MxS32 p_speed, @@ -91,13 +92,15 @@ MxResult MxTransitionManager::StartTransition( MxBool p_playMusicInAnim ) { - if (this->m_transitionType == e_notTransitioning) { + assert(m_mode == e_idle); + + if (m_mode == e_idle) { if (!p_playMusicInAnim) { MxBackgroundAudioManager* backgroundAudioManager = BackgroundAudioManager(); backgroundAudioManager->Stop(); } - this->m_transitionType = p_animationType; + m_mode = p_animationType; m_copyFlags.m_bit0 = p_doCopy; @@ -110,9 +113,9 @@ MxResult MxTransitionManager::StartTransition( } MxU32 time = timeGetTime(); - this->m_systemTime = time; + m_systemTime = time; - this->m_animationSpeed = p_speed; + m_animationSpeed = p_speed; MxTickleManager* tickleManager = TickleManager(); tickleManager->RegisterClient(this, p_speed); @@ -133,8 +136,8 @@ MxResult MxTransitionManager::StartTransition( // FUNCTION: LEGO1 0x1004bc30 void MxTransitionManager::EndTransition(MxBool p_notifyWorld) { - if (m_transitionType != e_notTransitioning) { - m_transitionType = e_notTransitioning; + if (m_mode != e_idle) { + m_mode = e_idle; m_copyFlags.m_bit0 = FALSE; diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp index b8125c50..f54fb548 100644 --- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -45,6 +45,7 @@ void LegoControlManager::Register(MxCore* p_listener) } // FUNCTION: LEGO1 0x10028ea0 +// FUNCTION: BETA10 0x1007c330 void LegoControlManager::Unregister(MxCore* p_listener) { LegoNotifyListCursor cursor(&m_notifyList); diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index 5383d39c..f546b2bf 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -339,6 +339,7 @@ void LegoInputManager::SetWorld(LegoWorld* p_world) } // FUNCTION: LEGO1 0x1005c730 +// FUNCTION: BETA10 0x100896dc void LegoInputManager::ClearWorld() { m_world = NULL; diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 9a41de96..5d9fbf1d 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -285,7 +285,7 @@ void LegoVideoManager::ToggleFPS(MxBool p_visible) MxResult LegoVideoManager::Tickle() { if (m_unk0x554 && !m_videoParam.Flags().GetFlipSurfaces() && - TransitionManager()->GetTransitionType() == MxTransitionManager::e_notTransitioning) { + TransitionManager()->GetTransitionType() == MxTransitionManager::e_idle) { Sleep(30); } diff --git a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp index cfe25812..8fefddf4 100644 --- a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp @@ -45,7 +45,7 @@ MxResult ElevatorBottom::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); - GameState()->SetCurrentArea(LegoGameState::e_elevbott); + GameState()->m_currentArea = LegoGameState::e_elevbott; GameState()->StopArea(LegoGameState::e_previousArea); return result; diff --git a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp index 453b0862..bd782ed8 100644 --- a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp @@ -91,7 +91,7 @@ MxResult GasStation::Create(MxDSAction& p_dsAction) m_state->m_unk0x14.m_unk0x00 = 3; } - GameState()->SetCurrentArea(LegoGameState::e_garage); + GameState()->m_currentArea = LegoGameState::e_garage; GameState()->StopArea(LegoGameState::e_previousArea); InputManager()->Register(this); diff --git a/LEGO1/lego/legoomni/src/worlds/historybook.cpp b/LEGO1/lego/legoomni/src/worlds/historybook.cpp index 4287fe56..bec6764f 100644 --- a/LEGO1/lego/legoomni/src/worlds/historybook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/historybook.cpp @@ -39,7 +39,7 @@ MxResult HistoryBook::Create(MxDSAction& p_dsAction) InputManager()->SetCamera(NULL); InputManager()->Register(this); - GameState()->SetCurrentArea(LegoGameState::Area::e_histbook); + GameState()->m_currentArea = LegoGameState::Area::e_histbook; GameState()->StopArea(LegoGameState::Area::e_previousArea); return result; } diff --git a/LEGO1/lego/legoomni/src/worlds/hospital.cpp b/LEGO1/lego/legoomni/src/worlds/hospital.cpp index 2bf024f2..6b3c8e5a 100644 --- a/LEGO1/lego/legoomni/src/worlds/hospital.cpp +++ b/LEGO1/lego/legoomni/src/worlds/hospital.cpp @@ -96,7 +96,7 @@ MxResult Hospital::Create(MxDSAction& p_dsAction) m_hospitalState->m_unk0x08.m_unk0x00 = 3; } - GameState()->SetCurrentArea(LegoGameState::e_hospital); + GameState()->m_currentArea = LegoGameState::e_hospital; GameState()->StopArea(LegoGameState::e_previousArea); InputManager()->Register(this); diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp index 8e882e75..342d85bd 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp @@ -210,7 +210,7 @@ MxResult Infocenter::Create(MxDSAction& p_dsAction) } } - GameState()->SetCurrentArea(LegoGameState::e_infomain); + GameState()->m_currentArea = LegoGameState::e_infomain; GameState()->StopArea(LegoGameState::e_previousArea); if (m_infocenterState->GetUnknown0x74() == 4) { @@ -523,9 +523,9 @@ void Infocenter::ReadyWorld() bgRed->Enable(TRUE); if (GameState()->GetCurrentAct() == GameState()->GetLoadedAct()) { - GameState()->SetCurrentArea(LegoGameState::e_act2main); + GameState()->m_currentArea = LegoGameState::e_act2main; GameState()->StopArea(LegoGameState::e_act2main); - GameState()->SetCurrentArea(LegoGameState::e_infomain); + GameState()->m_currentArea = LegoGameState::e_infomain; } m_infocenterState->SetUnknown0x74(5); @@ -579,9 +579,9 @@ void Infocenter::ReadyWorld() bgRed->Enable(TRUE); if (GameState()->GetCurrentAct() == GameState()->GetLoadedAct()) { - GameState()->SetCurrentArea(LegoGameState::e_act3script); + GameState()->m_currentArea = LegoGameState::e_act3script; GameState()->StopArea(LegoGameState::e_act3script); - GameState()->SetCurrentArea(LegoGameState::e_infomain); + GameState()->m_currentArea = LegoGameState::e_infomain; } m_infocenterState->SetUnknown0x74(5); diff --git a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp index 4b6d7850..5f3ae04c 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp @@ -48,7 +48,7 @@ MxResult InfocenterDoor::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); - GameState()->SetCurrentArea(LegoGameState::e_infodoor); + GameState()->m_currentArea = LegoGameState::e_infodoor; GameState()->StopArea(LegoGameState::e_previousArea); return result; diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index 66e7a559..347e4b07 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -112,8 +112,8 @@ MxResult Isle::Create(MxDSAction& p_dsAction) m_destLocation = LegoGameState::e_infomain; } - if (GameState()->GetCurrentArea() == LegoGameState::e_isle) { - GameState()->SetCurrentArea(LegoGameState::e_undefined); + if (GameState()->m_currentArea == LegoGameState::e_isle) { + GameState()->m_currentArea = LegoGameState::e_undefined; } LegoGameState* gameState = GameState(); diff --git a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp index ca27142d..fe476499 100644 --- a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp +++ b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp @@ -61,7 +61,7 @@ MxResult JukeBox::Create(MxDSAction& p_dsAction) m_state->m_music = JukeBoxState::e_pasquell; } - GameState()->SetCurrentArea(LegoGameState::e_jukeboxw); + GameState()->m_currentArea = LegoGameState::e_jukeboxw; GameState()->StopArea(LegoGameState::e_previousArea); TickleManager()->RegisterClient(this, 2000); return ret; diff --git a/LEGO1/lego/legoomni/src/worlds/police.cpp b/LEGO1/lego/legoomni/src/worlds/police.cpp index cf7bb0f8..43bd67bf 100644 --- a/LEGO1/lego/legoomni/src/worlds/police.cpp +++ b/LEGO1/lego/legoomni/src/worlds/police.cpp @@ -63,7 +63,7 @@ MxResult Police::Create(MxDSAction& p_dsAction) } m_policeState = policeState; - GameState()->SetCurrentArea(LegoGameState::e_police); + GameState()->m_currentArea = LegoGameState::e_police; GameState()->StopArea(LegoGameState::e_previousArea); return ret; } diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index 234903bf..fe4ac424 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -97,7 +97,7 @@ MxResult RegistrationBook::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); InputManager()->Register(this); - GameState()->SetCurrentArea(LegoGameState::e_regbook); + GameState()->m_currentArea = LegoGameState::e_regbook; GameState()->StopArea(LegoGameState::e_previousArea); m_infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); diff --git a/LEGO1/lego/legoomni/src/worlds/score.cpp b/LEGO1/lego/legoomni/src/worlds/score.cpp index db9a24ec..3ecae676 100644 --- a/LEGO1/lego/legoomni/src/worlds/score.cpp +++ b/LEGO1/lego/legoomni/src/worlds/score.cpp @@ -63,7 +63,7 @@ MxResult Score::Create(MxDSAction& p_dsAction) LegoGameState* gameState = GameState(); ScoreState* state = (ScoreState*) gameState->GetState("ScoreState"); m_state = state ? state : (ScoreState*) gameState->CreateState("ScoreState"); - GameState()->SetCurrentArea(LegoGameState::e_infoscor); + GameState()->m_currentArea = LegoGameState::e_infoscor; GameState()->StopArea(LegoGameState::e_previousArea); } diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 49e2efbd..d4770e46 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -19,6 +19,7 @@ // _free // LIBRARY: LEGO1 0x1008b020 +// LIBRARY: BETA10 0x100f8d20 // ___CxxFrameHandler // LIBRARY: LEGO1 0x1008b24c diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 58d36198..b2f4d53a 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -78,6 +78,7 @@ class Mx4DPointFloat : public Vector4 { const float& operator[](int idx) const { return m_data[idx]; } // SYNTHETIC: LEGO1 0x10064b20 + // SYNTHETIC: BETA10 0x10070420 // Mx4DPointFloat::operator= private: diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h index 5ac9b2be..a9249225 100644 --- a/LEGO1/mxgeometry/mxmatrix.h +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -20,6 +20,7 @@ class MxMatrix : public Matrix4 { // FUNCTION: BETA10 0x10010860 float* operator[](int idx) { return m_data[idx]; } + // FUNCTION: BETA10 0x1001c670 const float* operator[](int idx) const { return m_data[idx]; } // FUNCTION: LEGO1 0x10002850 diff --git a/LEGO1/omni/src/notify/mxnotificationmanager.cpp b/LEGO1/omni/src/notify/mxnotificationmanager.cpp index dec49818..61e051f7 100644 --- a/LEGO1/omni/src/notify/mxnotificationmanager.cpp +++ b/LEGO1/omni/src/notify/mxnotificationmanager.cpp @@ -178,6 +178,7 @@ void MxNotificationManager::Register(MxCore* p_listener) } // FUNCTION: LEGO1 0x100acdf0 +// FUNCTION: BETA10 0x10126785 void MxNotificationManager::Unregister(MxCore* p_listener) { AUTOLOCK(m_lock); diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h index 5e70aa5e..8daf1f51 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -51,6 +51,7 @@ class OrientableROI : public ROI { // FUNCTION: BETA10 0x1004aa70 const float* GetWorldUp() const { return m_local2world[1]; } + // FUNCTION: BETA10 0x10070380 OrientableROI* GetParentROI() const { return m_parentROI; } void SetParentROI(OrientableROI* p_parentROI) { m_parentROI = p_parentROI; } diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index a09e62c4..8f871474 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -152,6 +152,7 @@ class Vector2 { virtual void SetVector(const Vector2* p_other) { EqualsImpl(p_other->m_data); } // vtable+0x6c // SYNTHETIC: LEGO1 0x10010be0 + // SYNTHETIC: BETA10 0x100121e0 // Vector3::operator= // SYNTHETIC: BETA10 0x1004af40 @@ -301,10 +302,14 @@ class Vector4 : public Vector3 { // FUNCTION: BETA10 0x10048780 Vector4(float* p_data) : Vector3(p_data) {} - // Hack: Some code initializes a Vector4 from a (most likely) const float* source. - // Example: LegoCarBuild::VTable0x6c + // Some code initializes a Vector4 from a `const float*` source. + // Example: `LegoCarBuild::VTable0x6c` // Vector4 however is a class that can mutate its underlying source, making // initialization with a const source fundamentally incompatible. + // BETA10 appears to have two separate constructors for Vector4 as well, + // supporting the theory that this decompilation is correct. + + // FUNCTION: BETA10 0x100701b0 Vector4(const float* p_data) : Vector3((float*) p_data) {} // Note: virtual function overloads appear in the virtual table From a14795c0c846d9ab501eb60707d0a8aa2a3d7c8f Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 1 Nov 2024 10:30:11 -0700 Subject: [PATCH 09/17] Implement/match Pizza::Tickle (#1127) --- LEGO1/lego/legoomni/include/pizza.h | 8 +++- LEGO1/lego/legoomni/src/actors/pizza.cpp | 61 +++++++++++++++++++++++- 2 files changed, 66 insertions(+), 3 deletions(-) diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index 629020cf..43fe2bfd 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -83,6 +83,12 @@ class PizzaMissionState : public LegoState { } } + // FUNCTION: BETA10 0x100ef7b0 + IsleScript::Script GetUnknownFinishAction() { return m_actions[m_numActions + 2]; } + + // FUNCTION: BETA10 0x100ef7e0 + MxLong GetTimeoutTime() { return m_finishTimes[3]; } + MxResult WriteToFile(LegoFile* p_file) { Write(p_file, m_unk0x06); @@ -205,7 +211,7 @@ class Pizza : public IsleActor { Act1State* m_act1state; // 0x88 IsleScript::Script m_unk0x8c; // 0x8c MxLong m_unk0x90; // 0x90 - undefined4 m_unk0x94; // 0x94 + MxLong m_unk0x94; // 0x94 MxBool m_unk0x98; // 0x98 }; diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index 82589946..a8337cd7 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -358,10 +358,67 @@ MxLong Pizza::HandlePathStruct(LegoPathStructNotificationParam& p_param) return 0; } -// STUB: LEGO1 0x100388a0 +// FUNCTION: LEGO1 0x100388a0 +// FUNCTION: BETA10 0x100ee2d9 MxResult Pizza::Tickle() { - // TODO + MxLong time = Timer()->GetTime(); + + if (m_unk0x90 != INT_MIN && m_unk0x94 + m_unk0x90 <= time) { + m_unk0x90 = INT_MIN; + m_skateBoard->EnableScenePresentation(FALSE); + m_skateBoard->SetUnknown0x160(FALSE); + TickleManager()->UnregisterClient(this); + } + + if (m_mission != NULL && m_mission->m_startTime != INT_MIN) { + if (m_state->m_unk0x0c == 4) { + if (time > m_mission->m_startTime + m_mission->GetTimeoutTime()) { + StopActions(); + m_mission->UpdateScore(LegoState::e_grey); + FUN_100382b0(); + BackgroundAudioManager()->LowerVolume(); + InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_Avo917In_PlayWav, NULL); + } + else if (time >= m_mission->m_startTime + 35000 && m_unk0x8c == IsleScript::c_noneIsle) { + switch (GameState()->GetActorId()) { + case LegoActor::c_pepper: + m_unk0x8c = IsleScript::c_Avo914In_PlayWav; + break; + case LegoActor::c_mama: + m_unk0x8c = IsleScript::c_Avo910In_PlayWav; + break; + case LegoActor::c_papa: + m_unk0x8c = IsleScript::c_Avo912In_PlayWav; + break; + case LegoActor::c_nick: + m_unk0x8c = IsleScript::c_Avo911In_PlayWav; + break; + case LegoActor::c_laura: + m_unk0x8c = IsleScript::c_Avo913In_PlayWav; + break; + } + + BackgroundAudioManager()->LowerVolume(); + + if (m_unk0x8c != IsleScript::c_noneIsle) { + InvokeAction(Extra::e_start, *g_isleScript, m_unk0x8c, NULL); + } + } + } + else if (m_state->m_unk0x0c == 2) { + if (Timer()->GetTime() > m_mission->m_startTime + 5000) { + m_skateBoard->SetUnknown0x160(FALSE); + m_skateBoard->EnableScenePresentation(FALSE); + TickleManager()->UnregisterClient(this); + m_mission->UpdateScore(LegoState::e_grey); + m_state->m_unk0x0c = 9; + AnimationManager()->FUN_1005f6d0(TRUE); + PlayAction(m_mission->GetUnknownFinishAction(), TRUE); + } + } + } + return SUCCESS; } From 4c95d7c8876c573b57fcc71ad8c77b699cfe301a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 1 Nov 2024 13:13:43 -0700 Subject: [PATCH 10/17] Implement/match Pizza::HandleEndAction (#1128) * Implement Pizza::HandleEndAction * Match --- LEGO1/lego/legoomni/include/isle.h | 1 + LEGO1/lego/legoomni/include/pizza.h | 8 +- LEGO1/lego/legoomni/src/actors/pizza.cpp | 157 ++++++++++++++++++++++- 3 files changed, 160 insertions(+), 6 deletions(-) diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index 5125cc3d..84aebed9 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -190,6 +190,7 @@ class Isle : public LegoWorld { virtual void VTable0x6c(LegoPathActor* p_actor); // vtable+6c void SetDestLocation(LegoGameState::Area p_destLocation) { m_destLocation = p_destLocation; } + MxBool HasHelicopter() { return m_helicopter != NULL; } void FUN_10033350(); diff --git a/LEGO1/lego/legoomni/include/pizza.h b/LEGO1/lego/legoomni/include/pizza.h index 43fe2bfd..a9457c24 100644 --- a/LEGO1/lego/legoomni/include/pizza.h +++ b/LEGO1/lego/legoomni/include/pizza.h @@ -83,6 +83,9 @@ class PizzaMissionState : public LegoState { } } + // FUNCTION: BETA10 0x100ef780 + IsleScript::Script* GetActions() { return m_actions; } + // FUNCTION: BETA10 0x100ef7b0 IsleScript::Script GetUnknownFinishAction() { return m_actions[m_numActions + 2]; } @@ -140,6 +143,9 @@ class PizzaMissionState : public LegoState { // FUNCTION: BETA10 0x100ef470 void SetUnknown0xb0(MxU32 p_unk0xb0) { m_unk0xb0 = p_unk0xb0; } + // FUNCTION: BETA10 0x100ef850 + MxU32 GetUnknown0xb0() { return m_unk0xb0; } + MxS16 GetHighScore(MxU8 p_actorId) { return GetMission(p_actorId)->m_hiScore; } // SYNTHETIC: LEGO1 0x10039350 @@ -190,7 +196,7 @@ class Pizza : public IsleActor { MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 MxLong HandleClick() override; // vtable+0x68 - MxLong HandleEndAction(MxEndActionNotificationParam&) override; // vtable+0x74 + MxLong HandleEndAction(MxEndActionNotificationParam& p_param) override; // vtable+0x74 MxLong HandlePathStruct(LegoPathStructNotificationParam& p_param) override; // vtable+0x80 void CreateState(); diff --git a/LEGO1/lego/legoomni/src/actors/pizza.cpp b/LEGO1/lego/legoomni/src/actors/pizza.cpp index a8337cd7..346153a5 100644 --- a/LEGO1/lego/legoomni/src/actors/pizza.cpp +++ b/LEGO1/lego/legoomni/src/actors/pizza.cpp @@ -4,15 +4,20 @@ #include "isle_actions.h" #include "jukebox_actions.h" #include "legoanimationmanager.h" +#include "legoeventnotificationparam.h" #include "legogamestate.h" +#include "legoinputmanager.h" #include "legopathstruct.h" #include "legoutils.h" #include "legoworld.h" #include "misc.h" +#include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" +#include "mxdebug.h" #include "mxmisc.h" #include "mxticklemanager.h" #include "mxtimer.h" +#include "mxtransitionmanager.h" #include "pizzeria.h" #include "skateboard.h" #include "sndanim_actions.h" @@ -187,6 +192,7 @@ void Pizza::FUN_10038220(IsleScript::Script p_objectId) } // FUNCTION: LEGO1 0x100382b0 +// FUNCTION: BETA10 0x100edc9b void Pizza::FUN_100382b0() { if (m_state->m_unk0x0c != 8) { @@ -209,6 +215,7 @@ void Pizza::FUN_100382b0() m_unk0x90 = INT_MIN; m_skateBoard->EnableScenePresentation(FALSE); m_skateBoard->SetUnknown0x160(FALSE); + MxTrace("Pizza mission: idle\n"); } } @@ -221,7 +228,7 @@ void Pizza::StopActions() PizzaMissionState::Mission* mission = m_mission; if (mission != NULL) { for (MxS32 i = 0; i < mission->m_numActions; i++) { - InvokeAction(Extra::e_stop, *g_isleScript, mission->m_actions[i], NULL); + InvokeAction(Extra::e_stop, *g_isleScript, mission->GetActions()[i], NULL); } } } @@ -242,6 +249,7 @@ MxLong Pizza::HandleClick() if (m_skateBoard == NULL) { m_skateBoard = (SkateBoard*) m_world->Find(m_atomId, IsleScript::c_SkateBoard_Actor); + assert(m_skateBoard); } IsleScript::Script action; @@ -287,6 +295,8 @@ MxLong Pizza::HandlePathStruct(LegoPathStructNotificationParam& p_param) else { m_mission->UpdateScore(LegoState::e_yellow); } + + MxTrace("Pizza mission: ending\n"); } else if ((p_param.GetTrigger() == LegoPathStruct::c_camAnim && ( ((p_param.GetData() == 0x24 || p_param.GetData() == 0x22) && GameState()->GetActorId() == LegoActor::c_mama) || @@ -340,6 +350,8 @@ MxLong Pizza::HandlePathStruct(LegoPathStructNotificationParam& p_param) m_state->m_unk0x0c = 5; PlayAction(action, TRUE); + + MxTrace("Pizza mission: ending\n"); } else if (p_param.GetTrigger() == LegoPathStruct::c_w) { if (p_param.GetData() == 0x15e && GameState()->GetActorId() == LegoActor::c_pepper) { @@ -373,12 +385,15 @@ MxResult Pizza::Tickle() if (m_mission != NULL && m_mission->m_startTime != INT_MIN) { if (m_state->m_unk0x0c == 4) { + assert(m_mission); + if (time > m_mission->m_startTime + m_mission->GetTimeoutTime()) { StopActions(); m_mission->UpdateScore(LegoState::e_grey); FUN_100382b0(); BackgroundAudioManager()->LowerVolume(); InvokeAction(Extra::e_start, *g_isleScript, IsleScript::c_Avo917In_PlayWav, NULL); + MxTrace("Pizza mission: timeout, stop\n"); } else if (time >= m_mission->m_startTime + 35000 && m_unk0x8c == IsleScript::c_noneIsle) { switch (GameState()->GetActorId()) { @@ -407,6 +422,8 @@ MxResult Pizza::Tickle() } } else if (m_state->m_unk0x0c == 2) { + assert(m_mission); + if (Timer()->GetTime() > m_mission->m_startTime + 5000) { m_skateBoard->SetUnknown0x160(FALSE); m_skateBoard->EnableScenePresentation(FALSE); @@ -415,6 +432,7 @@ MxResult Pizza::Tickle() m_state->m_unk0x0c = 9; AnimationManager()->FUN_1005f6d0(TRUE); PlayAction(m_mission->GetUnknownFinishAction(), TRUE); + MxTrace("Pizza mission: timeout, declining\n"); } } } @@ -422,11 +440,140 @@ MxResult Pizza::Tickle() return SUCCESS; } -// STUB: LEGO1 0x10038b10 -MxLong Pizza::HandleEndAction(MxEndActionNotificationParam&) +// FUNCTION: LEGO1 0x10038b10 +// FUNCTION: BETA10 0x100ee4f5 +MxLong Pizza::HandleEndAction(MxEndActionNotificationParam& p_param) { - // TODO - return 0; + MxLong result = 0; + MxU32 objectId = p_param.GetAction()->GetObjectId(); + + if (m_unk0x8c == objectId) { + BackgroundAudioManager()->RaiseVolume(); + return 1; + } + + switch (m_state->m_unk0x0c) { + case 1: + if (m_state->GetUnknown0xb0() == objectId) { + m_state->m_unk0x0c = 2; + m_mission->m_startTime = Timer()->GetTime(); + TickleManager()->RegisterClient(this, 200); + MxTrace("Pizza mission: proposed\n"); + } + break; + case 3: + if (m_state->GetUnknown0xb0() == objectId) { + m_mission->m_startTime = Timer()->GetTime(); + + PizzaMissionState::Mission* mission = m_mission; + for (MxS32 i = 0; i < mission->m_numActions; i++) { + InvokeAction(Extra::e_start, *g_isleScript, mission->GetActions()[i], NULL); + } + + m_state->m_unk0x0c = 4; + m_state->SetUnknown0xb0(IsleScript::c_noneIsle); + UserActor()->SetState(0); + m_skateBoard->SetUnknown0x160(TRUE); + m_world->PlaceActor(m_skateBoard, "int37", 2, 0.5, 3, 0.5); + +#ifdef COMPAT_MODE + { + LegoEventNotificationParam param(c_notificationClick, NULL, 0, 0, 0, 0); + m_skateBoard->Notify(param); + } +#else + m_skateBoard->Notify(LegoEventNotificationParam(c_notificationClick, NULL, 0, 0, 0, 0)); +#endif + + MxTrace("Pizza mission: continues\n"); + result = 1; + } + break; + case 5: + if (m_state->GetUnknown0xb0() == objectId) { + StopActions(); + + if (GameState()->GetActorId() == LegoActor::c_pepper) { + IsleScript::Script action = IsleScript::c_noneIsle; + + if (!((Isle*) CurrentWorld())->HasHelicopter()) { + switch (m_mission->m_unk0x14) { + case 1: + action = IsleScript::c_pja126br_RunAnim; + m_mission->m_unk0x14++; + m_state->m_unk0x0c = 6; + MxTrace("Pizza mission: succeeds\n"); + break; + case 2: + action = IsleScript::c_pja129br_RunAnim; + m_unk0x90 = Timer()->GetTime(); + m_unk0x94 = 500; + m_mission->m_unk0x14++; + m_state->m_unk0x0c = 6; + MxTrace("Pizza mission: succeeds\n"); + break; + case 3: + action = IsleScript::c_pja131br_RunAnim; + m_unk0x90 = Timer()->GetTime(); + m_unk0x94 = 500; + m_state->m_unk0x0c = 6; + break; + } + } + else { + action = IsleScript::c_pja132br_RunAnim; + m_unk0x90 = Timer()->GetTime(); + m_unk0x94 = 2300; + m_state->m_unk0x0c = 8; + InputManager()->DisableInputProcessing(); + InputManager()->SetUnknown336(TRUE); + MxTrace("Pizza mission: go to Act2\n"); + } + + PlayAction(action, TRUE); + } + else { + FUN_100382b0(); + m_state->m_unk0x0c = 0; + m_state->SetUnknown0xb0(IsleScript::c_noneIsle); + } + } + break; + case 6: + if (m_state->GetUnknown0xb0() == objectId) { + if (objectId == IsleScript::c_pja126br_RunAnim) { + PlayAction(IsleScript::c_pja127br_RunAnim, TRUE); + m_unk0x90 = Timer()->GetTime(); + m_unk0x94 = 700; + } + else if (objectId == IsleScript::c_pja129br_RunAnim) { + PlayAction(IsleScript::c_pja130br_RunAnim, TRUE); + } + else { + FUN_100382b0(); + m_state->m_unk0x0c = 0; + m_state->SetUnknown0xb0(IsleScript::c_noneIsle); + } + } + break; + case 8: + if (m_state->GetUnknown0xb0() == objectId) { + m_act1state->m_unk0x018 = 0; + m_state->m_unk0x0c = 0; + GameState()->m_currentArea = LegoGameState::e_isle; + TickleManager()->UnregisterClient(this); + ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_act2main); + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + } + break; + case 9: + if (m_state->GetUnknown0xb0() == objectId) { + FUN_100382b0(); + } + break; + } + + return result; } // FUNCTION: LEGO1 0x10038fe0 From 519d8c570a4976fbdfa06192297fb690fcdc0e62 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 3 Nov 2024 08:44:07 -0700 Subject: [PATCH 11/17] Implement/match remaining GasStation functions (#1129) * Implement/match remaining GasStation functions * Name variables --- LEGO1/lego/legoomni/include/gasstation.h | 20 +-- LEGO1/lego/legoomni/src/worlds/gasstation.cpp | 122 ++++++++++-------- 2 files changed, 80 insertions(+), 62 deletions(-) diff --git a/LEGO1/lego/legoomni/include/gasstation.h b/LEGO1/lego/legoomni/include/gasstation.h index 92f4593e..b53fc0f7 100644 --- a/LEGO1/lego/legoomni/include/gasstation.h +++ b/LEGO1/lego/legoomni/include/gasstation.h @@ -38,19 +38,19 @@ class GasStationState : public LegoState { // SYNTHETIC: LEGO1 0x10006290 // GasStationState::`scalar deleting destructor' - void FUN_10006430(GarageScript::Script); - void FUN_10006460(GarageScript::Script); - void FUN_10006490(); + void PlayAction(GarageScript::Script p_objectId); + void StopAction(GarageScript::Script p_objectId); + void StopActions(); // TODO: Most likely getters/setters are not used according to BETA. - undefined4 m_unk0x08[3]; // 0x08 - Unknown0x14 m_unk0x14; // 0x14 - MxS16 m_unk0x18; // 0x18 - MxS16 m_unk0x1a; // 0x1a - MxS16 m_unk0x1c; // 0x1c - MxS16 m_unk0x1e; // 0x1e - MxS16 m_unk0x20; // 0x20 + GarageScript::Script m_actions[3]; // 0x08 + Unknown0x14 m_unk0x14; // 0x14 + MxS16 m_pepperAction; // 0x18 + MxS16 m_mamaAction; // 0x1a + MxS16 m_papaAction; // 0x1c + MxS16 m_nickAction; // 0x1e + MxS16 m_lauraAction; // 0x20 }; // VTABLE: LEGO1 0x100d4650 diff --git a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp index bd782ed8..ebdf7d4a 100644 --- a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp @@ -138,7 +138,7 @@ void GasStation::ReadyWorld() switch (m_currentActorId) { case LegoActor::c_pepper: - switch (m_state->m_unk0x18) { + switch (m_state->m_pepperAction) { case 0: m_state->m_unk0x14.m_unk0x00 = 5; PlayAction(GarageScript::c_wgs002nu_RunAnim); @@ -162,14 +162,14 @@ void GasStation::ReadyWorld() break; } - if (m_state->m_unk0x18 < 5) { - m_state->m_unk0x18++; + if (m_state->m_pepperAction < 5) { + m_state->m_pepperAction++; } FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); break; case LegoActor::c_mama: - switch (m_state->m_unk0x1a) { + switch (m_state->m_mamaAction) { case 0: m_state->m_unk0x14.m_unk0x00 = 5; PlayAction(GarageScript::c_wgs006nu_RunAnim); @@ -188,14 +188,14 @@ void GasStation::ReadyWorld() break; } - if (m_state->m_unk0x1a < 5) { - m_state->m_unk0x1a++; + if (m_state->m_mamaAction < 5) { + m_state->m_mamaAction++; } FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); break; case LegoActor::c_papa: - switch (m_state->m_unk0x1c) { + switch (m_state->m_papaAction) { case 0: m_state->m_unk0x14.m_unk0x00 = 5; PlayAction(GarageScript::c_wgs012nu_RunAnim); @@ -214,14 +214,14 @@ void GasStation::ReadyWorld() break; } - if (m_state->m_unk0x1c < 5) { - m_state->m_unk0x1c++; + if (m_state->m_papaAction < 5) { + m_state->m_papaAction++; } FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); break; case LegoActor::c_nick: - switch (m_state->m_unk0x1e) { + switch (m_state->m_nickAction) { case 0: m_state->m_unk0x14.m_unk0x00 = 5; PlayAction(GarageScript::c_wgs009nu_RunAnim); @@ -240,14 +240,14 @@ void GasStation::ReadyWorld() break; } - if (m_state->m_unk0x1e < 5) { - m_state->m_unk0x1e++; + if (m_state->m_nickAction < 5) { + m_state->m_nickAction++; } FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); break; case LegoActor::c_laura: - switch (m_state->m_unk0x20) { + switch (m_state->m_lauraAction) { case 0: m_state->m_unk0x14.m_unk0x00 = 5; PlayAction(GarageScript::c_wgs020nu_RunAnim); @@ -266,8 +266,8 @@ void GasStation::ReadyWorld() break; } - if (m_state->m_unk0x20 < 5) { - m_state->m_unk0x20++; + if (m_state->m_lauraAction < 5) { + m_state->m_lauraAction++; } FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); @@ -288,7 +288,7 @@ inline void GasStation::PlayAction(GarageScript::Script p_objectId) BackgroundAudioManager()->LowerVolume(); Start(&action); - m_state->FUN_10006430(p_objectId); + m_state->PlayAction(p_objectId); } // FUNCTION: BETA10 0x10029f00 @@ -297,7 +297,7 @@ inline void GasStation::StopAction(GarageScript::Script p_objectId) if (p_objectId != GarageScript::c_noneGarage) { InvokeAction(Extra::e_stop, *g_garageScript, p_objectId, NULL); BackgroundAudioManager()->RaiseVolume(); - m_state->FUN_10006460(p_objectId); + m_state->StopAction(p_objectId); } } @@ -310,7 +310,7 @@ MxLong GasStation::HandleEndAction(MxEndActionNotificationParam& p_param) MxDSAction* action = p_param.GetAction(); if (action->GetAtomId() == m_atomId && action->GetObjectId()) { - m_state->FUN_10006460((GarageScript::Script) action->GetObjectId()); + m_state->StopAction((GarageScript::Script) action->GetObjectId()); m_unk0x106 = 0; switch (m_state->m_unk0x14.m_unk0x00) { @@ -357,7 +357,7 @@ MxLong GasStation::HandleEndAction(MxEndActionNotificationParam& p_param) MxLong GasStation::HandleKeyPress(MxS8 p_key) { if (p_key == VK_SPACE && g_unk0x100f0160 == 0 && m_unk0x106 != 0) { - m_state->FUN_10006490(); + m_state->StopActions(); return 1; } @@ -394,6 +394,7 @@ MxLong GasStation::HandleButtonDown(LegoControlManagerNotificationParam& p_param } // FUNCTION: LEGO1 0x10005b20 +// FUNCTION: BETA10 0x10029445 MxLong GasStation::HandleControl(LegoControlManagerNotificationParam& p_param) { if (p_param.GetUnknown0x28() == 1) { @@ -405,7 +406,7 @@ MxLong GasStation::HandleControl(LegoControlManagerNotificationParam& p_param) m_state->m_unk0x14.m_unk0x00 = 0; m_destLocation = LegoGameState::Area::e_garadoor; - m_state->FUN_10006490(); + m_state->StopActions(); m_radio.Stop(); BackgroundAudioManager()->Stop(); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); @@ -414,7 +415,7 @@ MxLong GasStation::HandleControl(LegoControlManagerNotificationParam& p_param) m_state->m_unk0x14.m_unk0x00 = 0; m_destLocation = LegoGameState::Area::e_infomain; - m_state->FUN_10006490(); + m_state->StopActions(); m_radio.Stop(); BackgroundAudioManager()->Stop(); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); @@ -423,7 +424,7 @@ MxLong GasStation::HandleControl(LegoControlManagerNotificationParam& p_param) m_state->m_unk0x14.m_unk0x00 = 0; m_destLocation = LegoGameState::Area::e_dunecarbuild; - m_state->FUN_10006490(); + m_state->StopActions(); m_radio.Stop(); BackgroundAudioManager()->Stop(); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); @@ -435,6 +436,7 @@ MxLong GasStation::HandleControl(LegoControlManagerNotificationParam& p_param) } // FUNCTION: LEGO1 0x10005c40 +// FUNCTION: BETA10 0x10029551 void GasStation::Enable(MxBool p_enable) { LegoWorld::Enable(p_enable); @@ -451,6 +453,7 @@ void GasStation::Enable(MxBool p_enable) } // FUNCTION: LEGO1 0x10005c90 +// FUNCTION: BETA10 0x100295c6 MxResult GasStation::Tickle() { if (!m_worldStarted) { @@ -495,64 +498,79 @@ MxResult GasStation::Tickle() MxBool GasStation::Escape() { m_radio.Stop(); - m_state->FUN_10006490(); + m_state->StopActions(); m_state->m_unk0x14.m_unk0x00 = 0; m_destLocation = LegoGameState::Area::e_infomain; return TRUE; } // FUNCTION: LEGO1 0x10005eb0 +// FUNCTION: BETA10 0x100296b8 GasStationState::GasStationState() { - m_unk0x18 = 0; - m_unk0x1a = 0; - m_unk0x1c = 0; - m_unk0x1e = 0; - m_unk0x20 = 0; - - undefined4* unk0x08 = m_unk0x08; - unk0x08[0] = -1; - unk0x08[1] = -1; - unk0x08[2] = -1; + m_pepperAction = 0; + m_mamaAction = 0; + m_papaAction = 0; + m_nickAction = 0; + m_lauraAction = 0; + memset(m_actions, GarageScript::c_noneGarage, sizeof(m_actions)); } // FUNCTION: LEGO1 0x10006300 +// FUNCTION: BETA10 0x10029754 MxResult GasStationState::Serialize(LegoFile* p_file) { LegoState::Serialize(p_file); if (p_file->IsWriteMode()) { - Write(p_file, m_unk0x18); - Write(p_file, m_unk0x1a); - Write(p_file, m_unk0x1c); - Write(p_file, m_unk0x1e); - Write(p_file, m_unk0x20); + Write(p_file, m_pepperAction); + Write(p_file, m_mamaAction); + Write(p_file, m_papaAction); + Write(p_file, m_nickAction); + Write(p_file, m_lauraAction); } else if (p_file->IsReadMode()) { - Read(p_file, &m_unk0x18); - Read(p_file, &m_unk0x1a); - Read(p_file, &m_unk0x1c); - Read(p_file, &m_unk0x1e); - Read(p_file, &m_unk0x20); + Read(p_file, &m_pepperAction); + Read(p_file, &m_mamaAction); + Read(p_file, &m_papaAction); + Read(p_file, &m_nickAction); + Read(p_file, &m_lauraAction); } return SUCCESS; } -// STUB: LEGO1 0x10006430 -void GasStationState::FUN_10006430(GarageScript::Script) +// FUNCTION: LEGO1 0x10006430 +void GasStationState::PlayAction(GarageScript::Script p_objectId) { - // TODO + for (MxS32 i = 0; i < (MxS32) sizeOfArray(m_actions); i++) { + if (m_actions[i] == GarageScript::c_noneGarage) { + m_actions[i] = p_objectId; + return; + } + } } -// STUB: LEGO1 0x10006460 -void GasStationState::FUN_10006460(GarageScript::Script) +// FUNCTION: LEGO1 0x10006460 +void GasStationState::StopAction(GarageScript::Script p_objectId) { - // TODO + for (MxS32 i = 0; i < (MxS32) sizeOfArray(m_actions); i++) { + if (m_actions[i] == p_objectId) { + m_actions[i] = GarageScript::c_noneGarage; + return; + } + } } -// STUB: LEGO1 0x10006490 -void GasStationState::FUN_10006490() +// FUNCTION: LEGO1 0x10006490 +void GasStationState::StopActions() { - // TODO + for (MxS32 i = 0; i < (MxS32) sizeOfArray(m_actions); i++) { + if (m_actions[i] != GarageScript::c_noneGarage) { + InvokeAction(Extra::e_stop, *g_garageScript, m_actions[i], NULL); + m_actions[i] = GarageScript::c_noneGarage; + } + } + + BackgroundAudioManager()->RaiseVolume(); } From e4453c410014eaaa0db5411085e7f8f64db794d1 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 3 Nov 2024 09:41:15 -0700 Subject: [PATCH 12/17] Implement/match Act1State::Act1State (#1130) * Implement/match Act1State::Act1State * Remove obsolete enum --- LEGO1/lego/legoomni/include/isle.h | 12 +---------- LEGO1/lego/legoomni/include/legostate.h | 1 - LEGO1/lego/legoomni/src/worlds/isle.cpp | 27 ++++++++++--------------- 3 files changed, 12 insertions(+), 28 deletions(-) diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index 84aebed9..3d50b835 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -32,12 +32,6 @@ class Act1State : public LegoState { c_floor3 }; - enum { - e_unk953 = 953, - e_unk954 = 954, - e_unk955 = 955, - }; - // SIZE 0x4c class NamedPlane { public: @@ -109,11 +103,7 @@ class Act1State : public LegoState { // TODO: Most likely getters/setters are not used according to BETA. - MxS32* m_unk0x008; // 0x008 FIXME: count for m_unk0x008 - MxS16 m_unk0x00c; // 0x00c - undefined2 m_unk0x00e; // 0x00e - undefined2 m_unk0x010; // 0x010 - undefined m_unk0x012; // 0x012 + Playlist m_unk0x008; // 0x008 MxS32 m_unk0x014; // 0x014 MxU32 m_unk0x018; // 0x018 MxS16 m_elevFloor; // 0x01c diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index 23a8599e..23d9f9df 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -73,7 +73,6 @@ class LegoState : public MxCore { return SUCCESS; } - private: MxU32* m_objectIds; // 0x00 MxS16 m_length; // 0x04 MxS16 m_mode; // 0x06 diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index 347e4b07..4a37afdd 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -46,11 +46,8 @@ DECOMP_SIZE_ASSERT(Isle, 0x140) MxU32 g_isleFlags = 0x7f; // GLOBAL: LEGO1 0x100f37f0 -MxS32 g_unk0x100f37f0[] = { - Act1State::e_unk953, - Act1State::e_unk954, - Act1State::e_unk955, -}; +IsleScript::Script g_unk0x100f37f0[] = + {IsleScript::c_Avo905Ps_PlayWav, IsleScript::c_Avo906Ps_PlayWav, IsleScript::c_Avo907Ps_PlayWav}; // FUNCTION: LEGO1 0x10030820 Isle::Isle() @@ -1283,16 +1280,16 @@ void Isle::FUN_10033350() m_destLocation = LegoGameState::e_infomain; } -// STUB: LEGO1 0x100334b0 -Act1State::Act1State() : m_unk0x00c(0), m_unk0x00e(0), m_unk0x008(NULL), m_unk0x010(0) +// FUNCTION: LEGO1 0x100334b0 +// FUNCTION: BETA10 0x10035197 +Act1State::Act1State() { - m_unk0x01e = FALSE; + m_elevFloor = Act1State::c_floor1; m_unk0x018 = 1; - m_unk0x010 = 0; - m_planeActive = FALSE; - m_unk0x00e = 0; + m_unk0x01e = FALSE; + m_unk0x008 = Playlist((MxU32*) g_unk0x100f37f0, sizeOfArray(g_unk0x100f37f0), Playlist::e_loop); m_unk0x01f = FALSE; - m_unk0x008 = g_unk0x100f37f0; + m_planeActive = FALSE; m_unk0x014 = -1; m_unk0x022 = FALSE; m_unk0x154 = NULL; @@ -1301,8 +1298,6 @@ Act1State::Act1State() : m_unk0x00c(0), m_unk0x00e(0), m_unk0x008(NULL), m_unk0x m_helicopter = NULL; m_unk0x1b0 = NULL; m_unk0x021 = 1; - m_elevFloor = Act1State::c_floor1; - m_unk0x00c = sizeOfArray(g_unk0x100f37f0); m_unk0x1b4 = NULL; m_jetski = NULL; m_unk0x208 = NULL; @@ -1391,7 +1386,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) } } - Write(p_file, m_unk0x010); + Write(p_file, m_unk0x008.m_nextIndex); Write(p_file, m_unk0x022); } else if (p_file->IsReadMode()) { @@ -1445,7 +1440,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) } } - Read(p_file, &m_unk0x010); + Read(p_file, &m_unk0x008.m_nextIndex); Read(p_file, &m_unk0x022); } From 040c97d92a18af27315cf482afc62baa8df325a3 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 3 Nov 2024 09:59:21 -0700 Subject: [PATCH 13/17] Implement/match Act1State::PlayCptClickDialogue (#1131) --- LEGO1/lego/legoomni/include/isle.h | 64 ++++++++++++------------- LEGO1/lego/legoomni/src/worlds/isle.cpp | 36 ++++++++------ 2 files changed, 53 insertions(+), 47 deletions(-) diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index 3d50b835..51d1f943 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -85,8 +85,8 @@ class Act1State : public LegoState { MxBool SetFlag() override; // vtable+0x18 MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c - void FUN_10034660(); - void FUN_100346a0(); + void PlayCptClickDialogue(); + void StopCptClickDialogue(); void FUN_10034b60(); void FUN_10034d00(); @@ -103,36 +103,36 @@ class Act1State : public LegoState { // TODO: Most likely getters/setters are not used according to BETA. - Playlist m_unk0x008; // 0x008 - MxS32 m_unk0x014; // 0x014 - MxU32 m_unk0x018; // 0x018 - MxS16 m_elevFloor; // 0x01c - MxBool m_unk0x01e; // 0x01e - MxBool m_unk0x01f; // 0x01f - MxBool m_planeActive; // 0x020 - undefined m_unk0x021; // 0x021 - MxBool m_unk0x022; // 0x022 - undefined m_unk0x023; // 0x023 - NamedPlane m_unk0x024; // 0x024 - NamedPlane m_unk0x070; // 0x070 - NamedPlane m_unk0x0bc; // 0x0bc - NamedPlane m_unk0x108; // 0x108 - LegoNamedTexture* m_unk0x154; // 0x154 - LegoNamedTexture* m_unk0x158; // 0x158 - LegoNamedTexture* m_unk0x15c; // 0x15c - Helicopter* m_helicopter; // 0x160 - NamedPlane m_unk0x164; // 0x164 - LegoNamedTexture* m_unk0x1b0; // 0x1b0 - LegoNamedTexture* m_unk0x1b4; // 0x1b4 - Jetski* m_jetski; // 0x1b8 - NamedPlane m_unk0x1bc; // 0x1bc - LegoNamedTexture* m_unk0x208; // 0x208 - DuneBuggy* m_dunebuggy; // 0x20c - NamedPlane m_unk0x210; // 0x210 - LegoNamedTexture* m_unk0x25c; // 0x25c - LegoNamedTexture* m_unk0x260; // 0x260 - LegoNamedTexture* m_unk0x264; // 0x264 - RaceCar* m_racecar; // 0x268 + Playlist m_cptClickDialogue; // 0x008 + IsleScript::Script m_currentCptClickDialogue; // 0x014 + MxU32 m_unk0x018; // 0x018 + MxS16 m_elevFloor; // 0x01c + MxBool m_unk0x01e; // 0x01e + MxBool m_unk0x01f; // 0x01f + MxBool m_planeActive; // 0x020 + undefined m_unk0x021; // 0x021 + MxBool m_unk0x022; // 0x022 + undefined m_unk0x023; // 0x023 + NamedPlane m_unk0x024; // 0x024 + NamedPlane m_unk0x070; // 0x070 + NamedPlane m_unk0x0bc; // 0x0bc + NamedPlane m_unk0x108; // 0x108 + LegoNamedTexture* m_unk0x154; // 0x154 + LegoNamedTexture* m_unk0x158; // 0x158 + LegoNamedTexture* m_unk0x15c; // 0x15c + Helicopter* m_helicopter; // 0x160 + NamedPlane m_unk0x164; // 0x164 + LegoNamedTexture* m_unk0x1b0; // 0x1b0 + LegoNamedTexture* m_unk0x1b4; // 0x1b4 + Jetski* m_jetski; // 0x1b8 + NamedPlane m_unk0x1bc; // 0x1bc + LegoNamedTexture* m_unk0x208; // 0x208 + DuneBuggy* m_dunebuggy; // 0x20c + NamedPlane m_unk0x210; // 0x210 + LegoNamedTexture* m_unk0x25c; // 0x25c + LegoNamedTexture* m_unk0x260; // 0x260 + LegoNamedTexture* m_unk0x264; // 0x264 + RaceCar* m_racecar; // 0x268 }; // FUNCTION: LEGO1 0x10033a70 diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index 4a37afdd..e34fad19 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -46,7 +46,7 @@ DECOMP_SIZE_ASSERT(Isle, 0x140) MxU32 g_isleFlags = 0x7f; // GLOBAL: LEGO1 0x100f37f0 -IsleScript::Script g_unk0x100f37f0[] = +IsleScript::Script g_cptClickDialogue[] = {IsleScript::c_Avo905Ps_PlayWav, IsleScript::c_Avo906Ps_PlayWav, IsleScript::c_Avo907Ps_PlayWav}; // FUNCTION: LEGO1 0x10030820 @@ -362,14 +362,14 @@ MxLong Isle::HandleControl(LegoControlManagerNotificationParam& p_param) TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); break; case IsleScript::c_Observe_LeftArrow_Ctl: - m_act1state->FUN_100346a0(); + m_act1state->StopCptClickDialogue(); m_radio.Stop(); case IsleScript::c_SeaView_RightArrow_Ctl: m_destLocation = LegoGameState::e_elevopen; TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); break; case IsleScript::c_Observe_RightArrow_Ctl: - m_act1state->FUN_100346a0(); + m_act1state->StopCptClickDialogue(); m_radio.Stop(); case IsleScript::c_SeaView_LeftArrow_Ctl: m_destLocation = LegoGameState::e_elevdown; @@ -420,7 +420,7 @@ MxLong Isle::HandleControl(LegoControlManagerNotificationParam& p_param) break; case IsleScript::c_Observe_Draw1_Ctl: case IsleScript::c_Observe_Draw2_Ctl: - m_act1state->FUN_10034660(); + m_act1state->PlayCptClickDialogue(); break; case IsleScript::c_ElevDown_Elevator_Ctl: m_destLocation = LegoGameState::e_elevride2; @@ -1287,10 +1287,10 @@ Act1State::Act1State() m_elevFloor = Act1State::c_floor1; m_unk0x018 = 1; m_unk0x01e = FALSE; - m_unk0x008 = Playlist((MxU32*) g_unk0x100f37f0, sizeOfArray(g_unk0x100f37f0), Playlist::e_loop); + m_cptClickDialogue = Playlist((MxU32*) g_cptClickDialogue, sizeOfArray(g_cptClickDialogue), Playlist::e_loop); m_unk0x01f = FALSE; m_planeActive = FALSE; - m_unk0x014 = -1; + m_currentCptClickDialogue = IsleScript::c_noneIsle; m_unk0x022 = FALSE; m_unk0x154 = NULL; m_unk0x158 = NULL; @@ -1386,7 +1386,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) } } - Write(p_file, m_unk0x008.m_nextIndex); + Write(p_file, m_cptClickDialogue.m_nextIndex); Write(p_file, m_unk0x022); } else if (p_file->IsReadMode()) { @@ -1440,7 +1440,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) } } - Read(p_file, &m_unk0x008.m_nextIndex); + Read(p_file, &m_cptClickDialogue.m_nextIndex); Read(p_file, &m_unk0x022); } @@ -1448,18 +1448,24 @@ MxResult Act1State::Serialize(LegoFile* p_file) return SUCCESS; } -// STUB: LEGO1 0x10034660 -void Act1State::FUN_10034660() +// FUNCTION: LEGO1 0x10034660 +void Act1State::PlayCptClickDialogue() { - // TODO + StopCptClickDialogue(); + m_currentCptClickDialogue = (IsleScript::Script) m_cptClickDialogue.Next(); + BackgroundAudioManager()->LowerVolume(); + + if (m_currentCptClickDialogue != IsleScript::c_noneIsle) { + InvokeAction(Extra::e_start, *g_isleScript, m_currentCptClickDialogue, NULL); + } } // FUNCTION: LEGO1 0x100346a0 -void Act1State::FUN_100346a0() +void Act1State::StopCptClickDialogue() { - if (m_unk0x014 != -1) { - InvokeAction(Extra::e_stop, *g_isleScript, m_unk0x014, NULL); - m_unk0x014 = -1; + if (m_currentCptClickDialogue != IsleScript::c_noneIsle) { + InvokeAction(Extra::e_stop, *g_isleScript, m_currentCptClickDialogue, NULL); + m_currentCptClickDialogue = IsleScript::c_noneIsle; } } From d8412a4697e27e68667f45e2a01cd9ffda6979e7 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 3 Nov 2024 11:06:09 -0700 Subject: [PATCH 14/17] Implement/match Act1State::RemoveActors (#1132) * Implement/match Act1State::RemoveActors * Fix annotation --- LEGO1/lego/legoomni/include/helicopter.h | 2 +- LEGO1/lego/legoomni/include/isle.h | 59 +++-------- .../legoomni/include/legoanimationmanager.h | 2 +- LEGO1/lego/legoomni/include/legonamedplane.h | 46 +++++++++ LEGO1/lego/legoomni/include/legopathactor.h | 3 + LEGO1/lego/legoomni/include/legostate.h | 2 +- LEGO1/lego/legoomni/include/score.h | 2 +- LEGO1/lego/legoomni/src/actors/bumpbouy.cpp | 3 +- .../legoomni/src/actors/jukeboxentity.cpp | 2 +- .../lego/legoomni/src/build/legocarbuild.cpp | 11 ++- .../src/common/legoanimationmanager.cpp | 4 +- .../legoomni/src/common/legogamestate.cpp | 16 +-- LEGO1/lego/legoomni/src/common/legoutils.cpp | 3 +- .../lego/legoomni/src/paths/legopathactor.cpp | 6 ++ LEGO1/lego/legoomni/src/worlds/infocenter.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/isle.cpp | 99 +++++++++++++------ 16 files changed, 163 insertions(+), 99 deletions(-) create mode 100644 LEGO1/lego/legoomni/include/legonamedplane.h diff --git a/LEGO1/lego/legoomni/include/helicopter.h b/LEGO1/lego/legoomni/include/helicopter.h index bf428819..74715234 100644 --- a/LEGO1/lego/legoomni/include/helicopter.h +++ b/LEGO1/lego/legoomni/include/helicopter.h @@ -28,7 +28,7 @@ class HelicopterState : public LegoState { MxBool IsSerializable() override { return FALSE; } // vtable+0x14 // FUNCTION: LEGO1 0x1000e0c0 - MxBool SetFlag() override + MxBool Reset() override { m_unk0x08 = 0; return TRUE; diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index 51d1f943..b470bae5 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -3,6 +3,7 @@ #include "actionsfwd.h" #include "legogamestate.h" +#include "legonamedplane.h" #include "legostate.h" #include "legoworld.h" #include "radio.h" @@ -32,41 +33,6 @@ class Act1State : public LegoState { c_floor3 }; - // SIZE 0x4c - class NamedPlane { - public: - // FUNCTION: LEGO1 0x10033800 - NamedPlane() {} - - void SetName(const char* p_name) { m_name = p_name; } - const MxString* GetName() const { return &m_name; } - - // FUNCTION: LEGO1 0x100344d0 - MxResult Serialize(LegoFile* p_file) - { - if (p_file->IsWriteMode()) { - p_file->WriteString(m_name); - p_file->WriteVector3(m_point1); - p_file->WriteVector3(m_point2); - p_file->WriteVector3(m_point3); - } - else if (p_file->IsReadMode()) { - p_file->ReadString(m_name); - p_file->ReadVector3(m_point1); - p_file->ReadVector3(m_point2); - p_file->ReadVector3(m_point3); - } - - return SUCCESS; - } - - private: - MxString m_name; // 0x00 - Mx3DPointFloat m_point1; // 0x10 - Mx3DPointFloat m_point2; // 0x24 - Mx3DPointFloat m_point3; // 0x38 - }; - Act1State(); // FUNCTION: LEGO1 0x100338a0 @@ -82,12 +48,12 @@ class Act1State : public LegoState { return !strcmp(p_name, Act1State::ClassName()) || LegoState::IsA(p_name); } - MxBool SetFlag() override; // vtable+0x18 + MxBool Reset() override; // vtable+0x18 MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c void PlayCptClickDialogue(); void StopCptClickDialogue(); - void FUN_10034b60(); + void RemoveActors(); void FUN_10034d00(); MxU32 GetUnknown18() { return m_unk0x018; } @@ -113,31 +79,28 @@ class Act1State : public LegoState { undefined m_unk0x021; // 0x021 MxBool m_unk0x022; // 0x022 undefined m_unk0x023; // 0x023 - NamedPlane m_unk0x024; // 0x024 - NamedPlane m_unk0x070; // 0x070 - NamedPlane m_unk0x0bc; // 0x0bc - NamedPlane m_unk0x108; // 0x108 + LegoNamedPlane m_motocyclePlane; // 0x024 + LegoNamedPlane m_bikePlane; // 0x070 + LegoNamedPlane m_skateboardPlane; // 0x0bc + LegoNamedPlane m_helicopterPlane; // 0x108 LegoNamedTexture* m_unk0x154; // 0x154 LegoNamedTexture* m_unk0x158; // 0x158 LegoNamedTexture* m_unk0x15c; // 0x15c Helicopter* m_helicopter; // 0x160 - NamedPlane m_unk0x164; // 0x164 + LegoNamedPlane m_jetskiPlane; // 0x164 LegoNamedTexture* m_unk0x1b0; // 0x1b0 LegoNamedTexture* m_unk0x1b4; // 0x1b4 Jetski* m_jetski; // 0x1b8 - NamedPlane m_unk0x1bc; // 0x1bc + LegoNamedPlane m_dunebuggyPlane; // 0x1bc LegoNamedTexture* m_unk0x208; // 0x208 DuneBuggy* m_dunebuggy; // 0x20c - NamedPlane m_unk0x210; // 0x210 + LegoNamedPlane m_racecarPlane; // 0x210 LegoNamedTexture* m_unk0x25c; // 0x25c LegoNamedTexture* m_unk0x260; // 0x260 LegoNamedTexture* m_unk0x264; // 0x264 RaceCar* m_racecar; // 0x268 }; -// FUNCTION: LEGO1 0x10033a70 -// Act1State::NamedPlane::~NamedPlane - // VTABLE: LEGO1 0x100d6fb8 // SIZE 0x140 class Isle : public LegoWorld { @@ -184,6 +147,8 @@ class Isle : public LegoWorld { void FUN_10033350(); + friend class Act1State; + // SYNTHETIC: LEGO1 0x10030a30 // Isle::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoanimationmanager.h b/LEGO1/lego/legoomni/include/legoanimationmanager.h index c568663e..64727b1e 100644 --- a/LEGO1/lego/legoomni/include/legoanimationmanager.h +++ b/LEGO1/lego/legoomni/include/legoanimationmanager.h @@ -67,7 +67,7 @@ class AnimState : public LegoState { return !strcmp(p_name, AnimState::ClassName()) || LegoState::IsA(p_name); } - MxBool SetFlag() override; // vtable+0x18 + MxBool Reset() override; // vtable+0x18 MxResult Serialize(LegoFile* p_file) override; // vtable+0x1c void CopyToAnims(MxU32, AnimInfo* p_anims, MxU32& p_outExtraCharacterId); diff --git a/LEGO1/lego/legoomni/include/legonamedplane.h b/LEGO1/lego/legoomni/include/legonamedplane.h new file mode 100644 index 00000000..aa4facea --- /dev/null +++ b/LEGO1/lego/legoomni/include/legonamedplane.h @@ -0,0 +1,46 @@ +#ifndef LEGONAMEDPLANE_H +#define LEGONAMEDPLANE_H + +#include "misc/legostorage.h" +#include "mxgeometry/mxgeometry3d.h" +#include "mxstring.h" + +// SIZE 0x4c +class LegoNamedPlane { +public: + // FUNCTION: LEGO1 0x10033800 + LegoNamedPlane() {} + + // FUNCTION: LEGO1 0x10033a70 + // LegoNamedPlane::~LegoNamedPlane + + void SetName(const char* p_name) { m_name = p_name; } + const MxString* GetName() const { return &m_name; } + + // FUNCTION: LEGO1 0x100344d0 + MxResult Serialize(LegoFile* p_file) + { + if (p_file->IsWriteMode()) { + p_file->WriteString(m_name); + p_file->WriteVector3(m_position); + p_file->WriteVector3(m_direction); + p_file->WriteVector3(m_up); + } + else if (p_file->IsReadMode()) { + p_file->ReadString(m_name); + p_file->ReadVector3(m_position); + p_file->ReadVector3(m_direction); + p_file->ReadVector3(m_up); + } + + return SUCCESS; + } + +private: + MxString m_name; // 0x00 + Mx3DPointFloat m_position; // 0x10 + Mx3DPointFloat m_direction; // 0x24 + Mx3DPointFloat m_up; // 0x38 +}; + +#endif // LEGONAMEDPLANE_H diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index 242d46b6..c845c897 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -7,6 +7,7 @@ #include "mxtypes.h" struct LegoEdge; +class LegoNamedPlane; class LegoPathBoundary; class LegoPathController; struct LegoPathEdgeContainer; @@ -140,6 +141,8 @@ class LegoPathActor : public LegoActor { void SetController(LegoPathController* p_controller) { m_controller = p_controller; } + void UpdatePlane(LegoNamedPlane& p_namedPlane); + // SYNTHETIC: LEGO1 0x1002d800 // LegoPathActor::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index 23d9f9df..68cf0a5b 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -99,7 +99,7 @@ class LegoState : public MxCore { virtual MxBool IsSerializable() { return TRUE; } // vtable+0x14 // FUNCTION: LEGO1 0x10005fa0 - virtual MxBool SetFlag() { return FALSE; } // vtable+0x18 + virtual MxBool Reset() { return FALSE; } // vtable+0x18 // FUNCTION: LEGO1 0x10005fb0 virtual MxResult Serialize(LegoFile* p_file) diff --git a/LEGO1/lego/legoomni/include/score.h b/LEGO1/lego/legoomni/include/score.h index af072e63..7ad505aa 100644 --- a/LEGO1/lego/legoomni/include/score.h +++ b/LEGO1/lego/legoomni/include/score.h @@ -31,7 +31,7 @@ class ScoreState : public LegoState { MxBool IsSerializable() override { return FALSE; } // vtable+0x14 // FUNCTION: LEGO1 0x1000de30 - MxBool SetFlag() override + MxBool Reset() override { m_playCubeTutorial = TRUE; return TRUE; diff --git a/LEGO1/lego/legoomni/src/actors/bumpbouy.cpp b/LEGO1/lego/legoomni/src/actors/bumpbouy.cpp index 52938ab3..24e6d5c7 100644 --- a/LEGO1/lego/legoomni/src/actors/bumpbouy.cpp +++ b/LEGO1/lego/legoomni/src/actors/bumpbouy.cpp @@ -1,6 +1,7 @@ #include "bumpbouy.h" #include "isle.h" +#include "isle_actions.h" #include "islepathactor.h" #include "legogamestate.h" #include "legovideomanager.h" @@ -44,7 +45,7 @@ MxLong BumpBouy::Notify(MxParam& p_param) assert(isleState); isleState->m_unk0x018 = 5; - Isle* isle = (Isle*) FindWorld(*g_isleScript, 0); + Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle); assert(isle); isle->SetDestLocation(LegoGameState::e_jetrace); diff --git a/LEGO1/lego/legoomni/src/actors/jukeboxentity.cpp b/LEGO1/lego/legoomni/src/actors/jukeboxentity.cpp index a504fcbc..2ac6ed54 100644 --- a/LEGO1/lego/legoomni/src/actors/jukeboxentity.cpp +++ b/LEGO1/lego/legoomni/src/actors/jukeboxentity.cpp @@ -41,7 +41,7 @@ MxLong JukeBoxEntity::Notify(MxParam& p_param) ((IslePathActor*) UserActor())->Exit(); } - ((Isle*) FindWorld(*g_isleScript, 0))->SetDestLocation(LegoGameState::e_jukeboxw); + ((Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle))->SetDestLocation(LegoGameState::e_jukeboxw); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); return 1; } diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index d03e4f09..a7396bdc 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -4,6 +4,7 @@ #include "dunebuggy.h" #include "dunecar_actions.h" #include "helicopter.h" +#include "isle_actions.h" #include "jetski.h" #include "jetski_actions.h" #include "jukebox_actions.h" @@ -1014,7 +1015,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) // This function was changed between BETA10 and LEGO1. // These lines looks like a relic from older code. LegoWorld* destWorld = NULL; - destWorld = FindWorld(*g_isleScript, 0); + destWorld = FindWorld(*g_isleScript, IsleScript::c__Isle); Act1State* gameState = (Act1State*) GameState()->GetState("Act1State"); @@ -1025,7 +1026,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) } gameState->m_helicopter = (Helicopter*) entity; - gameState->m_unk0x108.SetName(""); + gameState->m_helicopterPlane.SetName(""); break; case LegoGameState::e_dunecarbuild: if (gameState->m_dunebuggy) { @@ -1033,7 +1034,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) } gameState->m_dunebuggy = (DuneBuggy*) entity; - gameState->m_unk0x1bc.SetName(""); + gameState->m_dunebuggyPlane.SetName(""); break; case LegoGameState::e_jetskibuild: if (gameState->m_jetski) { @@ -1041,7 +1042,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) } gameState->m_jetski = (Jetski*) entity; - gameState->m_unk0x164.SetName(""); + gameState->m_jetskiPlane.SetName(""); break; case LegoGameState::e_racecarbuild: if (gameState->m_racecar) { @@ -1049,7 +1050,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) } gameState->m_racecar = (RaceCar*) entity; - gameState->m_unk0x210.SetName(""); + gameState->m_racecarPlane.SetName(""); break; } diff --git a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp index fc7431f8..9d34a28b 100644 --- a/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoanimationmanager.cpp @@ -383,7 +383,7 @@ void LegoAnimationManager::Reset(MxBool p_und) m_unk0x402 = FALSE; if (p_und && m_animState != NULL) { - m_animState->SetFlag(); + m_animState->Reset(); } MxBool suspended = m_suspended; @@ -2951,7 +2951,7 @@ MxResult AnimState::Serialize(LegoFile* p_file) } // FUNCTION: LEGO1 0x100654f0 -MxBool AnimState::SetFlag() +MxBool AnimState::Reset() { if (m_unk0x10 != NULL) { m_extraCharacterId = 0; diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index a4001bc2..882cc944 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -302,7 +302,7 @@ MxResult LegoGameState::DeleteState() m_stateArray = NULL; for (MxS32 count = 0; count < stateCount; count++) { - if (!stateArray[count]->SetFlag() && stateArray[count]->IsSerializable()) { + if (!stateArray[count]->Reset() && stateArray[count]->IsSerializable()) { delete stateArray[count]; } else { @@ -780,7 +780,7 @@ void LegoGameState::StopArea(Area p_area) inline void LoadIsle() { - LegoWorld* world = FindWorld(*g_isleScript, 0); + LegoWorld* world = FindWorld(*g_isleScript, IsleScript::c__Isle); if (world != NULL) { if (!world->GetUnknown0xd0Empty()) { NotificationManager()->Send(world, MxNotificationParam(c_notificationType20, NULL)); @@ -957,7 +957,7 @@ void LegoGameState::SwitchArea(Area p_area) InvokeAction(Extra::ActionType::e_opendisk, *g_racecarScript, RacecarScript::c__StartUp, NULL); break; case e_act2main: { - LegoWorld* act2main = FindWorld(*g_act2mainScript, 0); + LegoWorld* act2main = FindWorld(*g_act2mainScript, Act2mainScript::c__Act2Main); if (act2main == NULL) { InvokeAction(Extra::ActionType::e_opendisk, *g_act2mainScript, Act2mainScript::c__Act2Main, NULL); @@ -969,7 +969,7 @@ void LegoGameState::SwitchArea(Area p_area) break; } case e_act3script: { - LegoWorld* act3 = FindWorld(*g_act3Script, 0); + LegoWorld* act3 = FindWorld(*g_act3Script, Act3Script::c__Act3); if (act3 == NULL) { InvokeAction(Extra::ActionType::e_opendisk, *g_act3Script, Act3Script::c__Act3, NULL); @@ -1105,7 +1105,7 @@ void LegoGameState::Init() SetCurrentAct(e_act1); if (m_loadedAct == e_act1) { - Isle* isle = (Isle*) FindWorld(*g_isleScript, 0); + Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle); Helicopter* copter = (Helicopter*) isle->Find(*g_copterScript, CopterScript::c_Helicopter_Actor); if (copter) { @@ -1215,13 +1215,13 @@ void LegoGameState::SetCurrentAct(Act p_currentAct) // FUNCTION: LEGO1 0x1003ceb0 void LegoGameState::FindLoadedAct() { - if (FindWorld(*g_isleScript, 0)) { + if (FindWorld(*g_isleScript, IsleScript::c__Isle)) { m_loadedAct = e_act1; } - else if (FindWorld(*g_act2mainScript, 0)) { + else if (FindWorld(*g_act2mainScript, Act2mainScript::c__Act2Main)) { m_loadedAct = e_act2; } - else if (FindWorld(*g_act3Script, 0)) { + else if (FindWorld(*g_act3Script, Act3Script::c__Act3)) { m_loadedAct = e_act3; } else { diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index 34248163..7f70425a 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -3,6 +3,7 @@ #include "3dmanager/lego3dmanager.h" #include "anim/legoanim.h" #include "isle.h" +#include "isle_actions.h" #include "islepathactor.h" #include "legoanimationmanager.h" #include "legoanimpresenter.h" @@ -333,7 +334,7 @@ void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender // FUNCTION: LEGO1 0x1003eab0 void SetCameraControllerFromIsle() { - InputManager()->SetCamera(FindWorld(*g_isleScript, 0)->GetCamera()); + InputManager()->SetCamera(FindWorld(*g_isleScript, IsleScript::c__Isle)->GetCamera()); } // FUNCTION: LEGO1 0x1003eae0 diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index e8aa7044..571f2b0e 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -718,3 +718,9 @@ void LegoPathActor::VTable0xa8() FUN_10010c30(); } } + +// STUB: LEGO1 0x1002f770 +void LegoPathActor::UpdatePlane(LegoNamedPlane& p_namedPlane) +{ + // TODO +} diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp index 342d85bd..1e248c07 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp @@ -1404,7 +1404,7 @@ void Infocenter::Reset() HelicopterState* state = (HelicopterState*) GameState()->GetState("HelicopterState"); if (state) { - state->SetFlag(); + state->Reset(); } } diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index e34fad19..c715dd34 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -39,7 +39,7 @@ #include "towtrack.h" DECOMP_SIZE_ASSERT(Act1State, 0x26c) -DECOMP_SIZE_ASSERT(Act1State::NamedPlane, 0x4c) +DECOMP_SIZE_ASSERT(LegoNamedPlane, 0x4c) DECOMP_SIZE_ASSERT(Isle, 0x140) // GLOBAL: LEGO1 0x100f1198 @@ -851,7 +851,7 @@ void Isle::Enable(MxBool p_enable) InputManager()->ClearWorld(); } - m_act1state->FUN_10034b60(); + m_act1state->RemoveActors(); } } @@ -1306,24 +1306,25 @@ Act1State::Act1State() m_unk0x260 = NULL; m_unk0x264 = NULL; m_racecar = NULL; - SetFlag(); + Reset(); } // FUNCTION: LEGO1 0x10033ac0 +// FUNCTION: BETA10 0x1003524f MxResult Act1State::Serialize(LegoFile* p_file) { LegoState::Serialize(p_file); - m_unk0x024.Serialize(p_file); - m_unk0x070.Serialize(p_file); - m_unk0x0bc.Serialize(p_file); - m_unk0x108.Serialize(p_file); - m_unk0x164.Serialize(p_file); - m_unk0x1bc.Serialize(p_file); - m_unk0x210.Serialize(p_file); + m_motocyclePlane.Serialize(p_file); + m_bikePlane.Serialize(p_file); + m_skateboardPlane.Serialize(p_file); + m_helicopterPlane.Serialize(p_file); + m_jetskiPlane.Serialize(p_file); + m_dunebuggyPlane.Serialize(p_file); + m_racecarPlane.Serialize(p_file); if (p_file->IsWriteMode()) { - if (m_unk0x108.GetName()->Compare("") != 0) { + if (m_helicopterPlane.GetName()->Compare("") != 0) { if (m_unk0x154) { WriteNamedTexture(p_file, m_unk0x154); } @@ -1343,7 +1344,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) FUN_1003f540(p_file, "chjetr.gif"); } } - if (m_unk0x164.GetName()->Compare("") != 0) { + if (m_jetskiPlane.GetName()->Compare("") != 0) { if (m_unk0x1b0) { WriteNamedTexture(p_file, m_unk0x1b0); } @@ -1357,7 +1358,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) FUN_1003f540(p_file, "jswnsh.gif"); } } - if (m_unk0x1bc.GetName()->Compare("") != 0) { + if (m_dunebuggyPlane.GetName()->Compare("") != 0) { if (m_unk0x208) { WriteNamedTexture(p_file, m_unk0x208); } @@ -1365,7 +1366,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) FUN_1003f540(p_file, "dbfrfn.gif"); } } - if (m_unk0x210.GetName()->Compare("") != 0) { + if (m_racecarPlane.GetName()->Compare("") != 0) { if (m_unk0x25c) { WriteNamedTexture(p_file, m_unk0x25c); } @@ -1390,7 +1391,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) Write(p_file, m_unk0x022); } else if (p_file->IsReadMode()) { - if (m_unk0x108.GetName()->Compare("") != 0) { + if (m_helicopterPlane.GetName()->Compare("") != 0) { m_unk0x154 = ReadNamedTexture(p_file); if (m_unk0x154 == NULL) { return FAILURE; @@ -1406,7 +1407,7 @@ MxResult Act1State::Serialize(LegoFile* p_file) return FAILURE; } } - if (m_unk0x164.GetName()->Compare("") != 0) { + if (m_jetskiPlane.GetName()->Compare("") != 0) { m_unk0x1b0 = ReadNamedTexture(p_file); if (m_unk0x1b0 == NULL) { return FAILURE; @@ -1417,13 +1418,13 @@ MxResult Act1State::Serialize(LegoFile* p_file) return FAILURE; } } - if (m_unk0x1bc.GetName()->Compare("") != 0) { + if (m_dunebuggyPlane.GetName()->Compare("") != 0) { m_unk0x208 = ReadNamedTexture(p_file); if (m_unk0x208 == NULL) { return FAILURE; } } - if (m_unk0x210.GetName()->Compare("") != 0) { + if (m_racecarPlane.GetName()->Compare("") != 0) { m_unk0x25c = ReadNamedTexture(p_file); if (m_unk0x25c == NULL) { return FAILURE; @@ -1470,13 +1471,13 @@ void Act1State::StopCptClickDialogue() } // FUNCTION: LEGO1 0x100346d0 -MxBool Act1State::SetFlag() +MxBool Act1State::Reset() { - m_unk0x024.SetName(""); - m_unk0x070.SetName(""); - m_unk0x0bc.SetName(""); + m_motocyclePlane.SetName(""); + m_bikePlane.SetName(""); + m_skateboardPlane.SetName(""); m_unk0x022 = FALSE; - m_unk0x108.SetName(""); + m_helicopterPlane.SetName(""); if (m_unk0x154) { delete m_unk0x154; @@ -1498,7 +1499,7 @@ MxBool Act1State::SetFlag() m_helicopter = NULL; } - m_unk0x164.SetName(""); + m_jetskiPlane.SetName(""); if (m_unk0x1b0) { delete m_unk0x1b0; @@ -1515,7 +1516,7 @@ MxBool Act1State::SetFlag() m_jetski = NULL; } - m_unk0x1bc.SetName(""); + m_dunebuggyPlane.SetName(""); if (m_unk0x208) { delete m_unk0x208; @@ -1527,7 +1528,7 @@ MxBool Act1State::SetFlag() m_dunebuggy = NULL; } - m_unk0x210.SetName(""); + m_racecarPlane.SetName(""); if (m_unk0x25c) { delete m_unk0x25c; @@ -1552,10 +1553,50 @@ MxBool Act1State::SetFlag() return TRUE; } -// STUB: LEGO1 0x10034b60 -void Act1State::FUN_10034b60() +// FUNCTION: LEGO1 0x10034b60 +void Act1State::RemoveActors() { - // TODO + Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle); + + isle->m_motocycle->UpdatePlane(m_motocyclePlane); + isle->m_bike->UpdatePlane(m_bikePlane); + isle->m_skateboard->UpdatePlane(m_skateboardPlane); + + if (isle->m_helicopter != NULL) { + isle->m_helicopter->UpdatePlane(m_helicopterPlane); + m_helicopter = isle->m_helicopter; + isle->RemoveActor(m_helicopter); + isle->VTable0x6c(m_helicopter); + m_helicopter->SetBoundary(NULL); + m_helicopter->SetController(NULL); + } + + if (isle->m_jetski != NULL) { + isle->m_jetski->UpdatePlane(m_jetskiPlane); + m_jetski = isle->m_jetski; + isle->RemoveActor(m_jetski); + isle->VTable0x6c(m_jetski); + m_jetski->SetBoundary(NULL); + m_jetski->SetController(NULL); + } + + if (isle->m_dunebuggy != NULL) { + isle->m_dunebuggy->UpdatePlane(m_dunebuggyPlane); + m_dunebuggy = isle->m_dunebuggy; + isle->RemoveActor(m_dunebuggy); + isle->VTable0x6c(m_dunebuggy); + m_dunebuggy->SetBoundary(NULL); + m_dunebuggy->SetController(NULL); + } + + if (isle->m_racecar != NULL) { + isle->m_racecar->UpdatePlane(m_racecarPlane); + m_racecar = isle->m_racecar; + isle->RemoveActor(m_racecar); + isle->VTable0x6c(m_racecar); + m_racecar->SetBoundary(NULL); + m_racecar->SetController(NULL); + } } // STUB: LEGO1 0x10034d00 From 1badadebaad512bb3a7fc738855a8941b4b585d7 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 3 Nov 2024 11:28:35 -0700 Subject: [PATCH 15/17] Implement/match LegoPathActor::UpdatePlane (#1133) --- LEGO1/lego/legoomni/include/legonamedplane.h | 4 ++++ LEGO1/lego/legoomni/src/paths/legopathactor.cpp | 8 ++++++-- LEGO1/lego/sources/geom/legowegedge.h | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legonamedplane.h b/LEGO1/lego/legoomni/include/legonamedplane.h index aa4facea..a97cd8fb 100644 --- a/LEGO1/lego/legoomni/include/legonamedplane.h +++ b/LEGO1/lego/legoomni/include/legonamedplane.h @@ -17,6 +17,10 @@ class LegoNamedPlane { void SetName(const char* p_name) { m_name = p_name; } const MxString* GetName() const { return &m_name; } + void SetPosition(const Mx3DPointFloat& p_position) { m_position = p_position; } + void SetDirection(const Mx3DPointFloat& p_direction) { m_direction = p_direction; } + void SetUp(const Mx3DPointFloat& p_up) { m_up = p_up; } + // FUNCTION: LEGO1 0x100344d0 MxResult Serialize(LegoFile* p_file) { diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 571f2b0e..0479e05d 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -4,6 +4,7 @@ #include "geom/legounkown100db7f4.h" #include "legocachesoundmanager.h" #include "legocameracontroller.h" +#include "legonamedplane.h" #include "legonavcontroller.h" #include "legopathboundary.h" #include "legopathedgecontainer.h" @@ -719,8 +720,11 @@ void LegoPathActor::VTable0xa8() } } -// STUB: LEGO1 0x1002f770 +// FUNCTION: LEGO1 0x1002f770 void LegoPathActor::UpdatePlane(LegoNamedPlane& p_namedPlane) { - // TODO + p_namedPlane.SetName(m_boundary->GetName()); + p_namedPlane.SetPosition(GetWorldPosition()); + p_namedPlane.SetDirection(GetWorldDirection()); + p_namedPlane.SetUp(GetWorldUp()); } diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index 1e774abf..1adbac27 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -48,7 +48,7 @@ class LegoWEGEdge : public LegoWEEdge { Mx4DPointFloat* GetEdgeNormal(int index) { return &m_edgeNormals[index]; } // FUNCTION: BETA10 0x1001c9b0 - LegoChar* GetName() { return m_name; } + const LegoChar* GetName() { return m_name; } void SetFlag0x10(LegoU32 p_disable) { From c65bc67e3dc929d0540530ecd7f3688c44f7e819 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Tue, 5 Nov 2024 21:33:51 +0100 Subject: [PATCH 16/17] Implement `FUN_10025720()` and others (#1134) * Implement `FUN_10025720()` and others * Address review comments, get 100 % --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/legocarbuild.h | 35 ++- LEGO1/lego/legoomni/include/legomain.h | 3 + LEGO1/lego/legoomni/include/legoutils.h | 5 +- .../src/audio/mxbackgroundaudiomanager.cpp | 1 + .../lego/legoomni/src/build/legocarbuild.cpp | 262 ++++++++++++++++-- LEGO1/lego/legoomni/src/common/legoutils.cpp | 46 ++- LEGO1/lego/legoomni/src/common/misc.cpp | 2 + LEGO1/lego/sources/roi/legoroi.cpp | 21 ++ LEGO1/lego/sources/roi/legoroi.h | 2 + LEGO1/library_msvc.h | 6 + 10 files changed, 345 insertions(+), 38 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index a18082db..6337aafd 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -73,6 +73,17 @@ typedef LegoVehicleBuildState LegoJetskiBuildState; // SIZE 0x34c class LegoCarBuild : public LegoWorld { public: + // SIZE 0x1c + struct LookupTableActions { + undefined4 m_unk0x00; // 0x00 + undefined4 m_unk0x04; // 0x04 + undefined4 m_unk0x08; // 0x08 + undefined4 m_unk0x0c; // 0x0c + undefined4 m_unk0x10; // 0x10 + undefined4 m_unk0x14; // 0x14 + undefined4 m_unk0x18; // 0x18 + }; + enum Unknown0xf8 { c_unknownminusone = -1, c_unknown8 = 8 @@ -133,9 +144,10 @@ class LegoCarBuild : public LegoWorld { void SetPresentersEnabled(MxBool p_enabled); void TogglePresentersEnabled(); void FUN_100250e0(MxBool p_param); - void FUN_10025350(MxS32 p_param); + void FUN_10025350(MxS32 p_objectId); void FUN_10025450(); - undefined4 FUN_10025720(undefined4 p_param1); + void FUN_10025720(undefined4 p_param1); + void FUN_10025d10(MxS32 p_param); MxS32 FUN_10025d70(); void FUN_10025db0(const char* p_param1, undefined4 p_param2); void FUN_10025e40(); @@ -148,12 +160,18 @@ class LegoCarBuild : public LegoWorld { // LegoCarBuild::`scalar deleting destructor' private: - Unknown0xf8 m_unk0xf8; // 0xf8 - MxS16 m_unk0xfc; // 0xfc - undefined m_unk0xfe[2]; // 0xfe - MxS32 m_unk0x100; // 0x100 - undefined4 m_unk0x104; // 0x104 - MxS8 m_unk0x108; // 0x108 + // inline functions + MxU32 Beta0x10070520(); + void StopActionIn0x344(); + + Unknown0xf8 m_unk0xf8; // 0xf8 + MxS16 m_unk0xfc; // 0xfc + MxS32 m_unk0x100; // 0x100 + undefined4 m_unk0x104; // 0x104 + + // name verified by BETA10 0x1006ebba + MxS8 m_numAnimsRun; // 0x108 + MxU8 m_unk0x109; // 0x109 MxU16 m_unk0x10a; // 0x10a DWORD m_unk0x10c; // 0x10c @@ -221,6 +239,7 @@ class LegoCarBuild : public LegoWorld { static MxS16 g_unk0x100f11cc; static MxFloat g_unk0x100d65a4; static MxFloat g_rotationAngleStepYAxis; + static LookupTableActions g_unk0x100d65b0[]; }; #endif // LEGOCARBUILD_H diff --git a/LEGO1/lego/legoomni/include/legomain.h b/LEGO1/lego/legoomni/include/legomain.h index 182500c1..4ac4f309 100644 --- a/LEGO1/lego/legoomni/include/legomain.h +++ b/LEGO1/lego/legoomni/include/legomain.h @@ -147,7 +147,10 @@ class LegoOmni : public MxOmni { void SetNavController(LegoNavController* p_navController) { m_navController = p_navController; } void SetUserActor(LegoPathActor* p_userActor) { m_userActor = p_userActor; } void SetCurrentWorld(LegoWorld* p_currentWorld) { m_currentWorld = p_currentWorld; } + + // FUNCTION: BETA10 0x100d55c0 void SetExit(MxBool p_exit) { m_exit = p_exit; } + MxResult StartActionIfUnknown0x13c(MxDSAction& p_dsAction) { return m_unk0x13c ? Start(&p_dsAction) : SUCCESS; } void SetUnknown13c(MxBool p_unk0x13c) { m_unk0x13c = p_unk0x13c; } diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h index b6143c36..8c4b44fe 100644 --- a/LEGO1/lego/legoomni/include/legoutils.h +++ b/LEGO1/lego/legoomni/include/legoutils.h @@ -10,6 +10,9 @@ #define WM_ISLE_SETCURSOR 0x5400 +// name verified by BETA10 0x100d4054 +#define DS_NOT_A_STREAM -1 + enum Cursor { e_cursorArrow = 0, e_cursorBusy, @@ -46,7 +49,7 @@ MxS16 CountTotalTreeNodes(LegoTreeNode* p_node); LegoTreeNode* GetTreeNode(LegoTreeNode* p_node, MxU32 p_index); void FUN_1003e050(LegoAnimPresenter* p_presenter); Extra::ActionType MatchActionString(const char*); -void InvokeAction(Extra::ActionType p_actionId, const MxAtomId& p_pAtom, MxS32 p_targetEntityId, LegoEntity* p_sender); +void InvokeAction(Extra::ActionType p_actionId, const MxAtomId& p_pAtom, MxS32 p_streamId, LegoEntity* p_sender); void SetCameraControllerFromIsle(); void ConvertHSVToRGB(float p_h, float p_s, float p_v, float* p_rOut, float* p_bOut, float* p_gOut); void PlayCamAnim(LegoPathActor* p_actor, MxBool p_unused, MxU32 p_location, MxBool p_bool); diff --git a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index d3e08256..4a921511 100644 --- a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -300,6 +300,7 @@ void MxBackgroundAudioManager::Stop() } // FUNCTION: LEGO1 0x1007f570 +// FUNCTION: BETA10 0x100e94e6 void MxBackgroundAudioManager::LowerVolume() { if (m_unk0x148 == 0) { diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index a7396bdc..68b1495f 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -24,6 +24,7 @@ #include "mxstillpresenter.h" #include "mxticklemanager.h" #include "mxtransitionmanager.h" +#include "mxvariabletable.h" #include "racecar.h" #include "racecar_actions.h" #include "scripts.h" @@ -40,6 +41,42 @@ DECOMP_SIZE_ASSERT(LegoCarBuild, 0x34c) DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50) +DECOMP_SIZE_ASSERT(LegoCarBuild::LookupTableActions, 0x1c); + +// These four structs can be matched to the vehicle types using BETA10 0x10070520 + +// GLOBAL: LEGO1 0x100d65b0 +// GLOBAL: BETA10 0x101bb7c0 +LegoCarBuild::LookupTableActions LegoCarBuild::g_unk0x100d65b0[] = { + {DunecarScript::c_igs001d3_RunAnim, + DunecarScript::c_igs002d3_RunAnim, + DunecarScript::c_igs003d3_RunAnim, + DunecarScript::c_igs004d3_RunAnim, + DunecarScript::c_igs005d3_RunAnim, + DunecarScript::c_igs004d3_RunAnim, + DunecarScript::c_igsxx1d3_RunAnim}, + {JetskiScript::c_ijs001d4_RunAnim, + JetskiScript::c_ijs003d4_RunAnim, + JetskiScript::c_ijs004d4_RunAnim, + JetskiScript::c_ijs005d4_RunAnim, + JetskiScript::c_ijs006d4_RunAnim, + JetskiScript::c_ijs007d4_RunAnim, + JetskiScript::c_ijsxx2d4_RunAnim}, + {CopterScript::c_ips001d2_RunAnim, + CopterScript::c_ips002d2_RunAnim, + CopterScript::c_ips003d2_RunAnim, + CopterScript::c_ips005d2_RunAnim, + CopterScript::c_ips004d2_RunAnim, + CopterScript::c_ips004d2_RunAnim, + CopterScript::c_ipsxx1d2_RunAnim}, + {RacecarScript::c_irt001d1_RunAnim, + RacecarScript::c_irt002d1_RunAnim, + RacecarScript::c_irt003d1_RunAnim, + RacecarScript::c_irt004d1_RunAnim, + RacecarScript::c_irt005d1_RunAnim, + RacecarScript::c_irt004d1_RunAnim, + RacecarScript::c_irtxx4d1_RunAnim} +}; // GLOBAL: LEGO1 0x100d65a4 MxFloat LegoCarBuild::g_unk0x100d65a4 = -0.1f; @@ -84,10 +121,10 @@ LegoCarBuild::LegoCarBuild() m_buildState = NULL; m_unk0x104 = 0; m_unk0x109 = 0; - m_unk0x108 = 0; + m_numAnimsRun = 0; m_unk0x338 = 0; m_destLocation = LegoGameState::e_undefined; - m_unk0x344 = 0xffffffff; + m_unk0x344 = DS_NOT_A_STREAM; m_unk0x174 = 0; NotificationManager()->Register(this); } @@ -610,8 +647,8 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) break; case c_notificationEndAnim: - if (m_unk0x108 > 0) { - m_unk0x108 -= 1; + if (m_numAnimsRun > 0) { + m_numAnimsRun -= 1; } FUN_10025e40(); @@ -632,7 +669,7 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) undefined4 LegoCarBuild::FUN_10024250(LegoEventNotificationParam* p_param) { if (p_param->GetKey() == ' ' && m_buildState->m_animationState != 4 && m_buildState->m_animationState != 2) { - if (m_unk0x108 > 0) { + if (m_numAnimsRun > 0) { DeleteObjects(&m_atomId, 500, 0x1fe); BackgroundAudioManager()->RaiseVolume(); m_unk0x109 = 0; @@ -815,7 +852,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) m_buildState->m_animationState != LegoVehicleBuildState::e_unknown2 && m_buildState->m_animationState != LegoVehicleBuildState::e_exiting && GameState()->GetCurrentAct() != LegoGameState::e_act2) { - if (m_unk0x108 > 0) { + if (m_numAnimsRun > 0) { DeleteObjects(&m_atomId, 500, 510); } @@ -829,7 +866,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) case CopterScript::c_Exit_Ctl: if (m_buildState->m_animationState != LegoVehicleBuildState::e_exiting && m_buildState->m_animationState != LegoVehicleBuildState::e_unknown4) { - if (m_unk0x108 > 0) { + if (m_numAnimsRun > 0) { DeleteObjects(&m_atomId, 500, 510); } @@ -1201,11 +1238,44 @@ void LegoCarBuild::FUN_100250e0(MxBool p_enabled) } } -// STUB: LEGO1 0x10025350 -// STUB: BETA10 0x1006e3c0 -void LegoCarBuild::FUN_10025350(MxS32 p_param) +// FUNCTION: LEGO1 0x10025350 +// FUNCTION: BETA10 0x1006e3c0 +void LegoCarBuild::FUN_10025350(MxS32 p_objectId) { - // TODO + const LegoChar* color; + LegoChar buffer[256]; + + if (!m_unk0x110) { + return; + } + + if (m_Yellow_Ctl->GetAction()->GetObjectId() == p_objectId) { + color = "lego yellow"; + } + else if (m_Red_Ctl->GetAction()->GetObjectId() == p_objectId) { + color = "lego red"; + } + else if (m_Blue_Ctl->GetAction()->GetObjectId() == p_objectId) { + color = "lego blue"; + } + else if (m_Green_Ctl->GetAction()->GetObjectId() == p_objectId) { + color = "lego green"; + } + else if (m_Gray_Ctl->GetAction()->GetObjectId() == p_objectId) { + color = "lego white"; + } + else if (m_Black_Ctl->GetAction()->GetObjectId() == p_objectId) { + color = "lego black"; + } + else { + return; + } + + m_Paint_Sound->Enable(FALSE); + m_Paint_Sound->Enable(TRUE); + m_unk0x110->FUN_100a93b0(color); + sprintf(buffer, "c_%s", m_unk0x110->GetName()); + VariableTable()->SetVariable(buffer, color); } // FUNCTION: LEGO1 0x10025450 @@ -1277,12 +1347,172 @@ void LegoCarBuild::Enable(MxBool p_enable) } } -// STUB: LEGO1 0x10025720 -// STUB: BETA10 0x1006e9df -undefined4 LegoCarBuild::FUN_10025720(undefined4 p_param1) +// FUNCTION: BETA10 0x10070520 +inline MxU32 LegoCarBuild::Beta0x10070520() { - // TODO - return 0; + switch (m_carId) { + case Helicopter_Actor: + return 2; + case DuneBugy_Actor: + return 0; + case Jetski_Actor: + return 1; + case RaceCar_Actor: + return 3; + default: + assert(0); + return 0; + } +} + +inline void LegoCarBuild::StopActionIn0x344() +{ + // There is no direct evidence for this inline function in LEGO1, + // but some code doesn't make much sense otherwise. For example, + // sometimes `m_unk0x344` is set to another value right below this call, + // which the original developer would likely have refactored. + if (m_unk0x344 != DS_NOT_A_STREAM) { + InvokeAction(Extra::ActionType::e_stop, m_atomId, m_unk0x344, NULL); + m_unk0x344 = DS_NOT_A_STREAM; + } +} + +// FUNCTION: LEGO1 0x10025720 +// FUNCTION: BETA10 0x1006e9df +void LegoCarBuild::FUN_10025720(undefined4 p_param) +{ + m_numAnimsRun++; + m_unk0x10a = 0; + MxS32 uVar6; + +#ifdef NDEBUG + + if (GameState()->GetCurrentAct() == LegoGameState::e_act2) { + // This is most likely related to the helicopter rebuild in Act 2 + switch (p_param) { + case 0: + case 1: + case 2: + case 3: + switch (rand() % 3) { + case 0: + m_unk0x10a = CopterScript::c_ips004d2_RunAnim; + StopActionIn0x344(); + m_unk0x344 = CopterScript::c_ips004d2_RunAnim; + BackgroundAudioManager()->LowerVolume(); + InvokeAction(Extra::ActionType::e_start, m_atomId, CopterScript::c_ips004d2_RunAnim, NULL); + break; + case 1: + m_unk0x10a = CopterScript::c_ips006d2_RunAnim; + StopActionIn0x344(); + m_unk0x344 = CopterScript::c_ips006d2_RunAnim; + BackgroundAudioManager()->LowerVolume(); + InvokeAction(Extra::ActionType::e_start, m_atomId, CopterScript::c_ips006d2_RunAnim, NULL); + break; + case 2: + m_unk0x10a = CopterScript::c_slp01xd2_RunAnim; + StopActionIn0x344(); + m_unk0x344 = CopterScript::c_slp01xd2_RunAnim; + BackgroundAudioManager()->LowerVolume(); + InvokeAction(Extra::ActionType::e_start, m_atomId, CopterScript::c_slp01xd2_RunAnim, NULL); + break; + } + break; + case 4: + FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x04); + break; + case 5: + FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x08); + break; + case 6: + m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x18; + uVar6 = m_unk0x10a; + StopActionIn0x344(); + + if (uVar6 != DS_NOT_A_STREAM) { + m_unk0x344 = uVar6; + BackgroundAudioManager()->LowerVolume(); + InvokeAction(Extra::ActionType::e_start, m_atomId, uVar6, NULL); + } + + break; + default: + m_numAnimsRun--; + return; + } + } + else { +#endif + // This part doesn't match BETA10 perfectly, but it's the closest we get without hundreds of #ifdef's + switch (p_param) { + case 0: + m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x00; + FUN_10025d10(m_unk0x10a); + break; + case 1: + m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x0c; + FUN_10025d10(m_unk0x10a); + + if (m_carId == 2) { + m_unk0x10a = 0; + } + + break; + case 2: + m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x10; + FUN_10025d10(m_unk0x10a); + + if (m_carId != 3) { + m_unk0x10a = 0; + } + + break; + case 3: + FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x14); + break; + case 4: + FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x04); + break; + case 5: + FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x08); + break; + case 6: + m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x18; + FUN_10025d10(m_unk0x10a); + break; + default: + assert(0); + m_numAnimsRun--; + + // Weird: This assertion can never be executed. The `assert(0)` above was probably introduced later. + assert(m_numAnimsRun >= 0); + return; + } +#ifdef NDEBUG + } +#endif + + if (m_unk0x10a != 0) { + m_unk0x10c = timeGetTime(); + } +} + +// FUNCTION: LEGO1 0x10025d10 +// FUNCTION: BETA10 0x10070490 +void LegoCarBuild::FUN_10025d10(MxS32 p_param) +{ + // this function has a different signature and partially different body in BETA10, but it is called in the same + // places + if (m_unk0x344 != DS_NOT_A_STREAM) { + InvokeAction(Extra::ActionType::e_stop, m_atomId, m_unk0x344, NULL); + m_unk0x344 = DS_NOT_A_STREAM; + } + + if (p_param != DS_NOT_A_STREAM) { + m_unk0x344 = p_param; + BackgroundAudioManager()->LowerVolume(); + InvokeAction(Extra::ActionType::e_start, m_atomId, p_param, NULL); + } } // FUNCTION: LEGO1 0x10025d70 diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index 7f70425a..e3c7dbef 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -240,24 +240,30 @@ void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender // FUNCTION: LEGO1 0x1003e430 // FUNCTION: BETA10 0x100d3fda -void InvokeAction(Extra::ActionType p_actionId, const MxAtomId& p_pAtom, MxS32 p_targetEntityId, LegoEntity* p_sender) +void InvokeAction(Extra::ActionType p_actionId, const MxAtomId& p_pAtom, MxS32 p_streamId, LegoEntity* p_sender) { MxDSAction action; action.SetAtomId(p_pAtom); - action.SetObjectId(p_targetEntityId); + action.SetObjectId(p_streamId); switch (p_actionId) { case Extra::ActionType::e_opendisk: - if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { + assert(p_streamId != DS_NOT_A_STREAM); + + if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_streamId)) { Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_diskStream); Start(&action); } + break; case Extra::ActionType::e_openram: - if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { + assert(p_streamId != DS_NOT_A_STREAM); + + if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_streamId)) { Streamer()->Open(p_pAtom.GetInternal(), MxStreamer::e_RAMStream); Start(&action); } + break; case Extra::ActionType::e_close: action.SetUnknown24(-2); @@ -265,35 +271,47 @@ void InvokeAction(Extra::ActionType p_actionId, const MxAtomId& p_pAtom, MxS32 p Streamer()->Close(p_pAtom.GetInternal()); break; case Extra::ActionType::e_start: - if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId)) { + assert(p_streamId != DS_NOT_A_STREAM); + + if (!CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_streamId)) { Start(&action); } + break; case Extra::ActionType::e_stop: + assert(p_streamId != DS_NOT_A_STREAM); action.SetUnknown24(-2); - if (!RemoveFromCurrentWorld(p_pAtom, p_targetEntityId)) { + + if (!RemoveFromCurrentWorld(p_pAtom, p_streamId)) { DeleteObject(action); } + break; case Extra::ActionType::e_run: _spawnl(0, "\\lego\\sources\\main\\main.exe", "\\lego\\sources\\main\\main.exe", "/script", &p_pAtom, 0); break; + case Extra::ActionType::e_enable: + assert(p_streamId != DS_NOT_A_STREAM); + CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_streamId); + break; + case Extra::ActionType::e_disable: + assert(p_streamId != DS_NOT_A_STREAM); + CheckIfEntityExists(FALSE, p_pAtom.GetInternal(), p_streamId); + break; case Extra::ActionType::e_exit: Lego()->SetExit(TRUE); break; - case Extra::ActionType::e_enable: - CheckIfEntityExists(TRUE, p_pAtom.GetInternal(), p_targetEntityId); - break; - case Extra::ActionType::e_disable: - CheckIfEntityExists(FALSE, p_pAtom.GetInternal(), p_targetEntityId); - break; case Extra::ActionType::e_notify: - NotifyEntity(p_pAtom.GetInternal(), p_targetEntityId, p_sender); + assert(p_streamId != DS_NOT_A_STREAM); + NotifyEntity(p_pAtom.GetInternal(), p_streamId, p_sender); break; + default: + assert("Invalid Action Control" == NULL); } } // FUNCTION: LEGO1 0x1003e670 +// FUNCTION: BETA10 0x100d43f2 MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_entityId) { LegoWorld* world = FindWorld(MxAtomId(p_filename, e_lowerCase2), p_entityId); @@ -308,6 +326,7 @@ MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_enti } // FUNCTION: LEGO1 0x1003e700 +// FUNCTION: BETA10 0x100d448a void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender) { MxAtomId atom(p_filename, e_lowerCase2); @@ -444,6 +463,7 @@ void FUN_1003eda0() } // FUNCTION: LEGO1 0x1003ee00 +// FUNCTION: BETA10 0x100d4c6f MxBool RemoveFromCurrentWorld(const MxAtomId& p_atomId, MxS32 p_id) { LegoWorld* world = CurrentWorld(); diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 2acc4be2..6c01313f 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -33,8 +33,10 @@ LegoVideoManager* VideoManager() } // FUNCTION: LEGO1 0x10015730 +// FUNCTION: BETA10 0x100e484e MxBackgroundAudioManager* BackgroundAudioManager() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetBackgroundAudioManager(); } diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index 94fed7c6..87b8a3a0 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -475,6 +475,7 @@ LegoResult LegoROI::SetFrame(LegoAnim* p_anim, LegoTime p_time) } // FUNCTION: LEGO1 0x100a9170 +// FUNCTION: BETA10 0x1018ae09 LegoResult LegoROI::FUN_100a9170(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha) { LegoResult result = SUCCESS; @@ -552,6 +553,13 @@ LegoResult LegoROI::GetTexture(LegoTextureInfo*& p_textureInfo) return FAILURE; } +// FUNCTION: LEGO1 0x100a9330 +// FUNCTION: BETA10 0x1018b22c +LegoResult LegoROI::FUN_100a9330(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha) +{ + return FUN_100a9170(p_red, p_green, p_blue, p_alpha); +} + // FUNCTION: LEGO1 0x100a9350 // FUNCTION: BETA10 0x1018b25c LegoResult LegoROI::FUN_100a9350(const LegoChar* p_color) @@ -564,6 +572,18 @@ LegoResult LegoROI::FUN_100a9350(const LegoChar* p_color) return SUCCESS; } +// FUNCTION: LEGO1 0x100a93b0 +// FUNCTION: BETA10 0x1018b2c0 +LegoResult LegoROI::FUN_100a93b0(const LegoChar* p_color) +{ + MxFloat red, green, blue, alpha; + if (ColorAliasLookup(p_color, red, green, blue, alpha)) { + return FUN_100a9330(red, green, blue, alpha); + } + + return 0; +} + // FUNCTION: LEGO1 0x100a9410 // FUNCTION: BETA10 0x1018b324 LegoU32 LegoROI::FUN_100a9410( @@ -746,6 +766,7 @@ LegoBool LegoROI::FUN_100a9bf0(const LegoChar* p_param, float& p_red, float& p_g } // FUNCTION: LEGO1 0x100a9c50 +// FUNCTION: BETA10 0x1018bdd9 LegoBool LegoROI::ColorAliasLookup(const LegoChar* p_param, float& p_red, float& p_green, float& p_blue, float& p_alpha) { for (LegoU32 i = 0; i < sizeOfArray(g_roiColorAliases); i++) { diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index babb566a..541cfac5 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -38,7 +38,9 @@ class LegoROI : public ViewROI { LegoResult FUN_100a9170(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult FUN_100a9210(LegoTextureInfo* p_textureInfo); LegoResult GetTexture(LegoTextureInfo*& p_textureInfo); + LegoResult FUN_100a9330(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult FUN_100a9350(const LegoChar* p_color); + LegoResult FUN_100a93b0(const LegoChar* p_color); LegoU32 FUN_100a9410(Vector3& p_v1, Vector3& p_v2, float p_f1, float p_f2, Vector3& p_v3, LegoBool p_collideBox); void SetName(const LegoChar* p_name); diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index d4770e46..c4a46848 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -732,6 +732,12 @@ // LIBRARY: BETA10 0x1018ed70 // _strupr +// LIBRARY: BETA10 0x100f9690 +// sprintf + +// LIBRARY: BETA10 0x100fb150 +// _spawnl + // LIBRARY: BETA10 0x1001d1a0 // `vector constructor iterator' From f4ab226946bfc7c670868d37adaf1326201acfbf Mon Sep 17 00:00:00 2001 From: Joshua Peisach Date: Sat, 9 Nov 2024 12:03:01 -0500 Subject: [PATCH 17/17] Implement Doors::VTable0x94 (#1136) * Implement Doors::VTable0x94 * Match function --------- Co-authored-by: Christian Semmler --- LEGO1/lego/legoomni/include/doors.h | 10 +++++----- LEGO1/lego/legoomni/src/actors/doors.cpp | 15 ++++++++++++--- 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/LEGO1/lego/legoomni/include/doors.h b/LEGO1/lego/legoomni/include/doors.h index 527d1de1..83c551b0 100644 --- a/LEGO1/lego/legoomni/include/doors.h +++ b/LEGO1/lego/legoomni/include/doors.h @@ -7,7 +7,7 @@ // SIZE 0x1f8 class Doors : public LegoPathActor { public: - Doors() : m_unk0x154(0), m_unk0x15c(0), m_unk0x160(0), m_unk0x1f4(0) {} + Doors() : m_unk0x154(0), m_unk0x15c(NULL), m_unk0x160(NULL), m_unk0x1f4(0) {} // FUNCTION: LEGO1 0x1000e430 const char* ClassName() const override // vtable+0x0c @@ -31,12 +31,12 @@ class Doors : public LegoPathActor { private: undefined4 m_unk0x154; // 0x154 - undefined4 m_unk0x158; // 0x158 - undefined4 m_unk0x15c; // 0x15c - undefined4 m_unk0x160; // 0x160 + MxFloat m_unk0x158; // 0x158 + Matrix4* m_unk0x15c; // 0x15c + Matrix4* m_unk0x160; // 0x160 MxMatrix m_unk0x164; // 0x164 MxMatrix m_unk0x1ac; // 0x1ac - undefined4 m_unk0x1f4; // 0x1f4 + MxFloat m_unk0x1f4; // 0x1f4 }; #endif // DOORS_H diff --git a/LEGO1/lego/legoomni/src/actors/doors.cpp b/LEGO1/lego/legoomni/src/actors/doors.cpp index d4aedd7c..2ac676b3 100644 --- a/LEGO1/lego/legoomni/src/actors/doors.cpp +++ b/LEGO1/lego/legoomni/src/actors/doors.cpp @@ -1,12 +1,21 @@ #include "doors.h" +#include "mxmisc.h" +#include "mxtimer.h" + DECOMP_SIZE_ASSERT(Doors, 0x1f8) -// STUB: LEGO1 0x10066100 +// FUNCTION: LEGO1 0x10066100 MxResult Doors::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) { - // TODO - return 0; + if (m_unk0x154 == 1) { + m_unk0x154 = 2; + m_unk0x158 = Timer()->GetTime(); + m_unk0x164 = m_unk0x15c[2]; + m_unk0x1ac = m_unk0x160[2]; + } + + return m_unk0x1f4 < 0.001 ? SUCCESS : FAILURE; } // STUB: LEGO1 0x10066250