Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
ProjectileHitbox.inc.c
Go to the documentation of this file.
1#ifndef _AI_PROJECTILE_HITBOX_INC_
2#define _AI_PROJECTILE_HITBOX_INC_ 0
3
4#include "common.h"
5#include "npc.h"
6#include "effects.h"
7
9 Enemy* enemy = script->owner1.enemy;
10 Bytecode* args = script->ptrReadPos;
12 Npc* npc = get_npc_unsafe(enemy->npcID);
17 s32 i;
18
19 if (ai_check_player_dist(enemy, 0, aiSettings->chaseRadius, aiSettings->chaseOffsetDist)) {
20 if (clamp_angle(get_clamped_angle_diff(camera->curYaw, npc->yaw)) < 180.0) {
21 facingAngle = 90.0f;
22 } else {
23 facingAngle = 270.0f;
24 }
25
28 if (fabsf(deltaAngle) > 75.0 || (2.0 * npc->collisionHeight <= fabsf(npc->pos.y - gPlayerStatusPtr->pos.y))) {
29 return -1;
30 }
32 return -1;
33 }
35 return -1;
36 }
37
38 // choose the first idle projectile hitbox
39 for (i = 0; i < enemy->AI_PROJECTILE_AMMO_COUNT; i++) {
40 s32 projectileNpcID = enemy->npcID + i + 1;
42
44
45 if (projectileEnemy->VAR_PROJECTILE_HITBOX_STATE == 0) {
46 return projectileNpcID;
47 }
48 }
49 }
50 return -1;
51}
52
54 Enemy* enemy = script->owner1.enemy;
55 Npc* npc = get_npc_unsafe(enemy->npcID);
56
57 if (basic_ai_check_player_dist(territory, enemy, arg1, arg2, 1) == 0) {
59
60 fx_emote(EMOTE_QUESTION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 15, &sp28);
62 npc->duration = 20;
63 script->functionTemp[0] = 33;
64 } else {
66
67 if (npcID != NPC_SELF && get_enemy(npcID)->varTable[0] == 0 && npc->turnAroundYawAdjustment == 0) {
69 npc->duration = enemy->varTable[1];
70 script->functionTemp[0] = 30;
71 }
72 }
73}
74
76 Enemy* enemy = script->owner1.enemy;
77 Npc* npc = get_npc_unsafe(enemy->npcID);
78 s32 npcID;
79
80 npc->duration--;
81 if (npc->duration <= 0) {
83 if (npcID < 0) {
85
86 fx_emote(EMOTE_QUESTION, npc, 0.0f, npc->collisionHeight, 1.0f, 2.0f, -20.0f, 15, &emoteTemp);
88 } else {
90
92 hitboxEnemy = get_enemy(npcID);
93 hitboxEnemy->varTable[4] = enemy->npcID;
94 hitboxEnemy->varTable[0] = 1;
95 }
96 npc->duration = enemy->varTable[2];
97 script->functionTemp[0] = AI_STATE_PROJECTILE_HITBOX_33;
98 }
99}
100
102 Enemy* enemy = script->owner1.enemy;
103
104 get_npc_unsafe(enemy->npcID)->duration = enemy->varTable[2];
105 script->functionTemp[0] = AI_STATE_PROJECTILE_HITBOX_33;
106}
107
109 Enemy* enemy = script->owner1.enemy;
110 Npc* npc = get_npc_unsafe(enemy->npcID);
111 Enemy* enemy2 = get_enemy(enemy->npcID + 1);
112 Npc* npc2 = get_npc_unsafe(enemy2->npcID);
113
114 npc->yaw = atan2(npc->pos.x, npc->pos.z, npc2->pos.x, npc2->pos.z);
115 if (enemy2->varTable[0] == 0) {
117 npc->duration = enemy->varTable[2];
118 script->functionTemp[0] = AI_STATE_PROJECTILE_HITBOX_33;
119 }
120}
121
122// TODO same as ParatroopaAI_Reset, but removes the extra args since it affects codegen...?
124 Npc* npc = get_npc_unsafe(script->owner1.enemy->npcID);
125
126 npc->duration--;
127 if (npc->duration <= 0) {
128 script->functionTemp[0] = AI_STATE_WANDER_INIT;
129 }
130}
131
132API_CALLABLE(N(ProjectileAI_Main)) {
133 Enemy* enemy = script->owner1.enemy;
134 Bytecode* args = script->ptrReadPos;
135 s32 phi_s6 = 0;
136 f32 x, y, z;
138 Npc* npc;
139 Npc* npc2;
141 u32 vt0;
142
143 if (get_enemy_safe(enemy->npcID) != NULL) {
144 if (enemy->varTable[0] != 5) {
146 npc = get_npc_unsafe(enemy->npcID);
147
148 if (enemy->varTable[1] & 2) {
150 }
151
152 if (isInitialCall || (enemy->aiFlags & AI_FLAG_SUSPEND)) {
153 script->functionTemp[0] = 0;
154 npc->duration = 0;
157 npc->flags &= ~NPC_FLAG_JUMPING;
158 enemy->varTable[0] = 0;
162 if (enemy->aiFlags & AI_FLAG_SUSPEND) {
163 enemy->aiFlags &= ~AI_FLAG_SUSPEND;
164 }
165 }
166
167 switch (script->functionTemp[0]) {
168 default:
169 return 0;
170 case 0:
173 enemy->varTable[0] = 0;
174 script->functionTemp[0] = 1;
175 // fallthrough
176 case 1:
177 vt0 = enemy->varTable[0];
178
179 if (enemy->varTable[0] == 1) {
180 enemy->varTable[0] = 2;
181 npc2 = get_npc_unsafe(enemy->varTable[4]);
182 npc->pos.x = npc2->pos.x;
183 npc->pos.z = npc2->pos.z;
184 add_vec2D_polar(&npc->pos.x, &npc->pos.z, enemy->varTable[3], 270.0f - npc2->renderYaw);
185 npc->pos.y = npc2->pos.y + enemy->varTable[2];
186 enemy->hitboxIsActive = vt0;
187 enemy->unk_10.x = npc->pos.x;
188 enemy->unk_10.y = npc->pos.y;
189 enemy->unk_10.z = npc->pos.z;
190 npc->rot.x = 0.0f;
191 npc->rot.y = 0.0f;
192 npc->rot.z = 0.0f;
193 npc->moveSpeed = aiSettings->moveSpeed;
194 npc->yaw = atan2(npc->pos.x, npc->pos.z, gPlayerStatusPtr->pos.x, gPlayerStatusPtr->pos.z);
195 npc->jumpVel = aiSettings->alertRadius;
196 npc->jumpScale = aiSettings->alertOffsetDist;
197 npc->moveToPos.y = npc2->pos.y;
200 npc->flags |= NPC_FLAG_JUMPING;
203 npc->duration = 90;
204 script->functionTemp[0] = 2;
205 break;
206 }
207 return 0;
208 case 2:
209 break;
210 }
211
212 x = npc->pos.x;
213 y = npc->pos.y + (npc->collisionHeight * 0.5);
214 z = npc->pos.z;
216 0, &x, &y, &z, npc->moveSpeed, npc->yaw, npc->collisionDiameter, npc->collisionHeight) != 0)
217 {
218 phi_s6 = 1;
219 }
220
221 x = npc->pos.x;
222 y = npc->pos.y;
223 z = npc->pos.z;
224 hitDepth = 1000.0f;
225 if ((npc_raycast_down_sides(npc->collisionChannel, &x, &y, &z, &hitDepth) != 0) &&
226 (hitDepth < fabsf(npc->jumpVel)) &&
227 (fabsf(y - npc->moveToPos.y) < 20.0))
228 {
229 npc->pos.y = y;
230 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
231 phi_s6 = 10;
232 }
233
234 if (hitDepth < 1.0) {
235 phi_s6 = 11;
236 }
237 npc->duration--;
238 if (npc->duration <= 0) {
239 phi_s6 = 20;
240 }
241
242 if (phi_s6 == 0) {
243 if (enemy->varTable[1] & 1) {
244 npc->rot.z += 40.0;
245 }
246 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
247 npc->pos.y += npc->jumpVel;
248 npc->jumpVel -= npc->jumpScale;
249 } else {
250 fx_walking_dust(2, npc->pos.x, npc->pos.y, npc->pos.z, 0, 0);
251 enemy->varTable[0] = 0;
252 npc->pos.x = NPC_DISPOSE_POS_X;
253 npc->pos.y = NPC_DISPOSE_POS_Y;
254 npc->pos.z = NPC_DISPOSE_POS_Z;
255 npc->jumpVel = 0.0f;
258 npc->flags &= ~NPC_FLAG_JUMPING;
261 script->functionTemp[0] = 0;
262 }
263 }
264 }
265 return ApiStatus_BLOCK;
266}
267
268API_CALLABLE(N(ProjectileAI_Reflect)) {
269 Enemy* enemy = script->owner1.enemy;
271 s32 phi_s4 = 0;
272 Npc* npc;
273 f32 x, y, z;
278 f32 yaw;
279 s32 cond;
280
281 if (isInitialCall) {
282 script->functionTemp[0] = 0;
283 }
284
285 if (get_enemy_safe(enemy->npcID) == NULL) {
287 return ApiStatus_DONE2;
288 }
289 if (enemy->varTable[0] == 5) {
291 return ApiStatus_DONE2;
292 }
293 if (get_enemy_safe(enemy->npcID) == NULL) {
295 return ApiStatus_DONE2;
296 }
297
298 npc = get_npc_unsafe(enemy->npcID);
299 switch (script->functionTemp[0]) {
300 case 0:
301 fx_walking_dust(2, npc->pos.x, npc->pos.y, npc->pos.z, 0.0f, 0.0f);
302 yaw = clamp_angle(camera->curYaw);
303 temp_f20_2 = clamp_angle(yaw + 180.0);
304 temp_f22 = clamp_angle(yaw + 90.0);
307 npc->yaw = temp_f22;
308 } else {
309 npc->yaw = temp_f20_3;
310 }
311 npc->duration = 30;
312 npc->jumpVel = 10.0f;
313 npc->jumpScale = 0.9f;
314 npc->moveSpeed *= 1.2;
315 script->functionTemp[0] = 1;
316 // fallthrough
317 case 1:
318 x = npc->pos.x;
319 y = npc->pos.y;
320 z = npc->pos.z;
321 if (npc_test_move_simple_with_slipping(0, &x, &y, &z, npc->moveSpeed, npc->yaw, npc->collisionDiameter,
322 npc->collisionHeight) == 0)
323 {
324 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
325 } else {
326 phi_s4 = 1;
327 }
328
329 cond = FALSE;
330 if (npc->jumpVel < 0.0) {
331 x = npc->pos.x;
332 y = npc->pos.y + 13.0;
333 z = npc->pos.z;
334 hitDepth = fabsf(npc->jumpVel) + 16.0;
335 if ((npc_raycast_down_sides(npc->collisionChannel, &x, &y, &z, &hitDepth) != 0) &&
336 (hitDepth <= (fabsf(npc->jumpVel) + 13.0)))
337 {
338 cond = TRUE;
339 }
340 }
341
342 if (!cond) {
343 npc->pos.y += npc->jumpVel;
344 npc->jumpVel -= npc->jumpScale;
345 } else {
346 phi_s4 = 10;
347 }
348
349 npc->duration--;
350 if (npc->duration <= 0) {
351 phi_s4 = 11;
352 }
353
354 if (phi_s4 != 0) {
355 fx_walking_dust(2, npc->pos.x, npc->pos.y, npc->pos.z, 0, 0);
356 enemy->varTable[0] = 0;
357 npc->pos.x = NPC_DISPOSE_POS_X;
358 npc->pos.y = NPC_DISPOSE_POS_Y;
359 npc->pos.z = NPC_DISPOSE_POS_Z;
362 npc->flags &= ~NPC_FLAG_JUMPING;
365 script->functionTemp[0] = 0;
367 return ApiStatus_DONE2;
368 }
369 if (enemy->varTable[1] & 1) {
370 npc->rot.z += 60.0;
371 }
372 break;
373 }
374 return ApiStatus_BLOCK;
375}
376
377#endif
BSS s32 PopupMenu_SelectedIndex
void N ProjectileHitbox_31(Evt *script)
s32 N ProjectileHitbox_GetUsableProjectileID(Evt *script)
void N ProjectileHitbox_33(Evt *script)
void N ProjectileHitbox_30(Evt *script)
void N UnkNpcAIFunc48(Evt *script, f32 arg1, f32 arg2, EnemyDetectVolume *territory)
void N ProjectileHitbox_32(Evt *script)
#define npc_raycast_down_sides
#define clamp_angle
#define atan2
@ EMOTE_QUESTION
Definition enums.h:497
@ ENEMY_ANIM_INDEX_MELEE_PRE
Definition enums.h:3434
@ ENEMY_ANIM_INDEX_IDLE
Definition enums.h:3426
@ ENEMY_ANIM_INDEX_MELEE_HIT
Definition enums.h:3435
@ AI_FLAG_SUSPEND
Definition enums.h:4570
@ AI_STATE_WANDER_INIT
Definition enums.h:4580
@ AI_STATE_PROJECTILE_HITBOX_33
Definition enums.h:4607
@ ENEMY_FLAG_IGNORE_HAMMER
Definition enums.h:4546
@ ENEMY_FLAG_IGNORE_PARTNER
Definition enums.h:4548
@ ENEMY_FLAG_PROJECTILE
Definition enums.h:4526
@ ENEMY_FLAG_SKIP_BATTLE
Definition enums.h:4540
@ ENEMY_FLAG_IGNORE_TOUCH
Definition enums.h:4544
@ ENEMY_FLAG_CANT_INTERACT
Definition enums.h:4547
@ ENEMY_FLAG_IGNORE_JUMP
Definition enums.h:4545
@ ENEMY_FLAG_ACTIVE_WHILE_OFFSCREEN
Definition enums.h:4541
@ NPC_SELF
Definition enums.h:2526
@ PARTNER_BOW
Definition enums.h:2894
@ PARTNER_SUSHIE
Definition enums.h:2892
@ NPC_FLAG_JUMPING
Definition enums.h:3009
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
Definition enums.h:3006
@ NPC_FLAG_INVISIBLE
Definition enums.h:2999
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
Definition enums.h:3016
#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:1689
f32 fabsf(f32 f)
s32 evt_set_variable(Evt *script, Bytecode var, s32 value)
Definition evt.c:1846
b32 npc_test_move_simple_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
b32 npc_test_move_taller_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
s32 ai_check_player_dist(Enemy *enemy, s32 arg1, f32 arg2, f32 arg3)
Definition 23680.c:515
void add_vec2D_polar(f32 *x, f32 *y, f32 r, f32 theta)
Definition 43F0.c:684
f32 get_clamped_angle_diff(f32, f32)
Definition 43F0.c:605
s32 flags
Definition npc.h:295
s16 npcID
Definition npc.h:300
Enemy * get_enemy_safe(s32 npcID)
Same as get_enemy(), with the exception of always returning a value if an enemy is not found.
Definition npc.c:2558
b32 basic_ai_check_player_dist(EnemyDetectVolume *arg0, Enemy *arg1, f32 arg2, f32 arg3, s8 arg4)
Definition 23680.c:429
Enemy * get_enemy(s32 npcID)
Looks for an enemy matching the specified npcID.
Definition npc.c:2539
void enable_npc_shadow(Npc *npc)
Definition npc.c:1026
s32 * animList
Definition npc.h:341
void disable_npc_shadow(Npc *npc)
Definition npc.c:1036
Npc * get_npc_unsafe(s32 npcID)
Definition npc.c:994
Vec3s unk_10
Definition npc.h:302
s8 hitboxIsActive
Definition npc.h:299
u32 aiFlags
Definition npc.h:332
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
Definition npc.c:985
Definition npc.h:294
#define NPC_DISPOSE_POS_Z
Definition macros.h:165
#define NPC_DISPOSE_POS_X
Definition macros.h:163
#define NPC_DISPOSE_POS_Y
Definition macros.h:164
#define LVar0
Definition macros.h:148
s16 collisionDiameter
f32 jumpScale
f32 jumpVel
s32 flags
AnimID curAnim
Vec3f moveToPos
s32 collisionChannel
s16 collisionHeight
s16 turnAroundYawAdjustment
Vec3f rot
s8 verticalRenderOffset
Vec3f pos
f32 moveSpeed
s16 duration
PlayerStatus * gPlayerStatusPtr
PartnerStatus gPartnerStatus
Definition partners.c:42
Camera gCameras[4]
Definition cam_main.c:17
s16 gCurrentCamID
Definition cam_main.c:13