Isle
Loading...
Searching...
No Matches
legopathcontroller.cpp
Go to the documentation of this file.
2
4#include "misc/legostorage.h"
5#include "mxmisc.h"
6#include "mxticklemanager.h"
7#include "mxtimer.h"
8
11DECOMP_SIZE_ASSERT(LegoPathController::CtrlBoundary, 0x08)
13
14// GLOBAL: LEGO1 0x100d7cc8
15MxU32 g_unk0x100d7cc8[] = {2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0, 2, 0};
16
17// GLOBAL: LEGO1 0x100d7d08
18MxU32 g_unk0x100d7d08[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
19
20// GLOBAL: LEGO1 0x100f42e8
21// GLOBAL: BETA10 0x101f25f0
22LegoPathController::CtrlBoundary* LegoPathController::g_ctrlBoundariesA = NULL;
23
24// GLOBAL: LEGO1 0x100f42ec
25// GLOBAL: BETA10 0x101f25f4
26LegoPathController::CtrlEdge* LegoPathController::g_ctrlEdgesA = NULL;
27
28// GLOBAL: LEGO1 0x100f42f0
29const char* LegoPathController::g_unk0x100f42f0[] = {
30 "edg03_21",
31 "edg03_23",
32 "edg03_30",
33 "edg03_31",
34 "edg03_39",
35 "edg03_40",
36 "edg03_91",
37 "edg03_92",
38 "edg03_99",
39 "edg03_100",
40 "edg03_112",
41 "edg03_113",
42 "edg10_61",
43 "edg10_62",
44 "edg10_55",
45 "edg10_58"
46};
47
48// GLOBAL: LEGO1 0x100f4330
49const char* LegoPathController::g_unk0x100f4330[] = {
50 "edg03_06",
51 "edg03_21",
52 "edg03_30",
53 "edg03_148",
54 "edg03_39",
55 "edg03_91",
56 "edg03_99",
57 "edg03_112",
58 "edg03_800",
59 "edg03_135"
60};
61
62// GLOBAL: LEGO1 0x100f4358
63LegoPathController::CtrlBoundary* LegoPathController::g_ctrlBoundariesB = NULL;
64
65// GLOBAL: LEGO1 0x100f435c
66LegoPathController::CtrlEdge* LegoPathController::g_ctrlEdgesB = NULL;
67
68// FUNCTION: LEGO1 0x10044f40
69// FUNCTION: BETA10 0x100b6860
71{
72 m_boundaries = NULL;
73 m_edges = NULL;
74 m_unk0x10 = NULL;
75 m_structs = NULL;
76 m_numL = 0;
77 m_numE = 0;
78 m_numN = 0;
79 m_numT = 0;
80}
81
82// FUNCTION: LEGO1 0x10045880
83// FUNCTION: BETA10 0x100b6959
84MxResult LegoPathController::Create(MxU8* p_data, const Vector3& p_location, const MxAtomId& p_trigger)
85{
86 MxResult result = FAILURE;
87 LegoMemory storage(p_data);
88
89 if ((result = Read(&storage)) == SUCCESS) {
90 MxS32 i;
91
92 for (i = 0; i < m_numT; i++) {
93 m_structs[i].SetAtomId(p_trigger);
94 }
95
96 for (i = 0; i < m_numN; i++) {
97 m_unk0x10[i] += p_location;
98 }
99
100 for (i = 0; i < m_numL; i++) {
101 LegoPathBoundary& boundary = m_boundaries[i];
102 MxS32 j;
103
104 for (j = 0; j < sizeOfArray(g_unk0x100f42f0); j++) {
105 if (!strcmpi(g_unk0x100f42f0[j], boundary.GetName())) {
106 g_ctrlBoundariesA[j].m_controller = this;
107 g_ctrlBoundariesA[j].m_boundary = &boundary;
108
109 MxU32 edge = g_unk0x100d7cc8[j];
110 g_ctrlEdgesA[j].m_controller = this;
111 g_ctrlEdgesA[j].m_edge = boundary.GetEdges()[edge];
112 }
113 }
114
115 for (j = 0; j < sizeOfArray(g_unk0x100f4330); j++) {
116 if (!strcmpi(g_unk0x100f4330[j], boundary.GetName())) {
117 g_ctrlBoundariesB[j].m_controller = this;
118 g_ctrlBoundariesB[j].m_boundary = &boundary;
119 g_ctrlEdgesB[j].m_controller = this;
120 g_ctrlEdgesB[j].m_edge = boundary.GetEdges()[g_unk0x100d7d08[j]];
121 }
122 }
123 }
124
125 TickleManager()->RegisterClient(this, 10);
126 }
127
128 if (result != SUCCESS) {
129 Destroy();
130 }
131
132 return result;
133}
134
135// FUNCTION: LEGO1 0x10045b20
136// FUNCTION: BETA10 0x100b6b8a
138{
140
141 if (m_boundaries != NULL) {
142 delete[] m_boundaries;
143 }
144 m_boundaries = NULL;
145 m_numL = 0;
146
147 if (m_unk0x10 != NULL) {
148 delete[] m_unk0x10;
149 }
150 m_unk0x10 = NULL;
151 m_numN = 0;
152
153 if (m_structs != NULL) {
154 delete[] m_structs;
155 }
156 m_structs = NULL;
157 m_numT = 0;
158
159 if (m_edges != NULL) {
160 delete[] m_edges;
161 }
162 m_edges = NULL;
163 m_numE = 0;
164
165 MxS32 j;
166 for (j = 0; j < sizeOfArray(g_unk0x100f42f0); j++) {
167 if (g_ctrlBoundariesA[j].m_controller == this) {
168 g_ctrlBoundariesA[j].m_controller = NULL;
169 g_ctrlBoundariesA[j].m_boundary = NULL;
170 }
171
172 if (g_ctrlEdgesA[j].m_controller == this) {
173 g_ctrlEdgesA[j].m_controller = NULL;
174 g_ctrlEdgesA[j].m_edge = NULL;
175 }
176 }
177
178 for (j = 0; j < sizeOfArray(g_unk0x100f4330); j++) {
179 if (g_ctrlBoundariesB[j].m_controller == this) {
180 g_ctrlBoundariesB[j].m_controller = NULL;
181 g_ctrlBoundariesB[j].m_boundary = NULL;
182 }
183
184 if (g_ctrlEdgesB[j].m_controller == this) {
185 g_ctrlEdgesB[j].m_controller = NULL;
186 g_ctrlEdgesB[j].m_edge = NULL;
187 }
188 }
189}
190
191// FUNCTION: LEGO1 0x10045c10
192// FUNCTION: BETA10 0x100b6d60
194{
195 FUN_10046970();
196 return SUCCESS;
197}
198
199// FUNCTION: LEGO1 0x10045c20
200// FUNCTION: BETA10 0x100b6d80
202 LegoPathActor* p_actor,
203 const char* p_name,
204 MxS32 p_src,
205 float p_srcScale,
206 MxS32 p_dest,
207 float p_destScale
208)
209{
210 if (p_actor->GetController() != NULL) {
211 p_actor->GetController()->RemoveActor(p_actor);
212 p_actor->SetController(NULL);
213 }
214
215 LegoPathBoundary* pBoundary = GetPathBoundary(p_name);
216
217 assert(pBoundary);
218 assert(p_src < pBoundary->GetNumEdges() && p_dest < pBoundary->GetNumEdges());
219
220 LegoEdge* pSrcE = pBoundary->GetEdges()[p_src];
221 LegoEdge* pDestE = pBoundary->GetEdges()[p_dest];
222
223 assert(pSrcE && pDestE);
224
225 float time = Timer()->GetTime();
226 MxResult result =
227 p_actor->VTable0x88(pBoundary, time, *pSrcE, p_srcScale, (LegoUnknown100db7f4&) *pDestE, p_destScale);
228
229 if (result != SUCCESS) {
230 assert(0);
231 return FAILURE;
232 }
233
234 p_actor->SetController(this);
235 m_actors.insert(p_actor);
236 return SUCCESS;
237}
238
239// FUNCTION: LEGO1 0x10046050
240// FUNCTION: BETA10 0x100b6f35
242 LegoPathActor* p_actor,
243 LegoAnimPresenter* p_presenter,
244 Vector3& p_position,
245 Vector3& p_direction
246)
247{
248 LegoPathBoundary* boundary = NULL;
249 float time = Timer()->GetTime();
250
251 if (p_actor->GetController() != NULL) {
252 p_actor->GetController()->RemoveActor(p_actor);
253 p_actor->SetController(NULL);
254 }
255
256 for (MxS32 i = 0; i < m_numL; i++) {
257 LegoPathBoundary& b = m_boundaries[i];
258 LegoAnimPresenterSet& presenters = b.GetPresenters();
259 LegoAnimPresenter* presenter = p_presenter;
260
261 if (presenters.find(presenter) != presenters.end()) {
262 MxS32 j;
263
264 for (j = 0; j < b.GetNumEdges(); j++) {
265 Mx4DPointFloat normal(*b.GetEdgeNormal(j));
266
267 if (p_position.Dot(p_position, normal) + normal[3] < 0.0f) {
268 break;
269 }
270 }
271
272 if (b.GetNumEdges() == j) {
273 if (boundary != NULL) {
274 return FAILURE;
275 }
276
277 boundary = &b;
278 }
279 }
280 }
281
282 if (boundary == NULL) {
283 return FAILURE;
284 }
285
286 for (MxS32 j = 0; j < boundary->GetNumEdges(); j++) {
287 LegoUnknown100db7f4* edge = (LegoUnknown100db7f4*) boundary->GetEdges()[j];
288
289 if (edge->GetMask0x03()) {
290 Mx3DPointFloat vec;
291
292 if (((LegoUnknown100db7f4*) edge->GetClockwiseEdge(*boundary))->FUN_1002ddc0(*boundary, vec) == SUCCESS &&
293 vec.Dot(vec, p_direction) < 0.0f) {
294 edge =
296 }
297
298 if (!edge->GetMask0x03()) {
299 return FAILURE;
300 }
301
302 if (p_actor->VTable0x84(boundary, time, p_position, p_direction, *edge, 0.5f) == SUCCESS) {
303 p_actor->SetController(this);
304 m_actors.insert(p_actor);
305 return SUCCESS;
306 }
307 }
308 }
309
310 return FAILURE;
311}
312
313// FUNCTION: LEGO1 0x100466a0
314// FUNCTION: BETA10 0x100b71fe
316{
317 if (p_actor->GetController() != NULL) {
318 p_actor->GetController()->RemoveActor(p_actor);
319 p_actor->SetController(NULL);
320 }
321
322 m_actors.insert(p_actor);
323 p_actor->SetController(this);
324 return SUCCESS;
325}
326
327// FUNCTION: LEGO1 0x10046770
328// FUNCTION: BETA10 0x100b7264
330{
331 MxResult result = FAILURE;
332
333 p_actor->VTable0xc4();
334 m_actors.erase(p_actor);
335
336 for (MxS32 i = 0; i < m_numL; i++) {
337 if (m_boundaries[i].RemoveActor(p_actor) == SUCCESS) {
338 result = SUCCESS;
339 }
340 }
341
342 return result;
343}
344
345// FUNCTION: LEGO1 0x100468f0
346// FUNCTION: BETA10 0x100b72f7
348{
349 for (MxS32 i = 0; i < m_numL; i++) {
350 if (!(m_boundaries[i].m_flags & LegoWEGEdge::c_bit3)) {
351 m_boundaries[i].FUN_10057fe0(p_presenter);
352 }
353 }
354}
355
356// FUNCTION: LEGO1 0x10046930
357// FUNCTION: BETA10 0x100b737b
359{
360 for (MxS32 i = 0; i < m_numL; i++) {
361 m_boundaries[i].FUN_100586e0(p_presenter);
362 }
363}
364
365// FUNCTION: LEGO1 0x10046970
366// FUNCTION: BETA10 0x100b73d8
367void LegoPathController::FUN_10046970()
368{
369 float time = Timer()->GetTime();
370
371 LegoPathActorSet lpas(m_actors);
372
373 for (LegoPathActorSet::iterator itpa = lpas.begin(); itpa != lpas.end(); itpa++) {
374 LegoPathActor* actor = *itpa;
375
376 if (m_actors.find(actor) != m_actors.end()) {
377 if (!((MxU8) actor->GetActorState() & LegoPathActor::c_disabled)) {
378 actor->Animate(time);
379 }
380 }
381 }
382}
383
384// FUNCTION: LEGO1 0x10046b30
386{
387 p_boundaries = m_boundaries;
388 p_numL = m_numL;
389 return SUCCESS;
390}
391
392// FUNCTION: LEGO1 0x10046b50
393// FUNCTION: BETA10 0x100b7531
395{
396 for (MxS32 i = 0; i < m_numL; i++) {
397 if (!strcmpi(m_boundaries[i].GetName(), p_name)) {
398 return &m_boundaries[i];
399 }
400 }
401
402 return NULL;
403}
404
405// FUNCTION: LEGO1 0x10046bb0
406// FUNCTION: BETA10 0x100b75bc
408{
409 for (MxS32 i = 0; i < m_numT; i++) {
410 m_structs[i].SetWorld(p_world);
411 }
412}
413
414// FUNCTION: LEGO1 0x10046be0
415// FUNCTION: BETA10 0x100b7614
417{
418 if (p_enable) {
419 TickleManager()->RegisterClient(this, 10);
420 }
421 else {
423 }
424}
425
426// FUNCTION: LEGO1 0x10046c10
427// FUNCTION: BETA10 0x100b767a
429{
430 if (g_ctrlBoundariesA != NULL || g_ctrlEdgesA != NULL || g_ctrlBoundariesB != NULL || g_ctrlEdgesB != NULL) {
431 return FAILURE;
432 }
433
434 g_ctrlBoundariesA = new CtrlBoundary[sizeOfArray(g_unk0x100f42f0)];
435 g_ctrlEdgesA = new CtrlEdge[sizeOfArray(g_unk0x100f42f0)];
436 g_ctrlBoundariesB = new CtrlBoundary[sizeOfArray(g_unk0x100f4330)];
437 g_ctrlEdgesB = new CtrlEdge[sizeOfArray(g_unk0x100f4330)];
438 return SUCCESS;
439}
440
441// FUNCTION: LEGO1 0x10046de0
442// FUNCTION: BETA10 0x100b779e
444{
445 if (g_ctrlBoundariesA == NULL || g_ctrlEdgesA == NULL) {
446 return FAILURE;
447 }
448
449 delete[] g_ctrlBoundariesA;
450 delete[] g_ctrlEdgesA;
451 delete[] g_ctrlBoundariesB;
452 delete[] g_ctrlEdgesB;
453 g_ctrlBoundariesA = NULL;
454 g_ctrlEdgesA = NULL;
455 g_ctrlBoundariesB = NULL;
456 g_ctrlEdgesB = NULL;
457 return SUCCESS;
458}
459
460// FUNCTION: LEGO1 0x10046e50
461// FUNCTION: BETA10 0x100b781f
462MxResult LegoPathController::Read(LegoStorage* p_storage)
463{
464 if (p_storage->Read(&m_numT, sizeof(m_numT)) != SUCCESS) {
465 return FAILURE;
466 }
467 if (m_numT > 0) {
468 m_structs = new LegoPathStruct[m_numT];
469 }
470
471 if (p_storage->Read(&m_numN, sizeof(m_numN)) != SUCCESS) {
472 return FAILURE;
473 }
474 if (m_numN > 0) {
475 m_unk0x10 = new Mx3DPointFloat[m_numN];
476 }
477
478 if (p_storage->Read(&m_numE, sizeof(m_numE)) != SUCCESS) {
479 return FAILURE;
480 }
481 if (m_numE > 0) {
482 m_edges = new LegoPathCtrlEdge[m_numE];
483 }
484
485 if (p_storage->Read(&m_numL, sizeof(m_numL)) != SUCCESS) {
486 return FAILURE;
487 }
488 if (m_numL > 0) {
489 m_boundaries = new LegoPathBoundary[m_numL];
490 }
491
492 if (m_numT > 0 && ReadStructs(p_storage) != SUCCESS) {
493 return FAILURE;
494 }
495
496 if (m_numN > 0) {
497 for (MxS32 i = 0; i < m_numN; i++) {
498 if (ReadVector(p_storage, m_unk0x10[i]) != SUCCESS) {
499 return FAILURE;
500 }
501 }
502 }
503
504 if (m_numE > 0 && ReadEdges(p_storage) != SUCCESS) {
505 return FAILURE;
506 }
507
508 if (m_numL > 0 && ReadBoundaries(p_storage) != SUCCESS) {
509 return FAILURE;
510 }
511
512 for (MxS32 j = 0; j < m_numE; j++) {
513 m_pfsE.insert(&m_edges[j]);
514 }
515
516 return SUCCESS;
517}
518
519// FUNCTION: LEGO1 0x10047b30
520// FUNCTION: BETA10 0x100b7cd6
521MxResult LegoPathController::ReadStructs(LegoStorage* p_storage)
522{
523 for (MxS32 i = 0; i < m_numT; i++) {
524 MxU8 length = 0;
525
526 if (p_storage->Read(&length, sizeof(length)) != SUCCESS) {
527 return FAILURE;
528 }
529
530 if (length > 0) {
531 m_structs[i].m_name = new char[length + 1];
532
533 if (p_storage->Read(m_structs[i].m_name, length) != SUCCESS) {
534 return FAILURE;
535 }
536
537 m_structs[i].m_name[length] = '\0';
538 }
539
540 if (p_storage->Read(&m_structs[i].m_flags, sizeof(m_structs[i].m_flags)) != SUCCESS) {
541 return FAILURE;
542 }
543 }
544
545 return SUCCESS;
546}
547
548// FUNCTION: LEGO1 0x10047c10
549// FUNCTION: BETA10 0x100b7df3
550MxResult LegoPathController::ReadEdges(LegoStorage* p_storage)
551{
552 for (MxS32 i = 0; i < m_numE; i++) {
553 LegoPathCtrlEdge& edge = m_edges[i];
554 MxU16 s;
555
556 if (p_storage->Read(&edge.m_flags, sizeof(edge.m_flags)) != SUCCESS) {
557 return FAILURE;
558 }
559
560 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
561 return FAILURE;
562 }
563 edge.m_pointA = &m_unk0x10[s];
564
565 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
566 return FAILURE;
567 }
568 edge.m_pointB = &m_unk0x10[s];
569
571 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
572 return FAILURE;
573 }
574 edge.m_faceA = &m_boundaries[s];
575
576 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
577 return FAILURE;
578 }
579 edge.m_ccwA = &m_edges[s];
580
581 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
582 return FAILURE;
583 }
584 edge.m_cwA = &m_edges[s];
585 }
586
588 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
589 return FAILURE;
590 }
591 edge.m_faceB = &m_boundaries[s];
592
593 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
594 return FAILURE;
595 }
596 edge.m_ccwB = &m_edges[s];
597
598 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
599 return FAILURE;
600 }
601 edge.m_cwB = &m_edges[s];
602 }
603
604 if (ReadVector(p_storage, edge.m_unk0x28) != SUCCESS) {
605 return FAILURE;
606 }
607
608 if (p_storage->Read(&edge.m_unk0x3c, sizeof(edge.m_unk0x3c)) != SUCCESS) {
609 return FAILURE;
610 }
611 }
612
613 return SUCCESS;
614}
615
616// FUNCTION: LEGO1 0x10047e90
617// FUNCTION: BETA10 0x100b8293
618MxResult LegoPathController::ReadBoundaries(LegoStorage* p_storage)
619{
620 for (MxS32 i = 0; i < m_numL; i++) {
621 LegoPathBoundary& boundary = m_boundaries[i];
622 MxU8 numE;
623 MxU16 s;
624 MxU8 j;
625
626 if (p_storage->Read(&numE, sizeof(numE)) != SUCCESS) {
627 return FAILURE;
628 }
629
630 boundary.m_edgeNormals = new Mx4DPointFloat[numE];
631
632 LegoUnknown100db7f4** edges = new LegoUnknown100db7f4*[numE];
633 boundary.SetEdges(edges, numE);
634
635 for (j = 0; j < numE; j++) {
636 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
637 return FAILURE;
638 }
639
640 edges[j] = &m_edges[s];
641 }
642
643 if (p_storage->Read(&boundary.m_flags, sizeof(boundary.m_flags)) != SUCCESS) {
644 return FAILURE;
645 }
646
647 if (p_storage->Read(&boundary.m_unk0x0d, sizeof(boundary.m_unk0x0d)) != SUCCESS) {
648 return FAILURE;
649 }
650
651 MxU8 length;
652 if (p_storage->Read(&length, sizeof(length)) != SUCCESS) {
653 return FAILURE;
654 }
655
656 if (length > 0) {
657 boundary.m_name = new char[length + 1];
658
659 if (p_storage->Read(boundary.m_name, length) != SUCCESS) {
660 return FAILURE;
661 }
662
663 boundary.m_name[length] = '\0';
664 }
665
666 if (ReadVector(p_storage, boundary.m_unk0x14) != SUCCESS) {
667 return FAILURE;
668 }
669
670 for (j = 0; j < numE; j++) {
671 if (ReadVector(p_storage, boundary.m_edgeNormals[j]) != SUCCESS) {
672 return FAILURE;
673 }
674 }
675
676 if (ReadVector(p_storage, boundary.m_unk0x30) != SUCCESS) {
677 return FAILURE;
678 }
679
680 if (p_storage->Read(&boundary.m_unk0x44, sizeof(boundary.m_unk0x44)) != SUCCESS) {
681 return FAILURE;
682 }
683
684 if (p_storage->Read(&boundary.m_numTriggers, sizeof(boundary.m_numTriggers)) != SUCCESS) {
685 return FAILURE;
686 }
687
688 if (boundary.m_numTriggers > 0) {
689 boundary.m_unk0x50 = new Mx3DPointFloat;
690 boundary.m_pathTrigger = new PathWithTrigger[boundary.m_numTriggers];
691
692 for (j = 0; j < boundary.m_numTriggers; j++) {
693 if (p_storage->Read(&s, sizeof(s)) != SUCCESS) {
694 return FAILURE;
695 }
696
697 boundary.m_pathTrigger[j].m_pathStruct = &m_structs[s];
698
699 if (p_storage->Read(&boundary.m_pathTrigger[j].m_data, sizeof(boundary.m_pathTrigger[j].m_data)) !=
700 SUCCESS) {
701 return FAILURE;
702 }
703
704 if (p_storage->Read(
705 &boundary.m_pathTrigger[j].m_unk0x08,
706 sizeof(boundary.m_pathTrigger[j].m_unk0x08)
707 ) != SUCCESS) {
708 return FAILURE;
709 }
710 }
711
712 if (ReadVector(p_storage, *boundary.m_unk0x50) != SUCCESS) {
713 return FAILURE;
714 }
715 }
716 }
717
718 return SUCCESS;
719}
720
721// FUNCTION: LEGO1 0x100482b0
722// FUNCTION: BETA10 0x100b8864
723MxResult LegoPathController::ReadVector(LegoStorage* p_storage, Mx3DPointFloat& p_vec)
724{
725 if (p_storage->Read(p_vec.GetData(), sizeof(float) * 3) != SUCCESS) {
726 return FAILURE;
727 }
728
729 return SUCCESS;
730}
731
732// FUNCTION: LEGO1 0x100482e0
733// FUNCTION: BETA10 0x100b88a1
734MxResult LegoPathController::ReadVector(LegoStorage* p_storage, Mx4DPointFloat& p_vec)
735{
736 if (p_storage->Read(p_vec.GetData(), sizeof(float) * 4) != SUCCESS) {
737 return FAILURE;
738 }
739
740 return SUCCESS;
741}
742
743// FUNCTION: LEGO1 0x10048310
744// FUNCTION: BETA10 0x100b8911
746 LegoPathEdgeContainer* p_grec,
747 const Vector3& p_oldPosition,
748 const Vector3& p_oldDirection,
749 LegoPathBoundary* p_oldBoundary,
750 const Vector3& p_newPosition,
751 const Vector3& p_newDirection,
752 LegoPathBoundary* p_newBoundary,
753 LegoU8 p_mask,
754 MxFloat* p_param9
755)
756{
757 p_grec->m_position = p_newPosition;
758 p_grec->m_direction = p_newDirection;
759 p_grec->m_boundary = p_newBoundary;
760
761 if (p_newBoundary == p_oldBoundary) {
762 p_grec->SetBit1(TRUE);
763 return SUCCESS;
764 }
765
766 list<LegoBEWithFloat> boundaryList;
767 list<LegoBEWithFloat>::iterator boundaryListIt;
768
769 LegoBEWithFloatSet boundarySet;
770 LegoBEWithFloatSet::iterator boundarySetItA;
771 LegoBEWithFloatSet::iterator boundarySetItB;
772
773 LegoPathCtrlEdgeSet pathCtrlEdgeSet(m_pfsE);
774
775 MxFloat local14 = 999999.0f;
776
777 p_grec->SetBit1(FALSE);
778
779 for (MxS32 i = 0; i < p_oldBoundary->GetNumEdges(); i++) {
780 LegoPathCtrlEdge* edge = (LegoPathCtrlEdge*) p_oldBoundary->GetEdges()[i];
781
782 if (edge->GetMask0x03()) {
783 LegoPathBoundary* otherFace = (LegoPathBoundary*) edge->OtherFace(p_oldBoundary);
784
785 if (otherFace != NULL && edge->BETA_1004a830(*otherFace, p_mask)) {
786 if (p_newBoundary == otherFace) {
787 float dist;
788 if ((dist = edge->DistanceToMidpoint(p_oldPosition) + edge->DistanceToMidpoint(p_newPosition)) <
789 local14) {
790 local14 = dist;
791 p_grec->erase(p_grec->begin(), p_grec->end());
792 p_grec->SetBit1(TRUE);
793 p_grec->push_back(LegoBoundaryEdge(edge, p_oldBoundary));
794 }
795 }
796 else {
797 boundaryList.push_back(LegoBEWithFloat(edge, p_oldBoundary, edge->DistanceToMidpoint(p_oldPosition))
798 );
799 boundarySet.insert(&boundaryList.back());
800 }
801 }
802 }
803
804 pathCtrlEdgeSet.erase(edge);
805 }
806
807 if (!p_grec->GetBit1()) {
808 while (pathCtrlEdgeSet.size() > 0) {
809 LegoBEWithFloat edgeWithFloat;
810 MxFloat local70 = 999999.0f;
811
812 boundarySetItA = boundarySetItB = boundarySet.begin();
813
814 if (boundarySetItB != boundarySet.end()) {
815 boundarySetItB++;
816 }
817
818 while (boundarySetItA != boundarySet.end()) {
819 MxU32 shouldRemove = TRUE;
820
821 LegoUnknown100db7f4* e = (*boundarySetItA)->m_edge;
822 LegoPathBoundary* b = (*boundarySetItA)->m_boundary;
823 assert(e && b);
824
826 assert(bOther);
827
828 if (!e->BETA_1004a830(*bOther, p_mask)) {
829 // This branch is empty, but present in the BETA - probably had comments only
830 }
831 else {
832 if (bOther == p_newBoundary) {
833 shouldRemove = FALSE;
834
835 LegoBEWithFloat* pfs = *boundarySetItA;
836 assert(pfs);
837
838 float dist;
839 if ((dist = pfs->m_edge->DistanceToMidpoint(p_newPosition) + pfs->m_unk0x0c) < local70) {
840 edgeWithFloat.m_edge = NULL;
841 local70 = dist;
842
843 // TODO: Match
844 if (dist < local14) {
845 local14 = dist;
846 p_grec->erase(p_grec->begin(), p_grec->end());
847 p_grec->SetBit1(TRUE);
848
849 do {
850 p_grec->push_front(LegoBoundaryEdge(pfs->m_edge, pfs->m_boundary));
851 pfs = pfs->m_next;
852 } while (pfs != NULL);
853 }
854 }
855 }
856 else {
857 for (MxS32 i = 0; i < bOther->GetNumEdges(); i++) {
858 LegoPathCtrlEdge* edge = (LegoPathCtrlEdge*) bOther->GetEdges()[i];
859
860 if (edge->GetMask0x03()) {
861 if (pathCtrlEdgeSet.find(edge) != pathCtrlEdgeSet.end()) {
862 shouldRemove = FALSE;
863
864 float dist;
865 if ((dist = edge->DistanceBetweenMidpoints(*e) + (*boundarySetItA)->m_unk0x0c) <
866 local70) {
867 local70 = dist;
868 edgeWithFloat = LegoBEWithFloat(edge, bOther, *boundarySetItA, dist);
869 }
870 }
871 }
872 }
873 }
874 }
875
876 if (shouldRemove) {
877 boundarySet.erase(boundarySetItA);
878 }
879
880 if (boundarySetItB != boundarySet.end()) {
881 boundarySetItA = boundarySetItB;
882 boundarySetItB++;
883 }
884 else {
885 break;
886 }
887 }
888
889 if (edgeWithFloat.m_edge != NULL) {
890 pathCtrlEdgeSet.erase(edgeWithFloat.m_edge);
891 boundaryList.push_back(edgeWithFloat);
892 boundarySet.insert(&boundaryList.back());
893 }
894 else {
895 break;
896 }
897 }
898 }
899
900 if (p_grec->GetBit1()) {
901 if (p_grec->size() > 0) {
902 LegoPathCtrlEdge* edge = p_grec->front().m_edge;
903
904 if (edge->FUN_10048c40(p_oldPosition)) {
905 p_grec->pop_front();
906 }
907 }
908
909 if (p_grec->size() > 0) {
910 LegoPathCtrlEdge* edge = p_grec->back().m_edge;
911
912 if (edge->FUN_10048c40(p_newPosition)) {
913 if (edge->OtherFace(p_grec->back().m_boundary) != NULL &&
914 edge->OtherFace(p_grec->back().m_boundary)->IsEqual(p_newBoundary)) {
915 p_grec->m_boundary = p_grec->back().m_boundary;
916 p_grec->pop_back();
917 }
918 }
919 }
920
921 if (p_param9 != NULL) {
922 *p_param9 = local14;
923 }
924
925 return SUCCESS;
926 }
927
928 return FAILURE;
929}
930
931// FUNCTION: LEGO1 0x1004a240
932// FUNCTION: BETA10 0x100b9160
934 LegoPathEdgeContainer& p_grec,
935 Vector3& p_v1,
936 Vector3& p_v2,
937 float p_f1,
938 LegoUnknown100db7f4*& p_edge,
939 LegoPathBoundary*& p_boundary
940)
941{
942 if (p_grec.size() == 0) {
943 p_v1 = p_grec.m_position;
944 p_v2 = p_grec.m_direction;
945 p_boundary = p_grec.m_boundary;
946 p_grec.SetBit1(FALSE);
947 return 1;
948 }
949
950 p_edge = p_grec.front().m_edge;
951 p_boundary = p_grec.front().m_boundary;
952 p_grec.pop_front();
953
954 Mx3DPointFloat vec;
955 p_v1 = *p_edge->CCWVertex(*p_boundary);
956 p_v1 -= *p_edge->CWVertex(*p_boundary);
957 p_v1 *= p_f1;
958 p_v1 += *p_edge->CWVertex(*p_boundary);
959 p_edge->FUN_1002ddc0(*p_boundary, vec);
960 p_v2.EqualsCross(*p_boundary->GetUnknown0x14(), vec);
961 return 0;
962}
963
964// FUNCTION: LEGO1 0x1004a380
965// FUNCTION: BETA10 0x100b957f
967 Vector3& p_param1,
968 Vector3& p_param2,
969 Mx3DPointFloat* p_param3,
970 LegoPathBoundary*& p_boundary,
971 MxFloat& p_param5
972)
973{
974 MxFloat param5 = p_param5;
975 Mx3DPointFloat local24;
976 MxU32 local8 = TRUE;
977
978 for (MxS32 i = 0; i < m_numL; i++) {
979 if (m_boundaries[i].m_flags & LegoPathBoundary::c_bit3) {
980 continue;
981 }
982
983 LegoPathBoundary* b = &m_boundaries[i];
984 Mx4DPointFloat* unk0x14 = b->GetUnknown0x14();
985 float local28 = p_param3[0].Dot(p_param3[0], *unk0x14);
986
987 if (local28 < 0.001 && local28 > -0.001) {
988 continue;
989 }
990
991 float local2c = p_param3[1].Dot(p_param3[1], *unk0x14);
992 float local34 = p_param3[2].Dot(p_param3[2], *unk0x14) + unk0x14->index_operator(3);
993 float local3c = local2c * local2c - local34 * local28 * 4.0f;
994
995 if (local3c < -0.001) {
996 continue;
997 }
998
999 if (local3c < 0.0f) {
1000 local3c = 0.0f;
1001 }
1002 else {
1003 local3c = sqrt(local3c);
1004 }
1005
1006 float local38 = (local3c - local2c) / (local28 * 2.0f);
1007 float local44 = (-local3c - local2c) / (local28 * 2.0f);
1008
1009 if (!IsBetween(local38, 0.0f, param5)) {
1010 if (IsBetween(local44, 0.0f, param5)) {
1011 local38 = local44;
1012 }
1013 else {
1014 continue;
1015 }
1016 }
1017
1018 if (local8 || FUN_100c17a0(local38, p_param5, 0.0f, param5)) {
1019 Mx3DPointFloat local58(p_param3[0]);
1020
1021 local58 *= local38 * local38;
1022 local24 = p_param3[1];
1023 local24 *= local38;
1024 local24 += p_param3[2];
1025 local24 += local58;
1026
1027 assert(b->GetNumEdges() > 1);
1028
1029 MxS32 j;
1030 for (j = b->GetNumEdges() - 1; j >= 0; j--) {
1031 Mx4DPointFloat* local60 = b->GetEdgeNormal(j);
1032
1033 if (local24.Dot(*local60, local24) + local60->index_operator(3) < -0.001) {
1034 break;
1035 }
1036 }
1037
1038 if (j < 0) {
1039 Mx3DPointFloat local74(p_param1);
1040 local74 -= local24;
1041
1042 if (local74.Dot(local74, *unk0x14) >= 0.0f) {
1043 p_param5 = local38;
1044 p_boundary = b;
1045 local8 = FALSE;
1046 }
1047 }
1048 }
1049 }
1050
1051 if (local8) {
1052 p_param5 = param5;
1053 return FAILURE;
1054 }
1055
1056 return SUCCESS;
1057}
[AI] Handles playback and synchronization of animated LEGO objects, including variable substitution,...
Implementation of LegoStorage for memory-backed buffers.
Definition: legostorage.h:317
[AI] An actor that moves along a predefined path, supporting boundary transitions,...
Definition: legopathactor.h:32
virtual MxResult VTable0x88(LegoPathBoundary *p_boundary, float p_time, LegoEdge &p_srcEdge, float p_srcScale, LegoUnknown100db7f4 &p_destEdge, float p_destScale)
[AI] Moves the actor between two edges across a boundary, recalculates placement and orientation.
virtual void Animate(float p_time)
[AI] Per-frame animation update.
MxU32 GetActorState()
[AI] Gets the current navigation/animation state of the actor.
virtual void VTable0xc4()
[AI] Empty handler for optional custom per-tick transition logic.
void SetController(LegoPathController *p_pathController)
[AI] Assigns a new path controller (used for actor transitions between paths).
@ c_disabled
[AI] Marks as disabled or inactive for path follow logic. [AI]
Definition: legopathactor.h:41
virtual MxResult VTable0x84(LegoPathBoundary *p_boundary, float p_time, Vector3 &p_p1, Vector3 &p_p4, LegoUnknown100db7f4 &p_destEdge, float p_destScale)
[AI] Moves actor to a destination edge.
LegoPathController * GetController()
[AI] Retrieves pointer to the path controller which governs this actor's movement.
[AI] Represents a path segment or boundary in the navigation network for actors (vehicles,...
LegoAnimPresenterSet & GetPresenters()
[AI] Direct access to the animation presenter set for this boundary.
MxU32 FUN_10057fe0(LegoAnimPresenter *p_presenter)
[AI] Adds an animation presenter to the set if within region, based on spatial bounds.
MxU32 FUN_100586e0(LegoAnimPresenter *p_presenter)
[AI] Removes an animation presenter from the set, or if nullptr resets all presenters' world associat...
[AI] Manager for controlling actors' movement along predefined geometric paths.
void FUN_100468f0(LegoAnimPresenter *p_presenter)
[AI] Processes all boundaries except those with bit3 set, invoking FUN_10057fe0 for the provided anim...
MxResult FUN_10046b30(LegoPathBoundary *&p_boundaries, MxS32 &p_numL)
[AI] Provides current array of boundaries and count as output parameters, for external queries.
MxResult Tickle() override
[AI] Implements the tickle (per-frame update) callback for the controller.
LegoPathBoundary * GetPathBoundary(const char *p_name)
[AI] Searches for a path boundary by name among owned boundaries.
static MxResult Init()
[AI] Static initializer for global controller boundary/edge arrays.
virtual void Destroy()
[AI] Deinitializes path controller, releases all owned resources and unregisters from tickle manager.
MxResult RemoveActor(LegoPathActor *p_actor)
[AI] Removes an actor from the controller, detaches it from controlled boundaries,...
MxResult PlaceActor(LegoPathActor *p_actor, const char *p_name, MxS32 p_src, float p_srcScale, MxS32 p_dest, float p_destScale)
[AI] Places an actor on a boundary at given source/destination edge indices, commonly for track segme...
MxResult FUN_10048310(LegoPathEdgeContainer *p_grec, const Vector3 &p_oldPosition, const Vector3 &p_oldDirection, LegoPathBoundary *p_oldBoundary, const Vector3 &p_newPosition, const Vector3 &p_newDirection, LegoPathBoundary *p_newBoundary, LegoU8 p_mask, MxFloat *p_param9)
[AI] Complex function performing path transition resolution; computes possible edge transition sequen...
virtual MxResult Create(MxU8 *p_data, const Vector3 &p_location, const MxAtomId &p_trigger)
[AI] Initializes the path controller from the provided binary data at the specified location,...
static MxResult Reset()
[AI] Resets (cleans up) global controller boundary/edge arrays allocated by Init().
MxResult FUN_1004a380(Vector3 &p_param1, Vector3 &p_param2, Mx3DPointFloat *p_param3, LegoPathBoundary *&p_boundary, MxFloat &p_param5)
[AI] Finds earliest intersection and placement on a valid boundary for the provided vectors and updat...
MxS32 FUN_1004a240(LegoPathEdgeContainer &p_grec, Vector3 &p_v1, Vector3 &p_v2, float p_f1, LegoUnknown100db7f4 *&p_edge, LegoPathBoundary *&p_boundary)
[AI] Computes path vector and orientation for an actor given a transition along the resolved edge con...
LegoPathController()
[AI] Constructs a LegoPathController, initializing boundary and edge pointers to NULL and counts to z...
void Enable(MxBool p_enable)
[AI] Enables or disables the controller's registration with the tickle manager, controlling per-frame...
void FUN_10046bb0(LegoWorld *p_world)
[AI] Assigns the provided world pointer to all struct triggers owned by this path controller.
void FUN_10046930(LegoAnimPresenter *p_presenter)
[AI] Invokes FUN_100586e0 for each boundary, with the provided animation presenter.
[AI] Represents a trigger/control element in the LEGO world's path system, linked logically to the wo...
void SetWorld(LegoWorld *p_world)
[AI] Binds a world instance to this path struct for context-specific handling.
void SetAtomId(const MxAtomId &p_atomId)
[AI] Sets this struct's AtomId for data/action lookup and dispatch.
Abstract base class providing an interface for file-like storage with binary and text read/write oper...
Definition: legostorage.h:16
virtual LegoResult Read(void *p_buffer, LegoU32 p_size)=0
Read bytes from storage into buffer.
void SetEdges(LegoUnknown100db7f4 **p_edges, LegoU8 p_numEdges)
[AI] Assigns the edge list and count for this face.
Definition: legoweedge.h:64
LegoU8 GetNumEdges()
[AI] Returns the number of edge elements assigned to this face.
Definition: legoweedge.h:43
LegoU32 IsEqual(LegoWEEdge *p_other)
[AI] Checks if this face object is the same as another.
Definition: legoweedge.h:56
LegoUnknown100db7f4 ** GetEdges()
[AI] Gets the array of pointers to the edge objects that form this face.
Definition: legoweedge.h:49
const LegoChar * GetName()
[AI] Returns the name string of this edge, typically used for debugging and lookup.
Definition: legowegedge.h:79
Mx4DPointFloat m_unk0x14
[AI] 4D plane equation or normal used for polygon/edge side tests. [AI]
Definition: legowegedge.h:112
float m_unk0x44
[AI] Maximum squared distance from center—polygon bounding radius or similar. [AI]
Definition: legowegedge.h:115
LegoU8 m_unk0x0d
[AI] Unknown, used for internal status/tracking. [AI]
Definition: legowegedge.h:110
LegoU8 m_numTriggers
[AI] Number of trigger (path/segment) structures attached to this edge. [AI]
Definition: legowegedge.h:116
Mx3DPointFloat * m_unk0x50
[AI] Transition direction/unit vector—used for edge trigger geometry. [AI]
Definition: legowegedge.h:118
Mx4DPointFloat * m_edgeNormals
[AI] Per-edge normals for each polygon segment, allocated dynamically. [AI]
Definition: legowegedge.h:113
LegoU8 m_flags
[AI] Flags indicating edge state, enabled/disabled, and type bits. [AI]
Definition: legowegedge.h:109
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
@ c_bit3
[AI]
Definition: legowegedge.h:37
LegoChar * m_name
[AI] Edge's name string, dynamically allocated for debug/lookup. [AI]
Definition: legowegedge.h:111
PathWithTrigger * m_pathTrigger
[AI] Array of triggers influencing entity motion or event logic on this edge. [AI]
Definition: legowegedge.h:117
Mx3DPointFloat m_unk0x30
[AI] Cached center for the edge polygon, used in geometric calculations. [AI]
Definition: legowegedge.h:114
Represents the active 3D world, holding all entity, animation, sound, path, and ROI objects.
Definition: legoworld.h:49
[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] Atomized (unique) string identifier, managed by reference counting.
Definition: mxatom.h:124
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
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.
virtual float * GetData()
[AI] Retrieves the mutable in-memory data pointer for this vector.
[AI] 3D vector class, providing vector and cross-product operations in 3D space.
Definition: vector.h:249
virtual void EqualsCross(const Vector3 &p_a, const Vector3 &p_b)
[AI] Sets this vector to be the cross product of p_a and p_b.
#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
set< LegoAnimPresenter *, LegoAnimPresenterSetCompare > LegoAnimPresenterSet
[AI] Defines a set of LegoAnimPresenter pointers, ordered by pointer value using LegoAnimPresenterSet...
set< LegoPathActor *, LegoPathActorSetCompare > LegoPathActorSet
[AI] Defines a set of LegoPathActor pointers, ordered by pointer value using LegoPathActorSetCompare.
MxU32 g_unk0x100d7cc8[]
MxU32 g_unk0x100d7d08[]
set< LegoPathCtrlEdge *, LegoPathCtrlEdgeCompare > LegoPathCtrlEdgeSet
[AI] Set of pointers to control edges, ordered using LegoPathCtrlEdgeCompare.
multiset< LegoBEWithFloat *, LegoBEWithFloatComparator > LegoBEWithFloatSet
[AI] Multiset of LegoBEWithFloat pointers, ordered by their annotation float value....
#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
unsigned char LegoU8
[AI] Unsigned 8-bit integer type used throughout LEGO Island.
Definition: legotypes.h:47
#define SUCCESS
[AI] Used to indicate a successful operation in result codes.
Definition: legotypes.h:30
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
float MxFloat
[AI]
Definition: mxtypes.h:68
unsigned char MxU8
[AI]
Definition: mxtypes.h:8
signed int MxS32
[AI]
Definition: mxtypes.h:38
unsigned short MxU16
[AI]
Definition: mxtypes.h:20
unsigned int MxU32
[AI]
Definition: mxtypes.h:32
[AI] Represents a path edge with extra float data and potential linkage (single-linked).
LegoPathBoundary * m_boundary
[AI] Path boundary this edge belongs to. [AI]
MxFloat m_unk0x0c
[AI] Annotation float; likely an edge priority, weight, parametric value, etc. [AI]
LegoPathCtrlEdge * m_edge
[AI] Pointer to the relevant path control edge. [AI]
LegoBEWithFloat * m_next
[AI] Next node in the edge chain, for linked structures (may be null). [AI]
[AI] Represents an edge within a path boundary, used for path following and geometric computations.
[AI] Represents an edge in the LEGO world geometry graph.
Definition: legoedge.h:16
LegoEdge * m_ccwB
[AI] Next edge (counterclockwise) around face B.
Definition: legoedge.h:118
LegoWEEdge * m_faceA
[AI] Pointer to the first face sharing this edge.
Definition: legoedge.h:97
LegoEdge * m_cwB
[AI] Next edge (clockwise) around face B.
Definition: legoedge.h:123
Vector3 * CWVertex(LegoWEEdge &p_face)
[AI] Returns the "clockwise" endpoint of this edge with respect to a given face.
Definition: legoedge.cpp:56
LegoWEEdge * m_faceB
[AI] Pointer to the second face sharing this edge.
Definition: legoedge.h:103
LegoEdge * GetCounterclockwiseEdge(LegoWEEdge &p_face)
[AI] Returns the counterclockwise adjacent edge relative to the given face.
Definition: legoedge.cpp:41
Vector3 * m_pointB
[AI] The second endpoint of the edge.
Definition: legoedge.h:133
LegoEdge * GetClockwiseEdge(LegoWEEdge &p_face)
[AI] Returns the clockwise adjacent edge relative to the given face.
Definition: legoedge.cpp:27
LegoEdge * m_ccwA
[AI] Next edge (counterclockwise) around face A.
Definition: legoedge.h:108
LegoEdge * m_cwA
[AI] Next edge (clockwise) around face A.
Definition: legoedge.h:113
Vector3 * m_pointA
[AI] The first endpoint of the edge.
Definition: legoedge.h:128
Vector3 * CCWVertex(LegoWEEdge &p_face)
[AI] Returns the "counterclockwise" endpoint of this edge with respect to a given face.
Definition: legoedge.cpp:69
[AI] Helper structure for rapid lookups of controller-boundary pairs, often used for global or indexe...
LegoPathBoundary * m_boundary
[AI] Associated path boundary within the controller. [AI]
LegoPathController * m_controller
[AI] Pointer to owning path controller. [AI]
[AI] Helper structure pairing controllers with edge references for global or fast access.
LegoUnknown100db7f4 * m_edge
[AI] Reference to a specific edge, typically a segment connector or trigger. [AI]
LegoPathController * m_controller
[AI] Pointer to owning path controller. [AI]
[AI] Controller-specific edge used in path navigation.
[AI] Container for path boundary edges, also stores position, direction, and flags.
Mx3DPointFloat m_direction
[AI] 3D direction vector reference, e.g., average or intended facing. [AI]
LegoPathBoundary * m_boundary
[AI] Associated boundary for all contained edges; may be null if container is generic....
Mx3DPointFloat m_position
[AI] 3D position reference for the edge group, e.g., start or mean location. [AI]
void SetBit1(MxU32 p_set)
[AI] Set or clear the c_bit1 flag in m_flags.
MxU32 GetBit1()
[AI] Query if the c_bit1 flag is set.
char * m_name
[AI] Dynamically allocated name for this path struct instance (e.g., a label or trigger identifier).
[AI] Represents an advanced edge in the LEGO Island geometry system, with direction,...
LegoU32 GetMask0x03()
[AI] Returns a mask of flags relevant to the two faces (bits 0 and 1: c_bit1, c_bit2).
@ c_bit4
[AI] Bit flag 4 (purpose unknown)
@ c_bit3
[AI] Bit flag 3 (purpose unknown)
float m_unk0x3c
[AI] Unknown float; likely represents additional metric (possibly precomputed distance/weight).
LegoU32 FUN_10048c40(const Vector3 &p_position)
[AI] Tests if a position is on this edge based on its direction and points, within a precision thresh...
LegoFloat DistanceBetweenMidpoints(const LegoUnknown100db7f4 &p_other)
[AI] Returns the Euclidean distance between the midpoints of this edge and another edge.
Mx3DPointFloat m_unk0x28
[AI] Represents the edge's direction/normal vector or outward face normal.
LegoFloat DistanceToMidpoint(const Vector3 &p_vec)
[AI] Calculates linear distance from a vector position to the 3D midpoint of the edge.
LegoU32 BETA_1004a830(LegoWEGEdge &p_face, LegoU8 p_mask)
[AI] Tests whether a WEG-edge meets complex mask and flag criteria for this edge, depending on mask a...
LegoU16 m_flags
[AI] Internal flags controlling per-face properties and connection status.
LegoWEEdge * OtherFace(LegoWEEdge *p_other)
[AI] Returns the opposite face pointer to the one passed in.
LegoResult FUN_1002ddc0(LegoWEEdge &p_f, Vector3 &p_point) const
[AI] Calculates the edge normal for use from the given face, negating it if called from faceA.
[AI] Represents a path segment with an associated trigger in LEGO Island pathing logic.
Definition: legowegedge.h:8
LegoPathStruct * m_pathStruct
[AI] Pointer to a path structure associated with this trigger. [AI]
Definition: legowegedge.h:18
float m_unk0x08
[AI] Distance along the path or trigger threshold (exact semantics unclear). [AI]
Definition: legowegedge.h:20
unsigned int m_data
[AI] Miscellaneous data value, use determined by path logic. [AI]
Definition: legowegedge.h:19