Isle
Loading...
Searching...
No Matches
legobuildingmanager.cpp
Go to the documentation of this file.
2
5#include "legoentity.h"
6#include "legopathboundary.h"
7#include "legosoundmanager.h"
8#include "legovideomanager.h"
9#include "legoworld.h"
10#include "misc.h"
11#include "misc/legostorage.h"
12#include "mxdebug.h"
13#include "mxmisc.h"
14#include "mxticklemanager.h"
15#include "mxtimer.h"
16
17#include <vec.h>
18
22
23// GLOBAL: LEGO1 0x100f3410
24const char* g_buildingInfoVariants[5] = {
25 "haus1",
26 "haus4",
27 "haus5",
28 "haus6",
29 "haus7",
30};
31
32// clang-format off
33// GLOBAL: LEGO1 0x100f3428
35 0.0f, 1.0f, 1.0f, 1.0f,
36 1.0f, 1.0f, 1.0f, 1.0f,
37 1.0f, 1.0f, 1.0f, 1.0f,
38 1.0f, 1.0f, 1.0f, 1.0f,
39};
40
41// GLOBAL: LEGO1 0x100f3468
43 5, 5, 5, 5,
44 3, 5, 5, 5,
45 3, 5, 5, 5,
46 5, 5, 5, 5,
47};
48
49// GLOBAL: LEGO1 0x100f3478
51 {
52 NULL, "infocen",
53 4, 0, 1,
54 -1, -1, 0x00,
55 8.99999f,
56 "edg02_74",
57 84.79617f, 9.0f, -10.2189f,
58 NULL,
59 },
60 {
61 NULL, "policsta",
62 4, 0, 1,
63 -1, -1, 0x10,
64 0.999992f,
65 "int33",
66 67.28488, 1.0f, -85.3917,
67 NULL,
68 },
69 {
70 NULL, "Jail",
71 4, 0, 1,
72 -1, -1, 0x10,
73 0.0f,
74 "edg02_50",
75 93.245659f, 0.0f, -48.7773f,
76 NULL,
77 },
78 {
79 NULL, "races",
80 4, 0, 1,
81 -1, -1, 0x10,
82 0.0f,
83 "int14",
84 -21.7321f, 0.0f, 11.23354f,
85 NULL,
86 },
87 {
88 NULL, "medcntr",
89 4, 0, 1,
90 -1, -1, 0x10,
91 3.99071f,
92 "edg02_27",
93 86.020737f, 4.0f, 31.35498f,
94 NULL,
95 },
96 {
97 NULL, "gas",
98 4, 0, 1,
99 -1, -1, 0x10,
100 0.0f,
101 "int24",
102 26.32025f, 0.0f, -2.28938f,
103 NULL,
104 },
105 {
106 NULL, "beach",
107 4, 0, 1,
108 -1, -1, 0x10,
109 -1.8125f,
110 "edg00_46",
111 14.375f, -1.3125f, -56.75f,
112 NULL,
113 },
114 {
115 NULL, "racef",
116 4, 0, 1,
117 -1, -1, 0x10,
118 0.0f,
119 "edg03_03",
120 -4.15951f, 0.0f, 5.2003198f,
121 NULL,
122 },
123 {
124 NULL, "racej",
125 4, 0, 1,
126 -1, -1, 0x10,
127 0.0f,
128 "edg03_03",
129 -4.15951f, 0.0f, 5.2003198f,
130 NULL,
131 },
132 {
133 NULL, "Store",
134 4, 0, 1,
135 -1, -1, 0x3e,
136 2.0f,
137 "edg02_60",
138 -49.4744f, 2.0f, -56.6276f,
139 NULL,
140 },
141 {
142 NULL, "Bank",
143 4, 0, 1,
144 -1, -1, 0x3e,
145 0.0f,
146 "edg02_36",
147 18.53531f, 0.0f, -16.6053f,
148 NULL,
149 },
150 {
151 NULL, "Post",
152 4, 0, 1,
153 -1, -1, 0x3e,
154 0.0f,
155 "edg02_58",
156 -33.5413f, 0.0f, -55.1791f,
157 NULL,
158 },
159 {
160 NULL, "haus1",
161 4, 0, 1,
162 -1, -1, 0x3f,
163 7.0625f,
164 "int11",
165 -62.7827f, 7.0f, -45.2215f,
166 NULL,
167 },
168 {
169 NULL, "haus2",
170 4, 0, 1,
171 -1, -1, 0x3e,
172 8.0f,
173 "int07",
174 -69.2376f, 8.0f, -6.8008099f,
175 NULL,
176 },
177 {
178 NULL, "haus3",
179 4, 0, 1,
180 -1, -1, 0x3e,
181 7.0f,
182 "edg01_24",
183 -69.0596f, 7.0f, -24.4928f,
184 NULL,
185 },
186 {
187 NULL, "Pizza",
188 4, 0, 1,
189 -1, -1, 0x10,
190 0.0f,
191 "int37",
192 -17.9438f, 0.0f, -46.827999f,
193 NULL,
194 },
195};
196// clang-format on
197
198// GLOBAL: LEGO1 0x100f3738
199MxU32 LegoBuildingManager::g_maxSound = 6;
200
201// GLOBAL: LEGO1 0x100f373c
203
204// GLOBAL: LEGO1 0x100f3740
206
207// clang-format off
208// GLOBAL: LEGO1 0x100f3788
210 0x00, 0x00, 0x00, 0x00,
211 0x00, 0x00, 0x00, 0x00,
212 0x00, 0x46, 0x49, 0x4c,
213 0x4f, 0x52, 0x55, 0x00,
214};
215// clang-format on
216
217// GLOBAL: LEGO1 0x100f37c8
218char* LegoBuildingManager::g_customizeAnimFile = NULL;
219
220// GLOBAL: LEGO1 0x100f37cc
222
223// GLOBAL: LEGO1 0x10104c30
224// GLOBAL: BETA10 0x10209fa0
226
227// GLOBAL: LEGO1 0x100f3748
228MxS32 LegoBuildingManager::g_maxMove[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 0};
229
230// FUNCTION: LEGO1 0x1002f8b0
232{
233 g_buildingManagerConfig = p_buildingManagerConfig;
234}
235
236// FUNCTION: LEGO1 0x1002f8c0
238{
239 Init();
240}
241
242// FUNCTION: LEGO1 0x1002f960
244{
245 delete[] g_customizeAnimFile;
246}
247
248// FUNCTION: LEGO1 0x1002f9d0
250{
251 for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
253 }
254
255 m_nextVariant = 0;
256 m_unk0x09 = FALSE;
257 m_numEntries = 0;
258 m_sound = NULL;
259 m_unk0x28 = FALSE;
260}
261
262// FUNCTION: LEGO1 0x1002fa00
263// FUNCTION: BETA10 0x10063ad1
265{
266 MxS32 i;
267 LegoWorld* world = CurrentWorld();
268
269 for (i = 0; i < sizeOfArray(g_buildingInfo); i++) {
270 CreateBuilding(i, world);
271 }
272
273 if (g_buildingManagerConfig <= 1) {
274 LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingInfoVariants[0]);
275 if (entity) {
276 entity->GetROI()->SetVisibility(TRUE);
277 m_unk0x09 = FALSE;
278 }
279 }
280 else {
281 for (i = 0; i < sizeOfArray(g_buildingInfoVariants); i++) {
282 LegoEntity* entity = (LegoEntity*) world->Find("MxEntity", g_buildingInfoVariants[i]);
283 if (entity) {
284 entity->GetROI()->SetVisibility(m_nextVariant == i);
285 }
286 }
287 }
288
289 m_unk0x09 = FALSE;
290}
291
292// FUNCTION: LEGO1 0x1002fa90
293// FUNCTION: BETA10 0x10063b88
295{
296 LegoEntity* entity = (LegoEntity*) p_world->Find("MxEntity", g_buildingInfo[p_index].m_variant);
297
298 if (entity) {
300 g_buildingInfo[p_index].m_entity = entity;
301 LegoROI* roi = entity->GetROI();
302 AdjustHeight(p_index);
303 MxMatrix mat = roi->GetLocal2World();
304 mat[3][1] = g_buildingInfo[p_index].m_unk0x14;
306 VideoManager()->Get3DManager()->Moved(*roi);
307 }
308}
309
310// FUNCTION: LEGO1 0x1002fb30
312{
313 MxU32 i;
314
315 for (i = 0; i < sizeOfArray(g_buildingInfo); i++) {
317 }
318
319 m_unk0x09 = FALSE;
320
321 for (i = 0; i < m_numEntries; i++) {
322 delete m_entries[i];
323 }
324
325 m_numEntries = 0;
326}
327
328// FUNCTION: LEGO1 0x1002fb80
329// FUNCTION: BETA10 0x10063cae
331{
332 MxResult result = FAILURE;
333
334 for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
336
337 if (p_storage->Write(&info->m_sound, sizeof(info->m_sound)) != SUCCESS) {
338 goto done;
339 }
340 if (p_storage->Write(&info->m_move, sizeof(info->m_move)) != SUCCESS) {
341 goto done;
342 }
343 if (p_storage->Write(&info->m_mood, sizeof(info->m_mood)) != SUCCESS) {
344 goto done;
345 }
346 if (p_storage->Write(&info->m_initialUnk0x11, sizeof(info->m_initialUnk0x11)) != SUCCESS) {
347 goto done;
348 }
349 }
350
351 if (p_storage->Write(&m_nextVariant, sizeof(m_nextVariant)) != SUCCESS) {
352 goto done;
353 }
354
355 result = SUCCESS;
356
357done:
358 return result;
359}
360
361// FUNCTION: LEGO1 0x1002fc10
362// FUNCTION: BETA10 0x10063dde
364{
365 MxResult result = FAILURE;
366
367 for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
369
370 if (p_storage->Read(&info->m_sound, sizeof(info->m_sound)) != SUCCESS) {
371 goto done;
372 }
373 if (p_storage->Read(&info->m_move, sizeof(info->m_move)) != SUCCESS) {
374 goto done;
375 }
376 if (p_storage->Read(&info->m_mood, sizeof(info->m_mood)) != SUCCESS) {
377 goto done;
378 }
379 if (p_storage->Read(&info->m_unk0x11, sizeof(info->m_unk0x11)) != SUCCESS) {
380 goto done;
381 }
382
383 info->m_initialUnk0x11 = info->m_unk0x11;
384 AdjustHeight(i);
385 }
386
387 if (p_storage->Read(&m_nextVariant, sizeof(m_nextVariant)) != SUCCESS) {
388 goto done;
389 }
390
391 if (g_buildingManagerConfig <= 1) {
392 m_nextVariant = 0;
393 }
394
395 result = SUCCESS;
396
397done:
398 return result;
399}
400
401// FUNCTION: LEGO1 0x1002fcc0
402// FUNCTION: BETA10 0x10063f1a
404{
405 if (g_buildingInfo[p_index].m_unk0x11 > 0) {
406 float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11;
407 g_buildingInfo[p_index].m_unk0x14 =
409 }
410 else if (g_buildingInfo[p_index].m_unk0x11 == 0) {
411 float value = g_buildingInfoDownshift[p_index] - g_buildingInfo[p_index].m_unk0x11;
412 g_buildingInfo[p_index].m_unk0x14 =
414
415 if (g_buildingInfo[p_index].m_entity != NULL) {
416 LegoROI* roi = g_buildingInfo[p_index].m_entity->GetROI();
417 if (roi != NULL) {
418 roi->SetVisibility(FALSE);
419 }
420 }
421 }
422 else {
424 }
425}
426
427// FUNCTION: LEGO1 0x1002fd70
428// FUNCTION: BETA10 0x10063fc9
430{
431 MxS32 i;
432
433 for (i = 0; i < sizeOfArray(g_buildingInfo); i++) {
434 if (g_buildingInfo[i].m_entity == p_entity) {
435 break;
436 }
437 }
438
439 if (i < sizeOfArray(g_buildingInfo)) {
440 return &g_buildingInfo[i];
441 }
442
443 return NULL;
444}
445
446// FUNCTION: LEGO1 0x1002fdb0
447// FUNCTION: BETA10 0x10064101
449{
450 if (g_buildingManagerConfig <= 1) {
451 return TRUE;
452 }
453
454 LegoBuildingInfo* info = GetInfo(p_entity);
455
456 if (info != NULL && info->m_flags & LegoBuildingInfo::c_hasVariants && info->m_unk0x11 == -1) {
457 LegoROI* roi = p_entity->GetROI();
458 if (++m_nextVariant >= sizeOfArray(g_buildingInfoVariants)) {
459 m_nextVariant = 0;
460 }
461
462 roi->SetVisibility(FALSE);
463 info->m_variant = g_buildingInfoVariants[m_nextVariant];
465
466 if (info->m_entity != NULL) {
468 }
469
470 return TRUE;
471 }
472
473 return FALSE;
474}
475
476// FUNCTION: LEGO1 0x1002fe40
477// FUNCTION: BETA10 0x100641d3
479{
480 MxBool result = FALSE;
481 LegoBuildingInfo* info = GetInfo(p_entity);
482
483 if (info != NULL && info->m_flags & LegoBuildingInfo::c_hasSounds) {
484 info->m_sound++;
485
486 if (info->m_sound >= g_maxSound) {
487 info->m_sound = 0;
488 }
489
490 result = TRUE;
491 }
492
493 return result;
494}
495
496// FUNCTION: LEGO1 0x1002fe80
497// FUNCTION: BETA10 0x10064242
499{
500 MxBool result = FALSE;
501 LegoBuildingInfo* info = GetInfo(p_entity);
502
503 if (info != NULL && info->m_flags & LegoBuildingInfo::c_hasMoves) {
504 info->m_move++;
505
506 if (info->m_move >= g_maxMove[info - g_buildingInfo]) {
507 info->m_move = 0;
508 }
509
510 result = TRUE;
511 }
512
513 return result;
514}
515
516// FUNCTION: LEGO1 0x1002fed0
517// FUNCTION: BETA10 0x100642c2
519{
520 MxBool result = FALSE;
521 LegoBuildingInfo* info = GetInfo(p_entity);
522
523 if (info != NULL && info->m_flags & LegoBuildingInfo::c_hasMoods) {
524 info->m_mood++;
525
526 if (info->m_mood > 3) {
527 info->m_mood = 0;
528 }
529
530 result = TRUE;
531 }
532
533 return result;
534}
535
536// FUNCTION: LEGO1 0x1002ff00
537// FUNCTION: BETA10 0x1006432d
539{
540 LegoBuildingInfo* info = GetInfo(p_entity);
541
542 if (info != NULL && info->m_flags & LegoBuildingInfo::c_hasMoves) {
543 return g_buildingAnimationId[info - g_buildingInfo] + info->m_move;
544 }
545
546 return 0;
547}
548
549// FUNCTION: LEGO1 0x1002ff40
550// FUNCTION: BETA10 0x10064398
552{
553 LegoBuildingInfo* info = GetInfo(p_entity);
554
555 if (info == NULL || !(info->m_flags & LegoBuildingInfo::c_hasSounds)) {
556 return 0;
557 }
558
559 if (p_state) {
560 return info->m_mood + g_unk0x100f3740;
561 }
562
563 if (info != NULL) {
564 return info->m_sound + g_unk0x100f373c;
565 }
566
567 return 0;
568}
569
570// FUNCTION: LEGO1 0x1002ff90
572{
573 if (g_customizeAnimFile != NULL) {
574 delete[] g_customizeAnimFile;
575 }
576
577 if (p_value != NULL) {
578 g_customizeAnimFile = new char[strlen(p_value) + 1];
579
580 if (g_customizeAnimFile != NULL) {
581 strcpy(g_customizeAnimFile, p_value);
582 }
583 }
584 else {
585 g_customizeAnimFile = NULL;
586 }
587}
588
589// FUNCTION: LEGO1 0x10030000
591{
592 LegoBuildingInfo* info = GetInfo(p_entity);
593
594 if (info == NULL) {
595 return FALSE;
596 }
597
598 return FUN_10030030(info - g_buildingInfo);
599}
600
602{
603 if (p_index >= sizeOfArray(g_buildingInfo)) {
604 return NULL;
605 }
606
607 return &g_buildingInfo[p_index];
608}
609
610// FUNCTION: LEGO1 0x10030030
612{
613 if (p_index >= sizeOfArray(g_buildingInfo)) {
614 return FALSE;
615 }
616
617 LegoBuildingInfo* info = GetBuildingInfo(p_index);
618 if (!info) {
619 return FALSE;
620 }
621
622 MxBool result = TRUE;
623
624 if (info->m_unk0x11 < 0) {
625 info->m_unk0x11 = g_buildingInfoDownshift[p_index];
626 }
627
628 if (info->m_unk0x11 <= 0) {
629 result = FALSE;
630 }
631 else {
632 LegoROI* roi = info->m_entity->GetROI();
633
634 info->m_unk0x11 -= 2;
635 if (info->m_unk0x11 == 1) {
636 info->m_unk0x11 = 0;
637 roi->SetVisibility(FALSE);
638 }
639 else {
640 AdjustHeight(p_index);
641 MxMatrix mat = roi->GetLocal2World();
642 mat[3][1] = g_buildingInfo[p_index].m_unk0x14;
644 VideoManager()->Get3DManager()->Moved(*roi);
645 }
646 }
647
648 return result;
649}
650
651// FUNCTION: LEGO1 0x10030110
653{
654 for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
655 if (&g_buildingInfo[i] == p_data) {
656 return FUN_10030030(i);
657 }
658 }
659
660 return FALSE;
661}
662
663// FUNCTION: LEGO1 0x10030150
664void LegoBuildingManager::ScheduleAnimation(LegoEntity* p_entity, MxLong p_length, MxBool p_haveSound, MxBool p_unk0x28)
665{
666 m_world = CurrentWorld();
667
668 if (p_haveSound) {
669 m_sound = SoundManager()->GetCacheSoundManager()->FindSoundByKey("bcrash");
670 m_sound->SetDistance(35, 60);
671 }
672
673 if (m_numEntries == 0) {
674 m_unk0x28 = p_unk0x28;
675 TickleManager()->RegisterClient(this, 50);
676 }
677
678 AnimEntry* entry = m_entries[m_numEntries] = new AnimEntry;
679 m_numEntries++;
680
681 entry->m_entity = p_entity;
682 entry->m_roi = p_entity->GetROI();
683
684 MxLong time = Timer()->GetTime();
685 time += p_length;
686 entry->m_time = time + 1000;
687
688 entry->m_unk0x0c = entry->m_roi->GetWorldPosition()[1];
689 entry->m_muted = p_haveSound == FALSE;
690 FUN_100307b0(p_entity, -2);
691}
692
693// FUNCTION: LEGO1 0x10030220
695{
696 MxLong time = Timer()->GetTime();
697
698 if (m_numEntries != 0) {
699 for (MxS32 i = 0; i < m_numEntries; i++) {
700 AnimEntry** ppEntry = &m_entries[i];
701 AnimEntry* entry = *ppEntry;
702
703 if (m_world != CurrentWorld() || !entry->m_entity) {
704 delete entry;
705 m_numEntries--;
706
707 if (m_numEntries != i) {
708 m_entries[i] = m_entries[m_numEntries];
709 m_entries[m_numEntries] = NULL;
710 }
711
712 break;
713 }
714
715 if (entry->m_time - time > 1000) {
716 break;
717 }
718
719 if (!entry->m_muted) {
720 entry->m_muted = TRUE;
721 SoundManager()->GetCacheSoundManager()->Play(m_sound, entry->m_roi->GetName(), FALSE);
722 }
723
724 MxMatrix local48;
725 MxMatrix locald8;
726
727 MxMatrix local120(entry->m_roi->GetLocal2World());
728 Mx3DPointFloat local134(local120[3]);
729
730 ZEROVEC3(local120[3]);
731
732 locald8.SetIdentity();
733 local48 = local120;
734
735 local134[1] = sin(((entry->m_time - time) * 10) * 0.0062831999f) * 0.4 + (entry->m_unk0x0c -= 0.05);
736 SET3(local120[3], local134);
737
739 VideoManager()->Get3DManager()->Moved(*entry->m_roi);
740
741 if (entry->m_time < time) {
742 LegoBuildingInfo* info = GetInfo(entry->m_entity);
743
744 if (info->m_unk0x11 && !m_unk0x28) {
745 MxS32 index = info - g_buildingInfo;
746 AdjustHeight(index);
747 MxMatrix mat = entry->m_roi->GetLocal2World();
748 mat[3][1] = g_buildingInfo[index].m_unk0x14;
750 VideoManager()->Get3DManager()->Moved(*entry->m_roi);
751 }
752 else {
753 info->m_unk0x11 = 0;
754 entry->m_roi->SetVisibility(FALSE);
755 }
756
757 delete entry;
758 m_numEntries--;
759
760 if (m_numEntries != i) {
761 i--;
762 *ppEntry = m_entries[m_numEntries];
763 m_entries[m_numEntries] = NULL;
764 }
765 }
766 }
767 }
768 else {
770 }
771
772 return SUCCESS;
773}
774
775// FUNCTION: LEGO1 0x10030590
776// FUNCTION: BETA10 0x1006474c
778{
779 for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
782 AdjustHeight(i);
783
784 if (g_buildingInfo[i].m_entity != NULL) {
786 MxMatrix mat = roi->GetLocal2World();
787 mat[3][1] = g_buildingInfo[i].m_unk0x14;
789 VideoManager()->Get3DManager()->Moved(*roi);
790 }
791 }
792}
793
794// FUNCTION: LEGO1 0x10030630
795// FUNCTION: BETA10 0x100648ab
797{
798 LegoWorld* world = CurrentWorld();
799
800 if (world == NULL) {
801 return FAILURE;
802 }
803
804 for (MxS32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
805 if (g_buildingInfo[i].m_entity != NULL && g_buildingInfo[i].m_boundaryName != NULL) {
806 g_buildingInfo[i].m_boundary = world->FindPathBoundary(g_buildingInfo[i].m_boundaryName);
807
808 if (g_buildingInfo[i].m_boundary != NULL) {
809 Mx3DPointFloat position(g_buildingInfo[i].m_x, g_buildingInfo[i].m_y, g_buildingInfo[i].m_z);
811
812 for (MxS32 j = 0; j < boundary->GetNumEdges(); j++) {
813 Mx4DPointFloat* normal = boundary->GetEdgeNormal(j);
814
815 if (position.Dot(*normal, position) + (*normal).index_operator(3) < -0.001) {
816 MxTrace(
817 "Building %d shot location (%g, %g, %g) is not in boundary %s.\n",
818 i,
819 position[0],
820 position[1],
821 position[2],
822 boundary->GetName()
823 );
825 break;
826 }
827 }
828
829 if (g_buildingInfo[i].m_boundary != NULL) {
831
832 if (position.Dot(position, unk0x14) + unk0x14.index_operator(3) > 0.001 ||
833 position.Dot(position, unk0x14) + unk0x14.index_operator(3) < -0.001) {
834
836 -((position[0] * unk0x14.index_operator(0) + unk0x14.index_operator(3) +
837 position[2] * unk0x14.index_operator(2)) /
838 unk0x14.index_operator(1));
839
840 MxTrace(
841 "Building %d shot location (%g, %g, %g) is not on plane of boundary %s...adjusting to (%g, "
842 "%g, "
843 "%g)\n",
844 i,
845 position[0],
846 position[1],
847 position[2],
848 g_buildingInfo[i].m_boundary->GetName(),
849 position[0],
851 position[2]
852 );
853 }
854 }
855 }
856 else {
857 MxTrace("Building %d is in boundary %s that does not exist.\n", i, g_buildingInfo[i].m_boundaryName);
858 }
859 }
860 }
861
862 m_unk0x09 = TRUE;
863 return SUCCESS;
864}
865
866// FUNCTION: LEGO1 0x10030790
867// FUNCTION: BETA10 0x10064db9
869{
870 if (!m_unk0x09) {
871 FUN_10030630();
872 }
873
874 p_length = sizeOfArray(g_buildingInfo);
875 return g_buildingInfo;
876}
877
878// FUNCTION: LEGO1 0x100307b0
880{
881 LegoBuildingInfo* info = GetInfo(p_entity);
882
883 if (info != NULL) {
884 if (info->m_unk0x11 < 0) {
886 }
887
888 if (info->m_unk0x11 > 0) {
889 info->m_unk0x11 += p_adjust;
890 if (info->m_unk0x11 <= 1 && p_adjust < 0) {
891 info->m_unk0x11 = 0;
892 }
893 }
894 }
895}
896
897// FUNCTION: LEGO1 0x10030800
899{
900 for (MxU32 i = 0; i < sizeOfArray(g_buildingInfo); i++) {
902 }
903}
BOOL Moved(ViewROI &rROI)
[AI] Notifies the manager that the ROI has moved and needs spatial update.
[AI] Manages LEGO buildings in the world, including their state, animation, switching,...
~LegoBuildingManager() override
[AI] Destructor. Cleans up scheduled animation file string and resets manager state.
void FUN_10030800()
[AI] Copies the current m_unk0x11 demo/counter into m_initialUnk0x11 for all buildings (for persisten...
MxBool SwitchSound(LegoEntity *p_entity)
[AI] Cycles the current active sound for a building (if sounds available).
void AdjustHeight(MxS32 p_index)
[AI] Adjusts (recalculates) a building's world Y position based on its current demo/build counter,...
MxResult Read(LegoStorage *p_storage)
[AI] Restores data from serialized building state in the given storage.
void FUN_100307b0(LegoEntity *p_entity, MxS32 p_adjust)
[AI] Adjusts the construction/demolition counter for a building entity, incrementing or decrementing ...
void Reset()
[AI] Removes all building-state links to world entities and cancels/cleans any scheduled animation en...
MxBool SwitchMove(LegoEntity *p_entity)
[AI] Cycles the current move/animation state for a building (if moves available).
void LoadWorldInfo()
[AI] Loads/creates building models for the current world, sets up variants appropriately for current ...
LegoBuildingInfo * GetInfoArray(MxS32 &p_length)
[AI] Returns the full set of LegoBuildingInfo entries, checks/initializes boundary data if needed.
static void SetCustomizeAnimFile(const char *p_value)
[AI] Sets the global filename for a custom "customize animation" SMK/FLC file.
MxBool FUN_10030110(LegoBuildingInfo *p_data)
[AI] Forwards to FUN_10030030 with lookup by pointer; used for pointer-based demolition/motion trigge...
LegoBuildingInfo * GetInfo(LegoEntity *p_entity)
[AI] Locates the building info entry for a specific building entity.
void FUN_10030590()
[AI] Resets all buildings' construction/demolition status to "unbuilt" (-1), updates heights/visibili...
LegoBuildingManager()
[AI] Constructor. Initializes state and building info array (see Init()).
void CreateBuilding(MxS32 p_index, LegoWorld *p_world)
[AI] Spawns and configures a building entity and its ROI based on world/array index.
void Init()
[AI] Initializes all manager fields, resets animation tracking, and loads the default building info a...
MxBool SwitchVariant(LegoEntity *p_entity)
[AI] Attempts to switch the building variant for the specified entity (e.g.
MxBool SwitchMood(LegoEntity *p_entity)
[AI] Cycles the current mood state for a building (if moods available, mood in 0.....
MxU32 GetSoundId(LegoEntity *p_entity, MxBool p_state)
[AI] Returns the sound id for a building entity, using either mood or active sound state.
MxBool FUN_10030000(LegoEntity *p_entity)
[AI] Attempts to "progress" demolition/animation of a building entity by calling FUN_10030030 on its ...
void ScheduleAnimation(LegoEntity *p_entity, MxLong p_length, MxBool p_haveSound, MxBool p_unk0x28)
[AI] Schedules an animation bounce/effect for a given building entity (updates AnimEntry tracking and...
static void configureLegoBuildingManager(MxS32 p_buildingManagerConfig)
[AI] Configure static settings for the LegoBuildingManager globally.
MxResult Tickle() override
[AI] Tick updates for scheduled animation: animates buildings scheduled in m_entries,...
MxU32 GetAnimationId(LegoEntity *p_entity)
[AI] Returns the animation id for a building entity, factoring in base animation id and move offset.
MxBool FUN_10030030(MxS32 p_index)
[AI] Internal: progresses the demolition/animation state/counter of the indexed building,...
MxResult FUN_10030630()
[AI] Performs a boundary existence/consistency check for each building, resolving path boundaries and...
MxResult Write(LegoStorage *p_storage)
[AI] Serializes current building state to the given storage.
LegoCacheSound * FindSoundByKey(const char *p_key)
[AI] Attempts to find and return a cached sound by its key (case-insensitive).
LegoCacheSound * Play(const char *p_key, const char *p_name, MxBool p_looping)
[AI] Plays a sound identified by key, with the given playback name and looping flag.
void SetDistance(MxS32 p_min, MxS32 p_max)
Sets minimum and maximum audible distances for 3D sound attenuation.
[AI] Represents an entity that can be placed and managed in the LEGO Island world.
Definition: legoentity.h:16
LegoROI * GetROI()
[AI] Gets the ROI (Realtime Object Instance) associated with this entity. [AI]
Definition: legoentity.h:161
void SetType(MxU8 p_type)
[AI] Sets the entity's type (actor/plant/building/etc.) [AI]
Definition: legoentity.cpp:459
@ e_building
[AI] Building entities, usually interactable or decorations [AI]
Definition: legoentity.h:23
[AI] Represents a path segment or boundary in the navigation network for actors (vehicles,...
[AI] Represents a Real-time Object Instance enriched with LEGO-specific functionality.
Definition: legoroi.h:43
const LegoChar * GetName() const
[AI] Gets this ROI's name.
Definition: legoroi.h:287
LegoCacheSoundManager * GetCacheSoundManager()
[AI] Returns the cache sound manager used to cache and reuse sound effects.
Abstract base class providing an interface for file-like storage with binary and text read/write oper...
Definition: legostorage.h:16
virtual LegoResult Write(const void *p_buffer, LegoU32 p_size)=0
Write bytes from buffer into storage.
virtual LegoResult Read(void *p_buffer, LegoU32 p_size)=0
Read bytes from storage into buffer.
Lego3DManager * Get3DManager()
[AI] Returns the Lego3DManager for this manager, which owns all 3D scene representations and view con...
LegoU8 GetNumEdges()
[AI] Returns the number of edge elements assigned to this face.
Definition: legoweedge.h:43
const LegoChar * GetName()
[AI] Returns the name string of this edge, typically used for debugging and lookup.
Definition: legowegedge.h:79
Mx4DPointFloat * GetEdgeNormal(int index)
[AI] Returns a pointer to the 4D edge normal at the given sub-edge index.
Definition: legowegedge.h:75
Mx4DPointFloat * GetUnknown0x14()
[AI] Returns a pointer to the cached 4D normal or reference plane for the edge.
Definition: legowegedge.h:70
Represents the active 3D world, holding all entity, animation, sound, path, and ROI objects.
Definition: legoworld.h:49
LegoPathBoundary * FindPathBoundary(const char *p_name)
Finds a path boundary in all path controllers by name.
Definition: legoworld.cpp:385
MxCore * Find(const char *p_class, const char *p_name)
Finds an object of a given class and name in the world.
Definition: legoworld.cpp:573
virtual void SetIdentity()
Sets this matrix to identity (diagonal 1, others 0).
[AI] Represents a 3D point with floating-point precision, inheriting from Vector3.
Definition: mxgeometry3d.h:14
[AI] 4D point class for floating point values.
Definition: mxgeometry4d.h:18
float & index_operator(int idx)
[AI] Explicit indexed access wrapper (alias for operator[]).
Definition: mxgeometry4d.h:73
[AI] Represents a 4x4 transformation matrix, specialized for the LEGO Island engine and derived from ...
Definition: mxmatrix.h:16
virtual void UnregisterClient(MxCore *p_client)
[AI] Unregisters (marks for destruction) a previously registered client.
virtual void RegisterClient(MxCore *p_client, MxTime p_interval)
[AI] Registers an MxCore object to receive periodic tickles.
MxLong GetTime()
Returns the current timer value in ms, depending on running state.
Definition: mxtimer.h:50
const float * GetWorldPosition() const
Returns a pointer to the world position from the transformation matrix (translation row).
const Matrix4 & GetLocal2World() const
Accessor for the current local-to-world transformation matrix.
void UpdateTransformationRelativeToParent(const Matrix4 &p_transform)
Calculates and updates the world transform relative to this object's parent, then calls UpdateWorldDa...
void SetVisibility(unsigned char p_visible)
[AI] Sets the visibility flag to the provided value.
Definition: roi.h:235
virtual float Dot(const float *p_a, const float *p_b) const
[AI] Compute the dot product of the two float arrays interpreted as vectors of 2 elements.
#define TRUE
Definition: d3drmdef.h:28
#define FALSE
Definition: d3drmdef.h:27
#define DECOMP_SIZE_ASSERT(T, S)
Definition: decomp.h:19
#define sizeOfArray(arr)
Definition: decomp.h:23
LegoBuildingInfo g_buildingInfoInit[16]
LegoBuildingInfo g_buildingInfo[16]
MxU32 g_unk0x100f373c
MxU32 g_unk0x100f3740
MxS32 g_buildingManagerConfig
LegoBuildingInfo * GetBuildingInfo(MxS32 p_index)
MxU8 g_buildingInfoDownshift[16]
float g_buildingInfoDownshiftScale[16]
const char * g_buildingInfoVariants[5]
MxU32 g_buildingAnimationId[16]
#define NULL
[AI] Null pointer value (C/C++ semantics).
Definition: legotypes.h:26
#define FAILURE
[AI] Used to indicate a failed operation in result codes.
Definition: legotypes.h:34
#define SUCCESS
[AI] Used to indicate a successful operation in result codes.
Definition: legotypes.h:30
LegoVideoManager * VideoManager()
[AI] Accessor for the game's LegoVideoManager subsystem. Used for managing 3D/video hardware....
Definition: misc.cpp:29
LegoSoundManager * SoundManager()
[AI] Accessor for the game's LegoSoundManager subsystem from the global LegoOmni instance....
Definition: misc.cpp:22
LegoWorld * CurrentWorld()
[AI] Accessor for the currently active LegoWorld instance. [AI]
Definition: misc.cpp:93
#define MxTrace(args)
[AI] Macro for trace logging (non-variadic version, MSVC compatibility), expands to nothing.
Definition: mxdebug.h:55
MxTimer * Timer()
[AI] Returns the global simulation timer.
Definition: mxmisc.cpp:33
MxTickleManager * TickleManager()
[AI] Provides access to the global tickle manager.
Definition: mxmisc.cpp:25
MxU8 MxBool
[AI]
Definition: mxtypes.h:124
MxLong MxResult
[AI]
Definition: mxtypes.h:106
int MxLong
[AI]
Definition: mxtypes.h:83
unsigned char MxU8
[AI]
Definition: mxtypes.h:8
signed int MxS32
[AI]
Definition: mxtypes.h:38
unsigned int MxU32
[AI]
Definition: mxtypes.h:32
[AI] Describes the state, configuration, and world placement of a single LEGO building entity,...
MxU32 m_move
[AI] Index or ID of current animation state [AI]
const char * m_variant
[AI] Name of the building's current variant (model name/ID) [AI]
float m_y
[AI] World Y coordinate for the building's ground placement [AI]
LegoEntity * m_entity
[AI] Associated entity in the world for this building [AI]
@ c_hasMoves
[AI] This building supports animation cycling [AI]
@ c_hasVariants
[AI] This building has multiple variant models (for switching appearance) [AI]
@ c_hasMoods
[AI] This building supports mood changes [AI]
@ c_hasSounds
[AI] This building supports multiple sounds [AI]
MxU32 m_sound
[AI] Index or ID of current sound selection [AI]
MxU8 m_mood
[AI] Current mood index (0-3) [AI]
MxS8 m_initialUnk0x11
[AI] Initial value for m_unk0x11, used for state resets or persistence [AI]
float m_unk0x14
[AI] World height or vertical offset for this building [AI]
LegoPathBoundary * m_boundary
[AI] Pointer to the world boundary (collision/trigger volume) [AI]
MxU8 m_flags
[AI] Bitfield of building properties (see enum above) [AI]
MxS8 m_unk0x11
[AI] Counter or state value for construction/demolition progress [AI]
[AI] Tracks and schedules a single animation entry for a building with sound and timer information,...
LegoEntity * m_entity
[AI] The building entity being animated [AI]
float m_unk0x0c
[AI] Internal Y offset for vertical bouncy animation (demolition effect) [AI]
MxBool m_muted
[AI] TRUE if sound should be muted for this animation [AI]
MxLong m_time
[AI] Target future time when the animation should complete [AI]
LegoROI * m_roi
[AI] ROI used for transformations and updates [AI]
#define SET3(to, from)
Definition: vec.h:310
#define ZEROVEC3(v)
Definition: vec.h:334