From 8026025fbdb6d89cd9659c1ab0fd68463cb144f8 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 8 Jan 2025 17:15:05 -0700 Subject: [PATCH 1/8] Improve `LegoRacers` `HitActor` matches (#1318) --- LEGO1/lego/legoomni/src/race/legoracers.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/LEGO1/lego/legoomni/src/race/legoracers.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp index f16a488c..14afc7f9 100644 --- a/LEGO1/lego/legoomni/src/race/legoracers.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -517,11 +517,12 @@ MxResult LegoRaceCar::HitActor(LegoPathActor* p_actor, MxBool p_bool) } } - if (p_bool && m_worldSpeed != 0) { - return SUCCESS; + if (p_bool) { + return m_worldSpeed != 0 ? SUCCESS : FAILURE; + } + else { + return FAILURE; } - - return FAILURE; } } @@ -717,11 +718,12 @@ MxResult LegoJetski::HitActor(LegoPathActor* p_actor, MxBool p_bool) } } - if (p_bool && m_worldSpeed != 0) { - return SUCCESS; + if (p_bool) { + return m_worldSpeed != 0 ? SUCCESS : FAILURE; + } + else { + return FAILURE; } - - return FAILURE; } } From 646ee0d70ac9ac36ef1d13cc16bd4fe3aed9506c Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 8 Jan 2025 17:15:29 -0700 Subject: [PATCH 2/8] Use `COMPAT_MODE` to fix inline function not defined warnings on modern compilers (#1315) * Use `COMPAT_MODE` to fix inline function not defined * Fix --- LEGO1/realtime/matrix.h | 4 ++++ LEGO1/realtime/vector.h | 6 ++++++ LEGO1/realtime/vector4d.inl.h | 3 +++ 3 files changed, 13 insertions(+) diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index c792f4da..307f4ce5 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -52,4 +52,8 @@ public: const float* operator[](int idx) const { return m_data[idx]; } }; +#ifdef COMPAT_MODE +#include "matrix4d.inl.h" +#endif + #endif // MATRIX_H diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index defaab57..3841783f 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -148,4 +148,10 @@ public: friend class Mx4DPointFloat; }; +#ifdef COMPAT_MODE +#include "vector2d.inl.h" +#include "vector3d.inl.h" +#include "vector4d.inl.h" +#endif + #endif // VECTOR_H diff --git a/LEGO1/realtime/vector4d.inl.h b/LEGO1/realtime/vector4d.inl.h index a94e8f09..7bfce62d 100644 --- a/LEGO1/realtime/vector4d.inl.h +++ b/LEGO1/realtime/vector4d.inl.h @@ -3,6 +3,9 @@ #include "vector.h" +#include +#include + // FUNCTION: LEGO1 0x10002870 void Vector4::AddImpl(const float* p_value) { From 5cd365c4f18f52cb76990d315840019813c4fe8c Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 8 Jan 2025 17:28:43 -0700 Subject: [PATCH 3/8] Order until the end of `LegoAnimActor` (#1319) --- LEGO1/lego/legoomni/src/actors/islepathactor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp index 4ae6272a..c1b5694a 100644 --- a/LEGO1/lego/legoomni/src/actors/islepathactor.cpp +++ b/LEGO1/lego/legoomni/src/actors/islepathactor.cpp @@ -19,9 +19,6 @@ DECOMP_SIZE_ASSERT(IslePathActor, 0x160) DECOMP_SIZE_ASSERT(IslePathActor::SpawnLocation, 0x38) -// GLOBAL: LEGO1 0x10102b28 -IslePathActor::SpawnLocation g_spawnLocations[IslePathActor::c_LOCATIONS_NUM]; - // FUNCTION: LEGO1 0x1001a200 IslePathActor::IslePathActor() { @@ -157,6 +154,9 @@ void IslePathActor::Exit() FUN_1003eda0(); } +// GLOBAL: LEGO1 0x10102b28 +IslePathActor::SpawnLocation g_spawnLocations[IslePathActor::c_LOCATIONS_NUM]; + // FUNCTION: LEGO1 0x1001a700 void IslePathActor::RegisterSpawnLocations() { From 58d3bd39e197d06531e20cce581dcf4e5f3eea5a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Wed, 8 Jan 2025 17:36:54 -0700 Subject: [PATCH 4/8] Add missing `SpawnLocation` ctor annotation (#1320) --- LEGO1/lego/legoomni/include/islepathactor.h | 1 + 1 file changed, 1 insertion(+) diff --git a/LEGO1/lego/legoomni/include/islepathactor.h b/LEGO1/lego/legoomni/include/islepathactor.h index 70a58702..e3a8bd37 100644 --- a/LEGO1/lego/legoomni/include/islepathactor.h +++ b/LEGO1/lego/legoomni/include/islepathactor.h @@ -28,6 +28,7 @@ public: // SIZE 0x38 struct SpawnLocation { + // FUNCTION: LEGO1 0x1001a6f0 SpawnLocation() {} // FUNCTION: LEGO1 0x1001b1b0 From ee2bcb4d531495cf9f41dfd4c7c82e873b729d36 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Thu, 9 Jan 2025 17:31:45 -0700 Subject: [PATCH 5/8] Order symbols in `LegoWorld` (#1321) * Partially order `LegoWorld` symbols * Further order `LegoWorld` --- LEGO1/lego/legoomni/include/legoworld.h | 44 ++++++++++++-------- LEGO1/lego/legoomni/src/entity/legoworld.cpp | 16 ------- LEGO1/omni/include/mxcollection.h | 7 ++-- LEGO1/omni/include/mxlist.h | 9 +--- 4 files changed, 31 insertions(+), 45 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index 9845e451..5a89c5aa 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -1,15 +1,18 @@ #ifndef LEGOWORLD_H #define LEGOWORLD_H +// clang-format off +#include "mxpresenterlist.h" +#include "legoentitylist.h" +#include "legocachesoundlist.h" +// clang-format on + #include "legoentity.h" #include "legomain.h" #include "legopathcontrollerlist.h" -#include "mxpresenterlist.h" #include "roi/legoroi.h" -class LegoCacheSoundList; class LegoCameraController; -class LegoEntityList; class LegoPathBoundary; class LegoHideAnimPresenter; @@ -44,8 +47,26 @@ public: LegoWorld(); ~LegoWorld() override; // vtable+0x00 - MxLong Notify(MxParam& p_param) override; // vtable+0x04 - MxResult Tickle() override; // vtable+0x08 + MxLong Notify(MxParam& p_param) override; // vtable+0x04 + MxResult Tickle() override; // vtable+0x08 + MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 + void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c + virtual void ReadyWorld(); // vtable+0x50 + virtual LegoCameraController* VTable0x54(); // vtable+0x54 + virtual void Add(MxCore* p_object); // vtable+0x58 + + // The BETA10 match could also be LegoWorld::Escape(), only the child classes might be able to tell + // FUNCTION: LEGO1 0x1001d670 + // FUNCTION: BETA10 0x10017530 + virtual MxBool VTable0x5c() { return FALSE; } // vtable+0x5c + + // FUNCTION: LEGO1 0x100010a0 + virtual void VTable0x60() {} // vtable+0x60 + + // FUNCTION: LEGO1 0x1001d680 + virtual MxBool Escape() { return FALSE; } // vtable+0x64 + + virtual void Enable(MxBool p_enable); // vtable+0x68 // FUNCTION: LEGO1 0x1001d690 // FUNCTION: BETA10 0x10017660 @@ -62,19 +83,6 @@ public: return !strcmp(p_name, LegoWorld::ClassName()) || LegoEntity::IsA(p_name); } - MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 - void Destroy(MxBool p_fromDestructor) override; // vtable+0x1c - virtual void ReadyWorld(); // vtable+0x50 - virtual LegoCameraController* VTable0x54(); // vtable+0x54 - virtual void Add(MxCore* p_object); // vtable+0x58 - virtual MxBool VTable0x5c(); // vtable+0x5c - - // FUNCTION: LEGO1 0x100010a0 - virtual void VTable0x60() {} // vtable+0x60 - - virtual MxBool Escape(); // vtable+0x64 - virtual void Enable(MxBool p_enable); // vtable+0x68 - MxBool PresentersPending(); void Remove(MxCore* p_object); MxResult PlaceActor( diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index e00d4365..658dc5fa 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -4,11 +4,9 @@ #include "legoanimationmanager.h" #include "legoanimpresenter.h" #include "legobuildingmanager.h" -#include "legocachesoundlist.h" #include "legocachesoundmanager.h" #include "legocameracontroller.h" #include "legocontrolmanager.h" -#include "legoentitylist.h" #include "legogamestate.h" #include "legoinputmanager.h" #include "legolocomotionanimpresenter.h" @@ -47,20 +45,6 @@ LegoWorld::LegoWorld() : m_list0x68(TRUE) 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; -} - -// FUNCTION: LEGO1 0x1001d680 -MxBool LegoWorld::Escape() -{ - return FALSE; -} - // FUNCTION: LEGO1 0x1001dfa0 LegoWorld::~LegoWorld() { diff --git a/LEGO1/omni/include/mxcollection.h b/LEGO1/omni/include/mxcollection.h index 0c21438c..7c008e49 100644 --- a/LEGO1/omni/include/mxcollection.h +++ b/LEGO1/omni/include/mxcollection.h @@ -12,13 +12,14 @@ public: SetDestroy(Destroy); } + virtual MxS8 Compare(T, T) { return 0; } // vtable+0x14 + + ~MxCollection() override {} + static void Destroy(T) {} void SetDestroy(void (*p_customDestructor)(T)) { this->m_customDestructor = p_customDestructor; } - ~MxCollection() override {} - virtual MxS8 Compare(T, T) { return 0; } - protected: MxU32 m_count; // 0x08 void (*m_customDestructor)(T); // 0x0c diff --git a/LEGO1/omni/include/mxlist.h b/LEGO1/omni/include/mxlist.h index b020eeb3..6ab165e2 100644 --- a/LEGO1/omni/include/mxlist.h +++ b/LEGO1/omni/include/mxlist.h @@ -46,8 +46,7 @@ template class MxList : protected MxCollection { public: MxList() { m_first = m_last = NULL; } - - ~MxList() override; + ~MxList() override { DeleteAll(); } void Append(T p_obj) { InsertEntry(p_obj, this->m_last, NULL); } void Prepend(T p_obj) { InsertEntry(p_obj, NULL, this->m_first); } @@ -127,12 +126,6 @@ public: MxPtrListCursor(MxPtrList* p_list) : MxListCursor(p_list) {} }; -template -MxList::~MxList() -{ - DeleteAll(); -} - // Delete entries and values template inline void MxList::DeleteAll() From ac3a551bcc234f5b239784dd0666a906640d07dd Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 10 Jan 2025 17:42:03 -0700 Subject: [PATCH 6/8] Improve symbol order until `LegoActor`, match `LegoPlantManager::ScheduleAnimation` (#1327) * Order `LegoCarBuild`, `LegoPlantManager` * Order until `LegoActor` --- CMakeLists.txt | 4 +- LEGO1/lego/legoomni/include/legocarbuild.h | 5 +- LEGO1/lego/legoomni/include/legoextraactor.h | 109 +++++++++++++++++- LEGO1/lego/legoomni/include/radio.h | 5 +- LEGO1/lego/legoomni/src/actors/radio.cpp | 6 - .../lego/legoomni/src/build/legocarbuild.cpp | 7 -- .../src/common/legobuildingmanager.cpp | 1 - .../legoomni/src/common/legoplantmanager.cpp | 6 +- .../legoomni/src/paths/legoextraactor.cpp | 103 ----------------- 9 files changed, 120 insertions(+), 126 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 69a2f5ff..2fc4a4ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -321,11 +321,9 @@ function(add_lego_libraries NAME) LEGO1/lego/legoomni/src/paths/legoanimactor.cpp LEGO1/lego/legoomni/src/entity/legoworld.cpp LEGO1/lego/legoomni/src/build/legocarbuild.cpp - LEGO1/lego/legoomni/src/actors/ambulance.cpp LEGO1/lego/legoomni/src/common/legoplantmanager.cpp LEGO1/lego/legoomni/src/actors/bumpbouy.cpp LEGO1/modeldb/modeldb.cpp - LEGO1/lego/legoomni/src/actors/pizza.cpp LEGO1/lego/legoomni/src/actors/racecar.cpp LEGO1/lego/legoomni/src/control/legocontrolmanager.cpp LEGO1/lego/legoomni/src/audio/legosoundmanager.cpp @@ -336,6 +334,8 @@ function(add_lego_libraries NAME) LEGO1/lego/legoomni/src/paths/legopathactor.cpp LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp LEGO1/lego/legoomni/src/worlds/isle.cpp + LEGO1/lego/legoomni/src/actors/ambulance.cpp + LEGO1/lego/legoomni/src/actors/pizza.cpp LEGO1/lego/legoomni/src/actors/motorcycle.cpp LEGO1/lego/legoomni/src/actors/act3ammo.cpp LEGO1/lego/legoomni/src/audio/legocachesoundmanager.cpp diff --git a/LEGO1/lego/legoomni/include/legocarbuild.h b/LEGO1/lego/legoomni/include/legocarbuild.h index 6be5f567..6add3be3 100644 --- a/LEGO1/lego/legoomni/include/legocarbuild.h +++ b/LEGO1/lego/legoomni/include/legocarbuild.h @@ -91,6 +91,10 @@ public: LegoCarBuild(); ~LegoCarBuild() override; + // FUNCTION: LEGO1 0x10022930 + // FUNCTION: BETA10 0x10070070 + MxBool VTable0x5c() override { return TRUE; } // vtable+0x5c + // FUNCTION: LEGO1 0x10022940 // FUNCTION: BETA10 0x10070090 const char* ClassName() const override // vtable+0x0c @@ -110,7 +114,6 @@ public: MxResult Create(MxDSAction& p_dsAction) override; // vtable+0x18 void ReadyWorld() override; // vtable+0x50 - MxBool VTable0x5c() override; // vtable+0x5c MxBool Escape() override; // vtable+0x64 void Enable(MxBool p_enable) override; // vtable+0x68 virtual void VTable0x6c(); // vtable+0x6c diff --git a/LEGO1/lego/legoomni/include/legoextraactor.h b/LEGO1/lego/legoomni/include/legoextraactor.h index 8c354a59..5f930820 100644 --- a/LEGO1/lego/legoomni/include/legoextraactor.h +++ b/LEGO1/lego/legoomni/include/legoextraactor.h @@ -2,6 +2,7 @@ #define LEGOEXTRAACTOR_H #include "legoanimactor.h" +#include "legopathboundary.h" // VTABLE: LEGO1 0x100d6c00 LegoAnimActor // VTABLE: LEGO1 0x100d6c10 LegoPathActor @@ -36,9 +37,9 @@ public: return !strcmp(p_name, LegoExtraActor::ClassName()) || LegoAnimActor::IsA(p_name); } - void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - MxS32 VTable0x68(Vector3&, Vector3&, Vector3&) override; // vtable+0x68 - MxU32 VTable0x6c( + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + MxS32 VTable0x68(Vector3& p_point1, Vector3& p_point2, Vector3& p_point3) override; // vtable+0x68 + inline MxU32 VTable0x6c( LegoPathBoundary* p_boundary, Vector3& p_v1, Vector3& p_v2, @@ -77,6 +78,108 @@ private: LegoAnimActorStruct* m_disAnim; // 0x64 }; +// FUNCTION: LEGO1 0x1002b980 +inline MxU32 LegoExtraActor::VTable0x6c( + LegoPathBoundary* p_boundary, + Vector3& p_v1, + Vector3& p_v2, + float p_f1, + float p_f2, + Vector3& p_v3 +) +{ + LegoAnimPresenterSet& presenters = p_boundary->GetPresenters(); + + for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) { + if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) { + return 1; + } + } + + LegoPathActorSet& plpas = p_boundary->GetActors(); + LegoPathActorSet lpas(plpas); + + for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) { + if (plpas.find(*itpa) != plpas.end()) { + LegoPathActor* actor = *itpa; + + if (this != actor && !(actor->GetActorState() & LegoPathActor::c_noCollide)) { + LegoROI* roi = actor->GetROI(); + + if ((roi != NULL && roi->GetVisibility()) || actor->GetCameraFlag()) { + if (actor->GetUserNavFlag()) { + MxMatrix local2world = roi->GetLocal2World(); + Vector3 local60(local2world[3]); + Mx3DPointFloat local54(p_v1); + + local54 -= local60; + float local1c = p_v2.Dot(p_v2, p_v2); + float local24 = p_v2.Dot(p_v2, local54) * 2.0f; + float local20 = local54.Dot(local54, local54); + + if (m_unk0x15 != 0 && local20 < 10.0f) { + return 0; + } + + local20 -= 1.0f; + + if (local1c >= 0.001 || local1c <= -0.001) { + float local40 = (local24 * local24) + (local20 * local1c * -4.0f); + + if (local40 >= -0.001) { + local1c *= 2.0f; + local24 = -local24; + + if (local40 < 0.0f) { + local40 = 0.0f; + } + + local40 = sqrt(local40); + float local20X = (local24 + local40) / local1c; + float local1cX = (local24 - local40) / local1c; + + if (local1cX < local20X) { + local40 = local20X; + local20X = local1cX; + local1cX = local40; + } + + if ((local20X >= 0.0f && local20X <= p_f1) || (local1cX >= 0.0f && local1cX <= p_f1) || + (local20X <= -0.01 && p_f1 + 0.01 <= local1cX)) { + p_v3 = p_v1; + + if (HitActor(actor, TRUE) < 0) { + return 0; + } + + actor->HitActor(this, FALSE); + return 2; + } + } + } + } + else { + if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { + if (HitActor(actor, TRUE) < 0) { + return 0; + } + + actor->HitActor(this, FALSE); + return 2; + } + } + } + } + } + } + + if (m_unk0x15 != 0) { + m_unk0x15--; + } + + return 0; +} + // GLOBAL: LEGO1 0x100d6be8 // LegoExtraActor::`vbtable'{for `LegoAnimActor'} diff --git a/LEGO1/lego/legoomni/include/radio.h b/LEGO1/lego/legoomni/include/radio.h index 87934c47..9ff8cb9c 100644 --- a/LEGO1/lego/legoomni/include/radio.h +++ b/LEGO1/lego/legoomni/include/radio.h @@ -15,6 +15,9 @@ class RadioState : public LegoState { public: RadioState(); + // FUNCTION: LEGO1 0x1002cf50 + MxBool IsSerializable() override { return FALSE; } // vtable+0x14 + // FUNCTION: LEGO1 0x1002cf60 // FUNCTION: BETA10 0x100f2850 const char* ClassName() const override // vtable+0x0c @@ -29,8 +32,6 @@ public: return !strcmp(p_name, RadioState::ClassName()) || LegoState::IsA(p_name); } - MxBool IsSerializable() override; // vtable+0x14 - // SYNTHETIC: LEGO1 0x1002d020 // RadioState::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/src/actors/radio.cpp b/LEGO1/lego/legoomni/src/actors/radio.cpp index 4b84a430..0291c18c 100644 --- a/LEGO1/lego/legoomni/src/actors/radio.cpp +++ b/LEGO1/lego/legoomni/src/actors/radio.cpp @@ -228,12 +228,6 @@ RadioState::RadioState() m_active = FALSE; } -// FUNCTION: LEGO1 0x1002cf50 -MxBool RadioState::IsSerializable() -{ - return FALSE; -} - // FUNCTION: LEGO1 0x1002d090 MxU32 RadioState::FUN_1002d090() { diff --git a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp index 61f6fc15..c65064c1 100644 --- a/LEGO1/lego/legoomni/src/build/legocarbuild.cpp +++ b/LEGO1/lego/legoomni/src/build/legocarbuild.cpp @@ -130,13 +130,6 @@ LegoCarBuild::LegoCarBuild() NotificationManager()->Register(this); } -// FUNCTION: LEGO1 0x10022930 -// FUNCTION: BETA10 0x10070070 -MxBool LegoCarBuild::VTable0x5c() -{ - return TRUE; -} - // FUNCTION: LEGO1 0x10022a80 // FUNCTION: BETA10 0x1006aea3 LegoCarBuild::~LegoCarBuild() diff --git a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp index 53544ef9..2d97b3ef 100644 --- a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp @@ -661,7 +661,6 @@ MxBool LegoBuildingManager::FUN_10030110(LegoBuildingInfo* p_data) } // FUNCTION: LEGO1 0x10030150 -// FUNCTION: BETA10 0x100644ff void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_length, MxBool p_haveSound, MxBool p_unk0x28) { m_world = CurrentWorld(); diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 2e7b0491..c7a821ae 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -618,7 +618,11 @@ void LegoPlantManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_length) entry->m_entity = p_entity; entry->m_roi = p_entity->GetROI(); - entry->m_time = Timer()->GetTime() + p_length + 1000; + + MxLong time = Timer()->GetTime(); + time += p_length; + entry->m_time = time + 1000; + FUN_100271b0(p_entity, -1); } diff --git a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp index ee83769e..2c2bd166 100644 --- a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp @@ -3,7 +3,6 @@ #include "anim/legoanim.h" #include "legocachesoundmanager.h" #include "legolocomotionanimpresenter.h" -#include "legopathboundary.h" #include "legosoundmanager.h" #include "legoworld.h" #include "misc.h" @@ -421,105 +420,3 @@ MxS32 LegoExtraActor::VTable0x68(Vector3& p_point1, Vector3& p_point2, Vector3& { return LegoPathActor::VTable0x68(p_point1, p_point2, p_point3); } - -// FUNCTION: LEGO1 0x1002b980 -MxU32 LegoExtraActor::VTable0x6c( - LegoPathBoundary* p_boundary, - Vector3& p_v1, - Vector3& p_v2, - float p_f1, - float p_f2, - Vector3& p_v3 -) -{ - LegoAnimPresenterSet& presenters = p_boundary->GetPresenters(); - - for (LegoAnimPresenterSet::iterator itap = presenters.begin(); itap != presenters.end(); itap++) { - if ((*itap)->VTable0x94(p_v1, p_v2, p_f1, p_f2, p_v3)) { - return 1; - } - } - - LegoPathActorSet& plpas = p_boundary->GetActors(); - LegoPathActorSet lpas(plpas); - - for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) { - if (plpas.find(*itpa) != plpas.end()) { - LegoPathActor* actor = *itpa; - - if (this != actor && !(actor->GetActorState() & LegoPathActor::c_noCollide)) { - LegoROI* roi = actor->GetROI(); - - if ((roi != NULL && roi->GetVisibility()) || actor->GetCameraFlag()) { - if (actor->GetUserNavFlag()) { - MxMatrix local2world = roi->GetLocal2World(); - Vector3 local60(local2world[3]); - Mx3DPointFloat local54(p_v1); - - local54 -= local60; - float local1c = p_v2.Dot(p_v2, p_v2); - float local24 = p_v2.Dot(p_v2, local54) * 2.0f; - float local20 = local54.Dot(local54, local54); - - if (m_unk0x15 != 0 && local20 < 10.0f) { - return 0; - } - - local20 -= 1.0f; - - if (local1c >= 0.001 || local1c <= -0.001) { - float local40 = (local24 * local24) + (local20 * local1c * -4.0f); - - if (local40 >= -0.001) { - local1c *= 2.0f; - local24 = -local24; - - if (local40 < 0.0f) { - local40 = 0.0f; - } - - local40 = sqrt(local40); - float local20X = (local24 + local40) / local1c; - float local1cX = (local24 - local40) / local1c; - - if (local1cX < local20X) { - local40 = local20X; - local20X = local1cX; - local1cX = local40; - } - - if ((local20X >= 0.0f && local20X <= p_f1) || (local1cX >= 0.0f && local1cX <= p_f1) || - (local20X <= -0.01 && p_f1 + 0.01 <= local1cX)) { - p_v3 = p_v1; - - if (HitActor(actor, TRUE) < 0) { - return 0; - } - - actor->HitActor(this, FALSE); - return 2; - } - } - } - } - else { - if (roi->FUN_100a9410(p_v1, p_v2, p_f1, p_f2, p_v3, m_collideBox && actor->GetCollideBox())) { - if (HitActor(actor, TRUE) < 0) { - return 0; - } - - actor->HitActor(this, FALSE); - return 2; - } - } - } - } - } - } - - if (m_unk0x15 != 0) { - m_unk0x15--; - } - - return 0; -} From 4d3481d2bd6514d3bef6dd4745c3043a81f3a471 Mon Sep 17 00:00:00 2001 From: MS Date: Sat, 11 Jan 2025 10:51:02 -0500 Subject: [PATCH 7/8] LegoWorld::Add to 100% (#1328) --- LEGO1/lego/legoomni/include/legoworld.h | 3 +- LEGO1/lego/legoomni/src/entity/legoworld.cpp | 301 +++++++++++-------- 2 files changed, 170 insertions(+), 134 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index 5a89c5aa..cdb67e4a 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -184,7 +184,8 @@ protected: // TEMPLATE: LEGO1 0x10020b20 // _Tree >::_Kfn,CoreSetCompare,allocator >::iterator::_Dec -// XTEMPLATE LEGO1 0x10020b70 +// TEMPLATE: LEGO1 0x10020b70 +// _Tree >::_Kfn,CoreSetCompare,allocator >::lower_bound // TEMPLATE: LEGO1 0x10020bb0 // _Tree >::_Kfn,CoreSetCompare,allocator >::_Buynode diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index 658dc5fa..0781c4b3 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -402,68 +402,88 @@ MxResult LegoWorld::GetCurrPathInfo(LegoPathBoundary** p_boundaries, MxS32& p_nu // FUNCTION: BETA10 0x100da90b void LegoWorld::Add(MxCore* p_object) { - if (p_object && !p_object->IsA("LegoWorld") && !p_object->IsA("LegoWorldPresenter")) { - if (p_object->IsA("LegoAnimPresenter")) { - LegoAnimPresenter* animPresenter = (LegoAnimPresenter*) p_object; + if (p_object == NULL || p_object->IsA("LegoWorld") || p_object->IsA("LegoWorldPresenter")) { + return; + } - if (!strcmpi(animPresenter->GetAction()->GetObjectName(), "ConfigAnimation")) { - FUN_1003e050(animPresenter); - animPresenter->GetAction()->SetDuration(animPresenter->GetAnimation()->GetDuration()); - } +#ifndef BETA10 + if (p_object->IsA("LegoAnimPresenter")) { + if (!strcmpi(((LegoAnimPresenter*) p_object)->GetAction()->GetObjectName(), "ConfigAnimation")) { + FUN_1003e050((LegoAnimPresenter*) p_object); + ((LegoAnimPresenter*) p_object) + ->GetAction() + ->SetDuration(((LegoAnimPresenter*) p_object)->GetAnimation()->GetDuration()); + } + } +#endif + + if (p_object->IsA("MxControlPresenter")) { + MxPresenterListCursor cursor(&m_controlPresenters); + + if (cursor.Find((MxPresenter*) p_object)) { + assert(0); + return; } - if (p_object->IsA("MxControlPresenter")) { - MxPresenterListCursor cursor(&m_controlPresenters); + m_controlPresenters.Append((MxPresenter*) p_object); + } + else if (p_object->IsA("MxEntity")) { + LegoEntityListCursor cursor(m_entityList); - if (cursor.Find((MxPresenter*) p_object)) { - return; - } - - m_controlPresenters.Append((MxPresenter*) p_object); + if (cursor.Find((LegoEntity*) p_object)) { + assert(0); + return; } - else if (p_object->IsA("MxEntity")) { - LegoEntityListCursor cursor(m_entityList); - if (cursor.Find((LegoEntity*) p_object)) { - return; - } + m_entityList->Append((LegoEntity*) p_object); + } + else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { + MxPresenterListCursor cursor(&m_animPresenters); - m_entityList->Append((LegoEntity*) p_object); + if (cursor.Find((MxPresenter*) p_object)) { + assert(0); + return; } - else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { - MxPresenterListCursor cursor(&m_animPresenters); - if (cursor.Find((MxPresenter*) p_object)) { - return; - } + ((MxPresenter*) p_object)->SendToCompositePresenter(Lego()); + m_animPresenters.Append(((MxPresenter*) p_object)); - ((MxPresenter*) p_object)->SendToCompositePresenter(Lego()); - m_animPresenters.Append(((MxPresenter*) p_object)); - - if (p_object->IsA("LegoHideAnimPresenter")) { - m_hideAnim = (LegoHideAnimPresenter*) p_object; - } + if (p_object->IsA("LegoHideAnimPresenter")) { + m_hideAnim = (LegoHideAnimPresenter*) p_object; } - else if (p_object->IsA("LegoCacheSound")) { - LegoCacheSoundListCursor cursor(m_cacheSoundList); + } +#ifndef BETA10 + else if (p_object->IsA("LegoCacheSound")) { + LegoCacheSoundListCursor cursor(m_cacheSoundList); - if (cursor.Find((LegoCacheSound*) p_object)) { - return; + if (cursor.Find((LegoCacheSound*) p_object)) { + assert(0); // ? + return; + } + + m_cacheSoundList->Append((LegoCacheSound*) p_object); + } +#endif + else { + MxCoreSet::iterator it = m_set0xa8.find(p_object); + if (it == m_set0xa8.end()) { +#ifdef BETA10 + if (p_object->IsA("MxPresenter")) { + assert(static_cast(p_object)->GetAction()); } +#endif - m_cacheSoundList->Append((LegoCacheSound*) p_object); + m_set0xa8.insert(p_object); } else { - if (m_set0xa8.find(p_object) == m_set0xa8.end()) { - m_set0xa8.insert(p_object); - } + assert(0); } + } - if (!m_set0xd0.empty() && p_object->IsA("MxPresenter")) { - if (((MxPresenter*) p_object)->IsEnabled()) { - ((MxPresenter*) p_object)->Enable(FALSE); - m_set0xd0.insert(p_object); - } + if (m_set0xd0.size() != 0 && p_object->IsA("MxPresenter")) { + if (((MxPresenter*) p_object)->IsEnabled()) { + ((MxPresenter*) p_object)->Enable(FALSE); + m_set0xd0.insert(p_object); } } } @@ -472,61 +492,65 @@ void LegoWorld::Add(MxCore* p_object) // FUNCTION: BETA10 0x100dad2a void LegoWorld::Remove(MxCore* p_object) { - if (p_object) { - MxCoreSet::iterator it; + MxCoreSet::iterator it; - if (p_object->IsA("MxControlPresenter")) { - MxPresenterListCursor cursor(&m_controlPresenters); + if (p_object == NULL) { + return; + } - if (cursor.Find((MxControlPresenter*) p_object)) { - cursor.Detach(); - ((MxControlPresenter*) p_object)->GetAction()->SetOrigin(Lego()); - ((MxControlPresenter*) p_object)->VTable0x68(TRUE); - } + if (p_object->IsA("MxControlPresenter")) { + MxPresenterListCursor cursor(&m_controlPresenters); + + if (cursor.Find((MxControlPresenter*) p_object)) { + cursor.Detach(); + ((MxControlPresenter*) p_object)->GetAction()->SetOrigin(Lego()); + ((MxControlPresenter*) p_object)->VTable0x68(TRUE); } - else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { - MxPresenterListCursor cursor(&m_animPresenters); + } + else if (p_object->IsA("LegoLocomotionAnimPresenter") || p_object->IsA("LegoHideAnimPresenter") || p_object->IsA("LegoLoopingAnimPresenter")) { + MxPresenterListCursor cursor(&m_animPresenters); - if (cursor.Find((MxPresenter*) p_object)) { - cursor.Detach(); - } - - if (p_object->IsA("LegoHideAnimPresenter")) { - m_hideAnim = NULL; - } + if (cursor.Find((MxPresenter*) p_object)) { + cursor.Detach(); } - else if (p_object->IsA("MxEntity")) { - if (p_object->IsA("LegoPathActor")) { - RemoveActor((LegoPathActor*) p_object); - } - if (m_entityList) { - LegoEntityListCursor cursor(m_entityList); - - if (cursor.Find((LegoEntity*) p_object)) { - cursor.Detach(); - } - } + if (p_object->IsA("LegoHideAnimPresenter")) { + m_hideAnim = NULL; + } + } + else if (p_object->IsA("MxEntity")) { + if (p_object->IsA("LegoPathActor")) { + RemoveActor((LegoPathActor*) p_object); } - else if (p_object->IsA("LegoCacheSound")) { - LegoCacheSoundListCursor cursor(m_cacheSoundList); - if (cursor.Find((LegoCacheSound*) p_object)) { + if (m_entityList) { + LegoEntityListCursor cursor(m_entityList); + + if (cursor.Find((LegoEntity*) p_object)) { cursor.Detach(); } } - else { - it = m_set0xa8.find(p_object); - if (it != m_set0xa8.end()) { - m_set0xa8.erase(it); - } - } + } +#ifndef BETA10 + else if (p_object->IsA("LegoCacheSound")) { + LegoCacheSoundListCursor cursor(m_cacheSoundList); - it = m_set0xd0.find(p_object); - if (it != m_set0xd0.end()) { - m_set0xd0.erase(it); + if (cursor.Find((LegoCacheSound*) p_object)) { + cursor.Detach(); } } +#endif + else { + it = m_set0xa8.find(p_object); + if (it != m_set0xa8.end()) { + m_set0xa8.erase(it); + } + } + + it = m_set0xd0.find(p_object); + if (it != m_set0xd0.end()) { + m_set0xd0.erase(it); + } } // FUNCTION: LEGO1 0x100213a0 @@ -643,57 +667,66 @@ MxCore* LegoWorld::Find(const MxAtomId& p_atom, MxS32 p_entityId) // FUNCTION: BETA10 0x100db758 void LegoWorld::Enable(MxBool p_enable) { - if (p_enable && !m_set0xd0.empty()) { - if (CurrentWorld() != this) { - if (CurrentWorld()) { - AnimationManager()->FUN_10061010(FALSE); - CurrentWorld()->Enable(FALSE); + MxCoreSet::iterator it; - LegoEntityListCursor cursor(m_entityList); - LegoEntity* entity; - - while (cursor.Next(entity)) { - if (entity->GetROI()) { - entity->GetROI()->SetEntity(entity); - GetViewManager()->Add(entity->GetROI()); - } - } - } - - while (!m_set0xd0.empty()) { - MxCoreSet::iterator it = m_set0xd0.begin(); - - if ((*it)->IsA("MxPresenter")) { - ((MxPresenter*) *it)->Enable(TRUE); - } - else if ((*it)->IsA("LegoPathController")) { - ((LegoPathController*) *it)->Enable(TRUE); - } - - m_set0xd0.erase(it); - } - - SetCurrentWorld(this); - ControlManager()->FUN_10028df0(&m_controlPresenters); - InputManager()->SetCamera(m_cameraController); - - if (m_cameraController) { - InputManager()->Register(m_cameraController->GetNavController()); - Lego()->SetNavController(m_cameraController->GetNavController()); - } - - if (m_worldId != LegoOmni::e_undefined) { - PlantManager()->LoadWorldInfo(m_worldId); - AnimationManager()->LoadWorldInfo(m_worldId); - BuildingManager()->LoadWorldInfo(); - AnimationManager()->Resume(); - } - - GameState()->ResetROI(); - SetIsWorldActive(TRUE); + if (p_enable && m_set0xd0.size() != 0) { + if (CurrentWorld() == this) { + return; } + if (CurrentWorld()) { + AnimationManager()->FUN_10061010(FALSE); + CurrentWorld()->Enable(FALSE); + + LegoEntityListCursor cursor(m_entityList); + LegoEntity* entity; + + while (cursor.Next(entity)) { + assert(entity->GetROI()); + + if (entity->GetROI()) { +#ifndef BETA10 + entity->GetROI()->SetEntity(entity); +#endif + GetViewManager()->Add(entity->GetROI()); + } + } + } + + while (m_set0xd0.size() != 0) { + it = m_set0xd0.begin(); + + if ((*it)->IsA("MxPresenter")) { + ((MxPresenter*) *it)->Enable(TRUE); + } + else if ((*it)->IsA("LegoPathController")) { + ((LegoPathController*) *it)->Enable(TRUE); + } + + m_set0xd0.erase(it); + } + + SetCurrentWorld(this); + ControlManager()->FUN_10028df0(&m_controlPresenters); + InputManager()->SetCamera(m_cameraController); + + if (m_cameraController) { + InputManager()->Register(m_cameraController->GetNavController()); + Lego()->SetNavController(m_cameraController->GetNavController()); + } + + if (m_worldId != LegoOmni::e_undefined) { + PlantManager()->LoadWorldInfo(m_worldId); + AnimationManager()->LoadWorldInfo(m_worldId); + BuildingManager()->LoadWorldInfo(); + AnimationManager()->Resume(); + } + + GameState()->ResetROI(); +#ifndef BETA10 + SetIsWorldActive(TRUE); +#endif } - else if (!p_enable && m_set0xd0.empty()) { + else if (!p_enable && m_set0xd0.size() != 0) { MxPresenter* presenter; LegoPathController* controller; LegoPathActor* actor = UserActor(); @@ -707,7 +740,9 @@ void LegoWorld::Enable(MxBool p_enable) if (m_worldId != LegoOmni::e_undefined) { PlantManager()->Reset(m_worldId); +#ifndef BETA10 BuildingManager()->Reset(); +#endif } MxPresenterListCursor controlPresenterCursor(&m_controlPresenters); From 33d8192d75587f85e31505b860ba839b22ba562a Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sat, 11 Jan 2025 09:55:19 -0700 Subject: [PATCH 8/8] Implement/match `LegoWorld::ActorExists` (#1330) --- LEGO1/lego/legoomni/include/legopathcontroller.h | 3 +++ LEGO1/lego/legoomni/include/legoworld.h | 1 + LEGO1/lego/legoomni/src/entity/legoworld.cpp | 15 +++++++++++++++ 3 files changed, 19 insertions(+) diff --git a/LEGO1/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h index 01094fe6..5e3bd8ae 100644 --- a/LEGO1/lego/legoomni/include/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -138,6 +138,9 @@ public: MxFloat& p_param5 ); + // FUNCTION: BETA10 0x100e0160 + MxBool ActorExists(LegoPathActor* p_actor) { return m_actors.find(p_actor) == m_actors.end() ? FALSE : TRUE; } + static MxResult Init(); static MxResult Reset(); diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index cdb67e4a..d7dc4671 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -101,6 +101,7 @@ public: Vector3& p_direction ); void RemoveActor(LegoPathActor* p_actor); + MxBool ActorExists(LegoPathActor* p_actor); void FUN_1001fda0(LegoAnimPresenter* p_presenter); void FUN_1001fe90(LegoAnimPresenter* p_presenter); LegoPathBoundary* FindPathBoundary(const char* p_name); diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index 0781c4b3..b49df6c3 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -334,6 +334,21 @@ void LegoWorld::RemoveActor(LegoPathActor* p_actor) } } +// FUNCTION: BETA10 0x100da560 +MxBool LegoWorld::ActorExists(LegoPathActor* p_actor) +{ + LegoPathControllerListCursor cursor(&m_list0x68); + LegoPathController* controller; + + while (cursor.Next(controller)) { + if (controller->ActorExists(p_actor) == TRUE) { + return TRUE; + } + } + + return FALSE; +} + // FUNCTION: LEGO1 0x1001fda0 // FUNCTION: BETA10 0x100da621 void LegoWorld::FUN_1001fda0(LegoAnimPresenter* p_presenter)