From 4a41671759b8d5e752b231e879816ebbe568188b Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sat, 3 Aug 2024 07:29:21 +0200 Subject: [PATCH] Implement/match `LegoRaceActor` (#1072) * Implement LegoRaceActor, add annotations * Change code duplication comments --------- Co-authored-by: jonschz --- LEGO1/define.cpp | 4 + LEGO1/define.h | 1 + LEGO1/lego/legoomni/include/legoraceactor.h | 20 +++- .../lego/legoomni/src/race/legoraceactor.cpp | 112 ++++++++++++++++-- LEGO1/lego/legoomni/src/race/legoracers.cpp | 1 + LEGO1/realtime/matrix.h | 1 + LEGO1/realtime/vector.h | 2 + 7 files changed, 125 insertions(+), 16 deletions(-) diff --git a/LEGO1/define.cpp b/LEGO1/define.cpp index 4460107f..1e1ac43a 100644 --- a/LEGO1/define.cpp +++ b/LEGO1/define.cpp @@ -139,3 +139,7 @@ const char* g_strBMP_ISMAP = "BMP_ISMAP"; // GLOBAL: LEGO1 0x101020e4 // STRING: LEGO1 0x10101eac const char* g_parseExtraTokens = ":;"; + +// GLOBAL: LEGO1 0x100f0c14 +// STRING: LEGO1 0x100f0c04 +const char* g_strHIT_ACTOR_SOUND = "HIT_ACTOR_SOUND"; diff --git a/LEGO1/define.h b/LEGO1/define.h index 1704d045..14a814ea 100644 --- a/LEGO1/define.h +++ b/LEGO1/define.h @@ -38,5 +38,6 @@ extern const char* g_strDB_CREATE; extern const char* g_strPERMIT_NAVIGATE; extern const char* g_strPATH; extern const char* g_strCOLLIDEBOX; +extern const char* g_strHIT_ACTOR_SOUND; #endif // DEFINE_H diff --git a/LEGO1/lego/legoomni/include/legoraceactor.h b/LEGO1/lego/legoomni/include/legoraceactor.h index 57325256..1fb1b28c 100644 --- a/LEGO1/lego/legoomni/include/legoraceactor.h +++ b/LEGO1/lego/legoomni/include/legoraceactor.h @@ -8,12 +8,16 @@ class Matrix4; // VTABLE: LEGO1 0x100d5b78 LegoAnimActor // VTABLE: LEGO1 0x100d5b88 LegoPathActor // VTABLE: LEGO1 0x100d5c54 LegoRaceActor +// VTABLE: BETA10 0x101be380 LegoAnimActor +// VTABLE: BETA10 0x101be398 LegoPathActor +// VTABLE: BETA10 0x101be488 LegoRaceActor // SIZE 0x180 class LegoRaceActor : public virtual LegoAnimActor { public: LegoRaceActor(); // FUNCTION: LEGO1 0x10014b00 + // FUNCTION: BETA10 0x100aaae0 const char* ClassName() const override // vtable+0x0c { // STRING: LEGO1 0x100f0bf4 @@ -26,9 +30,9 @@ public: return !strcmp(p_name, LegoRaceActor::ClassName()) || LegoAnimActor::IsA(p_name); } - MxS32 VTable0x68(Vector3&, Vector3&, Vector3&) override; // vtable+0x68 - MxU32 VTable0x90(float, Matrix4&) override; // vtable+0x90 - MxResult VTable0x94(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94 + MxS32 VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3) override; // vtable+0x68 + MxU32 VTable0x90(float p_float, Matrix4& p_matrix) override; // vtable+0x90 + MxResult VTable0x94(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94 // FUNCTION: LEGO1 0x10014aa0 virtual MxResult FUN_10014aa0() { return SUCCESS; } @@ -40,7 +44,15 @@ public: // LegoRaceActor::`scalar deleting destructor' private: - undefined4 m_unk0x08; // 0x08 + MxFloat m_unk0x08; // 0x08 + + static Mx3DPointFloat g_unk0x10102b08; }; +// GLOBAL: LEGO1 0x100d5b68 +// LegoRaceActor::`vbtable'{for `LegoRaceActor'} + +// GLOBAL: LEGO1 0x100d5b60 +// LegoRaceActor::`vbtable'{for `LegoAnimActor'} + #endif // LEGORACEACTOR_H diff --git a/LEGO1/lego/legoomni/src/race/legoraceactor.cpp b/LEGO1/lego/legoomni/src/race/legoraceactor.cpp index 9bc47709..32455e4a 100644 --- a/LEGO1/lego/legoomni/src/race/legoraceactor.cpp +++ b/LEGO1/lego/legoomni/src/race/legoraceactor.cpp @@ -1,7 +1,20 @@ #include "legoraceactor.h" +#include "define.h" +#include "legocachesoundmanager.h" +#include "legosoundmanager.h" +#include "misc.h" +#include "mxmisc.h" +#include "mxtimer.h" +#include "mxvariabletable.h" +#include "roi/legoroi.h" + DECOMP_SIZE_ASSERT(LegoRaceActor, 0x180) +// Initialized at LEGO1 0x100145a0 +// GLOBAL: LEGO1 0x10102b08 +Mx3DPointFloat LegoRaceActor::g_unk0x10102b08 = Mx3DPointFloat(0.0, 2.0, 0.0); + // FUNCTION: LEGO1 0x100145d0 LegoRaceActor::LegoRaceActor() { @@ -9,23 +22,98 @@ LegoRaceActor::LegoRaceActor() m_unk0x08 = 0; } -// STUB: LEGO1 0x10014750 -MxS32 LegoRaceActor::VTable0x68(Vector3&, Vector3&, Vector3&) +// FUNCTION: LEGO1 0x10014750 +// FUNCTION: BETA10 0x100c9bba +MxS32 LegoRaceActor::VTable0x68(Vector3& p_v1, Vector3& p_v2, Vector3& p_v3) { - // TODO + MxS32 result = LegoPathActor::VTable0x68(p_v1, p_v2, p_v3); + + if (m_userNavFlag && result) { + MxLong time = Timer()->GetTime(); + if (time - g_unk0x100f3308 > 1000) { + g_unk0x100f3308 = time; + const char* soundKey = VariableTable()->GetVariable(g_strHIT_ACTOR_SOUND); + + if (soundKey && *soundKey) { + SoundManager()->GetCacheSoundManager()->Play(soundKey, NULL, FALSE); + } + } + } + + return result; +} + +// FUNCTION: LEGO1 0x100147f0 +// FUNCTION: BETA10 0x100c9c93 +MxU32 LegoRaceActor::VTable0x90(float p_float, Matrix4& p_transform) +{ + // Note: Code duplication with LegoExtraActor::VTable0x90 + switch (m_state) { + case 0: + case 1: + return 1; + + case 2: + m_unk0x08 = p_float + 2000.0f; + m_state = 3; + m_actorTime += (p_float - m_lastTime) * m_worldSpeed; + m_lastTime = p_float; + return 0; + + case 3: + assert(!m_userNavFlag); + Vector3 positionRef(p_transform[3]); + + p_transform = m_roi->GetLocal2World(); + + if (m_unk0x08 > p_float) { + Mx3DPointFloat position; + + position = positionRef; + positionRef.Clear(); + p_transform.RotateX(0.6); + positionRef = position; + + m_actorTime += (p_float - m_lastTime) * m_worldSpeed; + m_lastTime = p_float; + + VTable0x74(p_transform); + return 0; + } + else { + m_state = 0; + m_unk0x08 = 0; + + ((Vector3&) positionRef).Sub(g_unk0x10102b08); + m_roi->FUN_100a58f0(p_transform); + return 1; + } + } + return 0; } -// STUB: LEGO1 0x100147f0 -MxU32 LegoRaceActor::VTable0x90(float, Matrix4&) -{ - // TODO - return 0; -} - -// STUB: LEGO1 0x10014a00 +// FUNCTION: LEGO1 0x10014a00 +// FUNCTION: BETA10 0x100c9f5c MxResult LegoRaceActor::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) { - // TODO + if (!p_actor->GetUserNavFlag()) { + if (p_actor->GetState()) { + return FAILURE; + } + + if (p_bool) { + LegoROI* roi = p_actor->GetROI(); // name verified by BETA10 0x100c9fcf + assert(roi); + MxMatrix matr; + matr = roi->GetLocal2World(); + + Vector3(matr[3]).Add(g_unk0x10102b08); + + roi->FUN_100a58f0(matr); + + p_actor->SetState(2); + } + } return 0; } diff --git a/LEGO1/lego/legoomni/src/race/legoracers.cpp b/LEGO1/lego/legoomni/src/race/legoracers.cpp index 5bebe2da..16963723 100644 --- a/LEGO1/lego/legoomni/src/race/legoracers.cpp +++ b/LEGO1/lego/legoomni/src/race/legoracers.cpp @@ -405,6 +405,7 @@ void LegoRaceCar::VTable0x70(float p_float) // FUNCTION: BETA10 0x100cbb84 MxResult LegoRaceCar::VTable0x94(LegoPathActor* p_actor, MxBool p_bool) { + // Note: Code duplication with LegoRaceActor::VTable0x94 if (!p_actor->GetUserNavFlag()) { if (p_actor->GetState()) { return FAILURE; diff --git a/LEGO1/realtime/matrix.h b/LEGO1/realtime/matrix.h index 92c7ac7d..a0508c4d 100644 --- a/LEGO1/realtime/matrix.h +++ b/LEGO1/realtime/matrix.h @@ -122,6 +122,7 @@ public: } } + // FUNCTION: BETA10 0x1001c6a0 void RotateX(const float& p_angle) { float s = sin(p_angle); diff --git a/LEGO1/realtime/vector.h b/LEGO1/realtime/vector.h index 86e389ef..920b24b1 100644 --- a/LEGO1/realtime/vector.h +++ b/LEGO1/realtime/vector.h @@ -162,6 +162,7 @@ protected: }; // VTABLE: LEGO1 0x100d4518 +// VTABLE: BETA10 0x101b8398 // SIZE 0x08 class Vector3 : public Vector2 { public: @@ -263,6 +264,7 @@ public: void EqualsImpl(float* p_data) override { memcpy(m_data, p_data, sizeof(float) * 3); } // vtable+0x20 // FUNCTION: LEGO1 0x10003bc0 + // FUNCTION: BETA10 0x101b84fc void Clear() override { memset(m_data, 0, sizeof(float) * 3); } // vtable+0x2c // FUNCTION: LEGO1 0x10003bd0