From e5d66d597d66d7a014736b62199cbf79399342cf Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 13 Jun 2024 14:32:28 -0400 Subject: [PATCH] Implement/match remaining Ambulance functions (#1030) --- LEGO1/lego/legoomni/include/ambulance.h | 2 +- LEGO1/lego/legoomni/include/legostate.h | 68 ++++++++--------- LEGO1/lego/legoomni/src/actors/ambulance.cpp | 77 ++++++++++++++++---- 3 files changed, 99 insertions(+), 48 deletions(-) diff --git a/LEGO1/lego/legoomni/include/ambulance.h b/LEGO1/lego/legoomni/include/ambulance.h index 70577f3a..3c6d8f0b 100644 --- a/LEGO1/lego/legoomni/include/ambulance.h +++ b/LEGO1/lego/legoomni/include/ambulance.h @@ -146,7 +146,7 @@ class Ambulance : public IslePathActor { void PlayFinalAnimation(IsleScript::Script p_objectId); void StopAction(IsleScript::Script p_objectId); void PlayAction(IsleScript::Script p_objectId); - void FUN_10036ec0(); + void Leave(); undefined m_unk0x160[4]; // 0x160 AmbulanceMissionState* m_state; // 0x164 diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index b181133f..1e149681 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -16,40 +16,6 @@ class LegoState : public MxCore { e_red }; - // FUNCTION: LEGO1 0x10005f40 - ~LegoState() override {} - - // FUNCTION: LEGO1 0x100060d0 - inline const char* ClassName() const override // vtable+0x0c - { - // STRING: LEGO1 0x100f01b8 - return "LegoState"; - } - - // FUNCTION: LEGO1 0x100060e0 - inline MxBool IsA(const char* p_name) const override // vtable+0x10 - { - return !strcmp(p_name, LegoState::ClassName()) || MxCore::IsA(p_name); - } - - // FUNCTION: LEGO1 0x10005f90 - virtual MxBool IsSerializable() { return TRUE; } // vtable+0x14 - - // FUNCTION: LEGO1 0x10005fa0 - virtual MxBool SetFlag() { return FALSE; } // vtable+0x18 - - // FUNCTION: LEGO1 0x10005fb0 - virtual MxResult Serialize(LegoFile* p_legoFile) - { - if (p_legoFile->IsWriteMode()) { - p_legoFile->WriteString(ClassName()); - } - return SUCCESS; - } // vtable+0x1c - - // SYNTHETIC: LEGO1 0x10006160 - // LegoState::`scalar deleting destructor' - // SIZE 0x0c class Playlist { public: @@ -98,6 +64,40 @@ class LegoState : public MxCore { MxS16 m_mode; // 0x06 MxS16 m_nextIndex; // 0x08 }; + + // FUNCTION: LEGO1 0x10005f40 + ~LegoState() override {} + + // FUNCTION: LEGO1 0x100060d0 + inline const char* ClassName() const override // vtable+0x0c + { + // STRING: LEGO1 0x100f01b8 + return "LegoState"; + } + + // FUNCTION: LEGO1 0x100060e0 + inline MxBool IsA(const char* p_name) const override // vtable+0x10 + { + return !strcmp(p_name, LegoState::ClassName()) || MxCore::IsA(p_name); + } + + // FUNCTION: LEGO1 0x10005f90 + virtual MxBool IsSerializable() { return TRUE; } // vtable+0x14 + + // FUNCTION: LEGO1 0x10005fa0 + virtual MxBool SetFlag() { return FALSE; } // vtable+0x18 + + // FUNCTION: LEGO1 0x10005fb0 + virtual MxResult Serialize(LegoFile* p_legoFile) + { + if (p_legoFile->IsWriteMode()) { + p_legoFile->WriteString(ClassName()); + } + return SUCCESS; + } // vtable+0x1c + + // SYNTHETIC: LEGO1 0x10006160 + // LegoState::`scalar deleting destructor' }; #endif // LEGOSTATE_H diff --git a/LEGO1/lego/legoomni/src/actors/ambulance.cpp b/LEGO1/lego/legoomni/src/actors/ambulance.cpp index 542c9fb1..4b9f86a6 100644 --- a/LEGO1/lego/legoomni/src/actors/ambulance.cpp +++ b/LEGO1/lego/legoomni/src/actors/ambulance.cpp @@ -16,6 +16,7 @@ #include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" #include "mxmisc.h" +#include "mxsoundpresenter.h" #include "mxticklemanager.h" #include "mxtimer.h" #include "mxtransitionmanager.h" @@ -25,6 +26,9 @@ DECOMP_SIZE_ASSERT(Ambulance, 0x184) DECOMP_SIZE_ASSERT(AmbulanceMissionState, 0x24) +// Flags used in isle.cpp +extern MxU32 g_isleFlags; + // FUNCTION: LEGO1 0x10035ee0 // FUNCTION: BETA10 0x10022820 Ambulance::Ambulance() @@ -278,7 +282,7 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructEvent& p_param) InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL); } - FUN_10036ec0(); + Leave(); MxLong time = Timer()->GetTime() - m_state->m_unk0x0c; if (time < 300000) { @@ -323,7 +327,7 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructEvent& p_param) InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL); } - FUN_10036ec0(); + Leave(); if (m_actorId < LegoActor::c_pepper || m_actorId > LegoActor::c_laura) { m_actorId = LegoActor::c_laura; @@ -353,7 +357,7 @@ MxLong Ambulance::HandlePathStruct(LegoPathStructEvent& p_param) InvokeAction(Extra::e_stop, *g_isleScript, m_lastAction, NULL); } - FUN_10036ec0(); + Leave(); PlayAnimation(IsleScript::c_hps116bd_RunAnim); } @@ -406,23 +410,60 @@ void Ambulance::FUN_10036e60() m_lastAnimation = IsleScript::c_noneIsle; } -// STUB: LEGO1 0x10036e90 +// FUNCTION: LEGO1 0x10036e90 void Ambulance::Exit() { - // TODO + GameState()->m_currentArea = LegoGameState::e_hospitalExterior; + StopActions(); + FUN_10037250(); + Leave(); } -// STUB: LEGO1 0x10036ec0 -void Ambulance::FUN_10036ec0() +// FUNCTION: LEGO1 0x10036ec0 +void Ambulance::Leave() { - // TODO + IslePathActor::Exit(); + CurrentWorld()->RemoveActor(this); + m_roi->SetVisibility(FALSE); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_AmbulanceDashboard_Bitmap); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_AmbulanceArms_Ctl); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_AmbulanceHorn_Ctl); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_AmbulanceHorn_Sound); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_AmbulanceInfo_Ctl); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_AmbulanceSpeedMeter); + RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_AmbulanceFuelMeter); + ControlManager()->Unregister(this); + TickleManager()->UnregisterClient(this); } -// STUB: LEGO1 0x10036f90 +// FUNCTION: LEGO1 0x10036f90 MxLong Ambulance::HandleControl(LegoControlManagerEvent& p_param) { - // TODO - return 0; + MxLong result = 0; + + if (p_param.GetUnknown0x28() == 1) { + switch (p_param.GetClickedObjectId()) { + case IsleScript::c_AmbulanceArms_Ctl: + Exit(); + GameState()->m_currentArea = LegoGameState::e_unk66; + result = 1; + break; + case IsleScript::c_AmbulanceInfo_Ctl: + ((Isle*) CurrentWorld())->SetDestLocation(LegoGameState::e_infomain); + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + Exit(); + GameState()->m_currentArea = LegoGameState::e_unk66; + result = 1; + break; + case IsleScript::c_AmbulanceHorn_Ctl: + MxSoundPresenter* presenter = + (MxSoundPresenter*) CurrentWorld()->Find("MxSoundPresenter", "AmbulanceHorn_Sound"); + presenter->Enable(p_param.GetUnknown0x28()); + break; + } + } + + return result; } // FUNCTION: LEGO1 0x10037060 @@ -533,10 +574,20 @@ void Ambulance::StopActions() StopAction(IsleScript::c_pns018rd_RunAnim); } -// STUB: LEGO1 0x10037250 +// FUNCTION: LEGO1 0x10037250 void Ambulance::FUN_10037250() { - // TODO + StopAction(m_lastAction); + BackgroundAudioManager()->RaiseVolume(); + ((Act1State*) GameState()->GetState("Act1State"))->m_unk0x018 = 0; + m_state->m_unk0x08 = 0; + m_unk0x16e = 0; + m_unk0x16c = 0; + g_isleFlags |= Isle::c_playMusic; + AnimationManager()->EnableCamAnims(TRUE); + AnimationManager()->FUN_1005f6d0(TRUE); + m_state->m_unk0x0c = INT_MIN; + m_state = NULL; } // FUNCTION: LEGO1 0x100372e0