Isle
Loading...
Searching...
No Matches
legocarbuild.cpp
Go to the documentation of this file.
1#include "legocarbuild.h"
2
3#include "copter_actions.h"
4#include "dunebuggy.h"
5#include "dunecar_actions.h"
6#include "helicopter.h"
7#include "isle_actions.h"
8#include "jetski.h"
9#include "jetski_actions.h"
10#include "jukebox_actions.h"
12#include "legocontrolmanager.h"
13#include "legogamestate.h"
14#include "legoinputmanager.h"
15#include "legomain.h"
16#include "legosoundmanager.h"
17#include "legoutils.h"
18#include "misc.h"
21#include "mxcontrolpresenter.h"
22#include "mxmisc.h"
24#include "mxsoundpresenter.h"
25#include "mxstillpresenter.h"
26#include "mxticklemanager.h"
27#include "mxtransitionmanager.h"
28#include "mxvariabletable.h"
29#include "racecar.h"
30#include "racecar_actions.h"
31#include "scripts.h"
32
33#include <isle.h>
34#include <vec.h>
35
36// Names and values verified by BETA10 0x1006d742.
37// Note that these were probably hard-coded numbers in the original.
38#define Helicopter_Actor CopterScript::c_Helicopter_Actor
39#define DuneBugy_Actor DunecarScript::c_DuneBugy_Actor
40#define Jetski_Actor JetskiScript::c_Jetski_Actor
41#define RaceCar_Actor RacecarScript::c_RaceCar_Actor
42
45DECOMP_SIZE_ASSERT(LegoCarBuild::LookupTableActions, 0x1c);
46
47// These four structs can be matched to the vehicle types using BETA10 0x10070520
48
49// GLOBAL: LEGO1 0x100d65b0
50// GLOBAL: BETA10 0x101bb7c0
51LegoCarBuild::LookupTableActions LegoCarBuild::g_unk0x100d65b0[] = {
80};
81
82// GLOBAL: LEGO1 0x100d65a4
83MxFloat LegoCarBuild::g_unk0x100d65a4 = -0.1f;
84
85// GLOBAL: LEGO1 0x100d65a8
86MxFloat LegoCarBuild::g_rotationAngleStepYAxis = 0.07;
87
88// GLOBAL: LEGO1 0x100f11cc
89MxS16 LegoCarBuild::g_unk0x100f11cc = -1;
90
91// FUNCTION: LEGO1 0x100226d0
92// FUNCTION: BETA10 0x1006ac10
94{
95 m_unk0x100 = 0;
96 m_unk0x110 = 0;
97 m_unk0xf8 = c_unknownminusone;
98 m_unk0x2d4 = FALSE;
99 m_unk0x258 = 0;
100 m_ColorBook_Bitmap = NULL;
101 m_Yellow_Ctl = NULL;
102 m_Red_Ctl = NULL;
103 m_Blue_Ctl = NULL;
104 m_Green_Ctl = NULL;
105 m_Gray_Ctl = NULL;
106 m_Black_Ctl = NULL;
107 m_Shelf_Sound = NULL;
108 m_PlaceBrick_Sound = NULL;
109 m_GetBrick_Sound = NULL;
110 m_Paint_Sound = NULL;
111 m_Decal_Sound = NULL;
112 m_Decal_Bitmap = NULL;
113 m_Decals_Ctl = NULL;
114 m_Decals_Ctl1 = NULL;
115 m_Decals_Ctl2 = NULL;
116 m_Decals_Ctl3 = NULL;
117 m_Decals_Ctl4 = NULL;
118 m_Decals_Ctl5 = NULL;
119 m_Decals_Ctl6 = NULL;
120 m_Decals_Ctl7 = NULL;
121 m_unk0x33c = NULL;
122 m_buildState = NULL;
123 m_unk0x104 = 0;
124 m_unk0x109 = 0;
125 m_numAnimsRun = 0;
126 m_unk0x338 = 0;
127 m_destLocation = LegoGameState::e_undefined;
128 m_unk0x344 = DS_NOT_A_STREAM;
129 m_unk0x174 = 0;
131}
132
133// FUNCTION: LEGO1 0x10022a80
134// FUNCTION: BETA10 0x1006aea3
136{
137 m_unk0x100 = 0;
138 m_unk0x110 = NULL;
139
140 if (m_unk0x258) {
141 m_unk0x258->SetUnknown0xbc(0);
143 m_unk0x258 = NULL;
144 }
145
146 ControlManager()->Unregister(this);
148
149 if (InputManager()->GetWorld() == this) {
151 }
152
153 InputManager()->UnRegister(this);
155}
156
157// FUNCTION: LEGO1 0x10022b70
158// FUNCTION: BETA10 0x1006afd9
160{
161 MxResult result = LegoWorld::Create(p_dsAction);
162
163 if (!result) {
164 // TickleManager()->RegisterClient(this, 100);
165 InputManager()->SetWorld(this);
166 ControlManager()->Register(this);
167
169
170 InputManager()->Register(this);
171
172 // variable name verified by BETA10 0x1006b1a6
173 const char* buildStateClassName = NULL;
174
175 if (m_atomId == *g_copterScript) {
176 buildStateClassName = "LegoCopterBuildState";
178 m_carId = Helicopter_Actor;
179 }
180 else if (m_atomId == *g_dunecarScript) {
181 buildStateClassName = "LegoDuneCarBuildState";
183 m_carId = DuneBugy_Actor;
184 }
185 else if (m_atomId == *g_jetskiScript) {
186 buildStateClassName = "LegoJetskiBuildState";
188 m_carId = Jetski_Actor;
189 }
190 else if (m_atomId == *g_racecarScript) {
191 buildStateClassName = "LegoRaceCarBuildState";
193 m_carId = RaceCar_Actor;
194 }
195
196 LegoGameState* gameState = GameState();
197
198 LegoVehicleBuildState* buildState = (LegoVehicleBuildState*) gameState->GetState(buildStateClassName);
199
200 if (!buildState) {
201 buildState = (LegoVehicleBuildState*) gameState->CreateState(buildStateClassName);
202 }
203
204 m_buildState = buildState;
205 m_unk0x174 = m_buildState->m_unk0x4d;
206
208
210 m_unk0x100 = 0;
211
214
215 result = SUCCESS;
216 }
217
218 return result;
219}
220
221// FUNCTION: LEGO1 0x10022cd0
223{
224 if (m_buildState) {
225 return m_buildState->m_placedPartCount;
226 }
227 else {
228 return 0;
229 }
230}
231
232// FUNCTION: LEGO1 0x10022cf0
234{
235 if (m_buildState) {
236 m_buildState->m_placedPartCount = p_placedPartCount;
237 }
238}
239
240// FUNCTION: LEGO1 0x10022d10
241// FUNCTION: BETA10 0x1006b27a
243{
244 m_ColorBook_Bitmap = (MxStillPresenter*) Find("MxStillPresenter", "ColorBook_Bitmap");
245 assert(m_ColorBook_Bitmap);
246 m_Yellow_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Yellow_Ctl");
247 assert(m_Yellow_Ctl);
248 m_Red_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Red_Ctl");
249 assert(m_Red_Ctl);
250 m_Blue_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Blue_Ctl");
251 assert(m_Blue_Ctl);
252 m_Green_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Green_Ctl");
253 assert(m_Green_Ctl);
254 m_Gray_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Gray_Ctl");
255 assert(m_Gray_Ctl);
256 m_Black_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Black_Ctl");
257 assert(m_Black_Ctl);
258 m_Shelf_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "Shelf_Sound");
259 assert(m_Shelf_Sound);
260 m_PlaceBrick_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "PlaceBrick_Sound");
261 assert(m_PlaceBrick_Sound);
262 m_GetBrick_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "GetBrick_Sound");
263 assert(m_GetBrick_Sound);
264 m_Paint_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "Paint_Sound");
265 assert(m_Paint_Sound);
266 m_Decal_Sound = (MxSoundPresenter*) Find("MxSoundPresenter", "Decal_Sound");
267 m_Decals_Ctl = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl");
268 m_Decals_Ctl1 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl1");
269 m_Decals_Ctl2 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl2");
270 m_Decal_Bitmap = (MxStillPresenter*) Find("MxStillPresenter", "Decal_Bitmap");
271 assert(m_Decal_Bitmap);
272 if (m_Decal_Bitmap) {
273 m_Decals_Ctl3 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl3");
274 assert(m_Decals_Ctl3);
275 m_Decals_Ctl4 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl4");
276 assert(m_Decals_Ctl4);
277 m_Decals_Ctl5 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl5");
278 assert(m_Decals_Ctl5);
279 m_Decals_Ctl6 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl6");
280 assert(m_Decals_Ctl6);
281 m_Decals_Ctl7 = (MxControlPresenter*) Find("MxControlPresenter", "Decals_Ctl7");
282 assert(m_Decals_Ctl7);
283 }
284}
285
286// FUNCTION: LEGO1 0x10022f00
288{
289 if (m_unk0x110) {
290 VTable0x6c();
291 m_unk0x258->SetUnknown0xbc(0);
292 m_unk0x100 = 5;
293 }
294}
295
296// FUNCTION: LEGO1 0x10022f30
297// FUNCTION: BETA10 0x1006b835
299{
300 if (m_unk0x110) {
303
304 if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) {
305 m_PlaceBrick_Sound->Enable(FALSE);
306 m_PlaceBrick_Sound->Enable(TRUE);
307 }
308
309 m_unk0x258->SetUnknown0xbc(1);
310 m_unk0x258->PutFrame();
311 m_unk0x110 = NULL;
312 m_unk0x100 = 0;
313 }
314}
315
316// FUNCTION: LEGO1 0x10022fc0
317// FUNCTION: BETA10 0x1006b90b
319{
320 m_unk0x178 = m_unk0x1c0;
321 m_unk0x110->WrappedSetLocalTransform(m_unk0x178);
322 m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition());
323
324 VTable0x70();
325}
326
327// FUNCTION: LEGO1 0x10023020
328// FUNCTION: BETA10 0x1006b991
330{
331 MxFloat worldPos[3];
332 MxFloat screenPos[4];
333
334 worldPos[0] = m_unk0x2a4[0];
335 worldPos[1] = m_unk0x2a4[1];
336 worldPos[2] = m_unk0x2a4[2];
337
338 TransformWorldToScreen(worldPos, screenPos);
339
340 m_unk0x290[0] = screenPos[0] / screenPos[3];
341 m_unk0x290[1] = screenPos[1] / screenPos[3];
342
343 worldPos[0] = m_unk0x2bc[0];
344 worldPos[1] = m_unk0x2bc[1];
345 worldPos[2] = m_unk0x2bc[2];
346
347 TransformWorldToScreen(worldPos, screenPos);
348
349 m_unk0x298[0] = screenPos[0] / screenPos[3];
350 m_unk0x298[1] = screenPos[1] / screenPos[3];
351
352 m_unk0x2a0 = sqrt((MxDouble) DISTSQRD2(m_unk0x290, m_unk0x298));
353
354 m_unk0x25c.SetStartEnd(m_unk0x178, m_unk0x208);
355}
356
357// FUNCTION: LEGO1 0x10023130
358// FUNCTION: BETA10 0x1006bb22
360{
361 if (m_unk0x110) {
362 MxFloat pfVar3[2];
363 MxFloat local30[3];
364 MxFloat local84[3];
365
366 p_x += (m_unk0x290[0] - m_unk0x250[0]);
367 p_y += (m_unk0x290[1] - m_unk0x250[1]);
368
369 pfVar3[0] = p_x;
370 pfVar3[1] = p_y;
371
372 if (FUN_1003ded0(pfVar3, local30, local84)) {
373 MxFloat local18[3];
374 MxFloat local8c[2];
375
376 local8c[0] = p_x;
377 local8c[1] = p_y;
378
379 local18[0] = 0;
380 local18[1] = 0;
381 local18[2] = 0;
382
383 MxMatrix local78;
384
385 if (p_y < m_unk0x290[1]) {
386 VTable0x74(local8c, local18);
387 }
388 else if (p_y > m_unk0x298[1]) {
389 VTable0x7c(local8c, local18);
390 }
391 else if (p_y >= m_unk0x290[1]) {
392 VTable0x78(local8c, local18);
393 }
394
395 MxS32 local20[2];
396
397 local20[0] = p_x - m_unk0x290[0];
398 local20[1] = p_y - m_unk0x290[1];
399
400 MxFloat local1c = sqrt((double) (NORMSQRD2(local20))) / m_unk0x2a0;
401
402 m_unk0x25c.InterpolateToMatrix(local78, local1c);
403
404 local78[3][0] = m_unk0x178[3][0] + local18[0];
405 local78[3][1] = m_unk0x178[3][1] + local18[1];
406 local78[3][2] = m_unk0x178[3][2] + local18[2];
407 local78[3][3] = 1.0;
408
409 m_unk0x110->WrappedSetLocalTransform(local78);
410 }
411 }
412}
413
414// FUNCTION: LEGO1 0x10023500
415// FUNCTION: BETA10 0x1006bdf6
416void LegoCarBuild::VTable0x74(MxFloat p_param1[2], MxFloat p_param2[3])
417{
418 MxFloat fVar1;
419 MxFloat local20[3];
420 MxFloat local14[3];
421
422 FUN_1003ded0(p_param1, local14, local20);
423
424 fVar1 = (m_unk0x2a4[2] - local20[2]) / local14[2];
425 p_param2[0] = (fVar1 * local14[0] + local20[0]) - m_unk0x2a4[0];
426 p_param2[1] = (fVar1 * local14[1] + local20[1]) - m_unk0x2a4[1];
427 p_param2[2] = 0.0;
428}
429
430// FUNCTION: LEGO1 0x10023570
431// FUNCTION: BETA10 0x1006be91
432void LegoCarBuild::VTable0x78(MxFloat p_param1[2], MxFloat p_param2[3])
433{
434 MxFloat fVar1;
435 MxFloat local18[3];
436 MxFloat localc[3];
437
438 FUN_1003ded0(p_param1, local18, localc);
439
440 p_param2[2] = m_unk0x2a4[2] +
441 (m_unk0x2bc[2] - m_unk0x2a4[2]) * ((p_param1[1] - m_unk0x290[1]) / (m_unk0x298[1] - m_unk0x290[1]));
442 fVar1 = (p_param2[2] - localc[2]) / local18[2];
443 p_param2[0] = fVar1 * local18[0] - m_unk0x2a4[0] + localc[0];
444 p_param2[1] = fVar1 * local18[1] - m_unk0x2a4[1] + localc[1];
445 p_param2[2] = p_param2[2] - m_unk0x2a4[2];
446}
447
448// FUNCTION: LEGO1 0x10023620
449// FUNCTION: BETA10 0x1006bfb5
450void LegoCarBuild::VTable0x7c(MxFloat p_param1[2], MxFloat p_param2[3])
451{
452 MxFloat local18[3];
453 MxFloat localc[3];
454 FUN_1003ded0(p_param1, local18, localc);
455
456 MxFloat fVar1 = (m_unk0x2bc[1] - localc[1]) / local18[1];
457 p_param2[0] = fVar1 * local18[0] - m_unk0x2a4[0] + localc[0];
458 p_param2[1] = m_unk0x2bc[1] - m_unk0x2a4[1];
459 p_param2[2] = fVar1 * local18[2] - m_unk0x2a4[2] + localc[2];
460}
461
462// FUNCTION: LEGO1 0x100236a0
463// FUNCTION: BETA10 0x100701f0
464void LegoCarBuild::VTable0x80(MxFloat p_param1[2], MxFloat p_param2[2], MxFloat p_param3, MxFloat p_param4[2])
465{
466 if (p_param1[1] == 0.0f) {
467 return;
468 }
469 p_param4[0] = ((p_param3 - p_param2[1]) / p_param1[1]) * p_param1[0] + p_param2[0];
470 p_param4[1] = p_param3;
471}
472
473// FUNCTION: LEGO1 0x100236d0
474// FUNCTION: BETA10 0x1006c076
476{
477 MxS32 pLVar2;
478
481 m_unk0x258->FUN_10079790(m_unk0x110->GetName());
482 m_unk0x258->SetUnknown0xbc(1);
483 m_unk0x110 = NULL;
484 m_unk0x100 = 0;
485
486 if (m_unk0x258->AllPartsPlaced()) {
487 // Note the code duplication with LEGO1 0x10025ee0
488 switch (m_carId) {
489 case 1:
490 pLVar2 = 0x2f;
491 break;
492 case 2:
493 pLVar2 = 0x31;
494 break;
495 case 3:
496 pLVar2 = 0x33;
497 break;
498 case 4:
499 pLVar2 = 0x35;
500 }
501
504
505 if (m_numAnimsRun > 0) {
506 DeleteObjects(&m_atomId, 500, 510);
507 }
508
509 if (GameState()->GetCurrentAct() == LegoGameState::e_act2) {
510 FUN_100243a0();
511 }
512 else {
513 m_buildState->m_unk0x4d = TRUE;
517 m_buildState->m_placedPartCount = 0;
518 }
519 }
520}
521
522#define LEGOCARBUILD_TICKLE_CASE(subtract, start, end, str) \
523 if (start < dTime && dTime < end) { \
524 FUN_10025db0(str, dTime - subtract); \
525 break; \
526 }
527
528// FUNCTION: LEGO1 0x100238b0
529// FUNCTION: BETA10 0x1006c18f
531{
532 if (!m_worldStarted) {
534 return SUCCESS;
535 }
536
537 if (m_unk0xf8 == c_unknown8) {
538 if (m_unk0xfc == 1) {
539 FUN_10024f50();
540 }
541
542 if (m_unk0x110) {
543 if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) {
544 FUN_10022f30();
545 }
546 }
547 }
548
549 if (m_unk0x100 == 5 && m_unk0x110) {
550 RotateY(m_unk0x110, g_unk0x100d65a4);
551 }
552
553 if (m_unk0x10a) {
554 DWORD time = timeGetTime();
555 DWORD dTime = (time - m_unk0x10c) / 100;
556
557 if (m_carId == RaceCar_Actor) {
558 switch (m_unk0x10a) {
560 LEGOCARBUILD_TICKLE_CASE(160, 160, 180, "Exit_Ctl")
561 LEGOCARBUILD_TICKLE_CASE(260, 260, 280, "ShelfUp_Ctl")
562 LEGOCARBUILD_TICKLE_CASE(330, 330, 340, "Yellow_Ctl")
563 LEGOCARBUILD_TICKLE_CASE(340, 340, 360, "Platform_Ctl")
564 LEGOCARBUILD_TICKLE_CASE(390, 390, 410, "Exit_Ctl")
565 break;
567 LEGOCARBUILD_TICKLE_CASE(50, 50, 60, "ShelfUp_Ctl")
568 LEGOCARBUILD_TICKLE_CASE(63, 65, 70, "Yellow_Ctl")
569 LEGOCARBUILD_TICKLE_CASE(70, 70, 80, "Platform_Ctl")
570 LEGOCARBUILD_TICKLE_CASE(95, 95, 105, "Exit_Ctl")
571 break;
573 LEGOCARBUILD_TICKLE_CASE(22, 24, 29, "Exit_Ctl")
574 LEGOCARBUILD_TICKLE_CASE(33, 35, 40, "ShelfUp_Ctl")
575 LEGOCARBUILD_TICKLE_CASE(43, 45, 50, "Yellow_Ctl")
576 LEGOCARBUILD_TICKLE_CASE(56, 58, 63, "Platform_Ctl")
577 break;
578 }
579 }
580 else if (m_carId == Jetski_Actor) {
581 switch (m_unk0x10a) {
583 LEGOCARBUILD_TICKLE_CASE(291, 291, 311, "Exit_Ctl")
584 LEGOCARBUILD_TICKLE_CASE(311, 311, 331, "ShelfUp_Ctl")
585 LEGOCARBUILD_TICKLE_CASE(412, 412, 432, "Yellow_Ctl")
586 LEGOCARBUILD_TICKLE_CASE(437, 437, 457, "Platform_Ctl")
587 LEGOCARBUILD_TICKLE_CASE(485, 485, 505, "Exit_Ctl")
588 break;
590 LEGOCARBUILD_TICKLE_CASE(32, 34, 39, "Exit_Ctl")
591 LEGOCARBUILD_TICKLE_CASE(68, 70, 75, "ShelfUp_Ctl")
592 LEGOCARBUILD_TICKLE_CASE(105, 105, 115, "Yellow_Ctl")
593 LEGOCARBUILD_TICKLE_CASE(133, 135, 140, "Platform_Ctl")
594 break;
596 LEGOCARBUILD_TICKLE_CASE(78, 78, 98, "Exit_Ctl")
597 break;
599 LEGOCARBUILD_TICKLE_CASE(93, 93, 113, "Exit_Ctl")
600 break;
601 }
602 }
603 else if (m_carId == DuneBugy_Actor) {
604 switch (m_unk0x10a) {
606 LEGOCARBUILD_TICKLE_CASE(155, 155, 175, "Exit_Ctl")
607 LEGOCARBUILD_TICKLE_CASE(215, 215, 235, "ShelfUp_Ctl")
608 LEGOCARBUILD_TICKLE_CASE(285, 285, 305, "Yellow_Ctl")
609 LEGOCARBUILD_TICKLE_CASE(300, 300, 320, "Platform_Ctl")
610 LEGOCARBUILD_TICKLE_CASE(340, 340, 360, "Exit_Ctl")
611 break;
613 LEGOCARBUILD_TICKLE_CASE(23, 23, 33, "Exit_Ctl")
614 LEGOCARBUILD_TICKLE_CASE(37, 39, 44, "ShelfUp_Ctl")
615 LEGOCARBUILD_TICKLE_CASE(105, 105, 115, "Yellow_Ctl")
616 LEGOCARBUILD_TICKLE_CASE(122, 124, 129, "Platform_Ctl")
617 break;
618 }
619 }
620 else if (m_carId == Helicopter_Actor) {
621 switch (m_unk0x10a) {
623 LEGOCARBUILD_TICKLE_CASE(185, 185, 205, "Exit_Ctl")
624 LEGOCARBUILD_TICKLE_CASE(235, 235, 255, "ShelfUp_Ctl")
625 LEGOCARBUILD_TICKLE_CASE(292, 292, 312, "Yellow_Ctl")
626 LEGOCARBUILD_TICKLE_CASE(315, 315, 335, "Platform_Ctl")
627 LEGOCARBUILD_TICKLE_CASE(353, 353, 373, "Exit_Ctl")
628 break;
630 LEGOCARBUILD_TICKLE_CASE(43, 45, 50, "Exit_Ctl")
631 LEGOCARBUILD_TICKLE_CASE(72, 74, 79, "ShelfUp_Ctl")
632 LEGOCARBUILD_TICKLE_CASE(114, 116, 121, "Yellow_Ctl")
633 LEGOCARBUILD_TICKLE_CASE(128, 130, 135, "Platform_Ctl")
634 break;
636 LEGOCARBUILD_TICKLE_CASE(30, 30, 40, "ShelfUp_Ctl")
637 LEGOCARBUILD_TICKLE_CASE(60, 60, 70, "Yellow_Ctl")
638 LEGOCARBUILD_TICKLE_CASE(48, 48, 58, "Platform_Ctl")
639 break;
640 }
641 }
642 }
643
644 return SUCCESS;
645}
646
647// FUNCTION: LEGO1 0x10024050
648// FUNCTION: BETA10 0x1006c976
650{
651 MxLong result = LegoWorld::Notify(p_param);
652 MxNotificationParam& param = (MxNotificationParam&) p_param;
653
654 if (m_worldStarted) {
655 switch (param.GetNotification()) {
658 result = 1;
659 break;
661 result = FUN_10024480((MxActionNotificationParam*) &p_param);
662 break;
664 result = FUN_10024250((LegoEventNotificationParam*) &p_param);
665 break;
667 result = FUN_100246e0(
668 ((LegoEventNotificationParam&) p_param).GetX(),
669 ((LegoEventNotificationParam&) p_param).GetY()
670 );
671
672 if (result || m_unk0x10a || m_buildState->m_animationState == 4 || m_buildState->m_animationState == 6) {
673 m_unk0x109 = 0;
674 break;
675 }
676
677 if (++m_unk0x109 > 2) {
678 FUN_10025720(6);
679 m_unk0x109 = 0;
680 }
681
682 break;
684 assert(m_buildState);
685 if (((m_buildState->m_animationState != 4) && (m_buildState->m_animationState != 6)) &&
686 (m_buildState->m_animationState != 2)) {
688 result = FUN_100244e0(
689 ((LegoEventNotificationParam&) p_param).GetX(),
690 ((LegoEventNotificationParam&) p_param).GetY()
691 );
692 }
693
694 break;
696 result = FUN_10024850(
697 ((LegoEventNotificationParam&) p_param).GetX(),
698 ((LegoEventNotificationParam&) p_param).GetY()
699 );
700
701 if (result == 1) {
702 m_unk0x109 = 0;
703 }
704
705 break;
707 result = FUN_10024890(&p_param);
708
709 if (result == 1) {
710 m_unk0x109 = 0;
711 }
712
713 break;
715 if (m_numAnimsRun > 0) {
716 m_numAnimsRun -= 1;
717 }
718
719 FUN_10025e40();
720 m_unk0x10a = 0;
721 result = 1;
722 break;
724 assert(m_destLocation != LegoGameState::e_undefined);
725 GameState()->SwitchArea(m_destLocation);
726 }
727 }
728
729 return result;
730}
731
732// FUNCTION: LEGO1 0x10024250
733// FUNCTION: BETA10 0x1006cc48
735{
736 if (p_param->GetKey() == ' ' && m_buildState->m_animationState != 4 && m_buildState->m_animationState != 2) {
737 if (m_numAnimsRun > 0) {
738 DeleteObjects(&m_atomId, 500, 0x1fe);
740 m_unk0x109 = 0;
741 }
742
743 return 1;
744 }
745
746 return 0;
747}
748
749// FUNCTION: LEGO1 0x100242c0
751{
752 m_presentersEnabled = FALSE;
754
755 if (BackgroundAudioManager()->GetEnabled()) {
759 }
760 else {
761 FUN_10024ef0();
762 }
763}
764
765// FUNCTION: LEGO1 0x100243a0
767{
768 switch (m_carId) {
769 case Helicopter_Actor:
770 if (GameState()->GetCurrentAct() == LegoGameState::Act::e_act2) {
771 m_destLocation = LegoGameState::Area::e_act3script;
773 break;
774 }
775 else {
776 m_destLocation = LegoGameState::Area::e_polidoor;
778 break;
779 }
780 case DuneBugy_Actor:
781 m_destLocation = LegoGameState::Area::e_garadoor;
783 break;
784 case Jetski_Actor:
785 m_destLocation = LegoGameState::Area::e_unk17;
787 break;
788 case RaceCar_Actor:
789 m_destLocation = LegoGameState::Area::e_unk20;
791 }
792}
793
794// FUNCTION: LEGO1 0x10024480
796{
797 MxS32 result = 0;
798
799 switch (m_buildState->m_animationState) {
800 case 3:
803 result = 1;
804 break;
805 case 6:
806 if (p_param->GetAction()->GetObjectId() == m_unk0x344) {
807 FUN_100243a0();
808 result = 1;
809 break;
810 }
811 }
812
813 return result;
814}
815
816// FUNCTION: LEGO1 0x100244e0
817// FUNCTION: BETA10 0x1006cfb6
819{
820 m_unk0x250[0] = p_x;
821 m_unk0x250[1] = p_y;
822
823 LegoROI* roi = PickROI(p_x, p_y);
824
825 if (!roi || !m_unk0x258->StringEndsOnYOrN(roi->GetName())) {
826 return 0;
827 }
828
829 if (m_unk0x110 != roi) {
830 FUN_10022f30();
831 m_unk0x110 = roi;
834 }
835
836 if (m_unk0x100 == 5 && m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) {
837 m_unk0x2d4 = TRUE;
838 }
839 else {
840 m_unk0x2d4 = FALSE;
841 }
842 FUN_10025450();
843 VTable0x70();
844
845 if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) {
846 if (m_unk0x100 != 5) {
847 m_unk0x250[0] += m_unk0x290[0] - m_unk0x298[0];
848 m_unk0x250[1] += m_unk0x290[1] - m_unk0x298[1];
849 }
850
851 if (m_unk0x100 == 0) {
852 m_unk0x114 = m_unk0x110->GetWorldBoundingSphere();
853 }
854 }
855 else {
856 if (m_unk0x258->FUN_10079c30(m_unk0x110->GetName())) {
857 m_unk0x114 = m_unk0x258->FUN_10079e20();
858 }
859 }
860
861 switch (m_unk0x100) {
862 case 0:
863 m_unk0x100 = 4;
864 break;
865 case 5:
866 m_unk0x100 = 3;
867 break;
868 }
869
870 m_GetBrick_Sound->Enable(FALSE);
871 m_GetBrick_Sound->Enable(TRUE);
872
873 m_unk0x258->SetUnknown0xbc(0);
874 return 1;
875}
876
877// FUNCTION: LEGO1 0x100246e0
878// FUNCTION: BETA10 0x1006d25a
880{
881 undefined4 result = 0;
882
883 switch (m_unk0x100) {
884 case 3:
885 FUN_10022f30();
886 result = 1;
887 break;
888 case 4:
889 FUN_10022f00();
890 result = 1;
891 break;
892 case 6:
893 if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName()) &&
894 SpheresIntersect(m_unk0x114, m_unk0x110->GetWorldBoundingSphere())) {
897 m_unk0x100 = 0;
898 m_unk0x110 = NULL;
899 m_PlaceBrick_Sound->Enable(FALSE);
900 m_PlaceBrick_Sound->Enable(TRUE);
901 m_unk0x258->SetUnknown0xbc(1);
902 }
903 else if (m_unk0x258->FUN_10079c30(m_unk0x110->GetName())) {
904 if (SpheresIntersect(m_unk0x114, m_unk0x110->GetWorldBoundingSphere())) {
905 m_PlaceBrick_Sound->Enable(FALSE);
906 m_PlaceBrick_Sound->Enable(TRUE);
907 FUN_100236d0();
908 }
909 else {
910 VTable0x6c();
911 m_unk0x100 = 5;
912 }
913 }
914 else {
915 VTable0x6c();
916 m_unk0x100 = 5;
917 }
918
919 result = 1;
920 break;
921 }
922
923 return result;
924}
925
926// FUNCTION: LEGO1 0x10024850
927// FUNCTION: BETA10 0x1006d48e
929{
930 MxS32 result = 0;
931
932 switch (m_unk0x100) {
933 case 3:
934 case 4:
935 m_unk0x100 = 6;
936 case 6:
937 FUN_10023130(p_x, p_y);
938 result = 1;
939 break;
940 }
941
942 return result;
943}
944
945#ifndef BETA10
946
947// FUNCTION: LEGO1 0x10024890
949{
950 undefined4 result = 0;
952 assert(m_buildState);
953
954 if (param->m_unk0x28) {
955 switch (param->m_clickedObjectId) {
956 // The enum values are all identical between CopterScript, DunecarScript, JetskiScript, and RacecarScript
961 GameState()->GetCurrentAct() != LegoGameState::e_act2) {
962 if (m_numAnimsRun > 0) {
963 DeleteObjects(&m_atomId, 500, 510);
964 }
965
966 m_unk0x258->SetUnknown0xbc(0);
967 m_destLocation = LegoGameState::e_infomain;
969 result = 1;
970 }
971
972 break;
976 if (m_numAnimsRun > 0) {
977 DeleteObjects(&m_atomId, 500, 510);
978 }
979
980 m_unk0x258->SetUnknown0xbc(0);
981
982 if (GameState()->GetCurrentAct() == LegoGameState::e_act2) {
983 FUN_100243a0();
984 }
985 else if (m_unk0x258->AllPartsPlaced() || m_buildState->m_unk0x4d) {
986 m_buildState->m_unk0x4d = TRUE;
988
990
992 }
993 else {
994 FUN_10025720(4);
996 }
997
998 result = 1;
999 }
1000 break;
1002 FUN_10024f30();
1003 m_Shelf_Sound->Enable(FALSE);
1004 m_Shelf_Sound->Enable(TRUE);
1005 result = 1;
1006 break;
1008 FUN_10024f50();
1009 m_unk0xf8 = c_unknown8;
1010 m_unk0xfc = param->m_unk0x28;
1011 result = 1;
1012 break;
1013 default:
1014 if ((m_Decals_Ctl && m_Decals_Ctl->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1015 (m_Decals_Ctl1 && m_Decals_Ctl1->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1016 (m_Decals_Ctl2 && m_Decals_Ctl2->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1017 (m_Decals_Ctl3 && m_Decals_Ctl3->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1018 (m_Decals_Ctl4 && m_Decals_Ctl4->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1019 (m_Decals_Ctl5 && m_Decals_Ctl5->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1020 (m_Decals_Ctl6 && m_Decals_Ctl6->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1021 (m_Decals_Ctl7 && m_Decals_Ctl7->GetAction()->GetObjectId() == param->m_clickedObjectId)) {
1022 m_unk0x258->SetPartObjectIdByName(m_unk0x110->GetName(), param->m_clickedObjectId);
1023 m_Decal_Sound->Enable(FALSE);
1024 m_Decal_Sound->Enable(TRUE);
1025 }
1026 else {
1028 }
1029
1030 result = 1;
1031 }
1032 }
1033 else {
1034 m_unk0xf8 = c_unknownminusone;
1035 m_unk0xfc = -1;
1036 }
1037
1038 // It is a bit unexpected that LEGO1 and BETA10 match so well with the `return 1`
1039 // and ignoring the `result` variable, but the match is hard to argue with
1040 return 1;
1041}
1042
1043#else
1044
1045// FUNCTION: BETA10 0x1006d512
1047{
1048 undefined4 result = 0;
1050 assert(m_buildState);
1051
1052 if (param->m_unk0x28) {
1053 switch (param->m_clickedObjectId) {
1055 m_unk0x258->SetUnknown0xbc(0);
1056 m_destLocation = LegoGameState::e_infomain;
1058 result = 1;
1059 break;
1062 m_unk0x258->SetUnknown0xbc(0);
1063
1064 if (m_unk0x258->AllPartsPlaced() || m_buildState->m_unk0x4d) {
1065 m_buildState->m_unk0x4d = TRUE;
1066
1067 // GameState()->GetCurrentAct() returns an MxS16 in BETA10
1068 if (GameState()->GetCurrentAct() == 0) {
1070
1072
1073 assert(m_buildState);
1075 }
1076
1077 else {
1078 FUN_10025720(5);
1080 }
1081 }
1082 else {
1083 FUN_10025720(4);
1085 }
1086
1087 switch (GameState()->m_currentArea) {
1089 assert(m_carId == Helicopter_Actor);
1090 break;
1092 assert(m_carId == DuneBugy_Actor);
1093 break;
1095 assert(m_carId == Jetski_Actor);
1096 break;
1098 assert(m_carId == RaceCar_Actor);
1099 break;
1100 }
1101
1102 result = 1;
1103 }
1104 break;
1106 FUN_10024f30();
1107 m_Shelf_Sound->Enable(FALSE);
1108 m_Shelf_Sound->Enable(TRUE);
1109 result = 1;
1110 break;
1112 FUN_10024f50();
1113 m_unk0xf8 = c_unknown8;
1114 m_unk0xfc = param->m_unk0x28;
1115 result = 1;
1116 break;
1117 default:
1118 if ((m_Decals_Ctl && m_Decals_Ctl->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1119 (m_Decals_Ctl1 && m_Decals_Ctl1->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1120 (m_Decals_Ctl2 && m_Decals_Ctl2->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1121 (m_Decals_Ctl3 && m_Decals_Ctl3->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1122 (m_Decals_Ctl4 && m_Decals_Ctl4->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1123 (m_Decals_Ctl5 && m_Decals_Ctl5->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1124 (m_Decals_Ctl6 && m_Decals_Ctl6->GetAction()->GetObjectId() == param->m_clickedObjectId) ||
1125 (m_Decals_Ctl7 && m_Decals_Ctl7->GetAction()->GetObjectId() == param->m_clickedObjectId)) {
1126 m_unk0x258->SetPartObjectIdByName(m_unk0x110->GetName(), param->m_clickedObjectId);
1127 m_Decal_Sound->Enable(FALSE);
1128 m_Decal_Sound->Enable(TRUE);
1129 }
1130 else {
1132 }
1133 result = 1;
1134 }
1135 }
1136 else {
1137 m_unk0xf8 = c_unknownminusone;
1138 m_unk0xfc = -1;
1139 }
1140
1141 return 1;
1142}
1143
1144#endif
1145
1146// FUNCTION: LEGO1 0x10024c20
1147// FUNCTION: BETA10 0x1006db21
1149{
1150 LegoEntity* entity;
1151 assert(m_buildState);
1152
1153 switch (m_buildState->m_animationState) {
1154 case 4:
1155 entity = (LegoEntity*) Find(m_atomId, m_carId);
1156
1157 if (entity && entity->GetROI()) {
1158 // This function was changed between BETA10 and LEGO1.
1159 // These lines looks like a relic from older code.
1160 LegoWorld* destWorld = NULL;
1162
1163 Act1State* gameState = (Act1State*) GameState()->GetState("Act1State");
1164
1165 switch (GameState()->m_currentArea) {
1167 if (gameState->m_helicopter) {
1168 delete gameState->m_helicopter;
1169 }
1170
1171 gameState->m_helicopter = (Helicopter*) entity;
1172 gameState->m_helicopterPlane.Reset();
1173 break;
1175 if (gameState->m_dunebuggy) {
1176 delete gameState->m_dunebuggy;
1177 }
1178
1179 gameState->m_dunebuggy = (DuneBuggy*) entity;
1180 gameState->m_dunebuggyPlane.Reset();
1181 break;
1183 if (gameState->m_jetski) {
1184 delete gameState->m_jetski;
1185 }
1186
1187 gameState->m_jetski = (Jetski*) entity;
1188 gameState->m_jetskiPlane.Reset();
1189 break;
1191 if (gameState->m_racecar) {
1192 delete gameState->m_racecar;
1193 }
1194
1195 gameState->m_racecar = (RaceCar*) entity;
1196 gameState->m_racecarPlane.Reset();
1197 break;
1198 }
1199
1200 assert(destWorld);
1202
1203 if (!m_unk0x258->AllPartsPlaced()) {
1204 FUN_100243a0();
1205 }
1206 else {
1207 FUN_10025720(5);
1208 }
1209 }
1210 else {
1212 }
1213 break;
1214 case 2:
1215 MxU32 jukeboxScript;
1216
1217 switch (m_carId) {
1218 case Helicopter_Actor:
1220 break;
1221 case DuneBugy_Actor:
1223 break;
1224 case Jetski_Actor:
1225 jukeboxScript = JukeboxScript::c_JetskiBuild_Music;
1226 break;
1227 case RaceCar_Actor:
1229 }
1230
1231 m_unk0x338 = SoundManager()->FUN_100aebd0(*g_jukeboxScript, jukeboxScript);
1232
1233 if (m_unk0x338) {
1235 FUN_10024ef0();
1236 }
1237 else {
1238 // In BETA10, NotificationManager->Send() also takes __FILE__ and __LINE__ arguments
1240 }
1241 break;
1242 }
1243
1244 return 1;
1245}
1246
1247// FUNCTION: LEGO1 0x10024ef0
1249{
1250 FUN_1003eda0();
1253 m_buildState->m_unk0x4c += 1;
1255}
1256
1257// FUNCTION: LEGO1 0x10024f30
1258// FUNCTION: BETA10 0x1006dfa0
1260{
1261 FUN_10022f30();
1262 m_unk0x258->SetUnknown0xbc(2);
1263}
1264
1265// FUNCTION: LEGO1 0x10024f50
1266// FUNCTION: BETA10 0x1006dfce
1268{
1269 m_unk0x2d4 = FALSE;
1270 m_unk0x258->RotateAroundYAxis(g_rotationAngleStepYAxis);
1271}
1272
1273// FUNCTION: LEGO1 0x10024f70
1274// FUNCTION: BETA10 0x1006e002
1276{
1277 if (m_unk0x258->StringEndsOnY(m_unk0x110->GetName())) {
1278 SetPresentersEnabled(p_enabled);
1279 }
1280}
1281
1282// FUNCTION: LEGO1 0x10024fa0
1283// FUNCTION: BETA10 0x1006e04f
1285{
1286 m_presentersEnabled = p_enabled;
1287 m_ColorBook_Bitmap->Enable(p_enabled);
1288 m_Yellow_Ctl->Enable(p_enabled);
1289 m_Red_Ctl->Enable(p_enabled);
1290 m_Blue_Ctl->Enable(p_enabled);
1291 m_Green_Ctl->Enable(p_enabled);
1292 m_Gray_Ctl->Enable(p_enabled);
1293 m_Black_Ctl->Enable(p_enabled);
1294}
1295
1296// FUNCTION: LEGO1 0x10025010
1298{
1299 m_ColorBook_Bitmap->Enable(!m_ColorBook_Bitmap->IsEnabled());
1300 m_Yellow_Ctl->Enable(!m_Yellow_Ctl->IsEnabled());
1301 m_Red_Ctl->Enable(!m_Red_Ctl->IsEnabled());
1302 m_Blue_Ctl->Enable(!m_Blue_Ctl->IsEnabled());
1303 m_Green_Ctl->Enable(!m_Green_Ctl->IsEnabled());
1304 m_Gray_Ctl->Enable(!m_Gray_Ctl->IsEnabled());
1305 m_Black_Ctl->Enable(!m_Black_Ctl->IsEnabled());
1306}
1307
1308// FUNCTION: LEGO1 0x100250e0
1309// FUNCTION: BETA10 0x1006e124
1311{
1312 if (m_unk0x258->StringDoesNotEndOnZero(m_unk0x110->GetName()) && m_Decals_Ctl) {
1313 if (strnicmp(m_unk0x110->GetName(), "JSFRNT", strlen("JSFRNT")) == 0) {
1314 m_Decal_Bitmap->Enable(p_enabled);
1315 m_Decals_Ctl->Enable(p_enabled);
1316 m_Decals_Ctl1->Enable(p_enabled);
1317 m_Decals_Ctl2->Enable(p_enabled);
1318 m_Decals_Ctl3->Enable(p_enabled);
1319 }
1320 else if (strnicmp(m_unk0x110->GetName(), "JSWNSH", strlen("JSWNSH")) == 0) {
1321 m_Decal_Bitmap->Enable(p_enabled);
1322 m_Decals_Ctl4->Enable(p_enabled);
1323 m_Decals_Ctl5->Enable(p_enabled);
1324 m_Decals_Ctl6->Enable(p_enabled);
1325 m_Decals_Ctl7->Enable(p_enabled);
1326 }
1327 else if (strnicmp(m_unk0x110->GetName(), "RCBACK", strlen("RCBACK")) == 0) {
1328 m_Decals_Ctl1->Enable(p_enabled);
1329 }
1330 else if (strnicmp(m_unk0x110->GetName(), "RCTAIL", strlen("RCTAIL")) == 0) {
1331 m_Decals_Ctl2->Enable(p_enabled);
1332 }
1333 else if (m_Decals_Ctl1 && strnicmp(m_unk0x110->GetName(), "chljety", strlen("chljety")) == 0) {
1334 m_Decals_Ctl1->Enable(p_enabled);
1335 }
1336 else if (m_Decals_Ctl2 && strnicmp(m_unk0x110->GetName(), "chrjety", strlen("chrjety")) == 0) {
1337 m_Decals_Ctl2->Enable(p_enabled);
1338 }
1339 else if (m_Decals_Ctl) {
1340 m_Decals_Ctl->Enable(p_enabled);
1341 }
1342 }
1343}
1344
1345// FUNCTION: LEGO1 0x10025350
1346// FUNCTION: BETA10 0x1006e3c0
1348{
1349 const LegoChar* color;
1350 LegoChar buffer[256];
1351
1352 if (!m_unk0x110) {
1353 return;
1354 }
1355
1356 if (m_Yellow_Ctl->GetAction()->GetObjectId() == p_objectId) {
1357 color = "lego yellow";
1358 }
1359 else if (m_Red_Ctl->GetAction()->GetObjectId() == p_objectId) {
1360 color = "lego red";
1361 }
1362 else if (m_Blue_Ctl->GetAction()->GetObjectId() == p_objectId) {
1363 color = "lego blue";
1364 }
1365 else if (m_Green_Ctl->GetAction()->GetObjectId() == p_objectId) {
1366 color = "lego green";
1367 }
1368 else if (m_Gray_Ctl->GetAction()->GetObjectId() == p_objectId) {
1369 color = "lego white";
1370 }
1371 else if (m_Black_Ctl->GetAction()->GetObjectId() == p_objectId) {
1372 color = "lego black";
1373 }
1374 else {
1375 return;
1376 }
1377
1378 m_Paint_Sound->Enable(FALSE);
1379 m_Paint_Sound->Enable(TRUE);
1380 m_unk0x110->FUN_100a93b0(color);
1381 sprintf(buffer, "c_%s", m_unk0x110->GetName());
1382 VariableTable()->SetVariable(buffer, color);
1383}
1384
1385// FUNCTION: LEGO1 0x10025450
1386// FUNCTION: BETA10 0x1006e599
1388{
1389 m_unk0x12c = m_unk0x110->GetLocal2World();
1390 m_unk0x1c0 = m_unk0x12c;
1391
1392 Vector3 lastColumnOfUnk0x1c0(m_unk0x1c0[3]);
1393 lastColumnOfUnk0x1c0 = Vector3(m_unk0x258->GetUnknown0xe0()[3]);
1394
1395 // This looks odd, but it improves the LEGO1 match while breaking the BETA10 match.
1396 // I don't know whether this is due to compiler entropy.
1397 // Feel free to replace unk0x178 -> m_unk0x178 and remove this variable if it improves the LEGO1 match
1398 // in the future.
1399 MxMatrix* unk0x178 = &m_unk0x178;
1400 *unk0x178 = m_unk0x12c;
1401
1402 if (m_unk0x258->PartIsPlaced(m_unk0x110->GetName())) {
1403 m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition());
1404
1405 if (!m_unk0x2d4) {
1406 m_unk0x2bc = m_unk0x2a4;
1407
1408 m_unk0x208 = m_unk0x12c;
1409 m_unk0x2a4[0] += m_unk0x1c0[3][0] - m_unk0x208[3][0];
1410 m_unk0x2a4[1] += m_unk0x1c0[3][1] - m_unk0x208[3][1];
1411 m_unk0x2a4[2] += m_unk0x1c0[3][2] - m_unk0x208[3][2];
1412 }
1413
1414 *unk0x178 = m_unk0x1c0;
1415 }
1416 else {
1417 const LegoChar* wiredName;
1418
1419 if (!m_unk0x258->FUN_10079c30(m_unk0x110->GetName())) {
1420 wiredName = m_unk0x258->GetWiredNameByPartName(m_unk0x110->GetName());
1421 }
1422 else {
1423 wiredName = m_unk0x258->GetWiredNameOfLastPlacedPart();
1424 }
1425
1426 LegoROI* parentROI = (LegoROI*) m_unk0x110->GetParentROI();
1427 m_unk0x208 = parentROI->FindChildROI(wiredName, parentROI)->GetLocal2World();
1428 m_unk0x2bc = Vector4(parentROI->FindChildROI(wiredName, parentROI)->GetWorldPosition());
1429 m_unk0x2a4 = Vector4(m_unk0x110->GetWorldPosition());
1430
1431 m_unk0x2a4[2] += (m_unk0x1c0[3][2] - m_unk0x12c[3][2]);
1432 m_unk0x178[3][2] = m_unk0x1c0[3][2];
1433 }
1434}
1435
1436// FUNCTION: LEGO1 0x100256c0
1437// FUNCTION: BETA10 0x1006e96c
1439{
1440 LegoWorld::Enable(p_enable);
1441
1442 if (p_enable) {
1443 InputManager()->SetWorld(this);
1445 }
1446 else {
1448 if (InputManager()->GetWorld() == this) {
1450 }
1451 }
1452}
1453
1454// FUNCTION: BETA10 0x10070520
1455inline MxU32 LegoCarBuild::Beta0x10070520()
1456{
1457 switch (m_carId) {
1458 case Helicopter_Actor:
1459 return 2;
1460 case DuneBugy_Actor:
1461 return 0;
1462 case Jetski_Actor:
1463 return 1;
1464 case RaceCar_Actor:
1465 return 3;
1466 default:
1467 assert(0);
1468 return 0;
1469 }
1470}
1471
1472inline void LegoCarBuild::StopActionIn0x344()
1473{
1474 // There is no direct evidence for this inline function in LEGO1,
1475 // but some code doesn't make much sense otherwise. For example,
1476 // sometimes `m_unk0x344` is set to another value right below this call,
1477 // which the original developer would likely have refactored.
1478 if (m_unk0x344 != DS_NOT_A_STREAM) {
1480 m_unk0x344 = DS_NOT_A_STREAM;
1481 }
1482}
1483
1484// FUNCTION: LEGO1 0x10025720
1485// FUNCTION: BETA10 0x1006e9df
1487{
1488 m_numAnimsRun++;
1489 m_unk0x10a = 0;
1490 MxS32 uVar6;
1491
1492#ifndef BETA10
1493 if (GameState()->GetCurrentAct() == LegoGameState::e_act2) {
1494 // This is most likely related to the helicopter rebuild in Act 2
1495 switch (p_param) {
1496 case 0:
1497 case 1:
1498 case 2:
1499 case 3:
1500 switch (rand() % 3) {
1501 case 0:
1503 StopActionIn0x344();
1507 break;
1508 case 1:
1510 StopActionIn0x344();
1514 break;
1515 case 2:
1517 StopActionIn0x344();
1521 break;
1522 }
1523 break;
1524 case 4:
1525 FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x04);
1526 break;
1527 case 5:
1528 FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x08);
1529 break;
1530 case 6:
1531 m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x18;
1532 uVar6 = m_unk0x10a;
1533 StopActionIn0x344();
1534
1535 if (uVar6 != DS_NOT_A_STREAM) {
1536 m_unk0x344 = uVar6;
1539 }
1540
1541 break;
1542 default:
1543 m_numAnimsRun--;
1544 return;
1545 }
1546 }
1547 else {
1548#endif
1549 // This part doesn't match BETA10 perfectly, but it's the closest we get without hundreds of #ifdef's
1550 switch (p_param) {
1551 case 0:
1552 m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x00;
1553 FUN_10025d10(m_unk0x10a);
1554 break;
1555 case 1:
1556 m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x0c;
1557 FUN_10025d10(m_unk0x10a);
1558
1559 if (m_carId == 2) {
1560 m_unk0x10a = 0;
1561 }
1562
1563 break;
1564 case 2:
1565 m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x10;
1566 FUN_10025d10(m_unk0x10a);
1567
1568 if (m_carId != 3) {
1569 m_unk0x10a = 0;
1570 }
1571
1572 break;
1573 case 3:
1574 FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x14);
1575 break;
1576 case 4:
1577 FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x04);
1578 break;
1579 case 5:
1580 FUN_10025d10(g_unk0x100d65b0[Beta0x10070520()].m_unk0x08);
1581 break;
1582 case 6:
1583 m_unk0x10a = g_unk0x100d65b0[Beta0x10070520()].m_unk0x18;
1584 FUN_10025d10(m_unk0x10a);
1585 break;
1586 default:
1587 assert(0);
1588 m_numAnimsRun--;
1589
1590 // Weird: This assertion can never be executed. The `assert(0)` above was probably introduced later.
1591 assert(m_numAnimsRun >= 0);
1592 return;
1593 }
1594#ifndef BETA10
1595 }
1596#endif
1597
1598 if (m_unk0x10a != 0) {
1599 m_unk0x10c = timeGetTime();
1600 }
1601}
1602
1603// FUNCTION: LEGO1 0x10025d10
1604// FUNCTION: BETA10 0x10070490
1606{
1607 // this function has a different signature and partially different body in BETA10, but it is called in the same
1608 // places
1609 if (m_unk0x344 != DS_NOT_A_STREAM) {
1611 m_unk0x344 = DS_NOT_A_STREAM;
1612 }
1613
1614 if (p_param != DS_NOT_A_STREAM) {
1615 m_unk0x344 = p_param;
1618 }
1619}
1620
1621// FUNCTION: LEGO1 0x10025d70
1623{
1624 switch (m_buildState->m_unk0x4c % 3) {
1625 case 1:
1626 return 1;
1627 case 2:
1628 return 2;
1629 case 3:
1630 return 3;
1631 default:
1632 return 0;
1633 }
1634}
1635
1636// FUNCTION: LEGO1 0x10025db0
1637// FUNCTION: BETA10 0x1006ed18
1638void LegoCarBuild::FUN_10025db0(const char* p_param1, undefined4 p_param2)
1639{
1640 m_unk0x33c = (MxControlPresenter*) Find("MxControlPresenter", p_param1);
1641
1642 MxS16 sVar3 = 1 - ((p_param2 / 5) & 1);
1643
1644 if (m_Yellow_Ctl == m_unk0x33c) {
1645 if (sVar3 != g_unk0x100f11cc) {
1647 g_unk0x100f11cc = sVar3;
1648 }
1649 }
1650 else {
1651 if (m_unk0x33c->GetUnknown0x4e() != sVar3) {
1652 m_unk0x33c->VTable0x6c(sVar3);
1653 }
1654
1655 g_unk0x100f11cc = -1;
1656 SetPresentersEnabled(m_presentersEnabled);
1657 }
1658}
1659
1660// FUNCTION: LEGO1 0x10025e40
1662{
1663 SetPresentersEnabled(m_presentersEnabled);
1664 if (m_unk0x33c && m_Yellow_Ctl != m_unk0x33c) {
1665 m_unk0x33c->VTable0x6c(0);
1666 }
1667}
1668
1669// FUNCTION: LEGO1 0x10025e70
1671{
1673 MxS32 targetEntityId = FUN_10025ee0(m_carId);
1675 DeleteObjects(&m_atomId, 500, 999);
1676
1678 m_destLocation = LegoGameState::e_infomain;
1679 return TRUE;
1680}
1681
1682// FUNCTION: LEGO1 0x10025ee0
1684{
1685 // TODO: Work out constants
1686 switch (p_param1) {
1687 case 1:
1688 return 0x2f;
1689 case 2:
1690 return 0x31;
1691 case 3:
1692 return 0x33;
1693 case 4:
1694 return 0x35;
1695 default:
1696 return -1;
1697 }
1698}
1699
1700// FUNCTION: LEGO1 0x10025f30
1702{
1703 m_className = p_classType;
1704 m_unk0x4c = 0;
1705 m_unk0x4d = FALSE;
1706 m_unk0x4e = FALSE;
1708}
1709
1710// FUNCTION: LEGO1 0x10026120
1711// FUNCTION: BETA10 0x1006eef0
1713{
1714 LegoState::Serialize(p_storage);
1715
1716 if (p_storage->IsReadMode()) {
1717 p_storage->ReadU8(m_unk0x4c);
1718 p_storage->ReadU8(m_unk0x4d);
1719 p_storage->ReadU8(m_unk0x4e);
1720#ifndef BETA10
1721 p_storage->ReadU8(m_placedPartCount);
1722#endif
1723 }
1724 else {
1725 p_storage->WriteU8(m_unk0x4c);
1726 p_storage->WriteU8(m_unk0x4d);
1727 p_storage->WriteU8(m_unk0x4e);
1728#ifndef BETA10
1729 p_storage->WriteU8(m_placedPartCount);
1730#endif
1731 }
1732
1733 return SUCCESS;
1734}
[AI] Holds state and transient gameplay data for the first act on Lego Island.
Definition: isle.h:29
DuneBuggy * m_dunebuggy
[AI] Serializable pointer to current dune buggy object (NULL when not held in state)....
Definition: isle.h:158
Helicopter * m_helicopter
[AI] Serializable pointer to current helicopter object (NULL when not held in state)....
Definition: isle.h:137
RaceCar * m_racecar
[AI] Serializable pointer to current racecar object (NULL when not held in state)....
Definition: isle.h:173
LegoNamedPlane m_helicopterPlane
[AI] Serialized/deserialized world placement state for helicopter.
Definition: isle.h:125
LegoNamedPlane m_jetskiPlane
[AI] Placement state for jetski in world (serializable). [AI]
Definition: isle.h:140
LegoNamedPlane m_dunebuggyPlane
[AI] Placement state for dune buggy in world (serializable). [AI]
Definition: isle.h:152
LegoNamedPlane m_racecarPlane
[AI] Placement state for racecar in world (serializable). [AI]
Definition: isle.h:161
Jetski * m_jetski
[AI] Serializable pointer to current jetski object (NULL when not held in state). [AI]
Definition: isle.h:149
[AI] Represents the player-controllable dune buggy vehicle in LEGO Island, inheriting movement and in...
Definition: dunebuggy.h:16
[AI] Represents the flyable helicopter vehicle/path actor in the game, handling all in-game behaviors...
Definition: helicopter.h:57
[AI] Represents the jetski vehicle placed in the 3D world of LEGO Island.
Definition: jetski.h:19
void SetUnknown0xbc(undefined2 p_unk0xbc)
[AI] Sets the internal unknown word at offset 0xbc.
Matrix4 & GetUnknown0xe0()
[AI] Provides access to the internal Matrix4 representing current animation state,...
void PutFrame() override
[AI] Called once per displayed animation frame.
const LegoChar * GetWiredNameOfLastPlacedPart()
[AI] Returns the wired part name for the last placed part.
void SetPartObjectIdByName(const LegoChar *p_name, MxS16 p_objectId)
[AI] Sets the object id for the given part name in the assembly state.
void FUN_10079790(const LegoChar *p_name)
[AI] Advances current placed part, handles swaps, and updates morph/visibility.
MxBool PartIsPlaced(const LegoChar *p_name)
[AI] Returns whether a part (by name) has already been placed in the sequence.
MxBool StringEndsOnY(const LegoChar *p_string)
[AI] Checks if the supplied string ends with "Y" or "y" in the second-to-last character.
void RotateAroundYAxis(MxFloat p_angle)
[AI] Rotates the assembly platform (root part) around the Y axis by the given angle (quaternion math)...
MxBool StringDoesNotEndOnZero(const LegoChar *p_string)
[AI] Checks if string does not end on the character '0'.
MxBool FUN_10079c30(const LegoChar *p_name)
[AI] Returns true if the part with the given name is not yet placed, but is the current to-be-placed ...
MxBool AllPartsPlaced()
[AI] Returns TRUE if all parts have been placed (i.e., assembly is complete).
const LegoChar * GetWiredNameByPartName(const LegoChar *p_name)
[AI] Retrieves the wireframe/scene-graph name associated with the player-facing part name.
const BoundingSphere & FUN_10079e20()
[AI] Returns the world bounding sphere of the next part to be placed.
MxBool StringEndsOnYOrN(const LegoChar *p_string)
[AI] Returns TRUE if the given part's name ends with 'Y', 'y', 'N', or 'n' as the second-to-last char...
[AI] World implementation for the LEGO vehicle builder (Racecar, Copter, Dune Car,...
Definition: legocarbuild.h:97
MxS16 GetPlacedPartCount()
[AI] Gets number of parts currently placed in build progress.
void FUN_10022f00()
[AI] Internal: handles transition when moving a placed part, possibly triggering state change.
MxResult Create(MxDSAction &p_dsAction) override
[AI] Creates world from script action; initializes build and assigns state according to area/car type...
MxS32 FUN_10025d70()
[AI] Gets next animation/cutscene ID depending on current build stage value.
void FUN_100243a0()
[AI] Handles the transition to the next act/location when building is complete.
LegoCarBuild()
[AI] Constructs a new LegoCarBuild world and initializes all references/UI.
MxResult Tickle() override
[AI] Tickle function (called every frame/tick); processes build logic and part animation.
void FUN_10024f30()
[AI] Internal: Logic for the shelf-up UI animation/response.
virtual void VTable0x7c(MxFloat p_param1[2], MxFloat p_param2[3])
[AI] Adjusts transformation for part manipulation above the "default" reference.
virtual void VTable0x70()
[AI] Computes screen-projected coordinates for picking/placing parts and updates internal pixel locat...
void FUN_10025350(MxS32 p_objectId)
[AI] Handles color/decal actions by object ID, mapping click to appropriate color or updating variabl...
void FUN_10025720(undefined4 p_param1)
[AI] Initiates the next world/cutscene/animation step, based on internal build progress and car ID.
void ReadyWorld() override
[AI] Prepares UI and scripting when world is ready.
undefined4 FUN_100244e0(MxLong p_x, MxLong p_y)
[AI] Handles mouse click/button down notifications to pick parts or trigger color/decal tools.
MxLong Notify(MxParam &p_param) override
[AI] Handles notifications (input, state, animation, world events) for the build world.
undefined4 FUN_10024c20(LegoEventNotificationParam *p_param)
[AI] Handles the core event when the build is completed and creation should be finalized.
MxBool Escape() override
[AI] Escapes from the build UI (initiates transition to outside world/menu).
void FUN_10024f50()
[AI] Internal: Handles part rotation/y-axis interaction.
virtual void VTable0x78(MxFloat p_param1[2], MxFloat p_param2[3])
[AI] Adjusts transformation for part manipulation when within the vertical bounds of the reference po...
virtual void VTable0x6c()
[AI] Internal logic, used during part drag/drop and animation (possibly for placing or updating a par...
virtual void VTable0x74(MxFloat p_param1[2], MxFloat p_param2[3])
[AI] Adjusts transformation for part manipulation based on mouse/drag locations below the "default" p...
void FUN_10022f30()
[AI] Internal: logic for finalizing or dropping a part at build location, updates sound and UI.
undefined4 FUN_10024250(LegoEventNotificationParam *p_param)
[AI] Handles keyboard event notifications, most notably the Space key for canceling animations or sou...
undefined4 FUN_10024890(MxParam *p_param)
[AI] Handles UI input/control presenter notifications.
void SetPlacedPartCount(MxU8 p_placedPartCount)
[AI] Sets the number of placed parts in the build state.
void InitPresenters()
[AI] Finds and initializes all presenters (UI and sound) used in the car build area.
void FUN_10025e40()
[AI] Re-applies enabled/disabled flags on presenters, resetting the last-toggled presenter if needed.
virtual void VTable0x80(MxFloat p_param1[2], MxFloat p_param2[2], MxFloat p_param3, MxFloat p_param4[2])
[AI] Used for conversions between projected and real pixel/world space.
@ c_unknownminusone
[AI] Default/uninitialized
Definition: legocarbuild.h:116
@ c_unknown8
[AI] Internal marker
Definition: legocarbuild.h:117
void FUN_100250e0(MxBool p_param)
[AI] Enables/Disables only the presenter set related to current part, using name pattern.
~LegoCarBuild() override
[AI] Cleans up presenters, unregisters input/notification handlers, and resets world build state.
void FUN_100236d0()
[AI] Internal: launches the finalization of all parts if build is completed; triggers further game pr...
undefined4 FUN_100246e0(MxLong p_x, MxLong p_y)
[AI] Handles mouse button up events; initiates part-finalization or validated placement.
void FUN_10025450()
[AI] Updates part transformation matrices and records old/new world/projected positions for drag/drop...
void FUN_10024f70(MxBool p_enabled)
[AI] Enables/Disables color/decal presenters depending on selected part and part name.
void TogglePresentersEnabled()
[AI] Toggles enabled/disabled state for all main presenters (color/decal tools).
MxS32 FUN_10025ee0(undefined4 p_param1)
[AI] Gets the appropriate jukebox/music action ID for the current car type, used when leaving the bui...
void Enable(MxBool p_enable) override
[AI] Enables or disables the world, handling both visual and audio states and input registration.
undefined4 FUN_10024480(MxActionNotificationParam *p_param)
[AI] Handles animation end notification action (e.g., volume restoration, state reset,...
void FUN_10025db0(const char *p_param1, undefined4 p_param2)
[AI] Controls global UI presentations actions (such as blinking or activation), based on progress in ...
MxS32 FUN_10024850(MxLong p_x, MxLong p_y)
[AI] Handles mouse move notifications for drag-to-place part.
void FUN_10025d10(MxS32 p_param)
[AI] Starts/stops an animation action for the specified parameter (e.g., cutscene transition,...
void FUN_10023130(MxLong p_x, MxLong p_y)
[AI] Internal: handles interaction when dragging part along projected axis.
void FUN_10024ef0()
[AI] Starts the cutscene or music intro for the build with necessary state adjustment.
void SetPresentersEnabled(MxBool p_enabled)
[AI] Controls common set of UI presenters' enabled state at once.
[AI] Notification parameter for the LegoControlManager, used to propagate information about control e...
MxS32 m_clickedObjectId
[AI] Object ID of the clicked control/presenter (or -1 if not set). [AI]
MxS16 m_unk0x28
[AI] Undetermined; settable via SetUnknown0x28. [AI]
void Register(MxCore *p_listener)
[AI] Adds a listener to be notified of control events.
void Unregister(MxCore *p_listener)
[AI] Removes a listener so it no longer receives control events.
[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
Notification parameter class for LEGO event notifications such as mouse events and modifier keys.
MxU8 GetKey() const
Returns the keycode for this event, or 0 if not used.
Comprehensive persistent game state manager: handles save/load, player selection, area switching,...
Definition: legogamestate.h:78
void SwitchArea(Area p_area)
Switches the whole game state into a new area/world; manages transitions/scene loads.
Area m_currentArea
Area/world the player is presently in. [AI].
LegoState * CreateState(const char *p_stateName)
Creates an instance of given state, registers it, and returns pointer.
@ e_act2
Act 2: main story segment two. [AI].
Definition: legogamestate.h:85
void StopArea(Area p_area)
Calls cleanup logic for the specified area (removes actors, VMs, closes handles, etc....
LegoState * GetState(const char *p_stateName)
Find an existing state (LegoState-derived) object by its registered script/class name.
@ e_infomain
Information Center, main screen. [AI].
Definition: legogamestate.h:96
@ e_unk20
Unknown [AI].
@ e_previousArea
Alias: go to previous area. [AI].
Definition: legogamestate.h:94
@ e_dunecarbuild
Vehicle construction: dune buggy. [AI].
@ e_racecarbuild
Vehicle construction: racecar. [AI].
@ e_act3script
Act 3 world/script main. [AI].
@ e_garadoor
Garage door or doorway. [AI].
@ e_copterbuild
Vehicle construction: helicopter. [AI].
@ e_polidoor
Police Station door. [AI].
@ e_undefined
Undefined or unset area. [AI].
Definition: legogamestate.h:93
@ e_jetskibuild
Vehicle construction: jetski. [AI].
@ e_unk17
Unknown. [AI].
void UnRegister(MxCore *)
[AI] Unregister a previously registered recipient so it will no longer receive input notifications.
void ClearWorld()
[AI] Remove any world assignment (used to clear targeting/scene changes). [AI]
void SetWorld(LegoWorld *p_world)
[AI] Assigns the current world to receive mouse/click/pick notifications.
void Register(MxCore *)
[AI] Register a core object as a recipient for keyboard events; safe for concurrent multi-threading.
@ c_clearScreen
[AI] When set, clears the display surface. [AI]
Definition: legomain.h:49
@ c_disable3d
[AI] When set, disables 3D rendering. [AI]
Definition: legomain.h:48
@ c_disableInput
[AI] When set, disables input processing. [AI]
Definition: legomain.h:47
[AI] Represents a Real-time Object Instance enriched with LEGO-specific functionality.
Definition: legoroi.h:43
LegoResult FUN_100a93b0(const LegoChar *p_name)
[AI] Like SetLodColor, but uses a different implementation or legacy style.
Definition: legoroi.cpp:582
LegoROI * FindChildROI(const LegoChar *p_name, LegoROI *p_roi)
[AI] Recursively searches for a child ROI by name, starting at the given ROI.
Definition: legoroi.cpp:349
const LegoChar * GetName() const
[AI] Gets this ROI's name.
Definition: legoroi.h:287
virtual MxResult Serialize(LegoStorage *p_storage)
[AI] Serialize state to a storage (for save/load).
Definition: legostate.h:141
Abstract base class providing an interface for file-like storage with binary and text read/write oper...
Definition: legostorage.h:16
LegoStorage * WriteU8(LegoU8 p_data)
Writes an 8-bit unsigned value to storage.
Definition: legostorage.h:99
LegoStorage * ReadU8(LegoU8 &p_data)
Reads an 8-bit unsigned value from storage.
Definition: legostorage.h:206
virtual LegoBool IsReadMode()
Returns TRUE if object was opened in read mode.
Definition: legostorage.h:78
[AI] Represents the persistent state of the LEGO vehicle build world, tracking animation and part pla...
Definition: legocarbuild.h:24
MxBool m_unk0x4d
[AI] Persists transition or completion flag across world reloads.
Definition: legocarbuild.h:77
AnimationState m_animationState
[AI] Current animation state within the build area.
Definition: legocarbuild.h:74
@ e_exiting
[AI] Build area is in the process of ending/exiting.
Definition: legocarbuild.h:35
@ e_entering
[AI] Transition/Entering the build area.
Definition: legocarbuild.h:31
@ e_unknown4
[AI] Indicates transition to exit (possibly ready for world exit or next act).
Definition: legocarbuild.h:34
@ e_cutscene
[AI] Indicates that the build is in a cutscene (camera or instructions animation).
Definition: legocarbuild.h:33
@ e_unknown0
[AI] Default/uninitialized state. Meaning unclear.
Definition: legocarbuild.h:30
@ e_unknown2
[AI] Likely a 'ready' or transitional state before a cutscene.
Definition: legocarbuild.h:32
MxResult Serialize(LegoStorage *p_storage) override
[AI] Serialize or deserialize the build state to/from a storage object for save/load.
MxBool m_unk0x4e
[AI] Unknown. Flag—purpose unclear.
Definition: legocarbuild.h:78
MxString m_className
[AI] Class name string ("LegoRaceCarBuildState", etc), used for identifying the build state type.
Definition: legocarbuild.h:69
MxU8 m_placedPartCount
[AI] Number of parts (bricks) placed during the build.
Definition: legocarbuild.h:79
LegoVehicleBuildState(const char *p_classType)
[AI] Constructs a LegoVehicleBuildState with a specified class type string, which identifies the buil...
MxU8 m_unk0x4c
[AI] Number of completed actions or animation steps, incremented through build progress.
Definition: legocarbuild.h:76
Represents the active 3D world, holding all entity, animation, sound, path, and ROI objects.
Definition: legoworld.h:49
virtual void Enable(MxBool p_enable)
Enables or disables (pauses) the world and its main components.
Definition: legoworld.cpp:684
MxResult Tickle() override
Main world tick/update, especially manages startup countdown.
Definition: legoworld.cpp:810
MxBool m_worldStarted
Indicates if the world has successfully started and is considered active.
Definition: legoworld.h:388
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
MxLong Notify(MxParam &p_param) override
Notification callback responding to registered events such as EndAction and NewPresenter.
Definition: legoworld.cpp:212
MxResult Create(MxDSAction &p_dsAction) override
Initializes the world using an action, creating entity and sound lists, and camera controller.
Definition: legoworld.cpp:58
[AI] Notification parameter class that contains information about an MxDSAction, used for inter-objec...
MxDSAction * GetAction()
[AI] Direct access to the underlying action.
void Init()
[AI] Reinitializes manager's active presenter and tickle state; typically called at the start of a sc...
undefined4 FUN_1007f610(MxPresenter *p_unk0x138, MxS32 p_speed, MxPresenter::TickleState p_tickleState)
[AI] Helper for queued volume changing: Sets up a coming presenter/action for activation with given s...
void RaiseVolume()
[AI] Requests that the background music volume is raised (decrements suppression counter); triggers f...
void LowerVolume()
[AI] Requests a reduction in current background music volume, queuing for fade out (increments suppre...
void Stop()
[AI] Immediately stops all background music, clears all actions and presenters, and resets tickle sta...
[AI] Presenter for UI controls, supporting toggles, grids, and "map" style controls with multiple int...
void Enable(MxBool p_enable) override
[AI] Enables or disables the control; delegates enable to correct sub-presenter based on current stat...
virtual void VTable0x6c(MxS16 p_unk0x4e)
[AI] Selects a state/sub-control by index, or advances the currently selected state if -1 is provided...
MxS16 GetUnknown0x4e()
[AI] Returns the current selected/control state index.
[AI] Represents an action deserialized from SI chunks, holding key animation or script parameters suc...
Definition: mxdsaction.h:17
MxU32 GetObjectId()
[AI] Returns the object id numeric value.
Definition: mxdsobject.h:130
MxAtomId m_atomId
The AtomId associated with this entity, used for resource and script identification.
Definition: mxentity.h:124
[AI] Represents a 4x4 transformation matrix, specialized for the LEGO Island engine and derived from ...
Definition: mxmatrix.h:16
void Enable(MxBool p_enable) override
[AI] Enables or disables media stream playback and transitions state as needed.
void Unregister(MxCore *p_listener)
[AI] Removes a previously registered listener and flushes any pending notifications for it.
void Register(MxCore *p_listener)
[AI] Registers a listener object to receive notifications.
MxResult Send(MxCore *p_listener, const MxNotificationParam &p_param)
[AI] Queues a notification to be sent to a specific registered listener.
[AI] Parameter object representing a single notification or event, carrying an identifier and sender ...
NotificationId GetNotification() const
[AI] Retrieves the current notification type of this parameter.
[AI] MxParam serves as a polymorphic base class for parameter passing in event and notification syste...
Definition: mxparam.h:7
virtual void SetTickleState(TickleState p_tickleState)
[AI] Forces the tickle state, advancing to the requested lifecycle stage.
Definition: mxpresenter.h:100
MxBool IsEnabled()
[AI] Returns whether this presenter is logically enabled (based on the associated action's flags).
@ e_repeating
[AI] Presentation is repeating (e.g., looping media).
Definition: mxpresenter.h:28
@ e_idle
[AI] Not processing an action.
Definition: mxpresenter.h:24
MxDSAction * GetAction() const
[AI] Returns the current action being presented.
Definition: mxpresenter.h:175
void SetStartEnd(Matrix4 &p_m1, Matrix4 &p_m2)
Sets start and end quaternions by converting two matrices to quaternion form.
int InterpolateToMatrix(Matrix4 &p_matrix, float p_f)
Interpolates between start and end quaternions using spherical interpolation (slerp) and produces a 4...
MxPresenter * FUN_100aebd0(const MxAtomId &p_atomId, MxU32 p_objectId)
[AI] Finds a presenter matching a specific atom ID and object ID.
[AI] Concrete presenter for sound playback and control within the LEGO Island engine.
[AI] Presenter for single still image/bitmap media sources in the game.
void Enable(MxBool p_enable) override
[AI] Sets the enabled/disabled state of the presenter, updating the video manager's rendering as need...
virtual void UnregisterClient(MxCore *p_client)
[AI] Unregisters (marks for destruction) a previously registered client.
MxResult StartTransition(TransitionType p_animationType, MxS32 p_speed, MxBool p_doCopy, MxBool p_playMusicInAnim)
[AI] Begins a new transition animation of type p_animationType at the specified speed,...
@ e_mosaic
[AI] Complex mosaic block-out effect.
void SetVariable(const char *p_key, const char *p_value)
Sets a variable by key and value, replacing or updating if it exists.
const BoundingSphere & GetWorldBoundingSphere() const override
Returns the object's bounding sphere in world coordinates.
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 WrappedSetLocalTransform(const Matrix4 &p_transform)
Wraps SetLocalTransform, for possible override or interface uniformity.
OrientableROI * GetParentROI() const
Accessor for the parent ROI in the transformation hierarchy.
[AI] Represents the drivable race car entity in the LEGO Island world.
Definition: racecar.h:24
[AI] 3D vector class, providing vector and cross-product operations in 3D space.
Definition: vector.h:249
[AI] A four-dimensional vector, supporting operations relevant for matrix and quaternion math (homoge...
Definition: vector.h:365
#define TRUE
Definition: d3drmdef.h:28
#define FALSE
Definition: d3drmdef.h:27
typedef DWORD(FAR PASCAL *LPCLIPPERCALLBACK)(LPDIRECTDRAWCLIPPER lpDDClipper
#define DECOMP_SIZE_ASSERT(T, S)
Definition: decomp.h:19
unsigned int undefined4
Definition: decomp.h:28
#define LEGOCARBUILD_TICKLE_CASE(subtract, start, end, str)
#define Helicopter_Actor
#define Jetski_Actor
#define RaceCar_Actor
#define DuneBugy_Actor
#define NULL
[AI] Null pointer value (C/C++ semantics).
Definition: legotypes.h:26
char LegoChar
[AI] Alias for char, for use in character/byte data and string handling.
Definition: legotypes.h:83
#define SUCCESS
[AI] Used to indicate a successful operation in result codes.
Definition: legotypes.h:30
#define DS_NOT_A_STREAM
[AI] Special stream ID indicating that the current stream is not valid.
Definition: legoutils.h:16
void EnableAnimations(MxBool p_enable)
[AI] Enables or disables animation playback globally.
Definition: legoutils.cpp:554
void InvokeAction(Extra::ActionType p_actionId, const MxAtomId &p_pAtom, MxS32 p_streamId, LegoEntity *p_sender)
[AI] Dispatches and triggers a game action on the given script or object.
Definition: legoutils.cpp:271
MxBool TransformWorldToScreen(const MxFloat p_world[3], MxFloat p_screen[4])
[AI] Projects a world-space point into normalized screen coordinates.
Definition: legoutils.cpp:130
LegoROI * PickROI(MxLong p_x, MxLong p_y)
[AI] Picks the ROI (Renderable Object Instance) at screen coordinates.
Definition: legoutils.cpp:39
void FUN_1003eda0()
[AI] Updates sound listener position to follow the view ROI's transform.
Definition: legoutils.cpp:476
void RotateY(LegoROI *p_roi, MxFloat p_angle)
[AI] Rotates the given ROI around the Y axis in world space.
Definition: legoutils.cpp:75
MxBool SpheresIntersect(const BoundingSphere &p_sphere1, const BoundingSphere &p_sphere2)
[AI] Tests if two bounding spheres in the 3D world intersect.
Definition: legoutils.cpp:93
MxAtomId * g_isleScript
[AI] Node used in hierarchical scene graphs and animation trees. [AI]
Definition: scripts.cpp:32
MxBool FUN_1003ded0(MxFloat p_param1[2], MxFloat p_param2[3], MxFloat p_param3[3])
[AI] Calculates a ray starting at a screen location and outputs its world origin and direction.
Definition: legoutils.cpp:102
LegoGameState * GameState()
[AI] Accessor for the game's central game state controller. [AI]
Definition: misc.cpp:61
void DeleteObjects(MxAtomId *p_id, MxS32 p_first, MxS32 p_last)
[AI] Batch deletes objects, given by atom id, and within the entity id range [p_first,...
Definition: misc.cpp:237
LegoSoundManager * SoundManager()
[AI] Accessor for the game's LegoSoundManager subsystem from the global LegoOmni instance....
Definition: misc.cpp:22
MxTransitionManager * TransitionManager()
[AI] Accessor for the MxTransitionManager, handling level transitions, fades, and world changes....
Definition: misc.cpp:208
MxBackgroundAudioManager * BackgroundAudioManager()
[AI] Accessor for the background audio manager. Used for background music and ambient sounds....
Definition: misc.cpp:37
LegoWorld * FindWorld(const MxAtomId &p_atom, MxS32 p_entityid)
[AI] Searches for or retrieves a LegoWorld instance based on an atom id and entity id.
Definition: misc.cpp:188
LegoControlManager * ControlManager()
[AI] Accessor for the control manager through the input manager; manages higher-level user/game contr...
Definition: misc.cpp:53
void FUN_10015820(MxBool p_disable, MxU16 p_flags)
[AI] Utility for enabling or disabling functionality in LegoOmni based on certain flags.
Definition: misc.cpp:143
void SetIsWorldActive(MxBool p_isWorldActive)
[AI] Toggles whether the world should be considered active (enables/disables camera/user control etc)...
Definition: misc.cpp:228
LegoInputManager * InputManager()
[AI] Accessor for the input manager, which handles keyboard, mouse, and controller input....
Definition: misc.cpp:45
MxVariableTable * VariableTable()
[AI] Returns the variable table used for script variables and global key/value state.
Definition: mxmisc.cpp:73
MxNotificationManager * NotificationManager()
[AI] Returns the notification manager for system-wide state/update notifications.
Definition: mxmisc.cpp:17
MxTickleManager * TickleManager()
[AI] Provides access to the global tickle manager.
Definition: mxmisc.cpp:25
@ c_notificationControl
[AI] UI control event [AI]
@ c_notificationButtonUp
[AI] Mouse/gamepad button release [AI]
@ c_notificationButtonDown
[AI] Mouse/gamepad button press [AI]
@ c_notificationEndAnim
[AI] End of an animation [AI]
@ c_notificationMouseMove
[AI] Mouse movement event [AI]
@ c_notificationKeyPress
[AI] Keyboard key press detected [AI]
@ c_notificationTransitioned
[AI] Object has transitioned states or locations [AI]
@ c_notificationType0
[AI] Undefined/Generic notification type [AI]
@ c_notificationEndAction
[AI] Indicates the end of an action [AI]
MxU8 MxBool
[AI]
Definition: mxtypes.h:124
MxLong MxResult
[AI]
Definition: mxtypes.h:106
int MxLong
[AI]
Definition: mxtypes.h:83
signed short MxS16
[AI]
Definition: mxtypes.h:26
float MxFloat
[AI]
Definition: mxtypes.h:68
unsigned char MxU8
[AI]
Definition: mxtypes.h:8
signed int MxS32
[AI]
Definition: mxtypes.h:38
unsigned int MxU32
[AI]
Definition: mxtypes.h:32
double MxDouble
[AI]
Definition: mxtypes.h:74
@ c_ips001d2_RunAnim
[AI] Trigger/action for running the full ips001d2 animation.
@ c_ips005d2_RunAnim
[AI] Trigger/action for running the full ips005d2 animation.
@ c_ipsxx1d2_RunAnim
[AI] Trigger/action for running the full ipsxx1d2 animation.
@ c_Exit_Ctl
[AI] "Exit" button or UI control handler.
@ c_ips003d2_RunAnim
[AI] Trigger/action for running the full ips003d2 animation.
@ c_ShelfUp_Ctl
[AI] "Shelf up" UI control, possibly for toggling/animating a shelf.
@ c_slp01xd2_RunAnim
[AI] Trigger/action for running the full slp01xd2 animation.
@ c_Info_Ctl
[AI] "Info" button or UI control handler for the copter UI.
@ c_ips004d2_RunAnim
[AI] Trigger/action for running the full ips004d2 animation.
@ c_Platform_Ctl
[AI] "Platform" control - possibly for animation/location logic.
@ c_ips002d2_RunAnim
[AI] Trigger/action for running the full ips002d2 animation.
@ c_ips006d2_RunAnim
[AI] Trigger/action for running the full ips006d2 animation.
@ c_igs002d3_RunAnim
[AI] Run animation for 002d3 sequence.
@ c_igs004d3_RunAnim
[AI] Run animation for 004d3 sequence.
@ c_igs005d3_RunAnim
[AI] Run animation for 005d3 sequence.
@ c_igs001d3_RunAnim
[AI] Run animation for 001d3 sequence.
@ c_igs003d3_RunAnim
[AI] Run animation for 003d3 sequence.
@ c_igsxx1d3_RunAnim
[AI] Run animation for xx1d3 sequence.
@ c_ijs007d4_RunAnim
[AI] Run animation for jetski type 7. [AI]
@ c_ijs003d4_RunAnim
[AI] Run animation for jetski type 3. [AI]
@ c_ijs006d4_RunAnim
[AI] Run animation for jetski type 6. [AI]
@ c_ijs001d4_RunAnim
[AI] Run animation for jetski type 1. [AI]
@ c_ijs005d4_RunAnim
[AI] Run animation for jetski type 5. [AI]
@ c_ijsxx2d4_RunAnim
[AI] Run animation for jetski type X. [AI]
@ c_ijs004d4_RunAnim
[AI] Run animation for jetski type 4. [AI]
@ c_HelicopterBuild_Music
[AI] Music used for the helicopter build event.
@ c_JetskiBuild_Music
[AI] Music for the Jetski build event.
@ c_DuneCarBuild_Music
[AI] Music used for the Dune Car build.
@ c_RaceCarBuild_Music
[AI] Music for the Race Car build.
[AI] Contains global script AtomId pointers and utility functions for managing script AtomIds in LEGO...
MxAtomId * g_jukeboxScript
[AI] Script AtomId for the Jukebox entity/event script.
Definition: scripts.cpp:70
MxAtomId * g_racecarScript
[AI] Script AtomId for the build/race car SI file.
Definition: scripts.cpp:15
MxAtomId * g_copterScript
[AI] Script AtomId for the helicopter ("copter") build or activity.
Definition: scripts.cpp:6
MxAtomId * g_jetskiScript
[AI] Script AtomId for the jet ski-related script.
Definition: scripts.cpp:12
MxAtomId * g_dunecarScript
[AI] Script AtomId for the dune car building or mission script.
Definition: scripts.cpp:9
@ e_stop
[AI] Stop an activity or playback [AI]
Definition: extra.h:31
@ e_start
[AI] Start an activity or playback [AI]
Definition: extra.h:30
undefined4 m_unk0x18
[AI] Script/action ID for animation 6.
Definition: legocarbuild.h:109
undefined4 m_unk0x10
[AI] Script/action ID for animation 4.
Definition: legocarbuild.h:107
undefined4 m_unk0x00
[AI] Script/action ID for animation 0.
Definition: legocarbuild.h:103
undefined4 m_unk0x0c
[AI] Script/action ID for animation 3.
Definition: legocarbuild.h:106
void Reset()
[AI] Reset the plane to "not present" by clearing its name.
#define DISTSQRD2(v, w)
Definition: vec.h:263
#define NORMSQRD2(v)
Definition: vec.h:260