Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
encounter.c
Go to the documentation of this file.
1#include "battle/battle.h"
2#include "script_api/battle.h"
3#include "npc.h"
4#include "effects.h"
5#include "hud_element.h"
6#include "world/partners.h"
7#include "sprite.h"
8#include "sprite/npc/BattleMerlee.h"
9#include "sprite/player.h"
10#include "model.h"
11
12API_CALLABLE(ShowMerleeCoinMessage);
13API_CALLABLE(ShowMerleeRanOutMessage);
14API_CALLABLE(FadeInMerlee);
15API_CALLABLE(FadeOutMerlee);
16API_CALLABLE(MerleeUpdateFX);
17API_CALLABLE(MerleeStopFX);
18API_CALLABLE(PlayMerleeGatherFX);
19API_CALLABLE(PlayMerleeOrbFX);
20
22
24
63
75
81
84 .itemDropChance = 10,
85 .itemDrops = {
86 {
87 .item = ITEM_MUSHROOM,
88 .weight = 50,
89 .flagIdx = -1,
90 },
91 },
92 .heartDrops = {
93 {
94 .cutoff = F16(75),
95 .generalChance = F16(100),
96 .attempts = 0,
97 .chancePerAttempt = 1,
98 },
99 {
100 .cutoff = F16(50),
101 .generalChance = F16(75),
102 .attempts = 0,
103 .chancePerAttempt = 2,
104 },
105 {
106 .cutoff = F16(25),
107 .generalChance = F16(50),
108 .attempts = 0,
109 .chancePerAttempt = 3,
110 },
111 {
112 .cutoff = F16(0),
113 .generalChance = F16(25),
114 .attempts = 0,
115 .chancePerAttempt = 4,
116 },
117 },
118 .flowerDrops = {
119 {
120 .cutoff = 1,
121 .generalChance = 3,
122 .attempts = 0,
123 .chancePerAttempt = 0,
124 },
125 },
126 .minCoinBonus = 0,
127 .maxCoinBonus = 0,
128};
129
156
172
176
181
189
190enum {
191 MERLEE_EFFECTS_HOLD = 0, // effects appear and track Merlee's position
192 MERLEE_EFFECTS_RELEASE = 1, // effects grow larger before vanishing
193 MERLEE_EFFECTS_DISMISS = 2, // effects vanish and are dismissed
194};
195
199s32 get_coin_drop_amount(Enemy* enemy);
200
201s32 get_defeated(s32 mapID, s32 encounterID) {
203 s32 encounterIdx = encounterID / 32;
204 s32 encounterShift = encounterID % 32;
205
207}
208
209void set_defeated(s32 mapID, s32 encounterID) {
211 s32 encounterIdx = encounterID / 32;
212 s32 encounterShift;
213 s32 flag;
214
215 flag = encounterID % 32;
216 encounterShift = flag;
218 currentEncounter->defeatFlags[mapID][encounterIdx] = flag | (1 << encounterShift);
219
220 // TODO: The below should work but has regalloc issues:
221 /*EncounterStatus *currentEncounter = &gCurrentEncounter;
222 s32 encounterIdx = encounterID / 32;
223 s32 encounterShift = encounterID % 32;
224
225 currentEncounter->defeatFlags[mapID][encounterIdx] |= (1 << encounterShift);*/
226}
227
228API_CALLABLE(ShowMerleeCoinMessage) {
229 if (isInitialCall) {
230 show_merlee_message(0, 60);
231 }
232
234 return ApiStatus_BLOCK;
235 } else {
236 return ApiStatus_DONE2;
237 }
238}
239
240API_CALLABLE(ShowMerleeRanOutMessage) {
241 if (isInitialCall) {
242 show_merlee_message(1, 60);
243 }
244
246 return ApiStatus_BLOCK;
247 } else {
248 return ApiStatus_DONE2;
249 }
250}
251
252API_CALLABLE(FadeBackgroundDarken) {
253 if (isInitialCall) {
256 mdl_set_shroud_tint_params(0, 0, 0, 0);
257 script->functionTemp[0] = 25;
258 }
259
260 mdl_set_shroud_tint_params(0, 0, 0, ((25 - script->functionTemp[0]) * 10) & 254);
261 script->functionTemp[0]--;
262
263 if (script->functionTemp[0] == 0) {
264 return ApiStatus_DONE2;
265 } else {
266 return ApiStatus_BLOCK;
267 }
268}
269
270API_CALLABLE(FadeBackgroundLighten) {
271 if (isInitialCall) {
272 script->functionTemp[0] = 25;
273 }
274
275 mdl_set_shroud_tint_params(0, 0, 0, (script->functionTemp[0] * 10) & 254);
276 script->functionTemp[0] -= 5;
277
278 if (script->functionTemp[0] == 0) {
279 mdl_set_shroud_tint_params(0, 0, 0, 0);
280 return ApiStatus_DONE2;
281 } else {
282 return ApiStatus_BLOCK;
283 }
284}
285
286API_CALLABLE(FadeInMerlee) {
288
289 if (isInitialCall) {
291 npc->alpha = 0;
292 }
293
294 npc->alpha += 17;
295
296 if ((u32)(npc->alpha & 0xFF) >= 0xFF) {
297 npc->alpha = 0xFF;
298 return ApiStatus_DONE1;
299 } else {
300 return ApiStatus_BLOCK;
301 }
302}
303
304API_CALLABLE(FadeOutMerlee) {
306
307 npc->alpha -= 17;
308 if (npc->alpha == 0) {
309 npc->alpha = 0;
310 return ApiStatus_DONE1;
311 } else {
312 return ApiStatus_BLOCK;
313 }
314}
315
316// same as BattleMerleeUpdateFX aside from syms
317API_CALLABLE(MerleeUpdateFX) {
320
321 if (isInitialCall) {
322 script->functionTemp[1] = 0;
324 WorldMerleeOrbEffect = fx_energy_orb_wave(0, merlee->pos.x, merlee->pos.y, merlee->pos.z, 0.4f, 0);
325 WorldMerleeWaveEffect = fx_energy_orb_wave(3, merlee->pos.x, merlee->pos.y, merlee->pos.z, 0.00001f, 0);
329 }
330
331 merlee->pos.y = WorldMerleeBasePosY + sin_rad(DEG_TO_RAD(script->functionTemp[1])) * 3.0f;
332
333 script->functionTemp[1] += 10;
334 script->functionTemp[1] = clamp_angle(script->functionTemp[1]);
335
337 effectData->pos.x = merlee->pos.x;
338 effectData->pos.y = merlee->pos.y + 16.0f;
339 effectData->pos.z = merlee->pos.z;
340
342 effectData->pos.x = merlee->pos.x;
343 effectData->pos.y = merlee->pos.y + 16.0f;
344 effectData->pos.z = merlee->pos.z + 5.0f;
345
351 return ApiStatus_DONE1;
352 }
353
356 effectData->scale += 0.35;
357 if (effectData->scale > 3.5) {
358 effectData->scale = 3.5;
359 }
360
361 if (WorldMerleeEffectsTime != 0) {
363 } else {
365 effectData->scale += 0.5;
366 if (effectData->scale > 5.0) {
368 }
369 }
370 }
371 return ApiStatus_BLOCK;
372}
373
374API_CALLABLE(MerleeStopFX) {
376 return ApiStatus_DONE2;
377}
378
379API_CALLABLE(GetCamLookAtObjVector) {
383
384 return ApiStatus_DONE2;
385}
386
387API_CALLABLE(HasMerleeCasts) {
388 script->varTable[0] = FALSE;
390 script->varTable[0] = TRUE;
391 }
392
393 return ApiStatus_DONE2;
394}
395
396API_CALLABLE(PlayMerleeGatherFX) {
397 Bytecode* args = script->ptrReadPos;
398 s32 var0 = evt_get_variable(script, *args++);
399 s32 var1 = evt_get_variable(script, *args++);
400 s32 var2 = evt_get_variable(script, *args++);
401
402 fx_energy_in_out(6, var0, var1, var2, 1.2f, 30);
403 return ApiStatus_DONE2;
404}
405
406API_CALLABLE(PlayMerleeOrbFX) {
407 Bytecode* args = script->ptrReadPos;
408 s32 var0 = evt_get_variable(script, *args++);
409 s32 var1 = evt_get_variable(script, *args++);
410 s32 var2 = evt_get_variable(script, *args++);
411
412 fx_energy_orb_wave(9, var0, var1, var2, 5.0f, 15);
413 return ApiStatus_DONE2;
414}
415
416API_CALLABLE(OnDefeatEnemy) {
417 Enemy* enemy = script->owner1.enemy;
418 Npc* npc = get_npc_unsafe(enemy->npcID);
419 s32 temp1;
420
421 if (isInitialCall) {
422 script->functionTemp[0] = 0;
423 script->functionTemp[1] = 20;
424 }
425
426 if (script->functionTemp[1] & 1) {
428 } else {
430 }
431
432 if (script->functionTemp[1] == 15) {
434 fx_damage_stars(FX_DAMAGE_STARS_1, npc->pos.x, npc->pos.y + (npc->collisionHeight / 2), npc->pos.z, 0, -1.0f, 0, 10);
435 }
436
437 temp1 = script->functionTemp[1];
438 if (script->functionTemp[1] == 10) {
439 fx_big_smoke_puff(npc->pos.x, npc->pos.y + 10.0f, npc->pos.z + 10.0f);
440 if (script->functionTemp[1] == temp1) { // what? (never can be false, seemingly)
441 spawn_drops(enemy);
442 }
443 }
444
445 script->functionTemp[1]--;
446 if (script->functionTemp[1] == 0) {
448 return ApiStatus_DONE1;
449 }
450
451 return ApiStatus_BLOCK;
452}
453
454API_CALLABLE(OnFleeBattleDrops) {
457
458 if (isInitialCall) {
459 script->functionTemp[0] = 0;
460 script->functionTemp[1] = 40;
461 script->functionTemp[2] = 0;
462 }
463
464 script->functionTemp[2]++;
465 if (script->functionTemp[2] >= 5) {
466 if (rand_int(100) < 50) {
467 if (playerData->coins != 0) {
468 playerData->coins--;
470 playerStatus->pos.y + playerStatus->colliderHeight, playerStatus->pos.z,
472 }
473 }
474 script->functionTemp[2] = 0;
475 }
476
477 return --script->functionTemp[1] == 0;
478}
479
484 s32 screenX, screenY, screenZ;
485 f32 npcX, npcY, npcZ;
486 f32 npcYaw;
488 f32 x, y, z;
489 s32 e;
491 f32 playerYaw;
493 Evt* script;
494 Npc* npc;
499
500 s32 triggeredBattle;
501 s32 cond2;
502 s32 firstStrikeType;
503 s32 suspendTime;
504
505 Enemy* enemy;
507 s32 i;
508
509 f32 playerJumpColHeight = 37.0f;
510 f32 playerColRadius = 14.0f;
511 f32 playerColHeight = 18.0f;
512
513 f32 dx, dz;
515
517 goto START_BATTLE;
518 }
519
520 currentEncounter->songID = -1;
521 currentEncounter->unk_18 = -1;
522 currentEncounter->hitType = 0;
523 currentEncounter->forbidFleeing = FALSE;
524 currentEncounter->dropWhackaBump = FALSE;
528
529 playerX = playerStatus->pos.x;
530 playerY = playerStatus->pos.y;
531 playerZ = playerStatus->pos.z;
532 playerYaw = playerStatus->spriteFacingAngle;
533
534 if (playerYaw < 180.0f) {
535 playerYaw = clamp_angle(camera->curYaw - 90.0f);
536 } else {
537 playerYaw = clamp_angle(camera->curYaw + 90.0f);
538 }
539
540 if (currentEncounter->battleTriggerCooldown != 0) {
542 currentEncounter->battleTriggerCooldown--;
543 }
544 if (playerStatus->blinkTimer != 0) {
545 if (!(playerStatus->flags & PS_FLAG_INPUT_DISABLED)) {
546 playerStatus->blinkTimer = currentEncounter->battleTriggerCooldown;
547 } else {
548 playerStatus->blinkTimer = 1;
549 }
550 }
551 }
552
553 for (e = 0; e < currentEncounter->numEncounters; e++) {
554 encounter = currentEncounter->encounterList[e];
555 if (encounter == NULL) {
556 continue;
557 }
558 for (i = 0; i < encounter->count; i++) {
559 enemy = encounter->enemy[i];
560 if (enemy == NULL || (enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
561 continue;
562 }
563 npc = get_npc_unsafe(enemy->npcID);
564 if (enemy->aiSuspendTime != 0) {
566 enemy->aiSuspendTime--;
567 suspendTime = enemy->aiSuspendTime;
568 } else {
569 suspendTime = 0;
570 }
571
572 if (suspendTime & 1) {
574 enemy->flags |= ENEMY_FLAG_SUSPENDED;
575 } else {
578 }
579
581 if (script != NULL) {
583 }
585 if (script != NULL) {
587 }
588
591 if (script != NULL) {
593 }
595 if (script != NULL) {
597 }
598 }
599 } else if (!(enemy->flags & ENEMY_FLAG_ACTIVE_WHILE_OFFSCREEN)) {
603 enemy->flags |= ENEMY_FLAG_SUSPENDED;
605 if (script != NULL) {
607 }
609 if (script != NULL) {
611 }
612 } else {
616 if (script != NULL) {
618 }
620 if (script != NULL) {
622 }
623 }
624 } else {
628 if (script != NULL) {
630 }
632 if (script != NULL) {
634 }
635 }
636
637 if (enemy->flags & ENEMY_FLAG_SUSPENDED) {
638 continue;
639 }
640 if (enemy->flags & ENEMY_FLAG_PASSIVE) {
642 if (npc == playerStatus->encounteredNPC) {
643 enemy->savedNpcYaw = npc->yaw;
644 npc->yaw = atan2(npc->pos.x, npc->pos.z, playerStatus->pos.x, playerStatus->pos.z);
646 if (script != NULL) {
648 }
649 } else {
650 if (enemy->savedNpcYaw != 12345) {
651 npc->yaw = enemy->savedNpcYaw;
652 enemy->savedNpcYaw = 12345;
653 }
655 if (script != NULL) {
657 }
658 }
659 } else {
661 if (script != NULL) {
663 }
664 }
665 }
666
667 if (currentEncounter->battleTriggerCooldown != 0
672 || (enemy->flags & ENEMY_FLAG_PASSIVE)
675 ) {
676 continue;
677 }
678
682 currentEncounter->curEncounter = encounter;
683 currentEncounter->curEnemy = enemy;
684 currentEncounter->firstStrikeType = FIRST_STRIKE_PLAYER;
685 goto START_BATTLE;
686 }
687
688 npcX = npc->pos.x;
689 npcY = npc->pos.y;
690 npcZ = npc->pos.z;
691 npcYaw = npc->yaw;
693 colRadius = npc->collisionDiameter / 2;
694
695 if (enemy->unk_DC != 0) {
696 npcYaw = npc->yawCamOffset;
697 if (npcYaw < 180.0f) {
698 npcYaw = clamp_angle(camera->curYaw - 90.0f);
699 } else {
700 npcYaw = clamp_angle(camera->curYaw + 90.0f);
701 }
702
704 }
705
706 dx = npcX - playerX;
707 dz = npcZ - playerZ;
708 distance = sqrtf(SQ(dx) + SQ(dz));
709
710 switch (playerStatus->actionState) {
712 x = playerX;
713 y = playerY;
714 z = playerZ;
715 if (clamp_angle(playerStatus->spriteFacingAngle) < 180.0f) {
716 hammerDir = clamp_angle(camera->curYaw - 90.0f);
717 if (playerStatus->trueAnimation & SPRITE_ID_BACK_FACING) {
719 }
720 } else {
721 hammerDir = clamp_angle(camera->curYaw + 90.0f);
722 if (playerStatus->trueAnimation & SPRITE_ID_BACK_FACING) {
724 }
725 }
726 add_vec2D_polar(&x, &z, 24.0f, hammerDir);
727 dx = npcX - x;
728 dz = npcZ - z;
729 distance = sqrtf(SQ(dx) + SQ(dz));
730 if (enemy->flags & ENEMY_FLAG_IGNORE_HAMMER) {
731 break;
732 }
733 if (!(playerStatus->flags & PS_FLAG_HAMMER_CHECK)) {
734 break;
735 }
737 break;
738 }
739
740 testX = npcX;
741 testY = npcY;
742 testZ = npcZ;
743
745 testX = playerX;
746 testY = playerY;
747 testZ = playerZ;
749 break;
750 }
751 }
752 if (enemy->hitboxIsActive) {
753 npcX = enemy->unk_10.x;
754 npcY = enemy->unk_10.y;
755 npcZ = enemy->unk_10.z;
756 }
757
761 if (angle1 >= 90.0f && angle2 >= 90.0f) {
763 }
764 if (angle1 < 90.0f && angle2 >= 90.0f) {
766 }
767 if (angle1 >= 90.0f && angle2 < 90.0f) {
769 }
770 if (angle1 < 90.0f && angle2 < 90.0f) {
772 }
773 if (triggeredBattle) {
778 currentEncounter->curEncounter = encounter;
779 currentEncounter->curEnemy = enemy;
780 currentEncounter->firstStrikeType = FIRST_STRIKE_PLAYER;
781 goto START_BATTLE;
782 }
783 break;
794 x = playerX;
795 z = playerZ;
796 if (!(enemy->flags & ENEMY_FLAG_IGNORE_JUMP)) {
798 continue;
799 }
801 continue;
802 }
803
804 testX = npcX;
805 testY = npcY;
806 testZ = npcZ;
808 testX = playerX;
809 testY = playerY;
810 testZ = playerZ;
812 break;
813 }
814 }
816 if (npcY + colHeight < playerY + playerJumpColHeight * 0.5f) {
817 if (playerStatus->actionState == ACTION_STATE_FALLING ||
818 playerStatus->actionState == ACTION_STATE_STEP_DOWN ||
819 playerStatus->actionState == ACTION_STATE_LAND ||
821 playerStatus->actionState == ACTION_STATE_SPIN_JUMP ||
822 playerStatus->actionState == ACTION_STATE_SPIN_POUND ||
823 playerStatus->actionState == ACTION_STATE_TORNADO_JUMP ||
826 }
827 }
828 if (playerY + playerJumpColHeight < npcY + colHeight * 0.5f) {
830 }
831 if (triggeredBattle) {
832 if (gPlayerData.bootsLevel < 0) {
835 currentEncounter->curEncounter = encounter;
836 currentEncounter->curEnemy = enemy;
837 currentEncounter->firstStrikeType = FIRST_STRIKE_NONE;
838 currentEncounter->hitTier = 0;
839 goto START_BATTLE;
840 }
842 switch (playerStatus->actionState) {
849 currentEncounter->hitTier = 0;
850 break;
853 currentEncounter->hitTier = 1;
854 break;
857 currentEncounter->hitTier = 2;
858 break;
859 }
862 currentEncounter->curEncounter = encounter;
863 currentEncounter->curEnemy = enemy;
864 currentEncounter->firstStrikeType = FIRST_STRIKE_PLAYER;
865 goto START_BATTLE;
866 }
867 }
868 break;
869 }
870
871 if (enemy->flags & ENEMY_FLAG_IGNORE_TOUCH) {
872 continue;
873 }
874
875 dx = npcX - playerX;
876 dz = npcZ - playerZ;
877 distance = sqrtf(SQ(dx) + SQ(dz));
878
879 if (distance >= (playerColRadius + colRadius) * 0.8) {
880 continue;
881 }
882 if (npcY + colHeight < playerY) {
883 continue;
884 }
886 continue;
887 }
888
889 testX = npcX;
890 testY = npcY;
891 testZ = npcZ;
893 testX = playerX;
894 testY = playerY;
895 testZ = playerZ;
897 continue;
898 }
899 }
902 triggeredBattle = !currentEncounter->scriptedBattle;
903 }
906 }
907 if ((playerStatus->animFlags & PA_FLAG_SPINNING) && !(enemy->flags & ENEMY_FLAG_IGNORE_SPIN) && triggeredBattle) {
909 testX = playerStatus->pos.x + ((npc->pos.x - playerStatus->pos.x) * 0.5f);
910 testY = playerStatus->pos.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->pos.y + playerStatus->colliderHeight)) * 0.5f);
911 testZ = playerStatus->pos.z + ((npc->pos.z - playerStatus->pos.z) * 0.5f);
912 fx_damage_stars(FX_DAMAGE_STARS_3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
916 currentEncounter->curEncounter = encounter;
917 currentEncounter->curEnemy = enemy;
918 currentEncounter->firstStrikeType = FIRST_STRIKE_NONE;
919 } else {
923 currentEncounter->curEncounter = encounter;
924 currentEncounter->curEnemy = enemy;
925 testX = playerStatus->pos.x + ((npc->pos.x - playerStatus->pos.x) * 0.5f);
926 testY = playerStatus->pos.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->pos.y + playerStatus->colliderHeight)) * 0.5f);
927 testZ = playerStatus->pos.z + ((npc->pos.z - playerStatus->pos.z) * 0.5f);
928 fx_damage_stars(FX_DAMAGE_STARS_3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
929 // if the hitbox is active, trigger a first strike
930 firstStrikeType = FIRST_STRIKE_NONE;
931 if (enemy->hitboxIsActive) {
933 firstStrikeType = FIRST_STRIKE_NONE;
934 } else {
935 firstStrikeType = FIRST_STRIKE_ENEMY;
936 }
937 }
938 // cancel the first strike if bump attack is applicable
940 && (gPlayerData.level >= enemy->npcSettings->level)
941 && !(enemy->flags & ENEMY_FLAG_PROJECTILE))
942 && !currentEncounter->scriptedBattle
943 ) {
944 firstStrikeType = FIRST_STRIKE_NONE;
945 }
946 currentEncounter->firstStrikeType = firstStrikeType;
947 }
948 goto START_BATTLE;
949 }
950 }
951
953 switch (currentEncounter->hitType) {
954 case 0:
955 break;
957 currentEnemy = enemy = currentEncounter->curEnemy;
958 if (enemy->aiScript != NULL) {
960 }
961 if (enemy->auxScript != NULL) {
963 }
964 encounter = currentEncounter->curEncounter;
965 for (i = 0; i < encounter->count; i++) {
966 enemy = encounter->enemy[i];
967 if (enemy == NULL) {
968 continue;
969 }
970 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
971 continue;
972 }
973 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
974 continue;
975 }
976 if ((currentEnemy->flags & ENEMY_FLAG_PROJECTILE) && enemy != currentEncounter->curEnemy) {
977 continue;
978 }
979
980 if (enemy->hitBytecode != NULL) {
983 enemy->hitScript = script;
984 enemy->hitScriptID = script->id;
985 script->owner1.enemy = enemy;
986 script->owner2.npcID = enemy->npcID;
987 script->groupFlags = enemy->scriptGroup;
988 }
989 }
992 if (playerStatus->actionState != ACTION_STATE_TORNADO_JUMP &&
994 playerStatus->actionState != ACTION_STATE_SPIN_JUMP &&
995 playerStatus->actionState != ACTION_STATE_SPIN_POUND) {
997 }
1000 npc = get_npc_unsafe(enemy->npcID);
1002 }
1003 currentEncounter->scriptedBattle = FALSE;
1004 currentEncounter->fadeOutAmount = 0;
1005 currentEncounter->substateDelay = 0;
1009 break;
1011 currentEnemy = enemy = currentEncounter->curEnemy;
1012 if (enemy->aiScript != NULL) {
1014 }
1015 if (enemy->auxScript != NULL) {
1017 }
1018 encounter = currentEncounter->curEncounter;
1019 for (i = 0; i < encounter->count; i++) {
1020 enemy = encounter->enemy[i];
1021 if (enemy == NULL) {
1022 continue;
1023 }
1024 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
1025 continue;
1026 }
1027 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
1028 continue;
1029 }
1030 if ((currentEnemy->flags & ENEMY_FLAG_PROJECTILE) && enemy != currentEncounter->curEnemy) {
1031 continue;
1032 }
1033
1034 if (enemy->hitBytecode != NULL) {
1037 enemy->hitScript = script;
1038 enemy->hitScriptID = script->id;
1039 script->owner1.enemy = enemy;
1040 script->owner2.npcID = enemy->npcID;
1041 script->groupFlags = enemy->scriptGroup;
1042 }
1043 }
1046 currentEncounter->scriptedBattle = FALSE;
1047 currentEncounter->fadeOutAmount = 0;
1048 currentEncounter->substateDelay = 0;
1053 break;
1055 currentEnemy = enemy = currentEncounter->curEnemy;
1056 if (enemy->aiScript != NULL) {
1058 }
1059 if (enemy->auxScript != NULL) {
1061 }
1062 encounter = currentEncounter->curEncounter;
1063
1064 cond2 = FALSE;
1065 for (i = 0; i < encounter->count; i++) {
1066 enemy = encounter->enemy[i];
1067 enemy = encounter->enemy[i];
1068 if (enemy == NULL) {
1069 continue;
1070 }
1071 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
1072 continue;
1073 }
1074 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
1075 continue;
1076 }
1077 if ((currentEnemy->flags & ENEMY_FLAG_PROJECTILE) && enemy != currentEncounter->curEnemy) {
1078 continue;
1079 }
1080 if (enemy->hitBytecode != NULL) {
1083 enemy->hitScript = script;
1084 enemy->hitScriptID = script->id;
1085 script->owner1.enemy = enemy;
1086 script->owner2.npcID = enemy->npcID;
1087 script->groupFlags = enemy->scriptGroup;
1088 npc = get_npc_unsafe(enemy->npcID);
1089 cond2 = TRUE;
1090 testX = playerStatus->pos.x + ((npc->pos.x - playerStatus->pos.x) * 0.5f);
1091 testY = playerStatus->pos.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->pos.y + playerStatus->colliderHeight)) * 0.5f);
1092 testZ = playerStatus->pos.z + ((npc->pos.z - playerStatus->pos.z) * 0.5f);
1093 fx_damage_stars(FX_DAMAGE_STARS_3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
1094 } else if (!(enemy->flags & ENEMY_FLAG_PASSIVE)) {
1095 npc = get_npc_unsafe(enemy->npcID);
1096 cond2 = TRUE;
1097 testX = playerStatus->pos.x + ((npc->pos.x - playerStatus->pos.x) * 0.5f);
1098 testY = playerStatus->pos.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->pos.y + playerStatus->colliderHeight)) * 0.5f);
1099 testZ = playerStatus->pos.z + ((npc->pos.z - playerStatus->pos.z) * 0.5f);
1100 fx_damage_stars(FX_DAMAGE_STARS_3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
1101 }
1102 }
1106 if (cond2) {
1108 }
1109 currentEncounter->fadeOutAmount = 0;
1110 currentEncounter->substateDelay = 0;
1111 currentEncounter->scriptedBattle = FALSE;
1116 break;
1118 currentEnemy = enemy = currentEncounter->curEnemy;
1119 if (enemy->aiScript != NULL) {
1121 }
1122 if (enemy->auxScript != NULL) {
1124 }
1125 encounter = currentEncounter->curEncounter;
1126 for (i = 0; i < encounter->count; i++) {
1127 enemy = encounter->enemy[i];
1128 if (enemy == NULL) {
1129 continue;
1130 }
1131 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
1132 continue;
1133 }
1134 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
1135 continue;
1136 }
1137 if ((currentEnemy->flags & ENEMY_FLAG_PROJECTILE) && enemy != currentEncounter->curEnemy) {
1138 continue;
1139 }
1140 if (enemy->hitBytecode != NULL) {
1143 enemy->hitScript = script;
1144 enemy->hitScriptID = script->id;
1145 script->owner1.enemy = enemy;
1146 script->owner2.npcID = enemy->npcID;
1147 script->groupFlags = enemy->scriptGroup;
1148 npc = get_npc_unsafe(enemy->npcID);
1149 testX = playerStatus->pos.x + ((npc->pos.x - playerStatus->pos.x) * 0.5f);
1150 testY = playerStatus->pos.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->pos.y + playerStatus->colliderHeight)) * 0.5f);
1151 testZ = playerStatus->pos.z + ((npc->pos.z - playerStatus->pos.z) * 0.5f);
1152 fx_damage_stars(FX_DAMAGE_STARS_3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
1153 } else if (!(enemy->flags & ENEMY_FLAG_PASSIVE)) {
1154 npc = get_npc_unsafe(enemy->npcID);
1155 testX = playerStatus->pos.x + ((npc->pos.x - playerStatus->pos.x) * 0.5f);
1156 testY = playerStatus->pos.y + (((npc->pos.y + npc->collisionHeight) - (playerStatus->pos.y + playerStatus->colliderHeight)) * 0.5f);
1157 testZ = playerStatus->pos.z + ((npc->pos.z - playerStatus->pos.z) * 0.5f);
1158 fx_damage_stars(FX_DAMAGE_STARS_3, npc->pos.x, npc->pos.y + npc->collisionHeight, npc->pos.z, 0.0f, -1.0f, 0.0f, 3);
1159 }
1160 }
1163 currentEncounter->fadeOutAmount = 0;
1164 currentEncounter->substateDelay = 0;
1165 currentEncounter->scriptedBattle = FALSE;
1171 break;
1174 enemy = currentEncounter->curEnemy;
1175 if (enemy != NULL && enemy->aiScript != NULL) {
1177 }
1178 enemy = currentEncounter->curEnemy;
1179 if (enemy->interactBytecode != NULL) {
1182 enemy->interactScript = script;
1183 enemy->interactScriptID = script->id;
1184 script->owner1.enemy = enemy;
1185 script->owner2.npcID = enemy->npcID;
1186 script->groupFlags = enemy->scriptGroup;
1187 }
1191 currentEncounter->fadeOutAmount = 0;
1192 currentEncounter->substateDelay = 0;
1193 func_800EF3D4(1);
1197 break;
1199 currentEnemy = enemy = currentEncounter->curEnemy;
1200 if (enemy->aiScript != NULL) {
1202 }
1203 if (enemy->auxScript != NULL) {
1205 }
1206 encounter = currentEncounter->curEncounter;
1207
1208 for (i = 0; i < encounter->count; i++) {
1209 enemy = encounter->enemy[i];
1210 if (enemy == NULL) {
1211 continue;
1212 }
1213 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
1214 continue;
1215 }
1216 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
1217 continue;
1218 }
1219 if ((currentEnemy->flags & ENEMY_FLAG_PROJECTILE) && enemy != currentEncounter->curEnemy) {
1220 continue;
1221 }
1222 if (enemy->hitBytecode != NULL) {
1225 enemy->hitScript = script;
1226 enemy->hitScriptID = script->id;
1227 script->owner1.enemy = enemy;
1228 script->owner2.npcID = enemy->npcID;
1229 script->groupFlags = enemy->scriptGroup;
1230 npc = get_npc_unsafe(enemy->npcID);
1231 testX = npc->pos.x;
1232 testY = npc->pos.y + npc->collisionHeight;
1233 testZ = npc->pos.z;
1234 fx_damage_stars(FX_DAMAGE_STARS_3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
1235 } else if (!(enemy->flags & ENEMY_FLAG_PASSIVE)) {
1236 npc = get_npc_unsafe(enemy->npcID);
1237 testX = npc->pos.x;
1238 testY = npc->pos.y + npc->collisionHeight;
1239 testZ = npc->pos.z;
1240 fx_damage_stars(FX_DAMAGE_STARS_3, testX, testY, testZ, 0.0f, -1.0f, 0.0f, 3);
1241 }
1242 }
1245 currentEncounter->fadeOutAmount = 0;
1246 currentEncounter->substateDelay = 0;
1247 currentEncounter->scriptedBattle = FALSE;
1253 break;
1254 }
1255}
1256
1258}
1259
1264 Enemy* enemy;
1265 s32 i;
1266 s32 j;
1267
1268 switch (gEncounterSubState) {
1270 currentEncounter->fadeOutAmount = 0;
1271 currentEncounter->substateDelay = 1;
1272 currentEncounter->fadeOutAccel = 1;
1273 currentEncounter->unk_08 = -1;
1275 D_80077C40 = FALSE;
1277
1278 // suspend all ai scripts
1279 for (i = 0; i < currentEncounter->numEncounters; i++) {
1280 encounter = currentEncounter->encounterList[i];
1281
1282 if (encounter != NULL) {
1283 for (j = 0; j < encounter->count; j++) {
1284 enemy = encounter->enemy[j];
1285 if (enemy != NULL && !(enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
1286 if (enemy->aiScript != NULL) {
1288 }
1289 if (enemy->auxScript != NULL) {
1291 }
1292 }
1293 }
1294 }
1295 }
1296
1297 // try skip-on-contact
1298 enemy = currentEncounter->curEnemy;
1299 if ((enemy->flags & ENEMY_FLAG_SKIP_BATTLE) && !currentEncounter->scriptedBattle) {
1300 currentEncounter->substateDelay = 0;
1301 currentEncounter->battleStartCountdown = 0;
1304 return;
1305 }
1306
1307 // try kill-on-contact
1309 currentEncounter->substateDelay = 0;
1310 currentEncounter->battleStartCountdown = 10;
1313 return;
1314 }
1315
1316 // try first attack kill
1317 enemy = currentEncounter->curEnemy;
1321 && (playerData->level >= enemy->npcSettings->level)
1322 && !(enemy->flags & ENEMY_FLAG_PROJECTILE)
1323 && !currentEncounter->scriptedBattle
1324 ) {
1325 currentEncounter->substateDelay = 0;
1326 currentEncounter->battleStartCountdown = 10;
1327 D_80077C40 = TRUE;
1329 return;
1330 }
1331
1332 // try bump attack kill
1333 enemy = currentEncounter->curEnemy;
1335 && (playerData->level >= enemy->npcSettings->level)
1336 && !(enemy->flags & ENEMY_FLAG_PROJECTILE)
1337 && !(currentEncounter->scriptedBattle)
1338 ) {
1339 currentEncounter->substateDelay = 0;
1340 currentEncounter->battleStartCountdown = 10;
1341 D_80077C40 = TRUE;
1343 return;
1344 }
1345
1346 // try spin attack kill
1347 enemy = currentEncounter->curEnemy;
1350 && playerData->level >= enemy->npcSettings->level
1351 && !(enemy->flags & ENEMY_FLAG_PROJECTILE)
1352 && !currentEncounter->scriptedBattle
1353 ) {
1354 currentEncounter->substateDelay = 0;
1355 currentEncounter->battleStartCountdown = 10;
1356 D_80077C40 = TRUE;
1358 return;
1359 }
1360
1361 // start battle music
1362 if (currentEncounter->songID < 0) {
1363 switch (currentEncounter->firstStrikeType) {
1364 case FIRST_STRIKE_NONE:
1366 break;
1369 break;
1370 case FIRST_STRIKE_ENEMY:
1372 break;
1373 }
1374 } else {
1376 }
1379
1380 currentEncounter->battleStartCountdown = 10;
1382 // fallthrough
1384 // wait for screen to fade out
1385 if (currentEncounter->fadeOutAmount != 255) {
1386 break;
1387 }
1388 // delay before loading the battle
1389 if (currentEncounter->battleStartCountdown != 0) {
1390 currentEncounter->battleStartCountdown--;
1391 break;
1392 }
1393
1394 // kill all enemy hit scripts
1395 encounter = currentEncounter->curEncounter;
1396 for (i = 0; i < encounter->count; i++) {
1397 enemy = encounter->enemy[i];
1398 if (enemy != NULL &&
1399 ((!(enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) || enemy == currentEncounter->curEnemy)) &&
1400 !(enemy->flags & ENEMY_FLAG_DISABLE_AI) &&
1401 enemy->hitScript != NULL)
1402 {
1404 enemy->hitScript = NULL;
1405 }
1406 }
1407
1409 currentEncounter->dizzyAttack.status = 0;
1410 currentEncounter->dizzyAttack.duration = 0;
1411
1412 enemy = currentEncounter->curEnemy;
1414
1416 currentEncounter->dizzyAttack.status = 4;
1417 currentEncounter->dizzyAttack.duration = 3;
1418 }
1419
1426 load_battle(encounter->battle);
1427 currentEncounter->unk_07 = 1;
1428 currentEncounter->unk_08 = 0;
1429 currentEncounter->hasMerleeCoinBonus = FALSE;
1430 currentEncounter->damageTaken = 0;
1431 currentEncounter->coinsEarned = 0;
1432 currentEncounter->fadeOutAccel = 0;
1433 currentEncounter->fadeOutAmount = 255;
1435
1436 // prepare to resume after battle
1440 break;
1442 if (currentEncounter->battleStartCountdown != 0) {
1443 currentEncounter->battleStartCountdown--;
1444 break;
1445 }
1446
1447 encounter = currentEncounter->curEncounter;
1448 for (i = 0; i < encounter->count; i++) {
1449 enemy = encounter->enemy[i];
1450 if (enemy != NULL &&
1451 (!(enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) || enemy == currentEncounter->curEnemy) &&
1452 !(enemy->flags & ENEMY_FLAG_DISABLE_AI) &&
1453 (enemy->hitScript != 0))
1454 {
1456 enemy->hitScript = NULL;
1457 }
1458 }
1459
1460 currentEncounter->unk_08 = 1;
1461 currentEncounter->unk_07 = 1;
1462 currentEncounter->battleOutcome = OUTCOME_PLAYER_WON;
1463 currentEncounter->hasMerleeCoinBonus = FALSE;
1464 currentEncounter->damageTaken = 0;
1465 currentEncounter->coinsEarned = 0;
1466
1467 currentEncounter->fadeOutAccel = 0;
1468 currentEncounter->fadeOutAmount = 0;
1472 break;
1474 currentEncounter->battleOutcome = OUTCOME_SKIP;
1475 currentEncounter->unk_08 = 1;
1476
1477 currentEncounter->fadeOutAmount = 0;
1478 currentEncounter->fadeOutAccel = 0;
1482 break;
1483 }
1484}
1485
1489
1490#if DX_DEBUG_MENU
1491 Npc* npc = NULL;
1492 if (encounter->curEnemy->npcID != (s16) DX_DEBUG_DUMMY_ID) {
1493 npc = get_npc_unsafe(encounter->curEnemy->npcID);
1494 }
1495#else
1496 Npc* npc = get_npc_unsafe(encounter->curEnemy->npcID);
1497#endif
1498
1499 if (encounter->substateDelay != 0) {
1504
1505 if (encounter->fadeOutAmount != 255) {
1506 encounter->fadeOutAccel++;
1507 if (encounter->fadeOutAccel > 10) {
1508 encounter->fadeOutAccel = 10;
1509 }
1510
1511 encounter->fadeOutAmount += encounter->fadeOutAccel;
1512 if (encounter->fadeOutAmount > 255) {
1513 encounter->fadeOutAmount = 255;
1514 }
1515
1516 playerX = playerStatus->pos.x;
1517 playerY = playerStatus->pos.y;
1518 playerZ = playerStatus->pos.z;
1519
1520 #if DX_DEBUG_MENU
1521 if (npc != NULL) {
1522 otherX = npc->pos.x;
1523 otherY = npc->pos.y;
1524 otherZ = npc->pos.z;
1525 } else {
1526 otherX = playerX;
1527 otherY = playerY;
1528 otherZ = playerZ;
1529 }
1530 #else
1531 otherX = npc->pos.x;
1532 otherY = npc->pos.y;
1533 otherZ = npc->pos.z;
1534 #endif
1535 if (otherY < -990.0f) {
1536 otherX = playerX;
1537 otherY = playerY;
1538 otherZ = playerZ;
1539 }
1540
1548 (pScreenY - oScreenY) / 2 + oScreenY);
1549 } else {
1556 (pScreenY - oScreenY) / 2 + oScreenY);
1557 }
1558 }
1559 }
1560}
1561
1564 s32 posX;
1565 s32 width;
1566 s32 xOffset;
1567 s32 screenWidthHalf;
1568
1569 if (currentEncounter->substateDelay == 0) {
1571 return;
1572 }
1573
1575 xOffset = gFirstStrikeMessagePos;
1576 if (xOffset > 0) {
1577 if (xOffset < 1600) {
1578 xOffset = 0;
1579 } else {
1580 xOffset -= 1600;
1581 }
1582 }
1583
1585
1586 switch (currentEncounter->firstStrikeType) {
1588 switch (currentEncounter->hitType) {
1592 posX = (xOffset + screenWidthHalf) - (width / 2);
1593 draw_box(0, WINDOW_STYLE_20, posX, 69, 0, width, 28, 255, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, NULL, 0, NULL,
1595 draw_msg(MSG_Menus_PlayerFirstStrike, posX + 11, 75, 0xFF, MSG_PAL_STANDARD, 0);
1596 break;
1599 posX = (xOffset + screenWidthHalf) - (width / 2);
1600 draw_box(0, WINDOW_STYLE_20, posX, 69, 0, width, 28, 255, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, NULL, 0, NULL,
1602 draw_msg(MSG_Menus_PartnerFirstStrike, posX + 11, 75, 0xFF, MSG_PAL_STANDARD, 0);
1603 break;
1604 }
1605 break;
1606 case FIRST_STRIKE_ENEMY:
1609 posX = (xOffset + screenWidthHalf) - (width / 2);
1610 draw_box(0, WINDOW_STYLE_4, posX, 69, 0, width, 28, 255, 0, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, NULL, 0, NULL,
1612 draw_msg(MSG_Menus_EnemyFirstStrike, posX + 11, 75, 0xFF, MSG_PAL_STANDARD, 0);
1613 }
1614 break;
1615 }
1616}
1617
1624 Evt* script;
1625 Enemy* enemy;
1626 s32 i, j;
1627 s32 hasDefeatScript;
1628 Npc* npc;
1629
1630 switch (gEncounterSubState) {
1632 if (currentEncounter->unk_08 == 0) {
1633 return;
1634 }
1635
1636 currentEncounter->unk_08 = 0;
1638 currentEncounter->scriptedBattle = FALSE;
1640 currentEncounter->dizzyAttack.status = 0;
1641 currentEncounter->unusedAttack1.status = 0;
1642 currentEncounter->unusedAttack2.status = 0;
1643 currentEncounter->unusedAttack3.status = 0;
1644 currentEncounter->dizzyAttack.duration = 0;
1645 currentEncounter->unusedAttack1.duration = 0;
1646 currentEncounter->unusedAttack2.duration = 0;
1647 currentEncounter->unusedAttack3.duration = 0;
1650 }
1651 currentEncounter->fadeOutAccel = 1;
1652 currentEncounter->battleStartCountdown = 0;
1655 if (currentEncounter->hitType == ENCOUNTER_TRIGGER_SPIN) {
1657 }
1658 currentEncounter->hitType = 0;
1659 if (!D_80077C40) {
1661 }
1663 if (partnerStatus->shouldResumeAbility) {
1665 } else if (!LastBattleStartedBySpin
1669 ) {
1671 }
1672 switch (currentEncounter->battleOutcome) {
1673 case OUTCOME_PLAYER_WON:
1675 break;
1678 break;
1681 break;
1682 case OUTCOME_SKIP:
1684 break;
1685 case OUTCOME_ENEMY_FLED:
1687 break;
1688 }
1689 break;
1691 if (currentEncounter->hasMerleeCoinBonus) {
1692 if (get_coin_drop_amount(currentEncounter->curEnemy) != 0) {
1696 } else {
1697 playerData->merleeTurnCount = 0;
1698 playerData->merleeCastsLeft++;
1699 }
1700 }
1702 break;
1704 // fade screen in and wait for merlee bonus to finish (if applicable)
1705 if (currentEncounter->hasMerleeCoinBonus) {
1706 if (get_coin_drop_amount(currentEncounter->curEnemy) != 0) {
1707 currentEncounter->fadeOutAccel += 4;
1708 currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
1709 if (currentEncounter->fadeOutAmount < 0) {
1710 currentEncounter->fadeOutAmount = 0;
1711 }
1713 break;
1714 }
1715 }
1716 }
1717 // start defeat scripts for current enemy
1718 encounter = currentEncounter->curEncounter;
1719 for (i = 0; i < encounter->count; i++) {
1720 enemy = encounter->enemy[i];
1721 if (enemy == NULL) {
1722 continue;
1723 }
1724 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
1725 continue;
1726 }
1727 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
1728 continue;
1729 }
1730 if (enemy->defeatBytecode != NULL) {
1732 enemy->defeatScript = script;
1733 enemy->defeatScriptID = script->id;
1734 script->owner1.enemy = enemy;
1735 script->owner2.npcID = enemy->npcID;
1736 script->groupFlags = EVT_GROUP_NEVER_PAUSE;
1737 currentEncounter->battleStartCountdown = 1;
1738 } else {
1740 enemy->defeatScript = script;
1741 enemy->defeatScriptID = script->id;
1742 script->owner1.enemy = enemy;
1743 script->owner2.npcID = enemy->npcID;
1744 script->groupFlags = EVT_GROUP_NEVER_PAUSE;
1745 }
1746 }
1749 && currentEncounter->battleStartCountdown == 0
1751 ) {
1753 }
1755 break;
1757 if (currentEncounter->fadeOutAmount == 0) {
1759 } else {
1760 currentEncounter->fadeOutAccel += 4;
1761 currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
1762 if (currentEncounter->fadeOutAmount < 0) {
1763 currentEncounter->fadeOutAmount = 0;
1764 }
1765 }
1766 break;
1768 // wait for all defeat scripts to finish
1770 encounter = currentEncounter->curEncounter;
1771 for (i = 0; i < encounter->count; i++) {
1772 enemy = encounter->enemy[i];
1773 if (enemy == NULL) {
1774 continue;
1775 }
1776 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
1777 continue;
1778 }
1779 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
1780 continue;
1781 }
1782 if (does_script_exist(enemy->defeatScriptID)) {
1784 } else {
1785 enemy->defeatScript = NULL;
1786 }
1787 }
1788 // kill defeated enemies
1789 if (!hasDefeatScript) {
1792 && currentEncounter->battleStartCountdown == 1
1793 ) {
1795 }
1796 encounter = currentEncounter->curEncounter;
1797 for (i = 0; i < encounter->count; i++) {
1798 enemy = encounter->enemy[i];
1799 enemy = encounter->enemy[i];
1800 if (enemy == NULL) {
1801 continue;
1802 }
1803 if (enemy->flags & ENEMY_FLAG_DO_NOT_KILL) {
1804 continue;
1805 }
1806 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
1807 continue;
1808 }
1809 if (!(enemy->flags & ENEMY_FLAG_PASSIVE)) {
1810 if (!(enemy->flags & ENEMY_FLAG_FLED)) {
1811 set_defeated(currentEncounter->mapID, encounter->encounterID + i);
1812 }
1813 }
1814 kill_enemy(enemy);
1815 }
1816
1817 currentEncounter->substateDelay = 0;
1820 && currentEncounter->battleStartCountdown == 1
1821 ) {
1822 currentEncounter->substateDelay = 30;
1823 }
1825 }
1826 break;
1829 if (gGameStatusPtr->stickX[0] != 0 || gGameStatusPtr->stickY[0] != 0) {
1830 currentEncounter->substateDelay = 0;
1831 }
1832 }
1833 if (currentEncounter->substateDelay != 0) {
1834 currentEncounter->substateDelay--;
1835 break;
1836 }
1837
1838 for (i = 0; i < currentEncounter->numEncounters; i++) {
1839 encounter = currentEncounter->encounterList[i];
1840 if (encounter == NULL) {
1841 continue;
1842 }
1843 for (j = 0; j < encounter->count; j++) {
1844 enemy = encounter->enemy[j];
1845 if (enemy == NULL || (enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
1846 continue;
1847 }
1848 if (enemy->aiScript != NULL) {
1850 }
1851 if (enemy->auxScript != NULL) {
1853 }
1854 }
1855 }
1856
1857 currentEncounter->battleTriggerCooldown = 15;
1862 }
1868 break;
1870 encounter = currentEncounter->curEncounter;
1871 for (i = 0; i < encounter->count; i++) {
1872 enemy = encounter->enemy[i];
1873 if (enemy == NULL) {
1874 continue;
1875 }
1876 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
1877 continue;
1878 }
1879 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
1880 continue;
1881 }
1882
1883 if (enemy->defeatBytecode != NULL) {
1885 enemy->defeatScript = script;
1886 enemy->defeatScriptID = script->id;
1887 enemy->aiFlags |= AI_FLAG_1;
1888 script->owner1.enemy = enemy;
1889 script->owner2.npcID = enemy->npcID;
1890 script->groupFlags = enemy->scriptGroup;
1891 }
1892 }
1894 break;
1896 if (currentEncounter->fadeOutAmount == 0) {
1898 } else {
1899 currentEncounter->fadeOutAccel += 4;
1900 currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
1901 if (currentEncounter->fadeOutAmount < 0) {
1902 currentEncounter->fadeOutAmount = 0;
1903 }
1904 }
1905 break;
1907 encounter = currentEncounter->curEncounter;
1909 for (i = 0; i < encounter->count; i++) {
1910 enemy = encounter->enemy[i];
1911 if (enemy == NULL) {
1912 continue;
1913 }
1914 if (!(enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
1915 if (does_script_exist(enemy->defeatScriptID)) {
1917 } else {
1918 enemy->defeatScript = NULL;
1919 }
1920 }
1921 }
1922 if (!hasDefeatScript) {
1923 for (i = 0; i < currentEncounter->numEncounters; i++) {
1924 encounter = currentEncounter->encounterList[i];
1925 if (encounter == NULL) {
1926 continue;
1927 }
1928 for (j = 0; j < encounter->count; j++) {
1929 enemy = encounter->enemy[j];
1930 if (enemy == NULL || (enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
1931 continue;
1932 }
1933 if (enemy->aiScript != NULL) {
1935 }
1936 if (enemy->auxScript != NULL) {
1938 }
1939 }
1940 }
1941
1942 enemy = currentEncounter->curEnemy;
1943 encounter = currentEncounter->curEncounter;
1944 if (!(enemy->flags & ENEMY_FLAG_NO_DELAY_AFTER_FLEE)) {
1945 enemy->aiSuspendTime = 45;
1946 playerStatus->blinkTimer = 45;
1947 for (j = 0; j < encounter->count; j++) {
1948 enemy = encounter->enemy[j];
1949 if (enemy == NULL) {
1950 continue;
1951 }
1952 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
1953 continue;
1954 }
1955 if (enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) {
1956 continue;
1957 }
1958 enemy->aiSuspendTime = 45;
1959 playerStatus->blinkTimer = 45;
1960 }
1961 }
1962
1963 enemy = currentEncounter->curEnemy;
1966 enemy->defeatScript = script;
1967 enemy->defeatScriptID = script->id;
1968 script->owner1.enemy = enemy;
1969 script->owner2.npcID = enemy->npcID;
1970 script->groupFlags = enemy->scriptGroup;
1971 }
1972
1973 currentEncounter->battleTriggerCooldown = 45;
1974 playerStatus->blinkTimer = 45;
1979 currentEncounter->substateDelay = 15;
1980 } else {
1981 currentEncounter->substateDelay = 0;
1982 }
1984 }
1985 break;
1987 if (currentEncounter->substateDelay != 0) {
1988 currentEncounter->substateDelay--;
1989 if (gGameStatusPtr->curButtons[0] == 0 && gGameStatusPtr->stickX[0] == 0 && gGameStatusPtr->stickY[0] == 0) {
1990 break;
1991 }
1992 }
1995 }
2000 break;
2003 encounter = currentEncounter->curEncounter;
2004 for (i = 0; i < encounter->count; i++) {
2005 enemy = encounter->enemy[i];
2006 if (enemy == NULL) {
2007 continue;
2008 }
2009 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
2010 continue;
2011 }
2012
2013 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
2014 continue;
2015 }
2016
2017 if (enemy->defeatBytecode != NULL) {
2019 enemy->defeatScript = script;
2020 enemy->defeatScriptID = script->id;
2021 script->owner1.enemy = enemy;
2022 script->owner2.npcID = enemy->npcID;
2023 script->groupFlags = enemy->scriptGroup;
2024 }
2025 }
2027 break;
2029 if (currentEncounter->fadeOutAmount == 0) {
2031 } else {
2032 currentEncounter->fadeOutAccel += 4;
2033 currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
2034 if (currentEncounter->fadeOutAmount < 0) {
2035 currentEncounter->fadeOutAmount = 0;
2036 }
2037 }
2038 break;
2041 encounter = currentEncounter->curEncounter;
2042 for (i = 0; i < encounter->count; i++) {
2043 enemy = encounter->enemy[i];
2044 if (enemy == NULL) {
2045 continue;
2046 }
2047 if (!(enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
2048 if (does_script_exist(enemy->defeatScriptID)) {
2050 } else {
2051 enemy->defeatScript = NULL;
2052 }
2053 }
2054 }
2055 if (!hasDefeatScript) {
2056 for (i = 0; i < currentEncounter->numEncounters; i++) {
2057 encounter = currentEncounter->encounterList[i];
2058 if (encounter == NULL) {
2059 continue;
2060 }
2061 for (j = 0; j < encounter->count; j++) {
2062 enemy = encounter->enemy[j];
2063 if (enemy == NULL || (enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
2064 continue;
2065 }
2066 if (enemy->aiScript != NULL) {
2068 }
2069 if (enemy->auxScript != NULL) {
2071 }
2072 }
2073 }
2077 currentEncounter->substateDelay = 15;
2079 }
2080 break;
2082 if (currentEncounter->substateDelay != 0) {
2083 currentEncounter->substateDelay--;
2084 if (gGameStatusPtr->curButtons[0] == 0 && gGameStatusPtr->stickX[0] == 0 && gGameStatusPtr->stickY[0] == 0) {
2085 break;
2086 }
2087 }
2092 break;
2094 // resume all ai scripts
2095 for (i = 0; i < currentEncounter->numEncounters; i++) {
2096 encounter = currentEncounter->encounterList[i];
2097 if (encounter == NULL) {
2098 continue;
2099 }
2100 for (j = 0; j < encounter->count; j++) {
2101 enemy = encounter->enemy[j];
2102 if (enemy == NULL || (enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
2103 continue;
2104 }
2105 if (enemy->aiScript != NULL) {
2107 }
2108 if (enemy->auxScript != NULL) {
2110 }
2111 }
2112 }
2120 break;
2122 encounter = currentEncounter->curEncounter;
2123 for (i = 0; i < encounter->count; i++) {
2124 enemy = encounter->enemy[i];
2125 if (enemy == NULL) {
2126 continue;
2127 }
2128 if ((enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) && enemy != currentEncounter->curEnemy) {
2129 continue;
2130 }
2131
2132 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
2133 continue;
2134 }
2135
2136 if (enemy->defeatBytecode != NULL) {
2138 enemy->defeatScript = script;
2139 enemy->defeatScriptID = script->id;
2140 script->owner1.enemy = enemy;
2141 script->owner2.npcID = enemy->npcID;
2142 script->groupFlags = enemy->scriptGroup;
2143 }
2144 }
2146 break;
2148 if (currentEncounter->fadeOutAmount == 0) {
2150 } else {
2151 currentEncounter->fadeOutAccel += 4;
2152 currentEncounter->fadeOutAmount -= currentEncounter->fadeOutAccel;
2153 if (currentEncounter->fadeOutAmount < 0) {
2154 currentEncounter->fadeOutAmount = 0;
2155 }
2156 }
2157 break;
2160 encounter = currentEncounter->curEncounter;
2161 for (i = 0; i < encounter->count; i++) {
2162 enemy = encounter->enemy[i];
2163 if (enemy == NULL) {
2164 continue;
2165 }
2166 if (!(enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
2167 if (does_script_exist(enemy->defeatScriptID)) {
2169 } else {
2170 enemy->defeatScript = NULL;
2171 }
2172 }
2173 }
2174 if (!hasDefeatScript) {
2175 for (i = 0; i < currentEncounter->numEncounters; i++) {
2176 encounter = currentEncounter->encounterList[i];
2177 if (encounter == NULL) {
2178 continue;
2179 }
2180 for (j = 0; j < encounter->count; j++) {
2181 enemy = encounter->enemy[j];
2182 if (enemy == NULL || (enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
2183 continue;
2184 }
2185 if (enemy->aiScript != NULL) {
2187 }
2188 if (enemy->auxScript != NULL) {
2190 }
2191 }
2192 }
2193
2194 enemy = currentEncounter->curEnemy;
2195 if (!(enemy->flags & ENEMY_FLAG_DO_NOT_KILL)) {
2196 encounter = currentEncounter->curEncounter;
2197 enemy->aiSuspendTime = 45;
2198 playerStatus->blinkTimer = 45;
2199 for (j = 0; j < encounter->count; j++) {
2200 enemy = encounter->enemy[j];
2201 if (enemy == NULL) {
2202 continue;
2203 }
2204 if (enemy->flags & ENEMY_FLAG_DISABLE_AI) {
2205 continue;
2206 }
2207 if (enemy->flags & ENEMY_FLAG_ENABLE_HIT_SCRIPT) {
2208 continue;
2209 }
2210 enemy->aiSuspendTime = 45;
2211 playerStatus->blinkTimer = 45;
2212 }
2213 }
2214
2215 currentEncounter->battleTriggerCooldown = 45;
2223 }
2224 break;
2225 }
2226
2227 for (i = 0; i < currentEncounter->numEncounters; i++) {
2228 encounter = currentEncounter->encounterList[i];
2229 if (encounter == NULL) {
2230 continue;
2231 }
2232 for (j = 0; j < encounter->count; j++) {
2233 enemy = encounter->enemy[j];
2234 if (enemy == NULL || (enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
2235 continue;
2236 }
2237
2238 npc = get_npc_unsafe(enemy->npcID);
2239 if (enemy->aiSuspendTime != 0) {
2240 if (enemy->aiSuspendTime & 1) {
2241 npc->flags |= NPC_FLAG_SUSPENDED;
2242 enemy->flags |= ENEMY_FLAG_SUSPENDED;
2243 } else {
2244 npc->flags &= ~NPC_FLAG_SUSPENDED;
2245 enemy->flags &= ~ENEMY_FLAG_SUSPENDED;
2246 }
2247 }
2248 }
2249 }
2250}
2251
2261
2266 s32 flag;
2267
2268 switch (gEncounterSubState) {
2270 currentEnemy = encounter->curEnemy;
2271 flag = FALSE;
2272
2273 if (currentEnemy->interactScript != NULL) {
2274 if (does_script_exist(currentEnemy->interactScriptID)) {
2275 flag = TRUE;
2276 } else {
2278 }
2279 }
2280
2281 if (currentEnemy->hitScript != NULL) {
2282 if (does_script_exist(currentEnemy->hitScriptID)) {
2283 flag = TRUE;
2284 } else {
2285 currentEnemy->hitScript = NULL;
2286 }
2287 }
2288
2289 if (!flag) {
2291 }
2292 break;
2295
2296 currentEnemy = encounter->curEnemy;
2297 if (currentEnemy != NULL && currentEnemy->aiScript != NULL) {
2298 resume_all_script(currentEnemy->aiScriptID);
2299 }
2300
2303
2304 if (playerStatus->actionState == ACTION_STATE_TALK) {
2306 }
2307
2308 func_800EF3D4(0);
2309 encounter->hitType = 0;
2314 break;
2315 }
2316}
2317
2320
2325 f32 npcX, npcY, npcZ;
2326 f32 angle;
2327 f32 deltaX, deltaZ;
2332 f32 length;
2333 f32 npcHeight;
2334 f32 npcRadius;
2336 Npc* resultNpc;
2337 Npc* npc;
2339 Enemy* enemy;
2340 f32 minLength;
2341 s32 i, j;
2342 f32 yaw;
2343
2344 playerStatus->encounteredNPC = NULL;
2346 playerHeight = playerStatus->colliderHeight;
2347 playerRadius = playerStatus->colliderDiameter / 2;
2348 playerX = playerStatus->pos.x;
2349 playerY = playerStatus->pos.y;
2350 playerZ = playerStatus->pos.z;
2351
2353 return FALSE;
2354 }
2355
2357 resultNpc = NULL;
2358 resultEnemy = NULL;
2359 minLength = 65535.0f;
2360
2361 for (i = 0; i < encounterStatus->numEncounters; i++) {
2362 encounter = encounterStatus->encounterList[i];
2363
2364 if (encounter == NULL) {
2365 continue;
2366 }
2367
2368 for (j = 0; j < encounter->count; j++) {
2369 enemy = encounter->enemy[j];
2370
2371 if (enemy == NULL) {
2372 continue;
2373 }
2374
2376 continue;
2377 }
2378
2379 if (!(enemy->flags & ENEMY_FLAG_PASSIVE)) {
2380 continue;
2381 }
2382
2383 if ((enemy->flags & ENEMY_FLAG_CANT_INTERACT) || enemy->interactBytecode == NULL) {
2384 continue;
2385 }
2386
2387 npc = get_npc_unsafe(enemy->npcID);
2388
2389 npcX = npc->pos.x;
2390 npcY = npc->pos.y;
2391 npcZ = npc->pos.z;
2392 deltaX = npcX - playerX;
2393 deltaZ = npcZ - playerZ;
2396 length = sqrtf(SQ(deltaX) + SQ(deltaZ));
2397
2398 // check cylinder-cylinder overlap
2399 if ((playerRadius + npcRadius <= length) ||
2400 (npcY + npcHeight < playerY) ||
2401 (playerY + playerHeight < npcY)) {
2402 continue;
2403 }
2404
2405 if (clamp_angle(playerStatus->spriteFacingAngle) < 180.0f) {
2406 angle = clamp_angle(camera->curYaw - 120.0f);
2407 if (playerStatus->trueAnimation & SPRITE_ID_BACK_FACING) {
2408 angle = clamp_angle(angle + 60.0f);
2409 }
2410 } else {
2411 angle = clamp_angle(camera->curYaw + 120.0f);
2412 if (playerStatus->trueAnimation & SPRITE_ID_BACK_FACING) {
2413 angle = clamp_angle(angle - 60.0f);
2414 }
2415 }
2416
2417 yaw = atan2(playerX, playerZ, npcX, npcZ);
2418 if (fabsf(get_clamped_angle_diff(angle, yaw)) > 90.0f) {
2419 continue;
2420 }
2421
2422 // only allow interact if line of sight exists
2423 // @bug? flag combination does not make sense
2425 f32 x = npcX;
2426 f32 y = npcY;
2427 f32 z = npcZ;
2428 yaw = atan2(npcX, npcZ, playerX, playerZ);
2429
2430 if (npc_test_move_taller_with_slipping(0, &x, &y, &z, length, yaw, npcHeight, 2.0f * npcRadius)) {
2431 continue;
2432 }
2433 }
2434
2435 if (length < minLength) {
2436 minLength = length;
2438 resultNpc = npc;
2439 resultEnemy = enemy;
2440 }
2441 }
2442 }
2443
2444 if (!(playerStatus->animFlags & PA_FLAG_8BIT_MARIO) && resultNpc != NULL && !is_picking_up_item()) {
2445 playerStatus->encounteredNPC = resultNpc;
2447 if (playerStatus->pressedButtons & BUTTON_A) {
2451 encounterStatus->curEncounter = resultEncounter;
2452 encounterStatus->curEnemy = resultEnemy;
2453 encounterStatus->firstStrikeType = FIRST_STRIKE_PLAYER;
2454 return TRUE;
2455 }
2456 }
2457 return FALSE;
2458}
2459
2463 NpcBlueprint* bp = &sp10;
2464 NpcGroup* groupList = (NpcGroup*)(currentEncounter->npcGroupList);
2465 s32 groupNpcCount;
2466 s32 mapID = currentEncounter->mapID;
2467
2468 Npc* newNpc;
2469 s32 newNpcIndex;
2470 s32 npcCount;
2471
2472 NpcSettings* npcSettings;
2474 Enemy* enemy;
2476 Evt* script;
2477
2478 s32 totalNpcCount;
2479
2480 s32 cond1;
2481 s32 cond2;
2482 s32 i;
2483 s32 k;
2484 s32 e;
2485
2486 switch (gEncounterSubState) {
2488 if (currentEncounter->resetMapEncounterFlags != 1) {
2489 // check for current map among most recently visited
2490 for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps); i++) {
2491 if (currentEncounter->recentMaps[i] == mapID) {
2492 break;
2493 }
2494 }
2495 // current map not found in recent: reset all defeat flags
2496 if (i >= ARRAY_COUNT(currentEncounter->recentMaps)) {
2497 for (k = 0; k < ARRAY_COUNT(currentEncounter->defeatFlags[mapID]); k++) {
2498 currentEncounter->defeatFlags[mapID][k] = FALSE;
2499 }
2500 }
2501 // add current map to recent maps, pushing out the least recent
2502 for (i = 0; i < ARRAY_COUNT(currentEncounter->recentMaps) - 1; i++) {
2503 currentEncounter->recentMaps[i] = currentEncounter->recentMaps[i + 1];
2504 }
2505 currentEncounter->recentMaps[i] = mapID;
2506 }
2507
2508 e = 0;
2509 totalNpcCount = 0;
2510 while (TRUE) {
2511 if (groupList->npcCount == 0) {
2512 break;
2513 }
2514
2515 npcData = groupList->npcs;
2516 groupNpcCount = groupList->npcCount;
2517
2518 encounter = heap_malloc(sizeof(*encounter));
2519
2520 currentEncounter->encounterList[e] = encounter;
2521 ASSERT(encounter != NULL);
2522 encounter->count = groupNpcCount;
2523 encounter->battle = groupList->battle;
2524 encounter->stage = groupList->stage - 1;
2525 encounter->encounterID = totalNpcCount;
2526 for (i = 0; i < groupNpcCount; i++) {
2527 if (get_defeated(mapID, encounter->encounterID + i)) {
2528 npcData++;
2529 encounter->enemy[i] = NULL;
2530 continue;
2531 }
2532
2533 enemy = encounter->enemy[i] = heap_malloc(sizeof(*enemy));
2534 ASSERT (enemy != NULL);
2535
2536 for (k = 0; k < ARRAY_COUNT(enemy->varTable); k++) {
2537 enemy->varTable[k] = 0;
2538 }
2539 enemy->encounterIndex = e;
2540 enemy->npcID = npcData->id;
2541 npcSettings = enemy->npcSettings = npcData->settings;
2542 enemy->drops = &npcData->drops;
2543 if ((*(s16*)(&npcData->drops) & 0xFF00) != 0x8000) { //TODO s16?
2544 enemy->drops = &DefaultEnemyDrops;
2545 }
2546 enemy->encountered = 0;
2547 if ((s32) npcData->init < EVT_LIMIT) {
2548 enemy->initBytecode = npcData->init;
2549 } else {
2550 enemy->initBytecode = NULL;
2551 }
2552 enemy->interactBytecode = npcSettings->onInteract;
2553 enemy->aiBytecode = npcSettings->ai;
2554 enemy->hitBytecode = npcSettings->onHit;
2555 enemy->auxBytecode = npcSettings->aux;
2556 enemy->defeatBytecode = npcSettings->onDefeat;
2557 enemy->initScript = NULL;
2558 enemy->interactScript = NULL;
2559 enemy->aiScript = NULL;
2560 enemy->hitScript = NULL;
2561 enemy->auxScript = NULL;
2562 enemy->defeatScript = NULL;
2563 enemy->interactScriptID = 0;
2564 enemy->aiScriptID = 0;
2565 enemy->hitScriptID = 0;
2566 enemy->auxScriptID = 0;
2567 enemy->defeatScriptID = 0;
2568 enemy->hitboxIsActive = FALSE;
2569 enemy->instigatorValue = 0;
2570 enemy->aiDetectFlags = npcData->aiDetectFlags;
2571
2572 enemy->aiFlags = npcData->aiFlags;
2573 enemy->unk_DC = 0;
2574 enemy->aiSuspendTime = 0;
2575 enemy->unk_B8 = (EvtScript*)npcSettings->unk_24; // ??
2576 enemy->unk_BC = NULL;
2577 enemy->unk_C0 = 0;
2578 enemy->unk_C4 = 0;
2579
2580 enemy->animList = (s32*)&npcData->animations;
2581 enemy->territory = &npcData->territory;
2582
2583 enemy->flags = npcSettings->flags;
2584 enemy->flags |= npcData->flags;
2585 enemy->unk_64 = NULL;
2586 enemy->tattleMsg = npcData->tattle;
2587 if (npcData->initVarCount != 0) {
2588 if (npcData->initVarCount == 1) {
2589 enemy->varTable[0] = npcData->initVar.value;
2590 } else {
2591 s32* initialVars = npcData->initVar.array;
2592 for (k = 0; k < npcData->initVarCount; k++) {
2593 enemy->varTable[k] = *initialVars++;
2594 }
2595 }
2596 }
2597
2598 // create the new NPC
2599 bp->flags = 0;
2600 if (npcSettings->defaultAnim == 0) {
2601 bp->initialAnim = enemy->animList[0];
2602 } else {
2603 bp->initialAnim = npcSettings->defaultAnim;
2604 }
2605 bp->onUpdate = NULL;
2606 bp->onRender = NULL;
2607 if (!(enemy->flags & ENEMY_FLAG_USE_PLAYER_SPRITE)) {
2608 newNpcIndex = create_standard_npc(bp, npcData->extraAnimations);
2609 } else {
2611 }
2612
2614 newNpc->npcID = npcData->id;
2615 newNpc->collisionDiameter = npcSettings->radius;
2616 newNpc->collisionHeight = npcSettings->height;
2617 enemy->spawnPos[0] = newNpc->pos.x = npcData->pos.x;
2618 enemy->spawnPos[1] = newNpc->pos.y = npcData->pos.y;
2619 enemy->spawnPos[2] = newNpc->pos.z = npcData->pos.z;
2620 newNpc->unk_96 = 0;
2621 newNpc->planarFlyDist = 0.0f;
2622 newNpc->homePos.x = newNpc->pos.x;
2623 newNpc->homePos.y = newNpc->pos.y;
2624 newNpc->homePos.z = newNpc->pos.z;
2625 set_npc_yaw(newNpc, npcData->yaw);
2626 enemy->savedNpcYaw = 12345;
2627 if (newNpc->collisionDiameter >= 24.0) {
2628 newNpc->shadowScale = newNpc->collisionDiameter / 24.0;
2629 } else {
2630 newNpc->shadowScale = 1.0f;
2631 }
2634 }
2637 }
2640 }
2641 if (enemy->flags & ENEMY_FLAG_FLYING) {
2642 newNpc->flags |= NPC_FLAG_FLYING;
2643 }
2644 if (enemy->flags & ENEMY_FLAG_GRAVITY) {
2645 newNpc->flags |= NPC_FLAG_GRAVITY;
2646 }
2647 if (!(enemy->flags & ENEMY_FLAG_PASSIVE)) {
2649 }
2650 if (enemy->flags & ENEMY_FLAG_HAS_NO_SPRITE) {
2652 }
2653 if (enemy->flags & ENEMY_FLAG_NO_SHADOW_RAYCAST) {
2655 }
2656 if (enemy->flags & ENEMY_FLAG_USE_INSPECT_ICON) {
2658 }
2661 }
2664 }
2666 if (enemy->flags & ENEMY_FLAG_PASSIVE) {
2668 }
2669 if (npcSettings->otherAI != NULL) {
2670 script = start_script(npcSettings->otherAI, EVT_PRIORITY_A, 0);
2671 enemy->aiScript = script;
2672 enemy->aiScriptID = script->id;
2673 script->owner1.enemy = enemy;
2674 script->owner2.npcID = enemy->npcID;
2675 script->groupFlags = enemy->scriptGroup;
2676 }
2677
2678 npcData++;
2679 }
2680 groupList++;
2681 e++;
2683 }
2684 currentEncounter->numEncounters = e;
2686 break;
2687
2689 cond2 = FALSE;
2690 for (e = 0; e < currentEncounter->numEncounters; e++) {
2691 encounter = currentEncounter->encounterList[e];
2692 if (encounter == NULL) {
2693 continue;
2694 }
2695 for (i = 0; i < encounter->count; i++) {
2696 enemy = encounter->enemy[i];
2697 if (enemy == NULL) {
2698 continue;
2699 }
2700 if (enemy->aiScript != NULL) {
2701 if (does_script_exist(enemy->aiScriptID)) {
2702 cond2 = TRUE;
2703 }
2704 }
2705 }
2706 }
2707 if (!cond2) {
2708 for (e = 0; e < currentEncounter->numEncounters; e++) {
2709 encounter = currentEncounter->encounterList[e];
2710 if (encounter == NULL) {
2711 continue;
2712 }
2713 for (i = 0; i < encounter->count; i++) {
2714 enemy = encounter->enemy[i];
2715 if (enemy == NULL) {
2716 continue;
2717 }
2718 if (enemy->initBytecode != NULL) {
2720 enemy->initScript = script;
2721 enemy->initScriptID = script->id;
2722 script->owner1.enemy = enemy;
2723 script->owner2.npcID = enemy->npcID;
2724 script->groupFlags = enemy->scriptGroup;
2725 }
2726 }
2727 }
2729 }
2730 break;
2731
2733 cond1 = FALSE;
2734
2735 for (e = 0; e < currentEncounter->numEncounters; e++) {
2736 encounter = currentEncounter->encounterList[e];
2737 if (encounter == NULL) {
2738 continue;
2739 }
2740 for (i = 0; i < encounter->count; i++) {
2741 enemy = encounter->enemy[i];
2742 if (enemy == NULL) {
2743 continue;
2744 }
2745 if (enemy->initScript != NULL) {
2746 if (does_script_exist(enemy->initScriptID)) {
2747 cond1 = TRUE;
2748 } else {
2749 enemy->initScript = NULL;
2750 }
2751 }
2752 }
2753 }
2754
2755 if (cond1) {
2756 break;
2757 }
2758
2759 for (e = 0; e < currentEncounter->numEncounters; e++) {
2760 encounter = currentEncounter->encounterList[e];
2761 if (encounter == NULL) {
2762 continue;
2763 }
2764 for (i = 0; i < encounter->count; i++) {
2765 enemy = encounter->enemy[i];
2766 if (enemy == NULL) {
2767 continue;
2768 }
2769 if (!(enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
2770 if (enemy->aiBytecode != NULL) {
2772 enemy->aiScript = script;
2773 enemy->aiScriptID = script->id;
2774 enemy->unk_C8 = 100;
2775 script->owner1.enemy = enemy;
2776 script->owner2.npcID = enemy->npcID;
2777 script->groupFlags = enemy->scriptGroup;
2778 }
2779 }
2780 }
2781 }
2782
2783 for (e = 0; e < currentEncounter->numEncounters; e++) {
2784 encounter = currentEncounter->encounterList[e];
2785 if (encounter == NULL) {
2786 continue;
2787 }
2788 for (i = 0; i < encounter->count; i++) {
2789 enemy = encounter->enemy[i];
2790 if (enemy == NULL) {
2791 continue;
2792 }
2793 if (!(enemy->flags & ENEMY_FLAG_DISABLE_AI)) {
2794 if (enemy->auxBytecode != NULL) {
2796 enemy->auxScript = script;
2797 enemy->auxScriptID = script->id;
2798 script->owner1.enemy = enemy;
2799 script->owner2.npcID = enemy->npcID;
2800 script->groupFlags = enemy->scriptGroup;
2801 }
2802 }
2803 }
2804 }
2809 break;
2810 }
2811}
2812
2814}
2815
BSS s32 PopupMenu_SelectedIndex
u8 groupFlags
s32 b32
Bytecode EvtScript[]
#define get_msg_width
#define sfx_play_sound_at_position
#define sqrtf
#define rand_int
#define clamp_angle
#define draw_msg
#define atan2
#define draw_box
EffectInstanceDataPtr data
Definition effects.h:2605
@ FX_DAMAGE_STARS_3
Definition effects.h:359
@ FX_DAMAGE_STARS_1
Definition effects.h:357
struct EnergyOrbWaveFXData * energyOrbWave
Definition effects.h:2546
#define ASSERT(condition)
void create_encounters(void)
Definition encounter.c:2460
s8 LastBattleStartedBySpin
Definition encounter.c:179
b32 check_conversation_trigger(void)
Definition encounter.c:2321
void update_encounters_conversation(void)
Definition encounter.c:2262
@ MERLEE_EFFECTS_DISMISS
Definition encounter.c:193
@ MERLEE_EFFECTS_RELEASE
Definition encounter.c:192
@ MERLEE_EFFECTS_HOLD
Definition encounter.c:191
void setup_status_bar_for_world(void)
Definition inventory.c:1460
void update_encounters_neutral(void)
Definition encounter.c:480
void show_first_strike_message(void)
Definition encounter.c:1562
BSS EffectInstance * WorldMerleeOrbEffect
Definition encounter.c:184
void update_encounters_post_battle(void)
Definition encounter.c:1618
s8 HasPreBattleSongPushed
Definition encounter.c:177
s32 get_coin_drop_amount(Enemy *enemy)
Definition 23680.c:312
BSS s32 WorldMerleeEffectsTime
Definition encounter.c:182
BSS s16 WorldMerleeEffectsState
Definition encounter.c:188
void init_encounters_ui(void)
Definition encounter.c:2813
BSS f32 WorldMerleeBasePosY
Definition encounter.c:183
BSS s32 MerleeDropCoinsEvtID
Definition encounter.c:187
EvtScript EnemyNpcDefeat
Definition encounter.c:157
void update_encounters_pre_battle(void)
Definition encounter.c:1260
s32 get_defeated(s32 mapID, s32 encounterID)
Definition encounter.c:201
s32 is_starting_conversation(void)
Definition encounter.c:2816
s16 gFirstStrikeMessagePos
Definition encounter.c:180
void set_defeated(s32 mapID, s32 encounterID)
Definition encounter.c:209
EvtScript EnemyNpcHit
Definition encounter.c:130
EvtScript EVS_NpcDefeat
Definition encounter.c:64
s8 PendingPartnerAbilityResume
Definition encounter.c:178
void draw_encounters_pre_battle(void)
Definition encounter.c:1486
void set_battle_formation(Battle *)
Definition battle.cpp:158
b32 D_80077C40
Definition encounter.c:21
BSS Evt * MerleeDropCoinsEvt
Definition encounter.c:186
s32 gEncounterState
Definition encounter.c:173
void draw_encounters_conversation(void)
Definition encounter.c:2318
EvtScript EVS_MerleeDropCoins
Definition encounter.c:25
EvtScript EVS_FleeBattleDrops
Definition encounter.c:76
EncounterStatus gCurrentEncounter
Definition encounter.c:175
b32 EncounterStateChanged
Definition encounter.c:23
void draw_encounters_neutral(void)
Definition encounter.c:1257
void partner_handle_after_battle(void)
Definition partners.c:1081
void draw_encounters_post_battle(void)
Definition encounter.c:2252
BSS EffectInstance * WorldMerleeWaveEffect
Definition encounter.c:185
s32 gEncounterSubState
Definition encounter.c:174
EnemyDrops DefaultEnemyDrops
Definition encounter.c:82
@ FX_INSTANCE_FLAG_DISMISS
Definition enums.h:3517
@ WINDOW_STYLE_4
Definition enums.h:6373
@ WINDOW_STYLE_20
Definition enums.h:6389
@ OVERLAY_NONE
Definition enums.h:2387
@ OVERLAY_START_BATTLE
Definition enums.h:2398
@ OVERLAY_SCREEN_COLOR
Definition enums.h:2388
@ ENV_TINT_SHROUD
Definition enums.h:4386
@ BUTTON_A
Definition enums.h:2790
@ NPC_DROP_FLAG_80
Definition enums.h:5088
@ DEBUG_CONTACT_CANT_TOUCH
Definition enums.h:4267
@ DEBUG_CONTACT_DIE_ON_TOUCH
Definition enums.h:4268
@ SCREEN_LAYER_FRONT
Definition enums.h:2382
@ SCREEN_LAYER_BACK
Definition enums.h:2383
@ ENEMY_ANIM_INDEX_HIT
Definition enums.h:3433
@ ENCOUNTER_FLAG_SKIP_FLEE_DROPS
Definition enums.h:4988
@ ENCOUNTER_FLAG_THUMBS_UP
Mario will do a 'thumbs up' animation after winning.
Definition enums.h:4986
@ ENCOUNTER_FLAG_CANT_SKIP_WIN_DELAY
Definition enums.h:4987
@ MSG_PAL_STANDARD
Definition enums.h:5414
@ ITEM_SPAWN_MODE_TOSS_SPAWN_ALWAYS
Definition enums.h:2294
@ ENCOUNTER_SUBSTATE_CONVERSATION_END
Definition enums.h:6320
@ ENCOUNTER_SUBSTATE_CONVERSATION_INIT
Definition enums.h:6319
@ SONG_NORMAL_BATTLE
Definition enums.h:284
@ AI_FLAG_1
Definition enums.h:4568
@ PS_FLAG_FALLING
Definition enums.h:3036
@ PS_FLAG_ENTERING_BATTLE
Definition enums.h:3061
@ PS_FLAG_JUMPING
Definition enums.h:3035
@ PS_FLAG_ARMS_RAISED
Definition enums.h:3063
@ PS_FLAG_HAMMER_CHECK
Definition enums.h:3073
@ PS_FLAG_INPUT_DISABLED
Definition enums.h:3052
@ PS_FLAG_HAS_CONVERSATION_NPC
Definition enums.h:3074
@ PARTNER_ACTION_NONE
Definition enums.h:2932
@ ENCOUNTER_TRIGGER_CONVERSATION
Definition enums.h:272
@ ENCOUNTER_TRIGGER_JUMP
Definition enums.h:269
@ ENCOUNTER_TRIGGER_HAMMER
Definition enums.h:271
@ ENCOUNTER_TRIGGER_NONE
Definition enums.h:268
@ ENCOUNTER_TRIGGER_PARTNER
Definition enums.h:273
@ ENCOUNTER_TRIGGER_SPIN
Definition enums.h:270
@ ENCOUNTER_SUBSTATE_POST_BATTLE_WON_FADE_IN
Definition enums.h:6325
@ ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_RESUME
Definition enums.h:6336
@ ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_FADE_IN
Definition enums.h:6335
@ ENCOUNTER_SUBSTATE_POST_BATTLE_SKIP
Definition enums.h:6338
@ ENCOUNTER_SUBSTATE_POST_BATTLE_FLED_RESUME
Definition enums.h:6332
@ ENCOUNTER_SUBSTATE_POST_BATTLE_WON_KILL
Definition enums.h:6326
@ ENCOUNTER_SUBSTATE_POST_BATTLE_FLED_INIT
Definition enums.h:6330
@ ENCOUNTER_SUBSTATE_POST_BATTLE_WON_RESUME
Definition enums.h:6327
@ ENCOUNTER_SUBSTATE_POST_BATTLE_ENEMY_FLED_INIT
Definition enums.h:6339
@ ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_DELAY
Definition enums.h:6337
@ ENCOUNTER_SUBSTATE_POST_BATTLE_FLED_FADE_IN
Definition enums.h:6331
@ ENCOUNTER_SUBSTATE_POST_BATTLE_LOST_INIT
Definition enums.h:6334
@ ENCOUNTER_SUBSTATE_POST_BATTLE_ENEMY_FLED_FADE_IN
Definition enums.h:6340
@ ENCOUNTER_SUBSTATE_POST_BATTLE_INIT
Definition enums.h:6324
@ ENCOUNTER_SUBSTATE_POST_BATTLE_PLAY_NPC_DEFEAT
Definition enums.h:6329
@ ENCOUNTER_SUBSTATE_POST_BATTLE_ENEMY_FLED_RESUME
Definition enums.h:6341
@ ENCOUNTER_SUBSTATE_POST_BATTLE_FLED_DELAY
Definition enums.h:6333
@ ENCOUNTER_SUBSTATE_POST_BATTLE_WON_CHECK_MERLEE
Definition enums.h:6328
@ ENEMY_FLAG_DISABLE_AI
Definition enums.h:4525
@ ENEMY_FLAG_DO_NOT_KILL
Definition enums.h:4522
@ ENEMY_FLAG_FLYING
Definition enums.h:4531
@ ENEMY_FLAG_RAYCAST_TO_INTERACT
Definition enums.h:4536
@ ENEMY_FLAG_NO_DELAY_AFTER_FLEE
Definition enums.h:4538
@ ENEMY_FLAG_IGNORE_ENTITY_COLLISION
Definition enums.h:4530
@ ENEMY_FLAG_HAS_NO_SPRITE
Definition enums.h:4534
@ ENEMY_FLAG_IGNORE_HAMMER
Definition enums.h:4546
@ ENEMY_FLAG_DO_NOT_AUTO_FACE_PLAYER
Definition enums.h:4542
@ ENEMY_FLAG_PASSIVE
Definition enums.h:4520
@ ENEMY_FLAG_GRAVITY
Definition enums.h:4532
@ ENEMY_FLAG_FLED
Definition enums.h:4524
@ ENEMY_FLAG_IGNORE_PARTNER
Definition enums.h:4548
@ ENEMY_FLAG_ENABLE_HIT_SCRIPT
Definition enums.h:4523
@ ENEMY_FLAG_USE_PLAYER_SPRITE
Definition enums.h:4537
@ ENEMY_FLAG_PROJECTILE
Definition enums.h:4526
@ ENEMY_FLAG_DONT_SUSPEND_SCRIPTS
Definition enums.h:4539
@ ENEMY_FLAG_SKIP_BATTLE
Definition enums.h:4540
@ ENEMY_FLAG_USE_INSPECT_ICON
Definition enums.h:4535
@ ENEMY_FLAG_IGNORE_SPIN
Definition enums.h:4549
@ ENEMY_FLAG_NO_SHADOW_RAYCAST
Definition enums.h:4533
@ ENEMY_FLAG_SUSPENDED
Definition enums.h:4551
@ ENEMY_FLAG_IGNORE_TOUCH
Definition enums.h:4544
@ ENEMY_FLAG_CANT_INTERACT
Definition enums.h:4547
@ ENEMY_FLAG_DONT_UPDATE_SHADOW_Y
Definition enums.h:4527
@ ENEMY_FLAG_IGNORE_PLAYER_COLLISION
Definition enums.h:4529
@ ENEMY_FLAG_IGNORE_JUMP
Definition enums.h:4545
@ ENEMY_FLAG_IGNORE_WORLD_COLLISION
Definition enums.h:4528
@ ENEMY_FLAG_ACTIVE_WHILE_OFFSCREEN
Definition enums.h:4541
@ COLLIDER_FLAG_IGNORE_PLAYER
Definition enums.h:4695
@ NPC_SELF
Definition enums.h:2526
@ NPC_BTL_MERLEE
Definition enums.h:2529
@ PA_FLAG_DIZZY_ATTACK_ENCOUNTER
Definition enums.h:3109
@ PA_FLAG_SPINNING
Definition enums.h:3107
@ PA_FLAG_8BIT_MARIO
Definition enums.h:3105
@ ENCOUNTER_SUBSTATE_PRE_BATTLE_INIT
Definition enums.h:6312
@ ENCOUNTER_SUBSTATE_PRE_BATTLE_AUTO_WIN
Definition enums.h:6314
@ ENCOUNTER_SUBSTATE_PRE_BATTLE_LOAD
Definition enums.h:6313
@ ENCOUNTER_SUBSTATE_PRE_BATTLE_SKIP
Definition enums.h:6315
@ ABILITY_BUMP_ATTACK
Definition enums.h:478
@ ABILITY_SPIN_ATTACK
Definition enums.h:476
@ ABILITY_CHILL_OUT
Definition enums.h:453
@ ABILITY_DIZZY_ATTACK
Definition enums.h:481
@ ABILITY_FIRST_ATTACK
Definition enums.h:439
@ SOUND_ACTOR_DEATH
Definition enums.h:1293
@ SOUND_MAGIC_DESCENDING
Definition enums.h:1414
@ SOUND_SPEEDY_SPIN_ATTACK
Definition enums.h:1553
@ SOUND_NONE
Definition enums.h:547
@ SOUND_SPEEDY_SPIN
Definition enums.h:1551
@ SOUND_SPIN_ATTACK
Definition enums.h:1552
@ SOUND_MAGIC_ASCENDING
Definition enums.h:1413
@ SOUND_MERLEE_APPEAR
Definition enums.h:972
@ SOUND_SPIN
Definition enums.h:1550
@ SOUND_HIT_PLAYER_NORMAL
Definition enums.h:719
@ OUTCOME_ENEMY_FLED
Definition enums.h:1905
@ OUTCOME_PLAYER_WON
Definition enums.h:1902
@ OUTCOME_SKIP
Definition enums.h:1906
@ OUTCOME_PLAYER_LOST
Definition enums.h:1903
@ OUTCOME_PLAYER_FLED
Definition enums.h:1904
@ PARTNER_BOW
Definition enums.h:2894
@ ACTION_STATE_RIDE
Definition enums.h:2461
@ ACTION_STATE_JUMP
Definition enums.h:2430
@ ACTION_STATE_STEP_DOWN_LAND
Definition enums.h:2438
@ ACTION_STATE_SPIN_POUND
Definition enums.h:2442
@ ACTION_STATE_SPIN_JUMP
Definition enums.h:2441
@ ACTION_STATE_IDLE
Definition enums.h:2426
@ ACTION_STATE_TALK
Reading signs doesn't count.
Definition enums.h:2440
@ ACTION_STATE_TORNADO_POUND
Definition enums.h:2444
@ ACTION_STATE_USE_SPINNING_FLOWER
Definition enums.h:2457
@ ACTION_STATE_FALLING
Definition enums.h:2435
@ ACTION_STATE_LAND
Definition enums.h:2437
@ ACTION_STATE_ENEMY_FIRST_STRIKE
Definition enums.h:2455
@ ACTION_STATE_BOUNCE
Used with Kooper.
Definition enums.h:2431
@ ACTION_STATE_STEP_DOWN
Definition enums.h:2436
@ ACTION_STATE_HAMMER
Definition enums.h:2446
@ ACTION_STATE_TORNADO_JUMP
Definition enums.h:2443
@ ENCOUNTER_STATE_POST_BATTLE
Definition enums.h:6298
@ ENCOUNTER_STATE_CONVERSATION
Definition enums.h:6297
@ ENCOUNTER_STATE_NEUTRAL
Definition enums.h:6295
@ ENCOUNTER_STATE_PRE_BATTLE
Definition enums.h:6296
@ FIRST_STRIKE_NONE
Definition enums.h:3458
@ FIRST_STRIKE_ENEMY
Definition enums.h:3460
@ FIRST_STRIKE_PLAYER
Definition enums.h:3459
@ DEMO_STATE_CHANGE_MAP
Definition enums.h:3536
@ SOUND_SPACE_DEFAULT
Definition enums.h:1737
@ GLOBAL_OVERRIDES_40
Definition enums.h:4324
@ GLOBAL_OVERRIDES_800
Definition enums.h:4329
@ GLOBAL_OVERRIDES_200
Definition enums.h:4327
@ GLOBAL_OVERRIDES_400
Definition enums.h:4328
@ GLOBAL_OVERRIDES_DISABLE_BATTLES
Definition enums.h:4326
@ ENCOUNTER_SUBSTATE_NEUTRAL
Definition enums.h:6308
@ ENCOUNTER_SUBSTATE_CREATE_RUN_INIT_SCRIPT
Definition enums.h:6303
@ ENCOUNTER_SUBSTATE_CREATE_RUN_AI
Definition enums.h:6304
@ ENCOUNTER_SUBSTATE_CREATE_INIT
Definition enums.h:6302
@ NPC_FLAG_IGNORE_ENTITY_COLLISION
Definition enums.h:3013
@ NPC_FLAG_FLYING
Definition enums.h:3001
@ NPC_FLAG_HAS_NO_SPRITE
Definition enums.h:3022
@ NPC_FLAG_SUSPENDED
Definition enums.h:3029
@ NPC_FLAG_RAYCAST_TO_INTERACT
Definition enums.h:3027
@ NPC_FLAG_IGNORE_WORLD_COLLISION
Definition enums.h:3004
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
Definition enums.h:3006
@ NPC_FLAG_GRAVITY
Definition enums.h:3007
@ NPC_FLAG_INVISIBLE
Definition enums.h:2999
@ NPC_FLAG_NO_SHADOW_RAYCAST
Definition enums.h:3003
@ NPC_FLAG_USE_INSPECT_ICON
Definition enums.h:3026
@ NPC_FLAG_DONT_UPDATE_SHADOW_Y
Definition enums.h:3008
@ EVT_PRIORITY_A
Definition evt.h:153
#define ApiStatus_DONE2
Definition evt.h:118
s32 Bytecode
Definition evt.h:7
@ EVT_GROUP_HOSTILE_NPC
Definition evt.h:144
@ EVT_GROUP_FLAG_BATTLE
Definition evt.h:138
@ EVT_GROUP_FLAG_INTERACT
Definition evt.h:134
@ EVT_GROUP_PASSIVE_NPC
Definition evt.h:143
@ EVT_GROUP_NEVER_PAUSE
Definition evt.h:142
#define ApiStatus_DONE1
Definition evt.h:117
#define ApiStatus_BLOCK
Definition evt.h:116
@ EVT_FLAG_SUSPENDED
doesn't affect child
Definition evt.h:163
void set_screen_overlay_params_back(u8, f32)
void set_battle_stage(s32)
Definition battle.cpp:154
s32 evt_get_variable(Evt *script, Bytecode var)
Definition evt.c:1689
s32 is_ability_active(s32 arg0)
Definition inventory.c:1735
f32 fabsf(f32 f)
s32 is_merlee_message_done(void)
void get_screen_coords(s32 camID, f32 x, f32 y, f32 z, s32 *screenX, s32 *screenY, s32 *screenZ)
Definition cam_main.c:409
void set_screen_overlay_alpha(s32, f32)
void spawn_drops(Enemy *enemy)
Definition 23680.c:8
void partner_disable_input(void)
Definition partners.c:2489
void func_800EF3D4(s32)
Definition partners.c:2414
s32 disable_player_input(void)
Definition 77480.c:989
s32 resume_all_group(s32 groupFlags)
s32 suspend_all_script(s32 id)
void set_screen_overlay_params_front(u8, f32)
void close_status_bar(void)
Definition inventory.c:1450
void mdl_set_all_tint_type(s32)
Definition model.c:4519
s32 enable_player_input(void)
Definition 77480.c:997
void set_script_flags(Evt *script, s32 flags)
void bgm_pop_battle_song(void)
Evt * start_script(EvtScript *source, s32 priority, s32 initialState)
s32 is_picking_up_item(void)
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
void clear_script_flags(Evt *script, s32 flags)
s32 partner_test_enemy_collision(Npc *enemy)
Definition partners.c:1051
b32 npc_test_move_taller_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
void show_merlee_message(s16, s16)
void set_screen_overlay_center(s32, s32, s32, s32)
void kill_script_by_ID(s32 id)
void set_screen_overlay_color(s32, u8, u8, u8)
void start_bounce_a(void)
Definition 7E9D0.c:300
void suggest_player_anim_allow_backward(AnimID anim)
Definition 77480.c:893
void partner_handle_before_battle(void)
Definition partners.c:1067
s32 resume_all_script(s32 id)
s32 does_script_exist(s32 id)
void load_battle(s32)
Definition battle.cpp:146
f32 sin_rad(f32 x)
Definition 43F0.c:711
void bgm_set_battle_song(s32, s32)
void bgm_push_battle_song(void)
Evt * start_script_in_group(EvtScript *source, u8 priority, u8 initialState, u8 groupFlags)
s32 make_item_entity_delayed(s32 itemID, f32 x, f32 y, f32 z, s32 itemSpawnMode, s32 pickupDelay, s32 pickupVar)
void add_vec2D_polar(f32 *x, f32 *y, f32 r, f32 theta)
Definition 43F0.c:683
Evt * get_script_by_id(s32 id)
f32 get_clamped_angle_diff(f32, f32)
Definition 43F0.c:604
void suspend_all_group(s32 groupFlags)
void * heap_malloc(s32 size)
Definition heap.c:34
void mdl_set_shroud_tint_params(u8 r, u8 g, u8 b, u8 a)
Definition model.c:3905
EvtScript * ai
Definition npc.h:149
EvtScript * onDefeat
Definition npc.h:152
s16 height
Definition npc.h:145
struct Evt * interactScript
Definition npc.h:312
s32 unk_C0
Definition npc.h:338
s32 flags
Definition npc.h:295
EvtScript * aux
Definition npc.h:151
s16 savedNpcYaw
Definition npc.h:346
s16 radius
Definition npc.h:146
s16 npcID
Definition npc.h:300
EnemyDrops * drops
Definition npc.h:343
s32 interactScriptID
Definition npc.h:318
struct Evt * hitScript
Definition npc.h:314
void kill_enemy(Enemy *enemy)
Definition npc.c:2372
EvtScript * hitBytecode
Definition npc.h:308
s8 encounterIndex
Definition npc.h:296
s8 instigatorValue
Definition npc.h:334
u8 scriptGroup
Definition npc.h:298
s32 auxScriptID
Definition npc.h:321
s32 initScriptID
Definition npc.h:317
s32 create_peach_npc(NpcBlueprint *blueprint)
Definition npc.c:197
EvtScript * onInteract
Definition npc.h:148
void * otherAI
Definition npc.h:147
s32 * animList
Definition npc.h:341
s32 create_standard_npc(NpcBlueprint *blueprint, AnimID *animList)
Definition npc.c:193
s32 unk_24
Definition npc.h:154
struct Evt * defeatScript
Definition npc.h:316
EvtScript * initBytecode
Definition npc.h:305
s16 spawnPos[3]
Definition npc.h:301
s8 aiSuspendTime
Definition npc.h:333
s32 unk_DC
Definition npc.h:345
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:993
s32 unk_C4
Definition npc.h:339
Vec3s unk_10
Definition npc.h:302
s8 hitboxIsActive
Definition npc.h:299
s32 fadeOutAccel
Definition npc.h:397
u8 dropFlags
Definition npc.h:187
EvtScript * interactBytecode
Definition npc.h:306
s32 aiScriptID
Definition npc.h:319
struct Evt * initScript
Definition npc.h:311
Npc * get_npc_by_index(s32 listIndex)
Definition npc.c:270
u8 aiDetectFlags
Definition npc.h:330
s32 defeatScriptID
Definition npc.h:322
NpcSettings * npcSettings
Definition npc.h:304
u32 aiFlags
Definition npc.h:332
s16 level
Definition npc.h:155
struct Evt * auxScript
Definition npc.h:315
EvtScript * unk_B8
Definition npc.h:336
s32 defeatFlags[60][12]
Definition npc.h:403
s32 unk_C8
Definition npc.h:340
u32 tattleMsg
Definition npc.h:344
void set_npc_yaw(Npc *npc, f32 yaw)
Definition npc.c:1244
s8 encountered
Definition npc.h:297
void * unk_64
Definition npc.h:323
EvtScript * onHit
Definition npc.h:150
EvtScript * defeatBytecode
Definition npc.h:310
EvtScript * aiBytecode
Definition npc.h:307
struct Evt * unk_BC
Definition npc.h:337
s32 flags
Definition npc.h:153
AnimID defaultAnim
Definition npc.h:144
struct Evt * aiScript
Definition npc.h:313
EvtScript * auxBytecode
Definition npc.h:309
EnemyTerritory * territory
Definition npc.h:342
s32 hitScriptID
Definition npc.h:320
Definition npc.h:294
Definition npc.h:243
Zero-terminated.
Definition npc.h:282
void partner_enable_input(void)
Definition partners.c:2480
void sfx_stop_sound(s32 soundID)
Definition sfx.c:507
void sfx_play_sound(s32 soundID)
Definition sfx.c:517
ApiStatus ShowMerleeCoinMessage(Evt *script, b32 isInitialCall)
ApiStatus PlaySound(Evt *script, b32 isInitialCall)
ApiStatus FadeBackgroundLighten(Evt *script, b32 isInitialCall)
ApiStatus DeleteNpc(Evt *script, b32 isInitialCall)
ApiStatus PlayMerleeGatherFX(Evt *script, b32 isInitialCall)
ApiStatus SetNpcAnimation(Evt *script, b32 isInitialCall)
ApiStatus SetEnemyFlagBits(Evt *script, b32 isInitialCall)
ApiStatus FadeInMerlee(Evt *script, b32 isInitialCall)
ApiStatus MerleeStopFX(Evt *script, b32 isInitialCall)
ApiStatus FadeOutMerlee(Evt *script, b32 isInitialCall)
ApiStatus OnFleeBattleDrops(Evt *script, b32 isInitialCall)
ApiStatus SetNpcRotation(Evt *script, b32 isInitialCall)
ApiStatus MerleeUpdateFX(Evt *script, b32 isInitialCall)
ApiStatus FadeBackgroundDarken(Evt *script, b32 isInitialCall)
ApiStatus CreateNpc(Evt *script, b32 isInitialCall)
ApiStatus RemoveNpc(Evt *script, b32 isInitialCall)
ApiStatus GetSelfAnimationFromTable(Evt *script, b32 isInitialCall)
ApiStatus DoNpcDefeat(Evt *script, b32 isInitialCall)
ApiStatus SetNpcPos(Evt *script, b32 isInitialCall)
ApiStatus OnDefeatEnemy(Evt *script, b32 isInitialCall)
ApiStatus GetOwnerEncounterTrigger(Evt *script, b32 isInitialCall)
ApiStatus PlayMerleeOrbFX(Evt *script, b32 isInitialCall)
ApiStatus HasMerleeCasts(Evt *script, b32 isInitialCall)
ApiStatus SetNpcYaw(Evt *script, b32 isInitialCall)
ApiStatus GetCamLookAtObjVector(Evt *script, b32 isInitialCall)
ApiStatus ShowMerleeRanOutMessage(Evt *script, b32 isInitialCall)
ApiStatus func_800458CC(Evt *script, b32 isInitialCall)
ApiStatus OnPlayerFled(Evt *script, b32 isInitialCall)
ApiStatus SetNpcFlagBits(Evt *script, b32 isInitialCall)
ApiStatus GetPlayerPos(Evt *script, b32 isInitialCall)
ApiStatus GetBattleOutcome(Evt *script, b32 isInitialCall)
#define Switch(LVAR)
Marks the start of a switch statement.
Definition macros.h:311
#define Set(VAR, INT_VALUE)
Sets the given variable to a given value casted to an integer.
Definition macros.h:365
#define CaseEq(RVAR)
Marks the start of a switch case that executes only if LVAR == RVAR. It also marks the end of any pre...
Definition macros.h:319
#define SCREEN_WIDTH
Definition macros.h:109
#define End
Signals the end of EVT script data. A script missing this will likely crash on load.
Definition macros.h:213
#define Add(VAR, INT_VALUE)
Definition macros.h:376
#define EndLoop
Marks the end of a loop.
Definition macros.h:248
#define EndCaseGroup
Marks the end of a switch case group (CaseOrEq and/or CaseAndEq), stopping fallthrough.
Definition macros.h:352
#define BSS
Definition macros.h:7
#define ARRAY_COUNT(arr)
Definition macros.h:40
#define CaseOrEq(RVAR)
Marks the start of a switch case that executes only if LVAR == RVAR.
Definition macros.h:341
#define EndIf
Marks the end of an if statement or an else block.
Definition macros.h:298
#define SCREEN_HEIGHT
Definition macros.h:110
#define ExecWait(EVT_SOURCE)
Launches a new child thread.
Definition macros.h:475
#define Thread
Marks the start of a thread block.
Definition macros.h:544
#define EndThread
Marks the end of a thread block.
Definition macros.h:547
#define LVar2
Definition macros.h:150
#define DEG_TO_RAD(deg)
Definition macros.h:138
#define LVar1
Definition macros.h:149
#define LVarA
Definition macros.h:158
#define Wait(NUM_FRAMES)
Blocks for the given number of frames.
Definition macros.h:254
#define SQ(x)
Definition macros.h:170
#define EndSwitch
Marks the end of a switch statement and any case.
Definition macros.h:362
#define IfEq(LVAR, RVAR)
Marks the beginning of an if statement that only executes if LVAR == RVAR.
Definition macros.h:269
#define F16(f)
Fixed-point short literal.
Definition macros.h:175
#define Call(FUNC, ARGS...)
Calls a given C EVT API function with any number of arguments.
Definition macros.h:576
#define Loop(TIMES)
Marks the beginning of a loop.
Definition macros.h:245
#define EVT_LIMIT
Definition macros.h:47
#define LVar0
Definition macros.h:148
#define Return
Kills the current EVT thread.
Definition macros.h:217
EvtScript EVS_NpcHitRecoil
Definition 38F00.c:13
@ SPRITE_ID_BACK_FACING
Definition sprite.h:13
Zero-terminated.
Definition battle.h:195
Vec3f lookAt_obj
s16 collisionDiameter
s32 flags
s16 collisionHeight
s16 yawCamOffset
Vec3f pos
s32 gOverrideFlags
Definition main_loop.c:10
PartnerStatus gPartnerStatus
Definition partners.c:42
GameStatus * gGameStatusPtr
Definition main_loop.c:31
Camera gCameras[4]
Definition cam_main.c:16
PlayerData gPlayerData
Definition 77480.c:39
u8 * gBackgroundTintModePtr
Definition model.c:105
PlayerStatus gPlayerStatus
Definition 77480.c:38
s32 gCurrentCameraID
Definition cam_math.c:5
void fx_damage_stars(s32, f32, f32, f32, f32, f32, f32, s32)