diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index cd39a01a..bec82ceb 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -2,12 +2,15 @@ #define LEGOBUILDINGMANAGER_H #include "decomp.h" +#include "misc/legotypes.h" #include "mxcore.h" class LegoEntity; class LegoROI; class LegoStorage; class LegoWorld; +class LegoCacheSound; +class LegoPathBoundary; // SIZE 0x2c struct LegoBuildingInfo { @@ -18,26 +21,35 @@ struct LegoBuildingInfo { c_bit4 = 0x08 }; - LegoEntity* m_entity; // 0x00 - const char* m_hausName; // 0x04 - MxU32 m_cycle1; // 0x08 - MxU32 m_cycle2; // 0x0c - MxU8 m_cycle3; // 0x10 - 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_x; // 0x1c - float m_y; // 0x20 - float m_z; // 0x24 - undefined* m_unk0x28; // 0x28 + LegoEntity* m_entity; // 0x00 + const char* m_hausName; // 0x04 + MxU32 m_cycle1; // 0x08 + MxU32 m_cycle2; // 0x0c + MxU8 m_cycle3; // 0x10 + 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_x; // 0x1c + float m_y; // 0x20 + float m_z; // 0x24 + LegoPathBoundary* m_boundary; // 0x28 }; // VTABLE: LEGO1 0x100d6f50 // SIZE 0x30 class LegoBuildingManager : public MxCore { public: + // SIZE 0x14 + struct AnimEntry { + LegoEntity* m_entity; // 0x00 + LegoROI* m_roi; // 0x04 + LegoTime m_time; // 0x08 + float m_unk0x0c; // 0x0c + MxBool m_muted; // 0x10 + }; + LegoBuildingManager(); ~LegoBuildingManager() override; @@ -64,12 +76,19 @@ class LegoBuildingManager : public MxCore { MxBool FUN_1002fe40(LegoEntity* p_entity); MxBool FUN_1002fe80(LegoEntity* p_entity); MxBool FUN_1002fed0(LegoEntity* p_entity); + MxU32 GetBuildingEntityId(LegoEntity* p_entity); MxU32 FUN_1002ff40(LegoEntity*, MxBool); MxBool FUN_10030000(LegoEntity* p_entity); MxBool FUN_10030030(MxS32 p_index); MxBool FUN_10030110(LegoBuildingInfo* p_data); + void ScheduleAnimation(LegoEntity* p_entity, MxU32 p_length, MxBool p_haveSound, MxBool p_unk0x28); void FUN_10030590(); void AdjustHeight(MxS32 p_index); + MxResult FUN_10030630(); + LegoBuildingInfo* GetInfoArray(MxS32& p_length); + void FUN_100307b0(LegoEntity* p_entity, MxS32 p_adjust); + + static void FUN_10030800(); // SYNTHETIC: LEGO1 0x1002f940 // LegoBuildingManager::`scalar deleting destructor' @@ -77,17 +96,13 @@ class LegoBuildingManager : public MxCore { private: static char* g_customizeAnimFile; - MxU8 m_nextVariant; // 0x08 - MxU8 m_unk0x09; // 0x09 - undefined4 m_unk0x0c; // 0x0c - undefined4 m_unk0x10; // 0x10 - undefined4 m_unk0x14; // 0x14 - undefined4 m_unk0x18; // 0x18 - undefined4 m_unk0x1c; // 0x1c - MxU8 m_unk0x20; // 0x20 - undefined4 m_unk0x24; // 0x24 - MxU8 m_unk0x28; // 0x28 - undefined4 m_unk0x2c; // 0x2c + MxU8 m_nextVariant; // 0x08 + MxU8 m_unk0x09; // 0x09 + AnimEntry* m_entries[5]; // 0x0c + MxS8 m_numEntries; // 0x20 + LegoCacheSound* m_sound; // 0x24 + MxBool m_unk0x28; // 0x28 + LegoWorld* m_world; // 0x2c }; #endif // LEGOBUILDINGMANAGER_H diff --git a/LEGO1/lego/legoomni/include/legocachsound.h b/LEGO1/lego/legoomni/include/legocachsound.h index fc0bb5f5..178430ff 100644 --- a/LEGO1/lego/legoomni/include/legocachsound.h +++ b/LEGO1/lego/legoomni/include/legocachsound.h @@ -37,6 +37,7 @@ class LegoCacheSound : public MxCore { MxResult FUN_10006a30(const char* p_str, MxBool); void FUN_10006b80(); void FUN_10006be0(); + void FUN_10006cb0(undefined4 p_und1, undefined4 p_und2); // SYNTHETIC: LEGO1 0x10006610 // LegoCacheSound::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legopathcontroller.h b/LEGO1/lego/legoomni/include/legopathcontroller.h index 392d083c..3a9527cc 100644 --- a/LEGO1/lego/legoomni/include/legopathcontroller.h +++ b/LEGO1/lego/legoomni/include/legopathcontroller.h @@ -56,6 +56,7 @@ class LegoPathController : public MxCore { void FUN_100468f0(LegoAnimPresenter* p_presenter); void FUN_10046930(LegoAnimPresenter* p_presenter); MxResult FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_value); + LegoPathBoundary* GetPathBoundary(const char* p_name); void Enable(MxBool p_enable); void FUN_10046bb0(LegoWorld* p_world); @@ -64,10 +65,10 @@ class LegoPathController : public MxCore { undefined4 m_unk0x0c; // 0x0c undefined4 m_unk0x10; // 0x10 undefined4 m_unk0x14; // 0x14 - MxS16 m_numL; // 0x18 - MxS16 m_numE; // 0x1a - MxS16 m_numN; // 0x1c - MxS16 m_numT; // 0x1e + MxU16 m_numL; // 0x18 + MxU16 m_numE; // 0x1a + MxU16 m_numN; // 0x1c + MxU16 m_numT; // 0x1e map m_pfsE; // 0x20 map m_unk0x30; // 0x30 }; diff --git a/LEGO1/lego/legoomni/include/legounknown100d5778.h b/LEGO1/lego/legoomni/include/legounknown100d5778.h index fe5df73f..5ae43070 100644 --- a/LEGO1/lego/legoomni/include/legounknown100d5778.h +++ b/LEGO1/lego/legoomni/include/legounknown100d5778.h @@ -20,6 +20,7 @@ class LegoUnknown100d5778 { void Destroy(); undefined4 FUN_100118e0(LPDIRECTSOUNDBUFFER p_dsBuffer); void FUN_10011ca0(); + MxS32 FUN_10011cf0(undefined4, undefined4); // SYNTHETIC: LEGO1 0x10011650 // LegoUnknown100d5778::`scalar deleting destructor' diff --git a/LEGO1/lego/legoomni/include/legoworld.h b/LEGO1/lego/legoomni/include/legoworld.h index 781a8ac6..782c9212 100644 --- a/LEGO1/lego/legoomni/include/legoworld.h +++ b/LEGO1/lego/legoomni/include/legoworld.h @@ -83,6 +83,7 @@ class LegoWorld : public LegoEntity { void FUN_1001fc80(IslePathActor* p_actor); void FUN_1001fda0(LegoAnimPresenter* p_presenter); void FUN_1001fe90(LegoAnimPresenter* p_presenter); + LegoPathBoundary* FindPathBoundary(const char* p_name); void AddPath(LegoPathController* p_controller); MxResult GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value); MxCore* Find(const char* p_class, const char* p_name); diff --git a/LEGO1/lego/legoomni/src/audio/legocachsound.cpp b/LEGO1/lego/legoomni/src/audio/legocachsound.cpp index 8689491a..7d4f565c 100644 --- a/LEGO1/lego/legoomni/src/audio/legocachsound.cpp +++ b/LEGO1/lego/legoomni/src/audio/legocachsound.cpp @@ -149,6 +149,12 @@ void LegoCacheSound::FUN_10006be0() } } +// FUNCTION: LEGO1 0x10006cb0 +void LegoCacheSound::FUN_10006cb0(undefined4 p_und1, undefined4 p_und2) +{ + m_unk0x10.FUN_10011cf0(p_und1, p_und2); +} + // FUNCTION: LEGO1 0x10006cd0 void LegoCacheSound::FUN_10006cd0(undefined4, undefined4) { diff --git a/LEGO1/lego/legoomni/src/audio/legounknown100d5778.cpp b/LEGO1/lego/legoomni/src/audio/legounknown100d5778.cpp index 03fe9752..3ff57585 100644 --- a/LEGO1/lego/legoomni/src/audio/legounknown100d5778.cpp +++ b/LEGO1/lego/legoomni/src/audio/legounknown100d5778.cpp @@ -81,3 +81,10 @@ void LegoUnknown100d5778::FUN_10011ca0() { // TODO } + +// STUB: LEGO1 0x10011cf0 +MxS32 LegoUnknown100d5778::FUN_10011cf0(undefined4, undefined4) +{ + // TODO + return 0; +} diff --git a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp index 02e878be..2dc88f9a 100644 --- a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp @@ -1,17 +1,24 @@ #include "legobuildingmanager.h" #include "3dmanager/lego3dmanager.h" +#include "legocachesoundmanager.h" #include "legoentity.h" +#include "legopathboundary.h" +#include "legosoundmanager.h" #include "legovideomanager.h" #include "legoworld.h" #include "misc.h" #include "misc/legostorage.h" +#include "mxmisc.h" +#include "mxticklemanager.h" +#include "mxtimer.h" DECOMP_SIZE_ASSERT(LegoBuildingManager, 0x30) DECOMP_SIZE_ASSERT(LegoBuildingInfo, 0x2c) +DECOMP_SIZE_ASSERT(LegoBuildingManager::AnimEntry, 0x14) // GLOBAL: LEGO1 0x100f3410 -const char* g_buildingDataHausName[5] = { +const char* g_buildingInfoHausName[5] = { "haus1", "haus4", "haus5", @@ -21,7 +28,7 @@ const char* g_buildingDataHausName[5] = { // clang-format off // GLOBAL: LEGO1 0x100f3428 -float g_buildingDataDownshiftScale[16] = { +float g_buildingInfoDownshiftScale[16] = { 0.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, @@ -29,7 +36,7 @@ float g_buildingDataDownshiftScale[16] = { }; // GLOBAL: LEGO1 0x100f3468 -MxU8 g_buildingDataDownshift[16] = { +MxU8 g_buildingInfoDownshift[16] = { 5, 5, 5, 5, 3, 5, 5, 5, 3, 5, 5, 5, @@ -188,6 +195,22 @@ LegoBuildingInfo g_buildingInfoInit[16] = { // GLOBAL: LEGO1 0x100f3738 MxU32 g_buildingCycle1Length = 6; +// GLOBAL: LEGO1 0x100f373c +MxU32 g_cycleLengthOffset1 = 0x3c; + +// GLOBAL: LEGO1 0x100f3740 +MxU32 g_cycleLengthOffset3 = 0x42; + +// clang-format off +// GLOBAL: LEGO1 0x100f3788 +MxU32 g_buildingEntityId[16] = { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x46, 0x49, 0x4c, + 0x4f, 0x52, 0x55, 0x00, +}; +// clang-format on + // GLOBAL: LEGO1 0x100f37c8 char* LegoBuildingManager::g_customizeAnimFile = NULL; @@ -227,9 +250,9 @@ void LegoBuildingManager::Init() m_nextVariant = 0; m_unk0x09 = 0; - m_unk0x20 = 0; - m_unk0x24 = 0; - m_unk0x28 = 0; + m_numEntries = 0; + m_sound = NULL; + m_unk0x28 = FALSE; } // FUNCTION: LEGO1 0x1002fa00 @@ -244,15 +267,15 @@ void LegoBuildingManager::FUN_1002fa00() } if (g_buildingManagerConfig <= 1) { - LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingDataHausName[0]); + LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingInfoHausName[0]); if (entity) { entity->GetROI()->SetVisibility(TRUE); m_unk0x09 = 0; } } else { - for (i = 0; i < _countof(g_buildingDataHausName); i++) { - LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingDataHausName[i]); + for (i = 0; i < _countof(g_buildingInfoHausName); i++) { + LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingInfoHausName[i]); if (entity) { entity->GetROI()->SetVisibility(m_nextVariant == i); } @@ -280,10 +303,22 @@ void LegoBuildingManager::UpdatePosition(MxS32 p_index, LegoWorld* p_world) } } -// STUB: LEGO1 0x1002fb30 +// FUNCTION: LEGO1 0x1002fb30 void LegoBuildingManager::FUN_1002fb30() { - // TODO + MxU32 i; + + for (i = 0; i < _countof(g_buildingInfo); i++) { + g_buildingInfo[i].m_entity = NULL; + } + + m_unk0x09 = 0; + + for (i = 0; i < m_numEntries; i++) { + delete m_entries[i]; + } + + m_numEntries = 0; } // FUNCTION: LEGO1 0x1002fb80 @@ -364,14 +399,14 @@ MxResult LegoBuildingManager::Read(LegoStorage* p_storage) void LegoBuildingManager::AdjustHeight(MxS32 p_index) { if (g_buildingInfo[p_index].m_unk0x11 > 0) { - float value = g_buildingDataDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11; + 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_buildingDataDownshiftScale[p_index]; + g_buildingInfoInit[p_index].m_unk0x014 - value * g_buildingInfoDownshiftScale[p_index]; } else if (g_buildingInfo[p_index].m_unk0x11 == 0) { - float value = g_buildingDataDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11; + 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_buildingDataDownshiftScale[p_index]; + g_buildingInfoInit[p_index].m_unk0x014 - value * g_buildingInfoDownshiftScale[p_index]; if (g_buildingInfo[p_index].m_entity != NULL) { LegoROI* roi = g_buildingInfo[p_index].m_entity->GetROI(); @@ -416,12 +451,12 @@ MxBool LegoBuildingManager::IncrementVariant(LegoEntity* p_entity) if (info != NULL && info->m_flags & LegoBuildingInfo::c_bit1 && info->m_unk0x11 == -1) { LegoROI* roi = p_entity->GetROI(); - if (++m_nextVariant >= _countof(g_buildingDataHausName)) { + if (++m_nextVariant >= _countof(g_buildingInfoHausName)) { m_nextVariant = 0; } roi->SetVisibility(FALSE); - info->m_hausName = g_buildingDataHausName[m_nextVariant]; + info->m_hausName = g_buildingInfoHausName[m_nextVariant]; UpdatePosition(12, CurrentWorld()); if (info->m_entity != NULL) { @@ -494,10 +529,37 @@ MxBool LegoBuildingManager::FUN_1002fed0(LegoEntity* p_entity) return result; } -// STUB: LEGO1 0x1002ff40 -MxU32 LegoBuildingManager::FUN_1002ff40(LegoEntity*, MxBool) +// FUNCTION: LEGO1 0x1002ff00 +// FUNCTION: BETA10 0x1006432d +MxU32 LegoBuildingManager::GetBuildingEntityId(LegoEntity* p_entity) { - // TODO + LegoBuildingInfo* info = GetInfo(p_entity); + + if (info != NULL && info->m_flags & LegoBuildingInfo::c_bit3) { + return g_buildingEntityId[info - g_buildingInfo] + info->m_cycle2; + } + + return 0; +} + +// FUNCTION: LEGO1 0x1002ff40 +// FUNCTION: BETA10 0x10064398 +MxU32 LegoBuildingManager::FUN_1002ff40(LegoEntity* p_entity, MxBool p_state) +{ + LegoBuildingInfo* info = GetInfo(p_entity); + + if (info == NULL || !(info->m_flags & LegoBuildingInfo::c_bit2)) { + return 0; + } + + if (p_state) { + return info->m_cycle3 + g_cycleLengthOffset3; + } + + if (info != NULL) { + return info->m_cycle1 + g_cycleLengthOffset1; + } + return 0; } @@ -550,15 +612,114 @@ MxBool LegoBuildingManager::FUN_10030110(LegoBuildingInfo* p_data) return FALSE; } +// FUNCTION: LEGO1 0x10030150 +void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxU32 p_length, MxBool p_haveSound, MxBool p_unk0x28) +{ + m_world = CurrentWorld(); + + if (p_haveSound) { + m_sound = SoundManager()->GetCacheSoundManager()->FUN_1003d170("bcrash"); + m_sound->FUN_10006cb0(35, 60); + } + + if (m_numEntries == 0) { + m_unk0x28 = p_unk0x28; + TickleManager()->RegisterClient(this, 50); + } + + AnimEntry* entry = m_entries[m_numEntries] = new AnimEntry; + m_numEntries++; + + entry->m_entity = p_entity; + entry->m_roi = p_entity->GetROI(); + entry->m_time = Timer()->GetTime() + p_length + 1000; + entry->m_unk0x0c = entry->m_roi->GetLocal2World()[3][1]; + entry->m_muted = p_haveSound == FALSE; + FUN_100307b0(p_entity, -2); +} + // STUB: LEGO1 0x10030220 MxResult LegoBuildingManager::Tickle() { - // TODO + // WIP, included some of this to understand the AnimEntry array. + LegoTime time = Timer()->GetTime(); + + if (m_numEntries != 0) { + if (m_numEntries > 0) { + for (MxS32 i = 0; i < m_numEntries; i++) { + AnimEntry* entry = m_entries[i]; + if (entry->m_time <= time) { + // Code to animate and play sounds + } + } + } + } + else { + TickleManager()->UnregisterClient(this); + } + return SUCCESS; } -// STUB: LEGO1 0x10030590 +// FUNCTION: LEGO1 0x10030590 +// FUNCTION: BETA10 0x1006474c void LegoBuildingManager::FUN_10030590() { - // TODO + for (MxS32 i = 0; i < _countof(g_buildingInfo); i++) { + g_buildingInfo[i].m_unk0x11 = -1; + g_buildingInfo[i].m_initialUnk0x11 = -1; + AdjustHeight(i); + + 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; + roi->FUN_100a46b0(mat); + VideoManager()->Get3DManager()->Moved(*roi); + } + } +} + +// STUB: LEGO1 0x10030630 +MxResult LegoBuildingManager::FUN_10030630() +{ + return SUCCESS; +} + +// FUNCTION: LEGO1 0x10030790 +LegoBuildingInfo* LegoBuildingManager::GetInfoArray(MxS32& p_length) +{ + if (m_unk0x09 == 0) { + FUN_10030630(); + } + + p_length = _countof(g_buildingInfo); + return g_buildingInfo; +} + +// FUNCTION: LEGO1 0x100307b0 +void LegoBuildingManager::FUN_100307b0(LegoEntity* p_entity, MxS32 p_adjust) +{ + LegoBuildingInfo* info = GetInfo(p_entity); + + if (info != NULL) { + if (info->m_unk0x11 < 0) { + info->m_unk0x11 = g_buildingInfoDownshift[info - g_buildingInfo]; + } + + if (info->m_unk0x11 > 0) { + info->m_unk0x11 += p_adjust; + if (info->m_unk0x11 <= 1 && p_adjust < 0) { + info->m_unk0x11 = 0; + } + } + } +} + +// FUNCTION: LEGO1 0x10030800 +void LegoBuildingManager::FUN_10030800() +{ + for (MxS32 i = 0; i < _countof(g_buildingInfo); i++) { + g_buildingInfo[i].m_initialUnk0x11 = g_buildingInfo[i].m_unk0x11; + } } diff --git a/LEGO1/lego/legoomni/src/entity/legoworld.cpp b/LEGO1/lego/legoomni/src/entity/legoworld.cpp index d109f145..fb9ac70e 100644 --- a/LEGO1/lego/legoomni/src/entity/legoworld.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoworld.cpp @@ -358,6 +358,23 @@ void LegoWorld::AddPath(LegoPathController* p_controller) m_list0x68.Append(p_controller); } +// FUNCTION: LEGO1 0x10020020 +LegoPathBoundary* LegoWorld::FindPathBoundary(const char* p_name) +{ + LegoPathControllerListCursor cursor(&m_list0x68); + LegoPathController* controller; + + while (cursor.Next(controller)) { + LegoPathBoundary* boundary = controller->GetPathBoundary(p_name); + + if (boundary) { + return boundary; + } + } + + return NULL; +} + // FUNCTION: LEGO1 0x10020120 MxResult LegoWorld::GetCurrPathInfo(LegoPathBoundary** p_path, MxS32& p_value) { diff --git a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp index 2a7c15e0..5ab492de 100644 --- a/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp +++ b/LEGO1/lego/legoomni/src/paths/legopathcontroller.cpp @@ -1,5 +1,7 @@ #include "legopathcontroller.h" +#include "legopathboundary.h" + DECOMP_SIZE_ASSERT(LegoPathController, 0x40) // STUB: LEGO1 0x10044f40 @@ -65,6 +67,19 @@ MxResult LegoPathController::FUN_10046b30(LegoPathBoundary** p_path, MxS32& p_va return SUCCESS; } +// FUNCTION: LEGO1 0x10046b50 +// FUNCTION: BETA10 0x100b7531 +LegoPathBoundary* LegoPathController::GetPathBoundary(const char* p_name) +{ + for (MxS32 i = 0; i < m_numL; i++) { + if (strcmpi(m_unk0x08[i].GetName(), p_name) == 0) { + return &m_unk0x08[i]; + } + } + + return NULL; +} + // STUB: LEGO1 0x10046bb0 void LegoPathController::FUN_10046bb0(LegoWorld* p_world) { diff --git a/LEGO1/lego/sources/geom/legowegedge.h b/LEGO1/lego/sources/geom/legowegedge.h index 34a285b3..8e44fc48 100644 --- a/LEGO1/lego/sources/geom/legowegedge.h +++ b/LEGO1/lego/sources/geom/legowegedge.h @@ -17,6 +17,7 @@ class LegoWEGEdge : public LegoWEEdge { inline LegoU32 GetFlag0x10() { return m_unk0x0c & 0x10 ? FALSE : TRUE; } inline Mx4DPointFloat* GetUnknown0x14() { return &m_unk0x14; } inline Mx4DPointFloat* GetEdgeNormal(int index) { return &m_edgeNormals[index]; } + inline LegoChar* GetName() { return m_name; } // SYNTHETIC: LEGO1 0x1009a7e0 // LegoWEGEdge::`scalar deleting destructor'