diff --git a/LEGO1/lego/legoomni/include/act3.h b/LEGO1/lego/legoomni/include/act3.h index b44c1d59..306da129 100644 --- a/LEGO1/lego/legoomni/include/act3.h +++ b/LEGO1/lego/legoomni/include/act3.h @@ -24,13 +24,14 @@ struct Act3ListElement { }; // SIZE 0x10 -class Act3List { +class Act3List : private list { public: Act3List() { m_unk0x04 = 0; } + void FUN_100720d0(MxU32 p_objectId); + private: - list m_unk0x00; // 0x00 - undefined4 m_unk0x04; // 0x0c + undefined4 m_unk0x04; // 0x0c }; // VTABLE: LEGO1 0x100d4fc8 @@ -108,6 +109,8 @@ class Act3 : public LegoWorld { void FUN_10073430(); protected: + MxLong HandleTransitionEnd(); + Act3State* m_state; // 0xf8 Act3Ammo m_pizzas[MAX_PIZZAS]; // 0xfc Act3Ammo m_donuts[MAX_DONUTS]; // 0x217c @@ -118,12 +121,15 @@ class Act3 : public LegoWorld { Helicopter* m_copter; // 0x420c Act3Shark* m_shark; // 0x4210 MxFloat m_time; // 0x4214 - undefined4 m_unk0x4218; // 0x4218 + undefined m_unk0x4218; // 0x4218 + undefined m_unk0x4219; // 0x4219 + undefined m_unk0x421a; // 0x421a + undefined m_unk0x421b; // 0x421b undefined m_unk0x421c; // 0x421c undefined m_unk0x421d; // 0x421d undefined m_unk0x421e; // 0x421e Act3List m_unk0x4220; // 0x4220 - undefined4 m_unk0x4230[15]; // 0x4230 + MxPresenter* m_helicopterDots[15]; // 0x4230 Act3Script::Script m_unk0x426c; // 0x426c LegoGameState::Area m_destLocation; // 0x4270 }; diff --git a/LEGO1/lego/legoomni/include/act3brickster.h b/LEGO1/lego/legoomni/include/act3brickster.h index 1e418abf..4e0c8240 100644 --- a/LEGO1/lego/legoomni/include/act3brickster.h +++ b/LEGO1/lego/legoomni/include/act3brickster.h @@ -29,6 +29,8 @@ class Act3Brickster : public Act3Actor { void SetUnknown0x24(MxFloat p_unk0x24) { m_unk0x24 = p_unk0x24; } void SetUnknown0x50(MxFloat p_unk0x50) { m_unk0x50 = p_unk0x50; } + MxResult FUN_100417c0(); + // SYNTHETIC: LEGO1 0x10043250 // Act3Brickster::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/helicopter.h b/LEGO1/lego/legoomni/include/helicopter.h index a7be42bc..1044dae2 100644 --- a/LEGO1/lego/legoomni/include/helicopter.h +++ b/LEGO1/lego/legoomni/include/helicopter.h @@ -5,6 +5,8 @@ #include "legostate.h" #include "realtime/matrix.h" +class Act3; + // VTABLE: LEGO1 0x100d5418 // SIZE 0x0c class HelicopterState : public LegoState { @@ -78,6 +80,9 @@ class Helicopter : public IslePathActor { // SYNTHETIC: LEGO1 0x10003210 // Helicopter::`scalar deleting destructor' + // m_state is accessed directly from Act3; confirmed by BETA10 + friend class Act3; + protected: MxMatrix m_unk0x160; // 0x160 MxMatrix m_unk0x1a8; // 0x1a8 diff --git a/LEGO1/lego/legoomni/src/actors/act3brickster.cpp b/LEGO1/lego/legoomni/src/actors/act3brickster.cpp index 395ffe04..6197d429 100644 --- a/LEGO1/lego/legoomni/src/actors/act3brickster.cpp +++ b/LEGO1/lego/legoomni/src/actors/act3brickster.cpp @@ -33,6 +33,14 @@ MxResult Act3Brickster::VTable0x94(LegoPathActor*, MxBool) return SUCCESS; } +// STUB: LEGO1 0x100417c0 +// STUB: BETA10 0x1001a407 +MxResult Act3Brickster::FUN_100417c0() +{ + // TODO + return SUCCESS; +} + // STUB: LEGO1 0x10042990 void Act3Brickster::SwitchBoundary(LegoPathBoundary*& p_boundary, LegoUnknown100db7f4*& p_edge, float& p_unk0xe4) { diff --git a/LEGO1/lego/legoomni/src/worlds/act3.cpp b/LEGO1/lego/legoomni/src/worlds/act3.cpp index a7b568dc..c2c6f65a 100644 --- a/LEGO1/lego/legoomni/src/worlds/act3.cpp +++ b/LEGO1/lego/legoomni/src/worlds/act3.cpp @@ -16,12 +16,14 @@ #include "legoutils.h" #include "legovideomanager.h" #include "misc.h" +#include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" #include "mxmisc.h" #include "mxnotificationmanager.h" #include "mxticklemanager.h" #include "mxtimer.h" #include "mxtransitionmanager.h" +#include "scripts.h" DECOMP_SIZE_ASSERT(Act3, 0x4274) DECOMP_SIZE_ASSERT(Act3State, 0x0c) @@ -32,6 +34,12 @@ DECOMP_SIZE_ASSERT(Act3List, 0x10) Act3Script::Script g_unk0x100d95e8[] = {Act3Script::c_tlp053in_RunAnim, Act3Script::c_tlp064la_RunAnim, Act3Script::c_tlp068in_RunAnim}; +// STUB: LEGO1 0x100720d0 +void Act3List::FUN_100720d0(MxU32 p_objectId) +{ + // TODO +} + // FUNCTION: LEGO1 0x10072270 // FUNCTION: BETA10 0x10015470 Act3::Act3() @@ -46,7 +54,7 @@ Act3::Act3() m_time = -1; m_unk0x421e = 0; - memset(m_unk0x4230, 0, sizeof(m_unk0x4230)); + memset(m_helicopterDots, 0, sizeof(m_helicopterDots)); NavController()->ResetMaxLinearAccel(NavController()->GetMaxLinearAccel() * 30.0f); NavController()->ResetMaxLinearDeccel(NavController()->GetMaxLinearDeccel() * 30.0f); @@ -153,14 +161,130 @@ void Act3::Destroy(MxBool p_fromDestructor) } } -// STUB: LEGO1 0x10072de0 -// STUB: BETA10 0x10016322 +// FUNCTION: LEGO1 0x10072de0 +// FUNCTION: BETA10 0x10016322 MxLong Act3::Notify(MxParam& p_param) { - // TODO + MxNotificationParam& param = (MxNotificationParam&) p_param; + LegoWorld::Notify(p_param); + + if (m_worldStarted) { + switch (param.GetNotification()) { + case c_notificationEndAction: { + MxEndActionNotificationParam& param = (MxEndActionNotificationParam&) p_param; + + if (param.GetAction() != NULL && param.GetAction()->GetAtomId() == *g_act3Script) { + if (param.GetAction()->GetObjectId() == Act3Script::c_HelicopterDashboard) { + MxDSAction action; + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + SetAppCursor(e_cursorArrow); + VideoManager()->Get3DManager()->SetFrustrum(45.0f, 0.1f, 125.0f); + + m_brickster->SetWorldSpeed(5.0f); + m_brickster->SetState(0); + assert(BackgroundAudioManager()); + + action.SetAtomId(*g_jukeboxScript); + action.SetObjectId(Act3Script::c_pzhitdn_PlayWav); + + BackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); + m_brickster->FUN_100417c0(); + + m_cop1->SetState(0); + m_cop1->SetWorldSpeed(2.0f); + m_cop1->VTable0xa8(); + + m_cop2->SetState(0); + m_cop2->SetWorldSpeed(2.0f); + m_cop2->VTable0xa8(); + + m_brickster->VTable0xa8(); + + m_unk0x4218 = 0; + m_unk0x4219 = 0; + m_unk0x421a = 0; + m_unk0x421b = 0; + m_unk0x421c = 0; + m_unk0x421d = 0; + + MxS32 length; + LegoBuildingInfo* info = BuildingManager()->GetInfoArray(length); + m_unk0x421e = 0; + + while (--length >= 0) { + if (info[length].m_unk0x11 < 0 && info[length].m_boundary != NULL && + info[length].m_entity != NULL) { + m_unk0x421e++; + } + } + + length = 0; + m_unk0x421e--; + char buf[80]; + + do { + sprintf(buf, "HelicopterDotOn%d_Bitmap", length + 1); + m_helicopterDots[length] = (MxPresenter*) Find("MxPresenter", buf); + + if (m_unk0x421e > length) { + m_helicopterDots[length]->Enable(TRUE); + } + else { + m_helicopterDots[length]->Enable(FALSE); + } + + length++; + } while (length < (MxS32) sizeOfArray(m_helicopterDots)); + } + else { + m_unk0x4220.FUN_100720d0(param.GetAction()->GetObjectId()); + } + } + break; + } + case c_notificationKeyPress: + if (m_state->m_unk0x08 == 1 && ((LegoEventNotificationParam&) p_param).GetKey() == ' ') { + AnimationManager()->FUN_10061010(FALSE); + return 1; + } + break; + case c_notificationButtonUp: + case c_notificationButtonDown: + if (m_state->m_unk0x08 == 1) { + return 1; + } + break; + case c_notificationEndAnim: + if (m_state->m_unk0x08 == 1) { + assert(m_copter && m_brickster && m_cop1 && m_cop2); + m_unk0x4220.FUN_100720d0(NULL); + m_state->m_unk0x08 = 0; + FUN_10015820(TRUE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + m_copter->HandleClick(); + m_copter->m_state->m_unk0x08 = 1; + m_copter->HandleEndAnim((LegoEndAnimNotificationParam&) param); + } + break; + case c_notificationTransitioned: + HandleTransitionEnd(); + return 1; + } + } + return 0; } +// FUNCTION: LEGO1 0x10073240 +MxLong Act3::HandleTransitionEnd() +{ + if (m_destLocation != LegoGameState::e_undefined) { + GameState()->SwitchArea(m_destLocation); + m_destLocation = LegoGameState::e_undefined; + } + + return 1; +} + // FUNCTION: LEGO1 0x10073270 void Act3::ReadyWorld() {