From e8e457f01ae7c47ef6b4fb668a6835952d58a1b1 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 29 Nov 2024 14:32:40 -0700 Subject: [PATCH] Implement/match LegoAct2::Enable (#1178) --- LEGO1/lego/legoomni/include/act2brick.h | 3 +- LEGO1/lego/legoomni/include/act3.h | 11 +- LEGO1/lego/legoomni/include/legoact2.h | 30 ++-- LEGO1/lego/legoomni/include/misc.h | 2 +- LEGO1/lego/legoomni/src/actors/buildings.cpp | 4 +- LEGO1/lego/legoomni/src/actors/helicopter.cpp | 2 +- LEGO1/lego/legoomni/src/common/misc.cpp | 4 +- LEGO1/lego/legoomni/src/entity/act2brick.cpp | 13 +- LEGO1/lego/legoomni/src/worlds/legoact2.cpp | 131 +++++++++++++++--- 9 files changed, 156 insertions(+), 44 deletions(-) diff --git a/LEGO1/lego/legoomni/include/act2brick.h b/LEGO1/lego/legoomni/include/act2brick.h index 1ff4529e..a0399730 100644 --- a/LEGO1/lego/legoomni/include/act2brick.h +++ b/LEGO1/lego/legoomni/include/act2brick.h @@ -31,7 +31,8 @@ class Act2Brick : public LegoPathActor { // SYNTHETIC: LEGO1 0x1007a450 // Act2Brick::`scalar deleting destructor' - void StopSound(); + void PlayWhistleSound(); + void StopWhistleSound(); private: static MxLong g_lastHitActorTime; diff --git a/LEGO1/lego/legoomni/include/act3.h b/LEGO1/lego/legoomni/include/act3.h index 888fc08a..9e5a6d74 100644 --- a/LEGO1/lego/legoomni/include/act3.h +++ b/LEGO1/lego/legoomni/include/act3.h @@ -1,6 +1,7 @@ #ifndef ACT3_H #define ACT3_H +#include "legogamestate.h" #include "legostate.h" #include "legoworld.h" @@ -69,7 +70,7 @@ class Act3 : public LegoWorld { void Enable(MxBool p_enable) override; // vtable+0x68 void SetUnknown420c(MxEntity* p_entity) { m_unk0x420c = p_entity; } - void SetUnknown4270(MxU32 p_unk0x4270) { m_unk0x4270 = p_unk0x4270; } + void SetDestLocation(LegoGameState::Area p_destLocation) { m_destLocation = p_destLocation; } // SYNTHETIC: LEGO1 0x10072630 // Act3::`scalar deleting destructor' @@ -80,10 +81,10 @@ class Act3 : public LegoWorld { void FUN_10073430(); protected: - undefined m_unk0xf8[0x4114]; // 0xf8 - MxEntity* m_unk0x420c; // 0x420c - undefined m_unk0x4210[0x60]; // 0x4210 - MxU32 m_unk0x4270; // 0x4270 + undefined m_unk0xf8[0x4114]; // 0xf8 + MxEntity* m_unk0x420c; // 0x420c + undefined m_unk0x4210[0x60]; // 0x4210 + LegoGameState::Area m_destLocation; // 0x4270 }; #endif // ACT3_H diff --git a/LEGO1/lego/legoomni/include/legoact2.h b/LEGO1/lego/legoomni/include/legoact2.h index c73e0c55..0af48ca0 100644 --- a/LEGO1/lego/legoomni/include/legoact2.h +++ b/LEGO1/lego/legoomni/include/legoact2.h @@ -17,7 +17,7 @@ class LegoAct2State : public LegoState { LegoAct2State() { m_unk0x08 = 0; - m_unk0x0c = 0; + m_enabled = 0; } ~LegoAct2State() override {} @@ -41,12 +41,11 @@ class LegoAct2State : public LegoState { // LegoAct2State::`scalar deleting destructor' undefined4 GetUnknown0x08() { return m_unk0x08; } - void SetUnknown0x0c(undefined p_unk0x0c) { m_unk0x0c = p_unk0x0c; } // TODO: Most likely getters/setters are not used according to BETA. undefined4 m_unk0x08; // 0x08 - undefined m_unk0x0c; // 0x0c + MxBool m_enabled; // 0x0c }; // VTABLE: LEGO1 0x100d82e0 @@ -85,23 +84,26 @@ class LegoAct2 : public LegoWorld { MxLong HandleEndAction(MxEndActionNotificationParam& p_param); MxLong HandleTransitionEnd(); MxLong HandlePathStruct(LegoPathStructNotificationParam& p_param); + void PlayMusic(JukeboxScript::Script p_objectId); void FUN_10051900(); + void InitBricks(); + void UninitBricks(); - Act2Brick m_bricks[10]; // 0x00f8 - undefined m_unk0x10c0; // 0x10c0 - undefined m_unk0x10c1; // 0x10c1 - undefined m_unk0x10c2; // 0x10c2 - undefined4 m_unk0x10c4; // 0x10c4 - undefined4 m_unk0x10c8; // 0x10c8 - LegoAct2State* m_gameState; // 0x10cc - MxS32 m_unk0x10d0; // 0x10d0 + Act2Brick m_bricks[10]; // 0x00f8 + undefined m_unk0x10c0; // 0x10c0 + undefined m_unk0x10c1; // 0x10c1 + undefined m_unk0x10c2; // 0x10c2 + undefined4 m_unk0x10c4; // 0x10c4 + JukeboxScript::Script m_music; // 0x10c8 + LegoAct2State* m_gameState; // 0x10cc + MxS32 m_unk0x10d0; // 0x10d0 // variable name verified by BETA10 0x10014633 char* m_siFile; // 0x10d4 - LegoROI* m_unk0x10d8; // 0x10d8 + LegoROI* m_pepper; // 0x10d8 MxMatrix m_unk0x10dc; // 0x10dc - undefined4 m_unk0x1124; // 0x1124 + LegoPathBoundary* m_unk0x1124; // 0x1124 LegoROI* m_ambulance; // 0x1128 undefined4 m_unk0x112c; // 0x112c undefined4 m_unk0x1130; // 0x1130 @@ -109,7 +111,7 @@ class LegoAct2 : public LegoWorld { Act2Actor* m_unk0x1138; // 0x1138 undefined m_unk0x113c; // 0x113c undefined4 m_unk0x1140; // 0x1140 - undefined4 m_unk0x1144; // 0x1144 + Act2mainScript::Script m_unk0x1144; // 0x1144 undefined m_unk0x1148[0x08]; // 0x1148 LegoGameState::Area m_destLocation; // 0x1150 }; diff --git a/LEGO1/lego/legoomni/include/misc.h b/LEGO1/lego/legoomni/include/misc.h index 9f476ae9..374b83f2 100644 --- a/LEGO1/lego/legoomni/include/misc.h +++ b/LEGO1/lego/legoomni/include/misc.h @@ -58,7 +58,7 @@ LegoWorld* FindWorld(const MxAtomId& p_atom, MxS32 p_entityid); MxDSAction& GetCurrentAction(); void SetCurrentWorld(LegoWorld* p_world); MxTransitionManager* TransitionManager(); -void PlayMusic(JukeboxScript::Script p_script); +void PlayMusic(JukeboxScript::Script p_objectId); void SetIsWorldActive(MxBool p_isWorldActive); void DeleteObjects(MxAtomId* p_id, MxS32 p_first, MxS32 p_last); diff --git a/LEGO1/lego/legoomni/src/actors/buildings.cpp b/LEGO1/lego/legoomni/src/actors/buildings.cpp index 64188031..ea7069cc 100644 --- a/LEGO1/lego/legoomni/src/actors/buildings.cpp +++ b/LEGO1/lego/legoomni/src/actors/buildings.cpp @@ -62,13 +62,13 @@ MxLong InfoCenterEntity::HandleClick(LegoEventNotificationParam& p_param) LegoAct2State* act2state = (LegoAct2State*) GameState()->GetState("LegoAct2State"); if (act2state) { - act2state->SetUnknown0x0c(0); + act2state->m_enabled = FALSE; } break; } case LegoGameState::Act::e_act3: Act3* act3 = (Act3*) FindWorld(*g_act3Script, Act3Script::c__Act3); - act3->SetUnknown4270(2); + act3->SetDestLocation(LegoGameState::e_infomain); break; } diff --git a/LEGO1/lego/legoomni/src/actors/helicopter.cpp b/LEGO1/lego/legoomni/src/actors/helicopter.cpp index 20088cf3..395ef5a6 100644 --- a/LEGO1/lego/legoomni/src/actors/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/actors/helicopter.cpp @@ -173,7 +173,7 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) switch (p_param.GetClickedObjectId()) { case IsleScript::c_HelicopterArms_Ctl: if (*g_act3Script == script) { - ((Act3*) CurrentWorld())->SetUnknown4270(2); + ((Act3*) CurrentWorld())->SetDestLocation(LegoGameState::e_infomain); TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); } else if (m_state->GetUnkown8() != 0) { diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 654a4b3d..5913ff74 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -208,11 +208,11 @@ MxTransitionManager* TransitionManager() } // FUNCTION: LEGO1 0x10015910 -void PlayMusic(JukeboxScript::Script p_script) +void PlayMusic(JukeboxScript::Script p_objectId) { MxDSAction action; action.SetAtomId(*g_jukeboxScript); - action.SetObjectId(p_script); + action.SetObjectId(p_objectId); LegoOmni::GetInstance()->GetBackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); } diff --git a/LEGO1/lego/legoomni/src/entity/act2brick.cpp b/LEGO1/lego/legoomni/src/entity/act2brick.cpp index a5811f26..9724f3b4 100644 --- a/LEGO1/lego/legoomni/src/entity/act2brick.cpp +++ b/LEGO1/lego/legoomni/src/entity/act2brick.cpp @@ -79,7 +79,7 @@ MxLong Act2Brick::Notify(MxParam& p_param) m_roi->SetVisibility(FALSE); if (m_whistleSound != NULL) { - StopSound(); + StopWhistleSound(); } MxNotificationParam param(c_notificationType22, this); @@ -90,9 +90,18 @@ MxLong Act2Brick::Notify(MxParam& p_param) return 0; } +// FUNCTION: LEGO1 0x1007a990 +// FUNCTION: BETA10 0x10012fca +void Act2Brick::PlayWhistleSound() +{ + if (m_whistleSound == NULL) { + m_whistleSound = SoundManager()->GetCacheSoundManager()->Play("xwhistle", m_roi->GetName(), TRUE); + } +} + // FUNCTION: LEGO1 0x1007a9d0 // FUNCTION: BETA10 0x1001300f -void Act2Brick::StopSound() +void Act2Brick::StopWhistleSound() { if (m_whistleSound != NULL) { SoundManager()->GetCacheSoundManager()->Stop(m_whistleSound); diff --git a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp index 7612bc34..ac120934 100644 --- a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp +++ b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp @@ -4,6 +4,7 @@ #include "act2main_actions.h" #include "infomain_actions.h" #include "islepathactor.h" +#include "jukebox_actions.h" #include "legoanimationmanager.h" #include "legocachesoundmanager.h" #include "legogamestate.h" @@ -11,6 +12,7 @@ #include "legomain.h" #include "legopathstruct.h" #include "legosoundmanager.h" +#include "legoutils.h" #include "misc.h" #include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" @@ -18,6 +20,7 @@ #include "mxmisc.h" #include "mxnotificationmanager.h" #include "mxticklemanager.h" +#include "scripts.h" #include @@ -49,7 +52,7 @@ LegoAct2::LegoAct2() { m_unk0x10c4 = 0; m_gameState = NULL; - m_unk0x10d8 = NULL; + m_pepper = NULL; m_ambulance = NULL; m_unk0x10c2 = 0; m_unk0x1130 = 0; @@ -57,9 +60,9 @@ LegoAct2::LegoAct2() m_unk0x10c1 = 0; m_unk0x1138 = NULL; m_unk0x1140 = 0; - m_unk0x1144 = 0; + m_unk0x1144 = Act2mainScript::c__Act2Main; m_destLocation = LegoGameState::e_undefined; - m_unk0x10c8 = 0; + m_music = JukeboxScript::c_MusicTheme1; m_siFile = ""; m_unk0x113c = 5; NotificationManager()->Register(this); @@ -150,7 +153,7 @@ MxResult LegoAct2::Tickle() m_unk0x10c4 = 1; break; case 1: - ((LegoPathActor*) m_unk0x10d8->GetEntity())->SetState(LegoPathActor::c_bit3); + ((LegoPathActor*) m_pepper->GetEntity())->SetState(LegoPathActor::c_bit3); switch (rand() % 3) { case 0: @@ -201,12 +204,12 @@ MxResult LegoAct2::Tickle() distance = DISTSQRD3(pepperPosition, otherPoint); - if (m_unk0x1144 == 0 && distance > 50.0f && pepperPosition[0] > -57.0f) { + if (m_unk0x1144 == Act2mainScript::c__Act2Main && distance > 50.0f && pepperPosition[0] > -57.0f) { FUN_10052560(Act2mainScript::c_Avo906In_PlayWav, FALSE, FALSE, NULL, NULL, NULL); m_unk0x1144 = Act2mainScript::c_Avo906In_PlayWav; } } - else if (m_unk0x10d0 >= 90000 && m_unk0x10d0 % 90000 == 0 && m_unk0x1144 == 0) { + else if (m_unk0x10d0 >= 90000 && m_unk0x10d0 % 90000 == 0 && m_unk0x1144 == Act2mainScript::c__Act2Main) { FUN_10052560(Act2mainScript::c_Avo908In_PlayWav, FALSE, FALSE, NULL, NULL, NULL); m_unk0x1144 = Act2mainScript::c_Avo908In_PlayWav; } @@ -266,7 +269,7 @@ MxLong LegoAct2::Notify(MxParam& p_param) m_ambulance = FindROI("ambul"); } - if (entity->GetROI() == m_unk0x10d8) { + if (entity->GetROI() == m_pepper) { HandlePathStruct(param); } @@ -283,12 +286,12 @@ MxLong LegoAct2::Notify(MxParam& p_param) LegoEntity* entity = (LegoEntity*) param.GetSender(); Mx3DPointFloat entityPosition(entity->GetROI()->GetWorldPosition()); - Mx3DPointFloat unk0x10d8(m_unk0x10d8->GetWorldPosition()); + Mx3DPointFloat unk0x10d8(m_pepper->GetWorldPosition()); Mx3DPointFloat locala4(unk0x10d8); ((Vector3&) entityPosition).Sub(unk0x10d8); - MxMatrix local2world(m_unk0x10d8->GetLocal2World()); + MxMatrix local2world(m_pepper->GetLocal2World()); Vector3 local30(local2world[0]); Vector3 localac(local2world[1]); Vector3 local28(local2world[2]); @@ -309,7 +312,7 @@ MxLong LegoAct2::Notify(MxParam& p_param) m_unk0x10c4 = 14; m_unk0x10d0 = 0; - ((LegoPathActor*) m_unk0x10d8->GetEntity())->SetState(LegoPathActor::c_bit3); + ((LegoPathActor*) m_pepper->GetEntity())->SetState(LegoPathActor::c_bit3); } break; case c_notificationTransitioned: @@ -345,11 +348,76 @@ void LegoAct2::ReadyWorld() // TODO } -// STUB: LEGO1 0x10050cf0 -// STUB: BETA10 0x1003bb2d +// FUNCTION: LEGO1 0x10050cf0 +// FUNCTION: BETA10 0x1003bb2d void LegoAct2::Enable(MxBool p_enable) { - // TODO + if (m_set0xd0.empty() == p_enable) { + return; + } + + LegoWorld::Enable(p_enable); + + if (p_enable) { + m_gameState->m_enabled = TRUE; + + GameState()->SetActor(LegoActor::c_pepper); + m_pepper = FindROI("pepper"); + + ((IslePathActor*) m_pepper->GetEntity())->VTable0xec(m_unk0x10dc, m_unk0x1124, TRUE); + + if (GameState()->GetPreviousArea() == LegoGameState::e_infomain) { + GameState()->StopArea(LegoGameState::e_infomain); + } + + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + + if (m_unk0x10c4 != 6 && m_unk0x10c4 != 12) { + PlayMusic(m_music); + } + + if (m_unk0x10c4 == 10 && m_unk0x10c0 == 6 && m_bricks[5].GetROI() != NULL) { + m_bricks[5].PlayWhistleSound(); + } + else if (m_unk0x10c4 == 13) { + InitBricks(); + } + + TickleManager()->RegisterClient(this, 20); + SetAppCursor(e_cursorArrow); + + if (m_unk0x10c4 == 2 || m_unk0x10c4 == 4 || m_unk0x10c4 == 6 || m_unk0x10c4 == 11 || m_unk0x10c4 == 12 || + m_unk0x10c4 == 14) { + MxDSAction action; + MxEndActionNotificationParam param(c_notificationEndAction, NULL, &action, FALSE); + + m_unk0x1140 = 0; + action.SetObjectId(0); + HandleEndAction(param); + } + + GameState()->m_isDirty = TRUE; + } + else { + m_unk0x10dc = m_pepper->GetLocal2World(); + m_unk0x1124 = ((LegoPathActor*) m_pepper->GetEntity())->GetBoundary(); + + FUN_10051900(); + BackgroundAudioManager()->Stop(); + UninitBricks(); + DeleteObjects(&m_atomId, Act2mainScript::c_VOhead0_PlayWav, Act2mainScript::c_VOhide_PlayWav); + + if (m_unk0x1144 != Act2mainScript::c__Act2Main) { + MxDSAction action; + action.SetAtomId(m_atomId); + action.SetUnknown24(-2); + action.SetObjectId(m_unk0x1144); + DeleteObject(action); + m_unk0x1144 = Act2mainScript::c__Act2Main; + } + + TickleManager()->UnregisterClient(this); + } } // STUB: LEGO1 0x10051460 @@ -360,6 +428,17 @@ MxLong LegoAct2::HandlePathStruct(LegoPathStructNotificationParam& p_param) return 0; } +// FUNCTION: LEGO1 0x10051840 +void LegoAct2::PlayMusic(JukeboxScript::Script p_objectId) +{ + MxDSAction action; + action.SetAtomId(*g_jukeboxScript); + action.SetObjectId(p_objectId); + + BackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); + m_music = p_objectId; +} + // FUNCTION: LEGO1 0x10051900 // FUNCTION: BETA10 0x1003bed1 void LegoAct2::FUN_10051900() @@ -394,13 +473,33 @@ MxBool LegoAct2::Escape() } if (m_gameState != NULL) { - m_gameState->m_unk0x0c = 0; + m_gameState->m_enabled = FALSE; } m_destLocation = LegoGameState::e_infomain; return TRUE; } +// FUNCTION: LEGO1 0x10051a60 +void LegoAct2::InitBricks() +{ + for (MxS32 i = 0; i < (MxS32) sizeOfArray(m_bricks); i++) { + if (m_bricks[i].GetROI() != NULL && m_bricks[i].GetROI()->GetVisibility()) { + m_bricks[i].PlayWhistleSound(); + } + } +} + +// FUNCTION: LEGO1 0x10051a90 +void LegoAct2::UninitBricks() +{ + for (MxS32 i = 0; i < (MxS32) sizeOfArray(m_bricks); i++) { + if (m_bricks[i].GetROI() != NULL) { + m_bricks[i].StopWhistleSound(); + } + } +} + // FUNCTION: LEGO1 0x10052560 // FUNCTION: BETA10 0x100145c6 undefined4 LegoAct2::FUN_10052560( @@ -420,8 +519,8 @@ undefined4 LegoAct2::FUN_10052560( MxDSAction action; action.SetObjectId(p_param1); - // not entirely sure about the constant - action.SetAtomId(*Lego()->GetWorldAtom(InfomainScript::c_Cop_Ctl)); + // World index: see LegoOmni::RegisterWorlds + action.SetAtomId(*Lego()->GetWorldAtom(15)); if (p_location) { action.SetUp(Mx3DPointFloat(0.0f, 1.0f, 0.0f));