From e56ac9ab555460b3ee1ba07e5a64aa24b02c9944 Mon Sep 17 00:00:00 2001 From: Christian Semmler Date: Fri, 22 Nov 2024 15:08:23 -0700 Subject: [PATCH] Implement/match LegoBuildingManager::FUN_10030630 (#1164) --- .../legoomni/include/legobuildingmanager.h | 6 +- .../src/common/legobuildingmanager.cpp | 95 ++++++++++++++++--- LEGO1/lego/sources/geom/legoweedge.h | 1 + LEGO1/lego/sources/geom/legowegedge.h | 1 + 4 files changed, 85 insertions(+), 18 deletions(-) diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index 276586fd..409e805c 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -29,8 +29,8 @@ struct LegoBuildingInfo { MxS8 m_unk0x11; // 0x11 MxS8 m_initialUnk0x11; // 0x12 - initial value loaded to m_unk0x11 MxU8 m_flags; // 0x13 - float m_unk0x014; // 0x14 - const char* m_unk0x18; // 0x18 + float m_unk0x14; // 0x14 + const char* m_boundaryName; // 0x18 float m_x; // 0x1c float m_y; // 0x20 float m_z; // 0x24 @@ -100,7 +100,7 @@ class LegoBuildingManager : public MxCore { static MxU32 g_maxSound; MxU8 m_nextVariant; // 0x08 - MxU8 m_unk0x09; // 0x09 + MxBool m_unk0x09; // 0x09 AnimEntry* m_entries[5]; // 0x0c MxS8 m_numEntries; // 0x20 LegoCacheSound* m_sound; // 0x24 diff --git a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp index d61313bd..1c0245c5 100644 --- a/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legobuildingmanager.cpp @@ -9,6 +9,7 @@ #include "legoworld.h" #include "misc.h" #include "misc/legostorage.h" +#include "mxdebug.h" #include "mxmisc.h" #include "mxticklemanager.h" #include "mxtimer.h" @@ -251,7 +252,7 @@ void LegoBuildingManager::Init() } m_nextVariant = 0; - m_unk0x09 = 0; + m_unk0x09 = FALSE; m_numEntries = 0; m_sound = NULL; m_unk0x28 = FALSE; @@ -272,7 +273,7 @@ void LegoBuildingManager::LoadWorldInfo() LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingInfoVariants[0]); if (entity) { entity->GetROI()->SetVisibility(TRUE); - m_unk0x09 = 0; + m_unk0x09 = FALSE; } } else { @@ -284,7 +285,7 @@ void LegoBuildingManager::LoadWorldInfo() } } - m_unk0x09 = 0; + m_unk0x09 = FALSE; } // FUNCTION: LEGO1 0x1002fa90 @@ -299,7 +300,7 @@ void LegoBuildingManager::CreateBuilding(MxS32 p_index, LegoWorld* p_world) LegoROI* roi = entity->GetROI(); AdjustHeight(p_index); MxMatrix mat = roi->GetLocal2World(); - mat[3][1] = g_buildingInfo[p_index].m_unk0x014; + mat[3][1] = g_buildingInfo[p_index].m_unk0x14; roi->UpdateTransformationRelativeToParent(mat); VideoManager()->Get3DManager()->Moved(*roi); } @@ -314,7 +315,7 @@ void LegoBuildingManager::Reset() g_buildingInfo[i].m_entity = NULL; } - m_unk0x09 = 0; + m_unk0x09 = FALSE; for (i = 0; i < m_numEntries; i++) { delete m_entries[i]; @@ -402,13 +403,13 @@ void LegoBuildingManager::AdjustHeight(MxS32 p_index) { if (g_buildingInfo[p_index].m_unk0x11 > 0) { float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11; - g_buildingInfo[p_index].m_unk0x014 = - g_buildingInfoInit[p_index].m_unk0x014 - value * g_buildingInfoDownshiftScale[p_index]; + g_buildingInfo[p_index].m_unk0x14 = + g_buildingInfoInit[p_index].m_unk0x14 - value * g_buildingInfoDownshiftScale[p_index]; } else if (g_buildingInfo[p_index].m_unk0x11 == 0) { float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11; - g_buildingInfo[p_index].m_unk0x014 = - g_buildingInfoInit[p_index].m_unk0x014 - value * g_buildingInfoDownshiftScale[p_index]; + g_buildingInfo[p_index].m_unk0x14 = + g_buildingInfoInit[p_index].m_unk0x14 - value * g_buildingInfoDownshiftScale[p_index]; if (g_buildingInfo[p_index].m_entity != NULL) { LegoROI* roi = g_buildingInfo[p_index].m_entity->GetROI(); @@ -418,7 +419,7 @@ void LegoBuildingManager::AdjustHeight(MxS32 p_index) } } else { - g_buildingInfo[p_index].m_unk0x014 = g_buildingInfoInit[p_index].m_unk0x014; + g_buildingInfo[p_index].m_unk0x14 = g_buildingInfoInit[p_index].m_unk0x14; } } @@ -637,7 +638,7 @@ MxBool LegoBuildingManager::FUN_10030030(MxS32 p_index) else { AdjustHeight(p_index); MxMatrix mat = roi->GetLocal2World(); - mat[3][1] = g_buildingInfo[p_index].m_unk0x014; + mat[3][1] = g_buildingInfo[p_index].m_unk0x14; roi->UpdateTransformationRelativeToParent(mat); VideoManager()->Get3DManager()->Moved(*roi); } @@ -739,7 +740,7 @@ MxResult LegoBuildingManager::Tickle() MxS32 index = info - g_buildingInfo; AdjustHeight(index); MxMatrix mat = entry->m_roi->GetLocal2World(); - mat[3][1] = g_buildingInfo[index].m_unk0x014; + mat[3][1] = g_buildingInfo[index].m_unk0x14; entry->m_roi->UpdateTransformationRelativeToParent(mat); VideoManager()->Get3DManager()->Moved(*entry->m_roi); } @@ -778,23 +779,87 @@ void LegoBuildingManager::FUN_10030590() if (g_buildingInfo[i].m_entity != NULL) { LegoROI* roi = g_buildingInfo[i].m_entity->GetROI(); MxMatrix mat = roi->GetLocal2World(); - mat[3][1] = g_buildingInfo[i].m_unk0x014; + mat[3][1] = g_buildingInfo[i].m_unk0x14; roi->UpdateTransformationRelativeToParent(mat); VideoManager()->Get3DManager()->Moved(*roi); } } } -// STUB: LEGO1 0x10030630 +// FUNCTION: LEGO1 0x10030630 +// FUNCTION: BETA10 0x100648ab MxResult LegoBuildingManager::FUN_10030630() { + LegoWorld* world = CurrentWorld(); + + if (world == NULL) { + return FAILURE; + } + + for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) { + if (g_buildingInfo[i].m_entity != NULL && g_buildingInfo[i].m_boundaryName != NULL) { + g_buildingInfo[i].m_boundary = world->FindPathBoundary(g_buildingInfo[i].m_boundaryName); + + if (g_buildingInfo[i].m_boundary != NULL) { + Mx3DPointFloat position(g_buildingInfo[i].m_x, g_buildingInfo[i].m_y, g_buildingInfo[i].m_z); + LegoPathBoundary* boundary = g_buildingInfo[i].m_boundary; + + for (MxS32 j = 0; j < boundary->GetNumEdges(); j++) { + Mx4DPointFloat* normal = boundary->GetEdgeNormal(j); + + if (position.Dot(normal, &position) + (*normal)[3] < -0.001) { + MxTrace( + "Building %d shot location (%g, %g, %g) is not in boundary %s.\n", + i, + position[0], + position[1], + position[2], + boundary->GetName() + ); + g_buildingInfo[i].m_boundary = NULL; + break; + } + } + + 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; + } + + 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 { + MxTrace("Building %d is in boundary %s that does not exist.\n", i, g_buildingInfo[i].m_boundaryName); + } + } + } + + m_unk0x09 = TRUE; return SUCCESS; } // FUNCTION: LEGO1 0x10030790 LegoBuildingInfo* LegoBuildingManager::GetInfoArray(MxS32& p_length) { - if (m_unk0x09 == 0) { + if (!m_unk0x09) { FUN_10030630(); } diff --git a/LEGO1/lego/sources/geom/legoweedge.h b/LEGO1/lego/sources/geom/legoweedge.h index a63eb50e..e8436427 100644 --- a/LEGO1/lego/sources/geom/legoweedge.h +++ b/LEGO1/lego/sources/geom/legoweedge.h @@ -16,6 +16,7 @@ class LegoWEEdge { virtual LegoResult VTable0x04(); // vtable+0x04 + // FUNCTION: BETA10 0x1001c980 LegoU8 GetNumEdges() { return m_numEdges; } // FUNCTION: BETA10 0x1001cc30 diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index 98a41433..728d7ade 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -46,6 +46,7 @@ class LegoWEGEdge : public LegoWEEdge { // FUNCTION: BETA10 0x1001ff80 Mx4DPointFloat* GetUnknown0x14() { return &m_unk0x14; } + // FUNCTION: BETA10 0x1001ca10 Mx4DPointFloat* GetEdgeNormal(int index) { return &m_edgeNormals[index]; } // FUNCTION: BETA10 0x1001c9b0