From bad32149cadeebb281b7d30a2de686bfc36e7537 Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Wed, 31 Jan 2024 07:34:36 -0500 Subject: [PATCH 1/2] implement LegoGameState::StopPreviousAction (#511) * implement RemoveFromWorld * fix unloading * Rename stuff, add default arg * Rename functions --------- Co-authored-by: Christian Semmler --- LEGO1/lego/legoomni/include/legogamestate.h | 13 +- LEGO1/lego/legoomni/include/legoutil.h | 1 + LEGO1/lego/legoomni/src/build/helicopter.cpp | 4 +- .../legoomni/src/common/legogamestate.cpp | 174 +++++++++++++++++- LEGO1/lego/legoomni/src/common/legoutil.cpp | 29 +++ .../src/infocenter/elevatorbottom.cpp | 6 +- .../legoomni/src/infocenter/infocenter.cpp | 2 +- .../src/infocenter/infocenterdoor.cpp | 4 +- LEGO1/lego/legoomni/src/infocenter/score.cpp | 6 +- LEGO1/lego/legoomni/src/isle/isle.cpp | 12 +- LEGO1/lego/legoomni/src/police/police.cpp | 4 +- 11 files changed, 223 insertions(+), 32 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 318aa7a3..5c631c6f 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -32,15 +32,16 @@ public: LegoState* CreateState(const char* p_stateName); void GetFileSavePath(MxString* p_outPath, MxULong p_slotn); - void FUN_1003a720(MxU32); - void HandleAction(MxU32); + void StopArea(MxU32 p_area = 0); + void SwitchArea(MxU32 p_area); inline MxU8 GetUnknownC() { return m_unk0x0c; } inline MxU32 GetUnknown10() { return m_unk0x10; } inline MxS32 GetCurrentAct() { return m_currentAct; } - inline undefined4 GetUnknown424() { return m_unk0x424; } + inline MxU32 GetCurrentArea() { return m_currentArea; } + inline void SetDirty(MxBool p_dirty) { m_isDirty = p_dirty; } - inline void SetUnknown424(undefined4 p_unk0x424) { m_unk0x424 = p_unk0x424; } + inline void SetCurrentArea(MxU32 p_currentArea) { m_currentArea = p_currentArea; } void SetSomeEnumState(undefined4 p_state); void FUN_1003ceb0(); @@ -75,8 +76,8 @@ private: ScoreStruct m_unk0xa6; // 0xa6 undefined m_unk0x41a[8]; // 0x41a - might be part of the structure at 0xa6 MxBool m_isDirty; // 0x420 - undefined4 m_unk0x424; // 0x424 - undefined4 m_prevArea; // 0x428 + MxU32 m_currentArea; // 0x424 + MxU32 m_previousArea; // 0x428 undefined4 m_unk0x42c; // 0x42c }; diff --git a/LEGO1/lego/legoomni/include/legoutil.h b/LEGO1/lego/legoomni/include/legoutil.h index 75e51c20..922a2c60 100644 --- a/LEGO1/lego/legoomni/include/legoutil.h +++ b/LEGO1/lego/legoomni/include/legoutil.h @@ -19,5 +19,6 @@ MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id); void FUN_1003ef00(MxBool); void SetAppCursor(WPARAM p_wparam); MxBool FUN_1003ef60(); +MxBool RemoveFromWorld(MxAtomId& p_atomId1, MxS32 p_id1, MxAtomId& p_atomId2, MxS32 p_id2); #endif // LEGOUTIL_H diff --git a/LEGO1/lego/legoomni/src/build/helicopter.cpp b/LEGO1/lego/legoomni/src/build/helicopter.cpp index 0f099228..9f11ace4 100644 --- a/LEGO1/lego/legoomni/src/build/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/build/helicopter.cpp @@ -62,7 +62,7 @@ void Helicopter::VTable0xe4() } IslePathActor::VTable0xe4(); if (!GameState()->GetUnknown10()) { - GameState()->SetUnknown424(0x3c); + GameState()->SetCurrentArea(0x3c); if (GetCurrentVehicle()) { if (GetCurrentVehicle()->IsA("IslePathActor")) { ((IslePathActor*) GetCurrentVehicle())->VTable0xe8(0x37, TRUE, 7); @@ -148,7 +148,7 @@ MxU32 Helicopter::VTable0xd4(LegoControlManagerEvent& p_param) else if (m_state->GetUnkown8() != 0) break; VTable0xe4(); - GameState()->SetUnknown424(0x42); + GameState()->SetCurrentArea(0x42); ret = 1; break; case 0x18: { diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index af5e8dac..789cf7c8 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -69,8 +69,8 @@ LegoGameState::LegoGameState() this->m_stateCount = 0; this->m_unk0x0c = 0; this->m_savePath = NULL; - this->m_unk0x424 = 0; - this->m_prevArea = 0; + this->m_currentArea = 0; + this->m_previousArea = 0; this->m_unk0x42c = 0; this->m_isDirty = FALSE; this->m_currentAct = -1; @@ -256,16 +256,176 @@ void LegoGameState::SerializePlayersInfo(MxS16) // TODO } -// STUB: LEGO1 0x1003a720 -void LegoGameState::FUN_1003a720(MxU32) +// FUNCTION: LEGO1 0x1003a720 +void LegoGameState::StopArea(MxU32 p_area) { - // TODO + if (p_area == 0) { + p_area = m_previousArea; + } + + switch (p_area) { + case 1: + InvokeAction(Extra::e_stop, *g_isleScript, 0, NULL); + InvokeAction(Extra::e_close, *g_isleScript, 0, NULL); + InvokeAction(Extra::e_close, *g_sndAnimScript, 0, NULL); + break; + case 2: + InvokeAction(Extra::e_stop, *g_infomainScript, 0, NULL); + InvokeAction(Extra::e_close, *g_infomainScript, 0, NULL); + break; + case 3: + InvokeAction(Extra::e_stop, *g_infodoorScript, 0, NULL); + InvokeAction(Extra::e_close, *g_infodoorScript, 0, NULL); + break; + case 5: + InvokeAction(Extra::e_stop, *g_elevbottScript, 0, NULL); + InvokeAction(Extra::e_close, *g_elevbottScript, 0, NULL); + break; + case 6: + case 7: + RemoveFromWorld(*g_isleScript, 0x41b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 1052, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x41d, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x41e, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x420, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x422, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x424, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x426, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x428, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x42a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x42b, *g_isleScript, 0); + break; + case 8: + RemoveFromWorld(*g_isleScript, 0x45b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x45c, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x45d, *g_isleScript, 0); + break; + case 9: + RemoveFromWorld(*g_isleScript, 0x475, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x476, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x477, *g_isleScript, 0); + break; + case 10: + RemoveFromWorld(*g_isleScript, 0x45f, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x460, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x461, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x462, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x463, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x464, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x465, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x466, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x467, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x469, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x468, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46c, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46d, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46e, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x46f, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x471, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x472, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x12, *g_isleScript, 0); + break; + case 0xb: + RemoveFromWorld(*g_isleScript, 0x47a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x47b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x47c, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x47d, *g_isleScript, 0); + break; + case 0xc: + InvokeAction(Extra::e_stop, *g_regbookScript, 0, NULL); + InvokeAction(Extra::e_close, *g_regbookScript, 0, NULL); + break; + case 0xd: + InvokeAction(Extra::e_stop, *g_infoscorScript, 0, NULL); + InvokeAction(Extra::e_close, *g_infoscorScript, 0, NULL); + break; + case 0xe: + InvokeAction(Extra::e_stop, *g_jetraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jetraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jetracerScript, 0, NULL); + break; + case 0x12: + InvokeAction(Extra::e_stop, *g_carraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_carraceScript, 0, NULL); + InvokeAction(Extra::e_close, *g_carracerScript, 0, NULL); + break; + case 0x1a: + Lego()->RemoveWorld(*g_garageScript, 0); + InvokeAction(Extra::e_stop, *g_garageScript, 0, NULL); + InvokeAction(Extra::e_close, *g_garageScript, 0, NULL); + break; + case 0x1b: + RemoveFromWorld(*g_isleScript, 0x489, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x48a, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x48b, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x48c, *g_isleScript, 0); + break; + case 0x1e: + InvokeAction(Extra::e_stop, *g_hospitalScript, 0, NULL); + InvokeAction(Extra::e_close, *g_hospitalScript, 0, NULL); + break; + case 0x22: + InvokeAction(Extra::e_stop, *g_policeScript, 0, NULL); + InvokeAction(Extra::e_close, *g_policeScript, 0, NULL); + break; + case 0x23: + RemoveFromWorld(*g_isleScript, 0x47f, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x480, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x481, *g_isleScript, 0); + RemoveFromWorld(*g_isleScript, 0x482, *g_isleScript, 0); + break; + case 0x24: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x2f, NULL); + InvokeAction(Extra::e_stop, *g_copterScript, 0, NULL); + InvokeAction(Extra::e_close, *g_copterScript, 0, NULL); + break; + case 0x25: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x31, NULL); + InvokeAction(Extra::e_stop, *g_dunecarScript, 0, NULL); + InvokeAction(Extra::e_close, *g_dunecarScript, 0, NULL); + break; + case 0x26: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x33, NULL); + InvokeAction(Extra::e_stop, *g_jetskiScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jetskiScript, 0, NULL); + break; + case 0x27: + InvokeAction(Extra::e_stop, *g_jukeboxScript, 0x35, NULL); + InvokeAction(Extra::e_stop, *g_racecarScript, 0, NULL); + InvokeAction(Extra::e_close, *g_racecarScript, 0, NULL); + break; + case 0x2e: + if (m_currentArea != 2) { + InvokeAction(Extra::e_stop, *g_act2mainScript, 0, NULL); + InvokeAction(Extra::e_close, *g_act2mainScript, 0, NULL); + } + break; + case 0x2f: + if (m_currentArea != 2) { + InvokeAction(Extra::e_stop, *g_act3Script, 0, NULL); + InvokeAction(Extra::e_close, *g_act3Script, 0, NULL); + } + break; + case 0x35: + InvokeAction(Extra::e_stop, *g_jukeboxwScript, 0, NULL); + InvokeAction(Extra::e_close, *g_jukeboxwScript, 0, NULL); + break; + case 0x38: + InvokeAction(Extra::e_disable, *g_histbookScript, 0, NULL); + InvokeAction(Extra::e_stop, *g_histbookScript, 0, NULL); + InvokeAction(Extra::e_close, *g_histbookScript, 0, NULL); + break; + } } // STUB: LEGO1 0x1003b060 -void LegoGameState::HandleAction(MxU32 p_area) +void LegoGameState::SwitchArea(MxU32 p_area) { - m_prevArea = p_area; + m_previousArea = m_currentArea; + m_currentArea = p_area; + BackgroundAudioManager()->Stop(); AnimationManager()->FUN_1005ef10(); VideoManager()->SetUnk0x554(0); diff --git a/LEGO1/lego/legoomni/src/common/legoutil.cpp b/LEGO1/lego/legoomni/src/common/legoutil.cpp index dfb4b740..9f388ad5 100644 --- a/LEGO1/lego/legoomni/src/common/legoutil.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutil.cpp @@ -195,6 +195,35 @@ MxBool FUN_1003ee00(MxAtomId& p_atomId, MxS32 p_id) return TRUE; } +// FUNCTION: LEGO1 0x1003ee80 +MxBool RemoveFromWorld(MxAtomId& p_entityAtom, MxS32 p_entityId, MxAtomId& p_worldAtom, MxS32 p_worldEntityId) +{ + LegoWorld* world = FindWorld(p_worldAtom, p_worldEntityId); + + if (world) { + MxCore* object = world->Find(p_entityAtom, p_entityId); + + if (object) { + world->Remove(object); + + if (!object->IsA("MxPresenter")) { + delete object; + } + else { + if (((MxPresenter*) object)->GetAction()) { + FUN_100b7220(((MxPresenter*) object)->GetAction(), MxDSAction::c_world, FALSE); + } + + ((MxPresenter*) object)->EndAction(); + } + + return TRUE; + } + } + + return FALSE; +} + // STUB: LEGO1 0x1003ef00 void FUN_1003ef00(MxBool) { diff --git a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp index 697ce5f1..84bbb4c6 100644 --- a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp @@ -38,8 +38,8 @@ MxResult ElevatorBottom::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); - GameState()->SetUnknown424(5); - GameState()->FUN_1003a720(0); + GameState()->SetCurrentArea(5); + GameState()->StopArea(); return result; } @@ -56,7 +56,7 @@ MxLong ElevatorBottom::Notify(MxParam& p_param) ret = HandleNotification17(p_param); break; case c_notificationTransitioned: - GameState()->HandleAction(m_unk0xf8); + GameState()->SwitchArea(m_unk0xf8); break; } } diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp index 651f06a6..3dca5c64 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -139,7 +139,7 @@ MxLong Infocenter::Notify(MxParam& p_param) } else if (m_unk0x104 != 0) { BackgroundAudioManager()->RaiseVolume(); - GameState()->HandleAction(m_unk0x104); + GameState()->SwitchArea(m_unk0x104); m_unk0x104 = 0; } break; diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp index 599096b2..4ed626ff 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp @@ -39,8 +39,8 @@ MxResult InfocenterDoor::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); - GameState()->SetUnknown424(3); - GameState()->FUN_1003a720(0); + GameState()->SetCurrentArea(3); + GameState()->StopArea(); return result; } diff --git a/LEGO1/lego/legoomni/src/infocenter/score.cpp b/LEGO1/lego/legoomni/src/infocenter/score.cpp index 181553d4..f75e0418 100644 --- a/LEGO1/lego/legoomni/src/infocenter/score.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/score.cpp @@ -52,8 +52,8 @@ MxResult Score::Create(MxDSAction& p_dsAction) LegoGameState* gs = GameState(); ScoreState* state = (ScoreState*) gs->GetState("ScoreState"); m_state = state ? state : (ScoreState*) gs->CreateState("ScoreState"); - GameState()->SetUnknown424(0xd); - GameState()->FUN_1003a720(0); + GameState()->SetCurrentArea(0xd); + GameState()->StopArea(); } return result; @@ -97,7 +97,7 @@ MxLong Score::Notify(MxParam& p_param) case c_notificationTransitioned: DeleteObjects(g_infoscorScript, 7, 9); if (m_unk0xf8) - GameState()->HandleAction(m_unk0xf8); + GameState()->SwitchArea(m_unk0xf8); ret = 1; break; default: diff --git a/LEGO1/lego/legoomni/src/isle/isle.cpp b/LEGO1/lego/legoomni/src/isle/isle.cpp index 40e07fa1..bb6d4fd8 100644 --- a/LEGO1/lego/legoomni/src/isle/isle.cpp +++ b/LEGO1/lego/legoomni/src/isle/isle.cpp @@ -62,21 +62,21 @@ MxResult Isle::Create(MxDSAction& p_dsAction) if (result == SUCCESS) { ControlManager()->Register(this); InputManager()->SetWorld(this); - GameState()->FUN_1003a720(0); + GameState()->StopArea(); switch (GameState()->GetCurrentAct()) { case 1: - GameState()->FUN_1003a720(0x2e); + GameState()->StopArea(0x2e); break; case 2: - GameState()->FUN_1003a720(0x2e); + GameState()->StopArea(0x2e); break; case -1: m_unk0x13c = 2; } - if (GameState()->GetUnknown424() == 1) { - GameState()->SetUnknown424(0); + if (GameState()->GetCurrentArea() == 1) { + GameState()->SetCurrentArea(0); } LegoGameState* gameState = GameState(); @@ -158,7 +158,7 @@ void Isle::ReadyWorld() LegoWorld::ReadyWorld(); if (m_act1state->GetUnknown21()) { - GameState()->HandleAction(2); + GameState()->SwitchArea(2); m_act1state->SetUnknown18(0); m_act1state->SetUnknown21(0); } diff --git a/LEGO1/lego/legoomni/src/police/police.cpp b/LEGO1/lego/legoomni/src/police/police.cpp index aac86238..c8c29486 100644 --- a/LEGO1/lego/legoomni/src/police/police.cpp +++ b/LEGO1/lego/legoomni/src/police/police.cpp @@ -55,8 +55,8 @@ MxResult Police::Create(MxDSAction& p_dsAction) } m_policeState = policeState; - GameState()->SetUnknown424(0x22); - GameState()->FUN_1003a720(0); + GameState()->SetCurrentArea(0x22); + GameState()->StopArea(); return ret; } From 9e0b19856c6d031b7581f49dc663ab38d54da49b Mon Sep 17 00:00:00 2001 From: Misha <106913236+MishaProductions@users.noreply.github.com> Date: Wed, 31 Jan 2024 09:47:15 -0500 Subject: [PATCH 2/2] Implement various infocenter functions (#510) * Implement various infocenter methods * fix order * Update infocenter.cpp * Update infocenter.cpp * Update infocenter.cpp * Update mxcontrolpresenter.cpp * Rename stuff for consistency * Add StateStruct to InfocenterState * Resolve some TODO * Use MxRect32 * Improve match * Match Infocenter::UpdateFrameHot * Fix VTable0x64 * WIP Match * Match * Cleanup --------- Co-authored-by: Christian Semmler --- LEGO1/lego/legoomni/include/act1state.h | 5 +- LEGO1/lego/legoomni/include/elevatorbottom.h | 4 +- LEGO1/lego/legoomni/include/infocenter.h | 36 +- LEGO1/lego/legoomni/include/infocenterdoor.h | 4 + LEGO1/lego/legoomni/include/infocenterstate.h | 34 +- LEGO1/lego/legoomni/include/legogamestate.h | 1 + LEGO1/lego/legoomni/include/legostate.h | 9 +- LEGO1/lego/legoomni/include/radio.h | 9 +- .../legoomni/src/common/legogamestate.cpp | 18 +- LEGO1/lego/legoomni/src/common/legostate.cpp | 9 - .../src/control/mxcontrolpresenter.cpp | 8 +- .../src/infocenter/elevatorbottom.cpp | 47 ++- .../legoomni/src/infocenter/infocenter.cpp | 320 +++++++++++++++--- .../src/infocenter/infocenterdoor.cpp | 85 ++++- LEGO1/lego/legoomni/src/infocenter/score.cpp | 2 +- LEGO1/lego/legoomni/src/isle/isle.cpp | 2 +- LEGO1/lego/legoomni/src/isle/radio.cpp | 6 +- LEGO1/omni/include/mxnotificationparam.h | 2 +- LEGO1/omni/include/mxpresenter.h | 2 + LEGO1/omni/include/mxrect32.h | 1 + 20 files changed, 486 insertions(+), 118 deletions(-) diff --git a/LEGO1/lego/legoomni/include/act1state.h b/LEGO1/lego/legoomni/include/act1state.h index 324d7195..988eb8c7 100644 --- a/LEGO1/lego/legoomni/include/act1state.h +++ b/LEGO1/lego/legoomni/include/act1state.h @@ -27,9 +27,12 @@ public: inline void SetUnknown18(MxU32 p_unk0x18) { m_unk0x18 = p_unk0x18; } inline MxU32 GetUnknown18() { return m_unk0x18; } - inline void SetUnknown21(MxS16 p_unk0x21) { m_unk0x21 = p_unk0x21; } + inline MxU32 GetUnknown1c() { return m_unk0x1c; } inline MxS16 GetUnknown21() { return m_unk0x21; } + inline void SetUnknown1c(MxU32 p_unk0x1c) { m_unk0x1c = p_unk0x1c; } + inline void SetUnknown21(MxS16 p_unk0x21) { m_unk0x21 = p_unk0x21; } + void FUN_10034d00(); // SYNTHETIC: LEGO1 0x10033960 diff --git a/LEGO1/lego/legoomni/include/elevatorbottom.h b/LEGO1/lego/legoomni/include/elevatorbottom.h index e52f5556..2c8711a3 100644 --- a/LEGO1/lego/legoomni/include/elevatorbottom.h +++ b/LEGO1/lego/legoomni/include/elevatorbottom.h @@ -4,6 +4,8 @@ #include "decomp.h" #include "legoworld.h" +class LegoControlManagerEvent; + // VTABLE: LEGO1 0x100d5f20 // SIZE: 0xfc (from inlined ctor at 0x1000a8aa) class ElevatorBottom : public LegoWorld { @@ -41,7 +43,7 @@ public: private: undefined4 m_unk0xf8; // 0xf8 - MxLong HandleNotification17(MxParam& p_param); + MxLong HandleClick(LegoControlManagerEvent& p_param); }; #endif // ELEVATORBOTTOM_H diff --git a/LEGO1/lego/legoomni/include/infocenter.h b/LEGO1/lego/legoomni/include/infocenter.h index b46099cd..56f01e09 100644 --- a/LEGO1/lego/legoomni/include/infocenter.h +++ b/LEGO1/lego/legoomni/include/infocenter.h @@ -2,10 +2,12 @@ #define INFOCENTER_H #include "legoworld.h" +#include "mxrect32.h" #include "radio.h" class InfocenterState; class MxStillPresenter; +class LegoControlManagerEvent; // SIZE 0x18 struct InfocenterMapEntry { @@ -14,10 +16,7 @@ struct InfocenterMapEntry { MxStillPresenter* m_presenter; // 0x00 undefined4 m_unk0x04; // 0x04 - undefined4 m_unk0x08; // 0x08 - undefined4 m_unk0x0c; // 0x0c - undefined4 m_unk0x10; // 0x10 - undefined4 m_unk0x14; // 0x14 + MxRect32 m_area; // 0x08 }; // VTABLE: LEGO1 0x100d9338 @@ -40,12 +39,15 @@ public: c_leftArrowCtl = 1, c_rightArrowCtl = 2, c_infoCtl = 3, + c_doorCtl = 4, c_boatCtl = 10, c_raceCtl = 11, c_pizzaCtl = 12, c_gasCtl = 13, c_medCtl = 14, c_copCtl = 15, + c_bigInfoCtl = 16, + c_bookCtl = 17, c_radioCtl = 18, c_mamaCtl = 21, c_papaCtl = 22, @@ -53,6 +55,15 @@ public: c_nickCtl = 24, c_lauraCtl = 25, + c_mamaSelected = 30, + c_papaSelected = 31, + c_pepperSelected = 32, + c_nickSelected = 33, + c_lauraSelected = 34, + + c_goToRegBook = 70, + c_goToRegBookRed = 71, + c_welcomeDialogue = 500, c_goodJobDialogue = 501, @@ -114,6 +125,13 @@ public: c_noCDDialogueUnused1 = 552, c_noCDDialogueUnused2 = 553, + c_gasCtlDescription = 555, + c_medCtlDescription = 556, + c_boatCtlDescription = 558, + c_copCtlDescription = 559, + c_pizzaCtlDescription = 560, + c_raceCtlDescription = 561, + c_leaveInfoCenterDialogue1 = 562, c_leaveInfoCenterDialogue2 = 563, c_leaveInfoCenterDialogue3 = 564, @@ -163,16 +181,18 @@ private: MxLong HandleKeyPress(MxS8 p_key); MxU8 HandleMouseMove(MxS32 p_x, MxS32 p_y); MxU8 HandleButtonUp(MxS32 p_x, MxS32 p_y); - MxU8 HandleNotification17(MxParam&); + MxU8 HandleClick(LegoControlManagerEvent& p_param); MxLong HandleEndAction(MxParam& p_param); MxLong HandleNotification0(MxParam&); - void FUN_10070dc0(MxBool); + void UpdateFrameHot(MxBool p_display); void FUN_10070e90(); void PlayCutscene(Cutscene p_entityId, MxBool p_scale); void StopCutscene(); + void FUN_10070d10(MxS32 p_x, MxS32 p_y); + void StartCredits(); void StopCredits(); @@ -185,10 +205,10 @@ private: InfomainScript m_currentInfomainScript; // 0xf8 MxS16 m_unk0xfc; // 0xfc InfocenterState* m_infocenterState; // 0x100 - undefined4 m_unk0x104; // 0x104 + undefined4 m_transitionDestination; // 0x104 Cutscene m_currentCutscene; // 0x108 Radio m_radio; // 0x10c - undefined4 m_unk0x11c; // 0x11c + MxStillPresenter* m_unk0x11c; // 0x11c InfocenterMapEntry m_mapAreas[7]; // 0x120 MxS16 m_unk0x1c8; // 0x1c8 MxStillPresenter* m_frameHotBitmap; // 0x1cc diff --git a/LEGO1/lego/legoomni/include/infocenterdoor.h b/LEGO1/lego/legoomni/include/infocenterdoor.h index 1d7b361d..0869d4e4 100644 --- a/LEGO1/lego/legoomni/include/infocenterdoor.h +++ b/LEGO1/lego/legoomni/include/infocenterdoor.h @@ -3,6 +3,8 @@ #include "legoworld.h" +class LegoControlManagerEvent; + // VTABLE: LEGO1 0x100d72d8 // SIZE 0xfc class InfocenterDoor : public LegoWorld { @@ -39,6 +41,8 @@ public: private: MxS32 m_unk0xf8; // 0xf8 + + MxLong HandleClick(LegoControlManagerEvent& p_param); }; #endif // INFOCENTERDOOR_H diff --git a/LEGO1/lego/legoomni/include/infocenterstate.h b/LEGO1/lego/legoomni/include/infocenterstate.h index 9399f8f4..ed23acef 100644 --- a/LEGO1/lego/legoomni/include/infocenterstate.h +++ b/LEGO1/lego/legoomni/include/infocenterstate.h @@ -30,6 +30,7 @@ public: inline MxS16 GetInfocenterBufferSize() { return sizeof(m_buffer) / sizeof(m_buffer[0]); } inline MxStillPresenter* GetInfocenterBufferElement(MxS32 p_index) { return m_buffer[p_index]; } + inline StateStruct& GetUnknown0x68() { return m_unk0x68; } inline MxU32 GetUnknown0x74() { return m_unk0x74; } inline void SetUnknown0x74(MxU32 p_unk0x74) { m_unk0x74 = p_unk0x74; } @@ -38,35 +39,10 @@ public: // InfocenterState::`scalar deleting destructor' private: - // Members should be renamed with their offsets before use - /* - struct UnkStruct - { - undefined4 unk1; - undefined2 unk2; - undefined2 unk3; - undefined2 unk4; - }; - - undefined2 unk1; - undefined2 unk2; - undefined4 unk3; - undefined4 padding1; - void *unk4; - undefined2 unk5; - undefined2 unk6; - undefined2 unk7; - undefined2 padding2; - void *unk8; - undefined2 unk9; - undefined2 unk10; - undefined2 unk11; - undefined2 padding3; - UnkStruct unk12[6]; - undefined4 unk13; - */ - - undefined m_pad[0x6c]; + undefined m_unk0x08[0x18]; // 0x08 + StateStruct m_unk0x20[3]; // 0x20 + StateStruct m_unk0x44[3]; // 0x44 + StateStruct m_unk0x68; // 0x68 MxU32 m_unk0x74; // 0x74 MxStillPresenter* m_buffer[7]; // 0x78 }; diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 5c631c6f..1af22e55 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -39,6 +39,7 @@ public: inline MxU32 GetUnknown10() { return m_unk0x10; } inline MxS32 GetCurrentAct() { return m_currentAct; } inline MxU32 GetCurrentArea() { return m_currentArea; } + inline MxU32 GetPreviousArea() { return m_previousArea; } inline void SetDirty(MxBool p_dirty) { m_isDirty = p_dirty; } inline void SetCurrentArea(MxU32 p_currentArea) { m_currentArea = p_currentArea; } diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index de66cdc6..fe10bbf7 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -51,7 +51,14 @@ public: undefined2 m_unk0x06; // 0x06 MxU16 m_unk0x08; // 0x08 - StateStruct(); + // FUNCTION: LEGO1 0x10017c00 + StateStruct() + { + m_unk0x04 = 0; + m_unk0x00 = NULL; + m_unk0x06 = 0; + m_unk0x08 = 0; + } MxU32 FUN_10014d00(); MxBool FUN_10014de0(MxU32 p_objectId); diff --git a/LEGO1/lego/legoomni/include/radio.h b/LEGO1/lego/legoomni/include/radio.h index 347a22d1..dd37ba44 100644 --- a/LEGO1/lego/legoomni/include/radio.h +++ b/LEGO1/lego/legoomni/include/radio.h @@ -29,20 +29,21 @@ public: } void Initialize(MxBool p_und); + void Play(); + void Stop(); // SYNTHETIC: LEGO1 0x1002c970 // Radio::`scalar deleting destructor' private: + void CreateRadioState(); + RadioState* m_state; // 0x08 MxBool m_unk0x0c; // 0x0c MxBool m_bgAudioPreviouslyEnabled; // 0x0d - void CreateRadioState(); - void Play(); - void Stop(); MxLong HandleEndAction(MxEndActionNotificationParam& p_param); - MxLong HandleNotification17(LegoControlManagerEvent& p_param); + MxLong HandleClick(LegoControlManagerEvent& p_param); }; #endif // RADIO_H diff --git a/LEGO1/lego/legoomni/src/common/legogamestate.cpp b/LEGO1/lego/legoomni/src/common/legogamestate.cpp index 789cf7c8..0a884a53 100644 --- a/LEGO1/lego/legoomni/src/common/legogamestate.cpp +++ b/LEGO1/lego/legoomni/src/common/legogamestate.cpp @@ -428,20 +428,32 @@ void LegoGameState::SwitchArea(MxU32 p_area) BackgroundAudioManager()->Stop(); AnimationManager()->FUN_1005ef10(); - VideoManager()->SetUnk0x554(0); + VideoManager()->SetUnk0x554(FALSE); MxAtomId* script = g_isleScript; switch (p_area) { case 1: break; case 2: - VideoManager()->SetUnk0x554(1); + VideoManager()->SetUnk0x554(TRUE); script = g_infomainScript; break; case 3: - VideoManager()->SetUnk0x554(1); + VideoManager()->SetUnk0x554(TRUE); script = g_infodoorScript; break; + // TODO + case 5: + script = g_elevbottScript; + break; + case 12: + VideoManager()->SetUnk0x554(TRUE); + script = g_regbookScript; + break; + case 13: + VideoManager()->SetUnk0x554(TRUE); + script = g_infoscorScript; + break; // TODO: implement other cases } diff --git a/LEGO1/lego/legoomni/src/common/legostate.cpp b/LEGO1/lego/legoomni/src/common/legostate.cpp index 5d3bcf4e..96a08dbe 100644 --- a/LEGO1/lego/legoomni/src/common/legostate.cpp +++ b/LEGO1/lego/legoomni/src/common/legostate.cpp @@ -16,12 +16,3 @@ MxBool LegoState::StateStruct::FUN_10014de0(MxU32 p_objectId) // TODO return FALSE; } - -// FUNCTION: LEGO1 0x10017c00 -LegoState::StateStruct::StateStruct() -{ - m_unk0x04 = 0; - m_unk0x00 = 0; - m_unk0x06 = 0; - m_unk0x08 = 0; -} diff --git a/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp index ae0288f7..39fb5eee 100644 --- a/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp +++ b/LEGO1/lego/legoomni/src/control/mxcontrolpresenter.cpp @@ -108,13 +108,13 @@ MxBool MxControlPresenter::FUN_10044270(MxS32 p_x, MxS32 p_y, MxVideoPresenter* if (m_unk0x4c == 3) { MxVideoPresenter* frontPresenter = (MxVideoPresenter*) m_list.front(); - if (p_presenter == frontPresenter || frontPresenter->GetDisplayZ() < frontPresenter->GetDisplayZ()) { + if (p_presenter == frontPresenter || frontPresenter->GetDisplayZ() < p_presenter->GetDisplayZ()) { if (p_presenter->VTable0x7c()) { MxS32 height = frontPresenter->GetHeight(); MxS32 width = frontPresenter->GetWidth(); if (frontPresenter->GetLocation().GetX() <= p_x && - p_x < width - 1 + frontPresenter->GetLocation().GetY() && + p_x < width - 1 + frontPresenter->GetLocation().GetX() && frontPresenter->GetLocation().GetY() <= p_y && p_y < height - 1 + frontPresenter->GetLocation().GetY()) { MxU8* start; @@ -198,7 +198,7 @@ MxBool MxControlPresenter::FUN_10044480(LegoControlManagerEvent* p_event, MxPres p_event->SetClickedObjectId(m_action->GetObjectId()); p_event->SetClickedAtom(m_action->GetAtomId().GetInternal()); VTable0x6c(0); - p_event->SetType(c_notificationType17); + p_event->SetType(c_notificationClick); p_event->SetUnknown0x28(m_unk0x4e); return TRUE; } @@ -208,7 +208,7 @@ MxBool MxControlPresenter::FUN_10044480(LegoControlManagerEvent* p_event, MxPres p_event->SetClickedObjectId(m_action->GetObjectId()); p_event->SetClickedAtom(m_action->GetAtomId().GetInternal()); VTable0x6c(m_unk0x56); - p_event->SetType(c_notificationType17); + p_event->SetType(c_notificationClick); p_event->SetUnknown0x28(m_unk0x4e); return TRUE; } diff --git a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp index 84bbb4c6..08f2cf50 100644 --- a/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/elevatorbottom.cpp @@ -1,5 +1,6 @@ #include "elevatorbottom.h" +#include "act1state.h" #include "jukebox.h" #include "legocontrolmanager.h" #include "legogamestate.h" @@ -7,9 +8,14 @@ #include "legoomni.h" #include "mxnotificationmanager.h" #include "mxomni.h" +#include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(ElevatorBottom, 0xfc) +// STRING: LEGO1 0x100f0d34 +// GLOBAL: LEGO1 0x100f3a44 +char* g_cameraLoc = "CAMERA_LOCATION"; + // FUNCTION: LEGO1 0x10017e90 ElevatorBottom::ElevatorBottom() { @@ -52,8 +58,8 @@ MxLong ElevatorBottom::Notify(MxParam& p_param) if (m_worldStarted) { switch (((MxNotificationParam&) p_param).GetType()) { - case c_notificationType17: - ret = HandleNotification17(p_param); + case c_notificationClick: + ret = HandleClick((LegoControlManagerEvent&) p_param); break; case c_notificationTransitioned: GameState()->SwitchArea(m_unk0xf8); @@ -72,10 +78,41 @@ void ElevatorBottom::ReadyWorld() FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } -// STUB: LEGO1 0x100181d0 -MxLong ElevatorBottom::HandleNotification17(MxParam& p_param) +// FUNCTION: LEGO1 0x100181d0 +MxLong ElevatorBottom::HandleClick(LegoControlManagerEvent& p_param) { - return 0; + MxLong result = 0; + + if (p_param.GetUnknown0x28() == 1) { + switch (p_param.GetClickedObjectId()) { + case 1: + m_unk0xf8 = 3; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 2: + m_unk0xf8 = 2; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 3: + LegoGameState* gs = GameState(); + Act1State* state = (Act1State*) gs->GetState("Act1State"); + + if (state == NULL) { + state = (Act1State*) gs->CreateState("Act1State"); + } + + state->SetUnknown1c(1); + m_unk0xf8 = 6; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + VariableTable()->SetVariable(g_cameraLoc, "LCAMZI1,90"); + result = 1; + break; + } + } + + return result; } // FUNCTION: LEGO1 0x100182c0 diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp index 3dca5c64..2a98f5af 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenter.cpp @@ -32,7 +32,7 @@ Infocenter::Infocenter() m_infocenterState = NULL; m_frameHotBitmap = 0; m_unk0x11c = 0; - m_unk0x104 = 0; + m_transitionDestination = 0; m_currentInfomainScript = c_noInfomain; m_currentCutscene = e_noIntro; @@ -126,8 +126,8 @@ MxLong Infocenter::Notify(MxParam& p_param) ((LegoEventNotificationParam&) p_param).GetY() ); break; - case c_notificationType17: - result = HandleNotification17(p_param); + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); break; case c_notificationTransitioned: StopBookAnimation(); @@ -137,10 +137,10 @@ MxLong Infocenter::Notify(MxParam& p_param) StartCredits(); m_infocenterState->SetUnknown0x74(0xd); } - else if (m_unk0x104 != 0) { + else if (m_transitionDestination != 0) { BackgroundAudioManager()->RaiseVolume(); - GameState()->SwitchArea(m_unk0x104); - m_unk0x104 = 0; + GameState()->SwitchArea(m_transitionDestination); + m_transitionDestination = 0; } break; } @@ -189,7 +189,7 @@ MxLong Infocenter::HandleEndAction(MxParam& p_param) break; } - FUN_10070dc0(TRUE); + UpdateFrameHot(TRUE); } } @@ -383,63 +383,82 @@ void Infocenter::InitializeBitmaps() ((MxPresenter*) Find(m_atom, c_radioCtl))->Enable(TRUE); m_mapAreas[0].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Info_A_Bitmap"); - m_mapAreas[0].m_unk0x08 = 391; - m_mapAreas[0].m_unk0x0c = 182; - m_mapAreas[0].m_unk0x10 = 427; - m_mapAreas[0].m_unk0x14 = 230; + m_mapAreas[0].m_area.SetLeft(391); + m_mapAreas[0].m_area.SetTop(182); + m_mapAreas[0].m_area.SetRight(427); + m_mapAreas[0].m_area.SetBottom(230); m_mapAreas[0].m_unk0x04 = 3; m_mapAreas[1].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Boat_A_Bitmap"); - m_mapAreas[1].m_unk0x08 = 304; - m_mapAreas[1].m_unk0x0c = 225; - m_mapAreas[1].m_unk0x10 = 350; - m_mapAreas[1].m_unk0x14 = 268; + m_mapAreas[1].m_area.SetLeft(304); + m_mapAreas[1].m_area.SetTop(225); + m_mapAreas[1].m_area.SetRight(350); + m_mapAreas[1].m_area.SetBottom(268); m_mapAreas[1].m_unk0x04 = 10; m_mapAreas[2].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Race_A_Bitmap"); - m_mapAreas[2].m_unk0x08 = 301; - m_mapAreas[2].m_unk0x0c = 133; - m_mapAreas[2].m_unk0x10 = 347; - m_mapAreas[2].m_unk0x14 = 181; + m_mapAreas[2].m_area.SetLeft(301); + m_mapAreas[2].m_area.SetTop(133); + m_mapAreas[2].m_area.SetRight(347); + m_mapAreas[2].m_area.SetBottom(181); m_mapAreas[2].m_unk0x04 = 11; m_mapAreas[3].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Pizza_A_Bitmap"); - m_mapAreas[3].m_unk0x08 = 289; - m_mapAreas[3].m_unk0x0c = 182; - m_mapAreas[3].m_unk0x10 = 335; - m_mapAreas[3].m_unk0x14 = 225; + m_mapAreas[3].m_area.SetLeft(289); + m_mapAreas[3].m_area.SetTop(182); + m_mapAreas[3].m_area.SetRight(335); + m_mapAreas[3].m_area.SetBottom(225); m_mapAreas[3].m_unk0x04 = 12; m_mapAreas[4].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Gas_A_Bitmap"); - m_mapAreas[4].m_unk0x10 = 391; - m_mapAreas[4].m_unk0x08 = 350; - m_mapAreas[4].m_unk0x0c = 161; - m_mapAreas[4].m_unk0x14 = 209; + m_mapAreas[4].m_area.SetLeft(350); + m_mapAreas[4].m_area.SetTop(161); + m_mapAreas[4].m_area.SetRight(391); + m_mapAreas[4].m_area.SetBottom(209); m_mapAreas[4].m_unk0x04 = 13; m_mapAreas[5].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Med_A_Bitmap"); - m_mapAreas[5].m_unk0x08 = 392; - m_mapAreas[5].m_unk0x0c = 130; - m_mapAreas[5].m_unk0x10 = 438; - m_mapAreas[5].m_unk0x14 = 176; + m_mapAreas[5].m_area.SetLeft(392); + m_mapAreas[5].m_area.SetTop(130); + m_mapAreas[5].m_area.SetRight(438); + m_mapAreas[5].m_area.SetBottom(176); m_mapAreas[5].m_unk0x04 = 14; m_mapAreas[6].m_presenter = (MxStillPresenter*) Find("MxStillPresenter", "Cop_A_Bitmap"); - m_mapAreas[6].m_unk0x08 = 396; - m_mapAreas[6].m_unk0x0c = 229; - m_mapAreas[6].m_unk0x10 = 442; - m_mapAreas[6].m_unk0x14 = 272; + m_mapAreas[6].m_area.SetLeft(396); + m_mapAreas[6].m_area.SetTop(229); + m_mapAreas[6].m_area.SetRight(442); + m_mapAreas[6].m_area.SetBottom(272); m_mapAreas[6].m_unk0x04 = 15; m_frameHotBitmap = (MxStillPresenter*) Find("MxStillPresenter", "FrameHot_Bitmap"); - FUN_10070dc0(TRUE); + UpdateFrameHot(TRUE); } -// STUB: LEGO1 0x1006fd00 +// FUNCTION: LEGO1 0x1006fd00 MxU8 Infocenter::HandleMouseMove(MxS32 p_x, MxS32 p_y) { - return 1; + if (m_unk0x11c) { + if (!m_unk0x11c->IsEnabled()) { + MxS32 oldDisplayZ = m_unk0x11c->GetDisplayZ(); + + m_unk0x11c->SetDisplayZ(1000); + VideoManager()->SortPresenterList(); + m_unk0x11c->Enable(TRUE); + m_unk0x11c->VTable0x88(p_x, p_y); + + m_unk0x11c->SetDisplayZ(oldDisplayZ); + } + else { + m_unk0x11c->VTable0x88(p_x, p_y); + } + + FUN_10070d10(p_x, p_y); + return 1; + } + + return 0; } // FUNCTION: LEGO1 0x1006fda0 @@ -492,12 +511,129 @@ MxLong Infocenter::HandleKeyPress(MxS8 p_key) // STUB: LEGO1 0x1006feb0 MxU8 Infocenter::HandleButtonUp(MxS32 p_x, MxS32 p_y) { - return 1; + return FALSE; } -// STUB: LEGO1 0x10070370 -MxU8 Infocenter::HandleNotification17(MxParam&) +// FUNCTION: LEGO1 0x10070370 +MxU8 Infocenter::HandleClick(LegoControlManagerEvent& p_param) { + if (p_param.GetUnknown0x28() == 1) { + m_infoManDialogueTimer = 0; + + InfomainScript actionToPlay = c_noInfomain; + StopCurrentAction(); + InfomainScript characterBitmap = c_noInfomain; + + GameState(); + + switch (p_param.GetClickedObjectId()) { + case c_leftArrowCtl: + m_infocenterState->SetUnknown0x74(14); + StopCurrentAction(); + + if (GameState()->GetUnknown10() == 0) { + m_radio.Stop(); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_transitionDestination = 5; + } + else { + MxU32 objectId = m_infocenterState->GetUnknown0x68().FUN_10014d00(); + PlayAction((InfomainScript) objectId); + } + + break; + case c_rightArrowCtl: + m_infocenterState->SetUnknown0x74(14); + StopCurrentAction(); + + if (GameState()->GetUnknown10() == 0) { + m_radio.Stop(); + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + m_transitionDestination = 13; + } + else { + MxU32 objectId = m_infocenterState->GetUnknown0x68().FUN_10014d00(); + PlayAction((InfomainScript) objectId); + } + + break; + case c_infoCtl: + m_radio.Stop(); + break; + case c_doorCtl: + if (m_infocenterState->GetUnknown0x74() != 8) { + actionToPlay = c_exitConfirmationDialogue; + m_radio.Stop(); + m_infocenterState->SetUnknown0x74(8); + } + + break; + case c_boatCtl: + actionToPlay = c_boatCtlDescription; + m_radio.Stop(); + break; + case c_raceCtl: + actionToPlay = c_raceCtlDescription; + m_radio.Stop(); + break; + case c_pizzaCtl: + actionToPlay = c_pizzaCtlDescription; + m_radio.Stop(); + break; + case c_gasCtl: + actionToPlay = c_gasCtlDescription; + m_radio.Stop(); + break; + case c_medCtl: + actionToPlay = c_medCtlDescription; + m_radio.Stop(); + break; + case c_copCtlDescription: + actionToPlay = c_copCtlDescription; + m_radio.Stop(); + break; + case c_bigInfoCtl: + // TODO + break; + case c_bookCtl: + m_transitionDestination = 12; + m_infocenterState->SetUnknown0x74(4); + actionToPlay = GameState()->GetUnknown10() ? c_goToRegBookRed : c_goToRegBook; + m_radio.Stop(); + GameState()->SetCurrentArea(GameState()->GetPreviousArea()); + InputManager()->DisableInputProcessing(); + break; + case c_mamaCtl: + characterBitmap = c_mamaSelected; + UpdateFrameHot(FALSE); + break; + case c_papaCtl: + characterBitmap = c_papaSelected; + UpdateFrameHot(FALSE); + break; + case c_pepperCtl: + characterBitmap = c_pepperSelected; + UpdateFrameHot(FALSE); + break; + case c_nickCtl: + characterBitmap = c_nickSelected; + UpdateFrameHot(FALSE); + break; + case c_lauraCtl: + characterBitmap = c_lauraCtl; + UpdateFrameHot(FALSE); + break; + } + + if (actionToPlay != c_noInfomain) { + PlayAction(actionToPlay); + } + + if (characterBitmap != c_noInfomain) { + m_unk0x11c = (MxStillPresenter*) Find(m_atom, characterBitmap); + } + } + return 1; } @@ -601,9 +737,81 @@ MxBool Infocenter::VTable0x5c() return TRUE; } -// STUB: LEGO1 0x10070dc0 -void Infocenter::FUN_10070dc0(MxBool) +// FUNCTION: LEGO1 0x10070d10 +void Infocenter::FUN_10070d10(MxS32 p_x, MxS32 p_y) { + MxS16 i; + for (i = 0; i < (MxS32) (sizeof(m_mapAreas) / sizeof(m_mapAreas[0])); i++) { + MxS32 right = m_mapAreas[i].m_area.GetRight(); + MxS32 bottom = m_mapAreas[i].m_area.GetBottom(); + MxS32 left = m_mapAreas[i].m_area.GetLeft(); + MxS32 top = m_mapAreas[i].m_area.GetTop(); + + if (left <= p_x && p_x <= right && top <= p_y && p_y <= bottom) + break; + } + + if (i == 7) { + i = -1; + } + + if (i != m_unk0x1c8) { + if (m_unk0x1c8 != -1) { + m_mapAreas[i].m_presenter->Enable(FALSE); + } + + m_unk0x1c8 = i; + if (i != -1) { + m_mapAreas[i].m_presenter->Enable(TRUE); + } + } +} + +// FUNCTION: LEGO1 0x10070dc0 +void Infocenter::UpdateFrameHot(MxBool p_display) +{ + if (p_display) { + MxS32 x, y; + + switch (GameState()->GetUnknownC()) { + case 1: + x = 302; + y = 81; + break; + case 2: + x = 204; + y = 81; + break; + case 3: + x = 253; + y = 81; + break; + case 4: + x = 353; + y = 81; + break; + case 5: + x = 399; + y = 81; + break; + default: + return; + } + + MxS32 originalDisplayZ = m_frameHotBitmap->GetDisplayZ(); + + m_frameHotBitmap->SetDisplayZ(1000); + VideoManager()->SortPresenterList(); + + m_frameHotBitmap->Enable(TRUE); + m_frameHotBitmap->VTable0x88(x, y); + m_frameHotBitmap->SetDisplayZ(originalDisplayZ); + } + else { + if (m_frameHotBitmap) { + m_frameHotBitmap->Enable(FALSE); + } + } } // STUB: LEGO1 0x10070e90 @@ -611,9 +819,33 @@ void Infocenter::FUN_10070e90() { } -// STUB: LEGO1 0x10070f60 +// FUNCTION: LEGO1 0x10070f60 MxBool Infocenter::VTable0x64() { + if (m_infocenterState != NULL) { + MxU32 val = m_infocenterState->GetUnknown0x74(); + + if (val == 0) { + StopCutscene(); + m_infocenterState->SetUnknown0x74(1); + } + else if (val == 13) { + StopCredits(); + } + else if (val != 8) { + m_infocenterState->SetUnknown0x74(8); + +#ifdef COMPAT_MODE + { + MxNotificationParam param(c_notificationType0, NULL); + Notify(param); + } +#else + Notify(MxNotificationParam(c_notificationType0, NULL)); +#endif + } + } + return FALSE; } diff --git a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp index 4ed626ff..47ab29ac 100644 --- a/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/infocenterdoor.cpp @@ -1,11 +1,15 @@ #include "infocenterdoor.h" +#include "infocenterstate.h" #include "jukebox.h" #include "legocontrolmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" #include "legoomni.h" +#include "mxactionnotificationparam.h" +#include "mxbackgroundaudiomanager.h" #include "mxnotificationmanager.h" +#include "mxtransitionmanager.h" DECOMP_SIZE_ASSERT(InfocenterDoor, 0xfc) @@ -45,11 +49,31 @@ MxResult InfocenterDoor::Create(MxDSAction& p_dsAction) return result; } -// STUB: LEGO1 0x100379e0 +// FUNCTION: LEGO1 0x100379e0 MxLong InfocenterDoor::Notify(MxParam& p_param) { - // TODO - return LegoWorld::Notify(p_param); + MxLong result = 0; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (((MxNotificationParam&) p_param).GetType()) { + case c_notificationEndAction: + if (((MxEndActionNotificationParam&) p_param).GetAction()->GetAtomId() == m_atom) { + BackgroundAudioManager()->RaiseVolume(); + result = 1; + } + break; + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); + break; + case c_notificationTransitioned: + GameState()->SwitchArea(m_unk0xf8); + result = 1; + break; + } + } + + return result; } // FUNCTION: LEGO1 0x10037a70 @@ -60,6 +84,61 @@ void InfocenterDoor::ReadyWorld() FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } +// FUNCTION: LEGO1 0x10037a90 +MxLong InfocenterDoor::HandleClick(LegoControlManagerEvent& p_param) +{ + MxLong result = 0; + + if (p_param.GetUnknown0x28() == 1) { + DeleteObjects(&m_atom, 500, 510); + + switch (p_param.GetClickedObjectId()) { + case 1: + m_unk0xf8 = 13; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 2: + m_unk0xf8 = 5; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 3: + m_unk0xf8 = 2; + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + case 4: + if (GameState()->GetUnknownC()) { + InfocenterState* state = (InfocenterState*) GameState()->GetState("InfocenterState"); + if (state->GetInfocenterBufferElement(0) != NULL) { + m_unk0xf8 = 4; + } + else { + MxDSAction action; + action.SetObjectId(503); + action.SetAtomId(*g_infodoorScript); + BackgroundAudioManager()->LowerVolume(); + Start(&action); + } + } + else { + MxDSAction action; + action.SetObjectId(500); + action.SetAtomId(*g_infodoorScript); + BackgroundAudioManager()->LowerVolume(); + Start(&action); + } + + TransitionManager()->StartTransition(MxTransitionManager::e_pixelation, 50, FALSE, FALSE); + result = 1; + break; + } + } + + return result; +} + // FUNCTION: LEGO1 0x10037c80 void InfocenterDoor::VTable0x68(MxBool p_add) { diff --git a/LEGO1/lego/legoomni/src/infocenter/score.cpp b/LEGO1/lego/legoomni/src/infocenter/score.cpp index f75e0418..ce378399 100644 --- a/LEGO1/lego/legoomni/src/infocenter/score.cpp +++ b/LEGO1/lego/legoomni/src/infocenter/score.cpp @@ -91,7 +91,7 @@ MxLong Score::Notify(MxParam& p_param) DeleteScript(); // Shutting down ret = 1; break; - case c_notificationType17: + case c_notificationClick: ret = FUN_100016d0((LegoControlManagerEvent&) p_param); break; case c_notificationTransitioned: diff --git a/LEGO1/lego/legoomni/src/isle/isle.cpp b/LEGO1/lego/legoomni/src/isle/isle.cpp index bb6d4fd8..c8c67570 100644 --- a/LEGO1/lego/legoomni/src/isle/isle.cpp +++ b/LEGO1/lego/legoomni/src/isle/isle.cpp @@ -115,7 +115,7 @@ MxLong Isle::Notify(MxParam& p_param) break; } break; - case c_notificationType17: + case c_notificationClick: result = HandleType17Notification(p_param); break; case c_notificationType18: diff --git a/LEGO1/lego/legoomni/src/isle/radio.cpp b/LEGO1/lego/legoomni/src/isle/radio.cpp index ad5d96b7..2f18ae59 100644 --- a/LEGO1/lego/legoomni/src/isle/radio.cpp +++ b/LEGO1/lego/legoomni/src/isle/radio.cpp @@ -41,8 +41,8 @@ MxLong Radio::Notify(MxParam& p_param) case c_notificationEndAction: result = HandleEndAction((MxEndActionNotificationParam&) p_param); break; - case c_notificationType17: - result = HandleNotification17((LegoControlManagerEvent&) p_param); + case c_notificationClick: + result = HandleClick((LegoControlManagerEvent&) p_param); break; } } @@ -89,7 +89,7 @@ void Radio::Stop() } // FUNCTION: LEGO1 0x1002cbc0 -MxLong Radio::HandleNotification17(LegoControlManagerEvent& p_param) +MxLong Radio::HandleClick(LegoControlManagerEvent& p_param) { MxDSAction action; // Unused MxS32 objectId = p_param.GetClickedObjectId(); diff --git a/LEGO1/omni/include/mxnotificationparam.h b/LEGO1/omni/include/mxnotificationparam.h index 9fe01c18..d0ad675f 100644 --- a/LEGO1/omni/include/mxnotificationparam.h +++ b/LEGO1/omni/include/mxnotificationparam.h @@ -23,7 +23,7 @@ enum NotificationId { c_notificationDragStart = 13, c_notificationDrag = 14, c_notificationTimer = 15, // 100d6aa0 - c_notificationType17 = 17, + c_notificationClick = 17, c_notificationType18 = 18, // 100d7e80 c_notificationType19 = 19, // 100d6230 c_notificationType20 = 20, diff --git a/LEGO1/omni/include/mxpresenter.h b/LEGO1/omni/include/mxpresenter.h index 3d9dd355..6198cd09 100644 --- a/LEGO1/omni/include/mxpresenter.h +++ b/LEGO1/omni/include/mxpresenter.h @@ -121,6 +121,8 @@ public: m_compositePresenter = p_compositePresenter; } + inline void SetDisplayZ(MxS32 p_displayZ) { m_displayZ = p_displayZ; } + // SYNTHETIC: LEGO1 0x1000c070 // MxPresenter::`scalar deleting destructor' diff --git a/LEGO1/omni/include/mxrect32.h b/LEGO1/omni/include/mxrect32.h index 20e1706e..207d93fa 100644 --- a/LEGO1/omni/include/mxrect32.h +++ b/LEGO1/omni/include/mxrect32.h @@ -65,6 +65,7 @@ public: } inline MxBool IsValid() const { return m_left < m_right && m_top < m_bottom; } + inline MxBool IntersectsWith(const MxRect32& p_rect) const { return m_left < p_rect.m_right && p_rect.m_left < m_right && m_top < p_rect.m_bottom && p_rect.m_top < m_bottom;