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] 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; }