From 97ff27af9e90a4e47db447d4799b0d70cf08f712 Mon Sep 17 00:00:00 2001 From: jonschz <17198703+jonschz@users.noreply.github.com> Date: Sat, 14 Dec 2024 16:35:08 +0100 Subject: [PATCH] Implement/match `LegoPlantManager::FUN_10026410` (#1223) * Implement/match `LegoPlantManager::FUN_10026410` * Full match on LEGO1 and BETA10 * Improve `LegoBuildingManager::FUN_10030630` --------- Co-authored-by: jonschz --- .../src/common/legobuildingmanager.cpp | 43 ++++++----- .../legoomni/src/common/legoplantmanager.cpp | 75 ++++++++++++++++++- LEGO1/lego/sources/geom/legowegedge.h | 1 + LEGO1/mxgeometry/mxgeometry3d.h | 7 +- 4 files changed, 101 insertions(+), 25 deletions(-) diff --git a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp index c02a86b8..9e1ddf62 100644 --- a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp @@ -221,6 +221,7 @@ char* LegoBuildingManager::g_customizeAnimFile = NULL; MxS32 g_buildingManagerConfig = 1; // GLOBAL: LEGO1 0x10104c30 +// GLOBAL: BETA10 0x10209fa0 LegoBuildingInfo g_buildingInfo[16]; // GLOBAL: LEGO1 0x100f3748 @@ -808,7 +809,7 @@ MxResult LegoBuildingManager::FUN_10030630() for (MxS32 j = 0; j < boundary->GetNumEdges(); j++) { Mx4DPointFloat* normal = boundary->GetEdgeNormal(j); - if (position.Dot(normal, &position) + (*normal)[3] < -0.001) { + if (position.Dot(normal, &position) + (*normal).index_operator(3) < -0.001) { MxTrace( "Building %d shot location (%g, %g, %g) is not in boundary %s.\n", i, @@ -825,26 +826,28 @@ MxResult LegoBuildingManager::FUN_10030630() if (g_buildingInfo[i].m_boundary != NULL) { Mx4DPointFloat& unk0x14 = *g_buildingInfo[i].m_boundary->GetUnknown0x14(); - if (position.Dot(&position, &unk0x14) + unk0x14[3] <= 0.001 && - position.Dot(&position, &unk0x14) + unk0x14[3] >= -0.001) { - continue; + if (position.Dot(&position, &unk0x14) + unk0x14.index_operator(3) > 0.001 || + position.Dot(&position, &unk0x14) + unk0x14.index_operator(3) < -0.001) { + + g_buildingInfo[i].m_y = + -((position[0] * unk0x14.index_operator(0) + unk0x14.index_operator(3) + + position[2] * unk0x14.index_operator(2)) / + unk0x14.index_operator(1)); + + MxTrace( + "Building %d shot location (%g, %g, %g) is not on plane of boundary %s...adjusting to (%g, " + "%g, " + "%g)\n", + i, + position[0], + position[1], + position[2], + g_buildingInfo[i].m_boundary->GetName(), + position[0], + g_buildingInfo[i].m_y, + position[2] + ); } - - g_buildingInfo[i].m_y = - -((unk0x14[3] + unk0x14[0] * position[0] + unk0x14[2] * position[2]) / unk0x14[1]); - - MxTrace( - "Building %d shot location (%g, %g, %g) is not on plane of boundary %s...adjusting to (%g, %g, " - "%g)\n", - i, - position[0], - position[1], - position[2], - g_buildingInfo[i].m_boundary->GetName(), - position[0], - g_buildingInfo[i].m_y, - position[2] - ); } } else { diff --git a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp index 57648063..7544b63e 100644 --- a/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legoplantmanager.cpp @@ -8,6 +8,7 @@ #include "legoworld.h" #include "misc.h" #include "misc/legostorage.h" +#include "mxdebug.h" #include "mxmisc.h" #include "mxticklemanager.h" #include "mxtimer.h" @@ -54,6 +55,7 @@ MxU32 g_plantAnimationId[4] = {30, 33, 36, 39}; char* LegoPlantManager::g_customizeAnimFile = NULL; // GLOBAL: LEGO1 0x10103180 +// GLOBAL: BETA10 0x1020f4c0 LegoPlantInfo g_plantInfo[81]; // FUNCTION: LEGO1 0x10026220 @@ -115,12 +117,77 @@ void LegoPlantManager::Reset(MxS32 p_worldId) m_unk0x0c = 0; } -// STUB: LEGO1 0x10026410 -// STUB: BETA10 0x100c50e9 +// FUNCTION: LEGO1 0x10026410 +// FUNCTION: BETA10 0x100c50e9 MxResult LegoPlantManager::FUN_10026410() { - // might be similar to LegoBuildingManager::FUN_10030630() - // TODO + // similar to LegoBuildingManager::FUN_10030630() + + LegoWorld* world = CurrentWorld(); + + if (world == NULL) { + return FAILURE; + } + + for (MxS32 i = 0; i < sizeOfArray(g_plantInfo); i++) { + if (g_plantInfo[i].m_entity != NULL && g_plantInfo[i].m_name != NULL) { + g_plantInfo[i].m_boundary = world->FindPathBoundary(g_plantInfo[i].m_name); + + if (g_plantInfo[i].m_boundary != NULL) { + Mx3DPointFloat position(g_plantInfo[i].m_x, g_plantInfo[i].m_y, g_plantInfo[i].m_z); + LegoPathBoundary* boundary = g_plantInfo[i].m_boundary; + + for (MxS32 j = 0; j < boundary->GetNumEdges(); j++) { + Mx4DPointFloat* normal = boundary->GetEdgeNormal(j); + + if (position.Dot(normal, &position) + (*normal).index_operator(3) < -0.001) { + MxTrace( + "Plant %d shot location (%g, %g, %g) is not in boundary %s.\n", + i, + position[0], + position[1], + position[2], + boundary->GetName() + ); + g_plantInfo[i].m_boundary = NULL; + break; + } + } + + if (g_plantInfo[i].m_boundary != NULL) { + Mx4DPointFloat& unk0x14 = *g_plantInfo[i].m_boundary->GetUnknown0x14(); + + if (position.Dot(&position, &unk0x14) + unk0x14.index_operator(3) > 0.001 || + position.Dot(&position, &unk0x14) + unk0x14.index_operator(3) < -0.001) { + + g_plantInfo[i].m_y = + -((position[0] * unk0x14.index_operator(0) + unk0x14.index_operator(3) + + position[2] * unk0x14.index_operator(2)) / + unk0x14.index_operator(1)); + + MxTrace( + "Plant %d shot location (%g, %g, %g) is not on plane of boundary %s...adjusting to (%g, " + "%g, " + "%g)\n", + i, + position[0], + position[1], + position[2], + g_plantInfo[i].m_boundary->GetName(), + position[0], + g_plantInfo[i].m_y, + position[2] + ); + } + } + } + else { + MxTrace("Plant %d is in boundary %s that does not exist.\n", i, g_plantInfo[i].m_name); + } + } + } + + m_unk0x0c = TRUE; return SUCCESS; } diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index be388c2d..ef29db9b 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -43,6 +43,7 @@ class LegoWEGEdge : public LegoWEEdge { // FUNCTION: BETA10 0x100270c0 LegoU32 GetFlag0x10() { return m_flags & c_bit5 ? FALSE : TRUE; } + // TODO: Other BETA10 reference at 0x1001c9e0, not sure what is going on // FUNCTION: BETA10 0x1001ff80 Mx4DPointFloat* GetUnknown0x14() { return &m_unk0x14; } diff --git a/LEGO1/mxgeometry/mxgeometry3d.h b/LEGO1/mxgeometry/mxgeometry3d.h index d7a87447..1cfa82ac 100644 --- a/LEGO1/mxgeometry/mxgeometry3d.h +++ b/LEGO1/mxgeometry/mxgeometry3d.h @@ -76,7 +76,12 @@ class Mx4DPointFloat : public Vector4 { // FUNCTION: BETA10 0x1004af10 float& operator[](int idx) { return m_data[idx]; } - const float& operator[](int idx) const { return m_data[idx]; } + // According to the PDB, BETA10 will not link this one if it is never used + // const float& operator[](int idx) const { return m_data[idx]; } + + // only used by a couple of BETA10 functions for some unknown reason + // FUNCTION: BETA10 0x1001c950 + float& index_operator(int idx) { return m_data[idx]; } // SYNTHETIC: LEGO1 0x10064b20 // SYNTHETIC: BETA10 0x10070420