From c06ffe71b532f4aa1964a4efecd490434a940e31 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sat, 13 Sep 2025 06:51:45 +0200 Subject: [PATCH 1/6] Add name substitution config (#1680) Co-authored-by: jonschz --- reccmp-project.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/reccmp-project.yml b/reccmp-project.yml index c0a1c907..315674a3 100644 --- a/reccmp-project.yml +++ b/reccmp-project.yml @@ -38,6 +38,10 @@ targets: - 0x100fb080 # memset etc. - 0x100f9570 + name-substitutions: + # Rename matched functions named like `FUN_12345678` to `LEGO1_12345678` + # so we can distinguish them from non-matched functions + - ["FUN_([0-9a-f]{8})", "LEGO1_\\1"] ALPHA: filename: ALPHA.DLL source-root: LEGO1 From d05d583368903224000860d364b13d558f13a9af Mon Sep 17 00:00:00 2001 From: Fabian Neundorf Date: Sun, 21 Sep 2025 20:11:04 +0200 Subject: [PATCH 2/6] Clear unknown parameter in `LegoEntity::SetROI` (#1688) --- LEGO1/lego/legoomni/include/act2actor.h | 4 ++-- LEGO1/lego/legoomni/include/legoactor.h | 4 ++-- LEGO1/lego/legoomni/include/legoentity.h | 8 ++++---- LEGO1/lego/legoomni/src/actors/act2actor.cpp | 4 ++-- LEGO1/lego/legoomni/src/entity/legoactor.cpp | 4 ++-- LEGO1/lego/legoomni/src/entity/legoentity.cpp | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/LEGO1/lego/legoomni/include/act2actor.h b/LEGO1/lego/legoomni/include/act2actor.h index 58455e90..6b39de3f 100644 --- a/LEGO1/lego/legoomni/include/act2actor.h +++ b/LEGO1/lego/legoomni/include/act2actor.h @@ -25,8 +25,8 @@ class Act2Actor : public LegoAnimActor { Act2Actor(); - void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) override; // vtable+0x24 - void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_updateTransform) override; // vtable+0x24 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 // FUNCTION: LEGO1 0x1001a180 MxS32 VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3) override diff --git a/LEGO1/lego/legoomni/include/legoactor.h b/LEGO1/lego/legoomni/include/legoactor.h index a3e68f2e..174ec4e1 100644 --- a/LEGO1/lego/legoomni/include/legoactor.h +++ b/LEGO1/lego/legoomni/include/legoactor.h @@ -40,8 +40,8 @@ class LegoActor : public LegoEntity { return !strcmp(p_name, LegoActor::ClassName()) || LegoEntity::IsA(p_name); } - void ParseAction(char* p_extra) override; // vtable+0x20 - void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) override; // vtable+0x24 + void ParseAction(char* p_extra) override; // vtable+0x20 + void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_updateTransform) override; // vtable+0x24 // FUNCTION: LEGO1 0x10002cc0 // FUNCTION: BETA10 0x1000f3e0 diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index ed1dd202..c4f81daf 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -53,10 +53,10 @@ class LegoEntity : public MxEntity { return !strcmp(p_name, LegoEntity::ClassName()) || MxEntity::IsA(p_name); } - virtual MxResult Create(MxDSAction& p_dsAction); // vtable+0x18 - virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c - virtual void ParseAction(char* p_extra); // vtable+0x20 - virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2); // vtable+0x24 + virtual MxResult Create(MxDSAction& p_dsAction); // vtable+0x18 + virtual void Destroy(MxBool p_fromDestructor); // vtable+0x1c + virtual void ParseAction(char* p_extra); // vtable+0x20 + virtual void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_updateTransform); // vtable+0x24 virtual void SetWorldTransform( const Vector3& p_location, const Vector3& p_direction, diff --git a/LEGO1/lego/legoomni/src/actors/act2actor.cpp b/LEGO1/lego/legoomni/src/actors/act2actor.cpp index 23697c6c..dcd7cb40 100644 --- a/LEGO1/lego/legoomni/src/actors/act2actor.cpp +++ b/LEGO1/lego/legoomni/src/actors/act2actor.cpp @@ -135,9 +135,9 @@ Act2Actor::Act2Actor() } // FUNCTION: LEGO1 0x10018940 -void Act2Actor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) +void Act2Actor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_updateTransform) { - LegoAnimActor::SetROI(p_roi, p_bool1, p_bool2); + LegoAnimActor::SetROI(p_roi, p_bool1, p_updateTransform); m_roi->SetVisibility(FALSE); } diff --git a/LEGO1/lego/legoomni/src/entity/legoactor.cpp b/LEGO1/lego/legoomni/src/entity/legoactor.cpp index 4b0428b8..c2196f30 100644 --- a/LEGO1/lego/legoomni/src/entity/legoactor.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoactor.cpp @@ -127,7 +127,7 @@ const char* LegoActor::GetActorName(MxU8 p_id) // FUNCTION: LEGO1 0x1002d670 // FUNCTION: BETA10 0x1003d65f -void LegoActor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) +void LegoActor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_updateTransform) { if (p_roi) { const char* name = p_roi->GetName(); @@ -141,7 +141,7 @@ void LegoActor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) } } - LegoEntity::SetROI(p_roi, p_bool1, p_bool2); + LegoEntity::SetROI(p_roi, p_bool1, p_updateTransform); } // FUNCTION: LEGO1 0x1002d6e0 diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index e0f3b810..d02c1c71 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -124,12 +124,12 @@ void LegoEntity::SetWorld() // FUNCTION: LEGO1 0x100108a0 // FUNCTION: BETA10 0x1007e724 -void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) +void LegoEntity::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_updateTransform) { m_roi = p_roi; if (m_roi != NULL) { - if (p_bool2) { + if (p_updateTransform) { MxMatrix mat; CalcLocalTransform( Mx3DPointFloat(m_worldLocation[0], m_worldLocation[1], m_worldLocation[2]), From 9531678dfdf81398327e111807492b7e831aacf6 Mon Sep 17 00:00:00 2001 From: Fabian Neundorf Date: Tue, 7 Oct 2025 23:04:02 +0200 Subject: [PATCH 3/6] Clear unknowns in `LegoCarBuild` (#1691) --- LEGO1/lego/legoomni/include/legocarbuild.h | 184 ++--- .../lego/legoomni/src/build/legocarbuild.cpp | 725 +++++++++--------- 2 files changed, 463 insertions(+), 446 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index 867a89a5..5da7ea5f 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -75,18 +75,28 @@ class LegoCarBuild : public LegoWorld { public: // SIZE 0x1c struct LookupTableActions { - undefined4 m_unk0x00; // 0x00 - undefined4 m_unk0x04; // 0x04 - undefined4 m_unk0x08; // 0x08 - undefined4 m_unk0x0c; // 0x0c - undefined4 m_unk0x10; // 0x10 - undefined4 m_unk0x14; // 0x14 - undefined4 m_unk0x18; // 0x18 + MxU32 m_introduction0; // 0x00 + MxU32 m_leaveUnfinished; // 0x04 + MxU32 m_completed; // 0x08 + MxU32 m_introduction1; // 0x0c + MxU32 m_introduction2; // 0x10 + MxU32 m_introduction3; // 0x14 + MxU32 m_shortExplanation; // 0x18 }; - enum Unknown0xf8 { - c_unknownminusone = -1, - c_unknown8 = 8 + enum LookupTableActionType { + e_introduction0 = 0, + e_introduction1 = 1, + e_introduction2 = 2, + e_introduction3 = 3, + e_leaveUnfinished = 4, + e_completed = 5, + e_shortExplanation = 6, + }; + + enum ResetPlacedSelectedPart { + c_disabled = -1, + c_enabled = 8 }; LegoCarBuild(); @@ -113,15 +123,15 @@ class LegoCarBuild : public LegoWorld { return !strcmp(p_name, LegoCarBuild::ClassName()) || LegoWorld::IsA(p_name); } - MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void ReadyWorld() override; // vtable+0x50 - MxBool Escape() override; // vtable+0x64 - void Enable(MxBool p_enable) override; // vtable+0x68 - virtual void VTable0x6c(); // vtable+0x6c - virtual void VTable0x70(); // vtable+0x70 - virtual void VTable0x74(MxFloat p_param1[2], MxFloat p_param2[3]); // vtable+0x74 - virtual void VTable0x78(MxFloat p_param1[2], MxFloat p_param2[3]); // vtable+0x78 - virtual void VTable0x7c(MxFloat p_param1[2], MxFloat p_param2[3]); // vtable+0x7c + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void ReadyWorld() override; // vtable+0x50 + MxBool Escape() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + virtual void InitializeDisplayingTransform(); // vtable+0x6c + virtual void CalculateStartAndTargetScreenPositions(); // vtable+0x70 + virtual void CalculateDragPositionAbove(MxFloat p_coordinates[2], MxFloat p_position[3]); // vtable+0x74 + virtual void CalculateDragPositionBetween(MxFloat p_coordinates[2], MxFloat p_position[3]); // vtable+0x78 + virtual void CalculateDragPositionOnGround(MxFloat p_coordinates[2], MxFloat p_position[3]); // vtable+0x7c virtual void VTable0x80( MxFloat p_param1[2], MxFloat p_param2[2], @@ -132,33 +142,33 @@ class LegoCarBuild : public LegoWorld { MxS16 GetPlacedPartCount(); void SetPlacedPartCount(MxU8 p_placedPartCount); void InitPresenters(); - void FUN_10022f00(); - void FUN_10022f30(); - void FUN_10023130(MxLong p_x, MxLong p_y); + void DisplaySelectedPart(); + void ResetSelectedPart(); + void CalculateSelectedPartMatrix(MxLong p_x, MxLong p_y); void AddSelectedPartToBuild(); - undefined4 FUN_10024250(LegoEventNotificationParam* p_param); - void FUN_100243a0(); - undefined4 FUN_10024480(MxActionNotificationParam* p_param); - undefined4 SelectPartFromMousePosition(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(MxParam* p_param); - undefined4 FUN_10024c20(MxNotificationParam* 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_objectId); - void FUN_10025450(); - void FUN_10025720(undefined4 p_param1); - void FUN_10025d10(MxS32 p_param); - MxS32 FUN_10025d70(); - void FUN_10025db0(const char* p_param1, undefined4 p_param2); - void FUN_10025e40(); - MxS32 FUN_10025ee0(undefined4 p_param1); + MxLong HandleKeyPress(LegoEventNotificationParam* p_param); + void InitExiting(); + MxLong HandleEndAction(MxActionNotificationParam* p_param); + MxLong SelectPartFromMousePosition(MxLong p_x, MxLong p_y); + MxLong HandleButtonUp(MxLong p_x, MxLong p_y); + MxLong HandleMouseMove(MxLong p_x, MxLong p_y); + MxLong HandleControl(MxParam* p_param); + MxLong HandleType0Notification(MxNotificationParam* p_param); + void StartIntroduction(); + void MoveShelves(); + void RotateVehicle(); + void EnableColorControlsForSelectedPart(MxBool p_enabled); + void SetColorControlsEnabled(MxBool p_enabled); + void ToggleColorControlsEnabled(); + void EnableDecalForSelectedPart(MxBool p_enabled); + void SetPartColor(MxS32 p_objectId); + void CalculateStartAndTargetTransforms(); + void StartActorScriptByType(MxS32 p_actionType); + void StartActorScript(MxS32 p_streamId); + MxS32 GetNextIntroduction(); + void TickleControl(const char* p_controlName, MxULong p_time); + void HandleEndAnim(); + MxS32 GetBuildMovieId(MxS32 p_carId); // FUNCTION: BETA10 0x100735b0 void SetCarBuildAnimPresenter(LegoCarBuildAnimPresenter* p_animPresenter) { m_animPresenter = p_animPresenter; } @@ -167,43 +177,45 @@ class LegoCarBuild : public LegoWorld { // LegoCarBuild::`scalar deleting destructor' private: - // inline functions - MxU32 Beta0x10070520(); - void StopActionIn0x344(); + enum { + e_idle = 0, + e_returning = 3, + e_selecting = 4, + e_displaying = 5, + e_dragging = 6, + }; - Unknown0xf8 m_unk0xf8; // 0xf8 - MxS16 m_unk0xfc; // 0xfc - MxS32 m_unk0x100; // 0x100 - undefined4 m_unk0x104; // 0x104 + // inline functions + MxU32 GetLookupIndex(); + void StopPlayingActorScript(); + + ResetPlacedSelectedPart m_resetPlacedSelectedPart; // 0xf8 + MxS16 m_rotateBuild; // 0xfc + MxS32 m_clickState; // 0x100 + undefined4 m_unk0x104; // 0x104 // name verified by BETA10 0x1006ebba MxS8 m_numAnimsRun; // 0x108 - MxU8 m_unk0x109; // 0x109 - MxU16 m_unk0x10a; // 0x10a - DWORD m_unk0x10c; // 0x10c - LegoROI* m_selectedPart; // 0x110 - BoundingSphere m_unk0x114; // 0x114 - MxMatrix m_unk0x12c; // 0x12c - undefined m_unk0x174; // 0x174 - MxMatrix m_unk0x178; // 0x178 - MxMatrix m_unk0x1c0; // 0x1c0 - MxMatrix m_unk0x208; // 0x208 - - // This is likely a location in pixel space - MxS32 m_unk0x250[2]; // 0x250 - - LegoCarBuildAnimPresenter* m_animPresenter; // 0x258 - MxQuaternionTransformer m_unk0x25c; // 0x25c - - // These two are likely locations in pixel space - MxS32 m_unk0x290[2]; // 0x290 - MxS32 m_unk0x298[2]; // 0x298 - - MxFloat m_unk0x2a0; // 0x2a0 - Mx4DPointFloat m_unk0x2a4; // 0x2a4 - Mx4DPointFloat m_unk0x2bc; // 0x2bc - MxBool m_selectedPartIsPlaced; // 0x2d4 + MxU8 m_missclickCounter; // 0x109 + MxU16 m_lastActorScript; // 0x10a + MxULong m_lastActorScriptStartTime; // 0x10c + LegoROI* m_selectedPart; // 0x110 + BoundingSphere m_targetBoundingSphere; // 0x114 + MxMatrix m_originalSelectedPartTransform; // 0x12c + MxBool m_alreadyFinished; // 0x174 + MxMatrix m_selectedPartStartTransform; // 0x178 + MxMatrix m_displayTransform; // 0x1c0 + MxMatrix m_selectedPartTargetTransform; // 0x208 + MxS32 m_selectedPartStartMousePosition[2]; // 0x250 + LegoCarBuildAnimPresenter* m_animPresenter; // 0x258 + MxQuaternionTransformer m_draggingQuarternionTransformer; // 0x25c + MxS32 m_selectedPartStartScreenPosition[2]; // 0x290 + MxS32 m_selectedPartTargetScreenPosition[2]; // 0x298 + MxFloat m_normalizedDistance; // 0x2a0 + Mx4DPointFloat m_selectedPartStartPosition; // 0x2a4 + Mx4DPointFloat m_selectedPartTargetPosition; // 0x2bc + MxBool m_displayedPartIsPlaced; // 0x2d4 // variable names verified by BETA10 0x1006b27a MxStillPresenter* m_ColorBook_Bitmap; // 0x2dc @@ -232,21 +244,21 @@ class LegoCarBuild : public LegoWorld { LegoVehicleBuildState* m_buildState; // 0x32c // variable name verified by BETA10 0x1006d742 - undefined4 m_carId; // 0x330 + MxS32 m_carId; // 0x330 // variable name verified by BETA10 0x1006cba7 LegoGameState::Area m_destLocation; // 0x334 - MxPresenter* m_unk0x338; // 0x338 - MxControlPresenter* m_unk0x33c; // 0x33c - undefined4 m_unk0x340; // 0x340 - undefined4 m_unk0x344; // 0x344 - MxU8 m_presentersEnabled; // 0x348 + MxPresenter* m_jukeboxPresenter; // 0x338 + MxControlPresenter* m_tickledControl; // 0x33c + undefined4 m_unk0x340; // 0x340 + MxS32 m_playingActorScript; // 0x344 + MxU8 m_presentersEnabled; // 0x348 - static MxS16 g_unk0x100f11cc; - static MxFloat g_unk0x100d65a4; + static MxS16 g_lastTickleState; + static MxFloat g_selectedPartRotationAngleStepYAxis; static MxFloat g_rotationAngleStepYAxis; - static LookupTableActions g_unk0x100d65b0[]; + static LookupTableActions g_actorScripts[]; }; #endif // LEGOCARBUILD_H diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 5ef54e8d..bb23e5d7 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -48,7 +48,7 @@ DECOMP_SIZE_ASSERT(LegoCarBuild::LookupTableActions, 0x1c); // GLOBAL: LEGO1 0x100d65b0 // GLOBAL: BETA10 0x101bb7c0 -LegoCarBuild::LookupTableActions LegoCarBuild::g_unk0x100d65b0[] = { +LegoCarBuild::LookupTableActions LegoCarBuild::g_actorScripts[] = { {DunecarScript::c_igs001d3_RunAnim, DunecarScript::c_igs002d3_RunAnim, DunecarScript::c_igs003d3_RunAnim, @@ -80,22 +80,22 @@ LegoCarBuild::LookupTableActions LegoCarBuild::g_unk0x100d65b0[] = { }; // GLOBAL: LEGO1 0x100d65a4 -MxFloat LegoCarBuild::g_unk0x100d65a4 = -0.1f; +MxFloat LegoCarBuild::g_selectedPartRotationAngleStepYAxis = -0.1f; // GLOBAL: LEGO1 0x100d65a8 MxFloat LegoCarBuild::g_rotationAngleStepYAxis = 0.07; // GLOBAL: LEGO1 0x100f11cc -MxS16 LegoCarBuild::g_unk0x100f11cc = -1; +MxS16 LegoCarBuild::g_lastTickleState = -1; // FUNCTION: LEGO1 0x100226d0 // FUNCTION: BETA10 0x1006ac10 LegoCarBuild::LegoCarBuild() { - m_unk0x100 = 0; + m_clickState = e_idle; m_selectedPart = 0; - m_unk0xf8 = c_unknownminusone; - m_selectedPartIsPlaced = FALSE; + m_resetPlacedSelectedPart = c_disabled; + m_displayedPartIsPlaced = FALSE; m_animPresenter = NULL; m_ColorBook_Bitmap = NULL; m_Yellow_Ctl = NULL; @@ -118,15 +118,15 @@ LegoCarBuild::LegoCarBuild() m_Decals_Ctl5 = NULL; m_Decals_Ctl6 = NULL; m_Decals_Ctl7 = NULL; - m_unk0x33c = NULL; + m_tickledControl = NULL; m_buildState = NULL; m_unk0x104 = 0; - m_unk0x109 = 0; + m_missclickCounter = 0; m_numAnimsRun = 0; - m_unk0x338 = 0; + m_jukeboxPresenter = 0; m_destLocation = LegoGameState::e_undefined; - m_unk0x344 = DS_NOT_A_STREAM; - m_unk0x174 = 0; + m_playingActorScript = DS_NOT_A_STREAM; + m_alreadyFinished = 0; NotificationManager()->Register(this); } @@ -134,7 +134,7 @@ LegoCarBuild::LegoCarBuild() // FUNCTION: BETA10 0x1006aea3 LegoCarBuild::~LegoCarBuild() { - m_unk0x100 = 0; + m_clickState = e_idle; m_selectedPart = NULL; if (m_animPresenter) { @@ -202,12 +202,12 @@ MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) } m_buildState = buildState; - m_unk0x174 = m_buildState->m_finishedBuild; + m_alreadyFinished = m_buildState->m_finishedBuild; GameState()->StopArea(LegoGameState::e_previousArea); m_buildState->m_animationState = LegoVehicleBuildState::e_entering; - m_unk0x100 = 0; + m_clickState = e_idle; BackgroundAudioManager()->Stop(); EnableAnimations(FALSE); @@ -286,22 +286,22 @@ void LegoCarBuild::InitPresenters() } // FUNCTION: LEGO1 0x10022f00 -void LegoCarBuild::FUN_10022f00() +void LegoCarBuild::DisplaySelectedPart() { if (m_selectedPart) { - VTable0x6c(); + InitializeDisplayingTransform(); m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_selected); - m_unk0x100 = 5; + m_clickState = e_displaying; } } // FUNCTION: LEGO1 0x10022f30 // FUNCTION: BETA10 0x1006b835 -void LegoCarBuild::FUN_10022f30() +void LegoCarBuild::ResetSelectedPart() { if (m_selectedPart) { - FUN_10024f70(FALSE); - FUN_100250e0(FALSE); + EnableColorControlsForSelectedPart(FALSE); + EnableDecalForSelectedPart(FALSE); if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) { m_PlaceBrick_Sound->Enable(FALSE); @@ -311,154 +311,157 @@ void LegoCarBuild::FUN_10022f30() m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_stopped); m_animPresenter->PutFrame(); m_selectedPart = NULL; - m_unk0x100 = 0; + m_clickState = e_idle; } } // FUNCTION: LEGO1 0x10022fc0 // FUNCTION: BETA10 0x1006b90b -void LegoCarBuild::VTable0x6c() +void LegoCarBuild::InitializeDisplayingTransform() { - m_unk0x178 = m_unk0x1c0; - m_selectedPart->WrappedSetLocal2WorldWithWorldDataUpdate(m_unk0x178); - m_unk0x2a4 = Vector4(m_selectedPart->GetWorldPosition()); + m_selectedPartStartTransform = m_displayTransform; + m_selectedPart->WrappedSetLocal2WorldWithWorldDataUpdate(m_selectedPartStartTransform); + m_selectedPartStartPosition = Vector4(m_selectedPart->GetWorldPosition()); - VTable0x70(); + CalculateStartAndTargetScreenPositions(); } // FUNCTION: LEGO1 0x10023020 // FUNCTION: BETA10 0x1006b991 -void LegoCarBuild::VTable0x70() +void LegoCarBuild::CalculateStartAndTargetScreenPositions() { MxFloat worldPos[3]; MxFloat screenPos[4]; - worldPos[0] = m_unk0x2a4[0]; - worldPos[1] = m_unk0x2a4[1]; - worldPos[2] = m_unk0x2a4[2]; + worldPos[0] = m_selectedPartStartPosition[0]; + worldPos[1] = m_selectedPartStartPosition[1]; + worldPos[2] = m_selectedPartStartPosition[2]; TransformWorldToScreen(worldPos, screenPos); - m_unk0x290[0] = screenPos[0] / screenPos[3]; - m_unk0x290[1] = screenPos[1] / screenPos[3]; + m_selectedPartStartScreenPosition[0] = screenPos[0] / screenPos[3]; + m_selectedPartStartScreenPosition[1] = screenPos[1] / screenPos[3]; - worldPos[0] = m_unk0x2bc[0]; - worldPos[1] = m_unk0x2bc[1]; - worldPos[2] = m_unk0x2bc[2]; + worldPos[0] = m_selectedPartTargetPosition[0]; + worldPos[1] = m_selectedPartTargetPosition[1]; + worldPos[2] = m_selectedPartTargetPosition[2]; TransformWorldToScreen(worldPos, screenPos); - m_unk0x298[0] = screenPos[0] / screenPos[3]; - m_unk0x298[1] = screenPos[1] / screenPos[3]; + m_selectedPartTargetScreenPosition[0] = screenPos[0] / screenPos[3]; + m_selectedPartTargetScreenPosition[1] = screenPos[1] / screenPos[3]; - m_unk0x2a0 = sqrt((MxDouble) DISTSQRD2(m_unk0x290, m_unk0x298)); + m_normalizedDistance = + sqrt((MxDouble) DISTSQRD2(m_selectedPartStartScreenPosition, m_selectedPartTargetScreenPosition)); - m_unk0x25c.SetStartEnd(m_unk0x178, m_unk0x208); + m_draggingQuarternionTransformer.SetStartEnd(m_selectedPartStartTransform, m_selectedPartTargetTransform); } // FUNCTION: LEGO1 0x10023130 // FUNCTION: BETA10 0x1006bb22 -void LegoCarBuild::FUN_10023130(MxLong p_x, MxLong p_y) +void LegoCarBuild::CalculateSelectedPartMatrix(MxLong p_x, MxLong p_y) { if (m_selectedPart) { - MxFloat pfVar3[2]; + MxFloat screenCoordinatesForRay[2]; MxFloat local30[3]; MxFloat local84[3]; - p_x += (m_unk0x290[0] - m_unk0x250[0]); - p_y += (m_unk0x290[1] - m_unk0x250[1]); + p_x += (m_selectedPartStartScreenPosition[0] - m_selectedPartStartMousePosition[0]); + p_y += (m_selectedPartStartScreenPosition[1] - m_selectedPartStartMousePosition[1]); - pfVar3[0] = p_x; - pfVar3[1] = p_y; + screenCoordinatesForRay[0] = p_x; + screenCoordinatesForRay[1] = p_y; - if (CalculateRayOriginDirection(pfVar3, local30, local84)) { - MxFloat local18[3]; - MxFloat local8c[2]; + if (CalculateRayOriginDirection(screenCoordinatesForRay, local30, local84)) { + MxFloat positionOffset[3]; + MxFloat screenPosition[2]; - local8c[0] = p_x; - local8c[1] = p_y; + screenPosition[0] = p_x; + screenPosition[1] = p_y; - local18[0] = 0; - local18[1] = 0; - local18[2] = 0; + positionOffset[0] = 0; + positionOffset[1] = 0; + positionOffset[2] = 0; - MxMatrix local78; + MxMatrix transform; - if (p_y < m_unk0x290[1]) { - VTable0x74(local8c, local18); + if (p_y < m_selectedPartStartScreenPosition[1]) { + CalculateDragPositionAbove(screenPosition, positionOffset); } - else if (p_y > m_unk0x298[1]) { - VTable0x7c(local8c, local18); + else if (p_y > m_selectedPartTargetScreenPosition[1]) { + CalculateDragPositionOnGround(screenPosition, positionOffset); } - else if (p_y >= m_unk0x290[1]) { - VTable0x78(local8c, local18); + else if (p_y >= m_selectedPartStartScreenPosition[1]) { + CalculateDragPositionBetween(screenPosition, positionOffset); } - MxS32 local20[2]; + MxS32 currentDistance[2]; - local20[0] = p_x - m_unk0x290[0]; - local20[1] = p_y - m_unk0x290[1]; + currentDistance[0] = p_x - m_selectedPartStartScreenPosition[0]; + currentDistance[1] = p_y - m_selectedPartStartScreenPosition[1]; - MxFloat local1c = sqrt((double) (NORMSQRD2(local20))) / m_unk0x2a0; + MxFloat distanceRatio = sqrt((double) (NORMSQRD2(currentDistance))) / m_normalizedDistance; - m_unk0x25c.InterpolateToMatrix(local78, local1c); + m_draggingQuarternionTransformer.InterpolateToMatrix(transform, distanceRatio); - local78[3][0] = m_unk0x178[3][0] + local18[0]; - local78[3][1] = m_unk0x178[3][1] + local18[1]; - local78[3][2] = m_unk0x178[3][2] + local18[2]; - local78[3][3] = 1.0; + transform[3][0] = m_selectedPartStartTransform[3][0] + positionOffset[0]; + transform[3][1] = m_selectedPartStartTransform[3][1] + positionOffset[1]; + transform[3][2] = m_selectedPartStartTransform[3][2] + positionOffset[2]; + transform[3][3] = 1.0; - m_selectedPart->WrappedSetLocal2WorldWithWorldDataUpdate(local78); + m_selectedPart->WrappedSetLocal2WorldWithWorldDataUpdate(transform); } } } // FUNCTION: LEGO1 0x10023500 // FUNCTION: BETA10 0x1006bdf6 -void LegoCarBuild::VTable0x74(MxFloat p_param1[2], MxFloat p_param2[3]) +void LegoCarBuild::CalculateDragPositionAbove(MxFloat p_coordinates[2], MxFloat p_position[3]) { - MxFloat fVar1; - MxFloat local20[3]; - MxFloat local14[3]; + MxFloat planeFactor; + MxFloat origin[3]; + MxFloat direction[3]; - CalculateRayOriginDirection(p_param1, local14, local20); + CalculateRayOriginDirection(p_coordinates, direction, origin); - fVar1 = (m_unk0x2a4[2] - local20[2]) / local14[2]; - p_param2[0] = (fVar1 * local14[0] + local20[0]) - m_unk0x2a4[0]; - p_param2[1] = (fVar1 * local14[1] + local20[1]) - m_unk0x2a4[1]; - p_param2[2] = 0.0; + planeFactor = (m_selectedPartStartPosition[2] - origin[2]) / direction[2]; + p_position[0] = (planeFactor * direction[0] + origin[0]) - m_selectedPartStartPosition[0]; + p_position[1] = (planeFactor * direction[1] + origin[1]) - m_selectedPartStartPosition[1]; + p_position[2] = 0.0; } // FUNCTION: LEGO1 0x10023570 // FUNCTION: BETA10 0x1006be91 -void LegoCarBuild::VTable0x78(MxFloat p_param1[2], MxFloat p_param2[3]) +void LegoCarBuild::CalculateDragPositionBetween(MxFloat p_coordinates[2], MxFloat p_position[3]) { - MxFloat fVar1; - MxFloat local18[3]; - MxFloat localc[3]; + MxFloat planeFactor; + MxFloat direction[3]; + MxFloat origin[3]; - CalculateRayOriginDirection(p_param1, local18, localc); + CalculateRayOriginDirection(p_coordinates, direction, origin); - p_param2[2] = m_unk0x2a4[2] + - (m_unk0x2bc[2] - m_unk0x2a4[2]) * ((p_param1[1] - m_unk0x290[1]) / (m_unk0x298[1] - m_unk0x290[1])); - fVar1 = (p_param2[2] - localc[2]) / local18[2]; - p_param2[0] = fVar1 * local18[0] - m_unk0x2a4[0] + localc[0]; - p_param2[1] = fVar1 * local18[1] - m_unk0x2a4[1] + localc[1]; - p_param2[2] = p_param2[2] - m_unk0x2a4[2]; + p_position[2] = m_selectedPartStartPosition[2] + + (m_selectedPartTargetPosition[2] - m_selectedPartStartPosition[2]) * + ((p_coordinates[1] - m_selectedPartStartScreenPosition[1]) / + (m_selectedPartTargetScreenPosition[1] - m_selectedPartStartScreenPosition[1])); + planeFactor = (p_position[2] - origin[2]) / direction[2]; + p_position[0] = planeFactor * direction[0] - m_selectedPartStartPosition[0] + origin[0]; + p_position[1] = planeFactor * direction[1] - m_selectedPartStartPosition[1] + origin[1]; + p_position[2] = p_position[2] - m_selectedPartStartPosition[2]; } // FUNCTION: LEGO1 0x10023620 // FUNCTION: BETA10 0x1006bfb5 -void LegoCarBuild::VTable0x7c(MxFloat p_param1[2], MxFloat p_param2[3]) +void LegoCarBuild::CalculateDragPositionOnGround(MxFloat p_coordinates[2], MxFloat p_position[3]) { - MxFloat local18[3]; - MxFloat localc[3]; - CalculateRayOriginDirection(p_param1, local18, localc); + MxFloat direction[3]; + MxFloat origin[3]; + CalculateRayOriginDirection(p_coordinates, direction, origin); - MxFloat fVar1 = (m_unk0x2bc[1] - localc[1]) / local18[1]; - p_param2[0] = fVar1 * local18[0] - m_unk0x2a4[0] + localc[0]; - p_param2[1] = m_unk0x2bc[1] - m_unk0x2a4[1]; - p_param2[2] = fVar1 * local18[2] - m_unk0x2a4[2] + localc[2]; + MxFloat planeFactor = (m_selectedPartTargetPosition[1] - origin[1]) / direction[1]; + p_position[0] = planeFactor * direction[0] - m_selectedPartStartPosition[0] + origin[0]; + p_position[1] = m_selectedPartTargetPosition[1] - m_selectedPartStartPosition[1]; + p_position[2] = planeFactor * direction[2] - m_selectedPartStartPosition[2] + origin[2]; } // FUNCTION: LEGO1 0x100236a0 @@ -476,40 +479,40 @@ void LegoCarBuild::VTable0x80(MxFloat p_param1[2], MxFloat p_param2[2], MxFloat // FUNCTION: BETA10 0x1006c076 void LegoCarBuild::AddSelectedPartToBuild() { - MxS32 pLVar2; + MxS32 jukeboxScript; - FUN_10024f70(FALSE); - FUN_100250e0(FALSE); + EnableColorControlsForSelectedPart(FALSE); + EnableDecalForSelectedPart(FALSE); m_animPresenter->AddPartToBuildByName(m_selectedPart->GetName()); m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_stopped); m_selectedPart = NULL; - m_unk0x100 = 0; + m_clickState = e_idle; if (m_animPresenter->AllPartsPlaced()) { // Note the code duplication with LEGO1 0x10025ee0 switch (m_carId) { - case 1: - pLVar2 = 0x2f; + case Helicopter_Actor: + jukeboxScript = JukeboxScript::c_HelicopterBuild_Movie; break; - case 2: - pLVar2 = 0x31; + case DuneBugy_Actor: + jukeboxScript = JukeboxScript::c_DuneCarBuild_Movie; break; - case 3: - pLVar2 = 0x33; + case Jetski_Actor: + jukeboxScript = JukeboxScript::c_JetskiBuild_Movie; break; - case 4: - pLVar2 = 0x35; + case RaceCar_Actor: + jukeboxScript = JukeboxScript::c_RaceCarBuild_Movie; } BackgroundAudioManager()->Init(); - InvokeAction(Extra::e_stop, *g_jukeboxScript, pLVar2, NULL); + InvokeAction(Extra::e_stop, *g_jukeboxScript, jukeboxScript, NULL); if (m_numAnimsRun > 0) { DeleteObjects(&m_atomId, 500, 510); } if (GameState()->GetCurrentAct() == LegoGameState::e_act2) { - FUN_100243a0(); + InitExiting(); } else { m_buildState->m_finishedBuild = TRUE; @@ -523,7 +526,7 @@ void LegoCarBuild::AddSelectedPartToBuild() #define LEGOCARBUILD_TICKLE_CASE(subtract, start, end, str) \ if (start < dTime && dTime < end) { \ - FUN_10025db0(str, dTime - subtract); \ + TickleControl(str, dTime - subtract); \ break; \ } @@ -536,28 +539,28 @@ MxResult LegoCarBuild::Tickle() return SUCCESS; } - if (m_unk0xf8 == c_unknown8) { - if (m_unk0xfc == 1) { - FUN_10024f50(); + if (m_resetPlacedSelectedPart == c_enabled) { + if (m_rotateBuild == 1) { + RotateVehicle(); } if (m_selectedPart) { if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) { - FUN_10022f30(); + ResetSelectedPart(); } } } - if (m_unk0x100 == 5 && m_selectedPart) { - RotateY(m_selectedPart, g_unk0x100d65a4); + if (m_clickState == e_displaying && m_selectedPart) { + RotateY(m_selectedPart, g_selectedPartRotationAngleStepYAxis); } - if (m_unk0x10a) { - DWORD time = timeGetTime(); - DWORD dTime = (time - m_unk0x10c) / 100; + if (m_lastActorScript) { + MxULong time = timeGetTime(); + MxULong dTime = (time - m_lastActorScriptStartTime) / 100; if (m_carId == RaceCar_Actor) { - switch (m_unk0x10a) { + switch (m_lastActorScript) { case RacecarScript::c_irt001d1_RunAnim: LEGOCARBUILD_TICKLE_CASE(160, 160, 180, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(260, 260, 280, "ShelfUp_Ctl") @@ -580,7 +583,7 @@ MxResult LegoCarBuild::Tickle() } } else if (m_carId == Jetski_Actor) { - switch (m_unk0x10a) { + switch (m_lastActorScript) { case JetskiScript::c_ijs001d4_RunAnim: LEGOCARBUILD_TICKLE_CASE(291, 291, 311, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(311, 311, 331, "ShelfUp_Ctl") @@ -603,7 +606,7 @@ MxResult LegoCarBuild::Tickle() } } else if (m_carId == DuneBugy_Actor) { - switch (m_unk0x10a) { + switch (m_lastActorScript) { case DunecarScript::c_igs001d3_RunAnim: LEGOCARBUILD_TICKLE_CASE(155, 155, 175, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(215, 215, 235, "ShelfUp_Ctl") @@ -620,7 +623,7 @@ MxResult LegoCarBuild::Tickle() } } else if (m_carId == Helicopter_Actor) { - switch (m_unk0x10a) { + switch (m_lastActorScript) { case CopterScript::c_ips001d2_RunAnim: LEGOCARBUILD_TICKLE_CASE(185, 185, 205, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(235, 235, 255, "ShelfUp_Ctl") @@ -656,30 +659,31 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) if (m_worldStarted) { switch (param.GetNotification()) { case c_notificationType0: - FUN_10024c20((MxNotificationParam*) &p_param); + HandleType0Notification((MxNotificationParam*) &p_param); result = 1; break; case c_notificationEndAction: - result = FUN_10024480((MxActionNotificationParam*) &p_param); + result = HandleEndAction((MxActionNotificationParam*) &p_param); break; case c_notificationKeyPress: - result = FUN_10024250((LegoEventNotificationParam*) &p_param); + result = HandleKeyPress((LegoEventNotificationParam*) &p_param); break; case c_notificationButtonUp: - result = FUN_100246e0( + result = HandleButtonUp( ((LegoEventNotificationParam&) p_param).GetX(), ((LegoEventNotificationParam&) p_param).GetY() ); - if (result || m_unk0x10a || m_buildState->m_animationState == LegoVehicleBuildState::e_finishedBuild || + if (result || m_lastActorScript || + m_buildState->m_animationState == LegoVehicleBuildState::e_finishedBuild || m_buildState->m_animationState == LegoVehicleBuildState::e_exiting) { - m_unk0x109 = 0; + m_missclickCounter = 0; break; } - if (++m_unk0x109 > 2) { - FUN_10025720(6); - m_unk0x109 = 0; + if (++m_missclickCounter > 2) { + StartActorScriptByType(LookupTableActionType::e_shortExplanation); + m_missclickCounter = 0; } break; @@ -697,21 +701,21 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) break; case c_notificationMouseMove: - result = FUN_10024850( + result = HandleMouseMove( ((LegoEventNotificationParam&) p_param).GetX(), ((LegoEventNotificationParam&) p_param).GetY() ); if (result == 1) { - m_unk0x109 = 0; + m_missclickCounter = 0; } break; case c_notificationControl: - result = FUN_10024890(&p_param); + result = HandleControl(&p_param); if (result == 1) { - m_unk0x109 = 0; + m_missclickCounter = 0; } break; @@ -720,8 +724,8 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) m_numAnimsRun -= 1; } - FUN_10025e40(); - m_unk0x10a = 0; + HandleEndAnim(); + m_lastActorScript = 0; result = 1; break; case c_notificationTransitioned: @@ -735,14 +739,14 @@ MxLong LegoCarBuild::Notify(MxParam& p_param) // FUNCTION: LEGO1 0x10024250 // FUNCTION: BETA10 0x1006cc48 -undefined4 LegoCarBuild::FUN_10024250(LegoEventNotificationParam* p_param) +MxLong LegoCarBuild::HandleKeyPress(LegoEventNotificationParam* p_param) { if (p_param->GetKey() == ' ' && m_buildState->m_animationState != LegoVehicleBuildState::e_finishedBuild && m_buildState->m_animationState != LegoVehicleBuildState::e_settingUpMovie) { if (m_numAnimsRun > 0) { DeleteObjects(&m_atomId, 500, 0x1fe); BackgroundAudioManager()->RaiseVolume(); - m_unk0x109 = 0; + m_missclickCounter = 0; } return 1; @@ -758,17 +762,17 @@ void LegoCarBuild::ReadyWorld() InitPresenters(); if (BackgroundAudioManager()->GetEnabled()) { - InvokeAction(Extra::ActionType::e_start, *g_jukeboxScript, FUN_10025ee0(m_carId), NULL); + InvokeAction(Extra::ActionType::e_start, *g_jukeboxScript, GetBuildMovieId(m_carId), NULL); m_buildState->m_animationState = LegoVehicleBuildState::e_settingUpMovie; NotificationManager()->Send(this, MxNotificationParam()); } else { - FUN_10024ef0(); + StartIntroduction(); } } // FUNCTION: LEGO1 0x100243a0 -void LegoCarBuild::FUN_100243a0() +void LegoCarBuild::InitExiting() { switch (m_carId) { case Helicopter_Actor: @@ -797,9 +801,9 @@ void LegoCarBuild::FUN_100243a0() } // FUNCTION: LEGO1 0x10024480 -undefined4 LegoCarBuild::FUN_10024480(MxActionNotificationParam* p_param) +MxLong LegoCarBuild::HandleEndAction(MxActionNotificationParam* p_param) { - MxS32 result = 0; + MxLong result = 0; switch (m_buildState->m_animationState) { case LegoVehicleBuildState::e_cutscene: @@ -808,8 +812,8 @@ undefined4 LegoCarBuild::FUN_10024480(MxActionNotificationParam* p_param) result = 1; break; case LegoVehicleBuildState::e_exiting: - if (p_param->GetAction()->GetObjectId() == m_unk0x344) { - FUN_100243a0(); + if (p_param->GetAction()->GetObjectId() == m_playingActorScript) { + InitExiting(); result = 1; break; } @@ -820,10 +824,10 @@ undefined4 LegoCarBuild::FUN_10024480(MxActionNotificationParam* p_param) // FUNCTION: LEGO1 0x100244e0 // FUNCTION: BETA10 0x1006cfb6 -undefined4 LegoCarBuild::SelectPartFromMousePosition(MxLong p_x, MxLong p_y) +MxLong LegoCarBuild::SelectPartFromMousePosition(MxLong p_x, MxLong p_y) { - m_unk0x250[0] = p_x; - m_unk0x250[1] = p_y; + m_selectedPartStartMousePosition[0] = p_x; + m_selectedPartStartMousePosition[1] = p_y; LegoROI* roi = PickROI(p_x, p_y); @@ -832,43 +836,45 @@ undefined4 LegoCarBuild::SelectPartFromMousePosition(MxLong p_x, MxLong p_y) } if (m_selectedPart != roi) { - FUN_10022f30(); + ResetSelectedPart(); m_selectedPart = roi; - FUN_10024f70(TRUE); - FUN_100250e0(TRUE); + EnableColorControlsForSelectedPart(TRUE); + EnableDecalForSelectedPart(TRUE); } - if (m_unk0x100 == 5 && m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) { - m_selectedPartIsPlaced = TRUE; + if (m_clickState == e_displaying && m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) { + m_displayedPartIsPlaced = TRUE; } else { - m_selectedPartIsPlaced = FALSE; + m_displayedPartIsPlaced = FALSE; } - FUN_10025450(); - VTable0x70(); + CalculateStartAndTargetTransforms(); + CalculateStartAndTargetScreenPositions(); if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) { - if (m_unk0x100 != 5) { - m_unk0x250[0] += m_unk0x290[0] - m_unk0x298[0]; - m_unk0x250[1] += m_unk0x290[1] - m_unk0x298[1]; + if (m_clickState != e_displaying) { + m_selectedPartStartMousePosition[0] += + m_selectedPartStartScreenPosition[0] - m_selectedPartTargetScreenPosition[0]; + m_selectedPartStartMousePosition[1] += + m_selectedPartStartScreenPosition[1] - m_selectedPartTargetScreenPosition[1]; } - if (m_unk0x100 == 0) { - m_unk0x114 = m_selectedPart->GetWorldBoundingSphere(); + if (m_clickState == e_idle) { + m_targetBoundingSphere = m_selectedPart->GetWorldBoundingSphere(); } } else { if (m_animPresenter->IsNextPartToPlace(m_selectedPart->GetName())) { - m_unk0x114 = m_animPresenter->GetTargetBoundingSphere(); + m_targetBoundingSphere = m_animPresenter->GetTargetBoundingSphere(); } } - switch (m_unk0x100) { - case 0: - m_unk0x100 = 4; + switch (m_clickState) { + case e_idle: + m_clickState = e_selecting; break; - case 5: - m_unk0x100 = 3; + case e_displaying: + m_clickState = e_returning; break; } @@ -881,44 +887,44 @@ undefined4 LegoCarBuild::SelectPartFromMousePosition(MxLong p_x, MxLong p_y) // FUNCTION: LEGO1 0x100246e0 // FUNCTION: BETA10 0x1006d25a -undefined4 LegoCarBuild::FUN_100246e0(MxLong p_x, MxLong p_y) +MxLong LegoCarBuild::HandleButtonUp(MxLong p_x, MxLong p_y) { - undefined4 result = 0; + MxLong result = 0; - switch (m_unk0x100) { - case 3: - FUN_10022f30(); + switch (m_clickState) { + case e_returning: + ResetSelectedPart(); result = 1; break; - case 4: - FUN_10022f00(); + case e_selecting: + DisplaySelectedPart(); result = 1; break; - case 6: + case e_dragging: if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName()) && - SpheresIntersect(m_unk0x114, m_selectedPart->GetWorldBoundingSphere())) { - FUN_10024f70(FALSE); - FUN_100250e0(FALSE); - m_unk0x100 = 0; + SpheresIntersect(m_targetBoundingSphere, m_selectedPart->GetWorldBoundingSphere())) { + EnableColorControlsForSelectedPart(FALSE); + EnableDecalForSelectedPart(FALSE); + m_clickState = e_idle; m_selectedPart = NULL; m_PlaceBrick_Sound->Enable(FALSE); m_PlaceBrick_Sound->Enable(TRUE); m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_stopped); } else if (m_animPresenter->IsNextPartToPlace(m_selectedPart->GetName())) { - if (SpheresIntersect(m_unk0x114, m_selectedPart->GetWorldBoundingSphere())) { + if (SpheresIntersect(m_targetBoundingSphere, m_selectedPart->GetWorldBoundingSphere())) { m_PlaceBrick_Sound->Enable(FALSE); m_PlaceBrick_Sound->Enable(TRUE); AddSelectedPartToBuild(); } else { - VTable0x6c(); - m_unk0x100 = 5; + InitializeDisplayingTransform(); + m_clickState = e_displaying; } } else { - VTable0x6c(); - m_unk0x100 = 5; + InitializeDisplayingTransform(); + m_clickState = e_displaying; } result = 1; @@ -930,16 +936,16 @@ undefined4 LegoCarBuild::FUN_100246e0(MxLong p_x, MxLong p_y) // FUNCTION: LEGO1 0x10024850 // FUNCTION: BETA10 0x1006d48e -MxS32 LegoCarBuild::FUN_10024850(MxLong p_x, MxLong p_y) +MxLong LegoCarBuild::HandleMouseMove(MxLong p_x, MxLong p_y) { - MxS32 result = 0; + MxLong result = 0; - switch (m_unk0x100) { - case 3: - case 4: - m_unk0x100 = 6; - case 6: - FUN_10023130(p_x, p_y); + switch (m_clickState) { + case e_returning: + case e_selecting: + m_clickState = e_dragging; + case e_dragging: + CalculateSelectedPartMatrix(p_x, p_y); result = 1; break; } @@ -950,9 +956,9 @@ MxS32 LegoCarBuild::FUN_10024850(MxLong p_x, MxLong p_y) #ifndef BETA10 // FUNCTION: LEGO1 0x10024890 -undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) +MxLong LegoCarBuild::HandleControl(MxParam* p_param) { - undefined4 result = 0; + MxLong result = 0; LegoControlManagerNotificationParam* param = (LegoControlManagerNotificationParam*) p_param; assert(m_buildState); @@ -985,7 +991,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_selected); if (GameState()->GetCurrentAct() == LegoGameState::e_act2) { - FUN_100243a0(); + InitExiting(); } else if (m_animPresenter->AllPartsPlaced() || m_buildState->m_finishedBuild) { m_buildState->m_finishedBuild = TRUE; @@ -996,7 +1002,7 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) m_buildState->m_animationState = LegoVehicleBuildState::e_finishedBuild; } else { - FUN_10025720(4); + StartActorScriptByType(LookupTableActionType::e_leaveUnfinished); m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; } @@ -1004,15 +1010,15 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) } break; case CopterScript::c_ShelfUp_Ctl: - FUN_10024f30(); + MoveShelves(); 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_enabledChild; + RotateVehicle(); + m_resetPlacedSelectedPart = c_enabled; + m_rotateBuild = param->m_enabledChild; result = 1; break; default: @@ -1029,15 +1035,15 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) m_Decal_Sound->Enable(TRUE); } else { - FUN_10025350(param->m_clickedObjectId); + SetPartColor(param->m_clickedObjectId); } result = 1; } } else { - m_unk0xf8 = c_unknownminusone; - m_unk0xfc = -1; + m_resetPlacedSelectedPart = c_disabled; + m_rotateBuild = -1; } // It is a bit unexpected that LEGO1 and BETA10 match so well with the `return 1` @@ -1048,9 +1054,9 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) #else // FUNCTION: BETA10 0x1006d512 -undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) +MxLong LegoCarBuild::HandleControl(MxParam* p_param) { - undefined4 result = 0; + MxLong result = 0; LegoControlManagerNotificationParam* param = (LegoControlManagerNotificationParam*) p_param; assert(m_buildState); @@ -1080,12 +1086,12 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) } else { - FUN_10025720(5); + StartActorScriptByType(LookupTableActionType::e_completed); m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; } } else { - FUN_10025720(4); + StartActorScriptByType(LookupTableActionType::e_leaveUnfinished); m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; } @@ -1108,15 +1114,15 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) } break; case CopterScript::c_ShelfUp_Ctl: - FUN_10024f30(); + MoveShelves(); 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_enabledChild; + RotateVehicle(); + m_resetPlacedSelectedPart = c_enabled; + m_rotateBuild = param->m_enabledChild; result = 1; break; default: @@ -1133,14 +1139,14 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) m_Decal_Sound->Enable(TRUE); } else { - FUN_10025350(param->m_clickedObjectId); + SetPartColor(param->m_clickedObjectId); } result = 1; } } else { - m_unk0xf8 = c_unknownminusone; - m_unk0xfc = -1; + m_resetPlacedSelectedPart = c_disabled; + m_rotateBuild = -1; } return 1; @@ -1150,13 +1156,13 @@ undefined4 LegoCarBuild::FUN_10024890(MxParam* p_param) // FUNCTION: LEGO1 0x10024c20 // FUNCTION: BETA10 0x1006db21 -undefined4 LegoCarBuild::FUN_10024c20(MxNotificationParam* p_param) +MxLong LegoCarBuild::HandleType0Notification(MxNotificationParam* p_param) { LegoEntity* entity; assert(m_buildState); switch (m_buildState->m_animationState) { - case LegoVehicleBuildState::e_finishedBuild: + case LegoVehicleBuildState::AnimationState::e_finishedBuild: entity = (LegoEntity*) Find(m_atomId, m_carId); if (entity && entity->GetROI()) { @@ -1206,17 +1212,17 @@ undefined4 LegoCarBuild::FUN_10024c20(MxNotificationParam* p_param) m_buildState->m_animationState = LegoVehicleBuildState::e_exiting; if (!m_animPresenter->AllPartsPlaced()) { - FUN_100243a0(); + InitExiting(); } else { - FUN_10025720(5); + StartActorScriptByType(LookupTableActionType::e_completed); } } else { NotificationManager()->Send(this, MxNotificationParam()); } break; - case LegoVehicleBuildState::e_settingUpMovie: + case LegoVehicleBuildState::AnimationState::e_settingUpMovie: MxU32 jukeboxScript; switch (m_carId) { @@ -1233,11 +1239,11 @@ undefined4 LegoCarBuild::FUN_10024c20(MxNotificationParam* p_param) jukeboxScript = JukeboxScript::c_RaceCarBuild_Music; } - m_unk0x338 = SoundManager()->FindPresenter(*g_jukeboxScript, jukeboxScript); + m_jukeboxPresenter = SoundManager()->FindPresenter(*g_jukeboxScript, jukeboxScript); - if (m_unk0x338) { - BackgroundAudioManager()->SetPendingPresenter(m_unk0x338, 5, MxPresenter::e_repeating); - FUN_10024ef0(); + if (m_jukeboxPresenter) { + BackgroundAudioManager()->SetPendingPresenter(m_jukeboxPresenter, 5, MxPresenter::e_repeating); + StartIntroduction(); } else { // In BETA10, NotificationManager->Send() also takes __FILE__ and __LINE__ arguments @@ -1250,43 +1256,43 @@ undefined4 LegoCarBuild::FUN_10024c20(MxNotificationParam* p_param) } // FUNCTION: LEGO1 0x10024ef0 -void LegoCarBuild::FUN_10024ef0() +void LegoCarBuild::StartIntroduction() { ResetViewVelocity(); m_buildState->m_animationState = LegoVehicleBuildState::e_cutscene; - FUN_10025720(FUN_10025d70()); + StartActorScriptByType(GetNextIntroduction()); m_buildState->m_introductionCounter += 1; Disable(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } // FUNCTION: LEGO1 0x10024f30 // FUNCTION: BETA10 0x1006dfa0 -void LegoCarBuild::FUN_10024f30() +void LegoCarBuild::MoveShelves() { - FUN_10022f30(); + ResetSelectedPart(); m_animPresenter->SetShelfState(LegoCarBuildAnimPresenter::e_moving); } // FUNCTION: LEGO1 0x10024f50 // FUNCTION: BETA10 0x1006dfce -void LegoCarBuild::FUN_10024f50() +void LegoCarBuild::RotateVehicle() { - m_selectedPartIsPlaced = FALSE; + m_displayedPartIsPlaced = FALSE; m_animPresenter->RotateAroundYAxis(g_rotationAngleStepYAxis); } // FUNCTION: LEGO1 0x10024f70 // FUNCTION: BETA10 0x1006e002 -void LegoCarBuild::FUN_10024f70(MxBool p_enabled) +void LegoCarBuild::EnableColorControlsForSelectedPart(MxBool p_enabled) { if (m_animPresenter->StringEndsOnY(m_selectedPart->GetName())) { - SetPresentersEnabled(p_enabled); + SetColorControlsEnabled(p_enabled); } } // FUNCTION: LEGO1 0x10024fa0 // FUNCTION: BETA10 0x1006e04f -void LegoCarBuild::SetPresentersEnabled(MxBool p_enabled) +void LegoCarBuild::SetColorControlsEnabled(MxBool p_enabled) { m_presentersEnabled = p_enabled; m_ColorBook_Bitmap->Enable(p_enabled); @@ -1299,7 +1305,7 @@ void LegoCarBuild::SetPresentersEnabled(MxBool p_enabled) } // FUNCTION: LEGO1 0x10025010 -void LegoCarBuild::TogglePresentersEnabled() +void LegoCarBuild::ToggleColorControlsEnabled() { m_ColorBook_Bitmap->Enable(!m_ColorBook_Bitmap->IsEnabled()); m_Yellow_Ctl->Enable(!m_Yellow_Ctl->IsEnabled()); @@ -1312,7 +1318,7 @@ void LegoCarBuild::TogglePresentersEnabled() // FUNCTION: LEGO1 0x100250e0 // FUNCTION: BETA10 0x1006e124 -void LegoCarBuild::FUN_100250e0(MxBool p_enabled) +void LegoCarBuild::EnableDecalForSelectedPart(MxBool p_enabled) { if (m_animPresenter->StringDoesNotEndOnZero(m_selectedPart->GetName()) && m_Decals_Ctl) { if (strnicmp(m_selectedPart->GetName(), "JSFRNT", strlen("JSFRNT")) == 0) { @@ -1349,7 +1355,7 @@ void LegoCarBuild::FUN_100250e0(MxBool p_enabled) // FUNCTION: LEGO1 0x10025350 // FUNCTION: BETA10 0x1006e3c0 -void LegoCarBuild::FUN_10025350(MxS32 p_objectId) +void LegoCarBuild::SetPartColor(MxS32 p_objectId) { const LegoChar* color; LegoChar buffer[256]; @@ -1389,34 +1395,34 @@ void LegoCarBuild::FUN_10025350(MxS32 p_objectId) // FUNCTION: LEGO1 0x10025450 // FUNCTION: BETA10 0x1006e599 -void LegoCarBuild::FUN_10025450() +void LegoCarBuild::CalculateStartAndTargetTransforms() { - m_unk0x12c = m_selectedPart->GetLocal2World(); - m_unk0x1c0 = m_unk0x12c; + m_originalSelectedPartTransform = m_selectedPart->GetLocal2World(); + m_displayTransform = m_originalSelectedPartTransform; - Vector3 lastColumnOfUnk0x1c0(m_unk0x1c0[3]); - lastColumnOfUnk0x1c0 = Vector3(m_animPresenter->GetBuildViewMatrix()[3]); + Vector3 displayPosition(m_displayTransform[3]); + displayPosition = Vector3(m_animPresenter->GetBuildViewMatrix()[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; + // Feel free to replace selectedPartStartTransform -> m_selectedPartStartTransform and remove this variable if it + // improves the LEGO1 match in the future. + MxMatrix* selectedPartStartTransform = &m_selectedPartStartTransform; + *selectedPartStartTransform = m_originalSelectedPartTransform; if (m_animPresenter->PartIsPlaced(m_selectedPart->GetName())) { - m_unk0x2a4 = Vector4(m_selectedPart->GetWorldPosition()); + m_selectedPartStartPosition = Vector4(m_selectedPart->GetWorldPosition()); - if (!m_selectedPartIsPlaced) { - m_unk0x2bc = m_unk0x2a4; + if (!m_displayedPartIsPlaced) { + m_selectedPartTargetPosition = m_selectedPartStartPosition; - 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]; + m_selectedPartTargetTransform = m_originalSelectedPartTransform; + m_selectedPartStartPosition[0] += m_displayTransform[3][0] - m_selectedPartTargetTransform[3][0]; + m_selectedPartStartPosition[1] += m_displayTransform[3][1] - m_selectedPartTargetTransform[3][1]; + m_selectedPartStartPosition[2] += m_displayTransform[3][2] - m_selectedPartTargetTransform[3][2]; } - *unk0x178 = m_unk0x1c0; + *selectedPartStartTransform = m_displayTransform; } else { const LegoChar* wiredName; @@ -1429,12 +1435,12 @@ void LegoCarBuild::FUN_10025450() } LegoROI* parentROI = (LegoROI*) m_selectedPart->GetParentROI(); - m_unk0x208 = parentROI->FindChildROI(wiredName, parentROI)->GetLocal2World(); - m_unk0x2bc = Vector4(parentROI->FindChildROI(wiredName, parentROI)->GetWorldPosition()); - m_unk0x2a4 = Vector4(m_selectedPart->GetWorldPosition()); + m_selectedPartTargetTransform = parentROI->FindChildROI(wiredName, parentROI)->GetLocal2World(); + m_selectedPartTargetPosition = Vector4(parentROI->FindChildROI(wiredName, parentROI)->GetWorldPosition()); + m_selectedPartStartPosition = Vector4(m_selectedPart->GetWorldPosition()); - m_unk0x2a4[2] += (m_unk0x1c0[3][2] - m_unk0x12c[3][2]); - m_unk0x178[3][2] = m_unk0x1c0[3][2]; + m_selectedPartStartPosition[2] += (m_displayTransform[3][2] - m_originalSelectedPartTransform[3][2]); + m_selectedPartStartTransform[3][2] = m_displayTransform[3][2]; } } @@ -1457,7 +1463,7 @@ void LegoCarBuild::Enable(MxBool p_enable) } // FUNCTION: BETA10 0x10070520 -inline MxU32 LegoCarBuild::Beta0x10070520() +inline MxU32 LegoCarBuild::GetLookupIndex() { switch (m_carId) { case Helicopter_Actor: @@ -1474,73 +1480,73 @@ inline MxU32 LegoCarBuild::Beta0x10070520() } } -inline void LegoCarBuild::StopActionIn0x344() +inline void LegoCarBuild::StopPlayingActorScript() { // There is no direct evidence for this inline function in LEGO1, // but some code doesn't make much sense otherwise. For example, - // sometimes `m_unk0x344` is set to another value right below this call, + // sometimes `m_playingActorScript` is set to another value right below this call, // which the original developer would likely have refactored. - if (m_unk0x344 != DS_NOT_A_STREAM) { - InvokeAction(Extra::ActionType::e_stop, m_atomId, m_unk0x344, NULL); - m_unk0x344 = DS_NOT_A_STREAM; + if (m_playingActorScript != DS_NOT_A_STREAM) { + InvokeAction(Extra::ActionType::e_stop, m_atomId, m_playingActorScript, NULL); + m_playingActorScript = DS_NOT_A_STREAM; } } // FUNCTION: LEGO1 0x10025720 // FUNCTION: BETA10 0x1006e9df -void LegoCarBuild::FUN_10025720(undefined4 p_param) +void LegoCarBuild::StartActorScriptByType(MxS32 p_actionType) { m_numAnimsRun++; - m_unk0x10a = 0; - MxS32 uVar6; + m_lastActorScript = 0; + MxS32 nextActorScript; #ifndef BETA10 if (GameState()->GetCurrentAct() == LegoGameState::e_act2) { // This is most likely related to the helicopter rebuild in Act 2 - switch (p_param) { - case 0: - case 1: - case 2: - case 3: + switch (p_actionType) { + case LookupTableActionType::e_introduction0: + case LookupTableActionType::e_introduction1: + case LookupTableActionType::e_introduction2: + case LookupTableActionType::e_introduction3: switch (rand() % 3) { case 0: - m_unk0x10a = CopterScript::c_ips004d2_RunAnim; - StopActionIn0x344(); - m_unk0x344 = CopterScript::c_ips004d2_RunAnim; + m_lastActorScript = CopterScript::c_ips004d2_RunAnim; + StopPlayingActorScript(); + m_playingActorScript = CopterScript::c_ips004d2_RunAnim; BackgroundAudioManager()->LowerVolume(); InvokeAction(Extra::ActionType::e_start, m_atomId, CopterScript::c_ips004d2_RunAnim, NULL); break; case 1: - m_unk0x10a = CopterScript::c_ips006d2_RunAnim; - StopActionIn0x344(); - m_unk0x344 = CopterScript::c_ips006d2_RunAnim; + m_lastActorScript = CopterScript::c_ips006d2_RunAnim; + StopPlayingActorScript(); + m_playingActorScript = CopterScript::c_ips006d2_RunAnim; BackgroundAudioManager()->LowerVolume(); InvokeAction(Extra::ActionType::e_start, m_atomId, CopterScript::c_ips006d2_RunAnim, NULL); break; case 2: - m_unk0x10a = CopterScript::c_slp01xd2_RunAnim; - StopActionIn0x344(); - m_unk0x344 = CopterScript::c_slp01xd2_RunAnim; + m_lastActorScript = CopterScript::c_slp01xd2_RunAnim; + StopPlayingActorScript(); + m_playingActorScript = CopterScript::c_slp01xd2_RunAnim; BackgroundAudioManager()->LowerVolume(); InvokeAction(Extra::ActionType::e_start, m_atomId, CopterScript::c_slp01xd2_RunAnim, NULL); break; } break; - case 4: - FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x04); + case LookupTableActionType::e_leaveUnfinished: + StartActorScript(g_actorScripts[GetLookupIndex()].m_leaveUnfinished); break; - case 5: - FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x08); + case LookupTableActionType::e_completed: + StartActorScript(g_actorScripts[GetLookupIndex()].m_completed); break; - case 6: - m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x18; - uVar6 = m_unk0x10a; - StopActionIn0x344(); + case LookupTableActionType::e_shortExplanation: + m_lastActorScript = g_actorScripts[GetLookupIndex()].m_shortExplanation; + nextActorScript = m_lastActorScript; + StopPlayingActorScript(); - if (uVar6 != DS_NOT_A_STREAM) { - m_unk0x344 = uVar6; + if (nextActorScript != DS_NOT_A_STREAM) { + m_playingActorScript = nextActorScript; BackgroundAudioManager()->LowerVolume(); - InvokeAction(Extra::ActionType::e_start, m_atomId, uVar6, NULL); + InvokeAction(Extra::ActionType::e_start, m_atomId, nextActorScript, NULL); } break; @@ -1552,41 +1558,41 @@ void LegoCarBuild::FUN_10025720(undefined4 p_param) else { #endif // This part doesn't match BETA10 perfectly, but it's the closest we get without hundreds of #ifdef's - switch (p_param) { - case 0: - m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x00; - FUN_10025d10(m_unk0x10a); + switch (p_actionType) { + case LookupTableActionType::e_introduction0: + m_lastActorScript = g_actorScripts[GetLookupIndex()].m_introduction0; + StartActorScript(m_lastActorScript); break; - case 1: - m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x0c; - FUN_10025d10(m_unk0x10a); + case LookupTableActionType::e_introduction1: + m_lastActorScript = g_actorScripts[GetLookupIndex()].m_introduction1; + StartActorScript(m_lastActorScript); - if (m_carId == 2) { - m_unk0x10a = 0; + if (m_carId == DuneBugy_Actor) { + m_lastActorScript = 0; } break; - case 2: - m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x10; - FUN_10025d10(m_unk0x10a); + case LookupTableActionType::e_introduction2: + m_lastActorScript = g_actorScripts[GetLookupIndex()].m_introduction2; + StartActorScript(m_lastActorScript); - if (m_carId != 3) { - m_unk0x10a = 0; + if (m_carId != Jetski_Actor) { + m_lastActorScript = 0; } break; - case 3: - FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x14); + case LookupTableActionType::e_introduction3: + StartActorScript(g_actorScripts[GetLookupIndex()].m_introduction3); break; - case 4: - FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x04); + case LookupTableActionType::e_leaveUnfinished: + StartActorScript(g_actorScripts[GetLookupIndex()].m_leaveUnfinished); break; - case 5: - FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x08); + case LookupTableActionType::e_completed: + StartActorScript(g_actorScripts[GetLookupIndex()].m_completed); break; - case 6: - m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x18; - FUN_10025d10(m_unk0x10a); + case LookupTableActionType::e_shortExplanation: + m_lastActorScript = g_actorScripts[GetLookupIndex()].m_shortExplanation; + StartActorScript(m_lastActorScript); break; default: assert(0); @@ -1600,74 +1606,74 @@ void LegoCarBuild::FUN_10025720(undefined4 p_param) } #endif - if (m_unk0x10a != 0) { - m_unk0x10c = timeGetTime(); + if (m_lastActorScript != 0) { + m_lastActorScriptStartTime = timeGetTime(); } } // FUNCTION: LEGO1 0x10025d10 // FUNCTION: BETA10 0x10070490 -void LegoCarBuild::FUN_10025d10(MxS32 p_param) +void LegoCarBuild::StartActorScript(MxS32 p_streamId) { // this function has a different signature and partially different body in BETA10, but it is called in the same // places - if (m_unk0x344 != DS_NOT_A_STREAM) { - InvokeAction(Extra::ActionType::e_stop, m_atomId, m_unk0x344, NULL); - m_unk0x344 = DS_NOT_A_STREAM; + if (m_playingActorScript != DS_NOT_A_STREAM) { + InvokeAction(Extra::ActionType::e_stop, m_atomId, m_playingActorScript, NULL); + m_playingActorScript = DS_NOT_A_STREAM; } - if (p_param != DS_NOT_A_STREAM) { - m_unk0x344 = p_param; + if (p_streamId != DS_NOT_A_STREAM) { + m_playingActorScript = p_streamId; BackgroundAudioManager()->LowerVolume(); - InvokeAction(Extra::ActionType::e_start, m_atomId, p_param, NULL); + InvokeAction(Extra::ActionType::e_start, m_atomId, p_streamId, NULL); } } // FUNCTION: LEGO1 0x10025d70 -MxS32 LegoCarBuild::FUN_10025d70() +MxS32 LegoCarBuild::GetNextIntroduction() { switch (m_buildState->m_introductionCounter % 3) { case 1: - return 1; + return LookupTableActionType::e_introduction1; case 2: - return 2; + return LookupTableActionType::e_introduction2; case 3: - return 3; + return LookupTableActionType::e_introduction3; default: - return 0; + return LookupTableActionType::e_introduction0; } } // FUNCTION: LEGO1 0x10025db0 // FUNCTION: BETA10 0x1006ed18 -void LegoCarBuild::FUN_10025db0(const char* p_param1, undefined4 p_param2) +void LegoCarBuild::TickleControl(const char* p_controlName, MxULong p_time) { - m_unk0x33c = (MxControlPresenter*) Find("MxControlPresenter", p_param1); + m_tickledControl = (MxControlPresenter*) Find("MxControlPresenter", p_controlName); - MxS16 sVar3 = 1 - ((p_param2 / 5) & 1); + MxS16 expectedState = 1 - ((p_time / 5) & 1); - if (m_Yellow_Ctl == m_unk0x33c) { - if (sVar3 != g_unk0x100f11cc) { - TogglePresentersEnabled(); - g_unk0x100f11cc = sVar3; + if (m_Yellow_Ctl == m_tickledControl) { + if (expectedState != g_lastTickleState) { + ToggleColorControlsEnabled(); + g_lastTickleState = expectedState; } } else { - if (m_unk0x33c->GetEnabledChild() != sVar3) { - m_unk0x33c->UpdateEnabledChild(sVar3); + if (m_tickledControl->GetEnabledChild() != expectedState) { + m_tickledControl->UpdateEnabledChild(expectedState); } - g_unk0x100f11cc = -1; - SetPresentersEnabled(m_presentersEnabled); + g_lastTickleState = -1; + SetColorControlsEnabled(m_presentersEnabled); } } // FUNCTION: LEGO1 0x10025e40 -void LegoCarBuild::FUN_10025e40() +void LegoCarBuild::HandleEndAnim() { - SetPresentersEnabled(m_presentersEnabled); - if (m_unk0x33c && m_Yellow_Ctl != m_unk0x33c) { - m_unk0x33c->UpdateEnabledChild(0); + SetColorControlsEnabled(m_presentersEnabled); + if (m_tickledControl && m_Yellow_Ctl != m_tickledControl) { + m_tickledControl->UpdateEnabledChild(0); } } @@ -1675,7 +1681,7 @@ void LegoCarBuild::FUN_10025e40() MxBool LegoCarBuild::Escape() { BackgroundAudioManager()->Init(); - MxS32 targetEntityId = FUN_10025ee0(m_carId); + MxS32 targetEntityId = GetBuildMovieId(m_carId); InvokeAction(Extra::ActionType::e_stop, *g_jukeboxScript, targetEntityId, NULL); DeleteObjects(&m_atomId, 500, 999); @@ -1685,18 +1691,17 @@ MxBool LegoCarBuild::Escape() } // FUNCTION: LEGO1 0x10025ee0 -MxS32 LegoCarBuild::FUN_10025ee0(undefined4 p_param1) +MxS32 LegoCarBuild::GetBuildMovieId(MxS32 p_carId) { - // TODO: Work out constants - switch (p_param1) { - case 1: - return 0x2f; - case 2: - return 0x31; - case 3: - return 0x33; - case 4: - return 0x35; + switch (p_carId) { + case Helicopter_Actor: + return JukeboxScript::c_HelicopterBuild_Movie; + case DuneBugy_Actor: + return JukeboxScript::c_DuneCarBuild_Movie; + case Jetski_Actor: + return JukeboxScript::c_JetskiBuild_Movie; + case RaceCar_Actor: + return JukeboxScript::c_RaceCarBuild_Movie; default: return -1; } From e355b5590770565f740132915dc7dc6c2f3f0485 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Thu, 9 Oct 2025 22:28:38 +0200 Subject: [PATCH 4/6] Fix some library globals (#1692) Co-authored-by: jonschz --- LEGO1/library_msvc.h | 16 +++++++++++++++- LEGO1/omni/src/audio/mxsoundmanager.cpp | 2 +- LEGO1/tgl/d3drm/renderer.cpp | 7 +++++-- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index dfd217d4..5ac63a53 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -937,8 +937,22 @@ // GLOBAL: LEGO1 0x100db6e0 // GUID_SysKeyboard -// Cannot be handled right now due to anonymous pointer in struct +// GLOBAL: LEGO1 0x100dd1c0 +// IID_IDirect3DRM2 + +// Cannot be handled right now due to anonymous pointer in struct. +// We can annotate it on the original side, but we have no symbol on the recomp side. +// We would need a way of annotating "the pointer at c_dfDIKeyboard+0x14 has orig address 0x10097f80". // // GLOBAL: LEGO1 0x10098f80 // c_dfDIKeyboard + +/// Globals from libraries without symbols + +// STRING: LEGO1 0x100dabb0 +static const char* ___crtLCMapStringA_str = "\0"; + +// STRING: LEGO1 0x100dabb4 +static const wchar_t *___crtLCMapStringA_wstr = L"\0"; + #endif diff --git a/LEGO1/omni/src/audio/mxsoundmanager.cpp b/LEGO1/omni/src/audio/mxsoundmanager.cpp index 660bda0d..85e6cde3 100644 --- a/LEGO1/omni/src/audio/mxsoundmanager.cpp +++ b/LEGO1/omni/src/audio/mxsoundmanager.cpp @@ -11,7 +11,7 @@ DECOMP_SIZE_ASSERT(MxSoundManager, 0x3c); -// GLOBAL LEGO1 0x10101420 +// GLOBAL: LEGO1 0x10101420 MxS32 g_volumeAttenuation[100] = {-6643, -5643, -5058, -4643, -4321, -4058, -3836, -3643, -3473, -3321, -3184, -3058, -2943, -2836, -2736, -2643, -2556, -2473, -2395, -2321, -2251, -2184, -2120, -2058, -2000, -1943, -1888, -1836, -1785, -1736, -1689, -1643, -1599, -1556, -1514, -1473, diff --git a/LEGO1/tgl/d3drm/renderer.cpp b/LEGO1/tgl/d3drm/renderer.cpp index c295b4b3..b537589b 100644 --- a/LEGO1/tgl/d3drm/renderer.cpp +++ b/LEGO1/tgl/d3drm/renderer.cpp @@ -88,8 +88,7 @@ inline Result RendererCreateDevice( if (Succeeded(result)) { if (rCreateData.m_pBackBuffer) { - // LEGO1 0x10101040 - // GLOBAL: BETA10 0x102055f4 + // annotated below static int g_setBufferCount = 1; if (g_setBufferCount) { Result result2 = ResultVal(rpDevice->SetBufferCount(2)); @@ -101,6 +100,10 @@ inline Result RendererCreateDevice( return result; } +// GLOBAL: LEGO1 0x10101040 +// GLOBAL: BETA10 0x102055f4 +// ?g_setBufferCount@?3??RendererCreateDevice@@YA?AW4Result@Tgl@@PAUIDirect3DRM2@@ABUDeviceDirectDrawCreateData@3@AAPAUIDirect3DRMDevice2@@@Z@4HA + // FUNCTION: BETA10 0x1016cf40 inline Result RendererImpl::CreateDevice(const DeviceDirectDrawCreateData& rCreateData, DeviceImpl& rDevice) { From fe5a238ae1068b615eea0c7148e0a64f46cdeb73 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sun, 12 Oct 2025 07:36:36 +0200 Subject: [PATCH 5/6] Add SmartHeap for LEGO1 (#1694) --------- Co-authored-by: jonschz --- ISLE/library_msvc.h | 3 - LEGO1/library_msvc.h | 15 +- LEGO1/library_smartheap.h | 312 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 321 insertions(+), 9 deletions(-) create mode 100644 LEGO1/library_smartheap.h diff --git a/ISLE/library_msvc.h b/ISLE/library_msvc.h index b65591d6..46438f76 100644 --- a/ISLE/library_msvc.h +++ b/ISLE/library_msvc.h @@ -324,9 +324,6 @@ // GLOBAL: ISLE 0x411850 // __cflush -// XGLOBAL ISLE 0x4125f8 -// ?_pnhHeap@@3P6AHI@ZA - // GLOBAL: ISLE 0x412888 // ___setlc_active diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index 5ac63a53..04e9a674 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -9,12 +9,6 @@ // LIBRARY: LEGO1 0x10086260 // ??3@YAXPAX@Z -// LIBRARY: LEGO1 0x1008a090 -// _malloc - -// LIBRARY: LEGO1 0x1008a100 -// _calloc - // LIBRARY: LEGO1 0x1008a1c0 // _free @@ -940,6 +934,15 @@ // GLOBAL: LEGO1 0x100dd1c0 // IID_IDirect3DRM2 +// LIBRARY: LEGO1 0x1008c960 +// ?_query_new_handler@@YAP6AHI@ZXZ + +// LIBRARY: LEGO1 0x1008c970 +// ?_query_new_mode@@YAHXZ + +// GLOBAL: LEGO1 0x100fd8ec +// __newmode + // Cannot be handled right now due to anonymous pointer in struct. // We can annotate it on the original side, but we have no symbol on the recomp side. // We would need a way of annotating "the pointer at c_dfDIKeyboard+0x14 has orig address 0x10097f80". diff --git a/LEGO1/library_smartheap.h b/LEGO1/library_smartheap.h new file mode 100644 index 00000000..adb04276 --- /dev/null +++ b/LEGO1/library_smartheap.h @@ -0,0 +1,312 @@ +#if 0 + +// LIBRARY: LEGO1 0x100861d0 +// ?shi_New@@YAPAXKIPAU_SHI_Pool@@@Z + +// LIBRARY: LEGO1 0x10086270 +// _MemInitDefaultPool@0 + +// LIBRARY: LEGO1 0x100862e0 +// _shi_call_new_handler_msc + +// LIBRARY: LEGO1 0x10086310 +// _MemPoolShrink@4 + +// LIBRARY: LEGO1 0x10086440 +// _MemPoolPreAllocate@12 + +// LIBRARY: LEGO1 0x100865c0 +// @_shi_initPageHeaders@4 + +// LIBRARY: LEGO1 0x10086830 +// @shi_allocPageHeader@4 + +// LIBRARY: LEGO1 0x10086860 +// @shi_freePageHeader@8 + +// LIBRARY: LEGO1 0x10086a10 +// @_shi_deletePage@8 + +// LIBRARY: LEGO1 0x10086af0 +// @_shi_allocExternal@12 + +// LIBRARY: LEGO1 0x10086d10 +// @_shi_initPageVariable@8 + +// LIBRARY: LEGO1 0x10086dc0 +// _MemAllocPtr@12 + +// LIBRARY: LEGO1 0x10087020 +// @_shi_allocVar@12 + +// LIBRARY: LEGO1 0x100871b0 +// @_shi_allocBlock@12 + +// LIBRARY: LEGO1 0x10087380 +// _MemFreePtr@4 + +// LIBRARY: LEGO1 0x10087430 +// @_shi_freeVar@4 + +// LIBRARY: LEGO1 0x10087520 +// _MemReAllocPtr@12 + +// LIBRARY: LEGO1 0x10087670 +// @_shi_resizeAny@16 + +// LIBRARY: LEGO1 0x10087910 +// @_shi_resizeVar@8 + +// LIBRARY: LEGO1 0x10087ae0 +// _MemSizePtr@4 + +// LIBRARY: LEGO1 0x10087b90 +// @shi_findAllocAddress@4 + +// LIBRARY: LEGO1 0x10087bd0 +// @_shi_sysAlloc@8 + +// LIBRARY: LEGO1 0x10087c60 +// @_shi_sysFree@4 + +// LIBRARY: LEGO1 0x10087cc0 +// @_shi_sysRealloc@12 + +// LIBRARY: LEGO1 0x10087d70 +// @_shi_sysResize@12 + +// LIBRARY: LEGO1 0x10087e50 +// @_shi_sysSize@4 + +// LIBRARY: LEGO1 0x10087e90 +// @_shi_sysAllocNear@4 + +// LIBRARY: LEGO1 0x10087eb0 +// @_shi_sysFreeNear@4 + +// LIBRARY: LEGO1 0x10087ed0 +// @_shi_sysValidatePtr@12 + +// LIBRARY: LEGO1 0x10087fd0 +// @_shi_sysValidateFunction@4 + +// LIBRARY: LEGO1 0x100885c0 +// @_shi_sysAllocPool@12 + +// LIBRARY: LEGO1 0x100887e0 +// @_shi_sysResizePool@16 + +// LIBRARY: LEGO1 0x10088950 +// @_shi_sysFreePage@4 + +// LIBRARY: LEGO1 0x10088a70 +// @_shi_sysSizePage@4 + +// LIBRARY: LEGO1 0x10088aa0 +// @_shi_sysSizePool@8 + +// LIBRARY: LEGO1 0x10088ac0 +// @_shi_registerShared@16 + +// LIBRARY: LEGO1 0x10088cc0 +// @_shi_unregisterShared@8 + +// LIBRARY: LEGO1 0x10088de0 +// @_shi_getNextPool@4 + +// LIBRARY: LEGO1 0x10088df0 +// @shi_delNextPool@4 + +// LIBRARY: LEGO1 0x10088ff0 +// @shi_createAndEnterMutexShr@12 + +// LIBRARY: LEGO1 0x100890e0 +// @shi_termPoolMutexShr@4 + +// LIBRARY: LEGO1 0x10089100 +// @shi_enterPoolMutexShr@4 + +// LIBRARY: LEGO1 0x10089120 +// @shi_leavePoolMutexShr@4 + +// LIBRARY: LEGO1 0x10089140 +// __shi_enterCriticalSection@0 + +// LIBRARY: LEGO1 0x10089160 +// __shi_leaveCriticalSection@0 + +// LIBRARY: LEGO1 0x10089180 +// __shi_createAndEnterMutex + +// LIBRARY: LEGO1 0x100891b0 +// _shi_enterPoolMutexSafely + +// LIBRARY: LEGO1 0x10089290 +// _shi_enterPoolInitMutexReader + +// LIBRARY: LEGO1 0x10089320 +// _shi_leavePoolInitMutexReader + +// LIBRARY: LEGO1 0x10089350 +// _shi_enterPoolInitMutexWriter + +// LIBRARY: LEGO1 0x10089420 +// _shi_leavePoolInitMutexWriter + +// LIBRARY: LEGO1 0x10089440 +// _shi_isNT + +// LIBRARY: LEGO1 0x10089470 +// _MemPoolInit@4 + +// LIBRARY: LEGO1 0x100897e0 +// _MemPoolSetPageSize@8 + +// LIBRARY: LEGO1 0x100898f0 +// _MemPoolSetBlockSizeFS@8 + +// LIBRARY: LEGO1 0x100899d0 +// @_shi_poolFree@8 + +// LIBRARY: LEGO1 0x10089b80 +// @_shi_invokeErrorHandler1@8 + +// LIBRARY: LEGO1 0x10089ea0 +// _MemErrorUnwind@0 + +// LIBRARY: LEGO1 0x10089ef0 +// _MemDefaultErrorHandler@4 + +// LIBRARY: LEGO1 0x10089f70 +// @_shi_taskRemovePool@4 + +// LIBRARY: LEGO1 0x1008a010 +// @_shi_getCurrentThreadContext@8 + +// LIBRARY: LEGO1 0x1008a070 +// @_shi_deleteThreadContext@8 + +// LIBRARY: LEGO1 0x1008a090 +// _malloc + +// LIBRARY: LEGO1 0x1008a100 +// _calloc + +// LIBRARY: LEGO1 0x1008a160 +// _realloc + +// LIBRARY: LEGO1 0x1008a1d0 +// __expand + +// LIBRARY: LEGO1 0x1008a210 +// __heapadd + +// LIBRARY: LEGO1 0x1008a220 +// __heapwalk + +// LIBRARY: LEGO1 0x1008a2b0 +// __heapused + +// LIBRARY: LEGO1 0x1008a2e0 +// __heapmin + +// LIBRARY: LEGO1 0x1008a300 +// __msize + +// LIBRARY: LEGO1 0x1008a310 +// __heapchk + +// LIBRARY: LEGO1 0x1008a340 +// __heapset + +// LIBRARY: LEGO1 0x1008a350 +// @_shi_sysReportError@16 + +// LIBRARY: LEGO1 0x1008a3d0 +// _MemPoolSize@4 + +// LIBRARY: LEGO1 0x1008a460 +// _MemPoolWalk@8 + +// LIBRARY: LEGO1 0x1008a500 +// @_shi_walkPool@16 + +// LIBRARY: LEGO1 0x1008a800 +// @shi_isBlockInUseSmall@8 + +// LIBRARY: LEGO1 0x1008aac0 +// @_shi_isBlockInUseFS@12 + +// LIBRARY: LEGO1 0x1008ab40 +// _MemPoolCheck@4 + +// LIBRARY: LEGO1 0x1008ade0 +// _MemCheckPtr@8 + +// GLOBAL: LEGO1 0x100da970 +// _szLibName + +// GLOBAL: LEGO1 0x100fc528 +// ?_new_handler@@3P6AXXZA + +// GLOBAL: LEGO1 0x100fc530 +// _MemDefaultPool + +// GLOBAL: LEGO1 0x100fc54c +// __shi_compactPoolFn + +// GLOBAL: LEGO1 0x100fc550 +// __shi_compactPageFn + +// GLOBAL: LEGO1 0x100fc554 +// _MemDefaultPoolFlags + +// GLOBAL: LEGO1 0x100fc55c +// __shi_mutexGlobalInit + +// GLOBAL: LEGO1 0x100fc560 +// __shi_mutexMovInit + +// GLOBAL: LEGO1 0x100fc564 +// __shi_mutexMovLockCount + +// GLOBAL: LEGO1 0x100fc568 +// _shi_initPoolReaders + +// GLOBAL: LEGO1 0x100fc56c +// _shi_eventInitPool + +// GLOBAL: LEGO1 0x100fc570 +// _shi_mutexMovShr + +// GLOBAL: LEGO1 0x100fc598 +// _shi_deferFreePools + +// GLOBAL: LEGO1 0x100fc5a8 +// __shi_poolTerminating + +// GLOBAL: LEGO1 0x100fc5ac +// _MemDefaultPoolBlockSizeFS + +// GLOBAL: LEGO1 0x100fc5b0 +// _MemDefaultPoolPageSize + +// GLOBAL: LEGO1 0x100fc5b4 +// _SmartHeap_malloc + +// GLOBAL: LEGO1 0x100fc7e0 +// __shi_TaskRecord + +// GLOBAL: LEGO1 0x10109368 +// ?_pnhHeap@@3P6AHI@ZA + +// GLOBAL: LEGO1 0x101095a0 +// __shi_mutexMov + +// GLOBAL: LEGO1 0x101095c0 +// _shi_mutexPoolSynch + +// GLOBAL: LEGO1 0x101095e0 +// __shi_mutexGlobal + +#endif From 828254cbfe5c42e2bbee261d7cdb8be460e7685f Mon Sep 17 00:00:00 2001 From: MS Date: Tue, 14 Oct 2025 19:52:09 -0400 Subject: [PATCH 6/6] Entropy CI: Use new virtualenv upon retry (#1695) --- .github/workflows/compare.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/compare.yml b/.github/workflows/compare.yml index a0cf4276..1e1c3b31 100644 --- a/.github/workflows/compare.yml +++ b/.github/workflows/compare.yml @@ -38,7 +38,7 @@ jobs: - name: Cache venv uses: actions/cache@v4 with: - key: venv-entropy-${{ github.run_id }} + key: venv-entropy-${{ github.run_id }}-${{ github.run_attempt }} path: .venv - name: Install python packages @@ -97,7 +97,7 @@ jobs: - name: Restore cached virtualenv uses: actions/cache@v4 with: - key: venv-entropy-${{ github.run_id }} + key: venv-entropy-${{ github.run_id }}-${{ github.run_attempt }} path: .venv - name: Prepare builds @@ -166,7 +166,7 @@ jobs: - name: Restore cached virtualenv uses: actions/cache@v4 with: - key: venv-entropy-${{ github.run_id }} + key: venv-entropy-${{ github.run_id }}-${{ github.run_attempt }} path: .venv - name: Aggregate Accuracy