diff --git a/LEGO1/lego/legoomni/include/legobuildingmanager.h b/LEGO1/lego/legoomni/include/legobuildingmanager.h index 380a1c99..cd39a01a 100644 --- a/LEGO1/lego/legoomni/include/legobuildingmanager.h +++ b/LEGO1/lego/legoomni/include/legobuildingmanager.h @@ -7,6 +7,32 @@ class LegoEntity; class LegoROI; class LegoStorage; +class LegoWorld; + +// SIZE 0x2c +struct LegoBuildingInfo { + enum { + c_bit1 = 0x01, + c_bit2 = 0x02, + c_bit3 = 0x04, + 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 +}; // VTABLE: LEGO1 0x100d6f50 // SIZE 0x30 @@ -29,13 +55,21 @@ class LegoBuildingManager : public MxCore { void Init(); void FUN_1002fa00(); + void UpdatePosition(MxS32 p_index, LegoWorld* p_world); void FUN_1002fb30(); MxResult Write(LegoStorage* p_storage); MxResult Read(LegoStorage* p_storage); - MxBool FUN_1002fdb0(LegoEntity* p_entity); + LegoBuildingInfo* GetInfo(LegoEntity* p_entity); + MxBool IncrementVariant(LegoEntity* p_entity); + MxBool FUN_1002fe40(LegoEntity* p_entity); + MxBool FUN_1002fe80(LegoEntity* p_entity); + MxBool FUN_1002fed0(LegoEntity* p_entity); MxU32 FUN_1002ff40(LegoEntity*, MxBool); - void FUN_10030000(LegoEntity* p_entity); + MxBool FUN_10030000(LegoEntity* p_entity); + MxBool FUN_10030030(MxS32 p_index); + MxBool FUN_10030110(LegoBuildingInfo* p_data); void FUN_10030590(); + void AdjustHeight(MxS32 p_index); // SYNTHETIC: LEGO1 0x1002f940 // LegoBuildingManager::`scalar deleting destructor' @@ -43,7 +77,17 @@ class LegoBuildingManager : public MxCore { private: static char* g_customizeAnimFile; - undefined m_unk0x08[0x28]; // 0x08 + 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 }; #endif // LEGOBUILDINGMANAGER_H diff --git a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp index 1b7c4273..02e878be 100644 --- a/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp +++ b/LEGO1/lego/legoomni/src/build/legobuildingmanager.cpp @@ -1,12 +1,204 @@ #include "legobuildingmanager.h" +#include "3dmanager/lego3dmanager.h" +#include "legoentity.h" +#include "legovideomanager.h" +#include "legoworld.h" +#include "misc.h" +#include "misc/legostorage.h" + DECOMP_SIZE_ASSERT(LegoBuildingManager, 0x30) +DECOMP_SIZE_ASSERT(LegoBuildingInfo, 0x2c) + +// GLOBAL: LEGO1 0x100f3410 +const char* g_buildingDataHausName[5] = { + "haus1", + "haus4", + "haus5", + "haus6", + "haus7", +}; + +// clang-format off +// GLOBAL: LEGO1 0x100f3428 +float g_buildingDataDownshiftScale[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, + 1.0f, 1.0f, 1.0f, 1.0f, +}; + +// GLOBAL: LEGO1 0x100f3468 +MxU8 g_buildingDataDownshift[16] = { + 5, 5, 5, 5, + 3, 5, 5, 5, + 3, 5, 5, 5, + 5, 5, 5, 5, +}; + +// GLOBAL: LEGO1 0x100f3478 +LegoBuildingInfo g_buildingInfoInit[16] = { + { + NULL, "infocen", + 4, 0, 1, + -1, -1, 0x00, + 8.99999f, + "edg02_74", + 84.79617f, 9.0f, -10.2189f, + NULL, + }, + { + NULL, "policsta", + 4, 0, 1, + -1, -1, 0x10, + 0.999992f, + "int33", + 67.28488, 1.0f, -85.3917, + NULL, + }, + { + NULL, "Jail", + 4, 0, 1, + -1, -1, 0x10, + 0.0f, + "edg02_50", + 93.245659f, 0.0f, -48.7773f, + NULL, + }, + { + NULL, "races", + 4, 0, 1, + -1, -1, 0x10, + 0.0f, + "int14", + -21.7321f, 0.0f, 11.23354f, + NULL, + }, + { + NULL, "medcntr", + 4, 0, 1, + -1, -1, 0x10, + 3.99071f, + "edg02_27", + 86.020737f, 4.0f, 31.35498f, + NULL, + }, + { + NULL, "gas", + 4, 0, 1, + -1, -1, 0x10, + 0.0f, + "int24", + 26.32025f, 0.0f, -2.28938f, + NULL, + }, + { + NULL, "beach", + 4, 0, 1, + -1, -1, 0x10, + -1.8125f, + "edg00_46", + 14.375f, -1.3125f, -56.75f, + NULL, + }, + { + NULL, "racef", + 4, 0, 1, + -1, -1, 0x10, + 0.0f, + "edg03_03", + -4.15951f, 0.0f, 5.2003198f, + NULL, + }, + { + NULL, "racej", + 4, 0, 1, + -1, -1, 0x10, + 0.0f, + "edg03_03", + -4.15951f, 0.0f, 5.2003198f, + NULL, + }, + { + NULL, "Store", + 4, 0, 1, + -1, -1, 0x3e, + 2.0f, + "edg02_60", + -49.4744f, 2.0f, -56.6276f, + NULL, + }, + { + NULL, "Bank", + 4, 0, 1, + -1, -1, 0x3e, + 0.0f, + "edg02_36", + 18.53531f, 0.0f, -16.6053f, + NULL, + }, + { + NULL, "Post", + 4, 0, 1, + -1, -1, 0x3e, + 0.0f, + "edg02_58", + -33.5413f, 0.0f, -55.1791f, + NULL, + }, + { + NULL, "haus1", + 4, 0, 1, + -1, -1, 0x3f, + 7.0625f, + "int11", + -62.7827f, 7.0f, -45.2215f, + NULL, + }, + { + NULL, "haus2", + 4, 0, 1, + -1, -1, 0x3e, + 8.0f, + "int07", + -69.2376f, 8.0f, -6.8008099f, + NULL, + }, + { + NULL, "haus3", + 4, 0, 1, + -1, -1, 0x3e, + 7.0f, + "edg01_24", + -69.0596f, 7.0f, -24.4928f, + NULL, + }, + { + NULL, "Pizza", + 4, 0, 1, + -1, -1, 0x10, + 0.0f, + "int37", + -17.9438f, 0.0f, -46.827999f, + NULL, + }, +}; +// clang-format on + +// GLOBAL: LEGO1 0x100f3738 +MxU32 g_buildingCycle1Length = 6; // GLOBAL: LEGO1 0x100f37c8 char* LegoBuildingManager::g_customizeAnimFile = NULL; // GLOBAL: LEGO1 0x100f37cc -int g_buildingManagerConfig = 1; +MxS32 g_buildingManagerConfig = 1; + +// GLOBAL: LEGO1 0x10104c30 +LegoBuildingInfo g_buildingInfo[16]; + +// GLOBAL: LEGO1 0x100f3748 +MxS32 g_buildingCycle2Length[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0}; // FUNCTION: LEGO1 0x1002f8b0 void LegoBuildingManager::configureLegoBuildingManager(MxS32 p_buildingManagerConfig) @@ -20,22 +212,72 @@ LegoBuildingManager::LegoBuildingManager() Init(); } -// STUB: LEGO1 0x1002f960 +// FUNCTION: LEGO1 0x1002f960 LegoBuildingManager::~LegoBuildingManager() { - // TODO + delete g_customizeAnimFile; } -// STUB: LEGO1 0x1002f9d0 +// FUNCTION: LEGO1 0x1002f9d0 void LegoBuildingManager::Init() { - // TODO + for (MxS32 i = 0; i < _countof(g_buildingInfo); i++) { + g_buildingInfo[i] = g_buildingInfoInit[i]; + } + + m_nextVariant = 0; + m_unk0x09 = 0; + m_unk0x20 = 0; + m_unk0x24 = 0; + m_unk0x28 = 0; } -// STUB: LEGO1 0x1002fa00 +// FUNCTION: LEGO1 0x1002fa00 +// FUNCTION: BETA10 0x10063ad1 void LegoBuildingManager::FUN_1002fa00() { - // TODO + MxS32 i; + LegoWorld* world = CurrentWorld(); + + for (i = 0; i < _countof(g_buildingInfo); i++) { + UpdatePosition(i, world); + } + + if (g_buildingManagerConfig <= 1) { + LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingDataHausName[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]); + if (entity) { + entity->GetROI()->SetVisibility(m_nextVariant == i); + } + } + } + + m_unk0x09 = 0; +} + +// FUNCTION: LEGO1 0x1002fa90 +// FUNCTION: BETA10 0x10063b88 +void LegoBuildingManager::UpdatePosition(MxS32 p_index, LegoWorld* p_world) +{ + LegoEntity* entity = (LegoEntity*) p_world->Find("MxEntity", g_buildingInfo[p_index].m_hausName); + + if (entity) { + entity->SetType(LegoEntity::e_building); + g_buildingInfo[p_index].m_entity = entity; + LegoROI* roi = entity->GetROI(); + AdjustHeight(p_index); + MxMatrix mat = roi->GetLocal2World(); + mat[3][1] = g_buildingInfo[p_index].m_unk0x014; + roi->FUN_100a46b0(mat); + VideoManager()->Get3DManager()->Moved(*roi); + } } // STUB: LEGO1 0x1002fb30 @@ -44,25 +286,214 @@ void LegoBuildingManager::FUN_1002fb30() // TODO } -// STUB: LEGO1 0x1002fb80 +// FUNCTION: LEGO1 0x1002fb80 +// FUNCTION: BETA10 0x10063cae MxResult LegoBuildingManager::Write(LegoStorage* p_storage) { - return SUCCESS; + MxResult result = FAILURE; + + for (MxS32 i = 0; i < _countof(g_buildingInfo); i++) { + LegoBuildingInfo* info = &g_buildingInfo[i]; + + if (p_storage->Write(&info->m_cycle1, sizeof(info->m_cycle1)) != SUCCESS) { + goto done; + } + if (p_storage->Write(&info->m_cycle2, sizeof(info->m_cycle2)) != SUCCESS) { + goto done; + } + if (p_storage->Write(&info->m_cycle3, sizeof(info->m_cycle3)) != SUCCESS) { + goto done; + } + if (p_storage->Write(&info->m_initialUnk0x11, sizeof(info->m_initialUnk0x11)) != SUCCESS) { + goto done; + } + } + + if (p_storage->Write(&m_nextVariant, sizeof(m_nextVariant)) != SUCCESS) { + goto done; + } + + result = SUCCESS; + +done: + return result; } -// STUB: LEGO1 0x1002fc10 +// FUNCTION: LEGO1 0x1002fc10 +// FUNCTION: BETA10 0x10063dde MxResult LegoBuildingManager::Read(LegoStorage* p_storage) { - return SUCCESS; + MxResult result = FAILURE; + + for (MxS32 i = 0; i < _countof(g_buildingInfo); i++) { + LegoBuildingInfo* info = &g_buildingInfo[i]; + + if (p_storage->Read(&info->m_cycle1, sizeof(info->m_cycle1)) != SUCCESS) { + goto done; + } + if (p_storage->Read(&info->m_cycle2, sizeof(info->m_cycle2)) != SUCCESS) { + goto done; + } + if (p_storage->Read(&info->m_cycle3, sizeof(info->m_cycle3)) != SUCCESS) { + goto done; + } + if (p_storage->Read(&info->m_unk0x11, sizeof(info->m_unk0x11)) != SUCCESS) { + goto done; + } + + info->m_initialUnk0x11 = info->m_unk0x11; + AdjustHeight(i); + } + + if (p_storage->Read(&m_nextVariant, sizeof(m_nextVariant)) != SUCCESS) { + goto done; + } + + if (g_buildingManagerConfig <= 1) { + m_nextVariant = 0; + } + + result = SUCCESS; + +done: + return result; } -// STUB: LEGO1 0x1002fdb0 -MxBool LegoBuildingManager::FUN_1002fdb0(LegoEntity* p_entity) +// FUNCTION: LEGO1 0x1002fcc0 +// FUNCTION: BETA10 0x10063f1a +void LegoBuildingManager::AdjustHeight(MxS32 p_index) { - // TODO + if (g_buildingInfo[p_index].m_unk0x11 > 0) { + float value = g_buildingDataDownshift[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]; + } + else if (g_buildingInfo[p_index].m_unk0x11 == 0) { + float value = g_buildingDataDownshift[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]; + + if (g_buildingInfo[p_index].m_entity != NULL) { + LegoROI* roi = g_buildingInfo[p_index].m_entity->GetROI(); + if (roi != NULL) { + roi->SetVisibility(FALSE); + } + } + } + else { + g_buildingInfo[p_index].m_unk0x014 = g_buildingInfoInit[p_index].m_unk0x014; + } +} + +// FUNCTION: LEGO1 0x1002fd70 +// FUNCTION: BETA10 0x10063fc9 +LegoBuildingInfo* LegoBuildingManager::GetInfo(LegoEntity* p_entity) +{ + MxS32 i; + + for (i = 0; i < _countof(g_buildingInfo); i++) { + if (g_buildingInfo[i].m_entity == p_entity) { + break; + } + } + + if (i < _countof(g_buildingInfo)) { + return &g_buildingInfo[i]; + } + + return NULL; +} + +// FUNCTION: LEGO1 0x1002fdb0 +// FUNCTION: BETA10 0x10064101 +MxBool LegoBuildingManager::IncrementVariant(LegoEntity* p_entity) +{ + if (g_buildingManagerConfig <= 1) { + return TRUE; + } + + LegoBuildingInfo* info = GetInfo(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)) { + m_nextVariant = 0; + } + + roi->SetVisibility(FALSE); + info->m_hausName = g_buildingDataHausName[m_nextVariant]; + UpdatePosition(12, CurrentWorld()); + + if (info->m_entity != NULL) { + info->m_entity->GetROI()->SetVisibility(TRUE); + } + + return TRUE; + } + return FALSE; } +// FUNCTION: LEGO1 0x1002fe40 +// FUNCTION: BETA10 0x100641d3 +MxBool LegoBuildingManager::FUN_1002fe40(LegoEntity* p_entity) +{ + MxBool result = FALSE; + LegoBuildingInfo* info = GetInfo(p_entity); + + if (info != NULL && info->m_flags & LegoBuildingInfo::c_bit2) { + info->m_cycle1++; + + if (info->m_cycle1 >= g_buildingCycle1Length) { + info->m_cycle1 = 0; + } + + result = TRUE; + } + + return result; +} + +// FUNCTION: LEGO1 0x1002fe80 +// FUNCTION: BETA10 0x10064242 +MxBool LegoBuildingManager::FUN_1002fe80(LegoEntity* p_entity) +{ + MxBool result = FALSE; + LegoBuildingInfo* info = GetInfo(p_entity); + + if (info != NULL && info->m_flags & LegoBuildingInfo::c_bit3) { + info->m_cycle2++; + + if (info->m_cycle2 >= g_buildingCycle2Length[info - g_buildingInfo]) { + info->m_cycle2 = 0; + } + + result = TRUE; + } + + return result; +} + +// FUNCTION: LEGO1 0x1002fed0 +// FUNCTION: BETA10 0x100642c2 +MxBool LegoBuildingManager::FUN_1002fed0(LegoEntity* p_entity) +{ + MxBool result = FALSE; + LegoBuildingInfo* info = GetInfo(p_entity); + + if (info != NULL && info->m_flags & LegoBuildingInfo::c_bit4) { + info->m_cycle3++; + + if (info->m_cycle3 > 3) { + info->m_cycle3 = 0; + } + + result = TRUE; + } + + return result; +} + // STUB: LEGO1 0x1002ff40 MxU32 LegoBuildingManager::FUN_1002ff40(LegoEntity*, MxBool) { @@ -89,10 +520,34 @@ void LegoBuildingManager::SetCustomizeAnimFile(const char* p_value) } } -// STUB: LEGO1 0x10030000 -void LegoBuildingManager::FUN_10030000(LegoEntity* p_entity) +// FUNCTION: LEGO1 0x10030000 +MxBool LegoBuildingManager::FUN_10030000(LegoEntity* p_entity) { - // TODO + LegoBuildingInfo* info = GetInfo(p_entity); + + if (info == NULL) { + return FALSE; + } + + return FUN_10030030(info - g_buildingInfo); +} + +// STUB: LEGO1 0x10030030 +MxBool LegoBuildingManager::FUN_10030030(MxS32 p_index) +{ + return TRUE; +} + +// FUNCTION: LEGO1 0x10030110 +MxBool LegoBuildingManager::FUN_10030110(LegoBuildingInfo* p_data) +{ + for (MxS32 i = 0; i < _countof(g_buildingInfo); i++) { + if (&g_buildingInfo[i] == p_data) { + return FUN_10030030(i); + } + } + + return FALSE; } // STUB: LEGO1 0x10030220 diff --git a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp index d5ba428b..a3fc9e2d 100644 --- a/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp +++ b/LEGO1/lego/legoomni/src/common/legocharactermanager.cpp @@ -40,7 +40,7 @@ MxU32 g_unk0x100fc4ec = 2; MxU32 g_unk0x100fc4f0 = 0; // GLOBAL: LEGO1 0x10104f20 -LegoCharacterInfo g_chracterInfo[66]; +LegoCharacterInfo g_characterInfo[66]; // FUNCTION: LEGO1 0x10082a20 LegoCharacterManager::LegoCharacterManager() @@ -55,22 +55,22 @@ LegoCharacterManager::LegoCharacterManager() // FUNCTION: LEGO1 0x10083270 void LegoCharacterManager::Init() { - for (MxS32 i = 0; i < _countof(g_chracterInfo); i++) { - g_chracterInfo[i] = g_characterInfoInit[i]; + for (MxS32 i = 0; i < _countof(g_characterInfo); i++) { + g_characterInfo[i] = g_characterInfoInit[i]; } } // FUNCTION: LEGO1 0x100832a0 void LegoCharacterManager::FUN_100832a0() { - for (MxS32 i = 0; i < _countof(g_chracterInfo); i++) { - LegoCharacterInfo* info = GetInfo(g_chracterInfo[i].m_name); + for (MxS32 i = 0; i < _countof(g_characterInfo); i++) { + LegoCharacterInfo* info = GetInfo(g_characterInfo[i].m_name); if (info != NULL) { LegoExtraActor* actor = info->m_actor; if (actor != NULL && actor->IsA("LegoExtraActor")) { - LegoROI* roi = g_chracterInfo[i].m_roi; + LegoROI* roi = g_characterInfo[i].m_roi; MxU32 refCount = GetRefCount(roi); while (refCount != 0) { @@ -87,8 +87,8 @@ MxResult LegoCharacterManager::Write(LegoStorage* p_storage) { MxResult result = FAILURE; - for (MxS32 i = 0; i < _countof(g_chracterInfo); i++) { - LegoCharacterInfo* info = &g_chracterInfo[i]; + for (MxS32 i = 0; i < _countof(g_characterInfo); i++) { + LegoCharacterInfo* info = &g_characterInfo[i]; if (p_storage->Write(&info->m_unk0x0c, sizeof(info->m_unk0x0c)) != SUCCESS) { goto done; @@ -142,8 +142,8 @@ MxResult LegoCharacterManager::Read(LegoStorage* p_storage) { MxResult result = FAILURE; - for (MxS32 i = 0; i < _countof(g_chracterInfo); i++) { - LegoCharacterInfo* info = &g_chracterInfo[i]; + for (MxS32 i = 0; i < _countof(g_characterInfo); i++) { + LegoCharacterInfo* info = &g_characterInfo[i]; if (p_storage->Read(&info->m_unk0x0c, sizeof(info->m_unk0x0c)) != SUCCESS) { goto done; @@ -588,8 +588,8 @@ MxBool LegoCharacterManager::FUN_100849a0(LegoROI* p_roi, LegoTextureInfo* p_tex // FUNCTION: LEGO1 0x10084c00 MxBool LegoCharacterManager::Exists(const char* p_key) { - for (MxU32 i = 0; i < _countof(g_chracterInfo); i++) { - if (!strcmpi(g_chracterInfo[i].m_name, p_key)) { + for (MxU32 i = 0; i < _countof(g_characterInfo); i++) { + if (!strcmpi(g_characterInfo[i].m_name, p_key)) { return TRUE; } } @@ -614,14 +614,14 @@ LegoCharacterInfo* LegoCharacterManager::GetInfo(const char* p_key) { MxU32 i; - for (i = 0; i < _countof(g_chracterInfo); i++) { - if (!strcmpi(g_chracterInfo[i].m_name, p_key)) { + for (i = 0; i < _countof(g_characterInfo); i++) { + if (!strcmpi(g_characterInfo[i].m_name, p_key)) { break; } } - if (i < _countof(g_chracterInfo)) { - return &g_chracterInfo[i]; + if (i < _countof(g_characterInfo)) { + return &g_characterInfo[i]; } return NULL; @@ -632,14 +632,14 @@ LegoCharacterInfo* LegoCharacterManager::GetInfo(LegoROI* p_roi) { MxU32 i; - for (i = 0; i < _countof(g_chracterInfo); i++) { - if (g_chracterInfo[i].m_roi == p_roi) { + for (i = 0; i < _countof(g_characterInfo); i++) { + if (g_characterInfo[i].m_roi == p_roi) { break; } } - if (i < _countof(g_chracterInfo)) { - return &g_chracterInfo[i]; + if (i < _countof(g_characterInfo)) { + return &g_characterInfo[i]; } return NULL; diff --git a/LEGO1/lego/legoomni/src/entity/legoentity.cpp b/LEGO1/lego/legoomni/src/entity/legoentity.cpp index d1f145c2..192fc804 100644 --- a/LEGO1/lego/legoomni/src/entity/legoentity.cpp +++ b/LEGO1/lego/legoomni/src/entity/legoentity.cpp @@ -294,7 +294,7 @@ void LegoEntity::VTable0x3c() PlantManager()->FUN_100269e0(this); break; case e_building: - BuildingManager()->FUN_1002fdb0(this); + BuildingManager()->IncrementVariant(this); break; }