From 4c0aae720b3a65a8033d53a98fd26a4bf101e267 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Fri, 1 Nov 2024 17:21:15 +0100 Subject: [PATCH] Implement `LegoCarBuild::FUN_10024890()` and others, refactor (#1126) * Commit finished code changes * Add enum data type * Refactor away GetCurrentArea, SetCurrentArea * Clean up and add FUN_10024890 * Add `SetPartObjectIdByName()` * Fix naming error * Address review comments, part 1 * Address review comments, part 2 --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/legocarbuild.h | 16 +- .../legoomni/include/legocarbuildpresenter.h | 25 +- LEGO1/lego/legoomni/include/legogamestate.h | 2 - .../lego/legoomni/include/legoinputmanager.h | 2 + .../legoomni/include/mxtransitionmanager.h | 21 +- LEGO1/lego/legoomni/src/actors/bike.cpp | 2 +- LEGO1/lego/legoomni/src/actors/helicopter.cpp | 4 +- .../lego/legoomni/src/build/legocarbuild.cpp | 363 ++++++++++++++++-- .../src/build/legocarbuildpresenter.cpp | 25 ++ LEGO1/lego/legoomni/src/common/legoutils.cpp | 1 + LEGO1/lego/legoomni/src/common/misc.cpp | 2 + .../src/common/mxtransitionmanager.cpp | 25 +- .../src/control/legocontrolmanager.cpp | 1 + .../legoomni/src/input/legoinputmanager.cpp | 1 + .../legoomni/src/video/legovideomanager.cpp | 2 +- .../legoomni/src/worlds/elevatorbottom.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/gasstation.cpp | 2 +- .../lego/legoomni/src/worlds/historybook.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/hospital.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/infocenter.cpp | 10 +- .../legoomni/src/worlds/infocenterdoor.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/isle.cpp | 4 +- LEGO1/lego/legoomni/src/worlds/jukebox.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/police.cpp | 2 +- .../legoomni/src/worlds/registrationbook.cpp | 2 +- LEGO1/lego/legoomni/src/worlds/score.cpp | 2 +- LEGO1/library_msvc.h | 1 + LEGO1/mxgeometry/mxgeometry3d.h | 1 + LEGO1/mxgeometry/mxmatrix.h | 1 + .../omni/src/notify/mxnotificationmanager.cpp | 1 + LEGO1/realtime/orientableroi.h | 1 + LEGO1/realtime/vector.h | 9 +- 32 files changed, 445 insertions(+), 93 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index 0afb08245c..a18082dbaa 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -6,6 +6,7 @@ #include "legoworld.h" class LegoCarBuildAnimPresenter; +class LegoControlManagerNotificationParam; class LegoEventNotificationParam; class MxControlPresenter; class MxStillPresenter; @@ -21,6 +22,7 @@ class LegoVehicleBuildState : public LegoState { e_entering = 1, e_unknown2 = 2, e_cutscene = 3, + e_unknown4 = 4, e_exiting = 6 }; @@ -71,6 +73,11 @@ typedef LegoVehicleBuildState LegoJetskiBuildState; // SIZE 0x34c class LegoCarBuild : public LegoWorld { public: + enum Unknown0xf8 { + c_unknownminusone = -1, + c_unknown8 = 8 + }; + LegoCarBuild(); ~LegoCarBuild() override; @@ -117,14 +124,16 @@ class LegoCarBuild : public LegoWorld { undefined4 FUN_100244e0(MxLong p_x, MxLong p_y); undefined4 FUN_100246e0(MxLong p_x, MxLong p_y); MxS32 FUN_10024850(MxLong p_x, MxLong p_y); - undefined4 FUN_10024890(LegoEventNotificationParam* p_param); + undefined4 FUN_10024890(MxParam* p_param); undefined4 FUN_10024c20(LegoEventNotificationParam* p_param); void FUN_10024ef0(); + void FUN_10024f30(); void FUN_10024f50(); void FUN_10024f70(MxBool p_enabled); void SetPresentersEnabled(MxBool p_enabled); void TogglePresentersEnabled(); void FUN_100250e0(MxBool p_param); + void FUN_10025350(MxS32 p_param); void FUN_10025450(); undefined4 FUN_10025720(undefined4 p_param1); MxS32 FUN_10025d70(); @@ -139,7 +148,7 @@ class LegoCarBuild : public LegoWorld { // LegoCarBuild::`scalar deleting destructor' private: - undefined4 m_unk0xf8; // 0xf8 + Unknown0xf8 m_unk0xf8; // 0xf8 MxS16 m_unk0xfc; // 0xfc undefined m_unk0xfe[2]; // 0xfe MxS32 m_unk0x100; // 0x100 @@ -197,7 +206,8 @@ class LegoCarBuild : public LegoWorld { // variable name verified by BETA10 0x1006b219 LegoVehicleBuildState* m_buildState; // 0x32c - undefined4 m_unk0x330; // 0x330 + // variable name verified by BETA10 0x1006d742 + undefined4 m_carId; // 0x330 // variable name verified by BETA10 0x1006cba7 LegoGameState::Area m_destLocation; // 0x334 diff --git a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h index b1233adadf..2e61b1e5a6 100644 --- a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h +++ b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h @@ -21,7 +21,7 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { { m_name = NULL; m_wiredName = NULL; - m_unk0x08 = 0; + m_objectId = 0; } // variable name verified by BETA10 0x10071b56 @@ -30,7 +30,8 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { // variable name verified by BETA10 0x100719f0 LegoChar* m_wiredName; // 0x04 - undefined2 m_unk0x08; // 0x08 + // variable name guessed based on the setter at LEGO1 0x0x10079dc0 and its use in LEGO1 0x10024890 + MxS16 m_objectId; // 0x08 }; LegoCarBuildAnimPresenter(); @@ -77,15 +78,33 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { MxBool StringEqualsShelf(const LegoChar* p_string); MxBool StringEndsOnY(const LegoChar* p_string); MxBool StringEndsOnZero(const LegoChar* p_string); + const LegoChar* GetWiredNameByPartName(const LegoChar* p_name); + void SetPartObjectIdByName(const LegoChar* p_name, MxS16 p_objectId); // FUNCTION: BETA10 0x10070180 void SetUnknown0xbc(undefined2 p_unk0xbc) { m_unk0xbc = p_unk0xbc; } + // FUNCTION: BETA10 0x100703b0 + MxMatrix& GetUnknown0xe0() { return m_unk0xe0; } + MxBool StringEndsOnW(LegoChar* p_param); MxBool StringEndsOnYOrN(const LegoChar* p_string); const BoundingSphere& FUN_10079e20(); + // FUNCTION: BETA10 0x100703e0 + const LegoChar* GetWiredNameOfLastPlacedPart() { return m_parts[m_placedPartCount].m_wiredName; } + + MxS16 GetNumberOfParts() { return m_numberOfParts; } + MxS16 GetPlacedPartCount() { return m_placedPartCount; } + + // FUNCTION: BETA10 0x10070270 + MxBool AllPartsPlaced() + { + // this function differs in BETA10 + return m_placedPartCount == m_numberOfParts; + } + // SYNTHETIC: LEGO1 0x10078660 // LegoCarBuildAnimPresenter::`scalar deleting destructor' @@ -118,8 +137,6 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { // name verified by BETA10 0x10070d63 LegoChar* m_mainSourceId; // 0x14c - - friend class LegoCarBuild; }; #endif // LEGOCARBUILDPRESENTER_H diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index 5e818cc7ae..dc26f8c3a3 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -172,13 +172,11 @@ class LegoGameState { Act GetCurrentAct() { return m_currentAct; } Act GetLoadedAct() { return m_loadedAct; } - Area GetCurrentArea() { return m_currentArea; } Area GetPreviousArea() { return m_previousArea; } Area GetUnknown0x42c() { return m_unk0x42c; } History* GetHistory() { return &m_history; } void SetDirty(MxBool p_isDirty) { m_isDirty = p_isDirty; } - void SetCurrentArea(Area p_currentArea) { m_currentArea = p_currentArea; } void SetPreviousArea(Area p_previousArea) { m_previousArea = p_previousArea; } void SetActorId(MxU8 p_actorId) { m_actorId = p_actorId; } void SetUnknown0x42c(Area p_unk0x42c) { m_unk0x42c = p_unk0x42c; } diff --git a/LEGO1/lego/legoomni/include/legoinputmanager.h b/LEGO1/lego/legoomni/include/legoinputmanager.h index 859d1a64d6..8f2b069338 100644 --- a/LEGO1/lego/legoomni/include/legoinputmanager.h +++ b/LEGO1/lego/legoomni/include/legoinputmanager.h @@ -121,7 +121,9 @@ class LegoInputManager : public MxPresenter { // FUNCTION: BETA10 0x10031ba0 LegoControlManager* GetControlManager() { return m_controlManager; } + // FUNCTION: BETA10 0x10017870 LegoWorld* GetWorld() { return m_world; } + LegoCameraController* GetCamera() { return m_camera; } void ProcessEvents(); diff --git a/LEGO1/lego/legoomni/include/mxtransitionmanager.h b/LEGO1/lego/legoomni/include/mxtransitionmanager.h index 0af65db54e..178b114a08 100644 --- a/LEGO1/lego/legoomni/include/mxtransitionmanager.h +++ b/LEGO1/lego/legoomni/include/mxtransitionmanager.h @@ -34,7 +34,7 @@ class MxTransitionManager : public MxCore { virtual MxResult GetDDrawSurfaceFromVideoManager(); // vtable+0x14 enum TransitionType { - e_notTransitioning = 0, + e_idle = 0, // name verified by BETA10 0x100ec4e6 e_noAnimation, e_dissolve, e_mosaic, @@ -45,7 +45,7 @@ class MxTransitionManager : public MxCore { MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim); - TransitionType GetTransitionType() { return m_transitionType; } + TransitionType GetTransitionType() { return m_mode; } // SYNTHETIC: LEGO1 0x1004b9e0 // MxTransitionManager::`scalar deleting destructor' @@ -68,13 +68,16 @@ class MxTransitionManager : public MxCore { FlagBitfield m_copyFlags; // 0x20 undefined4 m_unk0x24; // 0x24 FlagBitfield m_unk0x28; // 0x28 - TransitionType m_transitionType; // 0x2c - LPDIRECTDRAWSURFACE m_ddSurface; // 0x30 - MxU16 m_animationTimer; // 0x34 - MxU16 m_columnOrder[640]; // 0x36 - MxU16 m_randomShift[480]; // 0x536 - MxULong m_systemTime; // 0x8f8 - MxS32 m_animationSpeed; // 0x8fc + + // name verified by BETA10 0x100ec4e6 + TransitionType m_mode; // 0x2c + + LPDIRECTDRAWSURFACE m_ddSurface; // 0x30 + MxU16 m_animationTimer; // 0x34 + MxU16 m_columnOrder[640]; // 0x36 + MxU16 m_randomShift[480]; // 0x536 + MxULong m_systemTime; // 0x8f8 + MxS32 m_animationSpeed; // 0x8fc }; #endif // MXTRANSITIONMANAGER_H diff --git a/LEGO1/lego/legoomni/src/actors/bike.cpp b/LEGO1/lego/legoomni/src/actors/bike.cpp index 0c5420be30..4793a2a2c8 100644 --- a/LEGO1/lego/legoomni/src/actors/bike.cpp +++ b/LEGO1/lego/legoomni/src/actors/bike.cpp @@ -40,7 +40,7 @@ MxResult Bike::Create(MxDSAction& p_dsAction) void Bike::Exit() { IslePathActor::Exit(); - GameState()->SetCurrentArea(LegoGameState::Area::e_bike); + GameState()->m_currentArea = LegoGameState::Area::e_bike; RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_BikeDashboard_Bitmap); RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_BikeArms_Ctl); RemoveFromCurrentWorld(*g_isleScript, IsleScript::c_BikeHorn_Ctl); diff --git a/LEGO1/lego/legoomni/src/actors/helicopter.cpp b/LEGO1/lego/legoomni/src/actors/helicopter.cpp index 1626f7befb..3aff55759b 100644 --- a/LEGO1/lego/legoomni/src/actors/helicopter.cpp +++ b/LEGO1/lego/legoomni/src/actors/helicopter.cpp @@ -76,7 +76,7 @@ void Helicopter::Exit() IslePathActor::Exit(); if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { - GameState()->SetCurrentArea(LegoGameState::e_copter); + GameState()->m_currentArea = LegoGameState::e_copter; if (UserActor() && UserActor()->IsA("IslePathActor")) { ((IslePathActor*) UserActor()) ->SpawnPlayer( @@ -180,7 +180,7 @@ MxLong Helicopter::HandleControl(LegoControlManagerNotificationParam& p_param) break; } Exit(); - GameState()->SetCurrentArea(LegoGameState::e_unk66); + GameState()->m_currentArea = LegoGameState::e_unk66; ret = 1; break; case IsleScript::c_Helicopter_TakeOff_Ctl: { diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 48e6bb03bb..d03e4f096d 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -1,8 +1,11 @@ #include "legocarbuild.h" +#include "copter_actions.h" #include "dunebuggy.h" +#include "dunecar_actions.h" #include "helicopter.h" #include "jetski.h" +#include "jetski_actions.h" #include "jukebox_actions.h" #include "legocarbuildpresenter.h" #include "legocontrolmanager.h" @@ -21,11 +24,19 @@ #include "mxticklemanager.h" #include "mxtransitionmanager.h" #include "racecar.h" +#include "racecar_actions.h" #include "scripts.h" #include #include +// Names and values verified by BETA10 0x1006d742. +// Note that these were probably hard-coded numbers in the original. +#define Helicopter_Actor CopterScript::c_Helicopter_Actor +#define DuneBugy_Actor DunecarScript::c_DuneBugy_Actor +#define Jetski_Actor JetskiScript::c_Jetski_Actor +#define RaceCar_Actor RacecarScript::c_RaceCar_Actor + DECOMP_SIZE_ASSERT(LegoCarBuild, 0x34c) DECOMP_SIZE_ASSERT(LegoVehicleBuildState, 0x50) @@ -44,7 +55,7 @@ LegoCarBuild::LegoCarBuild() { m_unk0x100 = 0; m_unk0x110 = 0; - m_unk0xf8 = 0xffffffff; + m_unk0xf8 = c_unknownminusone; m_unk0x2d4 = FALSE; m_unk0x258 = 0; m_ColorBook_Bitmap = NULL; @@ -87,12 +98,27 @@ MxBool LegoCarBuild::VTable0x5c() return TRUE; } -// STUB: LEGO1 0x10022a80 -// STUB: BETA10 0x1006aea3 +// FUNCTION: LEGO1 0x10022a80 +// FUNCTION: BETA10 0x1006aea3 LegoCarBuild::~LegoCarBuild() { - // TODO - // ... + m_unk0x100 = 0; + m_unk0x110 = NULL; + + if (m_unk0x258) { + m_unk0x258->SetUnknown0xbc(0); + m_unk0x258->SetTickleState(MxPresenter::e_idle); + m_unk0x258 = NULL; + } + + ControlManager()->Unregister(this); + TickleManager()->UnregisterClient(this); + + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + + InputManager()->UnRegister(this); NotificationManager()->Unregister(this); } @@ -116,23 +142,23 @@ MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) if (m_atomId == *g_copterScript) { buildStateClassName = "LegoCopterBuildState"; - GameState()->SetCurrentArea(LegoGameState::e_copterbuild); - m_unk0x330 = 1; + GameState()->m_currentArea = LegoGameState::e_copterbuild; + m_carId = Helicopter_Actor; } else if (m_atomId == *g_dunecarScript) { buildStateClassName = "LegoDuneCarBuildState"; - GameState()->SetCurrentArea(LegoGameState::e_dunecarbuild); - m_unk0x330 = 2; + GameState()->m_currentArea = LegoGameState::e_dunecarbuild; + m_carId = DuneBugy_Actor; } else if (m_atomId == *g_jetskiScript) { buildStateClassName = "LegoJetskiBuildState"; - GameState()->SetCurrentArea(LegoGameState::e_jetskibuild); - m_unk0x330 = 3; + GameState()->m_currentArea = LegoGameState::e_jetskibuild; + m_carId = Jetski_Actor; } else if (m_atomId == *g_racecarScript) { buildStateClassName = "LegoRaceCarBuildState"; - GameState()->SetCurrentArea(LegoGameState::e_racecarbuild); - m_unk0x330 = 4; + GameState()->m_currentArea = LegoGameState::e_racecarbuild; + m_carId = Helicopter_Actor; } LegoGameState* gameState = GameState(); @@ -409,7 +435,7 @@ MxResult LegoCarBuild::Tickle() return SUCCESS; } - if (m_unk0xf8 == 8) { + if (m_unk0xf8 == c_unknown8) { if (m_unk0xfc == 1) { FUN_10024f50(); } @@ -429,7 +455,7 @@ MxResult LegoCarBuild::Tickle() DWORD time = timeGetTime(); DWORD dTime = (time - m_unk0x10c) / 100; - if (m_unk0x330 == 4) { + if (m_carId == Helicopter_Actor) { switch (m_unk0x10a) { // TODO: Work out constants case 500: @@ -452,7 +478,7 @@ MxResult LegoCarBuild::Tickle() return SUCCESS; } } - else if (m_unk0x330 == 3) { + else if (m_carId == Jetski_Actor) { switch (m_unk0x10a) { case 500: LEGOCARBUILD_TICKLE_CASE(291, 291, 311, "Exit_Ctl") @@ -473,7 +499,7 @@ MxResult LegoCarBuild::Tickle() // return SUCCESS; } } - else if (m_unk0x330 == 2) { + else if (m_carId == DuneBugy_Actor) { switch (m_unk0x10a) { case 500: LEGOCARBUILD_TICKLE_CASE(155, 155, 175, "Exit_Ctl") @@ -490,7 +516,7 @@ MxResult LegoCarBuild::Tickle() return SUCCESS; } } - else if (m_unk0x330 == 1) { + else if (m_carId == Helicopter_Actor) { switch (m_unk0x10a) { case 500: LEGOCARBUILD_TICKLE_CASE(185, 185, 205, "Exit_Ctl") @@ -575,7 +601,7 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) break; case c_notificationControl: - result = FUN_10024890((LegoEventNotificationParam*) &p_param); + result = FUN_10024890(&p_param); if (result == 1) { m_unk0x109 = 0; @@ -624,7 +650,7 @@ void LegoCarBuild::ReadyWorld() InitPresenters(); if (BackgroundAudioManager()->GetEnabled()) { - InvokeAction(Extra::ActionType::e_start, *g_jukeboxScript, FUN_10025ee0(m_unk0x330), NULL); + InvokeAction(Extra::ActionType::e_start, *g_jukeboxScript, FUN_10025ee0(m_carId), NULL); m_buildState->m_animationState = LegoVehicleBuildState::e_unknown2; NotificationManager()->Send(this, MxNotificationParam()); } @@ -636,8 +662,8 @@ void LegoCarBuild::ReadyWorld() // FUNCTION: LEGO1 0x100243a0 void LegoCarBuild::FUN_100243a0() { - switch (m_unk0x330) { - case 1: + switch (m_carId) { + case Helicopter_Actor: if (GameState()->GetCurrentAct() == LegoGameState::Act::e_act2) { m_destLocation = LegoGameState::Area::e_act3script; TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); @@ -648,15 +674,15 @@ void LegoCarBuild::FUN_100243a0() TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); break; } - case 2: + case DuneBugy_Actor: m_destLocation = LegoGameState::Area::e_garadoor; TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); break; - case 3: + case Jetski_Actor: m_destLocation = LegoGameState::Area::e_unk17; TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); break; - case 4: + case RaceCar_Actor: m_destLocation = LegoGameState::Area::e_unk20; TransitionManager()->StartTransition(MxTransitionManager::TransitionType::e_mosaic, 50, FALSE, FALSE); } @@ -771,14 +797,207 @@ MxS32 LegoCarBuild::FUN_10024850(MxLong p_x, MxLong p_y) return result; } -// STUB: LEGO1 0x10024890 -// STUB: BETA10 0x1006d512 -undefined4 LegoCarBuild::FUN_10024890(LegoEventNotificationParam* p_param) +#ifdef NDEBUG + +// FUNCTION: LEGO1 0x10024890 +undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) { - // TODO - return 0; + undefined4 result = 0; + LegoControlManagerNotificationParam* param = (LegoControlManagerNotificationParam*) p_param; + assert(m_buildState); + + if (param->m_unk0x28) { + switch (param->m_clickedObjectId) { + // The enum values are all identical between CopterScript, DunecarScript, JetskiScript, and RacecarScript + case CopterScript::c_Info_Ctl: + if (m_buildState->m_animationState != LegoVehicleBuildState::e_unknown4 && + m_buildState->m_animationState != LegoVehicleBuildState::e_unknown2 && + m_buildState->m_animationState != LegoVehicleBuildState::e_exiting && + GameState()->GetCurrentAct() != LegoGameState::e_act2) { + if (m_unk0x108 > 0) { + DeleteObjects(&m_atomId, 500, 510); + } + + m_unk0x258->SetUnknown0xbc(0); + m_destLocation = LegoGameState::e_infomain; + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + result = 1; + } + + break; + case CopterScript::c_Exit_Ctl: + if (m_buildState->m_animationState != LegoVehicleBuildState::e_exiting && + m_buildState->m_animationState != LegoVehicleBuildState::e_unknown4) { + if (m_unk0x108 > 0) { + DeleteObjects(&m_atomId, 500, 510); + } + + m_unk0x258->SetUnknown0xbc(0); + + if (GameState()->GetCurrentAct() == LegoGameState::e_act2) { + FUN_100243a0(); + } + else if (m_unk0x258->AllPartsPlaced() || m_buildState->m_unk0x4d) { + m_buildState->m_unk0x4d = TRUE; + InvokeAction(Extra::e_start, m_atomId, m_carId, NULL); + + NotificationManager()->Send(this, MxNotificationParam()); + + m_buildState->m_animationState = LegoVehicleBuildState::e_unknown4; + } + else { + FUN_10025720(4); + m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; + } + + result = 1; + } + break; + case CopterScript::c_ShelfUp_Ctl: + FUN_10024f30(); + m_Shelf_Sound->Enable(FALSE); + m_Shelf_Sound->Enable(TRUE); + result = 1; + break; + case CopterScript::c_Platform_Ctl: + FUN_10024f50(); + m_unk0xf8 = c_unknown8; + m_unk0xfc = param->m_unk0x28; + result = 1; + break; + default: + if ((m_Decals_Ctl && m_Decals_Ctl->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl1 && m_Decals_Ctl1->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl2 && m_Decals_Ctl2->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl3 && m_Decals_Ctl3->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl4 && m_Decals_Ctl4->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl5 && m_Decals_Ctl5->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl6 && m_Decals_Ctl6->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl7 && m_Decals_Ctl7->GetAction()->GetObjectId() == param->m_clickedObjectId)) { + m_unk0x258->SetPartObjectIdByName(m_unk0x110->GetName(), param->m_clickedObjectId); + m_Decal_Sound->Enable(FALSE); + m_Decal_Sound->Enable(TRUE); + } + else { + FUN_10025350(param->m_clickedObjectId); + } + + result = 1; + } + } + else { + m_unk0xf8 = c_unknownminusone; + m_unk0xfc = -1; + } + + // It is a bit unexpected that LEGO1 and BETA10 match so well with the `return 1` + // and ignoring the `result` variable, but the match is hard to argue with + return 1; } +#else + +// FUNCTION: BETA10 0x1006d512 +undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) +{ + undefined4 result = 0; + LegoControlManagerNotificationParam* param = (LegoControlManagerNotificationParam*) p_param; + assert(m_buildState); + + if (param->m_unk0x28) { + switch (param->m_clickedObjectId) { + case CopterScript::c_Info_Ctl: + m_unk0x258->SetUnknown0xbc(0); + m_destLocation = LegoGameState::e_infomain; + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + result = 1; + break; + case CopterScript::c_Exit_Ctl: + if (m_buildState->m_animationState != LegoVehicleBuildState::e_exiting) { + m_unk0x258->SetUnknown0xbc(0); + + if (m_unk0x258->AllPartsPlaced() || m_buildState->m_unk0x4d) { + m_buildState->m_unk0x4d = TRUE; + + // GameState()->GetCurrentAct() returns an MxS16 in BETA10 + if (GameState()->GetCurrentAct() == 0) { + InvokeAction(Extra::e_start, m_atomId, m_carId, NULL); + + NotificationManager()->Send(this, MxNotificationParam()); + + assert(m_buildState); + m_buildState->m_animationState = LegoVehicleBuildState::e_unknown4; + } + + else { + FUN_10025720(5); + m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; + } + } + else { + FUN_10025720(4); + m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; + } + + switch (GameState()->m_currentArea) { + case LegoGameState::e_copterbuild: + assert(m_carId == Helicopter_Actor); + break; + case LegoGameState::e_dunecarbuild: + assert(m_carId == DuneBugy_Actor); + break; + case LegoGameState::e_jetskibuild: + assert(m_carId == Jetski_Actor); + break; + case LegoGameState::e_racecarbuild: + assert(m_carId == RaceCar_Actor); + break; + } + + result = 1; + } + break; + case CopterScript::c_ShelfUp_Ctl: + FUN_10024f30(); + m_Shelf_Sound->Enable(FALSE); + m_Shelf_Sound->Enable(TRUE); + result = 1; + break; + case CopterScript::c_Platform_Ctl: + FUN_10024f50(); + m_unk0xf8 = c_unknown8; + m_unk0xfc = param->m_unk0x28; + result = 1; + break; + default: + if ((m_Decals_Ctl && m_Decals_Ctl->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl1 && m_Decals_Ctl1->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl2 && m_Decals_Ctl2->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl3 && m_Decals_Ctl3->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl4 && m_Decals_Ctl4->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl5 && m_Decals_Ctl5->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl6 && m_Decals_Ctl6->GetAction()->GetObjectId() == param->m_clickedObjectId) || + (m_Decals_Ctl7 && m_Decals_Ctl7->GetAction()->GetObjectId() == param->m_clickedObjectId)) { + m_unk0x258->SetPartObjectIdByName(m_unk0x110->GetName(), param->m_clickedObjectId); + m_Decal_Sound->Enable(FALSE); + m_Decal_Sound->Enable(TRUE); + } + else { + FUN_10025350(param->m_clickedObjectId); + } + result = 1; + } + } + else { + m_unk0xf8 = c_unknownminusone; + m_unk0xfc = -1; + } + + return 1; +} + +#endif + // FUNCTION: LEGO1 0x10024c20 // FUNCTION: BETA10 0x1006db21 undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) @@ -788,7 +1007,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) switch (m_buildState->m_animationState) { case 4: - entity = (LegoEntity*) Find(m_atomId, m_unk0x330); + entity = (LegoEntity*) Find(m_atomId, m_carId); if (entity && entity->GetROI()) { @@ -799,7 +1018,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) Act1State* gameState = (Act1State*) GameState()->GetState("Act1State"); - switch (GameState()->GetCurrentArea()) { + switch (GameState()->m_currentArea) { case LegoGameState::e_copterbuild: if (gameState->m_helicopter) { delete gameState->m_helicopter; @@ -837,7 +1056,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) assert(destWorld); m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; - if (m_unk0x258->m_numberOfParts != m_unk0x258->m_placedPartCount) { + if (m_unk0x258->AllPartsPlaced()) { FUN_100243a0(); } else { @@ -852,17 +1071,17 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) case 2: MxU32 jukeboxScript; - switch (m_unk0x330) { - case 1: + switch (m_carId) { + case Helicopter_Actor: jukeboxScript = JukeboxScript::c_HelicopterBuild_Music; break; - case 2: + case DuneBugy_Actor: jukeboxScript = JukeboxScript::c_DuneCarBuild_Music; break; - case 3: + case Jetski_Actor: jukeboxScript = JukeboxScript::c_JetskiBuild_Music; break; - case 4: + case RaceCar_Actor: jukeboxScript = JukeboxScript::c_RaceCarBuild_Music; } @@ -893,6 +1112,14 @@ void LegoCarBuild::FUN_10024ef0() FUN_10015820(FALSE, 7); } +// FUNCTION: LEGO1 0x10024f30 +// FUNCTION: BETA10 0x1006dfa0 +void LegoCarBuild::FUN_10024f30() +{ + FUN_10022f30(); + m_unk0x258->SetUnknown0xbc(2); +} + // FUNCTION: LEGO1 0x10024f50 // FUNCTION: BETA10 0x1006dfce void LegoCarBuild::FUN_10024f50() @@ -973,13 +1200,64 @@ void LegoCarBuild::FUN_100250e0(MxBool p_enabled) } } -// STUB: LEGO1 0x10025450 -// STUB: BETA10 0x1006e599 -void LegoCarBuild::FUN_10025450() +// STUB: LEGO1 0x10025350 +// STUB: BETA10 0x1006e3c0 +void LegoCarBuild::FUN_10025350(MxS32 p_param) { // TODO } +// FUNCTION: LEGO1 0x10025450 +// FUNCTION: BETA10 0x1006e599 +void LegoCarBuild::FUN_10025450() +{ + m_unk0x12c = m_unk0x110->GetLocal2World(); + m_unk0x1c0 = m_unk0x12c; + + Vector3 lastColumnOfUnk0x1c0(m_unk0x1c0[3]); + lastColumnOfUnk0x1c0 = Vector3(m_unk0x258->GetUnknown0xe0()[3]); + + // This looks odd, but it improves the LEGO1 match while breaking the BETA10 match. + // I don't know whether this is due to compiler entropy. + // Feel free to replace unk0x178 -> m_unk0x178 and remove this variable if it improves the LEGO1 match + // in the future. + MxMatrix* unk0x178 = &m_unk0x178; + *unk0x178 = m_unk0x12c; + + if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) { + m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition()); + + if (!m_unk0x2d4) { + m_unk0x2bc = m_unk0x2a4; + + m_unk0x208 = m_unk0x12c; + m_unk0x2a4[0] += m_unk0x1c0[3][0] - m_unk0x208[3][0]; + m_unk0x2a4[1] += m_unk0x1c0[3][1] - m_unk0x208[3][1]; + m_unk0x2a4[2] += m_unk0x1c0[3][2] - m_unk0x208[3][2]; + } + + *unk0x178 = m_unk0x1c0; + } + else { + const LegoChar* wiredName; + + if (!m_unk0x258->FUN_10079c30(m_unk0x110->GetName())) { + wiredName = m_unk0x258->GetWiredNameByPartName(m_unk0x110->GetName()); + } + else { + wiredName = m_unk0x258->GetWiredNameOfLastPlacedPart(); + } + + LegoROI* parentROI = (LegoROI*) m_unk0x110->GetParentROI(); + m_unk0x208 = parentROI->FindChildROI(wiredName, parentROI)->GetLocal2World(); + m_unk0x2bc = Vector4(parentROI->FindChildROI(wiredName, parentROI)->GetWorldPosition()); + m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition()); + + m_unk0x2a4[2] += (m_unk0x1c0[3][2] - m_unk0x12c[3][2]); + m_unk0x178[3][2] = m_unk0x1c0[3][2]; + } +} + // FUNCTION: LEGO1 0x100256c0 // FUNCTION: BETA10 0x1006e96c void LegoCarBuild::Enable(MxBool p_enable) @@ -999,6 +1277,7 @@ void LegoCarBuild::Enable(MxBool p_enable) } // STUB: LEGO1 0x10025720 +// STUB: BETA10 0x1006e9df undefined4 LegoCarBuild::FUN_10025720(undefined4 p_param1) { // TODO @@ -1057,7 +1336,7 @@ void LegoCarBuild::FUN_10025e40() MxBool LegoCarBuild::Escape() { BackgroundAudioManager()->Init(); - MxS32 targetEntityId = FUN_10025ee0(m_unk0x330); + MxS32 targetEntityId = FUN_10025ee0(m_carId); InvokeAction(Extra::ActionType::e_stop, *g_jukeboxScript, targetEntityId, NULL); DeleteObjects(&m_atomId, 500, 999); diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp index 28cfbc53b2..546aac6733 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp @@ -627,6 +627,31 @@ MxBool LegoCarBuildAnimPresenter::StringEndsOnZero(const LegoChar* p_string) return (p_string[strlen(p_string) - 2] != '0'); } +// FUNCTION: LEGO1 0x10079d60 +// FUNCTION: BETA10 0x1007284c +const LegoChar* LegoCarBuildAnimPresenter::GetWiredNameByPartName(const LegoChar* p_name) +{ + for (MxS16 i = 0; i < m_numberOfParts; i++) { + if (strcmpi(p_name, m_parts[i].m_name) == 0) { + return m_parts[i].m_wiredName; + } + } + + return NULL; +} + +// FUNCTION: LEGO1 0x10079dc0 +// FUNCTION: BETA10 0x100728d1 +void LegoCarBuildAnimPresenter::SetPartObjectIdByName(const LegoChar* p_name, MxS16 p_objectId) +{ + for (MxS16 i = 0; i < m_numberOfParts; i++) { + if (strcmpi(p_name, m_parts[i].m_name) == 0) { + m_parts[i].m_objectId = p_objectId; + return; + } + } +} + // FUNCTION: LEGO1 0x10079e20 // FUNCTION: BETA10 0x10072959 const BoundingSphere& LegoCarBuildAnimPresenter::FUN_10079e20() diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index d90e655e9a..342481637d 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -238,6 +238,7 @@ MxBool CheckIfEntityExists(MxBool p_enable, const char* p_filename, MxS32 p_enti void NotifyEntity(const char* p_filename, MxS32 p_entityId, LegoEntity* p_sender); // FUNCTION: LEGO1 0x1003e430 +// FUNCTION: BETA10 0x100d3fda void InvokeAction(Extra::ActionType p_actionId, const MxAtomId& p_pAtom, MxS32 p_targetEntityId, LegoEntity* p_sender) { MxDSAction action; diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index f9c78e5d3f..2acc4be24e 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -188,8 +188,10 @@ void SetCurrentWorld(LegoWorld* p_world) } // FUNCTION: LEGO1 0x10015900 +// FUNCTION: BETA10 0x100e4f02 MxTransitionManager* TransitionManager() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetTransitionManager(); } diff --git a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp index bb252592e9..566468e5c5 100644 --- a/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/mxtransitionmanager.cpp @@ -21,7 +21,7 @@ RECT g_fullScreenRect = {0, 0, 640, 480}; MxTransitionManager::MxTransitionManager() { m_animationTimer = 0; - m_transitionType = e_notTransitioning; + m_mode = e_idle; m_ddSurface = NULL; m_waitIndicator = NULL; m_copyBuffer = NULL; @@ -47,20 +47,20 @@ MxTransitionManager::~MxTransitionManager() MxResult MxTransitionManager::GetDDrawSurfaceFromVideoManager() // vtable+0x14 { LegoVideoManager* videoManager = VideoManager(); - this->m_ddSurface = videoManager->GetDisplaySurface()->GetDirectDrawSurface2(); + m_ddSurface = videoManager->GetDisplaySurface()->GetDirectDrawSurface2(); return SUCCESS; } // FUNCTION: LEGO1 0x1004bac0 MxResult MxTransitionManager::Tickle() { - if (this->m_animationSpeed + this->m_systemTime > timeGetTime()) { + if (m_animationSpeed + m_systemTime > timeGetTime()) { return SUCCESS; } - this->m_systemTime = timeGetTime(); + m_systemTime = timeGetTime(); - switch (this->m_transitionType) { + switch (m_mode) { case e_noAnimation: NoTransition(); break; @@ -84,6 +84,7 @@ MxResult MxTransitionManager::Tickle() } // FUNCTION: LEGO1 0x1004bb70 +// FUNCTION: BETA10 0x100ec4c1 MxResult MxTransitionManager::StartTransition( TransitionType p_animationType, MxS32 p_speed, @@ -91,13 +92,15 @@ MxResult MxTransitionManager::StartTransition( MxBool p_playMusicInAnim ) { - if (this->m_transitionType == e_notTransitioning) { + assert(m_mode == e_idle); + + if (m_mode == e_idle) { if (!p_playMusicInAnim) { MxBackgroundAudioManager* backgroundAudioManager = BackgroundAudioManager(); backgroundAudioManager->Stop(); } - this->m_transitionType = p_animationType; + m_mode = p_animationType; m_copyFlags.m_bit0 = p_doCopy; @@ -110,9 +113,9 @@ MxResult MxTransitionManager::StartTransition( } MxU32 time = timeGetTime(); - this->m_systemTime = time; + m_systemTime = time; - this->m_animationSpeed = p_speed; + m_animationSpeed = p_speed; MxTickleManager* tickleManager = TickleManager(); tickleManager->RegisterClient(this, p_speed); @@ -133,8 +136,8 @@ MxResult MxTransitionManager::StartTransition( // FUNCTION: LEGO1 0x1004bc30 void MxTransitionManager::EndTransition(MxBool p_notifyWorld) { - if (m_transitionType != e_notTransitioning) { - m_transitionType = e_notTransitioning; + if (m_mode != e_idle) { + m_mode = e_idle; m_copyFlags.m_bit0 = FALSE; diff --git a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp index b8125c50bf..f54fb548ef 100644 --- a/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp +++ b/LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp @@ -45,6 +45,7 @@ void LegoControlManager::Register(MxCore* p_listener) } // FUNCTION: LEGO1 0x10028ea0 +// FUNCTION: BETA10 0x1007c330 void LegoControlManager::Unregister(MxCore* p_listener) { LegoNotifyListCursor cursor(&m_notifyList); diff --git a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp index 5383d39c5e..f546b2bf2e 100644 --- a/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp +++ b/LEGO1/lego/legoomni/src/input/legoinputmanager.cpp @@ -339,6 +339,7 @@ void LegoInputManager::SetWorld(LegoWorld* p_world) } // FUNCTION: LEGO1 0x1005c730 +// FUNCTION: BETA10 0x100896dc void LegoInputManager::ClearWorld() { m_world = NULL; diff --git a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp index 9a41de966b..5d9fbf1d13 100644 --- a/LEGO1/lego/legoomni/src/video/legovideomanager.cpp +++ b/LEGO1/lego/legoomni/src/video/legovideomanager.cpp @@ -285,7 +285,7 @@ void LegoVideoManager::ToggleFPS(MxBool p_visible) MxResult LegoVideoManager::Tickle() { if (m_unk0x554 && !m_videoParam.Flags().GetFlipSurfaces() && - TransitionManager()->GetTransitionType() == MxTransitionManager::e_notTransitioning) { + TransitionManager()->GetTransitionType() == MxTransitionManager::e_idle) { Sleep(30); } diff --git a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp index cfe2581265..8fefddf4a5 100644 --- a/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp +++ b/LEGO1/lego/legoomni/src/worlds/elevatorbottom.cpp @@ -45,7 +45,7 @@ MxResult ElevatorBottom::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); - GameState()->SetCurrentArea(LegoGameState::e_elevbott); + GameState()->m_currentArea = LegoGameState::e_elevbott; GameState()->StopArea(LegoGameState::e_previousArea); return result; diff --git a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp index 453b0862a9..bd782ed8fd 100644 --- a/LEGO1/lego/legoomni/src/worlds/gasstation.cpp +++ b/LEGO1/lego/legoomni/src/worlds/gasstation.cpp @@ -91,7 +91,7 @@ MxResult GasStation::Create(MxDSAction& p_dsAction) m_state->m_unk0x14.m_unk0x00 = 3; } - GameState()->SetCurrentArea(LegoGameState::e_garage); + GameState()->m_currentArea = LegoGameState::e_garage; GameState()->StopArea(LegoGameState::e_previousArea); InputManager()->Register(this); diff --git a/LEGO1/lego/legoomni/src/worlds/historybook.cpp b/LEGO1/lego/legoomni/src/worlds/historybook.cpp index 4287fe56a8..bec6764fbd 100644 --- a/LEGO1/lego/legoomni/src/worlds/historybook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/historybook.cpp @@ -39,7 +39,7 @@ MxResult HistoryBook::Create(MxDSAction& p_dsAction) InputManager()->SetCamera(NULL); InputManager()->Register(this); - GameState()->SetCurrentArea(LegoGameState::Area::e_histbook); + GameState()->m_currentArea = LegoGameState::Area::e_histbook; GameState()->StopArea(LegoGameState::Area::e_previousArea); return result; } diff --git a/LEGO1/lego/legoomni/src/worlds/hospital.cpp b/LEGO1/lego/legoomni/src/worlds/hospital.cpp index 2bf024f240..6b3c8e5a42 100644 --- a/LEGO1/lego/legoomni/src/worlds/hospital.cpp +++ b/LEGO1/lego/legoomni/src/worlds/hospital.cpp @@ -96,7 +96,7 @@ MxResult Hospital::Create(MxDSAction& p_dsAction) m_hospitalState->m_unk0x08.m_unk0x00 = 3; } - GameState()->SetCurrentArea(LegoGameState::e_hospital); + GameState()->m_currentArea = LegoGameState::e_hospital; GameState()->StopArea(LegoGameState::e_previousArea); InputManager()->Register(this); diff --git a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp index 8e882e7509..342d85bd40 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenter.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenter.cpp @@ -210,7 +210,7 @@ MxResult Infocenter::Create(MxDSAction& p_dsAction) } } - GameState()->SetCurrentArea(LegoGameState::e_infomain); + GameState()->m_currentArea = LegoGameState::e_infomain; GameState()->StopArea(LegoGameState::e_previousArea); if (m_infocenterState->GetUnknown0x74() == 4) { @@ -523,9 +523,9 @@ void Infocenter::ReadyWorld() bgRed->Enable(TRUE); if (GameState()->GetCurrentAct() == GameState()->GetLoadedAct()) { - GameState()->SetCurrentArea(LegoGameState::e_act2main); + GameState()->m_currentArea = LegoGameState::e_act2main; GameState()->StopArea(LegoGameState::e_act2main); - GameState()->SetCurrentArea(LegoGameState::e_infomain); + GameState()->m_currentArea = LegoGameState::e_infomain; } m_infocenterState->SetUnknown0x74(5); @@ -579,9 +579,9 @@ void Infocenter::ReadyWorld() bgRed->Enable(TRUE); if (GameState()->GetCurrentAct() == GameState()->GetLoadedAct()) { - GameState()->SetCurrentArea(LegoGameState::e_act3script); + GameState()->m_currentArea = LegoGameState::e_act3script; GameState()->StopArea(LegoGameState::e_act3script); - GameState()->SetCurrentArea(LegoGameState::e_infomain); + GameState()->m_currentArea = LegoGameState::e_infomain; } m_infocenterState->SetUnknown0x74(5); diff --git a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp index 4b6d7850cc..5f3ae04c61 100644 --- a/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp +++ b/LEGO1/lego/legoomni/src/worlds/infocenterdoor.cpp @@ -48,7 +48,7 @@ MxResult InfocenterDoor::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); - GameState()->SetCurrentArea(LegoGameState::e_infodoor); + GameState()->m_currentArea = LegoGameState::e_infodoor; GameState()->StopArea(LegoGameState::e_previousArea); return result; diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index 66e7a5593a..347e4b077c 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -112,8 +112,8 @@ MxResult Isle::Create(MxDSAction& p_dsAction) m_destLocation = LegoGameState::e_infomain; } - if (GameState()->GetCurrentArea() == LegoGameState::e_isle) { - GameState()->SetCurrentArea(LegoGameState::e_undefined); + if (GameState()->m_currentArea == LegoGameState::e_isle) { + GameState()->m_currentArea = LegoGameState::e_undefined; } LegoGameState* gameState = GameState(); diff --git a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp index ca27142d1b..fe476499d7 100644 --- a/LEGO1/lego/legoomni/src/worlds/jukebox.cpp +++ b/LEGO1/lego/legoomni/src/worlds/jukebox.cpp @@ -61,7 +61,7 @@ MxResult JukeBox::Create(MxDSAction& p_dsAction) m_state->m_music = JukeBoxState::e_pasquell; } - GameState()->SetCurrentArea(LegoGameState::e_jukeboxw); + GameState()->m_currentArea = LegoGameState::e_jukeboxw; GameState()->StopArea(LegoGameState::e_previousArea); TickleManager()->RegisterClient(this, 2000); return ret; diff --git a/LEGO1/lego/legoomni/src/worlds/police.cpp b/LEGO1/lego/legoomni/src/worlds/police.cpp index cf7bb0f843..43bd67bfd8 100644 --- a/LEGO1/lego/legoomni/src/worlds/police.cpp +++ b/LEGO1/lego/legoomni/src/worlds/police.cpp @@ -63,7 +63,7 @@ MxResult Police::Create(MxDSAction& p_dsAction) } m_policeState = policeState; - GameState()->SetCurrentArea(LegoGameState::e_police); + GameState()->m_currentArea = LegoGameState::e_police; GameState()->StopArea(LegoGameState::e_previousArea); return ret; } diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index 234903bf94..fe4ac4245c 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -97,7 +97,7 @@ MxResult RegistrationBook::Create(MxDSAction& p_dsAction) SetIsWorldActive(FALSE); InputManager()->Register(this); - GameState()->SetCurrentArea(LegoGameState::e_regbook); + GameState()->m_currentArea = LegoGameState::e_regbook; GameState()->StopArea(LegoGameState::e_previousArea); m_infocenterState = (InfocenterState*) GameState()->GetState("InfocenterState"); diff --git a/LEGO1/lego/legoomni/src/worlds/score.cpp b/LEGO1/lego/legoomni/src/worlds/score.cpp index db9a24ec55..3ecae676e4 100644 --- a/LEGO1/lego/legoomni/src/worlds/score.cpp +++ b/LEGO1/lego/legoomni/src/worlds/score.cpp @@ -63,7 +63,7 @@ MxResult Score::Create(MxDSAction& p_dsAction) LegoGameState* gameState = GameState(); ScoreState* state = (ScoreState*) gameState->GetState("ScoreState"); m_state = state ? state : (ScoreState*) gameState->CreateState("ScoreState"); - GameState()->SetCurrentArea(LegoGameState::e_infoscor); + GameState()->m_currentArea = LegoGameState::e_infoscor; GameState()->StopArea(LegoGameState::e_previousArea); } diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 49e2efbd0b..d4770e46cd 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -19,6 +19,7 @@ // _free // LIBRARY: LEGO1 0x1008b020 +// LIBRARY: BETA10 0x100f8d20 // ___CxxFrameHandler // LIBRARY: LEGO1 0x1008b24c diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index 58d36198a7..b2f4d53a34 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -78,6 +78,7 @@ class Mx4DPointFloat : public Vector4 { const float& operator[](int idx) const { return m_data[idx]; } // SYNTHETIC: LEGO1 0x10064b20 + // SYNTHETIC: BETA10 0x10070420 // Mx4DPointFloat::operator= private: diff --git a/LEGO1/mxgeometry/mxmatrix.h b/LEGO1/mxgeometry/mxmatrix.h index 5ac9b2be1b..a9249225e2 100644 --- a/LEGO1/mxgeometry/mxmatrix.h +++ b/LEGO1/mxgeometry/mxmatrix.h @@ -20,6 +20,7 @@ class MxMatrix : public Matrix4 { // FUNCTION: BETA10 0x10010860 float* operator[](int idx) { return m_data[idx]; } + // FUNCTION: BETA10 0x1001c670 const float* operator[](int idx) const { return m_data[idx]; } // FUNCTION: LEGO1 0x10002850 diff --git a/LEGO1/omni/src/notify/mxnotificationmanager.cpp b/LEGO1/omni/src/notify/mxnotificationmanager.cpp index dec4981884..61e051f7c4 100644 --- a/LEGO1/omni/src/notify/mxnotificationmanager.cpp +++ b/LEGO1/omni/src/notify/mxnotificationmanager.cpp @@ -178,6 +178,7 @@ void MxNotificationManager::Register(MxCore* p_listener) } // FUNCTION: LEGO1 0x100acdf0 +// FUNCTION: BETA10 0x10126785 void MxNotificationManager::Unregister(MxCore* p_listener) { AUTOLOCK(m_lock); diff --git a/LEGO1/realtime/orientableroi.h b/LEGO1/realtime/orientableroi.h index 5e70aa5e12..8daf1f5133 100644 --- a/LEGO1/realtime/orientableroi.h +++ b/LEGO1/realtime/orientableroi.h @@ -51,6 +51,7 @@ class OrientableROI : public ROI { // FUNCTION: BETA10 0x1004aa70 const float* GetWorldUp() const { return m_local2world[1]; } + // FUNCTION: BETA10 0x10070380 OrientableROI* GetParentROI() const { return m_parentROI; } void SetParentROI(OrientableROI* p_parentROI) { m_parentROI = p_parentROI; } diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index a09e62c4ea..8f87147456 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -152,6 +152,7 @@ class Vector2 { virtual void SetVector(const Vector2* p_other) { EqualsImpl(p_other->m_data); } // vtable+0x6c // SYNTHETIC: LEGO1 0x10010be0 + // SYNTHETIC: BETA10 0x100121e0 // Vector3::operator= // SYNTHETIC: BETA10 0x1004af40 @@ -301,10 +302,14 @@ class Vector4 : public Vector3 { // FUNCTION: BETA10 0x10048780 Vector4(float* p_data) : Vector3(p_data) {} - // Hack: Some code initializes a Vector4 from a (most likely) const float* source. - // Example: LegoCarBuild::VTable0x6c + // Some code initializes a Vector4 from a `const float*` source. + // Example: `LegoCarBuild::VTable0x6c` // Vector4 however is a class that can mutate its underlying source, making // initialization with a const source fundamentally incompatible. + // BETA10 appears to have two separate constructors for Vector4 as well, + // supporting the theory that this decompilation is correct. + + // FUNCTION: BETA10 0x100701b0 Vector4(const float* p_data) : Vector3((float*) p_data) {} // Note: virtual function overloads appear in the virtual table