From 2c10c8e34434dadcc24bfbbbf27647174d450386 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sat, 9 Nov 2024 14:54:17 -0700 Subject: [PATCH 01/13] Implement/match Doors::VTable0x70 and Doors::ParseAction (#1137) * Implement/match Doors::VTable0x70 and Doors::ParseAction * Fix --- LEGO1/lego/legoomni/include/doors.h | 21 +++--- LEGO1/lego/legoomni/src/actors/doors.cpp | 95 ++++++++++++++++++++++-- LEGO1/lego/sources/geom/legowegedge.h | 1 + 3 files changed, 100 insertions(+), 17 deletions(-) diff --git a/LEGO1/lego/legoomni/include/doors.h b/LEGO1/lego/legoomni/include/doors.h index 83c551b0..7fb2c392 100644 --- a/LEGO1/lego/legoomni/include/doors.h +++ b/LEGO1/lego/legoomni/include/doors.h @@ -3,11 +3,13 @@ #include "legopathactor.h" +class LegoROI; + // VTABLE: LEGO1 0x100d4788 // SIZE 0x1f8 class Doors : public LegoPathActor { public: - Doors() : m_unk0x154(0), m_unk0x15c(NULL), m_unk0x160(NULL), m_unk0x1f4(0) {} + Doors() : m_unk0x154(0), m_ltDoor(NULL), m_rtDoor(NULL), m_unk0x1f4(0) {} // FUNCTION: LEGO1 0x1000e430 const char* ClassName() const override // vtable+0x0c @@ -22,21 +24,22 @@ class Doors : public LegoPathActor { return !strcmp(p_name, Doors::ClassName()) || LegoPathActor::IsA(p_name); } - void ParseAction(char*) override; // vtable+0x20 + void ParseAction(char* p_extra) override; // vtable+0x20 void VTable0x70(float p_float) override; // vtable+0x70 MxResult VTable0x94(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94 + virtual double VTable0xcc(float p_float); // vtable+0xcc // SYNTHETIC: LEGO1 0x1000e580 // Doors::`scalar deleting destructor' private: - undefined4 m_unk0x154; // 0x154 - MxFloat m_unk0x158; // 0x158 - Matrix4* m_unk0x15c; // 0x15c - Matrix4* m_unk0x160; // 0x160 - MxMatrix m_unk0x164; // 0x164 - MxMatrix m_unk0x1ac; // 0x1ac - MxFloat m_unk0x1f4; // 0x1f4 + undefined4 m_unk0x154; // 0x154 + MxFloat m_unk0x158; // 0x158 + LegoROI* m_ltDoor; // 0x15c + LegoROI* m_rtDoor; // 0x160 + MxMatrix m_ltDoorLocal; // 0x164 + MxMatrix m_rtDoorLocal; // 0x1ac + MxFloat m_unk0x1f4; // 0x1f4 }; #endif // DOORS_H diff --git a/LEGO1/lego/legoomni/src/actors/doors.cpp b/LEGO1/lego/legoomni/src/actors/doors.cpp index 2ac676b3..f2eb68ee 100644 --- a/LEGO1/lego/legoomni/src/actors/doors.cpp +++ b/LEGO1/lego/legoomni/src/actors/doors.cpp @@ -1,31 +1,110 @@ #include "doors.h" +#include "legopathboundary.h" #include "mxmisc.h" #include "mxtimer.h" +#include "roi/legoroi.h" + +#include DECOMP_SIZE_ASSERT(Doors, 0x1f8) // FUNCTION: LEGO1 0x10066100 +// FUNCTION: BETA10 0x10026850 MxResult Doors::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) { + assert(m_ltDoor && m_rtDoor); + if (m_unk0x154 == 1) { m_unk0x154 = 2; m_unk0x158 = Timer()->GetTime(); - m_unk0x164 = m_unk0x15c[2]; - m_unk0x1ac = m_unk0x160[2]; + m_ltDoorLocal = m_ltDoor->GetLocal2World(); + m_rtDoorLocal = m_rtDoor->GetLocal2World(); } return m_unk0x1f4 < 0.001 ? SUCCESS : FAILURE; } -// STUB: LEGO1 0x10066250 -void Doors::VTable0x70(float p_float) +// STUB: LEGO1 0x10066190 +// FUNCTION: BETA10 0x1002696b +double Doors::VTable0xcc(float p_float) { - // TODO + return 0.0; } -// STUB: LEGO1 0x100664e0 -void Doors::ParseAction(char*) +// FUNCTION: LEGO1 0x10066250 +// FUNCTION: BETA10 0x10026a45 +void Doors::VTable0x70(float p_float) { - // TODO + assert(m_ltDoor && m_rtDoor); + + // TODO: Match + m_roi->SetVisibility(m_boundary->GetFlag0x10()); + + switch (m_unk0x154) { + case 0: + m_unk0x154 = 1; + m_state = 0; + break; + case 1: + break; + case 2: + float local8 = VTable0xcc(p_float); + + if (local8 > 0.0f) { + MxMatrix local58(m_ltDoorLocal); + Vector3 local10(local58[3]); + + local10.Clear(); + local58.RotateY(-local8); + local10 = m_ltDoorLocal[3]; + m_ltDoor->FUN_100a58f0(local58); + m_ltDoor->VTable0x14(); + + local58 = m_rtDoorLocal; + local10.Clear(); + local58.RotateY(local8); + local10 = m_rtDoorLocal[3]; + m_rtDoor->FUN_100a58f0(local58); + m_rtDoor->VTable0x14(); + + m_unk0x1f4 = local8; + } + + if (m_unk0x158 + 6000.0f < p_float) { + m_ltDoor->FUN_100a58f0(m_ltDoorLocal); + m_rtDoor->FUN_100a58f0(m_rtDoorLocal); + m_ltDoor->VTable0x14(); + m_rtDoor->VTable0x14(); + m_unk0x154 = 1; + m_state = 0; + m_unk0x1f4 = 0; + } + } +} + +// FUNCTION: LEGO1 0x100664e0 +// FUNCTION: BETA10 0x10026ceb +void Doors::ParseAction(char* p_extra) +{ + LegoPathActor::ParseAction(p_extra); + + assert(m_ltDoor == NULL && m_rtDoor == NULL); + assert(m_roi); + assert(!strncmp(m_roi->GetName(), "rcdor", 5)); + + const CompoundObject* comp = m_roi->GetComp(); + + for (CompoundObject::const_iterator it = comp->begin(); it != comp->end(); it++) { + LegoROI* roi = (LegoROI*) *it; + + if (roi && (!strnicmp(roi->GetName(), "dor-lt", 6) || !strnicmp(roi->GetName(), "dor-sl", 6))) { + m_ltDoor = roi; + } + else if (roi && (!strnicmp(roi->GetName(), "dor-rt", 6) || !strnicmp(roi->GetName(), "dor-sr", 6))) { + m_rtDoor = roi; + } + } + + assert(m_ltDoor && m_rtDoor); } diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index 1adbac27..98a41433 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -40,6 +40,7 @@ class LegoWEGEdge : public LegoWEEdge { LegoResult VTable0x04() override; // vtable+0x04 + // FUNCTION: BETA10 0x100270c0 LegoU32 GetFlag0x10() { return m_flags & c_bit5 ? FALSE : TRUE; } // FUNCTION: BETA10 0x1001ff80 From 0b94b4803b96a9542bd4ffb706e609344dbc9726 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 10 Nov 2024 08:43:07 -0700 Subject: [PATCH 02/13] Implement/match Act2GenActor::VTable0x94 (#1138) --- LEGO1/lego/legoomni/include/act2genactor.h | 5 +++- .../lego/legoomni/src/actors/act2genactor.cpp | 28 +++++++++++++++++-- 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/LEGO1/lego/legoomni/include/act2genactor.h b/LEGO1/lego/legoomni/include/act2genactor.h index 93cc05da..1831870e 100644 --- a/LEGO1/lego/legoomni/include/act2genactor.h +++ b/LEGO1/lego/legoomni/include/act2genactor.h @@ -6,10 +6,13 @@ // VTABLE: LEGO1 0x100d4ed8 // SIZE 0x154 class Act2GenActor : public LegoPathActor { - MxResult VTable0x94(LegoPathActor*, MxBool) override; // vtable+0x94 + MxResult VTable0x94(LegoPathActor* p_actor, MxBool) override; // vtable+0x94 // SYNTHETIC: LEGO1 0x1000f5a0 // Act2GenActor::`scalar deleting destructor' + +private: + static MxLong g_lastHitActorTime; }; #endif // ACT2GENACTOR_H diff --git a/LEGO1/lego/legoomni/src/actors/act2genactor.cpp b/LEGO1/lego/legoomni/src/actors/act2genactor.cpp index d7ade7b1..fa66335e 100644 --- a/LEGO1/lego/legoomni/src/actors/act2genactor.cpp +++ b/LEGO1/lego/legoomni/src/actors/act2genactor.cpp @@ -1,10 +1,32 @@ #include "act2genactor.h" +#include "legocachesoundmanager.h" +#include "legosoundmanager.h" +#include "misc.h" +#include "mxmisc.h" +#include "mxtimer.h" +#include "roi/legoroi.h" + DECOMP_SIZE_ASSERT(Act2GenActor, 0x154) -// STUB: LEGO1 0x10018740 -MxResult Act2GenActor::VTable0x94(LegoPathActor*, MxBool) +// GLOBAL: LEGO1 0x100f0f18 +MxLong Act2GenActor::g_lastHitActorTime = 0; + +// FUNCTION: LEGO1 0x10018740 +// FUNCTION: BETA10 0x1000c7a0 +MxResult Act2GenActor::VTable0x94(LegoPathActor* p_actor, MxBool) { - // TODO + MxLong time = Timer()->GetTime(); + MxLong diff = time - g_lastHitActorTime; + + if (strcmp(p_actor->GetROI()->GetName(), "pepper")) { + return SUCCESS; + } + + g_lastHitActorTime = time; + if (diff > 1000) { + SoundManager()->GetCacheSoundManager()->Play("hitactor", NULL, FALSE); + } + return SUCCESS; } From 40159b43c79dbbc09bc93f1518a40d6c2b699890 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 10 Nov 2024 09:07:48 -0700 Subject: [PATCH 03/13] Implement/match HistoryBook::~HistoryBook (#1139) --- LEGO1/lego/legoomni/include/legogamestate.h | 3 +++ .../lego/legoomni/src/worlds/historybook.cpp | 27 +++++++++++++++++-- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legogamestate.h b/LEGO1/lego/legoomni/include/legogamestate.h index dc26f8c3..d17e8e2c 100644 --- a/LEGO1/lego/legoomni/include/legogamestate.h +++ b/LEGO1/lego/legoomni/include/legogamestate.h @@ -131,6 +131,9 @@ class LegoGameState { void WriteScoreHistory(); void FUN_1003ccf0(LegoFile&); + // FUNCTION: BETA10 0x1002c2b0 + MxS16 GetCount() { return m_count; } + ScoreItem* GetScore(MxS16 p_index) { return p_index >= m_count ? NULL : &m_scores[p_index]; } MxS16 m_count; // 0x00 diff --git a/LEGO1/lego/legoomni/src/worlds/historybook.cpp b/LEGO1/lego/legoomni/src/worlds/historybook.cpp index bec6764f..e9ca3b4d 100644 --- a/LEGO1/lego/legoomni/src/worlds/historybook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/historybook.cpp @@ -21,10 +21,33 @@ HistoryBook::HistoryBook() NotificationManager()->Register(this); } -// STUB: LEGO1 0x100824d0 +// FUNCTION: LEGO1 0x100824d0 +// FUNCTION: BETA10 0x1002b63e HistoryBook::~HistoryBook() { - // TODO + for (MxS16 scoreIndex = 0; scoreIndex < GameState()->m_history.GetCount(); scoreIndex++) { + if (m_scores[scoreIndex]) { + delete m_scores[scoreIndex]->GetAction(); + delete m_scores[scoreIndex]; + m_scores[scoreIndex] = NULL; + } + + for (MxS16 letterIndex = 0; letterIndex < (MxS16) sizeOfArray(m_names[0]); letterIndex++) { + if (m_names[scoreIndex][letterIndex]) { + delete m_names[scoreIndex][letterIndex]->GetAction(); + delete m_names[scoreIndex][letterIndex]; + m_names[scoreIndex][letterIndex] = NULL; + } + } + } + + InputManager()->UnRegister(this); + if (InputManager()->GetWorld() == this) { + InputManager()->ClearWorld(); + } + + ControlManager()->Unregister(this); + NotificationManager()->Unregister(this); } // FUNCTION: LEGO1 0x10082610 From 86a8bad545ccbad24f704f3627951d6e467d5ea5 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 10 Nov 2024 09:18:36 -0700 Subject: [PATCH 04/13] Implement/match RegistrationBook::FUN_100778c0 (#1140) --- .../legoomni/src/worlds/registrationbook.cpp | 53 ++++++++++++++++++- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index fe4ac424..cbc8858d 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -13,6 +13,7 @@ #include "legogamestate.h" #include "legoinputmanager.h" #include "legopathstruct.h" +#include "legoutils.h" #include "misc.h" #include "mxactionnotificationparam.h" #include "mxbackgroundaudiomanager.h" @@ -330,10 +331,58 @@ void RegistrationBook::WriteInfocenterLetters(MxS16 p_user) } } -// STUB: LEGO1 0x100778c0 +// FUNCTION: LEGO1 0x100778c0 void RegistrationBook::FUN_100778c0() { - // TODO + if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { + Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); + + if (strcmp(act1state->m_helicopterPlane.GetName()->GetData(), "") != 0) { + InvokeAction(Extra::e_start, m_atomId, CopterScript::c_Helicopter_Actor, NULL); + NotificationManager()->Send( + this, + LegoPathStructNotificationParam(c_notificationPathStruct, NULL, 0, CopterScript::c_Helicopter_Actor) + ); + + m_unk0x2b8++; + } + + if (strcmp(act1state->m_jetskiPlane.GetName()->GetData(), "") != 0) { + InvokeAction(Extra::e_start, m_atomId, JetskiScript::c_Jetski_Actor, NULL); + NotificationManager()->Send( + this, + LegoPathStructNotificationParam(c_notificationPathStruct, NULL, 0, JetskiScript::c_Jetski_Actor) + ); + + m_unk0x2b8++; + } + + if (strcmp(act1state->m_dunebuggyPlane.GetName()->GetData(), "") != 0) { + InvokeAction(Extra::e_start, m_atomId, DunecarScript::c_DuneBugy_Actor, NULL); + NotificationManager()->Send( + this, + LegoPathStructNotificationParam(c_notificationPathStruct, NULL, 0, DunecarScript::c_DuneBugy_Actor) + ); + + m_unk0x2b8++; + } + + if (strcmp(act1state->m_racecarPlane.GetName()->GetData(), "") != 0) { + InvokeAction(Extra::e_start, m_atomId, RacecarScript::c_RaceCar_Actor, NULL); + NotificationManager()->Send( + this, + LegoPathStructNotificationParam(c_notificationPathStruct, NULL, 0, RacecarScript::c_RaceCar_Actor) + ); + + m_unk0x2b8++; + } + + if (m_unk0x2b8 != 0) { + DeleteObjects(&m_atomId, RegbookScript::c_iic006in_RunAnim, RegbookScript::c_iic008in_PlayWav); + InputManager()->DisableInputProcessing(); + SetAppCursor(e_cursorBusy); + } + } } // FUNCTION: LEGO1 0x10077cc0 From 6885abdc7859075526c37535ff74b8860f384e51 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 10 Nov 2024 09:35:44 -0700 Subject: [PATCH 05/13] Implement/match LegoROI::FUN_100a9dd0 (#1141) * Implement/match LegoROI::FUN_100a9dd0 * Implement/match LegoROI::FUN_100a9cf0 --- LEGO1/lego/sources/roi/legolod.cpp | 7 +++++++ LEGO1/lego/sources/roi/legolod.h | 1 + LEGO1/lego/sources/roi/legoroi.cpp | 27 +++++++++++++++++++++------ LEGO1/lego/sources/roi/legoroi.h | 1 + 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/LEGO1/lego/sources/roi/legolod.cpp b/LEGO1/lego/sources/roi/legolod.cpp index c325c670..45f0f864 100644 --- a/LEGO1/lego/sources/roi/legolod.cpp +++ b/LEGO1/lego/sources/roi/legolod.cpp @@ -388,6 +388,13 @@ LegoBool LegoLOD::FUN_100aae20(const LegoChar* p_name) return FALSE; } +// FUNCTION: LEGO1 0x100aae60 +// FUNCTION: BETA10 0x1018e50f +void LegoLOD::FUN_100aae60() +{ + m_unk0x1c = 0; +} + inline BOOL GetMeshData(IDirect3DRMMesh*& mesh, D3DRMGROUPINDEX& index, Tgl::Mesh* pMesh) { mesh = ((TglImpl::MeshImpl*) pMesh)->ImplementationData()->groupMesh; diff --git a/LEGO1/lego/sources/roi/legolod.h b/LEGO1/lego/sources/roi/legolod.h index a47a3d24..0d50e675 100644 --- a/LEGO1/lego/sources/roi/legolod.h +++ b/LEGO1/lego/sources/roi/legolod.h @@ -32,6 +32,7 @@ class LegoLOD : public ViewLOD { LegoResult FUN_100aacb0(LegoFloat p_red, LegoFloat p_green, LegoFloat p_blue, LegoFloat p_alpha); LegoResult FUN_100aad00(LegoTextureInfo* p_textureInfo); LegoResult FUN_100aad70(LegoTextureInfo* p_textureInfo); + void FUN_100aae60(); LegoResult GetTexture(LegoTextureInfo*& p_textureInfo); static LegoBool FUN_100aae20(const LegoChar* p_name); diff --git a/LEGO1/lego/sources/roi/legoroi.cpp b/LEGO1/lego/sources/roi/legoroi.cpp index 87b8a3a0..c9e0d21a 100644 --- a/LEGO1/lego/sources/roi/legoroi.cpp +++ b/LEGO1/lego/sources/roi/legoroi.cpp @@ -53,6 +53,9 @@ const char* g_unk0x10101390[] = {"rcuser", "jsuser", "dunebugy", "chtrblad", "ch // GLOBAL: LEGO1 0x101013ac ROIHandler g_unk0x101013ac = NULL; +// GLOBAL: LEGO1 0x101013b0 +TextureHandler g_unk0x101013b0 = NULL; + // FUNCTION: LEGO1 0x100a81b0 void LegoROI::FUN_100a81b0(const LegoChar* p_error, const LegoChar* p_name) { @@ -757,7 +760,7 @@ LegoBool LegoROI::FUN_100a9bf0(const LegoChar* p_param, float& p_red, float& p_g if (g_unk0x101013ac) { char buf[32]; - if (g_unk0x101013ac(p_param, buf, 32)) { + if (g_unk0x101013ac(p_param, buf, sizeof(buf))) { p_param = buf; } } @@ -782,10 +785,18 @@ LegoBool LegoROI::ColorAliasLookup(const LegoChar* p_param, float& p_red, float& return FALSE; } -// STUB: LEGO1 0x100a9cf0 +// FUNCTION: LEGO1 0x100a9cf0 LegoBool LegoROI::FUN_100a9cf0(const LegoChar* p_param, unsigned char* paletteEntries, LegoU32 p_numEntries) { - // TODO + if (p_param == NULL) { + return FALSE; + } + + if (g_unk0x101013b0 != NULL) { + return g_unk0x101013b0(p_param, paletteEntries, p_numEntries); + } + + paletteEntries[0] = '\0'; return FALSE; } @@ -812,11 +823,15 @@ void LegoROI::SetName(const LegoChar* p_name) } } -// STUB: LEGO1 0x100a9dd0 -// STUB: BETA10 0x1018bfdb +// FUNCTION: LEGO1 0x100a9dd0 +// FUNCTION: BETA10 0x1018bfdb void LegoROI::FUN_100a9dd0() { - // TODO + int lodCount = GetLODCount(); + for (LegoS32 i = 0; i < lodCount; i++) { + LegoLOD* lod = (LegoLOD*) GetLOD(i); + lod->FUN_100aae60(); + } } // FUNCTION: LEGO1 0x100a9e10 diff --git a/LEGO1/lego/sources/roi/legoroi.h b/LEGO1/lego/sources/roi/legoroi.h index 541cfac5..82fe10af 100644 --- a/LEGO1/lego/sources/roi/legoroi.h +++ b/LEGO1/lego/sources/roi/legoroi.h @@ -5,6 +5,7 @@ #include "viewmanager/viewroi.h" typedef unsigned char (*ROIHandler)(const char*, char*, unsigned int); +typedef unsigned char (*TextureHandler)(const char*, unsigned char*, unsigned int); class LegoEntity; class LegoTextureContainer; From 5d3d66965d5bec48b631fe3f671a2988b8425851 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 10 Nov 2024 13:26:48 -0700 Subject: [PATCH 06/13] Implement/match Act1State::PlaceActors and related (#1142) * Implement/match Act1State::PlaceActors and related * Fix naming --- LEGO1/lego/legoomni/include/isle.h | 14 +- LEGO1/lego/legoomni/include/islepathactor.h | 2 + LEGO1/lego/legoomni/include/legonamedplane.h | 5 +- .../lego/legoomni/include/legonamedtexture.h | 2 +- LEGO1/lego/legoomni/include/legopathactor.h | 1 + LEGO1/lego/legoomni/include/legoutils.h | 3 +- LEGO1/lego/legoomni/src/common/legoutils.cpp | 18 +- .../lego/legoomni/src/paths/legopathactor.cpp | 10 ++ LEGO1/lego/legoomni/src/worlds/isle.cpp | 170 +++++++++++++++++- 9 files changed, 207 insertions(+), 18 deletions(-) diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index b470bae5..d20b0579 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -54,7 +54,7 @@ class Act1State : public LegoState { void PlayCptClickDialogue(); void StopCptClickDialogue(); void RemoveActors(); - void FUN_10034d00(); + void PlaceActors(); MxU32 GetUnknown18() { return m_unk0x018; } ElevatorFloor GetElevatorFloor() { return (ElevatorFloor) m_elevFloor; } @@ -129,18 +129,18 @@ class Isle : public LegoWorld { } MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void ReadyWorld() override; // vtable+50 - void Add(MxCore* p_object) override; // vtable+58 + void ReadyWorld() override; // vtable+0x50 + void Add(MxCore* p_object) override; // vtable+0x58 // FUNCTION: LEGO1 0x10030900 - MxBool VTable0x5c() override { return TRUE; } // vtable+5c + MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c // FUNCTION: LEGO1 0x10033170 void VTable0x60() override {} // vtable+60 - MxBool Escape() override; // vtable+64 - void Enable(MxBool p_enable) override; // vtable+68 - virtual void VTable0x6c(LegoPathActor* p_actor); // vtable+6c + MxBool Escape() override; // vtable+0x64 + void Enable(MxBool p_enable) override; // vtable+0x68 + virtual void VTable0x6c(LegoPathActor* p_actor); // vtable+0x6c void SetDestLocation(LegoGameState::Area p_destLocation) { m_destLocation = p_destLocation; } MxBool HasHelicopter() { return m_helicopter != NULL; } diff --git a/LEGO1/lego/legoomni/include/islepathactor.h b/LEGO1/lego/legoomni/include/islepathactor.h index 3a74e42c..f332ccc9 100644 --- a/LEGO1/lego/legoomni/include/islepathactor.h +++ b/LEGO1/lego/legoomni/include/islepathactor.h @@ -137,6 +137,8 @@ class IslePathActor : public LegoPathActor { SetState(0); } + void SetWorld(LegoWorld* p_world) { m_world = p_world; } + static void RegisterSpawnLocations(); protected: diff --git a/LEGO1/lego/legoomni/include/legonamedplane.h b/LEGO1/lego/legoomni/include/legonamedplane.h index a97cd8fb..6403d583 100644 --- a/LEGO1/lego/legoomni/include/legonamedplane.h +++ b/LEGO1/lego/legoomni/include/legonamedplane.h @@ -14,9 +14,12 @@ class LegoNamedPlane { // FUNCTION: LEGO1 0x10033a70 // LegoNamedPlane::~LegoNamedPlane - void SetName(const char* p_name) { m_name = p_name; } const MxString* GetName() const { return &m_name; } + const Mx3DPointFloat& GetPosition() { return m_position; } + const Mx3DPointFloat& GetDirection() { return m_direction; } + const Mx3DPointFloat& GetUp() { return m_up; } + void SetName(const char* p_name) { m_name = p_name; } void SetPosition(const Mx3DPointFloat& p_position) { m_position = p_position; } void SetDirection(const Mx3DPointFloat& p_direction) { m_direction = p_direction; } void SetUp(const Mx3DPointFloat& p_up) { m_up = p_up; } diff --git a/LEGO1/lego/legoomni/include/legonamedtexture.h b/LEGO1/lego/legoomni/include/legonamedtexture.h index 66b9663e..330ce775 100644 --- a/LEGO1/lego/legoomni/include/legonamedtexture.h +++ b/LEGO1/lego/legoomni/include/legonamedtexture.h @@ -21,7 +21,7 @@ class LegoNamedTexture { private: MxString m_name; // 0x00 - LegoTexture* m_texture; // 0x04 + LegoTexture* m_texture; // 0x10 }; #endif // LEGONAMEDTEXTURE_H diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index c845c897..c4d5cd8d 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -142,6 +142,7 @@ class LegoPathActor : public LegoActor { void SetController(LegoPathController* p_controller) { m_controller = p_controller; } void UpdatePlane(LegoNamedPlane& p_namedPlane); + void PlaceActor(LegoNamedPlane& p_namedPlane); // SYNTHETIC: LEGO1 0x1002d800 // LegoPathActor::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h index 8c4b44fe..604e860c 100644 --- a/LEGO1/lego/legoomni/include/legoutils.h +++ b/LEGO1/lego/legoomni/include/legoutils.h @@ -63,7 +63,8 @@ MxS32 UpdateLightPosition(MxS32 p_increase); void SetLightPosition(MxS32 p_index); LegoNamedTexture* ReadNamedTexture(LegoFile* p_file); void FUN_1003f540(LegoFile* p_file, const char* p_filename); -void WriteNamedTexture(LegoFile* p_file, LegoNamedTexture* p_texture); +void WriteNamedTexture(LegoFile* p_file, LegoNamedTexture* p_namedTexture); +void FUN_1003f930(LegoNamedTexture* p_namedTexture); // FUNCTION: BETA10 0x100260a0 inline void StartIsleAction(IsleScript::Script p_objectId) diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index e3c7dbef..d38ff896 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -17,6 +17,8 @@ #include "legoworld.h" #include "legoworldlist.h" #include "misc.h" +#include "misc/legocontainer.h" +#include "misc/legoimage.h" #include "misc/legotree.h" #include "mxdsaction.h" #include "mxmisc.h" @@ -664,8 +666,18 @@ void FUN_1003f540(LegoFile* p_file, const char* p_filename) } // FUNCTION: LEGO1 0x1003f8a0 -void WriteNamedTexture(LegoFile* p_file, LegoNamedTexture* p_texture) +void WriteNamedTexture(LegoFile* p_file, LegoNamedTexture* p_namedTexture) { - p_file->WriteString(*p_texture->GetName()); - p_texture->GetTexture()->Write(p_file); + p_file->WriteString(*p_namedTexture->GetName()); + p_namedTexture->GetTexture()->Write(p_file); +} + +// FUNCTION: LEGO1 0x1003f930 +void FUN_1003f930(LegoNamedTexture* p_namedTexture) +{ + LegoTextureInfo* textureInfo = TextureContainer()->Get(p_namedTexture->GetName()->GetData()); + + if (textureInfo != NULL) { + textureInfo->FUN_10066010(p_namedTexture->GetTexture()->GetImage()->GetBits()); + } } diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 0479e05d..7ecaa431 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -728,3 +728,13 @@ void LegoPathActor::UpdatePlane(LegoNamedPlane& p_namedPlane) p_namedPlane.SetDirection(GetWorldDirection()); p_namedPlane.SetUp(GetWorldUp()); } + +// FUNCTION: LEGO1 0x1002f830 +void LegoPathActor::PlaceActor(LegoNamedPlane& p_namedPlane) +{ + if (strcmp(p_namedPlane.GetName()->GetData(), "") != 0) { + LegoWorld* world = CurrentWorld(); + world->PlaceActor(this, p_namedPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + SetLocation(p_namedPlane.GetPosition(), p_namedPlane.GetDirection(), p_namedPlane.GetUp(), TRUE); + } +} diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index c715dd34..00f54aed 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -37,6 +37,7 @@ #include "scripts.h" #include "skateboard.h" #include "towtrack.h" +#include "viewmanager/viewmanager.h" DECOMP_SIZE_ASSERT(Act1State, 0x26c) DECOMP_SIZE_ASSERT(LegoNamedPlane, 0x4c) @@ -279,7 +280,7 @@ void Isle::ReadyWorld() else if (GameState()->GetLoadedAct() != LegoGameState::e_act1) { EnableAnimations(TRUE); FUN_10032620(); - m_act1state->FUN_10034d00(); + m_act1state->PlaceActors(); FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); } } @@ -541,7 +542,7 @@ void Isle::Enable(MxBool p_enable) CreateState(); VideoManager()->ResetPalette(FALSE); - m_act1state->FUN_10034d00(); + m_act1state->PlaceActors(); if (UserActor() != NULL && UserActor()->GetActorId() != LegoActor::c_none) { // TODO: Match, most likely an inline function @@ -1599,8 +1600,167 @@ void Act1State::RemoveActors() } } -// STUB: LEGO1 0x10034d00 -void Act1State::FUN_10034d00() +// FUNCTION: LEGO1 0x10034d00 +void Act1State::PlaceActors() { - // TODO + Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle); + + if (strcmp(m_motocyclePlane.GetName()->GetData(), "") != 0) { + isle->m_motocycle->PlaceActor(m_motocyclePlane); + } + else { + isle->PlaceActor(isle->m_motocycle, "INT43", 4, 0.5f, 1, 0.5f); + } + + if (strcmp(m_bikePlane.GetName()->GetData(), "") != 0) { + isle->m_bike->PlaceActor(m_bikePlane); + } + else { + isle->PlaceActor(isle->m_bike, "INT44", 2, 0.5f, 0, 0.5f); + } + + if (strcmp(m_skateboardPlane.GetName()->GetData(), "") != 0) { + isle->m_skateboard->PlaceActor(m_skateboardPlane); + } + else { + isle->PlaceActor(isle->m_skateboard, "EDG02_84", 4, 0.5f, 0, 0.5f); + } + + if (m_helicopter != NULL) { + if (!strcmp(m_helicopterPlane.GetName()->GetData(), "")) { + m_helicopter->SpawnPlayer(LegoGameState::e_unk40, FALSE, 0); + } + else { + isle->PlaceActor(m_helicopter, m_helicopterPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + m_helicopter->SetLocation( + m_helicopterPlane.GetPosition(), + m_helicopterPlane.GetDirection(), + m_helicopterPlane.GetUp(), + TRUE + ); + isle->Add(m_helicopter); + m_helicopter->SetWorld(isle); + } + + GetViewManager()->Add(m_helicopter->GetROI()); + m_helicopter->GetROI()->SetVisibility(TRUE); + m_helicopterPlane.SetName(""); + m_helicopter = NULL; + + if (m_unk0x154 != NULL) { + FUN_1003f930(m_unk0x154); + delete m_unk0x154; + m_unk0x154 = NULL; + } + + if (m_unk0x158 != NULL) { + FUN_1003f930(m_unk0x158); + delete m_unk0x158; + m_unk0x158 = NULL; + } + + if (m_unk0x15c != NULL) { + FUN_1003f930(m_unk0x15c); + delete m_unk0x15c; + m_unk0x15c = NULL; + } + } + + if (m_jetski != NULL) { + if (!strcmp(m_jetskiPlane.GetName()->GetData(), "")) { + m_jetski->SpawnPlayer(LegoGameState::e_unk45, FALSE, 0); + } + else { + isle->PlaceActor(m_jetski, m_jetskiPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + m_jetski + ->SetLocation(m_jetskiPlane.GetPosition(), m_jetskiPlane.GetDirection(), m_jetskiPlane.GetUp(), TRUE); + isle->Add(m_jetski); + m_jetski->SetWorld(isle); + } + + GetViewManager()->Add(m_jetski->GetROI()); + m_jetski->GetROI()->SetVisibility(TRUE); + m_jetskiPlane.SetName(""); + m_jetski = NULL; + + if (m_unk0x1b0 != NULL) { + FUN_1003f930(m_unk0x1b0); + delete m_unk0x1b0; + m_unk0x1b0 = NULL; + } + + if (m_unk0x1b4 != NULL) { + FUN_1003f930(m_unk0x1b4); + delete m_unk0x1b4; + m_unk0x1b4 = NULL; + } + } + + if (m_dunebuggy != NULL) { + if (!strcmp(m_dunebuggyPlane.GetName()->GetData(), "")) { + m_dunebuggy->SpawnPlayer(LegoGameState::e_unk43, FALSE, 0); + } + else { + isle->PlaceActor(m_dunebuggy, m_dunebuggyPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + m_dunebuggy->SetLocation( + m_dunebuggyPlane.GetPosition(), + m_dunebuggyPlane.GetDirection(), + m_dunebuggyPlane.GetUp(), + TRUE + ); + isle->Add(m_dunebuggy); + m_dunebuggy->SetWorld(isle); + } + + GetViewManager()->Add(m_dunebuggy->GetROI()); + m_dunebuggy->GetROI()->SetVisibility(TRUE); + m_dunebuggyPlane.SetName(""); + m_dunebuggy = NULL; + + if (m_unk0x208 != NULL) { + FUN_1003f930(m_unk0x208); + delete m_unk0x208; + m_unk0x208 = NULL; + } + } + + if (m_racecar != NULL) { + if (!strcmp(m_racecarPlane.GetName()->GetData(), "")) { + m_racecar->SpawnPlayer(LegoGameState::e_unk44, FALSE, 0); + } + else { + isle->PlaceActor(m_racecar, m_racecarPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + m_racecar->SetLocation( + m_racecarPlane.GetPosition(), + m_racecarPlane.GetDirection(), + m_racecarPlane.GetUp(), + TRUE + ); + isle->Add(m_racecar); + m_racecar->SetWorld(isle); + } + + GetViewManager()->Add(m_racecar->GetROI()); + m_racecar->GetROI()->SetVisibility(TRUE); + m_racecarPlane.SetName(""); + m_racecar = NULL; + + if (m_unk0x25c != NULL) { + FUN_1003f930(m_unk0x25c); + delete m_unk0x25c; + m_unk0x25c = NULL; + } + + if (m_unk0x260 != NULL) { + FUN_1003f930(m_unk0x260); + delete m_unk0x260; + m_unk0x260 = NULL; + } + + if (m_unk0x264 != NULL) { + FUN_1003f930(m_unk0x264); + delete m_unk0x264; + m_unk0x264 = NULL; + } + } } From cd261b9518a02b5dbd2242c7976d1c5fab405467 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 10 Nov 2024 14:47:12 -0700 Subject: [PATCH 07/13] Refactor/improve matches in Act1State (#1143) * Refactor/improve matches in Act1State * Fix naming --- LEGO1/lego/legoomni/include/isle.h | 18 +- LEGO1/lego/legoomni/include/legonamedplane.h | 5 +- LEGO1/lego/legoomni/include/legostate.h | 1 + .../lego/legoomni/src/build/legocarbuild.cpp | 9 +- .../lego/legoomni/src/paths/legopathactor.cpp | 4 +- LEGO1/lego/legoomni/src/worlds/isle.cpp | 330 +++++++++--------- .../legoomni/src/worlds/registrationbook.cpp | 8 +- LEGO1/lego/sources/misc/legostorage.h | 18 +- 8 files changed, 200 insertions(+), 193 deletions(-) diff --git a/LEGO1/lego/legoomni/include/isle.h b/LEGO1/lego/legoomni/include/isle.h index d20b0579..f75d3273 100644 --- a/LEGO1/lego/legoomni/include/isle.h +++ b/LEGO1/lego/legoomni/include/isle.h @@ -83,21 +83,21 @@ class Act1State : public LegoState { LegoNamedPlane m_bikePlane; // 0x070 LegoNamedPlane m_skateboardPlane; // 0x0bc LegoNamedPlane m_helicopterPlane; // 0x108 - LegoNamedTexture* m_unk0x154; // 0x154 - LegoNamedTexture* m_unk0x158; // 0x158 - LegoNamedTexture* m_unk0x15c; // 0x15c + LegoNamedTexture* m_helicopterWindshield; // 0x154 + LegoNamedTexture* m_helicopterJetLeft; // 0x158 + LegoNamedTexture* m_helicopterJetRight; // 0x15c Helicopter* m_helicopter; // 0x160 LegoNamedPlane m_jetskiPlane; // 0x164 - LegoNamedTexture* m_unk0x1b0; // 0x1b0 - LegoNamedTexture* m_unk0x1b4; // 0x1b4 + LegoNamedTexture* m_jetskiFront; // 0x1b0 + LegoNamedTexture* m_jetskiWindshield; // 0x1b4 Jetski* m_jetski; // 0x1b8 LegoNamedPlane m_dunebuggyPlane; // 0x1bc - LegoNamedTexture* m_unk0x208; // 0x208 + LegoNamedTexture* m_dunebuggyFront; // 0x208 DuneBuggy* m_dunebuggy; // 0x20c LegoNamedPlane m_racecarPlane; // 0x210 - LegoNamedTexture* m_unk0x25c; // 0x25c - LegoNamedTexture* m_unk0x260; // 0x260 - LegoNamedTexture* m_unk0x264; // 0x264 + LegoNamedTexture* m_racecarFront; // 0x25c + LegoNamedTexture* m_racecarBack; // 0x260 + LegoNamedTexture* m_racecarTail; // 0x264 RaceCar* m_racecar; // 0x268 }; diff --git a/LEGO1/lego/legoomni/include/legonamedplane.h b/LEGO1/lego/legoomni/include/legonamedplane.h index 6403d583..43f97506 100644 --- a/LEGO1/lego/legoomni/include/legonamedplane.h +++ b/LEGO1/lego/legoomni/include/legonamedplane.h @@ -14,7 +14,7 @@ class LegoNamedPlane { // FUNCTION: LEGO1 0x10033a70 // LegoNamedPlane::~LegoNamedPlane - const MxString* GetName() const { return &m_name; } + const char* GetName() const { return m_name.GetData(); } const Mx3DPointFloat& GetPosition() { return m_position; } const Mx3DPointFloat& GetDirection() { return m_direction; } const Mx3DPointFloat& GetUp() { return m_up; } @@ -24,6 +24,9 @@ class LegoNamedPlane { void SetDirection(const Mx3DPointFloat& p_direction) { m_direction = p_direction; } void SetUp(const Mx3DPointFloat& p_up) { m_up = p_up; } + MxBool IsPresent() { return strcmp(m_name.GetData(), "") != 0; } + void Reset() { m_name = ""; } + // FUNCTION: LEGO1 0x100344d0 MxResult Serialize(LegoFile* p_file) { diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index 68cf0a5b..f217573c 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -73,6 +73,7 @@ class LegoState : public MxCore { return SUCCESS; } + private: MxU32* m_objectIds; // 0x00 MxS16 m_length; // 0x04 MxS16 m_mode; // 0x06 diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 68b1495f..14a8ca77 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -1048,7 +1048,6 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) entity = (LegoEntity*) Find(m_atomId, m_carId); if (entity && entity->GetROI()) { - // This function was changed between BETA10 and LEGO1. // These lines looks like a relic from older code. LegoWorld* destWorld = NULL; @@ -1063,7 +1062,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) } gameState->m_helicopter = (Helicopter*) entity; - gameState->m_helicopterPlane.SetName(""); + gameState->m_helicopterPlane.Reset(); break; case LegoGameState::e_dunecarbuild: if (gameState->m_dunebuggy) { @@ -1071,7 +1070,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) } gameState->m_dunebuggy = (DuneBuggy*) entity; - gameState->m_dunebuggyPlane.SetName(""); + gameState->m_dunebuggyPlane.Reset(); break; case LegoGameState::e_jetskibuild: if (gameState->m_jetski) { @@ -1079,7 +1078,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) } gameState->m_jetski = (Jetski*) entity; - gameState->m_jetskiPlane.SetName(""); + gameState->m_jetskiPlane.Reset(); break; case LegoGameState::e_racecarbuild: if (gameState->m_racecar) { @@ -1087,7 +1086,7 @@ undefined4 LegoCarBuild::FUN_10024c20(LegoEventNotificationParam* p_param) } gameState->m_racecar = (RaceCar*) entity; - gameState->m_racecarPlane.SetName(""); + gameState->m_racecarPlane.Reset(); break; } diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 7ecaa431..32bcc24c 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -732,9 +732,9 @@ void LegoPathActor::UpdatePlane(LegoNamedPlane& p_namedPlane) // FUNCTION: LEGO1 0x1002f830 void LegoPathActor::PlaceActor(LegoNamedPlane& p_namedPlane) { - if (strcmp(p_namedPlane.GetName()->GetData(), "") != 0) { + if (p_namedPlane.IsPresent()) { LegoWorld* world = CurrentWorld(); - world->PlaceActor(this, p_namedPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + world->PlaceActor(this, p_namedPlane.GetName(), 0, 0.5f, 1, 0.5f); SetLocation(p_namedPlane.GetPosition(), p_namedPlane.GetDirection(), p_namedPlane.GetUp(), TRUE); } } diff --git a/LEGO1/lego/legoomni/src/worlds/isle.cpp b/LEGO1/lego/legoomni/src/worlds/isle.cpp index 00f54aed..2e76e1a3 100644 --- a/LEGO1/lego/legoomni/src/worlds/isle.cpp +++ b/LEGO1/lego/legoomni/src/worlds/isle.cpp @@ -1293,19 +1293,19 @@ Act1State::Act1State() m_planeActive = FALSE; m_currentCptClickDialogue = IsleScript::c_noneIsle; m_unk0x022 = FALSE; - m_unk0x154 = NULL; - m_unk0x158 = NULL; - m_unk0x15c = NULL; + m_helicopterWindshield = NULL; + m_helicopterJetLeft = NULL; + m_helicopterJetRight = NULL; m_helicopter = NULL; - m_unk0x1b0 = NULL; + m_jetskiFront = NULL; m_unk0x021 = 1; - m_unk0x1b4 = NULL; + m_jetskiWindshield = NULL; m_jetski = NULL; - m_unk0x208 = NULL; + m_dunebuggyFront = NULL; m_dunebuggy = NULL; - m_unk0x25c = NULL; - m_unk0x260 = NULL; - m_unk0x264 = NULL; + m_racecarFront = NULL; + m_racecarBack = NULL; + m_racecarTail = NULL; m_racecar = NULL; Reset(); } @@ -1325,124 +1325,135 @@ MxResult Act1State::Serialize(LegoFile* p_file) m_racecarPlane.Serialize(p_file); if (p_file->IsWriteMode()) { - if (m_helicopterPlane.GetName()->Compare("") != 0) { - if (m_unk0x154) { - WriteNamedTexture(p_file, m_unk0x154); + if (m_helicopterPlane.IsPresent()) { + if (m_helicopterWindshield) { + WriteNamedTexture(p_file, m_helicopterWindshield); } else { FUN_1003f540(p_file, "chwind.gif"); } - if (m_unk0x158) { - WriteNamedTexture(p_file, m_unk0x158); + + if (m_helicopterJetLeft) { + WriteNamedTexture(p_file, m_helicopterJetLeft); } else { FUN_1003f540(p_file, "chjetl.gif"); } - if (m_unk0x15c) { - WriteNamedTexture(p_file, m_unk0x15c); + + if (m_helicopterJetRight) { + WriteNamedTexture(p_file, m_helicopterJetRight); } else { FUN_1003f540(p_file, "chjetr.gif"); } } - if (m_jetskiPlane.GetName()->Compare("") != 0) { - if (m_unk0x1b0) { - WriteNamedTexture(p_file, m_unk0x1b0); + + if (m_jetskiPlane.IsPresent()) { + if (m_jetskiFront) { + WriteNamedTexture(p_file, m_jetskiFront); } else { FUN_1003f540(p_file, "jsfrnt.gif"); } - if (m_unk0x1b4) { - WriteNamedTexture(p_file, m_unk0x1b4); + + if (m_jetskiWindshield) { + WriteNamedTexture(p_file, m_jetskiWindshield); } else { FUN_1003f540(p_file, "jswnsh.gif"); } } - if (m_dunebuggyPlane.GetName()->Compare("") != 0) { - if (m_unk0x208) { - WriteNamedTexture(p_file, m_unk0x208); + + if (m_dunebuggyPlane.IsPresent()) { + if (m_dunebuggyFront) { + WriteNamedTexture(p_file, m_dunebuggyFront); } else { FUN_1003f540(p_file, "dbfrfn.gif"); } } - if (m_racecarPlane.GetName()->Compare("") != 0) { - if (m_unk0x25c) { - WriteNamedTexture(p_file, m_unk0x25c); + + if (m_racecarPlane.IsPresent()) { + if (m_racecarFront) { + WriteNamedTexture(p_file, m_racecarFront); } else { FUN_1003f540(p_file, "rcfrnt.gif"); } - if (m_unk0x260) { - WriteNamedTexture(p_file, m_unk0x260); + + if (m_racecarBack) { + WriteNamedTexture(p_file, m_racecarBack); } else { FUN_1003f540(p_file, "rcback.gif"); } - if (m_unk0x264) { - WriteNamedTexture(p_file, m_unk0x264); + + if (m_racecarTail) { + WriteNamedTexture(p_file, m_racecarTail); } else { FUN_1003f540(p_file, "rctail.gif"); } } - Write(p_file, m_cptClickDialogue.m_nextIndex); + m_cptClickDialogue.WriteToFile(p_file); Write(p_file, m_unk0x022); } else if (p_file->IsReadMode()) { - if (m_helicopterPlane.GetName()->Compare("") != 0) { - m_unk0x154 = ReadNamedTexture(p_file); - if (m_unk0x154 == NULL) { + if (m_helicopterPlane.IsPresent()) { + m_helicopterWindshield = ReadNamedTexture(p_file); + if (m_helicopterWindshield == NULL) { return FAILURE; } - m_unk0x158 = ReadNamedTexture(p_file); - if (m_unk0x158 == NULL) { + m_helicopterJetLeft = ReadNamedTexture(p_file); + if (m_helicopterJetLeft == NULL) { return FAILURE; } - m_unk0x15c = ReadNamedTexture(p_file); - if (m_unk0x15c == NULL) { - return FAILURE; - } - } - if (m_jetskiPlane.GetName()->Compare("") != 0) { - m_unk0x1b0 = ReadNamedTexture(p_file); - if (m_unk0x1b0 == NULL) { - return FAILURE; - } - - m_unk0x1b4 = ReadNamedTexture(p_file); - if (m_unk0x1b4 == NULL) { - return FAILURE; - } - } - if (m_dunebuggyPlane.GetName()->Compare("") != 0) { - m_unk0x208 = ReadNamedTexture(p_file); - if (m_unk0x208 == NULL) { - return FAILURE; - } - } - if (m_racecarPlane.GetName()->Compare("") != 0) { - m_unk0x25c = ReadNamedTexture(p_file); - if (m_unk0x25c == NULL) { - return FAILURE; - } - - m_unk0x260 = ReadNamedTexture(p_file); - if (m_unk0x260 == NULL) { - return FAILURE; - } - - m_unk0x264 = ReadNamedTexture(p_file); - if (m_unk0x264 == NULL) { + m_helicopterJetRight = ReadNamedTexture(p_file); + if (m_helicopterJetRight == NULL) { return FAILURE; } } - Read(p_file, &m_cptClickDialogue.m_nextIndex); + if (m_jetskiPlane.IsPresent()) { + m_jetskiFront = ReadNamedTexture(p_file); + if (m_jetskiFront == NULL) { + return FAILURE; + } + + m_jetskiWindshield = ReadNamedTexture(p_file); + if (m_jetskiWindshield == NULL) { + return FAILURE; + } + } + + if (m_dunebuggyPlane.IsPresent()) { + m_dunebuggyFront = ReadNamedTexture(p_file); + if (m_dunebuggyFront == NULL) { + return FAILURE; + } + } + + if (m_racecarPlane.IsPresent()) { + m_racecarFront = ReadNamedTexture(p_file); + if (m_racecarFront == NULL) { + return FAILURE; + } + + m_racecarBack = ReadNamedTexture(p_file); + if (m_racecarBack == NULL) { + return FAILURE; + } + + m_racecarTail = ReadNamedTexture(p_file); + if (m_racecarTail == NULL) { + return FAILURE; + } + } + + m_cptClickDialogue.ReadFromFile(p_file); Read(p_file, &m_unk0x022); } @@ -1474,25 +1485,25 @@ void Act1State::StopCptClickDialogue() // FUNCTION: LEGO1 0x100346d0 MxBool Act1State::Reset() { - m_motocyclePlane.SetName(""); - m_bikePlane.SetName(""); - m_skateboardPlane.SetName(""); + m_motocyclePlane.Reset(); + m_bikePlane.Reset(); + m_skateboardPlane.Reset(); m_unk0x022 = FALSE; - m_helicopterPlane.SetName(""); - if (m_unk0x154) { - delete m_unk0x154; - m_unk0x154 = NULL; + m_helicopterPlane.Reset(); + if (m_helicopterWindshield) { + delete m_helicopterWindshield; + m_helicopterWindshield = NULL; } - if (m_unk0x158) { - delete m_unk0x158; - m_unk0x158 = NULL; + if (m_helicopterJetLeft) { + delete m_helicopterJetLeft; + m_helicopterJetLeft = NULL; } - if (m_unk0x15c) { - delete m_unk0x15c; - m_unk0x15c = NULL; + if (m_helicopterJetRight) { + delete m_helicopterJetRight; + m_helicopterJetRight = NULL; } if (m_helicopter) { @@ -1500,16 +1511,15 @@ MxBool Act1State::Reset() m_helicopter = NULL; } - m_jetskiPlane.SetName(""); - - if (m_unk0x1b0) { - delete m_unk0x1b0; - m_unk0x1b0 = NULL; + m_jetskiPlane.Reset(); + if (m_jetskiFront) { + delete m_jetskiFront; + m_jetskiFront = NULL; } - if (m_unk0x1b4) { - delete m_unk0x1b4; - m_unk0x1b4 = NULL; + if (m_jetskiWindshield) { + delete m_jetskiWindshield; + m_jetskiWindshield = NULL; } if (m_jetski) { @@ -1517,11 +1527,10 @@ MxBool Act1State::Reset() m_jetski = NULL; } - m_dunebuggyPlane.SetName(""); - - if (m_unk0x208) { - delete m_unk0x208; - m_unk0x208 = NULL; + m_dunebuggyPlane.Reset(); + if (m_dunebuggyFront) { + delete m_dunebuggyFront; + m_dunebuggyFront = NULL; } if (m_dunebuggy) { @@ -1529,21 +1538,20 @@ MxBool Act1State::Reset() m_dunebuggy = NULL; } - m_racecarPlane.SetName(""); - - if (m_unk0x25c) { - delete m_unk0x25c; - m_unk0x25c = NULL; + m_racecarPlane.Reset(); + if (m_racecarFront) { + delete m_racecarFront; + m_racecarFront = NULL; } - if (m_unk0x260) { - delete m_unk0x260; - m_unk0x260 = NULL; + if (m_racecarBack) { + delete m_racecarBack; + m_racecarBack = NULL; } - if (m_unk0x264) { - delete m_unk0x264; - m_unk0x264 = NULL; + if (m_racecarTail) { + delete m_racecarTail; + m_racecarTail = NULL; } if (m_racecar) { @@ -1605,21 +1613,21 @@ void Act1State::PlaceActors() { Isle* isle = (Isle*) FindWorld(*g_isleScript, IsleScript::c__Isle); - if (strcmp(m_motocyclePlane.GetName()->GetData(), "") != 0) { + if (m_motocyclePlane.IsPresent()) { isle->m_motocycle->PlaceActor(m_motocyclePlane); } else { isle->PlaceActor(isle->m_motocycle, "INT43", 4, 0.5f, 1, 0.5f); } - if (strcmp(m_bikePlane.GetName()->GetData(), "") != 0) { + if (m_bikePlane.IsPresent()) { isle->m_bike->PlaceActor(m_bikePlane); } else { isle->PlaceActor(isle->m_bike, "INT44", 2, 0.5f, 0, 0.5f); } - if (strcmp(m_skateboardPlane.GetName()->GetData(), "") != 0) { + if (m_skateboardPlane.IsPresent()) { isle->m_skateboard->PlaceActor(m_skateboardPlane); } else { @@ -1627,11 +1635,11 @@ void Act1State::PlaceActors() } if (m_helicopter != NULL) { - if (!strcmp(m_helicopterPlane.GetName()->GetData(), "")) { + if (!m_helicopterPlane.IsPresent()) { m_helicopter->SpawnPlayer(LegoGameState::e_unk40, FALSE, 0); } else { - isle->PlaceActor(m_helicopter, m_helicopterPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + isle->PlaceActor(m_helicopter, m_helicopterPlane.GetName(), 0, 0.5f, 1, 0.5f); m_helicopter->SetLocation( m_helicopterPlane.GetPosition(), m_helicopterPlane.GetDirection(), @@ -1644,34 +1652,34 @@ void Act1State::PlaceActors() GetViewManager()->Add(m_helicopter->GetROI()); m_helicopter->GetROI()->SetVisibility(TRUE); - m_helicopterPlane.SetName(""); + m_helicopterPlane.Reset(); m_helicopter = NULL; - if (m_unk0x154 != NULL) { - FUN_1003f930(m_unk0x154); - delete m_unk0x154; - m_unk0x154 = NULL; + if (m_helicopterWindshield != NULL) { + FUN_1003f930(m_helicopterWindshield); + delete m_helicopterWindshield; + m_helicopterWindshield = NULL; } - if (m_unk0x158 != NULL) { - FUN_1003f930(m_unk0x158); - delete m_unk0x158; - m_unk0x158 = NULL; + if (m_helicopterJetLeft != NULL) { + FUN_1003f930(m_helicopterJetLeft); + delete m_helicopterJetLeft; + m_helicopterJetLeft = NULL; } - if (m_unk0x15c != NULL) { - FUN_1003f930(m_unk0x15c); - delete m_unk0x15c; - m_unk0x15c = NULL; + if (m_helicopterJetRight != NULL) { + FUN_1003f930(m_helicopterJetRight); + delete m_helicopterJetRight; + m_helicopterJetRight = NULL; } } if (m_jetski != NULL) { - if (!strcmp(m_jetskiPlane.GetName()->GetData(), "")) { + if (!m_jetskiPlane.IsPresent()) { m_jetski->SpawnPlayer(LegoGameState::e_unk45, FALSE, 0); } else { - isle->PlaceActor(m_jetski, m_jetskiPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + isle->PlaceActor(m_jetski, m_jetskiPlane.GetName(), 0, 0.5f, 1, 0.5f); m_jetski ->SetLocation(m_jetskiPlane.GetPosition(), m_jetskiPlane.GetDirection(), m_jetskiPlane.GetUp(), TRUE); isle->Add(m_jetski); @@ -1680,28 +1688,28 @@ void Act1State::PlaceActors() GetViewManager()->Add(m_jetski->GetROI()); m_jetski->GetROI()->SetVisibility(TRUE); - m_jetskiPlane.SetName(""); + m_jetskiPlane.Reset(); m_jetski = NULL; - if (m_unk0x1b0 != NULL) { - FUN_1003f930(m_unk0x1b0); - delete m_unk0x1b0; - m_unk0x1b0 = NULL; + if (m_jetskiFront != NULL) { + FUN_1003f930(m_jetskiFront); + delete m_jetskiFront; + m_jetskiFront = NULL; } - if (m_unk0x1b4 != NULL) { - FUN_1003f930(m_unk0x1b4); - delete m_unk0x1b4; - m_unk0x1b4 = NULL; + if (m_jetskiWindshield != NULL) { + FUN_1003f930(m_jetskiWindshield); + delete m_jetskiWindshield; + m_jetskiWindshield = NULL; } } if (m_dunebuggy != NULL) { - if (!strcmp(m_dunebuggyPlane.GetName()->GetData(), "")) { + if (!m_dunebuggyPlane.IsPresent()) { m_dunebuggy->SpawnPlayer(LegoGameState::e_unk43, FALSE, 0); } else { - isle->PlaceActor(m_dunebuggy, m_dunebuggyPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + isle->PlaceActor(m_dunebuggy, m_dunebuggyPlane.GetName(), 0, 0.5f, 1, 0.5f); m_dunebuggy->SetLocation( m_dunebuggyPlane.GetPosition(), m_dunebuggyPlane.GetDirection(), @@ -1714,22 +1722,22 @@ void Act1State::PlaceActors() GetViewManager()->Add(m_dunebuggy->GetROI()); m_dunebuggy->GetROI()->SetVisibility(TRUE); - m_dunebuggyPlane.SetName(""); + m_dunebuggyPlane.Reset(); m_dunebuggy = NULL; - if (m_unk0x208 != NULL) { - FUN_1003f930(m_unk0x208); - delete m_unk0x208; - m_unk0x208 = NULL; + if (m_dunebuggyFront != NULL) { + FUN_1003f930(m_dunebuggyFront); + delete m_dunebuggyFront; + m_dunebuggyFront = NULL; } } if (m_racecar != NULL) { - if (!strcmp(m_racecarPlane.GetName()->GetData(), "")) { + if (!m_racecarPlane.IsPresent()) { m_racecar->SpawnPlayer(LegoGameState::e_unk44, FALSE, 0); } else { - isle->PlaceActor(m_racecar, m_racecarPlane.GetName()->GetData(), 0, 0.5f, 1, 0.5f); + isle->PlaceActor(m_racecar, m_racecarPlane.GetName(), 0, 0.5f, 1, 0.5f); m_racecar->SetLocation( m_racecarPlane.GetPosition(), m_racecarPlane.GetDirection(), @@ -1742,25 +1750,25 @@ void Act1State::PlaceActors() GetViewManager()->Add(m_racecar->GetROI()); m_racecar->GetROI()->SetVisibility(TRUE); - m_racecarPlane.SetName(""); + m_racecarPlane.Reset(); m_racecar = NULL; - if (m_unk0x25c != NULL) { - FUN_1003f930(m_unk0x25c); - delete m_unk0x25c; - m_unk0x25c = NULL; + if (m_racecarFront != NULL) { + FUN_1003f930(m_racecarFront); + delete m_racecarFront; + m_racecarFront = NULL; } - if (m_unk0x260 != NULL) { - FUN_1003f930(m_unk0x260); - delete m_unk0x260; - m_unk0x260 = NULL; + if (m_racecarBack != NULL) { + FUN_1003f930(m_racecarBack); + delete m_racecarBack; + m_racecarBack = NULL; } - if (m_unk0x264 != NULL) { - FUN_1003f930(m_unk0x264); - delete m_unk0x264; - m_unk0x264 = NULL; + if (m_racecarTail != NULL) { + FUN_1003f930(m_racecarTail); + delete m_racecarTail; + m_racecarTail = NULL; } } } diff --git a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp index cbc8858d..a1451cb6 100644 --- a/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp +++ b/LEGO1/lego/legoomni/src/worlds/registrationbook.cpp @@ -337,7 +337,7 @@ void RegistrationBook::FUN_100778c0() if (GameState()->GetCurrentAct() == LegoGameState::e_act1) { Act1State* act1state = (Act1State*) GameState()->GetState("Act1State"); - if (strcmp(act1state->m_helicopterPlane.GetName()->GetData(), "") != 0) { + if (act1state->m_helicopterPlane.IsPresent()) { InvokeAction(Extra::e_start, m_atomId, CopterScript::c_Helicopter_Actor, NULL); NotificationManager()->Send( this, @@ -347,7 +347,7 @@ void RegistrationBook::FUN_100778c0() m_unk0x2b8++; } - if (strcmp(act1state->m_jetskiPlane.GetName()->GetData(), "") != 0) { + if (act1state->m_jetskiPlane.IsPresent()) { InvokeAction(Extra::e_start, m_atomId, JetskiScript::c_Jetski_Actor, NULL); NotificationManager()->Send( this, @@ -357,7 +357,7 @@ void RegistrationBook::FUN_100778c0() m_unk0x2b8++; } - if (strcmp(act1state->m_dunebuggyPlane.GetName()->GetData(), "") != 0) { + if (act1state->m_dunebuggyPlane.IsPresent()) { InvokeAction(Extra::e_start, m_atomId, DunecarScript::c_DuneBugy_Actor, NULL); NotificationManager()->Send( this, @@ -367,7 +367,7 @@ void RegistrationBook::FUN_100778c0() m_unk0x2b8++; } - if (strcmp(act1state->m_racecarPlane.GetName()->GetData(), "") != 0) { + if (act1state->m_racecarPlane.IsPresent()) { InvokeAction(Extra::e_start, m_atomId, RacecarScript::c_RaceCar_Actor, NULL); NotificationManager()->Send( this, diff --git a/LEGO1/lego/sources/misc/legostorage.h b/LEGO1/lego/sources/misc/legostorage.h index 5934617b..5de72303 100644 --- a/LEGO1/lego/sources/misc/legostorage.h +++ b/LEGO1/lego/sources/misc/legostorage.h @@ -91,6 +91,7 @@ class LegoFile : public LegoStorage { public: LegoFile(); ~LegoFile() override; + LegoResult Read(void* p_buffer, LegoU32 p_size) override; // vtable+0x04 LegoResult Write(const void* p_buffer, LegoU32 p_size) override; // vtable+0x08 LegoResult GetPosition(LegoU32& p_position) override; // vtable+0x0c @@ -100,23 +101,18 @@ class LegoFile : public LegoStorage { // FUNCTION: LEGO1 0x100343d0 LegoStorage* WriteVector3(Mx3DPointFloat p_vec3) { - float data = p_vec3[0]; - Write(&data, sizeof(float)); - - data = p_vec3[1]; - Write(&data, sizeof(float)); - - data = p_vec3[2]; - Write(&data, sizeof(float)); + ::Write(this, p_vec3[0]); + ::Write(this, p_vec3[1]); + ::Write(this, p_vec3[2]); return this; } // FUNCTION: LEGO1 0x10034430 LegoStorage* ReadVector3(Mx3DPointFloat& p_vec3) { - Read(&p_vec3[0], sizeof(float)); - Read(&p_vec3[1], sizeof(float)); - Read(&p_vec3[2], sizeof(float)); + ::Read(this, &p_vec3[0]); + ::Read(this, &p_vec3[1]); + ::Read(this, &p_vec3[2]); return this; } From 26f8dd1a6a66ccdb60f24feb127161b181b4a473 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sun, 10 Nov 2024 15:23:47 -0700 Subject: [PATCH 08/13] Match LegoCarBuild::Tickle (#1145) --- .../lego/legoomni/src/build/legocarbuild.cpp | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 14a8ca77..825b37e4 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -461,7 +461,7 @@ void LegoCarBuild::VTable0x80(MxFloat p_param1[2], MxFloat p_param2[2], MxFloat #define LEGOCARBUILD_TICKLE_CASE(subtract, start, end, str) \ if (start < dTime && dTime < end) { \ FUN_10025db0(str, dTime - subtract); \ - return SUCCESS; \ + break; \ } // FUNCTION: LEGO1 0x100238b0 @@ -493,91 +493,94 @@ MxResult LegoCarBuild::Tickle() DWORD time = timeGetTime(); DWORD dTime = (time - m_unk0x10c) / 100; - if (m_carId == Helicopter_Actor) { + if (m_carId == RaceCar_Actor) { switch (m_unk0x10a) { - // TODO: Work out constants - case 500: + case RacecarScript::c_irt001d1_RunAnim: LEGOCARBUILD_TICKLE_CASE(160, 160, 180, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(260, 260, 280, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(330, 330, 340, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(340, 340, 360, "Platform_Ctl") LEGOCARBUILD_TICKLE_CASE(390, 390, 410, "Exit_Ctl") - case 503: + break; + case RacecarScript::c_irt004d1_RunAnim: LEGOCARBUILD_TICKLE_CASE(50, 50, 60, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(63, 65, 70, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(70, 70, 80, "Platform_Ctl") LEGOCARBUILD_TICKLE_CASE(95, 95, 105, "Exit_Ctl") - case 504: + break; + case RacecarScript::c_irtxx4d1_RunAnim: LEGOCARBUILD_TICKLE_CASE(22, 24, 29, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(33, 35, 40, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(43, 45, 50, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(56, 58, 63, "Platform_Ctl") - default: - return SUCCESS; + break; } } else if (m_carId == Jetski_Actor) { switch (m_unk0x10a) { - case 500: + case JetskiScript::c_ijs001d4_RunAnim: LEGOCARBUILD_TICKLE_CASE(291, 291, 311, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(311, 311, 331, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(412, 412, 432, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(437, 437, 457, "Platform_Ctl") LEGOCARBUILD_TICKLE_CASE(485, 485, 505, "Exit_Ctl") - case 501: + break; + case JetskiScript::c_ijsxx2d4_RunAnim: LEGOCARBUILD_TICKLE_CASE(32, 34, 39, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(68, 70, 75, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(105, 105, 115, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(133, 135, 140, "Platform_Ctl") - case 504: + break; + case JetskiScript::c_ijs005d4_RunAnim: LEGOCARBUILD_TICKLE_CASE(78, 78, 98, "Exit_Ctl") - case 505: + break; + case JetskiScript::c_ijs006d4_RunAnim: LEGOCARBUILD_TICKLE_CASE(93, 93, 113, "Exit_Ctl") - // default: // not sure if present - // return SUCCESS; + break; } } else if (m_carId == DuneBugy_Actor) { switch (m_unk0x10a) { - case 500: + case DunecarScript::c_igs001d3_RunAnim: LEGOCARBUILD_TICKLE_CASE(155, 155, 175, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(215, 215, 235, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(285, 285, 305, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(300, 300, 320, "Platform_Ctl") LEGOCARBUILD_TICKLE_CASE(340, 340, 360, "Exit_Ctl") - case 501: + break; + case DunecarScript::c_igsxx1d3_RunAnim: LEGOCARBUILD_TICKLE_CASE(23, 23, 33, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(37, 39, 44, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(105, 105, 115, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(122, 124, 129, "Platform_Ctl") - default: - return SUCCESS; + break; } } else if (m_carId == Helicopter_Actor) { switch (m_unk0x10a) { - case 500: + case CopterScript::c_ips001d2_RunAnim: LEGOCARBUILD_TICKLE_CASE(185, 185, 205, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(235, 235, 255, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(292, 292, 312, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(315, 315, 335, "Platform_Ctl") LEGOCARBUILD_TICKLE_CASE(353, 353, 373, "Exit_Ctl") - case 501: + break; + case CopterScript::c_ipsxx1d2_RunAnim: LEGOCARBUILD_TICKLE_CASE(43, 45, 50, "Exit_Ctl") LEGOCARBUILD_TICKLE_CASE(72, 74, 79, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(114, 116, 121, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(128, 130, 135, "Platform_Ctl") - case 505: + break; + case CopterScript::c_ips005d2_RunAnim: LEGOCARBUILD_TICKLE_CASE(30, 30, 40, "ShelfUp_Ctl") LEGOCARBUILD_TICKLE_CASE(60, 60, 70, "Yellow_Ctl") LEGOCARBUILD_TICKLE_CASE(48, 48, 58, "Platform_Ctl") - default: - return SUCCESS; + break; } } } - return 0; + return SUCCESS; } // FUNCTION: LEGO1 0x10024050 From 6cda0d95c749decd4a0bca326f71005063375bbd Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Mon, 11 Nov 2024 15:44:03 +0100 Subject: [PATCH 09/13] Complete `LegoCarBuild` (#1144) * Complete `LegoCarBuild` * Fix match error * Address review comments * Fix regression * Fix minor sign comparison issue --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/legocarbuild.h | 3 + .../legoomni/include/legocarbuildpresenter.h | 5 +- LEGO1/lego/legoomni/include/legoutils.h | 2 + .../src/audio/mxbackgroundaudiomanager.cpp | 1 + .../lego/legoomni/src/build/legocarbuild.cpp | 115 +++++++++++++++++- .../src/build/legocarbuildpresenter.cpp | 34 +++++- LEGO1/lego/legoomni/src/common/legoutils.cpp | 8 ++ LEGO1/lego/legoomni/src/main/scripts.cpp | 1 + LEGO1/lego/sources/misc/legoutil.h | 3 + 9 files changed, 163 insertions(+), 9 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index 6337aafd..945d7d06 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -126,9 +126,12 @@ class LegoCarBuild : public LegoWorld { ); // vtable+0x80 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 FUN_100236d0(); undefined4 FUN_10024250(LegoEventNotificationParam* p_param); void FUN_100243a0(); undefined4 FUN_10024480(MxActionNotificationParam* p_param); diff --git a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h index 2e61b1e5..deb55c03 100644 --- a/LEGO1/lego/legoomni/include/legocarbuildpresenter.h +++ b/LEGO1/lego/legoomni/include/legocarbuildpresenter.h @@ -70,6 +70,7 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { void FUN_10079680(LegoChar* p_param); LegoAnimNodeData* FindNodeDataByName(LegoTreeNode* p_treeNode, const LegoChar* p_name); LegoTreeNode* FindNodeByName(LegoTreeNode* p_treeNode, const LegoChar* p_name); + void FUN_10079790(const LegoChar* p_name); void RotateAroundYAxis(MxFloat p_angle); MxBool FUN_10079c30(const LegoChar* p_name); MxBool PartIsPlaced(const LegoChar* p_name); @@ -77,7 +78,7 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { MxBool StringEqualsPlatform(const LegoChar* p_string); MxBool StringEqualsShelf(const LegoChar* p_string); MxBool StringEndsOnY(const LegoChar* p_string); - MxBool StringEndsOnZero(const LegoChar* p_string); + MxBool StringDoesNotEndOnZero(const LegoChar* p_string); const LegoChar* GetWiredNameByPartName(const LegoChar* p_name); void SetPartObjectIdByName(const LegoChar* p_name, MxS16 p_objectId); @@ -130,7 +131,7 @@ class LegoCarBuildAnimPresenter : public LegoAnimPresenter { MxFloat m_unk0x130; // 0x130 MxFloat m_unk0x134; // 0x134 MxFloat m_unk0x138; // 0x138 - MxLong m_unk0x13c; // 0x13c + MxULong m_unk0x13c; // 0x13c LegoEntity* m_unk0x140; // 0x140 MxS32 m_unk0x144; // 0x144 MxS32 m_unk0x148; // 0x148 diff --git a/LEGO1/lego/legoomni/include/legoutils.h b/LEGO1/lego/legoomni/include/legoutils.h index 604e860c..ceb64416 100644 --- a/LEGO1/lego/legoomni/include/legoutils.h +++ b/LEGO1/lego/legoomni/include/legoutils.h @@ -28,6 +28,7 @@ enum Cursor { e_cursorNone }; +class BoundingSphere; class MxAtomId; class LegoEntity; class LegoFile; @@ -43,6 +44,7 @@ LegoEntity* PickEntity(MxLong, MxLong); LegoROI* PickROI(MxLong, MxLong); LegoROI* PickParentROI(MxLong p_a, MxLong p_b); void FUN_1003dde0(LegoROI* p_param1, MxFloat p_param2); +MxBool SpheresIntersect(const BoundingSphere& p_sphere1, const BoundingSphere& p_sphere2); MxBool FUN_1003ded0(MxFloat p_param1[2], MxFloat p_param2[3], MxFloat p_param3[3]); MxBool TransformWorldToScreen(const MxFloat p_world[3], MxFloat p_screen[4]); MxS16 CountTotalTreeNodes(LegoTreeNode* p_node); diff --git a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index 4a921511..7ab16e56 100644 --- a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -358,6 +358,7 @@ undefined4 MxBackgroundAudioManager::FUN_1007f610( } // FUNCTION: LEGO1 0x1007f650 +// FUNCTION: BETA10 0x100e9663 void MxBackgroundAudioManager::Init() { this->m_unk0xa0 = 0; diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 825b37e4..0f6306fb 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -196,7 +196,7 @@ MxResult LegoCarBuild::Create(MxDSAction& p_dsAction) else if (m_atomId == *g_racecarScript) { buildStateClassName = "LegoRaceCarBuildState"; GameState()->m_currentArea = LegoGameState::e_racecarbuild; - m_carId = Helicopter_Actor; + m_carId = RaceCar_Actor; } LegoGameState* gameState = GameState(); @@ -235,6 +235,14 @@ MxS16 LegoCarBuild::GetPlacedPartCount() } } +// FUNCTION: LEGO1 0x10022cf0 +void LegoCarBuild::SetPlacedPartCount(MxU8 p_placedPartCount) +{ + if (m_buildState) { + m_buildState->m_placedPartCount = p_placedPartCount; + } +} + // FUNCTION: LEGO1 0x10022d10 // FUNCTION: BETA10 0x1006b27a void LegoCarBuild::InitPresenters() @@ -281,6 +289,16 @@ void LegoCarBuild::InitPresenters() } } +// FUNCTION: LEGO1 0x10022f00 +void LegoCarBuild::FUN_10022f00() +{ + if (m_unk0x110) { + VTable0x6c(); + m_unk0x258->SetUnknown0xbc(0); + m_unk0x100 = 5; + } +} + // FUNCTION: LEGO1 0x10022f30 // FUNCTION: BETA10 0x1006b835 void LegoCarBuild::FUN_10022f30() @@ -458,6 +476,55 @@ void LegoCarBuild::VTable0x80(MxFloat p_param1[2], MxFloat p_param2[2], MxFloat p_param4[1] = p_param3; } +// FUNCTION: LEGO1 0x100236d0 +// FUNCTION: BETA10 0x1006c076 +void LegoCarBuild::FUN_100236d0() +{ + MxS32 pLVar2; + + FUN_10024f70(FALSE); + FUN_100250e0(FALSE); + m_unk0x258->FUN_10079790(m_unk0x110->GetName()); + m_unk0x258->SetUnknown0xbc(1); + m_unk0x110 = NULL; + m_unk0x100 = 0; + + if (m_unk0x258->AllPartsPlaced()) { + // Note the code duplication with LEGO1 0x10025ee0 + switch (m_carId) { + case 1: + pLVar2 = 0x2f; + break; + case 2: + pLVar2 = 0x31; + break; + case 3: + pLVar2 = 0x33; + break; + case 4: + pLVar2 = 0x35; + } + + BackgroundAudioManager()->Init(); + InvokeAction(Extra::e_stop, *g_jukeboxScript, pLVar2, NULL); + + if (m_numAnimsRun > 0) { + DeleteObjects(&m_atomId, 500, 510); + } + + if (GameState()->GetCurrentAct() == LegoGameState::e_act2) { + FUN_100243a0(); + } + else { + 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; + m_buildState->m_placedPartCount = 0; + } + } +} + #define LEGOCARBUILD_TICKLE_CASE(subtract, start, end, str) \ if (start < dTime && dTime < end) { \ FUN_10025db0(str, dTime - subtract); \ @@ -812,11 +879,49 @@ undefined4 LegoCarBuild::FUN_100244e0(MxLong p_x, MxLong p_y) return 1; } -// STUB: LEGO1 0x100246e0 +// FUNCTION: LEGO1 0x100246e0 undefined4 LegoCarBuild::FUN_100246e0(MxLong p_x, MxLong p_y) { - // TODO - return 0; + switch (m_unk0x100) { + case 3: + FUN_10022f30(); + return 1; + case 4: + FUN_10022f00(); + return 1; + case 6: + if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) { + if (SpheresIntersect(m_unk0x114, m_unk0x110->GetWorldBoundingSphere())) { + FUN_10024f70(FALSE); + FUN_100250e0(FALSE); + m_unk0x100 = 0; + m_unk0x110 = NULL; + m_PlaceBrick_Sound->Enable(FALSE); + m_PlaceBrick_Sound->Enable(TRUE); + m_unk0x258->SetUnknown0xbc(1); + return 1; + } + } + + if (m_unk0x258->FUN_10079c30(m_unk0x110->GetName())) { + if (SpheresIntersect(m_unk0x114, m_unk0x110->GetWorldBoundingSphere())) { + m_PlaceBrick_Sound->Enable(FALSE); + m_PlaceBrick_Sound->Enable(TRUE); + FUN_100236d0(); + return 1; + } + + VTable0x6c(); + m_unk0x100 = 5; + return 1; + } + + VTable0x6c(); + m_unk0x100 = 5; + return 1; + default: + return 0; + } } // FUNCTION: LEGO1 0x10024850 @@ -1207,7 +1312,7 @@ void LegoCarBuild::TogglePresentersEnabled() // FUNCTION: BETA10 0x1006e124 void LegoCarBuild::FUN_100250e0(MxBool p_enabled) { - if (m_unk0x258->StringEndsOnZero(m_unk0x110->GetName()) && m_Decals_Ctl) { + if (m_unk0x258->StringDoesNotEndOnZero(m_unk0x110->GetName()) && m_Decals_Ctl) { if (strnicmp(m_unk0x110->GetName(), "JSFRNT", strlen("JSFRNT")) == 0) { m_Decal_Bitmap->Enable(p_enabled); m_Decals_Ctl->Enable(p_enabled); diff --git a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp index 546aac67..7e0486ee 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuildpresenter.cpp @@ -9,6 +9,7 @@ #include "legovideomanager.h" #include "legoworld.h" #include "misc.h" +#include "misc/legoutil.h" #include "mxautolock.h" #include "mxcompositepresenter.h" #include "mxmisc.h" @@ -507,6 +508,35 @@ LegoTreeNode* LegoCarBuildAnimPresenter::FindNodeByName(LegoTreeNode* p_treeNode return NULL; } +// FUNCTION: LEGO1 0x10079790 +// FUNCTION: BETA10 0x100720a3 +void LegoCarBuildAnimPresenter::FUN_10079790(const LegoChar* p_name) +{ + MxS16 i; + LegoChar buffer[40]; + + if (strcmpi(m_parts[m_placedPartCount].m_name, p_name) != 0) { + for (i = m_placedPartCount + 1; i < m_numberOfParts; i++) { + if (stricmp(m_parts[i].m_name, p_name) == 0) { + break; + } + } + + strcpy(buffer, m_parts[m_placedPartCount].m_name); + strcpy(m_parts[m_placedPartCount].m_name, m_parts[i].m_name); + strcpy(m_parts[i].m_name, buffer); + Swap(m_parts[m_placedPartCount].m_objectId, m_parts[i].m_objectId); + } + FUN_10079050(m_placedPartCount); + m_placedPartCount++; + + ((LegoCarBuild*) m_currentWorld)->SetPlacedPartCount(m_placedPartCount); + + if (m_placedPartCount < m_numberOfParts) { + FUN_10079680(m_parts[m_placedPartCount].m_wiredName); + } +} + // FUNCTION: LEGO1 0x10079920 // FUNCTION: BETA10 0x1007225d void LegoCarBuildAnimPresenter::RotateAroundYAxis(MxFloat p_angle) @@ -622,9 +652,9 @@ MxBool LegoCarBuildAnimPresenter::StringEndsOnY(const LegoChar* p_string) // FUNCTION: LEGO1 0x10079d30 // FUNCTION: BETA10 0x1007280e -MxBool LegoCarBuildAnimPresenter::StringEndsOnZero(const LegoChar* p_string) +MxBool LegoCarBuildAnimPresenter::StringDoesNotEndOnZero(const LegoChar* p_string) { - return (p_string[strlen(p_string) - 2] != '0'); + return (p_string[strlen(p_string) - 1] != '0'); } // FUNCTION: LEGO1 0x10079d60 diff --git a/LEGO1/lego/legoomni/src/common/legoutils.cpp b/LEGO1/lego/legoomni/src/common/legoutils.cpp index d38ff896..c5e658a6 100644 --- a/LEGO1/lego/legoomni/src/common/legoutils.cpp +++ b/LEGO1/lego/legoomni/src/common/legoutils.cpp @@ -72,6 +72,14 @@ void FUN_1003dde0(LegoROI* p_param1, MxFloat p_param2) // TODO } +// FUNCTION: LEGO1 0x1003de80 +MxBool SpheresIntersect(const BoundingSphere& p_sphere1, const BoundingSphere& p_sphere2) +{ + // This doesn't look clean, but it matches. + // p_sphere1.Center().GetData() doesn't work out + return sqrt(DISTSQRD3(&p_sphere1.Center()[0], &p_sphere2.Center()[0])) < p_sphere1.Radius() + p_sphere2.Radius(); +} + // FUNCTION: LEGO1 0x1003ded0 // FUNCTION: BETA10 0x100d3802 MxBool FUN_1003ded0(MxFloat p_param1[2], MxFloat p_param2[3], MxFloat p_param3[3]) diff --git a/LEGO1/lego/legoomni/src/main/scripts.cpp b/LEGO1/lego/legoomni/src/main/scripts.cpp index b5d7fe54..b5b8f9fe 100644 --- a/LEGO1/lego/legoomni/src/main/scripts.cpp +++ b/LEGO1/lego/legoomni/src/main/scripts.cpp @@ -64,6 +64,7 @@ MxAtomId* g_act2mainScript = NULL; MxAtomId* g_act3Script = NULL; // GLOBAL: LEGO1 0x100f456c +// GLOBAL: BETA10 0x102114e0 MxAtomId* g_jukeboxScript = NULL; // GLOBAL: LEGO1 0x100f4570 diff --git a/LEGO1/lego/sources/misc/legoutil.h b/LEGO1/lego/sources/misc/legoutil.h index 92bb84c2..fc42d462 100644 --- a/LEGO1/lego/sources/misc/legoutil.h +++ b/LEGO1/lego/sources/misc/legoutil.h @@ -39,6 +39,9 @@ inline void Swap(T& p_t1, T& p_t2) p_t2 = t; } +// TEMPLATE: BETA10 0x10073c20 +// Swap + template inline T DToR(T p_d) { From bebe780c772316756539a0c10730ece227c1e5b7 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 11 Nov 2024 10:48:45 -0700 Subject: [PATCH 10/13] Implement/match LegoAct2::Create (#1146) --- LEGO1/lego/legoomni/include/legoact2.h | 2 +- LEGO1/lego/legoomni/src/worlds/legoact2.cpp | 46 +++++++++++++++++++-- 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoact2.h b/LEGO1/lego/legoomni/include/legoact2.h index 3f8b65ef..7482f0ce 100644 --- a/LEGO1/lego/legoomni/include/legoact2.h +++ b/LEGO1/lego/legoomni/include/legoact2.h @@ -78,7 +78,7 @@ class LegoAct2 : public LegoWorld { undefined m_unk0x10c2; // 0x10c2 undefined4 m_unk0x10c4; // 0x10c4 undefined4 m_unk0x10c8; // 0x10c8 - undefined4 m_unk0x10cc; // 0x10cc + LegoAct2State* m_gameState; // 0x10cc undefined4 m_unk0x10d0; // 0x10d0 char* m_unk0x10d4; // 0x10d4 undefined4 m_unk0x10d8; // 0x10d8 diff --git a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp index 523cee3c..a11b63b6 100644 --- a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp +++ b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp @@ -1,6 +1,7 @@ #include "legoact2.h" #include "legoanimationmanager.h" +#include "legogamestate.h" #include "legoinputmanager.h" #include "misc.h" #include "mxmisc.h" @@ -40,11 +41,50 @@ LegoAct2::~LegoAct2() NotificationManager()->Unregister(this); } -// STUB: LEGO1 0x1004ff20 +// FUNCTION: LEGO1 0x1004ff20 +// FUNCTION: BETA10 0x1003a7ff MxResult LegoAct2::Create(MxDSAction& p_dsAction) { - // TODO - return SUCCESS; + GameState()->FindLoadedAct(); + + MxResult result = LegoWorld::Create(p_dsAction); + if (result == SUCCESS) { + AnimationManager()->EnableCamAnims(FALSE); + + LegoGameState* gameState = GameState(); + LegoAct2State* state = (LegoAct2State*) gameState->GetState("LegoAct2State"); + + if (state == NULL) { + state = (LegoAct2State*) gameState->CreateState("LegoAct2State"); + } + + m_gameState = state; + m_gameState->m_unk0x08 = 0; + + switch (GameState()->GetLoadedAct()) { + case LegoGameState::e_act2: + GameState()->StopArea(LegoGameState::e_infomain); + GameState()->StopArea(LegoGameState::e_act2main); + break; + case LegoGameState::e_act3: + GameState()->StopArea(LegoGameState::e_infomain); + GameState()->StopArea(LegoGameState::e_act3script); + break; + case LegoGameState::e_act1: + case LegoGameState::e_actNotFound: + GameState()->StopArea(LegoGameState::e_undefined); + if (GameState()->GetPreviousArea() == LegoGameState::e_infomain) { + GameState()->StopArea(LegoGameState::e_isle); + } + } + + GameState()->m_currentArea = LegoGameState::e_act2main; + GameState()->SetCurrentAct(LegoGameState::e_act2); + InputManager()->Register(this); + GameState()->SetDirty(TRUE); + } + + return result; } // STUB: LEGO1 0x10050040 From 71a1c515968163b5a3c9dae5d4d55fc3272c7f45 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 11 Nov 2024 11:30:34 -0700 Subject: [PATCH 11/13] Implement/match LegoAct2::Escape (#1147) * Implement/match LegoAct2::Escape * Match empty function --- LEGO1/lego/legoomni/src/worlds/legoact2.cpp | 27 +++++++++++++++++---- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp index a11b63b6..cc8f5d73 100644 --- a/LEGO1/lego/legoomni/src/worlds/legoact2.cpp +++ b/LEGO1/lego/legoomni/src/worlds/legoact2.cpp @@ -1,9 +1,12 @@ #include "legoact2.h" +#include "act2main_actions.h" +#include "islepathactor.h" #include "legoanimationmanager.h" #include "legogamestate.h" #include "legoinputmanager.h" #include "misc.h" +#include "mxbackgroundaudiomanager.h" #include "mxmisc.h" #include "mxnotificationmanager.h" #include "mxticklemanager.h" @@ -127,15 +130,29 @@ void LegoAct2::FUN_10051900() } } -// STUB: LEGO1 0x100519c0 +// FUNCTION: LEGO1 0x100519c0 void LegoAct2::VTable0x60() { - // TODO + // empty } -// STUB: LEGO1 0x100519d0 +// FUNCTION: LEGO1 0x100519d0 MxBool LegoAct2::Escape() { - // TODO - return FALSE; + BackgroundAudioManager()->Stop(); + AnimationManager()->FUN_10061010(FALSE); + DeleteObjects(&m_atomId, Act2mainScript::c_snsx50bu_RunAnim, 999); + + if (UserActor() != NULL) { + if (UserActor()->GetActorId() != GameState()->GetActorId()) { + ((IslePathActor*) UserActor())->Exit(); + } + } + + if (m_gameState != NULL) { + m_gameState->m_unk0x0c = 0; + } + + m_unk0x1150 = 2; + return TRUE; } From 8e23bfb2666b2ec4d41f308749b022413b2ea03e Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Mon, 11 Nov 2024 11:36:36 -0700 Subject: [PATCH 12/13] Implement/match some Act2Actor functions (#1148) --- LEGO1/lego/legoomni/include/act2actor.h | 31 +++++++++--- LEGO1/lego/legoomni/src/actors/act2actor.cpp | 52 +++++++++++++++----- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/LEGO1/lego/legoomni/include/act2actor.h b/LEGO1/lego/legoomni/include/act2actor.h index 7ae28781..27a5fe22 100644 --- a/LEGO1/lego/legoomni/include/act2actor.h +++ b/LEGO1/lego/legoomni/include/act2actor.h @@ -10,19 +10,34 @@ class Act2Actor : public LegoAnimActor { public: Act2Actor(); - void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) override; // vtable+0x24 - void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - MxS32 VTable0x68(Vector3&, Vector3&, Vector3&) override; // vtable+0x68 - void VTable0x70(float p_und) override; // vtable+0x70 - MxResult VTable0x94(LegoPathActor*, MxBool) override; // vtable+0x94 - MxResult VTable0x9c() override; // vtable+0x9c - MxS32 VTable0xa0() override; // vtable+0xa0 + void SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) override; // vtable+0x24 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + MxS32 VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3) override; // vtable+0x68 + void VTable0x70(float p_und) override; // vtable+0x70 + MxResult VTable0x94(LegoPathActor*, MxBool) override; // vtable+0x94 + MxResult VTable0x9c() override; // vtable+0x9c + MxS32 VTable0xa0() override; // vtable+0xa0 // SYNTHETIC: LEGO1 0x1001a0a0 // Act2Actor::`scalar deleting destructor' private: - undefined m_unk0x1c[0x34]; // 0x1c + undefined m_unk0x1c; // 0x1c + undefined m_unk0x1d; // 0x1d + undefined m_unk0x1e; // 0x1e + MxBool m_unk0x1f; // 0x1f + undefined4 m_unk0x20; // 0x20 + undefined4 m_unk0x24; // 0x24 + undefined4 m_unk0x28; // 0x28 + undefined4 m_unk0x2c; // 0x2c + undefined4 m_unk0x30; // 0x30 + undefined4 m_unk0x34; // 0x34 + undefined4 m_unk0x38; // 0x38 + undefined4 m_unk0x3c; // 0x3c + undefined m_unk0x40; // 0x40 + undefined4 m_unk0x44; // 0x44 + undefined m_unk0x48; // 0x48 + undefined4 m_unk0x4c; // 0x4c }; #endif // ACT2ACTOR_H diff --git a/LEGO1/lego/legoomni/src/actors/act2actor.cpp b/LEGO1/lego/legoomni/src/actors/act2actor.cpp index bc100885..c978c3ed 100644 --- a/LEGO1/lego/legoomni/src/actors/act2actor.cpp +++ b/LEGO1/lego/legoomni/src/actors/act2actor.cpp @@ -1,23 +1,49 @@ #include "act2actor.h" +#include "legocachesoundmanager.h" +#include "legosoundmanager.h" +#include "misc.h" +#include "roi/legoroi.h" + DECOMP_SIZE_ASSERT(Act2Actor, 0x1a8) // STUB: LEGO1 0x100187e0 Act2Actor::Act2Actor() { - // TODO + m_unk0x1c = 0; + m_unk0x1d = 0; + m_unk0x1f = FALSE; + m_unk0x24 = 0; + m_unk0x20 = 0; + m_unk0x1e = 0; + m_unk0x28 = 4; + m_unk0x2c = 0; + m_unk0x30 = 0; + m_unk0x34 = 0; + m_unk0x44 = 0; + m_unk0x40 = 1; + m_unk0x48 = 0; + m_unk0x4c = 0; + m_unk0x38 = 0; + m_unk0x3c = 0; } -// STUB: LEGO1 0x10018940 +// FUNCTION: LEGO1 0x10018940 void Act2Actor::SetROI(LegoROI* p_roi, MxBool p_bool1, MxBool p_bool2) { - // TODO + LegoAnimActor::SetROI(p_roi, p_bool1, p_bool2); + m_roi->SetVisibility(FALSE); } -// STUB: LEGO1 0x100189f0 +// FUNCTION: LEGO1 0x100189f0 MxResult Act2Actor::VTable0x94(LegoPathActor*, MxBool) { - // TODO + if (m_unk0x1f == FALSE) { + m_unk0x1f = TRUE; + m_unk0x20 = 0; + } + + SoundManager()->GetCacheSoundManager()->Play("hitactor", NULL, FALSE); return SUCCESS; } @@ -34,10 +60,11 @@ void Act2Actor::VTable0x70(float p_und) // TODO } -// STUB: LEGO1 0x10019280 +// FUNCTION: LEGO1 0x10019280 void Act2Actor::SetWorldSpeed(MxFloat p_worldSpeed) { - // TODO + LegoAnimActor::SetWorldSpeed(p_worldSpeed); + m_unk0x44 = 0; } // STUB: LEGO1 0x100195a0 @@ -47,9 +74,12 @@ MxS32 Act2Actor::VTable0xa0() return 0; } -// STUB: LEGO1 0x1001a180 -MxS32 Act2Actor::VTable0x68(Vector3&, Vector3&, Vector3&) +// FUNCTION: LEGO1 0x1001a180 +MxS32 Act2Actor::VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3) { - // TODO - return 0; + if (m_unk0x1f) { + return 0; + } + + return LegoAnimActor::VTable0x68(p_v1, p_v2, p_v3); } From 71a7498481fa56af26bfbca5d1b5911f66085a51 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Thu, 14 Nov 2024 21:42:38 +0100 Subject: [PATCH 13/13] Implement most of `JetskiRace`, add BETA10 annotations (#1149) * Implement most of `JetskiRace`, add BETA10 annotations * Fix declaration order issue * Clean up FUN_10012de0 * Fix regression * Address review comments * Address another review comment --------- Co-authored-by: jonschz --- LEGO1/lego/legoomni/include/jetskirace.h | 7 + LEGO1/lego/legoomni/include/legoactor.h | 2 +- LEGO1/lego/legoomni/include/legoentity.h | 1 + LEGO1/lego/legoomni/include/legorace.h | 26 ++- LEGO1/lego/legoomni/include/legoracers.h | 5 +- LEGO1/lego/legoomni/include/legostate.h | 5 + LEGO1/lego/legoomni/include/legoworld.h | 38 +++-- .../include/mxbackgroundaudiomanager.h | 8 +- .../src/audio/mxbackgroundaudiomanager.cpp | 29 ++-- LEGO1/lego/legoomni/src/common/misc.cpp | 2 + LEGO1/lego/legoomni/src/entity/legoworld.cpp | 17 +- .../legoomni/src/paths/legopathstruct.cpp | 1 + LEGO1/lego/legoomni/src/race/jetskirace.cpp | 153 ++++++++++++++++-- LEGO1/lego/legoomni/src/race/legorace.cpp | 10 +- LEGO1/lego/legoomni/src/race/legoracers.cpp | 24 +++ LEGO1/library_msvc.h | 3 + LEGO1/omni/include/mxentity.h | 2 + 17 files changed, 272 insertions(+), 61 deletions(-) diff --git a/LEGO1/lego/legoomni/include/jetskirace.h b/LEGO1/lego/legoomni/include/jetskirace.h index 77501f4f..ce1ea834 100644 --- a/LEGO1/lego/legoomni/include/jetskirace.h +++ b/LEGO1/lego/legoomni/include/jetskirace.h @@ -4,27 +4,33 @@ #include "legorace.h" // VTABLE: LEGO1 0x100d4fa8 +// VTABLE: BETA10 0x101bd5d0 // SIZE 0x2c class JetskiRaceState : public RaceState { public: // FUNCTION: LEGO1 0x1000dc40 + // FUNCTION: BETA10 0x100a8f30 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f00ac + // STRING: BETA10 0x101f1d0c return "JetskiRaceState"; } // FUNCTION: LEGO1 0x1000dc50 + // FUNCTION: BETA10 0x100a8f60 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JetskiRaceState::ClassName()) || RaceState::IsA(p_name); } // SYNTHETIC: LEGO1 0x1000f680 + // SYNTHETIC: BETA10 0x100a9d10 // JetskiRaceState::`scalar deleting destructor' }; // VTABLE: LEGO1 0x100d4fe8 +// VTABLE: BETA10 0x101bd268 // SIZE 0x144 class JetskiRace : public LegoRace { public: @@ -43,6 +49,7 @@ class JetskiRace : public LegoRace { } // FUNCTION: LEGO1 0x1000db00 + // FUNCTION: BETA10 0x100a8860 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, JetskiRace::ClassName()) || LegoRace::IsA(p_name); diff --git a/LEGO1/lego/legoomni/include/legoactor.h b/LEGO1/lego/legoomni/include/legoactor.h index d5641b72..75ea7e63 100644 --- a/LEGO1/lego/legoomni/include/legoactor.h +++ b/LEGO1/lego/legoomni/include/legoactor.h @@ -62,9 +62,9 @@ class LegoActor : public LegoEntity { static const char* GetActorName(MxU8 p_id); -protected: void Mute(MxBool p_muted); +protected: MxFloat m_frequencyFactor; // 0x68 LegoCacheSound* m_sound; // 0x6c MxFloat m_unk0x70; // 0x70 diff --git a/LEGO1/lego/legoomni/include/legoentity.h b/LEGO1/lego/legoomni/include/legoentity.h index 115ed813..26256c84 100644 --- a/LEGO1/lego/legoomni/include/legoentity.h +++ b/LEGO1/lego/legoomni/include/legoentity.h @@ -45,6 +45,7 @@ class LegoEntity : public MxEntity { } // FUNCTION: LEGO1 0x1000c300 + // FUNCTION: BETA10 0x100125a0 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoEntity::ClassName()) || MxEntity::IsA(p_name); diff --git a/LEGO1/lego/legoomni/include/legorace.h b/LEGO1/lego/legoomni/include/legorace.h index ff463538..cad39de1 100644 --- a/LEGO1/lego/legoomni/include/legorace.h +++ b/LEGO1/lego/legoomni/include/legorace.h @@ -3,6 +3,7 @@ #include "decomp.h" #include "legogamestate.h" +#include "legoraceactor.h" #include "legoracemap.h" #include "legostate.h" #include "legoworld.h" @@ -17,6 +18,7 @@ class MxNotificationParam; class LegoPathStructNotificationParam; // VTABLE: LEGO1 0x100d5e30 +// VTABLE: BETA10 0x101be270 // SIZE 0x2c class RaceState : public LegoState { public: @@ -34,6 +36,7 @@ class RaceState : public LegoState { MxS16 GetUnknown0x02() { return m_unk0x02; } MxS16 GetHighScore() { return m_score; } + // FUNCTION: BETA10 0x100c96f0 MxResult Serialize(LegoFile* p_file) { if (p_file->IsReadMode()) { @@ -59,13 +62,16 @@ class RaceState : public LegoState { RaceState(); // FUNCTION: LEGO1 0x10016010 + // FUNCTION: BETA10 0x100a9040 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f07d0 + // STRING: BETA10 0x101f1d20 return "RaceState"; } // FUNCTION: LEGO1 0x10016020 + // FUNCTION: BETA10 0x100a8fd0 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, RaceState::ClassName()) || LegoState::IsA(p_name); @@ -90,6 +96,7 @@ class RaceState : public LegoState { }; // VTABLE: LEGO1 0x100d5db0 +// VTABLE: BETA10 0x101be1e0 // SIZE 0x144 class LegoRace : public LegoWorld { public: @@ -113,6 +120,7 @@ class LegoRace : public LegoWorld { } // FUNCTION: LEGO1 0x10015bb0 + // FUNCTION: BETA10 0x100a88d0 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoRace::ClassName()) || LegoWorld::IsA(p_name); @@ -132,8 +140,12 @@ class LegoRace : public LegoWorld { // FUNCTION: LEGO1 0x1000dab0 virtual MxLong HandleType0Notification(MxNotificationParam&) { return 0; } // vtable+0x78 - // STUB: LEGO1 0x1000dac0 - virtual void VTable0x7c(LegoRaceMap*, undefined4) {} // vtable+0x7c + // FUNCTION: LEGO1 0x1000dac0 + // FUNCTION: BETA10 0x100a87d0 + virtual void VTable0x7c(LegoRaceActor* p_map, MxU32 p_index) // vtable+0x7c + { + m_unk0x110[p_index] = (LegoRaceActor*) p_map; + } // SYNTHETIC: LEGO1 0x10015cc0 // LegoRace::`scalar deleting destructor' @@ -145,16 +157,14 @@ class LegoRace : public LegoWorld { undefined4 m_unk0x104; // 0x104 undefined4 m_unk0x108; // 0x108 undefined4 m_unk0x10c; // 0x10c - undefined4 m_unk0x110; // 0x110 - undefined4 m_unk0x114; // 0x114 - undefined4 m_unk0x118; // 0x118 + LegoRaceActor* m_unk0x110[3]; // 0x110 LegoGameState::Area m_destLocation; // 0x11c LegoPathActor* m_pathActor; // 0x120 Act1State* m_act1State; // 0x124 - undefined4 m_unk0x128; // 0x128 - undefined4 m_unk0x12c; // 0x12c + MxStillPresenter* m_unk0x128; // 0x128 + MxStillPresenter* m_unk0x12c; // 0x12c MxRect32 m_unk0x130; // 0x130 - undefined4 m_unk0x140; // 0x140 + RaceState* m_raceState; // 0x140 }; #endif // LEGORACE_H diff --git a/LEGO1/lego/legoomni/include/legoracers.h b/LEGO1/lego/legoomni/include/legoracers.h index ea8472d1..add7d795 100644 --- a/LEGO1/lego/legoomni/include/legoracers.h +++ b/LEGO1/lego/legoomni/include/legoracers.h @@ -75,6 +75,9 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { virtual void FUN_10012ff0(float p_param); virtual MxU32 HandleSkeletonKicks(float p_param1); + static void FUN_10012de0(); + static void FUN_10013670(); + // SYNTHETIC: LEGO1 0x10014240 // LegoRaceCar::`scalar deleting destructor' @@ -108,10 +111,10 @@ class LegoRaceCar : public LegoCarRaceActor, public LegoRaceMap { static MxU32 g_srtsl6to10Index; static MxU32 g_emptySoundKeyListIndex; static MxU32 g_srtrhIndex; + static Mx3DPointFloat g_unk0x10102af0; static MxLong g_timeLastSoundPlayed; static MxS32 g_unk0x100f0b88; static MxBool g_unk0x100f0b8c; - static Mx3DPointFloat g_unk0x10102af0; }; #endif // LEGORACERS_H diff --git a/LEGO1/lego/legoomni/include/legostate.h b/LEGO1/lego/legoomni/include/legostate.h index f217573c..b8b9c47f 100644 --- a/LEGO1/lego/legoomni/include/legostate.h +++ b/LEGO1/lego/legoomni/include/legostate.h @@ -6,6 +6,7 @@ #include "mxcore.h" // VTABLE: LEGO1 0x100d46c0 +// VTABLE: BETA10 0x101b89d8 // SIZE 0x08 class LegoState : public MxCore { public: @@ -84,13 +85,16 @@ class LegoState : public MxCore { ~LegoState() override {} // FUNCTION: LEGO1 0x100060d0 + // FUNCTION: BETA10 0x10017d20 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f01b8 + // STRING: BETA10 0x101dcdac return "LegoState"; } // FUNCTION: LEGO1 0x100060e0 + // FUNCTION: BETA10 0x100a9000 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoState::ClassName()) || MxCore::IsA(p_name); @@ -103,6 +107,7 @@ class LegoState : public MxCore { virtual MxBool Reset() { return FALSE; } // vtable+0x18 // FUNCTION: LEGO1 0x10005fb0 + // FUNCTION: BETA10 0x10017af0 virtual MxResult Serialize(LegoFile* p_file) { if (p_file->IsWriteMode()) { diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index d248ab5b..e2aaf8f4 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -28,6 +28,7 @@ struct CoreSetCompare { typedef set MxCoreSet; // VTABLE: LEGO1 0x100d6280 +// VTABLE: BETA10 0x101befd8 // SIZE 0xf8 class LegoWorld : public LegoEntity { public: @@ -46,6 +47,7 @@ class LegoWorld : public LegoEntity { MxResult Tickle() override; // vtable+0x08 // FUNCTION: LEGO1 0x1001d690 + // FUNCTION: BETA10 0x10017660 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0058 @@ -53,6 +55,7 @@ class LegoWorld : public LegoEntity { } // FUNCTION: LEGO1 0x1001d6a0 + // FUNCTION: BETA10 0x100175f0 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, LegoWorld::ClassName()) || LegoEntity::IsA(p_name); @@ -104,7 +107,7 @@ class LegoWorld : public LegoEntity { MxS32 GetWorldId() { return m_worldId; } MxBool GetUnknown0xd0Empty() { return m_set0xd0.empty(); } list& GetROIList() { return m_roiList; } - LegoHideAnimPresenter* GetHideAnimPresenter() { return m_hideAnimPresenter; } + LegoHideAnimPresenter* GetHideAnimPresenter() { return m_hideAnim; } void SetWorldId(MxS32 p_worldId) { m_worldId = p_worldId; } @@ -112,21 +115,24 @@ class LegoWorld : public LegoEntity { // LegoWorld::`scalar deleting destructor' protected: - LegoPathControllerList m_list0x68; // 0x68 - MxPresenterList m_animPresenters; // 0x80 - LegoCameraController* m_cameraController; // 0x98 - LegoEntityList* m_entityList; // 0x9c - LegoCacheSoundList* m_cacheSoundList; // 0xa0 - MxBool m_destroyed; // 0xa4 - MxCoreSet m_set0xa8; // 0xa8 - MxPresenterList m_controlPresenters; // 0xb8 - MxCoreSet m_set0xd0; // 0xd0 - list m_roiList; // 0xe0 - MxS32 m_worldId; // 0xec - LegoHideAnimPresenter* m_hideAnimPresenter; // 0xf0 - MxS16 m_startupTicks; // 0xf4 - MxBool m_worldStarted; // 0xf6 - undefined m_unk0xf7; // 0xf7 + LegoPathControllerList m_list0x68; // 0x68 + MxPresenterList m_animPresenters; // 0x80 + LegoCameraController* m_cameraController; // 0x98 + LegoEntityList* m_entityList; // 0x9c + LegoCacheSoundList* m_cacheSoundList; // 0xa0 + MxBool m_destroyed; // 0xa4 + MxCoreSet m_set0xa8; // 0xa8 + MxPresenterList m_controlPresenters; // 0xb8 + MxCoreSet m_set0xd0; // 0xd0 + list m_roiList; // 0xe0 + MxS32 m_worldId; // 0xec + + // name verified by BETA10 0x100c7f59 + LegoHideAnimPresenter* m_hideAnim; // 0xf0 + + MxS16 m_startupTicks; // 0xf4 + MxBool m_worldStarted; // 0xf6 + undefined m_unk0xf7; // 0xf7 }; // clang-format off diff --git a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h index 88bec8b1..210f646c 100644 --- a/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h +++ b/LEGO1/lego/legoomni/include/mxbackgroundaudiomanager.h @@ -35,7 +35,7 @@ class MxBackgroundAudioManager : public MxCore { void StartAction(MxParam& p_param); void StopAction(MxParam& p_param); - MxResult PlayMusic(MxDSAction& p_action, undefined4 p_unk0x140, MxPresenter::TickleState p_tickleState); + MxResult PlayMusic(MxDSAction& p_action, undefined4 p_speed, MxPresenter::TickleState p_tickleState); void FUN_1007ee70(); void FUN_1007ef40(); @@ -48,7 +48,7 @@ class MxBackgroundAudioManager : public MxCore { void Stop(); void LowerVolume(); void RaiseVolume(); - undefined4 FUN_1007f610(MxPresenter* p_unk0x138, MxS32 p_unk0x140, MxPresenter::TickleState p_tickleState); + undefined4 FUN_1007f610(MxPresenter* p_unk0x138, MxS32 p_speed, MxPresenter::TickleState p_tickleState); // SYNTHETIC: LEGO1 0x1007ec00 // MxBackgroundAudioManager::`scalar deleting destructor' @@ -66,7 +66,9 @@ class MxBackgroundAudioManager : public MxCore { // name is inferred from context MxPresenter::TickleState m_tickleState; // 0x13c - MxS32 m_unk0x140; // 0x140 + // name inferred from parameter p_speed + MxS32 m_speed; // 0x140 + MxS32 m_targetVolume; // 0x144 MxS16 m_unk0x148; // 0x148 MxAtomId m_script; // 0x14c diff --git a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp index 7ab16e56..98cf881b 100644 --- a/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp +++ b/LEGO1/lego/legoomni/src/audio/mxbackgroundaudiomanager.cpp @@ -21,7 +21,7 @@ MxBackgroundAudioManager::MxBackgroundAudioManager() m_unk0xa0 = 0; m_unk0x138 = 0; m_tickleState = MxPresenter::e_idle; - m_unk0x140 = 0; + m_speed = 0; m_targetVolume = 0; m_unk0x148 = 0; m_enabled = FALSE; @@ -128,8 +128,8 @@ void MxBackgroundAudioManager::FUN_1007ef40() volume = m_unk0x138->GetVolume(); if (volume < compare) { - if (m_unk0x140 + m_unk0x138->GetVolume() <= compare) { - compare = m_unk0x140 + m_unk0x138->GetVolume(); + if (m_speed + m_unk0x138->GetVolume() <= compare) { + compare = m_speed + m_unk0x138->GetVolume(); } m_unk0x138->SetVolume(compare); @@ -150,8 +150,8 @@ void MxBackgroundAudioManager::FUN_1007ef40() DeleteObject(*m_unk0xa0->GetAction()); } else { - if (m_unk0xa0->GetVolume() - m_unk0x140 > 0) { - volume = m_unk0xa0->GetVolume() - m_unk0x140; + if (m_unk0xa0->GetVolume() - m_speed > 0) { + volume = m_unk0xa0->GetVolume() - m_speed; } else { volume = 0; @@ -178,11 +178,11 @@ void MxBackgroundAudioManager::FadeInOrFadeOut() } if (volume < compare) { - volume = Min(volume + m_unk0x140, compare); + volume = Min(volume + m_speed, compare); m_unk0xa0->SetVolume(volume); } else if (compare < volume) { - volume = Max(volume - m_unk0x140, compare); + volume = Max(volume - m_speed, compare); m_unk0xa0->SetVolume(volume); } else { @@ -238,12 +238,15 @@ void MxBackgroundAudioManager::StopAction(MxParam& p_param) } // FUNCTION: LEGO1 0x1007f2f0 +// FUNCTION: BETA10 0x100e90fc MxResult MxBackgroundAudioManager::PlayMusic( MxDSAction& p_action, - undefined4 p_unk0x140, + undefined4 p_speed, MxPresenter::TickleState p_tickleState ) { + assert(p_speed > 0); + if (!m_enabled) { return SUCCESS; } @@ -267,7 +270,7 @@ MxResult MxBackgroundAudioManager::PlayMusic( if (result == SUCCESS) { m_tickleState = p_tickleState; - m_unk0x140 = p_unk0x140; + m_speed = p_speed; } return result; @@ -307,7 +310,7 @@ void MxBackgroundAudioManager::LowerVolume() if (m_tickleState == 0) { m_tickleState = MxPresenter::e_starting; } - m_unk0x140 = 20; + m_speed = 20; } m_unk0x148++; } @@ -321,7 +324,7 @@ void MxBackgroundAudioManager::RaiseVolume() if (m_tickleState == 0) { m_tickleState = MxPresenter::e_starting; } - m_unk0x140 = 10; + m_speed = 10; } } } @@ -342,7 +345,7 @@ void MxBackgroundAudioManager::Enable(MxBool p_enable) // FUNCTION: BETA10 0x100e95ee undefined4 MxBackgroundAudioManager::FUN_1007f610( MxPresenter* p_unk0x138, - MxS32 p_unk0x140, + MxS32 p_speed, MxPresenter::TickleState p_tickleState ) @@ -352,7 +355,7 @@ undefined4 MxBackgroundAudioManager::FUN_1007f610( ((MxCompositePresenter*) m_unk0x138)->VTable0x60(NULL); - m_unk0x140 = p_unk0x140; + m_speed = p_speed; m_tickleState = p_tickleState; return 0; } diff --git a/LEGO1/lego/legoomni/src/common/misc.cpp b/LEGO1/lego/legoomni/src/common/misc.cpp index 6c01313f..61399b00 100644 --- a/LEGO1/lego/legoomni/src/common/misc.cpp +++ b/LEGO1/lego/legoomni/src/common/misc.cpp @@ -63,8 +63,10 @@ LegoGameState* GameState() } // FUNCTION: LEGO1 0x10015770 +// FUNCTION: BETA10 0x100e4971 LegoAnimationManager* AnimationManager() { + assert(LegoOmni::GetInstance()); return LegoOmni::GetInstance()->GetAnimationManager(); } diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index 822121e6..f28134e9 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -42,15 +42,17 @@ LegoWorld::LegoWorld() : m_list0x68(TRUE) m_entityList = NULL; m_cacheSoundList = NULL; m_destroyed = FALSE; - m_hideAnimPresenter = NULL; + m_hideAnim = NULL; m_worldStarted = FALSE; NotificationManager()->Register(this); } // FUNCTION: LEGO1 0x1001d670 +// FUNCTION: BETA10 0x10017530 MxBool LegoWorld::VTable0x5c() { + // The BETA10 match could also be LegoWorld::Escape(), only the child classes might be able to tell return FALSE; } @@ -245,6 +247,7 @@ MxLong LegoWorld::Notify(MxParam& p_param) } // FUNCTION: LEGO1 0x1001f630 +// FUNCTION: BETA10 0x100d9fc2 LegoCameraController* LegoWorld::VTable0x54() { MxBool success = FALSE; @@ -413,6 +416,7 @@ MxResult LegoWorld::GetCurrPathInfo(LegoPathBoundary** p_boundaries, MxS32& p_nu } // FUNCTION: LEGO1 0x10020220 +// FUNCTION: BETA10 0x100da90b void LegoWorld::Add(MxCore* p_object) { if (p_object && !p_object->IsA("LegoWorld") && !p_object->IsA("LegoWorldPresenter")) { @@ -443,7 +447,8 @@ void LegoWorld::Add(MxCore* p_object) m_entityList->Append((LegoEntity*) p_object); } - else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { + else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || + p_object->IsA("LegoLoopingAnimPresenter")) { MxPresenterListCursor cursor(&m_animPresenters); if (cursor.Find((MxPresenter*) p_object)) { @@ -454,7 +459,7 @@ void LegoWorld::Add(MxCore* p_object) m_animPresenters.Append(((MxPresenter*) p_object)); if (p_object->IsA("LegoHideAnimPresenter")) { - m_hideAnimPresenter = (LegoHideAnimPresenter*) p_object; + m_hideAnim = (LegoHideAnimPresenter*) p_object; } } else if (p_object->IsA("LegoCacheSound")) { @@ -497,7 +502,8 @@ void LegoWorld::Remove(MxCore* p_object) ((MxControlPresenter*) p_object)->VTable0x68(TRUE); } } - else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { + else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || + p_object->IsA("LegoLoopingAnimPresenter")) { MxPresenterListCursor cursor(&m_animPresenters); if (cursor.Find((MxPresenter*) p_object)) { @@ -505,7 +511,7 @@ void LegoWorld::Remove(MxCore* p_object) } if (p_object->IsA("LegoHideAnimPresenter")) { - m_hideAnimPresenter = NULL; + m_hideAnim = NULL; } } else if (p_object->IsA("MxEntity")) { @@ -654,6 +660,7 @@ MxCore* LegoWorld::Find(const MxAtomId& p_atom, MxS32 p_entityId) } // FUNCTION: LEGO1 0x10021a70 +// FUNCTION: BETA10 0x100db758 void LegoWorld::Enable(MxBool p_enable) { if (p_enable && !m_set0xd0.empty()) { diff --git a/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp b/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp index 970402c8..e269f727 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathstruct.cpp @@ -19,6 +19,7 @@ DECOMP_SIZE_ASSERT(LegoPathStruct, 0x14) extern MxU32 g_isleFlags; // GLOBAL: LEGO1 0x100f119c +// GLOBAL: BETA10 0x100f119c MxBool g_unk0x100f119c = FALSE; // FUNCTION: LEGO1 0x1001b700 diff --git a/LEGO1/lego/legoomni/src/race/jetskirace.cpp b/LEGO1/lego/legoomni/src/race/jetskirace.cpp index 3b39e584..ba0cd4ea 100644 --- a/LEGO1/lego/legoomni/src/race/jetskirace.cpp +++ b/LEGO1/lego/legoomni/src/race/jetskirace.cpp @@ -1,28 +1,154 @@ #include "jetskirace.h" +#include "actions/jetrace_actions.h" +#include "actions/jetski_actions.h" +#include "actions/jukebox_actions.h" +#include "dunebuggy.h" +#include "isle.h" +#include "legoanimationmanager.h" +#include "legocontrolmanager.h" +#include "legohideanimpresenter.h" +#include "legomain.h" +#include "legopathstruct.h" +#include "legoracers.h" +#include "legoracespecial.h" +#include "legoutils.h" +#include "misc.h" +#include "mxactionnotificationparam.h" +#include "mxbackgroundaudiomanager.h" +#include "mxmisc.h" +#include "mxstillpresenter.h" +#include "mxtransitionmanager.h" +#include "mxvariabletable.h" +#include "scripts.h" + +// Defined in legopathstruct.cpp +extern MxBool g_unk0x100f119c; + +// Defined in jetski.cpp +extern const char* g_varJSFRNTY5; +extern const char* g_varJSWNSHY5; + +// Defined in legoracespecial.cpp +extern const char* g_raceState; +extern const char* g_racing; + +// Defined in legopathactor.cpp +extern const char* g_strHIT_WALL_SOUND; + DECOMP_SIZE_ASSERT(JetskiRace, 0x144) -// STUB: LEGO1 0x100162c0 +// FUNCTION: LEGO1 0x100162c0 +// FUNCTION: BETA10 0x100c7e6f MxResult JetskiRace::Create(MxDSAction& p_dsAction) { - return SUCCESS; + MxResult result = LegoRace::Create(p_dsAction); + + GameState()->m_currentArea = LegoGameState::e_jetrace; + GameState()->StopArea(LegoGameState::e_undefined); + LegoGameState* gameState = GameState(); + RaceState* jetskiRaceState = (RaceState*) gameState->GetState("JetskiRaceState"); + + if (!jetskiRaceState) { + jetskiRaceState = (RaceState*) gameState->CreateState("JetskiRaceState"); + } + + m_raceState = jetskiRaceState; + + if (!jetskiRaceState) { + return FAILURE; + } + + m_raceState->m_unk0x28 = 1; + m_unk0x130.SetLeft(397); + m_unk0x130.SetTop(317); + m_unk0x130.SetRight(543); + m_unk0x130.SetBottom(333); + LegoRaceCar::FUN_10013670(); + InvokeAction( + Extra::e_start, + m_atomId, + DuneBuggy::GetColorOffset(g_varJSFRNTY5) + (DuneBuggy::GetColorOffset(g_varJSWNSHY5) * 5 + 0xf) * 2, + NULL + ); + InvokeAction(Extra::e_start, m_atomId, JetraceScript::c_JetskiDashboard, NULL); + g_unk0x100f119c = TRUE; + + return result; } -// STUB: LEGO1 0x100163b0 +// FUNCTION: LEGO1 0x100163b0 +// FUNCTION: BETA10 0x100c7f10 void JetskiRace::ReadyWorld() { + assert(m_hideAnim); + LegoWorld::ReadyWorld(); + m_hideAnim->FUN_1006db40(0); + + MxDSAction action; + action.SetAtomId(*g_jukeboxScript); + action.SetObjectId(JukeboxScript::c_JetskiRace_Music); + BackgroundAudioManager()->PlayMusic(action, 5, MxPresenter::e_repeating); + + AnimationManager()->Resume(); + + m_unk0x128 = (MxStillPresenter*) Find("MxPresenter", "JetskiLocator2"); + m_unk0x128->SetPosition(m_unk0x130.GetLeft(), m_unk0x130.GetTop()); + m_unk0x12c = (MxStillPresenter*) Find("MxPresenter", "JetskiLocator3"); + m_unk0x12c->SetPosition(m_unk0x130.GetLeft(), m_unk0x130.GetTop()); + + FUN_10015820(FALSE, LegoOmni::c_disableInput | LegoOmni::c_disable3d | LegoOmni::c_clearScreen); + + VariableTable()->SetVariable("DISTANCE", "0.036"); + + InvokeAction(Extra::e_start, *g_jetraceScript, JetraceScript::c_AirHorn_PlayWav, NULL); } -// STUB: LEGO1 0x10016520 -MxLong JetskiRace::HandleEndAction(MxEndActionNotificationParam&) +// FUNCTION: LEGO1 0x10016520 +MxLong JetskiRace::HandleEndAction(MxEndActionNotificationParam& p_param) { - return 0; + MxLong result = 0; + + if ((p_param.GetAction()) && (p_param.GetAction()->GetObjectId() == JetraceScript::c_AirHorn_PlayWav)) { + m_unk0x110[0]->Mute(FALSE); + m_unk0x110[1]->Mute(FALSE); + m_unk0x110[2]->Mute(FALSE); + + VariableTable()->SetVariable(g_raceState, g_racing); + result = 1; + } + + return result; } -// STUB: LEGO1 0x100165a0 -MxLong JetskiRace::HandleClick(LegoEventNotificationParam&) +// FUNCTION: LEGO1 0x100165a0 +MxLong JetskiRace::HandleClick(LegoEventNotificationParam& p_param) { - return 0; + MxLong result = 0; + if (((LegoControlManagerNotificationParam*) &p_param)->m_unk0x28 == 1) { + switch (((LegoControlManagerNotificationParam*) &p_param)->m_clickedObjectId) { + case JetraceScript::c_JetskiArms_Ctl: + m_act1State->m_unk0x018 = 0; + VariableTable()->SetVariable(g_raceState, ""); + VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); + LegoRaceCar::FUN_10012de0(); + m_destLocation = LegoGameState::e_jetraceExterior; + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + break; + case JetraceScript::c_JetskiInfo_Ctl: + m_act1State->m_unk0x018 = 0; + VariableTable()->SetVariable(g_raceState, ""); + VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); + LegoRaceCar::FUN_10012de0(); + m_destLocation = LegoGameState::e_infomain; + result = 1; + TransitionManager()->StartTransition(MxTransitionManager::e_mosaic, 50, FALSE, FALSE); + break; + default: + break; + } + } + return result; } // STUB: LEGO1 0x100166a0 @@ -31,8 +157,15 @@ MxLong JetskiRace::HandlePathStruct(LegoPathStructNotificationParam&) return 0; } -// STUB: LEGO1 0x10016a10 +// FUNCTION: LEGO1 0x10016a10 MxBool JetskiRace::Escape() { + AnimationManager()->FUN_10061010(FALSE); + DeleteObjects(&m_atomId, 500, 999); + m_act1State->m_unk0x018 = 0; + VariableTable()->SetVariable(g_raceState, ""); + VariableTable()->SetVariable(g_strHIT_WALL_SOUND, ""); + m_destLocation = LegoGameState::e_infomain; + LegoRaceCar::FUN_10012de0(); return TRUE; } diff --git a/LEGO1/lego/legoomni/src/race/legorace.cpp b/LEGO1/lego/legoomni/src/race/legorace.cpp index f4cad9d0..2564f7a5 100644 --- a/LEGO1/lego/legoomni/src/race/legorace.cpp +++ b/LEGO1/lego/legoomni/src/race/legorace.cpp @@ -23,10 +23,10 @@ LegoRace::LegoRace() m_unk0x104 = 0; m_unk0x108 = 0; m_unk0x10c = 0; - m_unk0x140 = 0; - m_unk0x110 = 0; - m_unk0x114 = 0; - m_unk0x118 = 0; + m_raceState = NULL; + m_unk0x110[0] = NULL; + m_unk0x110[1] = NULL; + m_unk0x110[2] = NULL; m_unk0x128 = 0; m_unk0x12c = 0; m_pathActor = 0; @@ -54,6 +54,7 @@ MxBool LegoRace::Escape() } // FUNCTION: LEGO1 0x10015ce0 +// FUNCTION: BETA10 0x100c7a71 MxResult LegoRace::Create(MxDSAction& p_dsAction) { MxResult result = LegoWorld::Create(p_dsAction); @@ -150,6 +151,7 @@ RaceState::RaceState() } // FUNCTION: LEGO1 0x10016140 +// FUNCTION: BETA10 0x100c7d9f MxResult RaceState::Serialize(LegoFile* p_file) { LegoState::Serialize(p_file); diff --git a/LEGO1/lego/legoomni/src/race/legoracers.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp index 7a60d59c..472421ec 100644 --- a/LEGO1/lego/legoomni/src/race/legoracers.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -21,6 +21,12 @@ DECOMP_SIZE_ASSERT(EdgeReference, 0x08) DECOMP_SIZE_ASSERT(SkeletonKickPhase, 0x10) DECOMP_SIZE_ASSERT(LegoRaceCar, 0x200) +// GLOBAL: LEGO1 0x100f0bac +static undefined4 g_unk0x100f0bac = 0; + +// GLOBAL: LEGO1 0x100f0bb0 +static undefined4 g_unk0x100f0bb0 = 0; + // GLOBAL: LEGO1 0x100f0a20 // GLOBAL: BETA10 0x101f5e34 EdgeReference LegoRaceCar::g_skBMap[] = { @@ -166,6 +172,14 @@ MxLong LegoRaceCar::Notify(MxParam& p_param) return LegoRaceMap::Notify(p_param); } +// FUNCTION: LEGO1 0x10012de0 +void LegoRaceCar::FUN_10012de0() +{ + g_unk0x100f0b8c = TRUE; + g_timeLastSoundPlayed = 0; + g_unk0x100f0b88 = 0; +} + // FUNCTION: LEGO1 0x10012e60 // FUNCTION: BETA10 0x100cb191 void LegoRaceCar::SetWorldSpeed(MxFloat p_worldSpeed) @@ -513,6 +527,16 @@ MxResult LegoRaceCar::VTable0x9c() return result; } +// FUNCTION: LEGO1 0x10013670 +void LegoRaceCar::FUN_10013670() +{ + g_unk0x100f0bac = (rand() & 0xc) >> 2; + + // Inlining the `rand()` causes this function to mismatch + MxU32 uVar1 = rand(); + g_unk0x100f0bb0 = uVar1 % 0xc >> 2; +} + // FUNCTION: LEGO1 0x10014500 // FUNCTION: BETA10 0x100cd5e0 MxU32 LegoRaceCar::VTable0x6c( diff --git a/LEGO1/library_msvc.h b/LEGO1/library_msvc.h index c4a46848..f50de490 100644 --- a/LEGO1/library_msvc.h +++ b/LEGO1/library_msvc.h @@ -741,4 +741,7 @@ // LIBRARY: BETA10 0x1001d1a0 // `vector constructor iterator' +// LIBRARY: BETA10 0x100f8ad0 +// strcmp + #endif diff --git a/LEGO1/omni/include/mxentity.h b/LEGO1/omni/include/mxentity.h index cf16ad07..96348a65 100644 --- a/LEGO1/omni/include/mxentity.h +++ b/LEGO1/omni/include/mxentity.h @@ -18,6 +18,7 @@ class MxEntity : public MxCore { ~MxEntity() override {} // FUNCTION: LEGO1 0x1000c180 + // FUNCTION: BETA10 0x10012700 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0070 @@ -25,6 +26,7 @@ class MxEntity : public MxCore { } // FUNCTION: LEGO1 0x1000c190 + // FUNCTION: BETA10 0x10012610 MxBool IsA(const char* p_name) const override // vtable+0x10 { return !strcmp(p_name, MxEntity::ClassName()) || MxCore::IsA(p_name);