Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
npc.c
Go to the documentation of this file.
1#include "common.h"
2#include "npc.h"
3#include "entity.h"
4#include "effects.h"
5#include "sprite.h"
6#include "world/partners.h"
7#include "sprite/npc/WorldWatt.h"
8
10static NpcList gWorldNpcList;
11static NpcList gBattleNpcList;
12static NpcList* gCurrentNpcListPtr;
13static s8 gNpcPlayerCollisionsEnabled;
14
15#define PAL_ANIM_END 0xFF
16
23
24// palette types for watt palette animations
25enum {
29};
30
47
49}
50
52 guMtxIdentF(mtx);
53 mtx[0][0] = 1.0f;
54 mtx[1][1] = -1.0f;
55 mtx[2][2] = 1.0f;
56 mtx[3][3] = 1.0f;
57}
58
59void clear_npcs(void) {
60 s32 i;
61
63 gCurrentNpcListPtr = &gWorldNpcList;
64 } else {
65 gCurrentNpcListPtr = &gBattleNpcList;
66 }
67
68 for (i = 0; i < MAX_NPCS; i++) {
69 (*gCurrentNpcListPtr)[i] = nullptr;
70 }
71
72 gNpcCount = 0;
73 gNpcPlayerCollisionsEnabled = true;
74}
75
76void init_npc_list(void) {
78 gCurrentNpcListPtr = &gWorldNpcList;
79 } else {
80 gCurrentNpcListPtr = &gBattleNpcList;
81 }
82
83 gNpcCount = 0;
84 gNpcPlayerCollisionsEnabled = true;
85}
86
88 Npc* npc;
89 s32 i;
90 s32 j;
91
92 for (i = 0; i < MAX_NPCS; i++) {
93 if ((*gCurrentNpcListPtr)[i] == nullptr) {
94 break;
95 }
96 }
97 ASSERT(i < MAX_NPCS);
98
99 (*gCurrentNpcListPtr)[i] = npc = heap_malloc(sizeof(*npc));
100 gNpcCount++;
101 ASSERT(npc != nullptr);
102
104 if (isPeachNpc) {
106 }
107
108 npc->collisionDiameter = 32;
109 npc->collisionHeight = 64;
110 npc->renderMode = 13;
111 npc->blur.any = nullptr;
112 npc->yaw = 0.0f;
113 npc->jumpVel = 0.0f;
114 npc->pos.x = 0.0f;
115 npc->pos.y = 0.0f;
116 npc->pos.z = 0.0f;
117 npc->colliderPos.x = 0.0f;
118 npc->colliderPos.y = 0.0f;
119 npc->colliderPos.z = 0.0f;
120 npc->rotPivotOffsetY = 0.0f;
121 npc->rot.x = 0.0f;
122 npc->rot.y = 0.0f;
123 npc->rot.z = 0.0f;
124 npc->homePos.x = 0.0f;
125 npc->homePos.y = 0.0f;
126 npc->homePos.z = 0.0f;
127 npc->unk_96 = 0; // TODO: fix
128 npc->verticalRenderOffset = 0;
129 npc->alpha = 255;
130 npc->hideAlpha = 255;
131 npc->jumpScale = 1.0f;
132 npc->moveSpeed = 4.0f;
133 npc->scale.x = 1.0f;
134 npc->scale.y = 1.0f;
135 npc->scale.z = 1.0f;
136 npc->curAnim = blueprint->initialAnim;
137 npc->animationSpeed = 1.0f;
138 npc->renderYaw = 0.0f;
139 npc->imgfxType = IMGFX_CLEAR;
140 npc->imgfxFlags = 0;
142 npc->isFacingAway = false;
143 npc->yawCamOffset = 0;
145 npc->curFloor = NO_COLLIDER;
146 npc->curWall = NO_COLLIDER;
149 npc->screenSpaceOffset2D[0] = 0.0f;
150 npc->screenSpaceOffset2D[1] = 0.0f;
151 npc->verticalStretch = 1.0f;
152
153 for (j = 0; j < ARRAY_COUNT(npc->decorations); j++) {
154 npc->decorations[j] = 0;
155 npc->decorationType[j] = 0;
156 }
157
158 npc->onUpdate = blueprint->onUpdate;
159 if (npc->onUpdate == nullptr) {
161 }
162
163 npc->onRender = blueprint->onRender;
164 if (npc->onRender == nullptr) {
166 }
167 if (!isPeachNpc) {
168 npc->extraAnimList = animList;
169 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
170 if (!(npc->flags & NPC_FLAG_PARTNER)) {
171 npc->spriteInstanceID = spr_load_npc_sprite(npc->curAnim, animList);
172 } else {
174 }
175 } else {
177 }
178 }
179
181 npc->shadowScale = 1.0f;
182
185 }
186 return i;
187}
188
190 return create_npc_impl(blueprint, nullptr, false);
191}
192
194 return create_npc_impl(blueprint, animList, false);
195}
196
198 return create_npc_impl(blueprint, nullptr, true);
199}
200
201void free_npc_by_index(s32 listIndex) {
202 Npc* npc;
203 s32 i;
204
205 listIndex &= ~BATTLE_NPC_ID_BIT;
206
207 npc = (*gCurrentNpcListPtr)[listIndex];
208 if (npc != nullptr) {
209 if (npc->flags) {
210 if (npc->blur.any != nullptr) {
211 heap_free(npc->blur.any);
212 npc->blur.any = nullptr;
213 }
214
215 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
217 }
218
220
221 for (i = 0; i < MAX_NPC_DECORATIONS; i++) {
222 npc_remove_decoration(npc, i);
223 }
224
225 if (npc->flags & NPC_FLAG_MOTION_BLUR) {
226 disable_npc_blur(npc);
227 }
228
229 heap_free((*gCurrentNpcListPtr)[listIndex]);
230 (*gCurrentNpcListPtr)[listIndex] = nullptr;
231 gNpcCount--;
232 }
233 }
234}
235
236void free_npc(Npc* npc) {
237 s32 i;
238
239 if (npc->blur.any != nullptr) {
240 heap_free(npc->blur.any);
241 npc->blur.any = nullptr;
242 }
243
244 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
246 }
247
249
250 for (i = 0; i < MAX_NPC_DECORATIONS; i++) {
251 npc_remove_decoration(npc, i);
252 }
253
254 if (npc->flags & NPC_FLAG_MOTION_BLUR) {
255 disable_npc_blur(npc);
256 }
257
258 heap_free(npc);
259
260 for (i = 0; i < MAX_NPCS; i++) {
261 if ((*gCurrentNpcListPtr)[i] == npc) {
262 break;
263 }
264 }
265
266 (*gCurrentNpcListPtr)[i] = nullptr;
267 gNpcCount--;
268}
269
271 return (*gCurrentNpcListPtr)[listIndex & ~BATTLE_NPC_ID_BIT];
272}
273
274// checks for lateral collision with the world directly in front of the NPC and in an X pattern offset 45 degrees from
275// the forward direction. when a collision is detected, the NPC position is adjusted an appropriate NPC flags are set
276// to signal the collision has occurred.
279 s32 hit;
280 f32 testX;
281 f32 testY;
282 f32 testZ;
283
286 } else if (
287 (npc->pos.x != npc->colliderPos.x)
288 || (npc->pos.y != npc->colliderPos.y)
289 || (npc->pos.z != npc->colliderPos.z)
291 ) {
293 testAngle = clamp_angle(npc->yaw);
294 testX = npc->pos.x;
295 testY = npc->pos.y;
296 testZ = npc->pos.z;
297
298 if (!(npc->flags & NPC_FLAG_PARTNER)) {
300 } else {
302 }
303
304 if (hit) {
307 npc->pos.x = testX;
308 npc->pos.z = testZ;
309 } else {
311 }
312
313 testAngle = clamp_angle(npc->yaw + 45.0f);
314 testX = npc->pos.x;
315 testY = npc->pos.y;
316 testZ = npc->pos.z;
317
318 if (!(npc->flags & NPC_FLAG_PARTNER)) {
320 } else {
322 }
323
324 if (hit) {
326 npc->pos.x = testX;
327 npc->pos.z = testZ;
328 } else {
330 }
331
332 testAngle = clamp_angle(npc->yaw - 45.0f);
333 testX = npc->pos.x;
334 testY = npc->pos.y;
335 testZ = npc->pos.z;
336 if (!(npc->flags & NPC_FLAG_PARTNER)) {
338 } else {
340 }
341
342 if (hit != 0) {
344 npc->pos.x = testX;
345 npc->pos.z = testZ;
346 } else {
348 }
349
350 if (npc->flags & NPC_FLAG_PARTNER) {
351 testAngle = clamp_angle(npc->yaw + 45.0f + 180.0f);
352 testX = npc->pos.x;
353 testY = npc->pos.y;
354 testZ = npc->pos.z;
356 npc->collisionDiameter) != 0) {
358 npc->pos.x = testX;
359 npc->pos.z = testZ;
360 } else {
362 }
363
364 testAngle = clamp_angle((npc->yaw - 45.0f) + 180.0f);
365 testX = npc->pos.x;
366 testY = npc->pos.y;
367 testZ = npc->pos.z;
369 npc->collisionDiameter) != 0) {
371 npc->pos.x = testX;
372 npc->pos.z = testZ;
373 return;
374 }
376 }
377 }
378}
379
381 Npc* otherNpc;
382 f32 angle;
384 f32 thisBuf;
387 f32 xDiff, zDiff;
388 f32 dist;
390 s32 i;
391
394 thisBuf = npc->collisionDiameter * 0.5f;
395 thisX = npc->pos.x;
396 thisY = npc->pos.y;
397 thisZ = npc->pos.z;
398
399 for (i = 0; i < MAX_NPCS; i++) {
401 if (otherNpc != nullptr && npc != otherNpc) {
402 if (otherNpc->flags != 0 && !(otherNpc->flags & (NPC_FLAG_SUSPENDED | NPC_FLAG_IGNORE_PLAYER_COLLISION))) {
403 if (!(otherNpc->pos.y + otherNpc->collisionHeight < thisY) &&
404 !(thisY + npc->collisionHeight < otherNpc->pos.y))
405 {
406 otherX = otherNpc->pos.x;
407 xDiff = otherX - thisX;
408 otherZ = otherNpc->pos.z;
409 zDiff = otherZ - thisZ;
410 otherBuf = otherNpc->collisionDiameter * 0.5f;
411 dist = sqrtf(SQ(xDiff) + SQ(zDiff));
412
413 if (!(thisBuf + otherBuf <= dist)) {
414 collision = false;
415 if (npc->flags & NPC_FLAG_PARTNER) {
417 } else if (!(otherNpc->flags & NPC_FLAG_PARTNER) ||
419 {
420 collision = true;
421 }
422
423 if (collision) {
425 dist = (thisBuf + otherBuf) - dist;
426 xDiff = dist * sin_rad(angle);
427 zDiff = -dist * cos_rad(angle);
428 thisX += xDiff * 0.1f;
429 thisZ += zDiff * 0.1f;
430 }
432 }
433 }
434 }
435 }
436 }
437 npc->pos.x = thisX;
438 npc->pos.z = thisZ;
439 }
440}
441
445 f32 playerYaw, yaw;
446 f32 npcX, npcZ;
447 f32 dist, colDist, distToNpc;
450
452 return false;
453 }
454
455 if (npc->flags & NPC_FLAG_PARTNER) {
456 return false;
457 }
458
459 if (!gNpcPlayerCollisionsEnabled) {
460 return false;
461 }
462
463 if (playerStatus->pos.y + playerStatus->colliderHeight < npc->pos.y) {
464 return false;
465 }
466
467 if (npc->pos.y + npc->collisionHeight < playerStatus->pos.y) {
468 return false;
469 }
470
472 playerZ = playerStatus->pos.z;
473
475 playerColRadius = playerStatus->colliderDiameter / 2;
476
477 npcX = npc->pos.x;
478 npcZ = npc->pos.z;
479
480 deltaX = playerX - npcX;
481 deltaZ = playerZ - npcZ;
482
485 if (colDist < distToNpc) {
486 return false;
487 }
488
490
491 npcX = npc->colliderPos.x;
492 npcZ = npc->colliderPos.z;
493
494 deltaX = playerX - npcX;
495 deltaZ = playerZ - npcZ;
496
497 dist = sqrtf(SQ(deltaX) + SQ(deltaZ));
498 yaw = atan2(playerX, playerZ, npcX, npcZ);
499
500 playerYaw = playerStatus->targetYaw;
501 dist = colDist - dist;
502 deltaX = dist * sin_rad(DEG_TO_RAD(yaw));
503 deltaZ = -dist * cos_rad(DEG_TO_RAD(yaw));
504
505 if (playerStatus->animFlags & PA_FLAG_RIDING_PARTNER) {
506 if (fabsf(get_clamped_angle_diff(yaw, playerYaw)) < 45.0f) {
507 playerStatus->pos.x -= deltaX;
508 playerStatus->pos.z -= deltaZ;
511 } else {
512 playerStatus->pos.x -= deltaX * 0.5f;
513 playerStatus->pos.z -= deltaZ * 0.5f;
514 wPartnerNpc->pos.x -= deltaX * 0.5f;
515 wPartnerNpc->pos.z -= deltaZ * 0.5f;
516 }
517 } else {
519 playerStatus->pos.x -= deltaX * 0.4f;
520 playerStatus->pos.z -= deltaZ * 0.4f;
521 } else {
522 dist = get_clamped_angle_diff(yaw, playerYaw); // required to match
523 if (fabsf(dist) < 45.0f) {
524 playerStatus->pos.x -= deltaX;
525 playerStatus->pos.z -= deltaZ;
526 } else {
527 playerStatus->pos.x -= deltaX * 0.5f;
528 playerStatus->pos.z -= deltaZ * 0.5f;
529 }
530 }
531 }
532 npc->pos.x = npc->colliderPos.x;
533 npc->pos.y = npc->colliderPos.y;
534 npc->pos.z = npc->colliderPos.z;
535 return true;
536}
537
538// update NPC position using gravitational acceleration = 1.0
539// if the NPC is within 16 units of the floor, they are snapped to it
541 f32 x, y, z, testLength;
542 f32 length;
543 s32 hitID;
544
545 if (!(npc->flags & NPC_FLAG_GRAVITY)) {
546 return;
547 }
548
549 if (npc->flags & NPC_FLAG_JUMPING) {
551 return;
552 }
553
554 npc->jumpScale = 1.0f;
555 npc->jumpVel -= npc->jumpScale;
556 npc->pos.y += npc->jumpVel;
557
558 x = npc->pos.x;
559 y = npc->pos.y + 13;
560 z = npc->pos.z;
561 testLength = length = fabsf(npc->jumpVel) + 16;
562
563 if (!(npc->flags & NPC_FLAG_PARTNER)) {
564 hitID = npc_raycast_down_sides(npc->collisionChannel, &x, &y, &z, &length);
565 } else {
566 hitID = npc_raycast_down_around(npc->collisionChannel, &x, &y, &z, &length, npc->yaw, npc->collisionDiameter);
567 }
568
569 if (hitID && length <= testLength) {
570 npc->jumpVel = 0.0f;
571 npc->flags |= NPC_FLAG_GROUNDED;
572 npc->pos.y = y;
574 } else {
576 }
577}
578
579// perform only collision traces and snapping to ground from gravity code
581 f32 x, y, z, testLength;
582 f32 length;
583 s32 hitID;
584
585 if (npc->flags & (NPC_FLAG_GRAVITY | NPC_FLAG_FLYING)) {
586 return false;
587 }
588
589 if (npc->flags & NPC_FLAG_JUMPING) {
591 return false;
592 }
593
594 length = testLength = fabsf(velocity) + 16;
595 x = npc->pos.x;
596 y = npc->pos.y + 13;
597 z = npc->pos.z;
598
599 if (!(npc->flags & NPC_FLAG_PARTNER)) {
600 hitID = npc_raycast_down_sides(npc->collisionChannel, &x, &y, &z, &length);
601 } else {
602 hitID = npc_raycast_down_around(npc->collisionChannel, &x, &y, &z, &length, npc->yaw, npc->collisionDiameter);
603 }
604
605 if (hitID != 0 && length <= testLength) {
606 npc->pos.y = y;
608 npc->flags |= NPC_FLAG_GROUNDED;
609 return true;
610 }
611
613 return false;
614}
615
616void update_npcs(void) {
618 f32 x, y, z;
620
623 s32 i;
624
625 for (i = 0; i < MAX_NPCS; i++) {
626 Npc* npc = (*gCurrentNpcListPtr)[i];
627
628 if (npc != nullptr) {
629 if (npc->flags != 0) {
632 continue;
633 }
634
635 npc->onUpdate(npc);
638 } else {
640 }
641
642 npc->curFloor = NO_COLLIDER;
643 npc->curWall = NO_COLLIDER;
645
648 npc_try_snap_to_ground(npc, 0.0f);
651
652 if (npc->flags & NPC_FLAG_MOTION_BLUR) {
653 update_npc_blur(npc);
654 }
655
656 if ((npc->pos.y < -2000.0f) && !(npc->flags & NPC_FLAG_PARTNER)) {
657 npc->pos.y = playerStatus->pos.y;
658 npc->jumpVel = 0.0f;
659 npc->moveSpeed = 0.0f;
660 npc->jumpScale = 0.0f;
661 npc->flags &= ~NPC_FLAG_JUMPING;
662 }
663
664 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
665 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
666 if (npc->curAnim != 0) {
667 if (npc->spriteInstanceID >= 0) {
669 }
670 }
671 }
672 } else {
674 }
675
676 if (npc->flags & NPC_FLAG_HAS_SHADOW) {
677 Shadow* shadow = get_shadow_by_index(npc->shadowIndex);
679
681 if (npc->flags & NPC_FLAG_REFLECT_WALL) {
683 }
684
685 x = npc->pos.x;
686 y = npc->pos.y;
687 z = npc->pos.z;
688 if (!(npc->flags & NPC_FLAG_NO_SHADOW_RAYCAST)) {
689 if ( x != npc->colliderPos.x
690 || y != npc->colliderPos.y
691 || z != npc->colliderPos.z
692 || (npc->flags & NPC_FLAG_DIRTY_SHADOW)
693 ) {
694 x = npc->pos.x;
695 y = npc->pos.y + (npc->collisionHeight / 2);
696 z = npc->pos.z;
697 hitLength = 1000.0f;
700 shadow->pos.x = x;
701 shadow->pos.y = y;
702 shadow->pos.z = z;
703 shadow->rot.x = hitYaw;
704 shadow->rot.y = npc->renderYaw;
705 shadow->rot.z = hitPitch;
706 shadow->scale.x *= npc->shadowScale;
708 }
709 } else {
711 shadow->pos.x = npc->pos.x;
712 shadow->pos.z = npc->pos.z;
713 } else {
714 shadow->pos.x = npc->pos.x;
715 shadow->pos.y = npc->pos.y;
716 shadow->pos.z = npc->pos.z;
717 }
718 }
719 }
720
721 npc->colliderPos.x = npc->pos.x;
722 npc->colliderPos.y = npc->pos.y;
723 npc->colliderPos.z = npc->pos.z;
725
726 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
727 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
728 if (npc->spriteInstanceID < 0) {
729 npc->spriteInstanceID++;
730 if (npc->spriteInstanceID == -1) {
732 ASSERT(npc->spriteInstanceID >= 0);
734 }
735 }
736 }
737 }
738 }
739 }
740 }
741 }
742}
743
748 f32 yaw;
749 s32 direction;
750
754
756 direction = 0;
757 camRelativeYaw = 0.0f;
758 } else if (camRelativeYaw > 5.0f && camRelativeYaw < 175.0f) {
759 direction = 1;
760 camRelativeYaw = 180.0f;
761 } else {
762 // direction is close to flipping, use saved value
763 direction = 2;
765 }
766
768
770 if (npc->isFacingAway != direction && direction != 2) {
771 npc->isFacingAway = direction;
772
773 if (npc->isFacingAway) {
774 npc->turnAroundYawAdjustment = 180;
775 } else {
776 npc->turnAroundYawAdjustment = -180;
777 }
778
779 if (fabsf(get_clamped_angle_diff(cameraYaw, npc->yaw)) >= 90.0f) {
781 }
782 }
783
784 if (npc->turnAroundYawAdjustment != 0) {
785 if (npc->turnAroundYawAdjustment < 0) {
786 npc->turnAroundYawAdjustment += 20;
787 }
788 if (npc->turnAroundYawAdjustment > 0) {
789 npc->turnAroundYawAdjustment -= 20;
790 }
791 }
792
793 if (npc->flags & NPC_FLAG_FLIP_INSTANTLY) {
795 }
796
798 yaw = npc->renderYaw;
799 } else {
800 yaw = npc->renderYaw;
801 }
802 } else {
803 yaw = npc->renderYaw;
804 }
805 return yaw;
806}
807
808void appendGfx_npc(void* data) {
809 Npc* npc = data;
811 f32 renderYaw = npc_get_render_yaw(npc);
812
813 guTranslateF(mtx1, npc->pos.x, npc->pos.y + npc->verticalRenderOffset, npc->pos.z);
814 if (npc->flags & NPC_FLAG_UPSIDE_DOWN) {
817 }
818
819 if (npc->rotPivotOffsetY != 0.0f) {
820 guTranslateF(mtx2, 0.0f, npc->rotPivotOffsetY, 0.0f);
822 }
823
824 if (npc->rot.y != 0.0f) {
825 guRotateF(mtx2, npc->rot.y, 0.0f, 1.0f, 0.0f);
827 }
828
829 if (npc->rot.x != 0.0f) {
830 guRotateF(mtx2, npc->rot.x, 1.0f, 0.0f, 0.0f);
832 }
833
834 if (npc->rot.z != 0.0f) {
835 guRotateF(mtx2, npc->rot.z, 0.0f, 0.0f, 1.0f);
837 }
838
839 if (npc->rotPivotOffsetY != 0.0f) {
840 guTranslateF(mtx2, 0.0f, -npc->rotPivotOffsetY, 0.0f);
842 }
843
844 if ((npc->screenSpaceOffset2D[0] != 0.0f) || (npc->screenSpaceOffset2D[1] != 0.0f)) {
847 }
848
849 if (npc->scale.x * SPRITE_WORLD_SCALE_D != 1.0f
850 || (npc->scale.y * npc->verticalStretch) * SPRITE_WORLD_SCALE_D != 1.0f
851 || npc->scale.z * SPRITE_WORLD_SCALE_D != 1.0f
852 ) {
856 }
857
858 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
859 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE) && (npc->curAnim != 0) && (npc->spriteInstanceID >= 0)) {
860 npc_draw_with_palswap(npc, renderYaw, mtx1);
862 }
863 } else {
864 npc_draw_with_palswap(npc, renderYaw, mtx1);
866 }
867
868 if (npc->flags & NPC_FLAG_REFLECT_WALL) {
869 guTranslateF(mtx1, npc->pos.x, npc->pos.y + npc->verticalRenderOffset, -npc->pos.z);
870 if (npc->flags & NPC_FLAG_UPSIDE_DOWN) {
873 }
874 if ((npc->rot.y != 0.0f) || (npc->rot.x != 0.0f) || (npc->rot.z != 0.0f)) {
875 guRotateRPYF(mtx2, npc->rot.x, npc->rot.y, npc->rot.z);
877 }
878
879 if (npc->scale.x * SPRITE_WORLD_SCALE_D != 1.0f
880 || (npc->scale.y * npc->verticalStretch) * SPRITE_WORLD_SCALE_D != 1.0f
881 || npc->scale.z * SPRITE_WORLD_SCALE_D != 1.0f
882 ) {
888
889 }
890
891 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
892 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE) && (npc->curAnim != 0)) {
893 spr_draw_npc_sprite(npc->spriteInstanceID, renderYaw, 0, 0, mtx1);
894 }
895 } else {
897 }
898 }
899
900 if (npc->flags & NPC_FLAG_REFLECT_FLOOR) {
901 guTranslateF(mtx1, npc->pos.x, -(npc->pos.y + npc->verticalRenderOffset), npc->pos.z);
904
905 if (npc->rot.y != 0.0f || npc->rot.x != 0.0f || npc->rot.z != 0.0f) {
906 guRotateRPYF(mtx2, npc->rot.x, npc->rot.y, npc->rot.z);
908 }
909
910 if (npc->scale.x * SPRITE_WORLD_SCALE_D != 1.0f
911 || (npc->scale.y * npc->verticalStretch) * SPRITE_WORLD_SCALE_D != 1.0f
912 || npc->scale.z * SPRITE_WORLD_SCALE_D != 1.0f
913 ) {
919 }
920 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
921 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE) && (npc->curAnim != 0)) {
922 spr_draw_npc_sprite(npc->spriteInstanceID, renderYaw, 0, 0, mtx1);
923 }
924 } else {
926 }
927 }
928 npc->onRender(npc);
929}
930
931void render_npcs(void) {
935 f32 x, y, z, s;
937 s32 i;
938
939 for (i = 0; i < MAX_NPCS; i++) {
940 Npc* npc = (*gCurrentNpcListPtr)[i];
941 if ((npc != nullptr)
942 && (npc->flags != 0)
944 ) {
945 transform_point(cam->mtxPerspective, npc->pos.x, npc->pos.y, npc->pos.z, 1.0f, &x, &y, &z, &s);
946 if (!(s < 0.01) || !(s > -0.01)) {
947 renderDist = ((z * 5000.0f) / s) + 5000.0f;
948 if (renderDist < 0.0f) {
949 renderDist = 0.0f;
950 } else if (renderDist > 10000.0f) {
951 renderDist = 10000.0f;
952 }
953
954 renderTaskPtr->dist = -renderDist;
955 renderTaskPtr->appendGfxArg = npc;
956 renderTaskPtr->appendGfx = appendGfx_npc;
958
959 if (npc->flags & NPC_FLAG_HIDING) {
960 u8 r, g, b, a;
961 mdl_get_shroud_tint_params(&r, &g, &b, &a);
962 npc->hideAlpha = 255 - a;
963 } else {
964 npc->hideAlpha = 255;
965 }
966
967 if (npc->hideAlpha != 0) {
969 }
970
971 if (npc->flags & NPC_FLAG_MOTION_BLUR) {
972 renderTaskPtr->dist = -renderDist;
974 renderTaskPtr->appendGfxArg = npc;
977 }
978 }
979 }
980 }
981}
982
983void npc_move_heading(Npc* npc, f32 speed, f32 yaw) {
984 f32 angle = DEG_TO_RAD(yaw);
985 f32 sin = sin_rad(angle);
986 f32 cos = cos_rad(angle);
987
988 npc->pos.x += speed * sin;
989 npc->pos.z += -speed * cos;
990}
991
993 s32 i;
994 Npc* npc;
995
996 for (i = 0; i < MAX_NPCS; i++) {
997 npc = (*gCurrentNpcListPtr)[i];
998 if (npc != nullptr && npc->flags != 0 && npc->npcID == npcID) {
999 break;
1000 }
1001 }
1002 ASSERT(i < MAX_NPCS);
1003
1004 return npc;
1005}
1006
1008 s32 i;
1009 Npc* npc;
1010
1011 for (i = 0; i < MAX_NPCS; i++) {
1012 npc = (*gCurrentNpcListPtr)[i];
1013 if (npc != nullptr && npc->flags != 0 && npc->npcID == npcID) {
1014 break;
1015 }
1016 }
1017 if (i >= MAX_NPCS) {
1018 return nullptr;
1019 }
1020
1021 return npc;
1022}
1023
1025 Shadow* shadow;
1026
1027 if (!(npc->flags & NPC_FLAG_HAS_SHADOW)) {
1028 shadow = get_shadow_by_index(npc->shadowIndex);
1029 shadow->flags &= ~ENTITY_FLAG_HIDDEN;
1031 }
1032}
1033
1035 Shadow* shadow;
1036
1037 if (npc->flags & NPC_FLAG_HAS_SHADOW) {
1038 shadow = get_shadow_by_index(npc->shadowIndex);
1039 shadow->flags |= ENTITY_FLAG_HIDDEN;
1042 }
1043}
1044
1045void set_npc_sprite(Npc* npc, s32 anim, AnimID* extraAnimList) {
1047
1048 npc->extraAnimList = extraAnimList;
1049
1050 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1051 npc->spriteInstanceID = spr_load_npc_sprite(anim, extraAnimList);
1052 ASSERT(npc->spriteInstanceID >= 0);
1053 }
1054
1055 npc->curAnim = anim;
1056
1057 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1058 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1060 }
1061 }
1062}
1063
1065 if (!(npc->flags & NPC_FLAG_MOTION_BLUR)) {
1067 s32 i;
1068
1070
1071 motionBlur = heap_malloc(sizeof(*motionBlur));
1072 npc->blur.motion = motionBlur;
1073 ASSERT(motionBlur != nullptr);
1074 motionBlur->unused = 0;
1075 motionBlur->index = 0;
1076
1077 for (i = 0; i < ARRAY_COUNT(motionBlur->posX); i++) {
1078 motionBlur->posX[i] = npc->pos.x;
1079 motionBlur->posY[i] = npc->pos.y;
1080 motionBlur->posZ[i] = npc->pos.z;
1081 }
1082 }
1083}
1084
1086 if (npc->flags & NPC_FLAG_MOTION_BLUR) {
1088
1089 heap_free(npc->blur.motion);
1090 npc->blur.motion = nullptr;
1091 }
1092}
1093
1095 NpcMotionBlur* motionBlur = npc->blur.motion;
1096 s32 index = motionBlur->index;
1097
1098 motionBlur->posX[index] = npc->pos.x;
1099 motionBlur->posY[index] = npc->pos.y;
1100 motionBlur->posZ[index] = npc->pos.z;
1101
1102 index++;
1103 if (index >= 20) {
1104 index = 0;
1105 }
1106
1107 motionBlur->index = index;
1108}
1109
1110void appendGfx_npc_blur(void* data) {
1111 Npc* npc = (Npc*) data;
1112 Matrix4f mtx, tempMtx;
1113 f32 x, y, z;
1114 f32 yaw;
1115 s32 strideIdx;
1116 s32 drawIdx;
1117 s32 bufPos;
1118 NpcMotionBlur* blur;
1119
1120 strideIdx = 0;
1121 drawIdx = 0;
1122 blur = npc->blur.motion;
1123 bufPos = blur->index;
1124
1125 while (true) {
1126 bufPos--;
1127 strideIdx++;
1128
1129 if (bufPos < 0) {
1130 bufPos = NPC_BLUR_FRAMES - 1;
1131 }
1132
1133 if (bufPos == blur->index) {
1134 break;
1135 }
1136
1137 // only draw every third blur frame
1138 if (strideIdx < 3) {
1139 continue;
1140 }
1141
1142 strideIdx = 0;
1143 drawIdx++;
1144
1145 // draw three blur samples
1146 if (drawIdx > 3) {
1147 break;
1148 }
1149
1150 x = blur->posX[bufPos];
1151 y = blur->posY[bufPos];
1152 z = blur->posZ[bufPos];
1153 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_ALPHA, 255, 255, 255, 120 - (drawIdx * 20), 0);
1154 yaw = npc->renderYaw;
1155 guTranslateF(mtx, x, y, z);
1156
1157 if (npc->rot.y != 0.0f) {
1158 guRotateF(tempMtx, npc->rot.y, 0.0f, 1.0f, 0.0f);
1159 guMtxCatF(tempMtx, mtx, mtx);
1160 }
1161 if (npc->rot.x != 0.0f) {
1162 guRotateF(tempMtx, npc->rot.y, 0.0f, 1.0f, 0.0f);
1163 guMtxCatF(tempMtx, mtx, mtx);
1164 }
1165 if (npc->rot.z != 0.0f) {
1166 guRotateF(tempMtx, npc->rot.y, 0.0f, 1.0f, 0.0f);
1167 guMtxCatF(tempMtx, mtx, mtx);
1168 }
1169
1170 if ((npc->scale.x * SPRITE_WORLD_SCALE_D) != 1.0
1171 || ((npc->scale.y * npc->verticalStretch) * SPRITE_WORLD_SCALE_D) != 1.0
1172 || (npc->scale.z * SPRITE_WORLD_SCALE_D) != 1.0
1173 ) {
1174 guScaleF(
1175 tempMtx,
1179 );
1180 guMtxCatF(tempMtx, mtx, mtx);
1181 }
1182
1183 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1184 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1185 spr_draw_npc_sprite(npc->spriteInstanceID, yaw, 0, 0, mtx);
1186 }
1187 } else {
1189 }
1190 }
1191 npc_imgfx_update(npc);
1192}
1193
1195 gNpcPlayerCollisionsEnabled = true;
1196}
1197
1199 gNpcPlayerCollisionsEnabled = false;
1200}
1201
1202void func_8003B1A8(void) {
1203}
1204
1205void npc_reload_all(void) {
1206 s32 i;
1207 s32 j;
1208
1209 for (i = 0; i < MAX_NPCS; i++) {
1210 Npc* npc = (*gCurrentNpcListPtr)[i];
1211 if (npc != nullptr) {
1212 if (npc->flags && !(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1213 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1214 if (!(npc->flags & NPC_FLAG_PARTNER)) {
1216 } else {
1218 }
1219 }
1220 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1221 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE) && (npc->palSwapType != NPC_PAL_ADJUST_NONE)) {
1223 npc->originalPalettesCount = 0;
1224 while (npc->originalPalettesList[npc->originalPalettesCount] != (PAL_PTR) -1) {
1225 npc->originalPalettesCount++;
1226 }
1228 }
1229 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1230 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1231 for (j = 0; j < MAX_NPC_DECORATIONS; j++) {
1233 }
1234 npc_imgfx_update(npc);
1235 }
1236 }
1237 }
1238 }
1239 }
1240 }
1241}
1242
1243void set_npc_yaw(Npc* npc, f32 yaw) {
1244 npc->yaw = yaw;
1245
1246 if (get_clamped_angle_diff(gCameras[gCurrentCameraID].curYaw, yaw) >= 0.0f) {
1247 npc->yawCamOffset = 180;
1248 npc->isFacingAway = true;
1249 } else {
1250 npc->yawCamOffset = 0;
1251 npc->isFacingAway = false;
1252 }
1253}
1254
1256 if (npc->palSwapType != mode) {
1257 npc->palSwapPrevType = npc->palSwapType;
1258 npc->palSwapType = mode;
1260 npc->resetPalAdjust = 1;
1261 }
1262}
1263
1265 if (npc->palSwapType != mode) {
1266 npc->palSwapPrevType = npc->palSwapType;
1267 npc->palSwapType = mode;
1269 npc->resetPalAdjust = -1;
1270 }
1271}
1272
1276 return;
1277 }
1278 npc->palSwapType = npc->palSwapPrevType;
1281 npc->resetPalAdjust = 1;
1282}
1283
1290
1297
1299 switch (npc->palSwapType) {
1302 break;
1305 break;
1307 npc_render_with_single_pal_blending(npc, yaw, false, mtx);
1308 break;
1310 npc_render_with_single_pal_blending(npc, yaw, true, mtx);
1311 break;
1314 break;
1315 }
1316}
1317
1319 if (npc->resetPalAdjust != 0) {
1320 npc->verticalStretch = 1.0f;
1321 npc->screenSpaceOffset2D[0] = 0.0f;
1322 npc->screenSpaceOffset2D[1] = 0.0f;
1323 npc->resetPalAdjust = 0;
1324 }
1325
1326 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1327 s32 alpha = (npc->alpha * npc->hideAlpha / 255);
1328 u32 mask;
1329 if (alpha < 255) {
1331 } else {
1332 mask = 0;
1333 }
1334 spr_draw_npc_sprite(npc->spriteInstanceID | mask, arg1, alpha, nullptr, mtx);
1335 } else {
1337 }
1338}
1339
1341 s32 i, j;
1342 s32 brightness;
1343 PAL_PTR src;
1344 PAL_PTR dst;
1345
1346 if (npc->resetPalAdjust != 0) {
1348 npc->originalPalettesCount = 0;
1349 while ((s32)npc->originalPalettesList[npc->originalPalettesCount] != -1) {
1350 npc->originalPalettesCount++;
1351 }
1352
1354 for (i = 0; i < npc->originalPalettesCount; i++) {
1355 dst = npc->copiedPalettes[i];
1356 src = npc->originalPalettesList[i];
1357 if (src != nullptr) {
1358 for (j = 0; j < SPR_PAL_SIZE; j++) {
1359 *dst++ = *src++;
1360 }
1361 }
1362 }
1363
1364 npc->palAnimState = -2;
1365 npc->palBlendAlpha = 0;
1366 npc->resetPalAdjust = 0;
1367 npc->nextPalTime = 0;
1368 }
1369
1370 if (npc->nextPalTime == 0) {
1371 npc->palAnimState += 2;
1372 brightness = wWattIdlePalettesAnim[npc->palAnimState];
1373 if (brightness == 255) {
1374 npc->palAnimState = 0;
1375 }
1376 npc->nextPalTime = wWattIdlePalettesAnim[npc->palAnimState + 1] / 2;
1377 }
1378
1379 brightness = wWattIdlePalettesAnim[npc->palAnimState];
1380 npc->nextPalTime--;
1381
1382 switch(brightness) {
1383 case WATT_DEFAULT:
1384 for (i = 0; i < npc->spriteColorVariations; i++) {
1385 dst = npc->copiedPalettes[i];
1386 src = npc->originalPalettesList[i];
1387 if (src != nullptr) {
1388 for (j = 0; j < SPR_PAL_SIZE; j++) {
1389 *dst++ = *src++;
1390 }
1391 }
1392 }
1393 break;
1394 case WATT_BRIGHTEST:
1395 for (i = 0; i < npc->spriteColorVariations; i++) {
1396 // use watt's Brightest palettes
1397 dst = npc->copiedPalettes[i];
1399 if (src != nullptr) {
1400 for (j = 0; j < SPR_PAL_SIZE; j++) {
1401 *dst++ = *src++;
1402 }
1403 }
1404 }
1405 break;
1406 case WATT_BRIGHTER:
1407 for (i = 0; i < npc->spriteColorVariations; i++) {
1408 // use watt's Brighter palettes
1409 dst = npc->copiedPalettes[i];
1411 if (src != nullptr) {
1412 for (j = 0; j < SPR_PAL_SIZE; j++) {
1413 *dst++ = *src++;
1414 }
1415 }
1416 }
1417 break;
1418 }
1419
1420 for (i = 0; i < npc->originalPalettesCount; i++) {
1421 npc->adjustedPalettes[i] = npc->copiedPalettes[i];
1422 }
1423
1424 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1425 s32 alpha = npc->alpha * npc->hideAlpha / 255;
1426 u32 mask = 0;
1427 if (alpha < 255) {
1429 }
1431 spr_draw_npc_sprite(npc->spriteInstanceID | mask, arg1, alpha, npc->adjustedPalettes, mtx);
1432 }
1433 npc->palBlendAlpha--;
1434}
1435
1437 u8 r = (UNPACK_PAL_R(colorA) * (255 - lerpAlpha) + UNPACK_PAL_R(colorB) * lerpAlpha) / 255;
1438 u8 g = (UNPACK_PAL_G(colorA) * (255 - lerpAlpha) + UNPACK_PAL_G(colorB) * lerpAlpha) / 255;
1439 u8 b = (UNPACK_PAL_B(colorA) * (255 - lerpAlpha) + UNPACK_PAL_B(colorB) * lerpAlpha) / 255;
1440 u8 a = UNPACK_PAL_A(colorB);
1441
1442 return PACK_PAL_RGBA(r, g, b, a);
1443}
1444
1446 PAL_PTR color1;
1447 PAL_PTR color2;
1449 s32 i, j;
1451
1452 // copy palettes from sprite data
1453 if (npc->resetPalAdjust != 0) {
1454 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1456 }
1457
1458 npc->originalPalettesCount = 0;
1459 while ((s32)npc->originalPalettesList[npc->originalPalettesCount] != -1) {
1460 npc->originalPalettesCount++;
1461 }
1462
1463 if (npc->resetPalAdjust == 1) {
1465 npc->palBlendAlpha = 0;
1466 } else {
1468 npc->palBlendAlpha = 255;
1469 }
1470
1471 for (i = 0; i < npc->originalPalettesCount; i++) {
1472 color1 = npc->copiedPalettes[i];
1473 color2 = npc->originalPalettesList[i];
1474 npc->adjustedPalettes[i] = color1;
1475 if (color2 != nullptr) {
1476 for (j = 0; j < SPR_PAL_SIZE; j++) {
1477 *color1++ = *color2++;
1478 }
1479 }
1480 }
1481
1482 if (!hasDifferentIntervals) {
1485 npc->palswapTimeBtoA = npc->palswapTimeAtoB;
1486 npc->palswapTimeHoldA = 0;
1487 }
1488
1489 npc->nextPalTime = npc->palswapTimeHoldA;
1490 npc->palBlendAlpha = 0;
1492 npc->resetPalAdjust = 0;
1493 }
1494
1495 // blending from A -> B
1496 switch (npc->palAnimState) {
1497 case PAL_SWAP_HOLD_A:
1498 if (npc->nextPalTime != 0) {
1499 npc->nextPalTime--;
1500 break;
1501 } else {
1502 npc->palBlendAlpha = 0;
1504 }
1505 // fallthrough
1506 case PAL_SWAP_A_TO_B:
1507 npc->palBlendAlpha += 25600 / npc->palswapTimeAtoB;
1508 if (npc->palBlendAlpha > 25500) {
1509 npc->palBlendAlpha = 25500;
1510 }
1511 blendAlpha = npc->palBlendAlpha / 100;
1512 // blend two palettes
1513 outColor = npc->copiedPalettes[0];
1514 color2 = npc->originalPalettesList[npc->blendPalA];
1515 color1 = npc->originalPalettesList[npc->blendPalB];
1516 npc->adjustedPalettes[0] = outColor;
1517
1518 for (j = 0; j < SPR_PAL_SIZE; j++) {
1519 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1520 }
1521
1522 if (blendAlpha == 255) {
1524 npc->nextPalTime = npc->palswapTimeHoldB;
1525 }
1526 break;
1527 }
1528
1529 // blending from B -> A
1530 switch (npc->palAnimState) {
1531 case PAL_SWAP_HOLD_B:
1532 if (npc->nextPalTime != 0) {
1533 npc->nextPalTime--;
1534 break;
1535 } else {
1536 npc->palBlendAlpha = 0;
1538 }
1539 // fallthrough
1540 case PAL_SWAP_B_TO_A:
1541 npc->palBlendAlpha += 25600 / npc->palswapTimeBtoA;
1542 if (npc->palBlendAlpha > 25500) {
1543 npc->palBlendAlpha = 25500;
1544 }
1545 blendAlpha = npc->palBlendAlpha / 100;
1546 // blend two palettes
1547 outColor = npc->copiedPalettes[0];
1548 color2 = npc->originalPalettesList[npc->blendPalB];
1549 color1 = npc->originalPalettesList[npc->blendPalA];
1550 npc->adjustedPalettes[0] = outColor;
1551
1552 for (j = 0; j < SPR_PAL_SIZE; j++) {
1553 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1554 }
1555
1556 if (blendAlpha == 255) {
1558 npc->nextPalTime = npc->palswapTimeHoldA;
1559 }
1560 break;
1561 }
1562
1563 switch (npc->palAnimState) {
1564 case PAL_SWAP_HOLD_A:
1565 case PAL_SWAP_A_TO_B:
1566 case PAL_SWAP_HOLD_B:
1567 case PAL_SWAP_B_TO_A:
1568 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1569 u32 mask = 0;
1570 blendAlpha = npc->alpha * npc->hideAlpha / 255;
1571 if (blendAlpha < 255) {
1573 }
1576 }
1577 break;
1578 }
1579}
1580
1582 PAL_PTR color1;
1583 PAL_PTR color2;
1585 s32 i, j;
1586 u8 blendAlpha;
1587
1588 // copy palettes from sprite data
1589 if (npc->resetPalAdjust != 0) {
1590 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1592 }
1593
1594 npc->originalPalettesCount = 0;
1595 while ((s32)npc->originalPalettesList[npc->originalPalettesCount] != -1) {
1596 npc->originalPalettesCount++;
1597 }
1598
1599 if (npc->resetPalAdjust == 1) {
1601 npc->palBlendAlpha = 0;
1602 } else {
1604 npc->palBlendAlpha = 255;
1605 }
1606
1607 for (i = 0; i < npc->originalPalettesCount; i++) {
1608 color1 = npc->copiedPalettes[i];
1609 color2 = npc->originalPalettesList[i];
1610 npc->adjustedPalettes[i] = color1;
1611 if (color2 != nullptr) {
1612 for (j = 0; j < SPR_PAL_SIZE; j++) {
1613 *color1++ = *color2++;
1614 }
1615 }
1616 }
1617
1618 npc->nextPalTime = npc->palswapTimeHoldA;
1619 npc->palBlendAlpha = 0;
1621 npc->resetPalAdjust = 0;
1622 }
1623
1624 // blending from A -> B
1625 switch (npc->palAnimState) {
1626 case PAL_SWAP_HOLD_A:
1627 if (npc->nextPalTime != 0) {
1628 npc->nextPalTime--;
1629 break;
1630 }
1631 npc->palBlendAlpha = 0;
1633 // fallthrough
1634 case PAL_SWAP_A_TO_B:
1635 npc->palBlendAlpha += 25600 / npc->palswapTimeAtoB;
1636 if (npc->palBlendAlpha > 25500) {
1637 npc->palBlendAlpha = 25500;
1638 }
1639 blendAlpha = npc->palBlendAlpha / 100;
1640
1641 // blend first two palettes
1642 outColor = npc->copiedPalettes[0];
1643 color2 = npc->originalPalettesList[npc->blendPalA];
1644 color1 = npc->originalPalettesList[npc->blendPalB];
1645 npc->adjustedPalettes[0] = outColor;
1646
1647 for (j = 0; j < SPR_PAL_SIZE; j++) {
1648 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1649 }
1650
1651 // blend next palettes
1652 outColor = npc->copiedPalettes[3];
1653 color2 = npc->originalPalettesList[npc->blendPalC];
1654 color1 = npc->originalPalettesList[npc->blendPalD];
1655 npc->adjustedPalettes[3] = outColor;
1656
1657 for (j = 0; j < SPR_PAL_SIZE; j++) {
1658 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1659 }
1660
1661 if (blendAlpha == 255) {
1663 npc->nextPalTime = npc->palswapTimeHoldB;
1664 }
1665 break;
1666 }
1667
1668 // blending from B -> A
1669 switch (npc->palAnimState) {
1670 case PAL_SWAP_HOLD_B:
1671 if (npc->nextPalTime != 0) {
1672 npc->nextPalTime--;
1673 break;
1674 } else {
1675 npc->palBlendAlpha = 0;
1677 }
1678 // fallthrough
1679 case PAL_SWAP_B_TO_A:
1680 npc->palBlendAlpha += 25600 / npc->palswapTimeBtoA;
1681 if (npc->palBlendAlpha > 25500) {
1682 npc->palBlendAlpha = 25500;
1683 }
1684 blendAlpha = npc->palBlendAlpha / 100;
1685
1686 // blend first two palettes
1687 outColor = npc->copiedPalettes[0];
1688 color2 = npc->originalPalettesList[npc->blendPalB];
1689 color1 = npc->originalPalettesList[npc->blendPalA];
1690 npc->adjustedPalettes[0] = outColor;
1691
1692 for (j = 0; j < SPR_PAL_SIZE; j++) {
1693 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1694 }
1695
1696 // blend next palettes
1697 outColor = npc->copiedPalettes[1];
1698 color2 = npc->originalPalettesList[npc->blendPalD];
1699 color1 = npc->originalPalettesList[npc->blendPalC];
1700 npc->adjustedPalettes[3] = npc->copiedPalettes[3];
1701
1702 for (j = 0; j < SPR_PAL_SIZE; j++) {
1703 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1704 }
1705
1706 if (blendAlpha == 255) {
1708 npc->nextPalTime = npc->palswapTimeHoldA;
1709 }
1710 break;
1711 }
1712
1713 switch (npc->palAnimState) {
1714 case PAL_SWAP_HOLD_A:
1715 case PAL_SWAP_A_TO_B:
1716 case PAL_SWAP_HOLD_B:
1717 case PAL_SWAP_B_TO_A:
1718 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1719 u32 mask = 0;
1720 blendAlpha = npc->alpha * npc->hideAlpha / 255;
1721 if (blendAlpha < 255) {
1723 }
1726 }
1727 break;
1728 }
1729}
1730
1731void npc_set_decoration(Npc* npc, s32 idx, s32 decorationType) {
1733 npc->decorationType[idx] = decorationType;
1734 npc->changedDecoration[idx] = 1;
1735 npc->decorationInitialized[idx] = 0;
1736}
1737
1739 switch (npc->decorationType[idx]) {
1742 break;
1745 break;
1748 break;
1751 break;
1754 break;
1757 break;
1760 break;
1761 }
1763}
1764
1766 s32 i;
1767
1768 for (i = 0; i < MAX_NPC_DECORATIONS; i++) {
1769 switch (npc->decorationType[i]) {
1772 break;
1775 break;
1778 break;
1781 break;
1784 break;
1787 break;
1790 break;
1791 }
1792 }
1793}
1794
1796 switch (npc->decorationType[idx]) {
1803 break;
1805 npc->decorationInitialized[idx] = 0;
1806 break;
1807 }
1808}
1809
1812
1815
1817 AuraFXData* data;
1818
1819 switch (npc->decorationInitialized[idx]) {
1820 case 0:
1821 fx_aura(FX_AURA_BLUE, npc->pos.x, npc->pos.y, npc->pos.z, 1.0f, &npc->decorations[idx]);
1822 npc->decorationInitialized[idx] = 1;
1823 // fallthrough
1824 case 1:
1825 data = npc->decorations[idx]->data.aura;
1826 data->posA.x = npc->pos.x;
1827 data->posA.y = npc->pos.y;
1828 data->posA.z = npc->pos.z;
1829 data->scale.x = (npc->scale.x * npc->collisionDiameter) * 0.01;
1830 data->scale.y = (npc->scale.y * npc->collisionHeight) * 0.01;
1831 data->renderYaw = npc->renderYaw;
1832 break;
1833 }
1834}
1835
1839
1841 switch (npc->decorationInitialized[idx]) {
1842 case 0:
1843 if (npc->yawCamOffset > 90) {
1844 fx_sweat(0, npc->pos.x, npc->pos.y + npc->collisionHeight, npc->pos.z, 5.0f, 45.0f, 20);
1845 } else {
1846 fx_sweat(0, npc->pos.x, npc->pos.y + npc->collisionHeight, npc->pos.z, 5.0f, -45.0f, 20);
1847 }
1848 npc->decorationGlowPhase[idx] = 10;
1849 npc->decorationInitialized[idx] = 1;
1850 break;
1851 case 1:
1852 if (npc->decorationGlowPhase[idx] != 0) {
1853 npc->decorationGlowPhase[idx]--;
1854 } else {
1855 npc->decorationInitialized[idx] = 0;
1856 }
1857 break;
1858 }
1859}
1860
1863
1865 StarsOrbitingFXData* data;
1866
1867 switch (npc->decorationInitialized[idx]) {
1868 case 0:
1869 fx_stars_orbiting(0, npc->pos.x, npc->pos.y + npc->collisionHeight, npc->pos.z, 20.0f, 3, &npc->decorations[idx]);
1870 npc->decorationInitialized[idx] = 1;
1871 break;
1872 case 1:
1873 data = npc->decorations[idx]->data.starsOrbiting;
1874 data->pos.x = npc->pos.x;
1875 data->pos.y = npc->pos.y + npc->collisionHeight;
1876 data->pos.z = npc->pos.z;
1877 break;
1878 }
1879}
1880
1884
1886 EnergyOrbWaveFXData* data;
1887
1888 switch (npc->decorationInitialized[idx]) {
1889 case 0:
1890 npc->decorations[idx] = fx_energy_orb_wave(2, npc->pos.x, npc->pos.y + npc->collisionHeight * 0.5, npc->pos.z, npc->scale.x * 0.8 + 0.2f, -1);
1891 npc->decorationInitialized[idx] = 1;
1892 break;
1893 case 1:
1894 data = npc->decorations[idx]->data.energyOrbWave;
1895 data->pos.x = npc->pos.x;
1896 data->pos.y = npc->pos.y + npc->collisionHeight * 0.5 * npc->scale.x;
1897 data->pos.z = npc->pos.z;
1898 data->scale = npc->scale.x * 0.8 + 0.2f;
1899 break;
1900 }
1901}
1902
1906
1908 EnergyOrbWaveFXData* data;
1909
1910 switch (npc->decorationInitialized[idx]) {
1911 case 0:
1912 npc->decorations[idx] = fx_energy_orb_wave(2, npc->pos.x, npc->pos.y + npc->collisionHeight * 0.5, npc->pos.z - 5.0f, 1.0f, 0);
1913 npc->decorationInitialized[idx] = 1;
1914 break;
1915 case 1:
1916 data = npc->decorations[idx]->data.energyOrbWave;
1917 data->pos.x = npc->pos.x;
1918 data->pos.y = npc->pos.y + npc->collisionHeight * 0.5;
1919 data->pos.z = npc->pos.z - 5.0f;
1920 data->scale = 1.0f;
1921 break;
1922 }
1923}
1924
1928
1930 #define RGBA_BUF_SIZE 20
1934 s32 color;
1935 s32 alpha;
1936 s32 i;
1937
1938 if (npc->decorationInitialized[idx] == 0) {
1940 npc->decorationInitialized[idx] = 1;
1941 }
1942 if (npc->decorationInitialized[idx] == 1) {
1943 npc->decorationGlowPhase[idx] += 7;
1944 if (npc->decorationGlowPhase[idx] >= 360) {
1945 npc->decorationGlowPhase[idx] %= 360;
1946 }
1947
1948 for (i = 0; i < RGBA_BUF_SIZE; i++) {
1949 rbuf[i] = (cosine(npc->decorationGlowPhase[idx] + (25 * i)) + 1.0) * 80.0f;
1950 gbuf[i] = (cosine(npc->decorationGlowPhase[idx] + (25 * i) + 45) + 1.0) * 80.0f;
1951 bbuf[i] = (cosine(npc->decorationGlowPhase[idx] + (25 * i) + 90) + 1.0) * 80.0f;
1952 }
1953
1954 alpha = 255;
1955 for (i = 0; i < RGBA_BUF_SIZE; i++) {
1956 color = (rbuf[i] << 24) | (gbuf[i] << 16) | (bbuf[i] << 8) | alpha;
1958 }
1959 }
1960 #undef RGBA_BUF_SIZE
1961}
1962
1965
1966Npc* npc_find_closest(f32 x, f32 y, f32 z, f32 radius) {
1967 Npc* closestNpc = nullptr;
1968 f32 closestDist = radius;
1969 f32 maxDist = radius;
1970 s32 i;
1971
1972 for (i = 0; i < ARRAY_COUNT(*gCurrentNpcListPtr); i++) {
1973 Npc* npc = (*gCurrentNpcListPtr)[i];
1974
1975 if (npc != nullptr && npc->flags != 0 && !(npc->flags & NPC_FLAG_PARTNER)) {
1976 if (!(npc->flags & (NPC_FLAG_SUSPENDED | NPC_FLAG_INACTIVE))) {
1977 f32 distance = fabsf(dist2D(npc->pos.x, npc->pos.z, x, z));
1978
1979 if (distance <= maxDist) {
1980 if (distance < closestDist) {
1982 closestNpc = npc;
1983 }
1984 }
1985 }
1986 }
1987 }
1988
1989 return closestNpc;
1990}
1991
1993 Npc* closestNpc = nullptr;
1994 f32 closestDist = radius;
1995 f32 maxDist = radius;
1996 s32 i;
1997
1998 for (i = 0; i < ARRAY_COUNT(*gCurrentNpcListPtr); i++) {
1999 Npc* npc = (*gCurrentNpcListPtr)[i];
2000
2001 if (npc != nullptr && npc->flags != 0 && (npc->flags & NPC_FLAG_PARTNER)) {
2002 if (!(npc->flags & (NPC_FLAG_SUSPENDED | NPC_FLAG_INACTIVE))) {
2003 f32 distance = fabsf(dist2D(npc->pos.x, npc->pos.z, x, z));
2004
2005 if (distance <= maxDist) {
2006 if (distance < closestDist) {
2008 closestNpc = npc;
2009 }
2010 }
2011 }
2012 }
2013 }
2014
2015 return closestNpc;
2016}
2017
2020 s32 y = get_entity_by_index(idx)->pos.y - 10.0f;
2021 Npc* npc;
2022 s32 i;
2023 s32 var_v1;
2024
2025 npc->pos = npc->pos; // TODO required to match
2026
2027 for (i = 0; i < ARRAY_COUNT(*gCurrentNpcListPtr); i++) {
2028 npc = (*gCurrentNpcListPtr)[i];
2029
2030 if (npc == nullptr) {
2031 continue;
2032 }
2033 if (npc->flags == 0) {
2034 continue;
2035 }
2037 continue;
2038 }
2039 if (npc->flags & NPC_FLAG_PARTNER) {
2040 var_v1 = i; // TODO required to match (dummy if statement to load NPC_FLAG_PARTNER into s5)
2041 }
2042 if (npc->pos.y < y) {
2043 continue;
2044 }
2047 if (var_v1 != 0) {
2048 if (idx == var_v1) {
2049 return i;
2050 }
2051 }
2052 } else {
2053 var_v1 = npc->curFloor;
2054 if (npc->curFloor & COLLISION_WITH_ENTITY_BIT) { // TODO required to match (can't use var_v1)
2055 if (idx == var_v1) {
2056 npc->pos = npc->pos; // TODO required to match
2057 return i;
2058 }
2059 }
2060 }
2061 }
2062
2063 return -1;
2064}
2065
2067 f32 x;
2068 f32 y;
2069 f32 z;
2070 f32 yaw;
2071
2072 if (npc->flags & NPC_FLAG_PARTNER) {
2073 y = get_shadow_by_index(npc->shadowIndex)->pos.y + 13.0f;
2074 } else {
2075 y = npc->pos.y + 13.0f;
2076 }
2077
2078 yaw = 16.0f;
2079 x = npc->pos.x;
2080 z = npc->pos.z;
2081
2083 if (yaw <= 16.0f) {
2084 return NpcHitQueryColliderID;
2085 }
2086 }
2087 return 0;
2088}
2089
2091 s32 imgfxType = npc->imgfxType;
2092 s32 imgfxArg1 = npc->imgfxArg1;
2093 s32 imgfxArg2 = npc->imgfxArg2;
2094 s32 imgfxArg3 = npc->imgfxArg3;
2095 s32 imgfxArg4 = npc->imgfxArg4;
2096 s32 imgfxFlags = npc->imgfxFlags;
2097
2098 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_CLEAR, 0, 0, 0, 0, 0);
2099
2100 switch (imgfxType) {
2101 case IMGFX_CLEAR:
2103 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_CLEAR, 0, 0, 0, 0, imgfxFlags);
2104 break;
2105 case IMGFX_UNK_2:
2106 case IMGFX_RESET:
2108 // fallthrough
2109 case IMGFX_UNK_1:
2110 set_npc_imgfx_all(npc->spriteInstanceID, imgfxType, 0, 0, 0, 0, imgfxFlags);
2111 break;
2112 case IMGFX_SET_WAVY:
2114 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_WAVY, imgfxArg1, imgfxArg2, imgfxArg3, 0, imgfxFlags);
2115 break;
2116 case IMGFX_SET_COLOR:
2118 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_COLOR, imgfxArg1, imgfxArg2, imgfxArg3, 255, imgfxFlags);
2119 break;
2120 case IMGFX_SET_ALPHA:
2122 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_ALPHA, 255, 255, 255, imgfxArg1, imgfxFlags);
2123 break;
2124 case IMGFX_SET_TINT:
2126 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_TINT, imgfxArg1, imgfxArg2, imgfxArg3, imgfxArg4, imgfxFlags);
2127 break;
2130 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_WHITE_FADE, imgfxArg1, imgfxArg2, imgfxArg3, 255, imgfxFlags);
2131 break;
2134 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_CREDITS_FADE, imgfxArg1, imgfxArg2, imgfxArg3, imgfxArg4, imgfxFlags);
2135 break;
2136 case IMGFX_SET_ANIM:
2138 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_ANIM, imgfxArg1, imgfxArg2, imgfxArg3, 0, imgfxFlags);
2139 break;
2140 case IMGFX_HOLOGRAM:
2142 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_HOLOGRAM, imgfxArg1, imgfxArg2, imgfxArg3, imgfxArg4, imgfxFlags);
2143 break;
2144 case IMGFX_FILL_COLOR:
2146 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_FILL_COLOR, imgfxArg1, imgfxArg2, imgfxArg3, 255, imgfxFlags);
2147 break;
2148 case IMGFX_OVERLAY:
2150 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_OVERLAY, imgfxArg1, 255, 0, 255, imgfxFlags);
2151 break;
2152 case IMGFX_OVERLAY_XLU:
2154 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_OVERLAY, imgfxArg1, imgfxArg2, 0, imgfxArg2, imgfxFlags);
2155 break;
2156 }
2157}
2158
2159void npc_set_imgfx_params(Npc* npc, s32 imgfxType, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6) {
2160 npc->imgfxType = imgfxType;
2161 npc->imgfxArg1 = arg2;
2162 npc->imgfxArg2 = arg3;
2163 npc->imgfxArg3 = arg4;
2164 npc->imgfxArg4 = arg5;
2165 npc->imgfxFlags = arg6;
2166 npc_imgfx_update(npc);
2167}
2168
2169void COPY_set_defeated(s32 mapID, s32 encounterID) {
2171 s32 encounterIdx = encounterID / 32;
2173 s32 flag;
2174
2175 flag = encounterID % 32;
2176 encounterShift = flag;
2178 currentEncounter->defeatFlags[mapID][encounterIdx] = flag | (1 << encounterShift);
2179
2180 // TODO: The below should work but has regalloc issues:
2181 /*EncounterStatus *currentEncounter = &gCurrentEncounter;
2182 s32 encounterIdx = encounterID / 32;
2183 s32 encounterShift = encounterID % 32;
2184
2185 currentEncounter->defeatFlags[mapID][encounterIdx] |= (1 << encounterShift);*/
2186}
2187
2190 s32 i;
2191 s32 j;
2192
2193 for (i = 0; i < ARRAY_COUNT(currentEncounter->encounterList); i++) {
2195 }
2196
2198 currentEncounter->numEncounters = 0;
2199 currentEncounter->firstStrikeType = FIRST_STRIKE_NONE;
2200 currentEncounter->hitType = 0;
2201 currentEncounter->battleTriggerCooldown = 0;
2202 currentEncounter->npcGroupList = 0;
2203 currentEncounter->unk_08 = 0;
2204 currentEncounter->dropWhackaBump = false;
2205
2206 for (i = 0; i < ARRAY_COUNT(currentEncounter->defeatFlags); i++) {
2207 for (j = 0; j < ARRAY_COUNT(currentEncounter->defeatFlags[i]); j++) {
2208 currentEncounter->defeatFlags[i][j] = 0;
2209 }
2210 }
2211
2212 for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps); i++) {
2213 currentEncounter->recentMaps[i] = -1;
2214 }
2215
2216 func_80045AC0();
2219}
2220
2223 s32 i;
2224 s32 j;
2225
2226 for (i = 0; i < ARRAY_COUNT(currentEncounter->encounterList); i++) {
2228 }
2229
2231 for (i = 0; i < ARRAY_COUNT(currentEncounter->defeatFlags); i++) {
2232 for (j = 0; j < ARRAY_COUNT(currentEncounter->defeatFlags[i]); j++) {
2233 currentEncounter->defeatFlags[i][j] = 0;
2234 }
2235 }
2236
2238 for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps); i++) {
2239 currentEncounter->recentMaps[i] = -1;
2240 }
2241 }
2242 }
2243
2244 currentEncounter->numEncounters = 0;
2245 currentEncounter->firstStrikeType = FIRST_STRIKE_NONE;
2246 currentEncounter->hitType = 0;
2247 currentEncounter->battleTriggerCooldown = 0;
2248 currentEncounter->curAreaIndex = gGameStatusPtr->areaID;
2249 currentEncounter->curMapIndex = gGameStatusPtr->mapID;
2250 currentEncounter->curEntryIndex = gGameStatusPtr->entryID;
2251 currentEncounter->npcGroupList = 0;
2252 currentEncounter->unk_08 = 0;
2253 currentEncounter->scriptedBattle = false;
2254
2255 func_80045AC0();
2258}
2259
2260void func_8003E50C(void) {
2261}
2262
2266
2268 switch (gEncounterState) {
2270 break;
2273 break;
2276 break;
2279 break;
2282 break;
2285 break;
2286 }
2287
2289}
2290
2292 switch (gEncounterState) {
2294 break;
2297 break;
2300 break;
2303 break;
2306 break;
2309 break;
2310 }
2311
2313}
2314
2316 switch (gEncounterState) {
2318 break;
2321 break;
2322 }
2323}
2324
2327
2328void make_npcs(s32 flags, s32 mapID, s32* npcGroupList) {
2330 s32 i;
2331 s32 j;
2332
2334 currentEncounter->mapID = mapID;
2335 currentEncounter->npcGroupList = npcGroupList;
2336
2338 for (i = 0; i < ARRAY_COUNT(currentEncounter->defeatFlags); i++) {
2339 for (j = 0; j < ARRAY_COUNT(currentEncounter->defeatFlags[i]); j++) {
2340 currentEncounter->defeatFlags[i][j] = 0;
2341 }
2342 }
2343
2345 for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps); i++) {
2346 currentEncounter->recentMaps[i] = -1;
2347 }
2348 }
2349 }
2350
2351 if (npcGroupList != nullptr) {
2353 EncounterStateChanged = true;
2355 }
2356}
2357
2358void kill_encounter(Enemy* enemy) {
2360 s32 i;
2361
2362 for (i = 0; i < encounter->count; i++) {
2363 Enemy* currentEnemy = encounter->enemy[i];
2364 if (currentEnemy != nullptr) {
2366 encounter->enemy[i] = nullptr;
2367 }
2368 }
2369}
2370
2371void kill_enemy(Enemy* enemy) {
2373 Encounter* encounter = encounterStatus->encounterList[enemy->encounterIndex];
2374 s32 i;
2375 s32 j;
2376
2377 for (i = 0; i < encounter->count; i++) {
2378 Enemy* currentEnemy = encounter->enemy[i];
2379 if (currentEnemy == enemy) {
2380 break;
2381 }
2382 }
2383
2384 if (enemy->initScript != nullptr) {
2386 }
2387 if (enemy->interactScript != nullptr) {
2389 }
2390 if (enemy->aiScript != nullptr) {
2392 }
2393 if (enemy->hitScript != nullptr) {
2395 }
2396 if (enemy->auxScript != nullptr) {
2398 }
2399 if (enemy->defeatScript != nullptr) {
2401 }
2402
2403 enemy->interactBytecode = nullptr;
2404 enemy->aiBytecode = nullptr;
2405 enemy->hitBytecode = nullptr;
2406 enemy->auxBytecode = nullptr;
2407 enemy->defeatBytecode = nullptr;
2408
2409 #if DX_DEBUG_MENU
2410 if (enemy->npcID != (s16) DX_DEBUG_DUMMY_ID) {
2411 free_npc(get_npc_unsafe(enemy->npcID));
2412 }
2413 #else
2414 free_npc(get_npc_unsafe(enemy->npcID));
2415 #endif
2416
2417 if (enemy->unk_64 != nullptr) {
2418 heap_free(enemy->unk_64);
2419 }
2420
2421 for (j = 0; j < ARRAY_COUNT(encounter->enemy); j++) {
2422 if (encounter->enemy[j] == enemy) {
2423 encounter->enemy[j] = nullptr;
2424 }
2425 }
2426
2427 if (!(enemy->flags & ENEMY_FLAG_DO_NOT_KILL)
2428 && (!(enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) || (enemy == encounterStatus->curEnemy))
2429 && !(enemy->flags & ENEMY_FLAG_PASSIVE)
2430 && !(enemy->flags & ENEMY_FLAG_FLED)
2431 ) {
2432 COPY_set_defeated(encounterStatus->mapID, encounter->encounterID + i);
2433 }
2434
2435 heap_free(enemy);
2436}
2437
2439 Evt* aiScript;
2440 s32 id;
2441
2442 if (enemy->aiScript != nullptr) {
2443 kill_script_by_ID(enemy->aiScript->id);
2444 }
2446 aiScript = enemy->aiScript = start_script(aiScriptBytecode, EVT_PRIORITY_A, 0);
2447 id = enemy->aiScriptID = aiScript->id;
2448 aiScript->owner1.enemy = enemy;
2449 return id;
2450}
2451
2453 Evt* auxScript;
2454 s32 id;
2455
2456 if (enemy->auxScript != nullptr) {
2458 }
2460 auxScript = enemy->auxScript = start_script(auxScriptBytecode, EVT_PRIORITY_A, 0);
2461 id = enemy->auxScriptID = auxScript->id;
2462 auxScript->owner1.enemy = enemy;
2463 return id;
2464}
2465
2467 Evt* interactScript;
2468 s32 id;
2469
2470 if (enemy->interactScript != nullptr) {
2472 }
2475 id = enemy->interactScriptID = interactScript->id;
2476 interactScript->owner1.enemy = enemy;
2477 return id;
2478}
2479
2482 s32 i;
2483 s32 j;
2484
2485 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2487 if (currentEncounter != nullptr) {
2488 for (j = 0; j < currentEncounter->count; j++) {
2490 if ((currentEnemy != nullptr) && (currentEnemy->npcID == npcID)) {
2492 break;
2493 }
2494 }
2495 }
2496 }
2497}
2498
2501 s32 i;
2502 s32 j;
2503
2504 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2506 if (currentEncounter != nullptr) {
2507 for (j = 0; j < currentEncounter->count; j++) {
2509 if ((currentEnemy != nullptr) && (currentEnemy->npcID == npcID)) {
2511 break;
2512 }
2513 }
2514 }
2515 }
2516}
2517
2520 s32 i;
2521 s32 j;
2522
2523 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2525 if (currentEncounter != nullptr) {
2526 for (j = 0; j < currentEncounter->count; j++) {
2528 if ((currentEnemy != nullptr) && (currentEnemy->npcID == npcID)) {
2530 break;
2531 }
2532 }
2533 }
2534 }
2535}
2536
2539 s32 i;
2540 s32 j;
2541
2542 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2544 if (currentEncounter != nullptr) {
2545 for (j = 0; j < currentEncounter->count; j++) {
2547 if ((currentEnemy != nullptr) && (currentEnemy->npcID == npcID)) {
2548 return currentEnemy;
2549 }
2550 }
2551 }
2552 }
2553 PANIC();
2554}
2555
2558 s32 i;
2559 s32 j;
2560
2561 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2563
2564 if (currentEncounter != nullptr) {
2565 for (j = 0; j < currentEncounter->count; j++) {
2567 if ((currentEnemy != nullptr) && (currentEnemy->npcID == npcID)) {
2568 return currentEnemy;
2569 }
2570 }
2571 }
2572 }
2573 return nullptr;
2574}
BSS s32 PopupMenu_SelectedIndex
PalSwapState
Npc * NpcList[64]
#define MAX_NPC_DECORATIONS
#define NPC_BLUR_FRAMES
s16 entityModelID
#define PAL_PTR
s32 b32
f32 Matrix4f[4][4]
Vec3f scale
Bytecode EvtScript[]
u32 AnimID
union Evt::@10 owner1
Initially -1.
s8 index
Current blur ring buffer index.
Ring buffer of an NPC's position over the past 20 frames.
s8 flags
Definition demo_api.c:15
#define transform_point
#define guRotateF
#define queue_render_task
#define sqrtf
#define npc_raycast_down_sides
#define guTranslateF
#define guMtxCatF
#define remove_effect
#define clamp_angle
#define mdl_get_shroud_tint_params
#define atan2
#define guScaleF
f32 renderYaw
Definition effects.h:1013
struct StarsOrbitingFXData * starsOrbiting
Definition effects.h:2511
s32 fadeTime
Definition effects.h:999
Vec2f scale
Definition effects.h:996
Vec3f posA
Definition effects.h:994
EffectInstanceDataPtr data
Definition effects.h:2605
@ FX_AURA_BLUE
Definition effects.h:988
struct EnergyOrbWaveFXData * energyOrbWave
Definition effects.h:2546
struct AuraFXData * aura
Definition effects.h:2523
#define ASSERT(condition)
EntityModel * get_entity_model(s32 idx)
@ ENTITY_MODEL_FLAG_REFLECT
Definition enums.h:4604
@ IMGFX_SET_ALPHA
Definition enums.h:4709
@ IMGFX_RESET
Definition enums.h:4705
@ IMGFX_HOLOGRAM
Definition enums.h:4715
@ IMGFX_SET_COLOR
Definition enums.h:4708
@ IMGFX_OVERLAY_XLU
Definition enums.h:4718
@ IMGFX_OVERLAY
Definition enums.h:4717
@ IMGFX_CLEAR
Definition enums.h:4702
@ IMGFX_SET_WAVY
Definition enums.h:4706
@ IMGFX_ALLOC_COLOR_BUF
Definition enums.h:4719
@ IMGFX_FILL_COLOR
Definition enums.h:4716
@ IMGFX_COLOR_BUF_SET_MODULATE
Definition enums.h:4714
@ IMGFX_SET_CREDITS_FADE
Definition enums.h:4712
@ IMGFX_SET_TINT
Definition enums.h:4710
@ IMGFX_SET_WHITE_FADE
Definition enums.h:4711
@ IMGFX_SET_ANIM
Definition enums.h:4707
@ IMGFX_UNK_2
Definition enums.h:4704
@ IMGFX_UNK_1
Definition enums.h:4703
@ NPC_DECORATION_WHITE_GLOW_BEHIND
Definition enums.h:1949
@ NPC_DECORATION_BOWSER_AURA
Definition enums.h:1945
@ NPC_DECORATION_CHARGED
Definition enums.h:1950
@ NPC_DECORATION_SWEAT
Definition enums.h:1946
@ NPC_DECORATION_NONE
Definition enums.h:1944
@ NPC_DECORATION_WHITE_GLOW_FRONT
Definition enums.h:1948
@ NPC_DECORATION_SEEING_STARS
Definition enums.h:1947
@ NPC_PAL_ADJUST_NONE
Definition enums.h:1954
@ NPC_PAL_ADJUST_BLEND_DOUBLE_PALETTES
Definition enums.h:1958
@ NPC_PAL_ADJUST_BLEND_PALETTES_UNIFORM_INTERVALS
Definition enums.h:1956
@ NPC_PAL_ADJUST_BLEND_PALETTES_VARYING_INTERVALS
Definition enums.h:1957
@ NPC_PAL_ADJUST_WATT_IDLE
Definition enums.h:1955
@ ENCOUNTER_FLAG_NONE
Definition enums.h:4571
@ SHADOW_VARYING_CIRCLE
Definition enums.h:2521
@ PS_FLAG_FALLING
Definition enums.h:3070
@ PS_FLAG_JUMPING
Definition enums.h:3069
@ PARTNER_ACTION_NONE
Definition enums.h:2966
@ ENEMY_FLAG_DO_NOT_KILL
Definition enums.h:4108
@ ENEMY_FLAG_PASSIVE
Definition enums.h:4106
@ ENEMY_FLAG_FLED
Definition enums.h:4110
@ ENEMY_FLAG_ENABLE_HIT_SCRIPT
Definition enums.h:4109
@ COLLIDER_FLAG_IGNORE_PLAYER
Definition enums.h:4281
@ COLLIDER_FLAG_IGNORE_SHELL
Definition enums.h:4280
@ COLLISION_IGNORE_ENTITIES
Definition enums.h:4283
@ COLLIDER_FLAG_IGNORE_NPC
Definition enums.h:4282
@ PA_FLAG_NPC_COLLIDED
Definition enums.h:3140
@ PA_FLAG_RIDING_PARTNER
Definition enums.h:3150
@ CONTEXT_WORLD
Definition enums.h:3562
@ RENDER_MODE_SURFACE_XLU_LAYER2
Definition enums.h:3321
@ RENDER_MODE_ALPHATEST
Definition enums.h:3310
@ RENDER_MODE_SURFACE_XLU_LAYER1
Definition enums.h:3316
@ ENTITY_FLAG_HIDDEN
Definition enums.h:2599
@ ENCOUNTER_STATE_POST_BATTLE
Definition enums.h:5884
@ ENCOUNTER_STATE_CONVERSATION
Definition enums.h:5883
@ ENCOUNTER_STATE_NEUTRAL
Definition enums.h:5881
@ ENCOUNTER_STATE_NONE
Definition enums.h:5879
@ ENCOUNTER_STATE_PRE_BATTLE
Definition enums.h:5882
@ ENCOUNTER_STATE_CREATE
Definition enums.h:5880
@ FIRST_STRIKE_NONE
Definition enums.h:3492
@ GLOBAL_OVERRIDES_800
Definition enums.h:3915
@ GLOBAL_OVERRIDES_PREV_400
Definition enums.h:3918
@ GLOBAL_OVERRIDES_400
Definition enums.h:3914
@ GLOBAL_OVERRIDES_PREV_800
Definition enums.h:3919
@ ENCOUNTER_SUBSTATE_CREATE_INIT
Definition enums.h:5888
@ NPC_FLAG_IGNORE_ENTITY_COLLISION
Definition enums.h:3047
@ NPC_FLAG_WORLD_COLLISION_DIRTY
Definition enums.h:3059
@ NPC_FLAG_FLYING
Definition enums.h:3035
@ NPC_FLAG_HAS_NO_SPRITE
Definition enums.h:3056
@ NPC_FLAG_HAS_SHADOW
Definition enums.h:3036
@ NPC_FLAG_SUSPENDED
Definition enums.h:3063
@ NPC_FLAG_ENABLED
Definition enums.h:3032
@ NPC_FLAG_REFLECT_WALL
Definition enums.h:3049
@ NPC_FLAG_JUMPING
Definition enums.h:3043
@ NPC_FLAG_MOTION_BLUR
Definition enums.h:3052
@ NPC_FLAG_TOUCHES_GROUND
Definition enums.h:3054
@ NPC_FLAG_IGNORE_WORLD_COLLISION
Definition enums.h:3038
@ NPC_FLAG_INACTIVE
Definition enums.h:3034
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
Definition enums.h:3040
@ NPC_FLAG_COLLDING_FORWARD_WITH_WORLD
Definition enums.h:3046
@ NPC_FLAG_UPSIDE_DOWN
Definition enums.h:3039
@ NPC_FLAG_FLIP_INSTANTLY
Definition enums.h:3053
@ NPC_FLAG_COLLIDING_WITH_NPC
Definition enums.h:3057
@ NPC_FLAG_DIRTY_SHADOW
Definition enums.h:3048
@ NPC_FLAG_GRAVITY
Definition enums.h:3041
@ NPC_FLAG_PARTNER
Definition enums.h:3058
@ NPC_FLAG_INVISIBLE
Definition enums.h:3033
@ NPC_FLAG_NO_SHADOW_RAYCAST
Definition enums.h:3037
@ NPC_FLAG_HIDING
Definition enums.h:3055
@ NPC_FLAG_GROUNDED
Definition enums.h:3044
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
Definition enums.h:3050
@ NPC_FLAG_COLLDING_WITH_WORLD
Definition enums.h:3045
@ NPC_FLAG_DONT_UPDATE_SHADOW_Y
Definition enums.h:3042
@ NPC_FLAG_NO_ANIMS_LOADED
Definition enums.h:3062
@ NPC_FLAG_REFLECT_FLOOR
Definition enums.h:3051
@ EVT_PRIORITY_A
Definition evt.h:154
void create_encounters(void)
Definition encounter.c:2460
void update_encounters_conversation(void)
Definition encounter.c:2262
b32 entity_raycast_down(f32 *, f32 *, f32 *, f32 *, f32 *, f32 *)
Mostly used for shadows.
Definition entity.c:1634
Entity * get_entity_by_index(s32 index)
Definition entity.c:530
void update_encounters_neutral(void)
Definition encounter.c:480
f32 fabsf(f32 f)
b32 npc_raycast_down_around(s32, f32 *, f32 *, f32 *, f32 *, f32, f32)
void show_first_strike_message(void)
Definition encounter.c:1562
void update_encounters_post_battle(void)
Definition encounter.c:1618
s32 npc_test_move_complex_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
Shadow * get_shadow_by_index(s32 index)
Definition entity.c:534
void init_encounters_ui(void)
Definition encounter.c:2812
void func_80045AC0(void)
f32 cosine(s16 arg0)
Definition 43F0.c:352
f32 cos_rad(f32 x)
Definition 43F0.c:717
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
void update_encounters_pre_battle(void)
Definition encounter.c:1260
s32 create_worker_scene(void(*updateFunc)(void), void(*renderFunc)(void))
Definition worker.c:32
s32 heap_free(void *ptr)
Definition heap.c:42
b32 npc_test_move_simple_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
Evt * start_script(EvtScript *source, s32 priority, s32 initialState)
b32 npc_test_move_taller_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
void draw_encounters_pre_battle(void)
Definition encounter.c:1486
void kill_script_by_ID(s32 id)
s32 create_shadow_type(s32 type, f32 x, f32 y, f32 z)
Definition entity.c:1525
void draw_merlee_messages(void)
void draw_encounters_conversation(void)
Definition encounter.c:2318
void update_merlee_messages(void)
void draw_encounters_neutral(void)
Definition encounter.c:1257
f32 sin_rad(f32 x)
Definition 43F0.c:713
void draw_encounters_post_battle(void)
Definition encounter.c:2252
void delete_shadow(s32)
Definition entity.c:626
void set_npc_shadow_scale(Shadow *shadow, f32 height, f32 npcRadius)
Definition entity.c:1684
f32 get_clamped_angle_diff(f32, f32)
Definition 43F0.c:606
void * heap_malloc(s32 size)
Definition heap.c:34
void npc_render_without_adjusted_palettes(Npc *npc, s32 arg1, Matrix4f mtx)
Definition npc.c:1318
void STUB_npc_callback(Npc *npc)
The default Npc::onUpdate and Npc::onRender callback.
Definition npc.c:48
s32 npc_try_snap_to_ground(Npc *npc, f32 velocity)
Definition npc.c:580
void npc_update_decoration_charged(Npc *npc, s32 idx)
Definition npc.c:1929
void free_npc(Npc *npc)
Definition npc.c:236
s32 create_basic_npc(NpcBlueprint *blueprint)
Definition npc.c:189
void npc_update_decoration_seeing_stars(Npc *npc, s32 idx)
Definition npc.c:1864
void npc_remove_decoration_glow_in_front(Npc *npc, s32 idx)
Definition npc.c:1903
void npc_imgfx_update(Npc *npc)
Definition npc.c:2090
void disable_npc_blur(Npc *npc)
Definition npc.c:1085
s32 create_npc_impl(NpcBlueprint *blueprint, AnimID *animList, s32 isPeachNpc)
Definition npc.c:87
s32 bind_enemy_ai(Enemy *enemy, EvtScript *aiScriptBytecode)
Binds the specified ai script to the specified enemy.
Definition npc.c:2438
void npc_reload_all(void)
Definition npc.c:1205
s32 bind_enemy_aux(Enemy *enemy, EvtScript *auxScriptBytecode)
Binds the specified auxillary script to the specified enemy.
Definition npc.c:2452
void appendGfx_npc_blur(void *data)
Definition npc.c:1110
Enemy * get_enemy_safe(s32 npcID)
Same as get_enemy(), with the exception of always returning a value if an enemy is not found.
Definition npc.c:2556
s32 npc_find_standing_on_entity(s32 entityIndex)
Definition npc.c:2018
void npc_set_imgfx_params(Npc *npc, s32 imgfxType, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6)
Definition npc.c:2159
void npc_remove_decoration_sweat(Npc *npc, s32 idx)
Definition npc.c:1861
void kill_enemy(Enemy *enemy)
Definition npc.c:2371
Enemy * get_enemy(s32 npcID)
Looks for an enemy matching the specified npcID.
Definition npc.c:2537
void npc_do_other_npc_collision(Npc *npc)
Definition npc.c:380
void func_8003E50C(void)
Definition npc.c:2260
void bind_npc_ai(s32 npcID, EvtScript *npcAiBytecode)
Binds the specified ai script to the npc matching the specified npcId.
Definition npc.c:2480
#define RGBA_BUF_SIZE
void npc_disable_collisions(void)
Definition npc.c:1198
void npc_set_palswap_1(Npc *npc, s32 palIndexA, s32 palIndexB, s32 timeHoldA, s32 timeAB)
Definition npc.c:1284
u8 wWattIdlePalettesAnim[]
Definition npc.c:31
void enable_npc_shadow(Npc *npc)
Definition npc.c:1024
void npc_remove_decoration_bowser_aura(Npc *npc, s32 idx)
Definition npc.c:1836
@ WATT_BRIGHTER
Definition npc.c:28
@ WATT_DEFAULT
Definition npc.c:26
@ WATT_BRIGHTEST
Definition npc.c:27
s32 create_peach_npc(NpcBlueprint *blueprint)
Definition npc.c:197
void npc_try_apply_gravity(Npc *npc)
Definition npc.c:540
void update_encounters(void)
Definition npc.c:2267
Npc * npc_find_closest_simple(f32 x, f32 y, f32 z, f32 radius)
Finds the closest simple-hitbox NPC to a given point within a radius.
Definition npc.c:1992
void enable_npc_blur(Npc *npc)
Definition npc.c:1064
@ PAL_SWAP_HOLD_A
Definition npc.c:18
@ PAL_SWAP_HOLD_B
Definition npc.c:20
@ PAL_SWAP_B_TO_A
Definition npc.c:21
@ PAL_SWAP_A_TO_B
Definition npc.c:19
s32 create_standard_npc(NpcBlueprint *blueprint, AnimID *animList)
Definition npc.c:193
void init_npc_list(void)
Points the current NPC list to the world or battle lists depending on game state.
Definition npc.c:76
void npc_render_with_watt_idle_palettes(Npc *npc, s32 arg1, Matrix4f mtx)
Definition npc.c:1340
void disable_npc_shadow(Npc *npc)
Definition npc.c:1034
void npc_draw_with_palswap(Npc *npc, s32 yaw, Matrix4f mtx)
Definition npc.c:1298
void free_npc_by_index(s32 listIndex)
Definition npc.c:201
void func_8003E514(s8 arg0)
Definition npc.c:2263
void clear_npcs(void)
Definition npc.c:59
void npc_revert_palswap_mode(Npc *npc)
Definition npc.c:1273
void make_npcs(s32 flags, s32 mapID, s32 *npcGroupList)
Definition npc.c:2328
void npc_set_decoration(Npc *npc, s32 idx, s32 decorationType)
Definition npc.c:1731
void render_npcs(void)
Renders all NPCs.
Definition npc.c:931
void npc_set_palswap_mode_A(Npc *npc, s32 mode)
Definition npc.c:1255
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:992
void npc_set_palswap_2(Npc *npc, s32 timeHoldB, s32 timeBA, s32 palIndexC, s32 palIndexD)
Definition npc.c:1291
void npc_enable_collisions(void)
Definition npc.c:1194
void npc_render_worker_do_nothing(void)
Definition npc.c:2325
void npc_remove_decoration_none(Npc *npc, s32 idx)
Definition npc.c:1813
void npc_update_decoration_glow_in_front(Npc *npc, s32 idx)
Definition npc.c:1885
Npc * npc_find_closest(f32 x, f32 y, f32 z, f32 radius)
Finds the closest NPC to a given point within a radius.
Definition npc.c:1966
void npc_reset_current_decoration(Npc *npc, s32 idx)
Definition npc.c:1795
#define PAL_ANIM_END
Definition npc.c:15
void mtx_ident_mirror_y(Matrix4f mtx)
Definition npc.c:51
void npc_do_world_collision(Npc *npc)
Definition npc.c:277
void bind_npc_aux(s32 npcID, EvtScript *npcAuxBytecode)
Binds the specified auxillary script to the npc matching the specified npcId.
Definition npc.c:2499
void update_npcs(void)
Updates all NPCs.
Definition npc.c:616
void npc_set_palswap_mode_B(Npc *npc, s32 mode)
Definition npc.c:1264
void npc_render_with_single_pal_blending(Npc *npc, s32 yaw, b32 hasDifferentIntervals, Matrix4f mtx)
Definition npc.c:1445
void bind_npc_interact(s32 npcID, EvtScript *npcInteractBytecode)
Binds the specified interact script to the npc matching the specified npcId.
Definition npc.c:2518
void npc_update_decorations(Npc *npc)
Definition npc.c:1765
Npc * get_npc_by_index(s32 listIndex)
Definition npc.c:270
void clear_encounter_status(void)
Definition npc.c:2221
void draw_first_strike_ui(void)
Definition npc.c:2315
void npc_remove_decoration(Npc *npc, s32 idx)
Definition npc.c:1738
void npc_update_decoration_bowser_aura(Npc *npc, s32 idx)
Definition npc.c:1816
void npc_remove_decoration_glow_behind(Npc *npc, s32 idx)
Definition npc.c:1925
f32 npc_get_render_yaw(Npc *npc)
Definition npc.c:744
void npc_render_with_double_pal_blending(Npc *npc, s32 yaw, Matrix4f mtx)
Definition npc.c:1581
void kill_encounter(Enemy *enemy)
Definition npc.c:2358
s32 npc_do_player_collision(Npc *npc)
Definition npc.c:442
void npc_remove_decoration_charged(Npc *npc, s32 idx)
Definition npc.c:1963
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
Definition npc.c:983
void update_npc_blur(Npc *npc)
Definition npc.c:1094
void appendGfx_npc(void *data)
Definition npc.c:808
void COPY_set_defeated(s32 mapID, s32 encounterID)
Duplicate of set_defeated().
Definition npc.c:2169
void func_8003B1A8(void)
Definition npc.c:1202
u16 npc_blend_palette_colors(u16 colorA, u16 colorB, s32 lerpAlpha)
Definition npc.c:1436
void draw_encounter_ui(void)
Definition npc.c:2291
void set_npc_yaw(Npc *npc, f32 yaw)
Definition npc.c:1243
s32 npc_get_collider_below(Npc *npc)
Definition npc.c:2066
void set_npc_sprite(Npc *npc, s32 anim, AnimID *extraAnimList)
Definition npc.c:1045
void init_encounter_status(void)
Definition npc.c:2188
void npc_update_decoration_glow_behind(Npc *npc, s32 idx)
Definition npc.c:1907
s16 gNpcCount
Definition npc.c:9
void npc_update_decoration_sweat(Npc *npc, s32 idx)
Definition npc.c:1840
void npc_remove_decoration_seeing_stars(Npc *npc, s32 idx)
Definition npc.c:1881
s32 bind_enemy_interact(Enemy *enemy, EvtScript *interactScriptBytecode)
Binds the specified interact script to the specified enemy.
Definition npc.c:2466
void npc_update_decoration_none(Npc *npc, s32 idx)
Definition npc.c:1810
Npc * get_npc_safe(s32 npcID)
Definition npc.c:1007
s8 resetMapEncounterFlags
Definition npc.h:389
struct Evt * interactScript
Definition npc.h:312
s32 flags
Definition npc.h:295
s16 npcID
Definition npc.h:300
s32 interactScriptID
Definition npc.h:318
struct Evt * hitScript
Definition npc.h:314
EvtScript * hitBytecode
Definition npc.h:308
s8 encounterIndex
Definition npc.h:296
s32 auxScriptID
Definition npc.h:321
s32 initScriptID
Definition npc.h:317
Encounter * encounterList[24]
Definition npc.h:392
struct Evt * defeatScript
Definition npc.h:316
EvtScript * interactBytecode
Definition npc.h:306
s32 aiScriptID
Definition npc.h:319
struct Evt * initScript
Definition npc.h:311
s32 defeatScriptID
Definition npc.h:322
EncounterStatus gCurrentEncounter
Definition encounter.c:175
struct Evt * auxScript
Definition npc.h:315
s32 defeatFlags[60][12]
Definition npc.h:403
void * unk_64
Definition npc.h:323
EvtScript * defeatBytecode
Definition npc.h:310
EvtScript * aiBytecode
Definition npc.h:307
struct Evt * aiScript
Definition npc.h:313
EvtScript * auxBytecode
Definition npc.h:309
s32 hitScriptID
Definition npc.h:320
Definition npc.h:294
Npc * wPartnerNpc
Definition partners.c:43
#define UNPACK_PAL_B(color)
Definition macros.h:280
#define UNPACK_PAL_R(color)
Definition macros.h:278
#define SPRITE_WORLD_SCALE_D
Definition macros.h:151
#define UNPACK_PAL_A(color)
Definition macros.h:281
#define COLLISION_WITH_ENTITY_BIT
Definition macros.h:163
#define ARRAY_COUNT(arr)
Definition macros.h:39
#define UNPACK_PAL_G(color)
Definition macros.h:279
#define SPR_PAL_SIZE
Definition macros.h:153
#define PACK_PAL_RGBA(r, g, b, a)
Definition macros.h:283
#define PANIC()
Definition macros.h:54
#define DEG_TO_RAD(deg)
Definition macros.h:145
#define BATTLE_NPC_ID_BIT
Definition macros.h:156
#define SQ(x)
Definition macros.h:177
#define MAX_NPCS
Definition macros.h:90
#define NO_COLLIDER
Definition macros.h:167
s32 spr_get_notify_value(s32 spriteInstanceID)
Definition sprite.c:1158
s32 spr_update_sprite(s32 spriteInstanceID, s32 animID, f32 timeScale)
Definition sprite.c:1061
s32 spr_free_sprite(s32 spriteInstanceID)
Definition sprite.c:1162
void set_npc_imgfx_all(s32 spriteIdx, ImgFXType imgfxType, s32 imgfxArg1, s32 imgfxArg2, s32 imgfxArg3, s32 imgfxArg4, s32 imgfxArg5)
Definition sprite.c:1238
s32 spr_get_npc_color_variations(s32 npcSpriteID)
Definition sprite.c:1306
s32 spr_draw_npc_sprite(s32 spriteInstanceID, s32 yaw, s32 alphaIn, PAL_PTR *paletteList, Matrix4f mtx)
Definition sprite.c:1094
PAL_PTR * spr_get_npc_palettes(s32 npcSpriteID)
Definition sprite.c:1296
s32 func_802DDEC4(s32 spriteIdx)
Definition sprite.c:954
s32 spr_load_npc_sprite(s32 animID, u32 *extraAnimList)
Definition sprite.c:1015
s32 spr_draw_player_sprite(s32 spriteInstanceID, s32 yaw, s32 alphaIn, PAL_PTR *paletteList, Matrix4f mtx)
Definition sprite.c:867
s32 spr_update_player_sprite(s32 spriteInstanceID, s32 animID, f32 timeScale)
Definition sprite.c:820
@ DRAW_SPRITE_OVERRIDE_YAW
Definition sprite.h:25
@ DRAW_SPRITE_OVERRIDE_ALPHA
Definition sprite.h:26
@ DRAW_SPRITE_OVERRIDE_PALETTES
Definition sprite.h:24
@ PLAYER_SPRITE_AUX1
Definition sprite.h:31
@ SPRITE_ID_TAIL_ALLOCATE
Definition sprite.h:18
void(* onRender)(struct Npc *)
Definition npc.h:89
void(* onUpdate)(struct Npc *)
Definition npc.h:88
s32 initialAnim
Definition npc.h:87
s32 flags
Definition npc.h:86
struct EffectInstance * decorations[2]
s8 palAnimState
s16 palswapTimeBtoA
s16 collisionDiameter
void(* onUpdate)(struct Npc *)
Run before anything else for this NPC in update_npcs()
s16 imgfxArg2
f32 jumpScale
Vec3f scale
s16 blendPalB
s16 imgfxArg3
s16 nextPalTime
f32 jumpVel
f32 animationSpeed
s16 palswapTimeAtoB
s8 renderMode
s16 unk_96
s16 imgfxType
s32 flags
f32 renderYaw
s16 blendPalC
s8 changedDecoration[2]
s8 decorationType[2]
s32 spriteInstanceID
AnimID curAnim
s8 palSwapType
f32 shadowScale
s16 palBlendAlpha
u8 hideAlpha
Used when hiding NPCs; Multiplied with Npc::alpha.
f32 screenSpaceOffset2D[2]
s8 originalPalettesCount
s16 blendPalA
s32 collisionChannel
b16 isFacingAway
u16 ** originalPalettesList
u16 * adjustedPalettes[16]
Vec3f colliderPos
s16 collisionHeight
s8 resetPalAdjust
s16 turnAroundYawAdjustment
Vec3f rot
s8 verticalRenderOffset
s16 yawCamOffset
u16 imgfxFlags
s8 palSwapPrevType
s16 decorationGlowPhase[2]
s32 animNotifyValue
Vec3f pos
f32 verticalStretch
AnimID * extraAnimList
s16 curFloor
f32 rotPivotOffsetY
s16 imgfxArg4
f32 moveSpeed
Vec3s homePos
s16 imgfxArg1
s8 decorationInitialized[2]
u16 palswapTimeHoldA
s16 blendPalD
union Npc::@0 blur
s16 curWall
s8 spriteColorVariations
s32 shadowIndex
s16 palswapTimeHoldB
void(* onRender)(struct Npc *)
Run after the display list for this NPC is built.
u16 copiedPalettes[16][16]
s32 gOverrideFlags
Definition main_loop.c:10
PartnerStatus gPartnerStatus
Definition partners.c:42
GameStatus * gGameStatusPtr
Definition main_loop.c:31
s32 NpcHitQueryColliderID
Camera gCameras[4]
Definition cam_main.c:16
PlayerStatus gPlayerStatus
Definition 77480.c:38
s32 gCurrentCameraID
Definition cam_math.c:5
s32 gEncounterState
Definition encounter.c:173
b32 EncounterStateChanged
Definition encounter.c:23
s16 gCurrentCamID
Definition cam_main.c:12
s32 gEncounterSubState
Definition encounter.c:174