From 7821d952eccf9fba4395fb4b3de6a25776bb354c Mon Sep 17 00:00:00 2001 From: Nathan M Gilbert Date: Sun, 14 Apr 2024 10:43:07 -0400 Subject: [PATCH] Pathactor (#800) * Implement LegoPathActor::VTable0x8c * Fix paramater name * WIP fixes * more fixes * style * fix * fix * fix --------- Co-authored-by: Christian Semmler --- LEGO1/lego/legoomni/include/legoextraactor.h | 5 +- .../lego/legoomni/include/legonavcontroller.h | 2 + LEGO1/lego/legoomni/include/legopathactor.h | 16 +- .../lego/legoomni/include/legopathboundary.h | 4 +- LEGO1/lego/legoomni/include/legoraceactor.h | 12 +- .../legoomni/src/paths/legoextraactor.cpp | 4 +- .../lego/legoomni/src/paths/legopathactor.cpp | 152 +++++++++++++++++- .../legoomni/src/paths/legopathboundary.cpp | 17 ++ .../lego/legoomni/src/race/legoraceactor.cpp | 3 +- LEGO1/lego/sources/misc/legounknown.cpp | 6 + LEGO1/lego/sources/misc/legounknown.h | 2 + tools/ncc/ncc.style | 2 +- 12 files changed, 199 insertions(+), 26 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legoextraactor.h b/LEGO1/lego/legoomni/include/legoextraactor.h index 5da2ddcb..814b4414 100644 --- a/LEGO1/lego/legoomni/include/legoextraactor.h +++ b/LEGO1/lego/legoomni/include/legoextraactor.h @@ -33,9 +33,8 @@ class LegoExtraActor : public virtual LegoAnimActor { return !strcmp(p_name, LegoExtraActor::ClassName()) || LegoAnimActor::IsA(p_name); } - void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - void VTable0x68(Mx3DPointFloat& p_point1, Mx3DPointFloat& p_point2, Mx3DPointFloat& p_point3) - override; // vtable+0x68 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + MxS32 VTable0x68(Vector3&, Vector3&, Vector3&) override; // vtable+0x68 void VTable0x6c() override; // vtable+0x6c void VTable0x70(float) override; // vtable+0x70 void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 diff --git a/LEGO1/lego/legoomni/include/legonavcontroller.h b/LEGO1/lego/legoomni/include/legonavcontroller.h index ffc98186..241cb417 100644 --- a/LEGO1/lego/legoomni/include/legonavcontroller.h +++ b/LEGO1/lego/legoomni/include/legonavcontroller.h @@ -72,6 +72,8 @@ class LegoNavController : public MxCore { ); static MxResult UpdateCameraLocation(MxU32 p_location); static MxResult UpdateCameraLocation(const char* p_location); + inline void SetLinearVel(MxFloat p_linearVel) { m_linearVel = p_linearVel; } + inline MxFloat GetLinearVel() { return m_linearVel; } inline MxFloat GetMaxLinearVel() { return m_maxLinearVel; } inline void ResetLinearVel(MxFloat p_maxLinearVel) { diff --git a/LEGO1/lego/legoomni/include/legopathactor.h b/LEGO1/lego/legoomni/include/legopathactor.h index 93eb6479..3b430b45 100644 --- a/LEGO1/lego/legoomni/include/legopathactor.h +++ b/LEGO1/lego/legoomni/include/legopathactor.h @@ -30,11 +30,11 @@ class LegoPathActor : public LegoActor { return !strcmp(p_name, LegoPathActor::ClassName()) || LegoActor::IsA(p_name); } - void ParseAction(char* p_extra) override; // vtable+0x20 - virtual void VTable0x68(Mx3DPointFloat&, Mx3DPointFloat&, Mx3DPointFloat&); // vtable+0x68 - virtual void VTable0x6c(); // vtable+0x6c - virtual void VTable0x70(float p_float); // vtable+0x70 - virtual void VTable0x74(Matrix4& p_transform); // vtable+0x74 + void ParseAction(char* p_extra) override; // vtable+0x20 + virtual MxS32 VTable0x68(Vector3&, Vector3&, Vector3&); // vtable+0x68 + virtual void VTable0x6c(); // vtable+0x6c + virtual void VTable0x70(float p_float); // vtable+0x70 + virtual void VTable0x74(Matrix4& p_transform); // vtable+0x74 // FUNCTION: LEGO1 0x10002d20 virtual void SetUserNavFlag(MxBool p_userNavFlag) { m_userNavFlag = p_userNavFlag; } // vtable+0x78 @@ -63,8 +63,8 @@ class LegoPathActor : public LegoActor { float p_srcScale, LegoUnknown100db7f4& p_destEdge, float p_destScale - ); // vtable+0x88 - virtual void VTable0x8c(); // vtable+0x8c + ); // vtable+0x88 + virtual MxS32 VTable0x8c(float p_time, Matrix4& p_transform); // vtable+0x8c // FUNCTION: LEGO1 0x10002d40 virtual MxU32 VTable0x90(float, Matrix4&) { return FALSE; } // vtable+0x90 @@ -118,7 +118,7 @@ class LegoPathActor : public LegoActor { protected: MxFloat m_BADuration; // 0x78 - undefined4 m_unk0x7c; // 0x7c + MxFloat m_unk0x7c; // 0x7c MxFloat m_actorTime; // 0x80 MxFloat m_lastTime; // 0x84 LegoPathBoundary* m_boundary; // 0x88 diff --git a/LEGO1/lego/legoomni/include/legopathboundary.h b/LEGO1/lego/legoomni/include/legopathboundary.h index 8a8a5759..ed400642 100644 --- a/LEGO1/lego/legoomni/include/legopathboundary.h +++ b/LEGO1/lego/legoomni/include/legopathboundary.h @@ -29,10 +29,12 @@ class LegoPathBoundary : public LegoWEGEdge { LegoPathBoundary(); MxResult AddActor(LegoPathActor* p_actor); + void FUN_100575b0(Vector3& p_point1, Vector3& p_point2, LegoPathActor* p_actor); + MxU32 Intersect(float p_scale, Vector3& p_point1, Vector3& p_point2, Vector3& p_point3, LegoEdge*& p_edge); inline LegoAnimPresenterSet* GetUnknown0x64() { return &m_unk0x64; } - // STUB: LEGO1 0x10047a80 + // SYNTHETIC: LEGO1 0x10047a80 // LegoPathBoundary::`scalar deleting destructor' private: diff --git a/LEGO1/lego/legoomni/include/legoraceactor.h b/LEGO1/lego/legoomni/include/legoraceactor.h index afb0255c..9ae2d92e 100644 --- a/LEGO1/lego/legoomni/include/legoraceactor.h +++ b/LEGO1/lego/legoomni/include/legoraceactor.h @@ -27,12 +27,12 @@ class LegoRaceActor : public virtual LegoAnimActor { return !strcmp(p_name, LegoRaceActor::ClassName()) || LegoAnimActor::IsA(p_name); } - void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 - void VTable0x68(Mx3DPointFloat&, Mx3DPointFloat&, Mx3DPointFloat&) override; // vtable+0x68 - void VTable0x70(float p_float) override; // vtable+0x70 - void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 - MxU32 VTable0x90(float, Matrix4&) override; // vtable+0x90 - MxResult VTable0x94(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94 + void SetWorldSpeed(MxFloat p_worldSpeed) override; // vtable+0x30 + MxS32 VTable0x68(Vector3&, Vector3&, Vector3&) override; // vtable+0x68 + void VTable0x70(float p_float) override; // vtable+0x70 + void VTable0x74(Matrix4& p_transform) override; // vtable+0x74 + MxU32 VTable0x90(float, Matrix4&) override; // vtable+0x90 + MxResult VTable0x94(LegoPathActor* p_actor, MxBool p_bool) override; // vtable+0x94 // FUNCTION: LEGO1 0x10014aa0 virtual MxResult FUN_10014aa0() { return SUCCESS; } diff --git a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp index 4217bbb7..5a9dcaed 100644 --- a/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legoextraactor.cpp @@ -418,9 +418,9 @@ void LegoExtraActor::VTable0xc4() } // FUNCTION: LEGO1 0x1002b6f0 -void LegoExtraActor::VTable0x68(Mx3DPointFloat& p_point1, Mx3DPointFloat& p_point2, Mx3DPointFloat& p_point3) +MxS32 LegoExtraActor::VTable0x68(Vector3& p_point1, Vector3& p_point2, Vector3& p_point3) { - LegoPathActor::VTable0x68(p_point1, p_point2, p_point3); + return LegoPathActor::VTable0x68(p_point1, p_point2, p_point3); } // STUB: LEGO1 0x1002b980 diff --git a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp index 7afcee61..2f5f6b9b 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathactor.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathactor.cpp @@ -1,9 +1,22 @@ #include "legopathactor.h" +#include "legonavcontroller.h" +#include "legosoundmanager.h" +#include "misc.h" +#include "mxmisc.h" +#include "mxtimer.h" + #include DECOMP_SIZE_ASSERT(LegoPathActor, 0x154) +// GLOBAL: LEGO1 0x100f3304 +// STRING: LEGO1 0x100f32f4 +const char* g_strHIT_WALL_SOUND = "HIT_WALL_SOUND"; + +// GLOBAL: LEGO1 0x100f3308 +MxLong g_unk0x100f3308 = 0; + // FUNCTION: LEGO1 0x1002d700 LegoPathActor::LegoPathActor() { @@ -195,10 +208,140 @@ MxResult LegoPathActor::VTable0x84( return SUCCESS; } -// STUB: LEGO1 0x1002e100 -void LegoPathActor::VTable0x8c() +// FUNCTION: LEGO1 0x1002e100 +MxS32 LegoPathActor::VTable0x8c(float p_time, Matrix4& p_transform) { - // TODO + if (m_userNavFlag && m_state == 0) { + m_lastTime = p_time; + + Mx3DPointFloat p1, p2, p3, p4, p5; + p5 = Vector3(m_roi->GetWorldDirection()); + p4 = Vector3(m_roi->GetWorldPosition()); + + LegoNavController* nav = NavController(); + m_worldSpeed = nav->GetLinearVel(); + + if (!nav->CalculateNewPosDir(p4, p5, p2, p1, m_boundary->GetUnknown0x14())) { + return -1; + } + + Mx3DPointFloat p6; + p6 = p2; + + m_unk0xe9 = m_boundary->Intersect(m_roi->GetWorldBoundingSphere().Radius(), p4, p2, p3, m_destEdge); + if (m_unk0xe9 == -1) { + return -1; + } + + if (m_unk0xe9 != 0) { + p2 = p3; + } + + MxS32 result = VTable0x68(p4, p2, p3); + + if (result > 0) { + p2 = p4; + m_unk0xe9 = 0; + result = 0; + } + else { + m_boundary->FUN_100575b0(p4, p2, this); + } + + LegoPathBoundary* oldBoundary = m_boundary; + + if (m_unk0xe9 != 0) { + WaitForAnimation(); + + if (m_boundary == oldBoundary) { + MxLong time = Timer()->GetTime(); + + if (time - g_unk0x100f3308 > 1000) { + g_unk0x100f3308 = time; + const char* var = VariableTable()->GetVariable(g_strHIT_WALL_SOUND); + + if (var && var[0] != 0) { + SoundManager()->GetCacheSoundManager()->FUN_1003dae0(var, NULL, FALSE); + } + } + + m_worldSpeed *= m_unk0x144; + nav->SetLinearVel(m_worldSpeed); + Mx3DPointFloat p7(p2); + ((Vector3&) p7).Sub(&p6); + + if (p7.Unitize() == 0) { + float f = sqrt(p1.LenSquared()) * m_unk0x140; + ((Vector3&) p7).Mul(f); + ((Vector3&) p1).Add(&p7); + } + } + } + + p_transform.SetIdentity(); + + Vector3 right(p_transform[0]); + Vector3 up(p_transform[1]); + Vector3 dir(p_transform[2]); + Vector3 pos(p_transform[3]); + + dir = p1; + up = *m_boundary->GetUnknown0x14(); + right.EqualsCross(&up, &dir); + right.Unitize(); + dir.EqualsCross(&right, &up); + pos = p2; + return result; + } + else { + if (p_time < 0 || m_worldSpeed <= 0) { + return -1; + } + + float f = (m_BADuration - m_unk0x7c) / m_worldSpeed + m_lastTime; + + if (f < p_time) { + m_unk0x7c = m_BADuration; + m_unk0xe9 = 1; + } + else { + f = p_time; + m_unk0x7c += (f - m_lastTime) * m_worldSpeed; + m_unk0xe9 = 0; + } + + m_actorTime += (f - m_lastTime) * m_worldSpeed; + m_lastTime = f; + p_transform.SetIdentity(); + + if (m_userNavFlag) { + m_unk0x8c.FUN_1009a1e0(m_BADuration / m_unk0x7c, p_transform, *m_boundary->GetUnknown0x14(), 0); + } + else { + m_unk0x8c.FUN_1009a1e0(m_BADuration / m_unk0x7c, p_transform, *m_boundary->GetUnknown0x14(), 1); + } + + Vector3 pos1(p_transform[3]); + Vector3 pos2(m_unk0xec[3]); + Mx3DPointFloat p1; + + if (VTable0x68(pos2, pos1, p1) > 0) { + m_lastTime = p_time; + return 1; + } + else { + m_boundary->FUN_100575b0(pos2, pos1, this); + pos2 = pos1; + + if (m_unk0xe9 != 0) { + WaitForAnimation(); + } + + return 0; + } + } + + return -1; } // STUB: LEGO1 0x1002e740 @@ -226,9 +369,10 @@ void LegoPathActor::VTable0x6c() } // STUB: LEGO1 0x1002ebe0 -void LegoPathActor::VTable0x68(Mx3DPointFloat&, Mx3DPointFloat&, Mx3DPointFloat&) +MxS32 LegoPathActor::VTable0x68(Vector3&, Vector3&, Vector3&) { // TODO + return 0; } // STUB: LEGO1 0x1002f020 diff --git a/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp b/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp index 19afed47..49ecfeb4 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathboundary.cpp @@ -17,3 +17,20 @@ MxResult LegoPathBoundary::AddActor(LegoPathActor* p_actor) p_actor->SetBoundary(this); return SUCCESS; } + +// STUB: LEGO1 0x100575b0 +void LegoPathBoundary::FUN_100575b0(Vector3& p_point1, Vector3& p_point2, LegoPathActor* p_actor) +{ +} + +// STUB: LEGO1 0x10057950 +MxU32 LegoPathBoundary::Intersect( + float p_scale, + Vector3& p_point1, + Vector3& p_point2, + Vector3& p_point3, + LegoEdge*& p_edge +) +{ + return 0; +} diff --git a/LEGO1/lego/legoomni/src/race/legoraceactor.cpp b/LEGO1/lego/legoomni/src/race/legoraceactor.cpp index 6df9d840..77f2a785 100644 --- a/LEGO1/lego/legoomni/src/race/legoraceactor.cpp +++ b/LEGO1/lego/legoomni/src/race/legoraceactor.cpp @@ -22,9 +22,10 @@ void LegoRaceActor::SetWorldSpeed(MxFloat p_worldSpeed) } // STUB: LEGO1 0x10014cc0 -void LegoRaceActor::VTable0x68(Mx3DPointFloat&, Mx3DPointFloat&, Mx3DPointFloat&) +MxS32 LegoRaceActor::VTable0x68(Vector3&, Vector3&, Vector3&) { // TODO + return 0; } // STUB: LEGO1 0x10014cd0 diff --git a/LEGO1/lego/sources/misc/legounknown.cpp b/LEGO1/lego/sources/misc/legounknown.cpp index f3e47974..e9210dc7 100644 --- a/LEGO1/lego/sources/misc/legounknown.cpp +++ b/LEGO1/lego/sources/misc/legounknown.cpp @@ -26,3 +26,9 @@ void LegoUnknown::FUN_1009a140(Vector3& p_point1, Vector3& p_point2, Vector3& p_ m_unk0x00[3][i] = (p_point1[i] - p_point3[i]) * 2.0f + p_point4[i] + p_point2[i]; } } + +// STUB: LEGO1 0x1009a1e0 +LegoResult LegoUnknown::FUN_1009a1e0(float, Matrix4&, Vector3&, LegoU32) +{ + return FAILURE; +} diff --git a/LEGO1/lego/sources/misc/legounknown.h b/LEGO1/lego/sources/misc/legounknown.h index 271b3276..8980d96a 100644 --- a/LEGO1/lego/sources/misc/legounknown.h +++ b/LEGO1/lego/sources/misc/legounknown.h @@ -3,6 +3,7 @@ #include "legotypes.h" #include "mxgeometry/mxgeometry3d.h" +#include "mxgeometry/mxmatrix.h" // SIZE 0x50 class LegoUnknown { @@ -11,6 +12,7 @@ class LegoUnknown { ~LegoUnknown(); void FUN_1009a140(Vector3& p_point1, Vector3& p_point2, Vector3& p_point3, Vector3& p_point4); + LegoResult FUN_1009a1e0(float, Matrix4&, Vector3&, LegoU32); private: Mx3DPointFloat m_unk0x00[4]; // 0x00 diff --git a/tools/ncc/ncc.style b/tools/ncc/ncc.style index 8dc0091b..5147d6bc 100644 --- a/tools/ncc/ncc.style +++ b/tools/ncc/ncc.style @@ -18,4 +18,4 @@ VariableName: Integer: '' Bool: '' Pointer: '' - Pattern: '^(unk0x[a-f0-9]{1,8}$|(?!unk)[a-z][a-zA-Z0-9]*)$' + Pattern: '^(unk0x[a-f0-9]{1,8}$|(?!unk)[a-z][a-zA-Z0-9]*|str[a-zA-Z0-9_]*)$'