From 67b4553eaa443a15e85af48d85eb61b7389c8ca5 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Sat, 14 Dec 2024 12:02:48 -0700 Subject: [PATCH] Implement/match `LegoPathController::FUN_1004a380` (#1226) --- LEGO1/lego/legoomni/include/act2actor.h | 2 +- .../legoomni/include/legopathcontroller.h | 27 +++++- LEGO1/lego/legoomni/src/actors/act2actor.cpp | 36 ++++---- .../legoomni/src/paths/legopathcontroller.cpp | 91 ++++++++++++++++++- 4 files changed, 131 insertions(+), 25 deletions(-) diff --git a/LEGO1/lego/legoomni/include/act2actor.h b/LEGO1/lego/legoomni/include/act2actor.h index ea07c89a..68b8f59d 100644 --- a/LEGO1/lego/legoomni/include/act2actor.h +++ b/LEGO1/lego/legoomni/include/act2actor.h @@ -34,7 +34,7 @@ class Act2Actor : public LegoAnimActor { MxU32 FUN_10019700(MxFloat p_param); void FUN_100199f0(MxS8 p_param); void FUN_100192a0(undefined4 p_location); - LegoEntity* FUN_10019b90(undefined* p_param); + LegoEntity* FUN_10019b90(MxBool* p_param); // SYNTHETIC: LEGO1 0x1001a0a0 // Act2Actor::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h index 80662e88..85ef1f9f 100644 --- a/LEGO1/lego/legoomni/include/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -130,7 +130,7 @@ class LegoPathController : public MxCore { LegoUnknown100db7f4*& p_edge, LegoPathBoundary*& p_boundary ); - undefined4 FUN_1004a380( + MxResult FUN_1004a380( Vector3& p_param1, Vector3& p_param2, Mx3DPointFloat* p_param3, @@ -160,6 +160,31 @@ class LegoPathController : public MxCore { static MxResult ReadVector(LegoStorage* p_storage, Mx3DPointFloat& p_vec); static MxResult ReadVector(LegoStorage* p_storage, Mx4DPointFloat& p_vec); + // FUNCTION: BETA10 0x100c16f0 + static MxU32 IsBetween(MxFloat p_v, MxFloat p_a, MxFloat p_b) + { + if (p_a <= p_b) { + return p_v >= p_a && p_v <= p_b; + } + else { + return p_v <= p_a && p_v >= p_b; + } + } + + // FUNCTION: BETA10 0x100c17a0 + static MxU32 FUN_100c17a0(MxFloat p_v1, MxFloat p_v2, MxFloat p_a, MxFloat p_b) + { + assert(IsBetween(p_v1, p_a, p_b)); + assert(IsBetween(p_v2, p_a, p_b)); + + if (p_a <= p_b) { + return p_v1 < p_v2; + } + else { + return p_v1 > p_v2; + } + } + LegoPathBoundary* m_boundaries; // 0x08 LegoPathCtrlEdge* m_edges; // 0x0c Mx3DPointFloat* m_unk0x10; // 0x10 diff --git a/LEGO1/lego/legoomni/src/actors/act2actor.cpp b/LEGO1/lego/legoomni/src/actors/act2actor.cpp index 1c1becc3..6d0ebba6 100644 --- a/LEGO1/lego/legoomni/src/actors/act2actor.cpp +++ b/LEGO1/lego/legoomni/src/actors/act2actor.cpp @@ -701,7 +701,7 @@ void Act2Actor::FUN_100199f0(MxS8 p_param) // FUNCTION: LEGO1 0x10019b90 // FUNCTION: BETA10 0x1000e374 -LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) +LegoEntity* Act2Actor::FUN_10019b90(MxBool* p_param) { MxS32 i; LegoBuildingInfo* buildingInfo = BuildingManager()->GetInfoArray(i); @@ -712,11 +712,11 @@ LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) case 0: if (buildingInfo[12].m_unk0x11) { result = buildingInfo[12].m_entity; - *p_param = 1; + *p_param = TRUE; } else if (buildingInfo[14].m_unk0x11) { result = buildingInfo[14].m_entity; - *p_param = 1; + *p_param = TRUE; } else { for (i = 0; g_unk0x100f0f30[i] != -1; i++) { @@ -730,7 +730,7 @@ LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) case 1: if (buildingInfo[13].m_unk0x11) { result = buildingInfo[13].m_entity; - *p_param = 1; + *p_param = TRUE; } else { for (i = 0; g_unk0x100f0f50[i] != -1; i++) { @@ -744,11 +744,11 @@ LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) case 2: if (buildingInfo[9].m_unk0x11) { result = buildingInfo[9].m_entity; - *p_param = 1; + *p_param = TRUE; } else if (buildingInfo[11].m_unk0x11) { result = buildingInfo[11].m_entity; - *p_param = 1; + *p_param = TRUE; } else { for (i = 0; g_unk0x100f0f90[i] != -1; i++) { @@ -762,15 +762,15 @@ LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) case 3: if (buildingInfo[7].m_unk0x11) { result = buildingInfo[7].m_entity; - *p_param = 1; + *p_param = TRUE; } else if (buildingInfo[8].m_unk0x11) { result = buildingInfo[8].m_entity; - *p_param = 1; + *p_param = TRUE; } else if (buildingInfo[3].m_unk0x11) { result = buildingInfo[3].m_entity; - *p_param = 1; + *p_param = TRUE; } else { for (i = 0; g_unk0x100f0fa8[i] != -1; i++) { @@ -784,11 +784,11 @@ LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) case 4: if (buildingInfo[5].m_unk0x11) { result = buildingInfo[5].m_entity; - *p_param = 1; + *p_param = TRUE; } else if (buildingInfo[10].m_unk0x11) { result = buildingInfo[10].m_entity; - *p_param = 1; + *p_param = TRUE; } else { for (i = 0; g_unk0x100f0fb8[i] != -1; i++) { @@ -802,7 +802,7 @@ LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) case 5: if (buildingInfo[4].m_unk0x11) { result = buildingInfo[4].m_entity; - *p_param = 1; + *p_param = TRUE; } else { for (i = 0; g_unk0x100f0fe8[i] != -1; i++) { @@ -816,7 +816,7 @@ LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) case 6: if (buildingInfo[2].m_unk0x11) { result = buildingInfo[2].m_entity; - *p_param = 1; + *p_param = TRUE; } else { for (i = 0; g_unk0x100f1000[i] != -1; i++) { @@ -830,7 +830,7 @@ LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) case 7: if (buildingInfo[6].m_unk0x11) { result = buildingInfo[6].m_entity; - *p_param = 1; + *p_param = TRUE; } else { for (i = 0; g_unk0x100f1018[i] != -1; i++) { @@ -853,15 +853,15 @@ LegoEntity* Act2Actor::FUN_10019b90(undefined* p_param) return result; } - if (buildingInfo[0xf].m_unk0x11) { - result = buildingInfo[0xf].m_entity; - *p_param = 1; + if (buildingInfo[15].m_unk0x11) { + result = buildingInfo[15].m_entity; + *p_param = TRUE; } break; } if (!result && !g_brickstrLocations[m_unk0x1d].m_unk0x1c) { - g_brickstrLocations[m_unk0x1d].m_unk0x1c = 1; + g_brickstrLocations[m_unk0x1d].m_unk0x1c = TRUE; m_unk0x48++; } diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp index be94dfaa..b17f1508 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -1015,9 +1015,9 @@ MxS32 LegoPathController::FUN_1004a240( return 0; } -// STUB: LEGO1 0x1004a380 -// STUB: BETA10 0x100b957f -undefined4 LegoPathController::FUN_1004a380( +// FUNCTION: LEGO1 0x1004a380 +// FUNCTION: BETA10 0x100b957f +MxResult LegoPathController::FUN_1004a380( Vector3& p_param1, Vector3& p_param2, Mx3DPointFloat* p_param3, @@ -1025,6 +1025,87 @@ undefined4 LegoPathController::FUN_1004a380( MxFloat& p_param5 ) { - // TODO - return 0; + MxFloat param5 = p_param5; + Mx3DPointFloat local24; + MxU32 local8 = TRUE; + + for (MxS32 i = 0; i < m_numL; i++) { + if (m_boundaries[i].m_flags & LegoPathBoundary::c_bit3) { + continue; + } + + LegoPathBoundary* b = &m_boundaries[i]; + Mx4DPointFloat* unk0x14 = b->GetUnknown0x14(); + float local28 = p_param3[0].Dot(&p_param3[0], unk0x14); + + if (local28 < 0.001 && local28 > -0.001) { + continue; + } + + float local2c = p_param3[1].Dot(&p_param3[1], unk0x14); + float local34 = p_param3[2].Dot(&p_param3[2], unk0x14) + unk0x14->index_operator(3); + float local3c = local2c * local2c - local34 * local28 * 4.0f; + + if (local3c < -0.001) { + continue; + } + + if (local3c < 0.0f) { + local3c = 0.0f; + } + else { + local3c = sqrt(local3c); + } + + float local38 = (local3c - local2c) / (local28 * 2.0f); + float local44 = (-local3c - local2c) / (local28 * 2.0f); + + if (!IsBetween(local38, 0.0f, param5)) { + if (IsBetween(local44, 0.0f, param5)) { + local38 = local44; + } + else { + continue; + } + } + + if (local8 || FUN_100c17a0(local38, p_param5, 0.0f, param5)) { + Mx3DPointFloat local58(p_param3[0]); + + local58 *= local38 * local38; + local24 = p_param3[1]; + local24 *= local38; + local24 += p_param3[2]; + local24 += local58; + + assert(b->GetNumEdges() > 1); + + MxS32 j; + for (j = b->GetNumEdges() - 1; j >= 0; j--) { + Mx4DPointFloat* local60 = b->GetEdgeNormal(j); + + if (local24.Dot(local60, &local24) + local60->index_operator(3) < -0.001) { + break; + } + } + + if (j < 0) { + Mx3DPointFloat local74(p_param1); + local74 -= local24; + + if (local74.Dot(&local74, unk0x14) >= 0.0f) { + p_param5 = local38; + p_boundary = b; + local8 = FALSE; + } + } + } + } + + if (local8) { + p_param5 = param5; + return FAILURE; + } + + return SUCCESS; }