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] = NULL;
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
87s32 create_npc_impl(NpcBlueprint* blueprint, AnimID* animList, s32 isPeachNpc) {
88 Npc* npc;
89 s32 i;
90 s32 j;
91
92 for (i = 0; i < MAX_NPCS; i++) {
93 if ((*gCurrentNpcListPtr)[i] == NULL) {
94 break;
95 }
96 }
97 ASSERT(i < MAX_NPCS);
98
99 (*gCurrentNpcListPtr)[i] = npc = heap_malloc(sizeof(*npc));
100 gNpcCount++;
101 ASSERT(npc != NULL);
102
104 if (isPeachNpc) {
106 }
107
108 npc->collisionDiameter = 32;
109 npc->collisionHeight = 64;
110 npc->renderMode = 13;
111 npc->blur.any = NULL;
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 == NULL) {
161 }
162
163 npc->onRender = blueprint->onRender;
164 if (npc->onRender == NULL) {
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, NULL, FALSE);
191}
192
193s32 create_standard_npc(NpcBlueprint* blueprint, AnimID* animList) {
194 return create_npc_impl(blueprint, animList, FALSE);
195}
196
198 return create_npc_impl(blueprint, NULL, 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 != NULL) {
209 if (npc->flags) {
210 if (npc->blur.any != NULL) {
211 heap_free(npc->blur.any);
212 npc->blur.any = NULL;
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] = NULL;
231 gNpcCount--;
232 }
233 }
234}
235
236void free_npc(Npc* npc) {
237 s32 i;
238
239 if (npc->blur.any != NULL) {
240 heap_free(npc->blur.any);
241 npc->blur.any = NULL;
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] = NULL;
267 gNpcCount--;
268}
269
270Npc* get_npc_by_index(s32 listIndex) {
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;
389 s32 collision;
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 != NULL && 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)) {
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 != NULL) {
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) {
932 Npc* npc;
936 f32 x, y, z, s;
938 s32 i;
939
940 for (i = 0; i < MAX_NPCS; i++) {
941 Npc* npc = (*gCurrentNpcListPtr)[i];
942 if ((npc != NULL)
943 && (npc->flags != 0)
945 ) {
946 transform_point(cam->mtxPerspective, npc->pos.x, npc->pos.y, npc->pos.z, 1.0f, &x, &y, &z, &s);
947 if (!(s < 0.01) || !(s > -0.01)) {
948 renderDist = ((z * 5000.0f) / s) + 5000.0f;
949 if (renderDist < 0.0f) {
950 renderDist = 0.0f;
951 } else if (renderDist > 10000.0f) {
952 renderDist = 10000.0f;
953 }
954
955 renderTaskPtr->dist = -renderDist;
956 renderTaskPtr->appendGfxArg = npc;
957 renderTaskPtr->appendGfx = appendGfx_npc;
959
960 if (npc->flags & NPC_FLAG_HIDING) {
961 u8 r, g, b, a;
962 mdl_get_shroud_tint_params(&r, &g, &b, &a);
963 npc->hideAlpha = 255 - a;
964 } else {
965 npc->hideAlpha = 255;
966 }
967
968 if (npc->hideAlpha != 0) {
970 }
971
972 if (npc->flags & NPC_FLAG_MOTION_BLUR) {
973 renderTaskPtr->dist = -renderDist;
975 renderTaskPtr->appendGfxArg = npc;
978 }
979 }
980 }
981 }
982}
983
984void npc_move_heading(Npc* npc, f32 speed, f32 yaw) {
985 f32 angle = DEG_TO_RAD(yaw);
986 f32 sin = sin_rad(angle);
987 f32 cos = cos_rad(angle);
988
989 npc->pos.x += speed * sin;
990 npc->pos.z += -speed * cos;
991}
992
993Npc* get_npc_unsafe(s32 npcID) {
994 s32 i;
995 Npc* npc;
996
997 for (i = 0; i < MAX_NPCS; i++) {
998 npc = (*gCurrentNpcListPtr)[i];
999 if (npc != NULL && npc->flags != 0 && npc->npcID == npcID) {
1000 break;
1001 }
1002 }
1003 ASSERT(i < MAX_NPCS);
1004
1005 return npc;
1006}
1007
1008Npc* get_npc_safe(s32 npcID) {
1009 s32 i;
1010 Npc* npc;
1011
1012 for (i = 0; i < MAX_NPCS; i++) {
1013 npc = (*gCurrentNpcListPtr)[i];
1014 if (npc != NULL && npc->flags != 0 && npc->npcID == npcID) {
1015 break;
1016 }
1017 }
1018 if (i >= MAX_NPCS) {
1019 return NULL;
1020 }
1021
1022 return npc;
1023}
1024
1026 Shadow* shadow;
1027
1028 if (!(npc->flags & NPC_FLAG_HAS_SHADOW)) {
1029 shadow = get_shadow_by_index(npc->shadowIndex);
1030 shadow->flags &= ~ENTITY_FLAG_HIDDEN;
1032 }
1033}
1034
1036 Shadow* shadow;
1037
1038 if (npc->flags & NPC_FLAG_HAS_SHADOW) {
1039 shadow = get_shadow_by_index(npc->shadowIndex);
1040 shadow->flags |= ENTITY_FLAG_HIDDEN;
1043 }
1044}
1045
1046void set_npc_sprite(Npc* npc, s32 anim, AnimID* extraAnimList) {
1048
1049 npc->extraAnimList = extraAnimList;
1050
1051 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1052 npc->spriteInstanceID = spr_load_npc_sprite(anim, extraAnimList);
1053 ASSERT(npc->spriteInstanceID >= 0);
1054 }
1055
1056 npc->curAnim = anim;
1057
1058 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1059 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1061 }
1062 }
1063}
1064
1066 if (!(npc->flags & NPC_FLAG_MOTION_BLUR)) {
1068 s32 i;
1069
1071
1072 motionBlur = heap_malloc(sizeof(*motionBlur));
1073 npc->blur.motion = motionBlur;
1075 motionBlur->unused = 0;
1076 motionBlur->index = 0;
1077
1078 for (i = 0; i < ARRAY_COUNT(motionBlur->posX); i++) {
1079 motionBlur->posX[i] = npc->pos.x;
1080 motionBlur->posY[i] = npc->pos.y;
1081 motionBlur->posZ[i] = npc->pos.z;
1082 }
1083 }
1084}
1085
1087 if (npc->flags & NPC_FLAG_MOTION_BLUR) {
1089
1090 heap_free(npc->blur.motion);
1091 npc->blur.motion = NULL;
1092 }
1093}
1094
1096 NpcMotionBlur* motionBlur = npc->blur.motion;
1097 s32 index = motionBlur->index;
1098
1099 motionBlur->posX[index] = npc->pos.x;
1100 motionBlur->posY[index] = npc->pos.y;
1101 motionBlur->posZ[index] = npc->pos.z;
1102
1103 index++;
1104 if (index >= 20) {
1105 index = 0;
1106 }
1107
1108 motionBlur->index = index;
1109}
1110
1111void appendGfx_npc_blur(void* data) {
1112 Npc* npc = (Npc*) data;
1113 Matrix4f mtx, tempMtx;
1114 f32 x, y, z;
1115 f32 yaw;
1116 s32 strideIdx;
1117 s32 drawIdx;
1118 s32 bufPos;
1119 NpcMotionBlur* blur;
1120
1121 strideIdx = 0;
1122 drawIdx = 0;
1123 blur = npc->blur.motion;
1124 bufPos = blur->index;
1125
1126 while (TRUE) {
1127 bufPos--;
1128 strideIdx++;
1129
1130 if (bufPos < 0) {
1131 bufPos = NPC_BLUR_FRAMES - 1;
1132 }
1133
1134 if (bufPos == blur->index) {
1135 break;
1136 }
1137
1138 // only draw every third blur frame
1139 if (strideIdx < 3) {
1140 continue;
1141 }
1142
1143 strideIdx = 0;
1144 drawIdx++;
1145
1146 // draw three blur samples
1147 if (drawIdx > 3) {
1148 break;
1149 }
1150
1151 x = blur->posX[bufPos];
1152 y = blur->posY[bufPos];
1153 z = blur->posZ[bufPos];
1154 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_ALPHA, 255, 255, 255, 120 - (drawIdx * 20), 0);
1155 yaw = npc->renderYaw;
1156 guTranslateF(mtx, x, y, z);
1157
1158 if (npc->rot.y != 0.0f) {
1159 guRotateF(tempMtx, npc->rot.y, 0.0f, 1.0f, 0.0f);
1160 guMtxCatF(tempMtx, mtx, mtx);
1161 }
1162 if (npc->rot.x != 0.0f) {
1163 guRotateF(tempMtx, npc->rot.y, 0.0f, 1.0f, 0.0f);
1164 guMtxCatF(tempMtx, mtx, mtx);
1165 }
1166 if (npc->rot.z != 0.0f) {
1167 guRotateF(tempMtx, npc->rot.y, 0.0f, 1.0f, 0.0f);
1168 guMtxCatF(tempMtx, mtx, mtx);
1169 }
1170
1171 if ((npc->scale.x * SPRITE_WORLD_SCALE_D) != 1.0
1172 || ((npc->scale.y * npc->verticalStretch) * SPRITE_WORLD_SCALE_D) != 1.0
1173 || (npc->scale.z * SPRITE_WORLD_SCALE_D) != 1.0
1174 ) {
1175 guScaleF(
1176 tempMtx,
1180 );
1181 guMtxCatF(tempMtx, mtx, mtx);
1182 }
1183
1184 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1185 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1186 spr_draw_npc_sprite(npc->spriteInstanceID, yaw, 0, 0, mtx);
1187 }
1188 } else {
1190 }
1191 }
1192 npc_imgfx_update(npc);
1193}
1194
1196 gNpcPlayerCollisionsEnabled = TRUE;
1197}
1198
1200 gNpcPlayerCollisionsEnabled = FALSE;
1201}
1202
1203void func_8003B1A8(void) {
1204}
1205
1206void npc_reload_all(void) {
1207 s32 i;
1208 s32 j;
1209
1210 for (i = 0; i < MAX_NPCS; i++) {
1211 Npc* npc = (*gCurrentNpcListPtr)[i];
1212 if (npc != NULL) {
1213 if (npc->flags && !(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1214 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1215 if (!(npc->flags & NPC_FLAG_PARTNER)) {
1217 } else {
1219 }
1220 }
1221 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1222 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE) && (npc->palSwapType != NPC_PAL_ADJUST_NONE)) {
1224 npc->originalPalettesCount = 0;
1225 while (npc->originalPalettesList[npc->originalPalettesCount] != (PAL_PTR) -1) {
1226 npc->originalPalettesCount++;
1227 }
1229 }
1230 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1231 if (!(npc->flags & NPC_FLAG_HAS_NO_SPRITE)) {
1232 for (j = 0; j < MAX_NPC_DECORATIONS; j++) {
1234 }
1235 npc_imgfx_update(npc);
1236 }
1237 }
1238 }
1239 }
1240 }
1241 }
1242}
1243
1244void set_npc_yaw(Npc* npc, f32 yaw) {
1245 npc->yaw = yaw;
1246
1247 if (get_clamped_angle_diff(gCameras[gCurrentCameraID].curYaw, yaw) >= 0.0f) {
1248 npc->yawCamOffset = 180;
1249 npc->isFacingAway = TRUE;
1250 } else {
1251 npc->yawCamOffset = 0;
1252 npc->isFacingAway = FALSE;
1253 }
1254}
1255
1256void npc_set_palswap_mode_A(Npc* npc, s32 mode) {
1257 if (npc->palSwapType != mode) {
1258 npc->palSwapPrevType = npc->palSwapType;
1259 npc->palSwapType = mode;
1261 npc->resetPalAdjust = 1;
1262 }
1263}
1264
1265void npc_set_palswap_mode_B(Npc* npc, s32 mode) {
1266 if (npc->palSwapType != mode) {
1267 npc->palSwapPrevType = npc->palSwapType;
1268 npc->palSwapType = mode;
1270 npc->resetPalAdjust = -1;
1271 }
1272}
1273
1277 return;
1278 }
1279 npc->palSwapType = npc->palSwapPrevType;
1282 npc->resetPalAdjust = 1;
1283}
1284
1286 npc->blendPalA = palIndexA;
1287 npc->blendPalB = palIndexB;
1289 npc->palswapTimeAtoB = timeAB;
1290}
1291
1294 npc->palswapTimeBtoA = timeBA;
1295 npc->blendPalC = palIndexC;
1296 npc->blendPalD = palIndexD;
1297}
1298
1299void npc_draw_with_palswap(Npc* npc, s32 yaw, Matrix4f mtx) {
1300 switch (npc->palSwapType) {
1303 break;
1306 break;
1309 break;
1312 break;
1315 break;
1316 }
1317}
1318
1320 if (npc->resetPalAdjust != 0) {
1321 npc->verticalStretch = 1.0f;
1322 npc->screenSpaceOffset2D[0] = 0.0f;
1323 npc->screenSpaceOffset2D[1] = 0.0f;
1324 npc->resetPalAdjust = 0;
1325 }
1326
1327 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1328 s32 alpha = (npc->alpha * npc->hideAlpha / 255);
1329 u32 mask;
1330 if (alpha < 255) {
1332 } else {
1333 mask = 0;
1334 }
1335 spr_draw_npc_sprite(npc->spriteInstanceID | mask, arg1, alpha, NULL, mtx);
1336 } else {
1338 }
1339}
1340
1342 s32 i, j;
1343 s32 brightness;
1344 PAL_PTR src;
1345 PAL_PTR dst;
1346
1347 if (npc->resetPalAdjust != 0) {
1349 npc->originalPalettesCount = 0;
1350 while ((s32)npc->originalPalettesList[npc->originalPalettesCount] != -1) {
1351 npc->originalPalettesCount++;
1352 }
1353
1355 for (i = 0; i < npc->originalPalettesCount; i++) {
1356 dst = npc->copiedPalettes[i];
1357 src = npc->originalPalettesList[i];
1358 if (src != NULL) {
1359 for (j = 0; j < SPR_PAL_SIZE; j++) {
1360 *dst++ = *src++;
1361 }
1362 }
1363 }
1364
1365 npc->palAnimState = -2;
1366 npc->palBlendAlpha = 0;
1367 npc->resetPalAdjust = 0;
1368 npc->nextPalTime = 0;
1369 }
1370
1371 if (npc->nextPalTime == 0) {
1372 npc->palAnimState += 2;
1373 brightness = wWattIdlePalettesAnim[npc->palAnimState];
1374 if (brightness == 255) {
1375 npc->palAnimState = 0;
1376 }
1377 npc->nextPalTime = wWattIdlePalettesAnim[npc->palAnimState + 1] / 2;
1378 }
1379
1380 brightness = wWattIdlePalettesAnim[npc->palAnimState];
1381 npc->nextPalTime--;
1382
1383 switch(brightness) {
1384 case WATT_DEFAULT:
1385 for (i = 0; i < npc->spriteColorVariations; i++) {
1386 dst = npc->copiedPalettes[i];
1387 src = npc->originalPalettesList[i];
1388 if (src != NULL) {
1389 for (j = 0; j < SPR_PAL_SIZE; j++) {
1390 *dst++ = *src++;
1391 }
1392 }
1393 }
1394 break;
1395 case WATT_BRIGHTEST:
1396 for (i = 0; i < npc->spriteColorVariations; i++) {
1397 // use watt's Brightest palettes
1398 dst = npc->copiedPalettes[i];
1400 if (src != NULL) {
1401 for (j = 0; j < SPR_PAL_SIZE; j++) {
1402 *dst++ = *src++;
1403 }
1404 }
1405 }
1406 break;
1407 case WATT_BRIGHTER:
1408 for (i = 0; i < npc->spriteColorVariations; i++) {
1409 // use watt's Brighter palettes
1410 dst = npc->copiedPalettes[i];
1412 if (src != NULL) {
1413 for (j = 0; j < SPR_PAL_SIZE; j++) {
1414 *dst++ = *src++;
1415 }
1416 }
1417 }
1418 break;
1419 }
1420
1421 for (i = 0; i < npc->originalPalettesCount; i++) {
1422 npc->adjustedPalettes[i] = npc->copiedPalettes[i];
1423 }
1424
1425 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1426 s32 alpha = npc->alpha * npc->hideAlpha / 255;
1427 u32 mask = 0;
1428 if (alpha < 255) {
1430 }
1433 }
1434 npc->palBlendAlpha--;
1435}
1436
1438 u8 r = (UNPACK_PAL_R(colorA) * (255 - lerpAlpha) + UNPACK_PAL_R(colorB) * lerpAlpha) / 255;
1439 u8 g = (UNPACK_PAL_G(colorA) * (255 - lerpAlpha) + UNPACK_PAL_G(colorB) * lerpAlpha) / 255;
1440 u8 b = (UNPACK_PAL_B(colorA) * (255 - lerpAlpha) + UNPACK_PAL_B(colorB) * lerpAlpha) / 255;
1441 u8 a = UNPACK_PAL_A(colorB);
1442
1443 return PACK_PAL_RGBA(r, g, b, a);
1444}
1445
1447 PAL_PTR color1;
1448 PAL_PTR color2;
1450 s32 i, j;
1451 s32 blendAlpha;
1452
1453 // copy palettes from sprite data
1454 if (npc->resetPalAdjust != 0) {
1455 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1457 }
1458
1459 npc->originalPalettesCount = 0;
1460 while ((s32)npc->originalPalettesList[npc->originalPalettesCount] != -1) {
1461 npc->originalPalettesCount++;
1462 }
1463
1464 if (npc->resetPalAdjust == 1) {
1466 npc->palBlendAlpha = 0;
1467 } else {
1469 npc->palBlendAlpha = 255;
1470 }
1471
1472 for (i = 0; i < npc->originalPalettesCount; i++) {
1473 color1 = npc->copiedPalettes[i];
1474 color2 = npc->originalPalettesList[i];
1475 npc->adjustedPalettes[i] = color1;
1476 if (color2 != NULL) {
1477 for (j = 0; j < SPR_PAL_SIZE; j++) {
1478 *color1++ = *color2++;
1479 }
1480 }
1481 }
1482
1483 if (!hasDifferentIntervals) {
1486 npc->palswapTimeBtoA = npc->palswapTimeAtoB;
1487 npc->palswapTimeHoldA = 0;
1488 }
1489
1490 npc->nextPalTime = npc->palswapTimeHoldA;
1491 npc->palBlendAlpha = 0;
1493 npc->resetPalAdjust = 0;
1494 }
1495
1496 // blending from A -> B
1497 switch (npc->palAnimState) {
1498 case PAL_SWAP_HOLD_A:
1499 if (npc->nextPalTime != 0) {
1500 npc->nextPalTime--;
1501 break;
1502 } else {
1503 npc->palBlendAlpha = 0;
1505 }
1506 // fallthrough
1507 case PAL_SWAP_A_TO_B:
1508 npc->palBlendAlpha += 25600 / npc->palswapTimeAtoB;
1509 if (npc->palBlendAlpha > 25500) {
1510 npc->palBlendAlpha = 25500;
1511 }
1512 blendAlpha = npc->palBlendAlpha / 100;
1513 // blend two palettes
1514 outColor = npc->copiedPalettes[0];
1515 color2 = npc->originalPalettesList[npc->blendPalA];
1516 color1 = npc->originalPalettesList[npc->blendPalB];
1517 npc->adjustedPalettes[0] = outColor;
1518
1519 for (j = 0; j < SPR_PAL_SIZE; j++) {
1520 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1521 }
1522
1523 if (blendAlpha == 255) {
1525 npc->nextPalTime = npc->palswapTimeHoldB;
1526 }
1527 break;
1528 }
1529
1530 // blending from B -> A
1531 switch (npc->palAnimState) {
1532 case PAL_SWAP_HOLD_B:
1533 if (npc->nextPalTime != 0) {
1534 npc->nextPalTime--;
1535 break;
1536 } else {
1537 npc->palBlendAlpha = 0;
1539 }
1540 // fallthrough
1541 case PAL_SWAP_B_TO_A:
1542 npc->palBlendAlpha += 25600 / npc->palswapTimeBtoA;
1543 if (npc->palBlendAlpha > 25500) {
1544 npc->palBlendAlpha = 25500;
1545 }
1546 blendAlpha = npc->palBlendAlpha / 100;
1547 // blend two palettes
1548 outColor = npc->copiedPalettes[0];
1549 color2 = npc->originalPalettesList[npc->blendPalB];
1550 color1 = npc->originalPalettesList[npc->blendPalA];
1551 npc->adjustedPalettes[0] = outColor;
1552
1553 for (j = 0; j < SPR_PAL_SIZE; j++) {
1554 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1555 }
1556
1557 if (blendAlpha == 255) {
1559 npc->nextPalTime = npc->palswapTimeHoldA;
1560 }
1561 break;
1562 }
1563
1564 switch (npc->palAnimState) {
1565 case PAL_SWAP_HOLD_A:
1566 case PAL_SWAP_A_TO_B:
1567 case PAL_SWAP_HOLD_B:
1568 case PAL_SWAP_B_TO_A:
1569 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1570 u32 mask = 0;
1571 blendAlpha = npc->alpha * npc->hideAlpha / 255;
1572 if (blendAlpha < 255) {
1574 }
1577 }
1578 break;
1579 }
1580}
1581
1583 PAL_PTR color1;
1584 PAL_PTR color2;
1586 s32 i, j;
1587 u8 blendAlpha;
1588
1589 // copy palettes from sprite data
1590 if (npc->resetPalAdjust != 0) {
1591 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1593 }
1594
1595 npc->originalPalettesCount = 0;
1596 while ((s32)npc->originalPalettesList[npc->originalPalettesCount] != -1) {
1597 npc->originalPalettesCount++;
1598 }
1599
1600 if (npc->resetPalAdjust == 1) {
1602 npc->palBlendAlpha = 0;
1603 } else {
1605 npc->palBlendAlpha = 255;
1606 }
1607
1608 for (i = 0; i < npc->originalPalettesCount; i++) {
1609 color1 = npc->copiedPalettes[i];
1610 color2 = npc->originalPalettesList[i];
1611 npc->adjustedPalettes[i] = color1;
1612 if (color2 != NULL) {
1613 for (j = 0; j < SPR_PAL_SIZE; j++) {
1614 *color1++ = *color2++;
1615 }
1616 }
1617 }
1618
1619 npc->nextPalTime = npc->palswapTimeHoldA;
1620 npc->palBlendAlpha = 0;
1622 npc->resetPalAdjust = 0;
1623 }
1624
1625 // blending from A -> B
1626 switch (npc->palAnimState) {
1627 case PAL_SWAP_HOLD_A:
1628 if (npc->nextPalTime != 0) {
1629 npc->nextPalTime--;
1630 break;
1631 }
1632 npc->palBlendAlpha = 0;
1634 // fallthrough
1635 case PAL_SWAP_A_TO_B:
1636 npc->palBlendAlpha += 25600 / npc->palswapTimeAtoB;
1637 if (npc->palBlendAlpha > 25500) {
1638 npc->palBlendAlpha = 25500;
1639 }
1640 blendAlpha = npc->palBlendAlpha / 100;
1641
1642 // blend first two palettes
1643 outColor = npc->copiedPalettes[0];
1644 color2 = npc->originalPalettesList[npc->blendPalA];
1645 color1 = npc->originalPalettesList[npc->blendPalB];
1646 npc->adjustedPalettes[0] = outColor;
1647
1648 for (j = 0; j < SPR_PAL_SIZE; j++) {
1649 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1650 }
1651
1652 // blend next palettes
1653 outColor = npc->copiedPalettes[3];
1654 color2 = npc->originalPalettesList[npc->blendPalC];
1655 color1 = npc->originalPalettesList[npc->blendPalD];
1656 npc->adjustedPalettes[3] = outColor;
1657
1658 for (j = 0; j < SPR_PAL_SIZE; j++) {
1659 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1660 }
1661
1662 if (blendAlpha == 255) {
1664 npc->nextPalTime = npc->palswapTimeHoldB;
1665 }
1666 break;
1667 }
1668
1669 // blending from B -> A
1670 switch (npc->palAnimState) {
1671 case PAL_SWAP_HOLD_B:
1672 if (npc->nextPalTime != 0) {
1673 npc->nextPalTime--;
1674 break;
1675 } else {
1676 npc->palBlendAlpha = 0;
1678 }
1679 // fallthrough
1680 case PAL_SWAP_B_TO_A:
1681 npc->palBlendAlpha += 25600 / npc->palswapTimeBtoA;
1682 if (npc->palBlendAlpha > 25500) {
1683 npc->palBlendAlpha = 25500;
1684 }
1685 blendAlpha = npc->palBlendAlpha / 100;
1686
1687 // blend first two palettes
1688 outColor = npc->copiedPalettes[0];
1689 color2 = npc->originalPalettesList[npc->blendPalB];
1690 color1 = npc->originalPalettesList[npc->blendPalA];
1691 npc->adjustedPalettes[0] = outColor;
1692
1693 for (j = 0; j < SPR_PAL_SIZE; j++) {
1694 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1695 }
1696
1697 // blend next palettes
1698 outColor = npc->copiedPalettes[1];
1699 color2 = npc->originalPalettesList[npc->blendPalD];
1700 color1 = npc->originalPalettesList[npc->blendPalC];
1701 npc->adjustedPalettes[3] = npc->copiedPalettes[3];
1702
1703 for (j = 0; j < SPR_PAL_SIZE; j++) {
1704 *outColor++ = npc_blend_palette_colors(*color2++, *color1++, blendAlpha);
1705 }
1706
1707 if (blendAlpha == 255) {
1709 npc->nextPalTime = npc->palswapTimeHoldA;
1710 }
1711 break;
1712 }
1713
1714 switch (npc->palAnimState) {
1715 case PAL_SWAP_HOLD_A:
1716 case PAL_SWAP_A_TO_B:
1717 case PAL_SWAP_HOLD_B:
1718 case PAL_SWAP_B_TO_A:
1719 if (!(npc->flags & NPC_FLAG_NO_ANIMS_LOADED)) {
1720 u32 mask = 0;
1721 blendAlpha = npc->alpha * npc->hideAlpha / 255;
1722 if (blendAlpha < 255) {
1724 }
1727 }
1728 break;
1729 }
1730}
1731
1732void npc_set_decoration(Npc* npc, s32 idx, s32 decorationType) {
1734 npc->decorationType[idx] = decorationType;
1735 npc->changedDecoration[idx] = 1;
1736 npc->decorationInitialized[idx] = 0;
1737}
1738
1740 switch (npc->decorationType[idx]) {
1743 break;
1746 break;
1749 break;
1752 break;
1755 break;
1758 break;
1761 break;
1762 }
1764}
1765
1767 s32 i;
1768
1769 for (i = 0; i < MAX_NPC_DECORATIONS; i++) {
1770 switch (npc->decorationType[i]) {
1773 break;
1776 break;
1779 break;
1782 break;
1785 break;
1788 break;
1791 break;
1792 }
1793 }
1794}
1795
1797 switch (npc->decorationType[idx]) {
1804 break;
1806 npc->decorationInitialized[idx] = 0;
1807 break;
1808 }
1809}
1810
1812}
1813
1815}
1816
1818 AuraFXData* data;
1819
1820 switch (npc->decorationInitialized[idx]) {
1821 case 0:
1822 fx_aura(FX_AURA_BLUE, npc->pos.x, npc->pos.y, npc->pos.z, 1.0f, &npc->decorations[idx]);
1823 npc->decorationInitialized[idx] = 1;
1824 // fallthrough
1825 case 1:
1826 data = npc->decorations[idx]->data.aura;
1827 data->posA.x = npc->pos.x;
1828 data->posA.y = npc->pos.y;
1829 data->posA.z = npc->pos.z;
1830 data->scale.x = (npc->scale.x * npc->collisionDiameter) * 0.01;
1831 data->scale.y = (npc->scale.y * npc->collisionHeight) * 0.01;
1832 data->renderYaw = npc->renderYaw;
1833 break;
1834 }
1835}
1836
1838 npc->decorations[idx]->data.aura->fadeTime = 5;
1839}
1840
1842 switch (npc->decorationInitialized[idx]) {
1843 case 0:
1844 if (npc->yawCamOffset > 90) {
1845 fx_sweat(0, npc->pos.x, npc->pos.y + npc->collisionHeight, npc->pos.z, 5.0f, 45.0f, 20);
1846 } else {
1847 fx_sweat(0, npc->pos.x, npc->pos.y + npc->collisionHeight, npc->pos.z, 5.0f, -45.0f, 20);
1848 }
1849 npc->decorationGlowPhase[idx] = 10;
1850 npc->decorationInitialized[idx] = 1;
1851 break;
1852 case 1:
1853 if (npc->decorationGlowPhase[idx] != 0) {
1854 npc->decorationGlowPhase[idx]--;
1855 } else {
1856 npc->decorationInitialized[idx] = 0;
1857 }
1858 break;
1859 }
1860}
1861
1863}
1864
1866 StarsOrbitingFXData* data;
1867
1868 switch (npc->decorationInitialized[idx]) {
1869 case 0:
1870 fx_stars_orbiting(0, npc->pos.x, npc->pos.y + npc->collisionHeight, npc->pos.z, 20.0f, 3, &npc->decorations[idx]);
1871 npc->decorationInitialized[idx] = 1;
1872 break;
1873 case 1:
1874 data = npc->decorations[idx]->data.starsOrbiting;
1875 data->pos.x = npc->pos.x;
1876 data->pos.y = npc->pos.y + npc->collisionHeight;
1877 data->pos.z = npc->pos.z;
1878 break;
1879 }
1880}
1881
1885
1887 EnergyOrbWaveFXData* data;
1888
1889 switch (npc->decorationInitialized[idx]) {
1890 case 0:
1891 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);
1892 npc->decorationInitialized[idx] = 1;
1893 break;
1894 case 1:
1895 data = npc->decorations[idx]->data.energyOrbWave;
1896 data->pos.x = npc->pos.x;
1897 data->pos.y = npc->pos.y + npc->collisionHeight * 0.5 * npc->scale.x;
1898 data->pos.z = npc->pos.z;
1899 data->scale = npc->scale.x * 0.8 + 0.2f;
1900 break;
1901 }
1902}
1903
1907
1909 EnergyOrbWaveFXData* data;
1910
1911 switch (npc->decorationInitialized[idx]) {
1912 case 0:
1913 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);
1914 npc->decorationInitialized[idx] = 1;
1915 break;
1916 case 1:
1917 data = npc->decorations[idx]->data.energyOrbWave;
1918 data->pos.x = npc->pos.x;
1919 data->pos.y = npc->pos.y + npc->collisionHeight * 0.5;
1920 data->pos.z = npc->pos.z - 5.0f;
1921 data->scale = 1.0f;
1922 break;
1923 }
1924}
1925
1929
1931 #define RGBA_BUF_SIZE 20
1935 s32 color;
1936 s32 alpha;
1937 s32 i;
1938
1939 if (npc->decorationInitialized[idx] == 0) {
1941 npc->decorationInitialized[idx] = 1;
1942 }
1943 if (npc->decorationInitialized[idx] == 1) {
1944 npc->decorationGlowPhase[idx] += 7;
1945 if (npc->decorationGlowPhase[idx] >= 360) {
1946 npc->decorationGlowPhase[idx] %= 360;
1947 }
1948
1949 for (i = 0; i < RGBA_BUF_SIZE; i++) {
1950 rbuf[i] = (cosine(npc->decorationGlowPhase[idx] + (25 * i)) + 1.0) * 80.0f;
1951 gbuf[i] = (cosine(npc->decorationGlowPhase[idx] + (25 * i) + 45) + 1.0) * 80.0f;
1952 bbuf[i] = (cosine(npc->decorationGlowPhase[idx] + (25 * i) + 90) + 1.0) * 80.0f;
1953 }
1954
1955 alpha = 255;
1956 for (i = 0; i < RGBA_BUF_SIZE; i++) {
1957 color = (rbuf[i] << 24) | (gbuf[i] << 16) | (bbuf[i] << 8) | alpha;
1959 }
1960 }
1961 #undef RGBA_BUF_SIZE
1962}
1963
1965}
1966
1967Npc* npc_find_closest(f32 x, f32 y, f32 z, f32 radius) {
1968 Npc* closestNpc = NULL;
1969 f32 closestDist = radius;
1970 f32 maxDist = radius;
1971 s32 i;
1972
1973 for (i = 0; i < ARRAY_COUNT(*gCurrentNpcListPtr); i++) {
1974 Npc* npc = (*gCurrentNpcListPtr)[i];
1975
1976 if (npc != NULL && npc->flags != 0 && !(npc->flags & NPC_FLAG_PARTNER)) {
1977 if (!(npc->flags & (NPC_FLAG_SUSPENDED | NPC_FLAG_INACTIVE))) {
1978 f32 distance = fabsf(dist2D(npc->pos.x, npc->pos.z, x, z));
1979
1980 if (distance <= maxDist) {
1981 if (distance < closestDist) {
1983 closestNpc = npc;
1984 }
1985 }
1986 }
1987 }
1988 }
1989
1990 return closestNpc;
1991}
1992
1994 Npc* closestNpc = NULL;
1995 f32 closestDist = radius;
1996 f32 maxDist = radius;
1997 s32 i;
1998
1999 for (i = 0; i < ARRAY_COUNT(*gCurrentNpcListPtr); i++) {
2000 Npc* npc = (*gCurrentNpcListPtr)[i];
2001
2002 if (npc != NULL && npc->flags != 0 && (npc->flags & NPC_FLAG_PARTNER)) {
2003 if (!(npc->flags & (NPC_FLAG_SUSPENDED | NPC_FLAG_INACTIVE))) {
2004 f32 distance = fabsf(dist2D(npc->pos.x, npc->pos.z, x, z));
2005
2006 if (distance <= maxDist) {
2007 if (distance < closestDist) {
2009 closestNpc = npc;
2010 }
2011 }
2012 }
2013 }
2014 }
2015
2016 return closestNpc;
2017}
2018
2021 s32 y = get_entity_by_index(idx)->pos.y - 10.0f;
2022 Npc* npc;
2023 s32 i;
2024 s32 var_v1;
2025
2026 npc->pos = npc->pos; // TODO required to match
2027
2028 for (i = 0; i < ARRAY_COUNT(*gCurrentNpcListPtr); i++) {
2029 npc = (*gCurrentNpcListPtr)[i];
2030
2031 if (npc == NULL) {
2032 continue;
2033 }
2034 if (npc->flags == 0) {
2035 continue;
2036 }
2038 continue;
2039 }
2040 if (npc->flags & NPC_FLAG_PARTNER) {
2041 var_v1 = i; // TODO required to match (dummy if statement to load NPC_FLAG_PARTNER into s5)
2042 }
2043 if (npc->pos.y < y) {
2044 continue;
2045 }
2048 if (var_v1 != 0) {
2049 if (idx == var_v1) {
2050 return i;
2051 }
2052 }
2053 } else {
2054 var_v1 = npc->curFloor;
2055 if (npc->curFloor & COLLISION_WITH_ENTITY_BIT) { // TODO required to match (can't use var_v1)
2056 if (idx == var_v1) {
2057 npc->pos = npc->pos; // TODO required to match
2058 return i;
2059 }
2060 }
2061 }
2062 }
2063
2064 return -1;
2065}
2066
2068 f32 x;
2069 f32 y;
2070 f32 z;
2071 f32 yaw;
2072
2073 if (npc->flags & NPC_FLAG_PARTNER) {
2074 y = get_shadow_by_index(npc->shadowIndex)->pos.y + 13.0f;
2075 } else {
2076 y = npc->pos.y + 13.0f;
2077 }
2078
2079 yaw = 16.0f;
2080 x = npc->pos.x;
2081 z = npc->pos.z;
2082
2084 if (yaw <= 16.0f) {
2085 return NpcHitQueryColliderID;
2086 }
2087 }
2088 return 0;
2089}
2090
2092 s32 imgfxType = npc->imgfxType;
2093 s32 imgfxArg1 = npc->imgfxArg1;
2094 s32 imgfxArg2 = npc->imgfxArg2;
2095 s32 imgfxArg3 = npc->imgfxArg3;
2096 s32 imgfxArg4 = npc->imgfxArg4;
2097 s32 imgfxFlags = npc->imgfxFlags;
2098
2099 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_CLEAR, 0, 0, 0, 0, 0);
2100
2101 switch (imgfxType) {
2102 case IMGFX_CLEAR:
2104 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_CLEAR, 0, 0, 0, 0, imgfxFlags);
2105 break;
2106 case IMGFX_UNK_2:
2107 case IMGFX_RESET:
2109 // fallthrough
2110 case IMGFX_UNK_1:
2111 set_npc_imgfx_all(npc->spriteInstanceID, imgfxType, 0, 0, 0, 0, imgfxFlags);
2112 break;
2113 case IMGFX_SET_WAVY:
2115 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_WAVY, imgfxArg1, imgfxArg2, imgfxArg3, 0, imgfxFlags);
2116 break;
2117 case IMGFX_SET_COLOR:
2119 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_COLOR, imgfxArg1, imgfxArg2, imgfxArg3, 255, imgfxFlags);
2120 break;
2121 case IMGFX_SET_ALPHA:
2123 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_ALPHA, 255, 255, 255, imgfxArg1, imgfxFlags);
2124 break;
2125 case IMGFX_SET_TINT:
2127 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_TINT, imgfxArg1, imgfxArg2, imgfxArg3, imgfxArg4, imgfxFlags);
2128 break;
2131 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_WHITE_FADE, imgfxArg1, imgfxArg2, imgfxArg3, 255, imgfxFlags);
2132 break;
2135 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_CREDITS_FADE, imgfxArg1, imgfxArg2, imgfxArg3, imgfxArg4, imgfxFlags);
2136 break;
2137 case IMGFX_SET_ANIM:
2139 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_SET_ANIM, imgfxArg1, imgfxArg2, imgfxArg3, 0, imgfxFlags);
2140 break;
2141 case IMGFX_HOLOGRAM:
2143 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_HOLOGRAM, imgfxArg1, imgfxArg2, imgfxArg3, imgfxArg4, imgfxFlags);
2144 break;
2145 case IMGFX_FILL_COLOR:
2147 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_FILL_COLOR, imgfxArg1, imgfxArg2, imgfxArg3, 255, imgfxFlags);
2148 break;
2149 case IMGFX_OVERLAY:
2151 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_OVERLAY, imgfxArg1, 255, 0, 255, imgfxFlags);
2152 break;
2153 case IMGFX_OVERLAY_XLU:
2155 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_OVERLAY, imgfxArg1, imgfxArg2, 0, imgfxArg2, imgfxFlags);
2156 break;
2157 }
2158}
2159
2160void npc_set_imgfx_params(Npc* npc, s32 imgfxType, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6) {
2161 npc->imgfxType = imgfxType;
2162 npc->imgfxArg1 = arg2;
2163 npc->imgfxArg2 = arg3;
2164 npc->imgfxArg3 = arg4;
2165 npc->imgfxArg4 = arg5;
2166 npc->imgfxFlags = arg6;
2167 npc_imgfx_update(npc);
2168}
2169
2170void COPY_set_defeated(s32 mapID, s32 encounterID) {
2172 s32 encounterIdx = encounterID / 32;
2173 s32 encounterShift;
2174 s32 flag;
2175
2176 flag = encounterID % 32;
2177 encounterShift = flag;
2179 currentEncounter->defeatFlags[mapID][encounterIdx] = flag | (1 << encounterShift);
2180
2181 // TODO: The below should work but has regalloc issues:
2182 /*EncounterStatus *currentEncounter = &gCurrentEncounter;
2183 s32 encounterIdx = encounterID / 32;
2184 s32 encounterShift = encounterID % 32;
2185
2186 currentEncounter->defeatFlags[mapID][encounterIdx] |= (1 << encounterShift);*/
2187}
2188
2191 s32 i;
2192 s32 j;
2193
2194 for (i = 0; i < ARRAY_COUNT(currentEncounter->encounterList); i++) {
2196 }
2197
2199 currentEncounter->numEncounters = 0;
2200 currentEncounter->firstStrikeType = FIRST_STRIKE_NONE;
2201 currentEncounter->hitType = 0;
2202 currentEncounter->battleTriggerCooldown = 0;
2203 currentEncounter->npcGroupList = 0;
2204 currentEncounter->unk_08 = 0;
2205 currentEncounter->dropWhackaBump = FALSE;
2206
2207 for (i = 0; i < ARRAY_COUNT(currentEncounter->defeatFlags); i++) {
2208 for (j = 0; j < ARRAY_COUNT(currentEncounter->defeatFlags[i]); j++) {
2209 currentEncounter->defeatFlags[i][j] = 0;
2210 }
2211 }
2212
2213 for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps); i++) {
2214 currentEncounter->recentMaps[i] = -1;
2215 }
2216
2217 func_80045AC0();
2220}
2221
2224 s32 i;
2225 s32 j;
2226
2227 for (i = 0; i < ARRAY_COUNT(currentEncounter->encounterList); i++) {
2229 }
2230
2232 for (i = 0; i < ARRAY_COUNT(currentEncounter->defeatFlags); i++) {
2233 for (j = 0; j < ARRAY_COUNT(currentEncounter->defeatFlags[i]); j++) {
2234 currentEncounter->defeatFlags[i][j] = 0;
2235 }
2236 }
2237
2239 for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps); i++) {
2240 currentEncounter->recentMaps[i] = -1;
2241 }
2242 }
2243 }
2244
2245 currentEncounter->numEncounters = 0;
2246 currentEncounter->firstStrikeType = FIRST_STRIKE_NONE;
2247 currentEncounter->hitType = 0;
2248 currentEncounter->battleTriggerCooldown = 0;
2249 currentEncounter->curAreaIndex = gGameStatusPtr->areaID;
2250 currentEncounter->curMapIndex = gGameStatusPtr->mapID;
2251 currentEncounter->curEntryIndex = gGameStatusPtr->entryID;
2252 currentEncounter->npcGroupList = 0;
2253 currentEncounter->unk_08 = 0;
2254 currentEncounter->scriptedBattle = FALSE;
2255
2256 func_80045AC0();
2259}
2260
2261void func_8003E50C(void) {
2262}
2263
2267
2269 switch (gEncounterState) {
2271 break;
2274 break;
2277 break;
2280 break;
2283 break;
2286 break;
2287 }
2288
2290}
2291
2293 switch (gEncounterState) {
2295 break;
2298 break;
2301 break;
2304 break;
2307 break;
2310 break;
2311 }
2312
2314}
2315
2317 switch (gEncounterState) {
2319 break;
2322 break;
2323 }
2324}
2325
2328
2329void make_npcs(s32 flags, s32 mapID, s32* npcGroupList) {
2331 s32 i;
2332 s32 j;
2333
2335 currentEncounter->mapID = mapID;
2336 currentEncounter->npcGroupList = npcGroupList;
2337
2339 for (i = 0; i < ARRAY_COUNT(currentEncounter->defeatFlags); i++) {
2340 for (j = 0; j < ARRAY_COUNT(currentEncounter->defeatFlags[i]); j++) {
2341 currentEncounter->defeatFlags[i][j] = 0;
2342 }
2343 }
2344
2346 for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps); i++) {
2347 currentEncounter->recentMaps[i] = -1;
2348 }
2349 }
2350 }
2351
2352 if (npcGroupList != NULL) {
2356 }
2357}
2358
2361 s32 i;
2362
2363 for (i = 0; i < encounter->count; i++) {
2364 Enemy* currentEnemy = encounter->enemy[i];
2365 if (currentEnemy != NULL) {
2367 encounter->enemy[i] = NULL;
2368 }
2369 }
2370}
2371
2372void kill_enemy(Enemy* enemy) {
2374 Encounter* encounter = encounterStatus->encounterList[enemy->encounterIndex];
2375 s32 i;
2376 s32 j;
2377
2378 for (i = 0; i < encounter->count; i++) {
2379 Enemy* currentEnemy = encounter->enemy[i];
2380 if (currentEnemy == enemy) {
2381 break;
2382 }
2383 }
2384
2385 if (enemy->initScript != NULL) {
2387 }
2388 if (enemy->interactScript != NULL) {
2390 }
2391 if (enemy->aiScript != NULL) {
2393 }
2394 if (enemy->hitScript != NULL) {
2396 }
2397 if (enemy->auxScript != NULL) {
2399 }
2400 if (enemy->defeatScript != NULL) {
2402 }
2403
2404 enemy->interactBytecode = NULL;
2405 enemy->aiBytecode = NULL;
2406 enemy->hitBytecode = NULL;
2407 enemy->auxBytecode = NULL;
2408 enemy->defeatBytecode = NULL;
2409
2410 #if DX_DEBUG_MENU
2411 if (enemy->npcID != (s16) DX_DEBUG_DUMMY_ID) {
2412 free_npc(get_npc_unsafe(enemy->npcID));
2413 }
2414 #else
2415 free_npc(get_npc_unsafe(enemy->npcID));
2416 #endif
2417
2418 if (enemy->unk_64 != NULL) {
2419 heap_free(enemy->unk_64);
2420 }
2421
2422 for (j = 0; j < ARRAY_COUNT(encounter->enemy); j++) {
2423 if (encounter->enemy[j] == enemy) {
2424 encounter->enemy[j] = NULL;
2425 }
2426 }
2427
2428 if (!(enemy->flags & ENEMY_FLAG_DO_NOT_KILL)
2429 && (!(enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) || (enemy == encounterStatus->curEnemy))
2430 && !(enemy->flags & ENEMY_FLAG_PASSIVE)
2431 && !(enemy->flags & ENEMY_FLAG_FLED)
2432 ) {
2433 COPY_set_defeated(encounterStatus->mapID, encounter->encounterID + i);
2434 }
2435
2436 heap_free(enemy);
2437}
2438
2440 Evt* aiScript;
2441 s32 id;
2442
2443 if (enemy->aiScript != NULL) {
2444 kill_script_by_ID(enemy->aiScript->id);
2445 }
2447 aiScript = enemy->aiScript = start_script(aiScriptBytecode, EVT_PRIORITY_A, 0);
2448 id = enemy->aiScriptID = aiScript->id;
2449 aiScript->owner1.enemy = enemy;
2450 return id;
2451}
2452
2454 Evt* auxScript;
2455 s32 id;
2456
2457 if (enemy->auxScript != NULL) {
2459 }
2461 auxScript = enemy->auxScript = start_script(auxScriptBytecode, EVT_PRIORITY_A, 0);
2462 id = enemy->auxScriptID = auxScript->id;
2463 auxScript->owner1.enemy = enemy;
2464 return id;
2465}
2466
2468 Evt* interactScript;
2469 s32 id;
2470
2471 if (enemy->interactScript != NULL) {
2473 }
2476 id = enemy->interactScriptID = interactScript->id;
2477 interactScript->owner1.enemy = enemy;
2478 return id;
2479}
2480
2483 s32 i;
2484 s32 j;
2485
2486 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2488 if (currentEncounter != NULL) {
2489 for (j = 0; j < currentEncounter->count; j++) {
2491 if ((currentEnemy != NULL) && (currentEnemy->npcID == npcID)) {
2493 break;
2494 }
2495 }
2496 }
2497 }
2498}
2499
2502 s32 i;
2503 s32 j;
2504
2505 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2507 if (currentEncounter != NULL) {
2508 for (j = 0; j < currentEncounter->count; j++) {
2510 if ((currentEnemy != NULL) && (currentEnemy->npcID == npcID)) {
2512 break;
2513 }
2514 }
2515 }
2516 }
2517}
2518
2521 s32 i;
2522 s32 j;
2523
2524 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2526 if (currentEncounter != NULL) {
2527 for (j = 0; j < currentEncounter->count; j++) {
2529 if ((currentEnemy != NULL) && (currentEnemy->npcID == npcID)) {
2531 break;
2532 }
2533 }
2534 }
2535 }
2536}
2537
2538Enemy* get_enemy(s32 npcID) {
2540 s32 i;
2541 s32 j;
2542
2543 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2545 if (currentEncounter != NULL) {
2546 for (j = 0; j < currentEncounter->count; j++) {
2548 if ((currentEnemy != NULL) && (currentEnemy->npcID == npcID)) {
2549 return currentEnemy;
2550 }
2551 }
2552 }
2553 }
2554 PANIC();
2555}
2556
2559 s32 i;
2560 s32 j;
2561
2562 for (i = 0; i < currentEncounterStatus->numEncounters; i++) {
2564
2565 if (currentEncounter != NULL) {
2566 for (j = 0; j < currentEncounter->count; j++) {
2568 if ((currentEnemy != NULL) && (currentEnemy->npcID == npcID)) {
2569 return currentEnemy;
2570 }
2571 }
2572 }
2573 }
2574 return NULL;
2575}
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:5018
@ IMGFX_SET_ALPHA
Definition enums.h:5123
@ IMGFX_RESET
Definition enums.h:5119
@ IMGFX_HOLOGRAM
Definition enums.h:5129
@ IMGFX_SET_COLOR
Definition enums.h:5122
@ IMGFX_OVERLAY_XLU
Definition enums.h:5132
@ IMGFX_OVERLAY
Definition enums.h:5131
@ IMGFX_CLEAR
Definition enums.h:5116
@ IMGFX_SET_WAVY
Definition enums.h:5120
@ IMGFX_ALLOC_COLOR_BUF
Definition enums.h:5133
@ IMGFX_FILL_COLOR
Definition enums.h:5130
@ IMGFX_COLOR_BUF_SET_MODULATE
Definition enums.h:5128
@ IMGFX_SET_CREDITS_FADE
Definition enums.h:5126
@ IMGFX_SET_TINT
Definition enums.h:5124
@ IMGFX_SET_WHITE_FADE
Definition enums.h:5125
@ IMGFX_SET_ANIM
Definition enums.h:5121
@ IMGFX_UNK_2
Definition enums.h:5118
@ IMGFX_UNK_1
Definition enums.h:5117
@ NPC_DECORATION_WHITE_GLOW_BEHIND
Definition enums.h:1923
@ NPC_DECORATION_BOWSER_AURA
Definition enums.h:1919
@ NPC_DECORATION_CHARGED
Definition enums.h:1924
@ NPC_DECORATION_SWEAT
Definition enums.h:1920
@ NPC_DECORATION_NONE
Definition enums.h:1918
@ NPC_DECORATION_WHITE_GLOW_FRONT
Definition enums.h:1922
@ NPC_DECORATION_SEEING_STARS
Definition enums.h:1921
@ NPC_PAL_ADJUST_NONE
Definition enums.h:1928
@ NPC_PAL_ADJUST_BLEND_DOUBLE_PALETTES
Definition enums.h:1932
@ NPC_PAL_ADJUST_BLEND_PALETTES_UNIFORM_INTERVALS
Definition enums.h:1930
@ NPC_PAL_ADJUST_BLEND_PALETTES_VARYING_INTERVALS
Definition enums.h:1931
@ NPC_PAL_ADJUST_WATT_IDLE
Definition enums.h:1929
@ ENCOUNTER_FLAG_NONE
Definition enums.h:4985
@ SHADOW_VARYING_CIRCLE
Definition enums.h:2535
@ PS_FLAG_FALLING
Definition enums.h:3036
@ PS_FLAG_JUMPING
Definition enums.h:3035
@ PARTNER_ACTION_NONE
Definition enums.h:2932
@ ENEMY_FLAG_DO_NOT_KILL
Definition enums.h:4522
@ ENEMY_FLAG_PASSIVE
Definition enums.h:4520
@ ENEMY_FLAG_FLED
Definition enums.h:4524
@ ENEMY_FLAG_ENABLE_HIT_SCRIPT
Definition enums.h:4523
@ COLLIDER_FLAG_IGNORE_PLAYER
Definition enums.h:4695
@ COLLIDER_FLAG_IGNORE_SHELL
Definition enums.h:4694
@ COLLISION_IGNORE_ENTITIES
Definition enums.h:4697
@ COLLIDER_FLAG_IGNORE_NPC
Definition enums.h:4696
@ PA_FLAG_NPC_COLLIDED
Definition enums.h:3106
@ PA_FLAG_RIDING_PARTNER
Definition enums.h:3116
@ CONTEXT_WORLD
Definition enums.h:3528
@ RENDER_MODE_SURFACE_XLU_LAYER2
Definition enums.h:3287
@ RENDER_MODE_ALPHATEST
Definition enums.h:3276
@ RENDER_MODE_SURFACE_XLU_LAYER1
Definition enums.h:3282
@ ENTITY_FLAG_HIDDEN
Definition enums.h:2613
@ ENCOUNTER_STATE_POST_BATTLE
Definition enums.h:6298
@ ENCOUNTER_STATE_CONVERSATION
Definition enums.h:6297
@ ENCOUNTER_STATE_NEUTRAL
Definition enums.h:6295
@ ENCOUNTER_STATE_NONE
Definition enums.h:6293
@ ENCOUNTER_STATE_PRE_BATTLE
Definition enums.h:6296
@ ENCOUNTER_STATE_CREATE
Definition enums.h:6294
@ FIRST_STRIKE_NONE
Definition enums.h:3458
@ GLOBAL_OVERRIDES_800
Definition enums.h:4329
@ GLOBAL_OVERRIDES_PREV_400
Definition enums.h:4332
@ GLOBAL_OVERRIDES_400
Definition enums.h:4328
@ GLOBAL_OVERRIDES_PREV_800
Definition enums.h:4333
@ ENCOUNTER_SUBSTATE_CREATE_INIT
Definition enums.h:6302
@ NPC_FLAG_IGNORE_ENTITY_COLLISION
Definition enums.h:3013
@ NPC_FLAG_WORLD_COLLISION_DIRTY
Definition enums.h:3025
@ NPC_FLAG_FLYING
Definition enums.h:3001
@ NPC_FLAG_HAS_NO_SPRITE
Definition enums.h:3022
@ NPC_FLAG_HAS_SHADOW
Definition enums.h:3002
@ NPC_FLAG_SUSPENDED
Definition enums.h:3029
@ NPC_FLAG_ENABLED
Definition enums.h:2998
@ NPC_FLAG_REFLECT_WALL
Definition enums.h:3015
@ NPC_FLAG_JUMPING
Definition enums.h:3009
@ NPC_FLAG_MOTION_BLUR
Definition enums.h:3018
@ NPC_FLAG_TOUCHES_GROUND
Definition enums.h:3020
@ NPC_FLAG_IGNORE_WORLD_COLLISION
Definition enums.h:3004
@ NPC_FLAG_INACTIVE
Definition enums.h:3000
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
Definition enums.h:3006
@ NPC_FLAG_COLLDING_FORWARD_WITH_WORLD
Definition enums.h:3012
@ NPC_FLAG_UPSIDE_DOWN
Definition enums.h:3005
@ NPC_FLAG_FLIP_INSTANTLY
Definition enums.h:3019
@ NPC_FLAG_COLLIDING_WITH_NPC
Definition enums.h:3023
@ NPC_FLAG_DIRTY_SHADOW
Definition enums.h:3014
@ NPC_FLAG_GRAVITY
Definition enums.h:3007
@ NPC_FLAG_PARTNER
Definition enums.h:3024
@ NPC_FLAG_INVISIBLE
Definition enums.h:2999
@ NPC_FLAG_NO_SHADOW_RAYCAST
Definition enums.h:3003
@ NPC_FLAG_HIDING
Definition enums.h:3021
@ NPC_FLAG_GROUNDED
Definition enums.h:3010
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
Definition enums.h:3016
@ NPC_FLAG_COLLDING_WITH_WORLD
Definition enums.h:3011
@ NPC_FLAG_DONT_UPDATE_SHADOW_Y
Definition enums.h:3008
@ NPC_FLAG_NO_ANIMS_LOADED
Definition enums.h:3028
@ NPC_FLAG_REFLECT_FLOOR
Definition enums.h:3017
@ EVT_PRIORITY_A
Definition evt.h:153
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:1637
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:2813
void func_80045AC0(void)
f32 cosine(s16 arg0)
Definition 43F0.c:352
f32 cos_rad(f32 x)
Definition 43F0.c:715
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:668
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:1528
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:711
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:1687
f32 get_clamped_angle_diff(f32, f32)
Definition 43F0.c:604
void * heap_malloc(s32 size)
Definition heap.c:34
void npc_render_without_adjusted_palettes(Npc *npc, s32 arg1, Matrix4f mtx)
Definition npc.c:1319
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:1930
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:1865
void npc_remove_decoration_glow_in_front(Npc *npc, s32 idx)
Definition npc.c:1904
void npc_imgfx_update(Npc *npc)
Definition npc.c:2091
s32 npc_render_with_single_pal_blending(Npc *npc, s32 yaw, b32 hasDifferentIntervals, Matrix4f mtx)
Definition npc.c:1446
void disable_npc_blur(Npc *npc)
Definition npc.c:1086
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:2439
void npc_reload_all(void)
Definition npc.c:1206
s32 bind_enemy_aux(Enemy *enemy, EvtScript *auxScriptBytecode)
Binds the specified auxillary script to the specified enemy.
Definition npc.c:2453
s32 npc_render_with_watt_idle_palettes(Npc *npc, s32 arg1, Matrix4f mtx)
Definition npc.c:1341
void appendGfx_npc_blur(void *data)
Definition npc.c:1111
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:2557
s32 npc_find_standing_on_entity(s32 entityIndex)
Definition npc.c:2019
void npc_set_imgfx_params(Npc *npc, s32 imgfxType, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6)
Definition npc.c:2160
void npc_remove_decoration_sweat(Npc *npc, s32 idx)
Definition npc.c:1862
void kill_enemy(Enemy *enemy)
Definition npc.c:2372
Enemy * get_enemy(s32 npcID)
Looks for an enemy matching the specified npcID.
Definition npc.c:2538
void npc_do_other_npc_collision(Npc *npc)
Definition npc.c:380
void func_8003E50C(void)
Definition npc.c:2261
void bind_npc_ai(s32 npcID, EvtScript *npcAiBytecode)
Binds the specified ai script to the npc matching the specified npcId.
Definition npc.c:2481
#define RGBA_BUF_SIZE
void npc_disable_collisions(void)
Definition npc.c:1199
void npc_set_palswap_1(Npc *npc, s32 palIndexA, s32 palIndexB, s32 timeHoldA, s32 timeAB)
Definition npc.c:1285
u8 wWattIdlePalettesAnim[]
Definition npc.c:31
void enable_npc_shadow(Npc *npc)
Definition npc.c:1025
void npc_remove_decoration_bowser_aura(Npc *npc, s32 idx)
Definition npc.c:1837
s32 npc_render_with_double_pal_blending(Npc *npc, s32 yaw, Matrix4f mtx)
Definition npc.c:1582
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:2268
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:1993
void enable_npc_blur(Npc *npc)
Definition npc.c:1065
@ 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 disable_npc_shadow(Npc *npc)
Definition npc.c:1035
void npc_draw_with_palswap(Npc *npc, s32 yaw, Matrix4f mtx)
Definition npc.c:1299
void free_npc_by_index(s32 listIndex)
Definition npc.c:201
void func_8003E514(s8 arg0)
Definition npc.c:2264
void clear_npcs(void)
Definition npc.c:59
void npc_revert_palswap_mode(Npc *npc)
Definition npc.c:1274
void make_npcs(s32 flags, s32 mapID, s32 *npcGroupList)
Definition npc.c:2329
void npc_set_decoration(Npc *npc, s32 idx, s32 decorationType)
Definition npc.c:1732
void render_npcs(void)
Renders all NPCs.
Definition npc.c:931
void npc_set_palswap_mode_A(Npc *npc, s32 mode)
Definition npc.c:1256
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:993
void npc_set_palswap_2(Npc *npc, s32 timeHoldB, s32 timeBA, s32 palIndexC, s32 palIndexD)
Definition npc.c:1292
void npc_enable_collisions(void)
Definition npc.c:1195
void npc_render_worker_do_nothing(void)
Definition npc.c:2326
@ WATT_BRIGHTER
Definition npc.c:28
@ WATT_DEFAULT
Definition npc.c:26
@ WATT_BRIGHTEST
Definition npc.c:27
void npc_remove_decoration_none(Npc *npc, s32 idx)
Definition npc.c:1814
void npc_update_decoration_glow_in_front(Npc *npc, s32 idx)
Definition npc.c:1886
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:1967
void npc_reset_current_decoration(Npc *npc, s32 idx)
Definition npc.c:1796
s32 npc_update_decorations(Npc *npc)
Definition npc.c:1766
#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:2500
void update_npcs(void)
Updates all NPCs.
Definition npc.c:616
void npc_set_palswap_mode_B(Npc *npc, s32 mode)
Definition npc.c:1265
s32 kill_encounter(Enemy *enemy)
Definition npc.c:2359
void bind_npc_interact(s32 npcID, EvtScript *npcInteractBytecode)
Binds the specified interact script to the npc matching the specified npcId.
Definition npc.c:2519
Npc * get_npc_by_index(s32 listIndex)
Definition npc.c:270
void clear_encounter_status(void)
Definition npc.c:2222
void draw_first_strike_ui(void)
Definition npc.c:2316
void npc_remove_decoration(Npc *npc, s32 idx)
Definition npc.c:1739
void npc_update_decoration_bowser_aura(Npc *npc, s32 idx)
Definition npc.c:1817
void npc_remove_decoration_glow_behind(Npc *npc, s32 idx)
Definition npc.c:1926
f32 npc_get_render_yaw(Npc *npc)
Definition npc.c:744
s32 npc_do_player_collision(Npc *npc)
Definition npc.c:442
void npc_remove_decoration_charged(Npc *npc, s32 idx)
Definition npc.c:1964
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
Definition npc.c:984
void update_npc_blur(Npc *npc)
Definition npc.c:1095
void appendGfx_npc(void *data)
Definition npc.c:808
void COPY_set_defeated(s32 mapID, s32 encounterID)
Duplicate of set_defeated().
Definition npc.c:2170
void func_8003B1A8(void)
Definition npc.c:1203
u16 npc_blend_palette_colors(u16 colorA, u16 colorB, s32 lerpAlpha)
Definition npc.c:1437
void draw_encounter_ui(void)
Definition npc.c:2292
void set_npc_yaw(Npc *npc, f32 yaw)
Definition npc.c:1244
s32 npc_get_collider_below(Npc *npc)
Definition npc.c:2067
void set_npc_sprite(Npc *npc, s32 anim, AnimID *extraAnimList)
Definition npc.c:1046
void init_encounter_status(void)
Definition npc.c:2189
void npc_update_decoration_glow_behind(Npc *npc, s32 idx)
Definition npc.c:1908
s16 gNpcCount
Definition npc.c:9
void npc_update_decoration_sweat(Npc *npc, s32 idx)
Definition npc.c:1841
void npc_remove_decoration_seeing_stars(Npc *npc, s32 idx)
Definition npc.c:1882
s32 bind_enemy_interact(Enemy *enemy, EvtScript *interactScriptBytecode)
Binds the specified interact script to the specified enemy.
Definition npc.c:2467
void npc_update_decoration_none(Npc *npc, s32 idx)
Definition npc.c:1811
Npc * get_npc_safe(s32 npcID)
Definition npc.c:1008
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:273
#define UNPACK_PAL_R(color)
Definition macros.h:271
#define SPRITE_WORLD_SCALE_D
Definition macros.h:144
#define UNPACK_PAL_A(color)
Definition macros.h:274
#define COLLISION_WITH_ENTITY_BIT
Definition macros.h:156
#define ARRAY_COUNT(arr)
Definition macros.h:40
#define UNPACK_PAL_G(color)
Definition macros.h:272
#define SPR_PAL_SIZE
Definition macros.h:146
#define PACK_PAL_RGBA(r, g, b, a)
Definition macros.h:276
#define PANIC()
Definition macros.h:55
#define DEG_TO_RAD(deg)
Definition macros.h:138
#define BATTLE_NPC_ID_BIT
Definition macros.h:149
#define SQ(x)
Definition macros.h:170
#define MAX_NPCS
Definition macros.h:91
#define NO_COLLIDER
Definition macros.h:160
s32 spr_draw_npc_sprite(s32 spriteInstanceID, s32 yaw, s32 arg2, PAL_PTR *paletteList, Matrix4f mtx)
Definition sprite.c:1105
s32 spr_update_sprite(s32 spriteInstanceID, s32 animID, f32 timeScale)
Definition sprite.c:1071
s32 spr_free_sprite(s32 spriteInstanceID)
Definition sprite.c:1177
s32 spr_get_notify_value(s32 spriteIndex)
Definition sprite.c:1173
void set_npc_imgfx_all(s32 spriteIdx, ImgFXType imgfxType, s32 imgfxArg1, s32 imgfxArg2, s32 imgfxArg3, s32 imgfxArg4, s32 imgfxArg5)
Definition sprite.c:1253
s32 spr_get_npc_color_variations(s32 npcSpriteID)
Definition sprite.c:1326
PAL_PTR * spr_get_npc_palettes(s32 npcSpriteID)
Definition sprite.c:1316
s32 func_802DDEC4(s32 spriteIdx)
Definition sprite.c:964
s32 spr_load_npc_sprite(s32 animID, u32 *extraAnimList)
Definition sprite.c:1025
s32 spr_draw_player_sprite(s32 spriteInstanceID, s32 yaw, s32 alphaIn, PAL_PTR *paletteList, Matrix4f mtx)
Definition sprite.c:872
s32 spr_update_player_sprite(s32 spriteInstanceID, s32 animID, f32 timeScale)
Definition sprite.c:823
@ PLAYER_SPRITE_AUX1
Definition sprite.h:27
@ DRAW_SPRITE_OVERRIDE_YAW
Definition sprite.h:21
@ DRAW_SPRITE_OVERRIDE_ALPHA
Definition sprite.h:22
@ DRAW_SPRITE_OVERRIDE_PALETTES
Definition sprite.h:20
@ SPRITE_ID_TAIL_ALLOCATE
Definition sprite.h:14
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
union Npc::@2 blur
s16 imgfxArg1
s8 decorationInitialized[2]
u16 palswapTimeHoldA
s16 blendPalD
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