Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
MagikoopaAI.inc.c
Go to the documentation of this file.
1#include "common.h"
2#include "npc.h"
3#include "sprite.h"
4
10
11#define ENEMY_FLAG_COMBINATION (ENEMY_FLAG_IGNORE_PARTNER | ENEMY_FLAG_CANT_INTERACT | \
12 ENEMY_FLAG_IGNORE_HAMMER | ENEMY_FLAG_IGNORE_JUMP | ENEMY_FLAG_IGNORE_TOUCH | ENEMY_FLAG_SKIP_BATTLE)
13
14extern MagikoopaTeleportAnim N(MagikoopaAI_TeleportAnim)[];
15
17
18void N(MagikoopaAI_00)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
19 Enemy* enemy = script->owner1.enemy;
20 Npc* npc = get_npc_unsafe(enemy->npcID);
21
22 npc->duration--;
23 if (npc->duration <= 0) {
25 npc->flags &= ~NPC_FLAG_INVISIBLE;
26 npc->duration = 0;
27 script->AI_TEMP_STATE = 1;
28 }
29}
30
31void N(MagikoopaAI_01)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
32 Enemy* enemy = script->owner1.enemy;
33 Npc* npc = get_npc_unsafe(enemy->npcID);
34 npc->scale.x = N(MagikoopaAI_TeleportAnim)[npc->duration].scaleX;
35 npc->scale.y = N(MagikoopaAI_TeleportAnim)[npc->duration].scaleY;
36 npc->alpha = N(MagikoopaAI_TeleportAnim)[npc->duration].alpha;
37
38 npc->duration++;
39 if (npc->duration == 4) {
42 }
43
44 if (N(MagikoopaAI_TeleportAnim)[npc->duration].alpha == 0) {
45 npc->alpha = 0xFF;
46 npc->scale.x = 1.0f;
47 npc->scale.y = 1.0f;
48 npc->scale.z = 1.0f;
50 script->AI_TEMP_STATE = 5;
51 }
52}
53
54void N(MagikoopaAI_05)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
55 Npc* npc = get_npc_unsafe(script->owner1.enemy->npcID);
56 f32 angle = (rand_int(100) % 2) * 180.0f;
57
58 npc->duration = 15;
59 npc->moveSpeed = 0.8f;
60 npc->yaw = angle + 90.0f;
61 script->AI_TEMP_STATE = 6;
62}
63
64void N(MagikoopaAI_06)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
65 Enemy* enemy = script->owner1.enemy;
66 Npc* npc = get_npc_unsafe(enemy->npcID);
67
68 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
69 npc->duration--;
70 if (npc->duration <= 0) {
71 script->AI_TEMP_STATE = 10;
72 }
73}
74
75void N(MagikoopaAI_10)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
76 Enemy* enemy = script->owner1.enemy;
77 Npc* npc = get_npc_unsafe(enemy->npcID);
78 f32 dist = dist2D(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
79 f32 posX, posY, posZ;
80
81 enemy->varTable[0] = 1;
82 npc->curAnim = enemy->animList[8];
83 npc->yaw = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
84 npc->flags &= ~NPC_FLAG_INVISIBLE;
85 npc->scale.x = 0.1f;
86 npc->scale.y = 0.1f;
87 npc->scale.z = 0.1f;
88 if (!(npc->flags & NPC_FLAG_FLYING)) {
89 posX = npc->pos.x;
90 dist = 200.0f;
91 posZ = npc->pos.z;
92 posY = npc->pos.y + 100.0;
93 if (npc_raycast_down_sides(npc->collisionChannel, &posX, &posY, &posZ, &dist) != 0) {
94 npc->pos.y = posY;
95 }
96 }
97 npc->duration = 0;
98 script->AI_TEMP_STATE = 0xB;
99}
100
101void N(MagikoopaAI_11)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
102 Enemy* enemy = script->owner1.enemy;
103 Npc* npc = get_npc_unsafe((s32) enemy->npcID);
104 f32 scale;
105 s16 alpha;
106
107 if (enemy->varTable[0] == 0) {
108 alpha = (npc->duration * 15) + 130;
109 } else {
110 alpha = (npc->duration * 15) + 30;
111 }
112 if (alpha > 255) {
113 alpha = 255;
114 }
115 npc->alpha = alpha;
116
117 npc->scale.x = ((f32)npc->duration * 0.1) + 0.4;
118 if (npc->scale.x > 1.0) {
119 npc->scale.x = 1.0f;
120 }
121 npc->scale.y = npc->scale.x;
122 npc->scale.z = npc->scale.x;
123
124 npc->duration++;
125 if (npc->duration == 5) {
127 enemy->flags &= ~ENEMY_FLAG_COMBINATION;
128 }
129 if (enemy->varTable[0] == 0) {
130 if (npc->duration >= 20) {
131 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_CLEAR, 0, 0, 0, 0, 0);
132 npc->alpha = 255;
133 npc->scale.x = 1.0f;
134 npc->scale.y = 1.0f;
135 npc->scale.z = 1.0f;
136 script->AI_TEMP_STATE = 20;
137 }
138 } else if (npc->duration >= 10) {
139 npc->alpha = 255;
140 npc->scale.x = 1.0f;
141 npc->scale.y = 1.0f;
142 npc->scale.z = 1.0f;
143 script->AI_TEMP_STATE = 20;
144 }
145}
146
147void N(MagikoopaAI_20)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
148 Enemy* enemy = script->owner1.enemy;
149 Npc* npc = get_npc_unsafe(enemy->npcID);
150
151 npc->duration = 40;
152 script->AI_TEMP_STATE = 21;
153}
154
155void N(MagikoopaAI_21)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
156 Enemy* enemy = script->owner1.enemy;
157 Npc* npc = get_npc_unsafe(enemy->npcID);
158 f32 posX, posY, posZ;
159 EffectInstance* emoteTemp;
160
161 npc->duration--;
162 if (npc->duration == 0) {
163 npc->curAnim = enemy->animList[0];
164 fx_emote(2, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 12, &emoteTemp);
165 npc->curAnim = enemy->animList[0];
166 npc->duration = 0xF;
167 script->AI_TEMP_STATE = 0;
168 return;
169 }
170 if (N(MagikoopaAI_CanShootSpell)(script, aiSettings->chaseRadius, aiSettings->chaseOffsetDist, territory) == 1) {
172 npc->curAnim = enemy->animList[8];
173 posX = npc->pos.x;
174 posY = npc->pos.y + 32.0f;
175 posZ = npc->pos.z + 1.0f;
176 add_vec2D_polar(&posX, &posZ, 17.0f, 270.0f - npc->renderYaw);
177 fx_gather_energy_pink(0, posX, posY, posZ, 0.1f, 0xD);
178 npc->duration = 0xF;
179 script->AI_TEMP_STATE = 0x16;
180 }
181}
182
183void N(MagikoopaAI_22)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
184 Enemy* temp_s0 = script->owner1.enemy;
185 Npc* temp_v0 = get_npc_unsafe(temp_s0->npcID);
186
187 temp_v0->duration--;
188 if (temp_v0->duration <= 0) {
189 temp_v0->curAnim = temp_s0->animList[9];
190 temp_v0->duration = 9;
191 script->AI_TEMP_STATE = 0x17;
192 }
193}
194
195void N(MagikoopaAI_23)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
196 Enemy* enemy = script->owner1.enemy;
197 Npc* npc = get_npc_unsafe(enemy->npcID);
198 s32 projectileEnemy;
199 EffectInstance* emoteTemp;
200
201 npc->duration--;
202 if (npc->duration <= 0) {
203 projectileEnemy = N(MagikoopaAI_CanShootSpell)(script, aiSettings->chaseRadius, aiSettings->chaseOffsetDist, territory);
204 if (projectileEnemy != 1) {
205 fx_emote(2, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 0xC, &emoteTemp);
206 npc->curAnim = enemy->animList[0];
207 npc->duration = 15;
208 script->AI_TEMP_STATE = 0;
209 } else {
211 get_enemy(enemy->npcID + 1)->varTable[0] = projectileEnemy;
212 npc->duration = 0x14;
213 script->AI_TEMP_STATE = 0x18;
214 }
215 }
216}
217
218void N(MagikoopaAI_24)(Evt* script, MobileAISettings* aiSettings, EnemyDetectVolume* territory) {
219 Enemy* enemy = script->owner1.enemy;
220 Npc* npc = get_npc_unsafe(enemy->npcID);
221
222 npc->duration--;
223 if (npc->duration <= 0) {
224 npc->curAnim = enemy->animList[0];
225 npc->duration = 3;
226 script->AI_TEMP_STATE = 0;
227 }
228}
229
230API_CALLABLE(N(MagikoopaAI_Main)) {
231 Enemy* enemy = script->owner1.enemy;
232 Npc* npc = get_npc_unsafe(enemy->npcID);
233 EnemyDetectVolume territory;
234 EnemyDetectVolume* territoryPtr = &territory;
235 Bytecode* args = script->ptrReadPos;
236 MobileAISettings* aiSettings = (MobileAISettings*) evt_get_variable(script, *args++);
237 f32 posX;
238 f32 posY;
239 f32 posZ;
240 f32 hitDepth;
241
242 territory.skipPlayerDetectChance = 0;
243 territory.shape = enemy->territory->wander.detectShape;
244 territory.pointX = enemy->territory->wander.detectPos.x;
245 territory.pointZ = enemy->territory->wander.detectPos.z;
246 territory.sizeX = enemy->territory->wander.detectSize.x;
247 territory.sizeZ = enemy->territory->wander.detectSize.z;
248 territory.halfHeight = 100.0f;
249 territory.detectFlags = 0;
250
251 if (isInitialCall || (enemy->aiFlags & AI_FLAG_SUSPEND)) {
252 npc->curAnim = enemy->animList[0];
253 npc->flags &= ~NPC_FLAG_JUMPING;
256 npc->duration = 0;
257 if (enemy->aiFlags & AI_FLAG_SUSPEND) {
258 enemy->aiFlags &= ~AI_FLAG_SUSPEND;
259 npc->alpha = 0xFF;
260 npc->duration = 20;
261 npc->scale.x = 1.0f;
262 npc->scale.y = 1.0f;
263 npc->scale.z = 1.0f;
264 }
265 script->AI_TEMP_STATE = 0;
266 }
267
268 switch (script->AI_TEMP_STATE) {
269 case 0:
270 N(MagikoopaAI_00)(script, aiSettings, territoryPtr);
271 if (script->AI_TEMP_STATE != 1) {
272 break;
273 }
274 // fallthrough
275 case 1:
276 N(MagikoopaAI_01)(script, aiSettings, territoryPtr);
277 break;
278 case 5:
279 N(MagikoopaAI_05)(script, aiSettings, territoryPtr);
280 // fallthrough
281 case 6:
282 N(MagikoopaAI_06)(script, aiSettings, territoryPtr);
283 break;
284 case 10:
285 N(MagikoopaAI_10)(script, aiSettings, territoryPtr);
286 // fallthrough
287 case 11:
288 N(MagikoopaAI_11)(script, aiSettings, territoryPtr);
289 break;
290 case 20:
291 N(MagikoopaAI_20)(script, aiSettings, territoryPtr);
292 break;
293 case 21:
294 N(MagikoopaAI_21)(script, aiSettings, territoryPtr);
295 break;
296 case 22:
297 N(MagikoopaAI_22)(script, aiSettings, territoryPtr);
298 break;
299 case 23:
300 N(MagikoopaAI_23)(script, aiSettings, territoryPtr);
301 break;
302 case 24:
303 N(MagikoopaAI_24)(script, aiSettings, territoryPtr);
304 break;
305 }
306 return ApiStatus_BLOCK;
307}
308
309API_CALLABLE(N(MagikoopaAI_OnPlayerWon)) {
310 Enemy* enemy = script->owner1.enemy;
311 Npc* npc = get_npc_unsafe(enemy->npcID);
312
313 npc->alpha = 255;
314 set_npc_imgfx_all(npc->spriteInstanceID, IMGFX_CLEAR, 0, 0, 0, 0, 0);
315 return ApiStatus_DONE2;
316}
317
318API_CALLABLE(N(MagikoopaAI_OnPlayerFled)) {
319 Enemy* enemy = script->owner1.enemy;
320 Npc* npc = get_npc_unsafe(enemy->npcID);
321
322 npc->alpha = 255;
323 npc->curAnim = enemy->animList[2];
324 npc->duration = 0;
325 script->functionTemp[0] = 0;
326 return ApiStatus_DONE2;
327}
328
329API_CALLABLE(N(MagikoopaAI_OnHitInit)) {
330 Enemy* enemy = script->owner1.enemy;
331
333 return ApiStatus_DONE2;
334}
335
336API_CALLABLE(N(MagikoopaAI_OnHit)) {
337 Enemy* enemy = script->owner1.enemy;
338 Npc* npc = get_npc_unsafe(enemy->npcID);
339
340 if (enemy->varTable[0] == 2) {
341 npc->jumpVel = 0.0f;
342 npc->moveSpeed = 0.0f;
343 }
344 return ApiStatus_DONE2;
345}
void N MagikoopaAI_00(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N MagikoopaAI_23(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N MagikoopaAI_01(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N MagikoopaAI_10(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
#define ENEMY_FLAG_COMBINATION
void N MagikoopaAI_05(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N MagikoopaAI_22(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N MagikoopaAI_11(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N MagikoopaAI_06(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N MagikoopaAI_21(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N MagikoopaAI_24(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
void N MagikoopaAI_20(Evt *script, MobileAISettings *aiSettings, EnemyDetectVolume *territory)
s32 N MagikoopaAI_CanShootSpell(Evt *script, f32 arg1, f32 arg2, EnemyDetectVolume *territory)
#define npc_raycast_down_sides
#define rand_int
#define atan2
@ IMGFX_CLEAR
Definition enums.h:5117
@ ENEMY_ANIM_INDEX_IDLE
Definition enums.h:3426
@ AI_FLAG_SUSPEND
Definition enums.h:4571
@ ENEMY_FLAG_ACTIVE_WHILE_OFFSCREEN
Definition enums.h:4542
@ SOUND_SPELL_CAST1
Definition enums.h:1498
@ SOUND_SPELL_CAST2
Definition enums.h:1499
@ NPC_FLAG_FLYING
Definition enums.h:3001
@ NPC_FLAG_FLIP_INSTANTLY
Definition enums.h:3019
@ NPC_FLAG_INVISIBLE
Definition enums.h:2999
#define ApiStatus_DONE2
Definition evt.h:118
s32 Bytecode
Definition evt.h:7
#define ApiStatus_BLOCK
Definition evt.h:116
s32 evt_get_variable(Evt *script, Bytecode var)
Definition evt.c:1690
void ai_enemy_play_sound(Npc *npc, s32 arg1, s32 arg2)
Definition 23680.c:543
s32 evt_set_variable(Evt *script, Bytecode var, s32 value)
Definition evt.c:1847
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
void add_vec2D_polar(f32 *x, f32 *y, f32 r, f32 theta)
Definition 43F0.c:685
enum TerritoryShape shape
Definition npc.h:201
s32 flags
Definition npc.h:295
VecXZi detectSize
Definition npc.h:216
enum TerritoryShape detectShape
Definition npc.h:217
s16 npcID
Definition npc.h:300
Enemy * get_enemy(s32 npcID)
Looks for an enemy matching the specified npcID.
Definition npc.c:2540
void enable_npc_shadow(Npc *npc)
Definition npc.c:1027
s32 * animList
Definition npc.h:341
Enemy * curEnemy
Definition npc.h:394
void disable_npc_shadow(Npc *npc)
Definition npc.c:1037
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:995
s16 detectFlags
Definition npc.h:207
EncounterStatus gCurrentEncounter
Definition encounter.c:176
u32 aiFlags
Definition npc.h:332
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
Definition npc.c:986
s32 skipPlayerDetectChance
Definition npc.h:200
EnemyTerritoryWander wander
Definition npc.h:232
EnemyTerritory * territory
Definition npc.h:342
Definition npc.h:294
#define LVar0
Definition macros.h:148
void set_npc_imgfx_all(s32 spriteIdx, ImgFXType imgfxType, s32 imgfxArg1, s32 imgfxArg2, s32 imgfxArg3, s32 imgfxArg4, s32 imgfxArg5)
Definition sprite.c:1254
Vec3f scale
f32 jumpVel
s32 flags
f32 renderYaw
s32 spriteInstanceID
AnimID curAnim
s32 collisionChannel
s16 collisionHeight
Vec3f pos
f32 moveSpeed
s16 duration
PlayerStatus * gPlayerStatusPtr