Paper Mario DX
Paper Mario (N64) modding
 
Loading...
Searching...
No Matches
bombette.c
Go to the documentation of this file.
1#include "common.h"
2#include "world/partners.h"
3#include "effects.h"
4#include "sprite/npc/WorldBombette.h"
5#include "sprite/player.h"
6
7#define NAMESPACE world_bombette
8
9BSS b32 N(PlayerWasFacingLeft);
10BSS b32 N(PlayingFuseSound);
11BSS b32 N(IsBlasting); // TRUE for 3 frames while using ability
12BSS b32 N(LockingPlayerInput);
13BSS b32 N(MaintainPosAfterBlast);
14BSS b32 N(TriggeredEarlyDetonation);
15BSS b32 N(MovementBlocked);
16BSS s32 N(D_802BE93C); // unused (padding?)
17
19
21 f32 x, y, z;
22 f32 angle = 0.0f;
23
24 // first pass looking for entities
25 while (angle < 360.0f) {
26 x = npc->pos.x;
27 y = npc->pos.y;
28 z = npc->pos.z;
30 &x, &y, &z, 30.0f, clamp_angle(npc->yaw + angle),
31 npc->collisionHeight, npc->collisionDiameter)
32 ) {
33 break;
34 }
35 angle += 45.0f;
36 }
37
38 // second pass looking for everything but entities
39 if (angle >= 360.0f) {
40 angle = 0.0f;
41
42 while (angle < 360.0f) {
43 x = npc->pos.x;
44 y = npc->pos.y;
45 z = npc->pos.z;
47 &x, &y, &z, 30.0f, clamp_angle(npc->yaw + angle),
48 npc->collisionHeight, npc->collisionDiameter)
49 ) {
50 break;
51 }
52 angle += 45.0f;
53 }
54
55 if (angle >= 360.0f) {
56 return;
57 }
58 }
59
60 // handle entity interaction if there was a collision
63 }
64}
65
66void N(init)(Npc* bombette) {
67 bombette->collisionHeight = 28;
68 bombette->collisionDiameter = 24;
69 N(IsBlasting) = FALSE;
70 N(PlayingFuseSound) = FALSE;
71}
72
73API_CALLABLE(N(TakeOut)) {
74 Npc* bombette = script->owner2.npc;
75
76 if (isInitialCall) {
77 partner_init_get_out(bombette);
78 }
79
80 if (partner_get_out(bombette)) {
81 return ApiStatus_DONE1;
82 } else {
83 return ApiStatus_BLOCK;
84 }
85}
86
88 Call(N(TakeOut))
89 Return
90 End
91};
92
93BSS TweesterPhysics N(TweesterPhysicsData);
94TweesterPhysics* N(TweesterPhysicsPtr) = &N(TweesterPhysicsData);
95
96API_CALLABLE(N(Update)) {
97 PlayerData* playerData = &gPlayerData;
98 Npc* bombette = script->owner2.npc;
99 f32 sinAngle, cosAngle, liftoffVelocity;
100 Entity* entity;
101
102 if (isInitialCall) {
103 partner_walking_enable(bombette, 1);
104 mem_clear(N(TweesterPhysicsPtr), sizeof(TweesterPhysics));
106 }
107
108 playerData->partnerUsedTime[PARTNER_BOMBETTE]++;
109 bombette->flags |= NPC_FLAG_DIRTY_SHADOW;
111
112 if (entity == NULL) {
115 return ApiStatus_BLOCK;
116 }
117
118 switch (N(TweesterPhysicsPtr)->state) {
120 N(TweesterPhysicsPtr)->state++;
121 N(TweesterPhysicsPtr)->prevFlags = bombette->flags;
122 N(TweesterPhysicsPtr)->radius = fabsf(dist2D(bombette->pos.x, bombette->pos.z,
123 entity->pos.x, entity->pos.z));
124 N(TweesterPhysicsPtr)->angle = atan2(entity->pos.x, entity->pos.z,
125 bombette->pos.x, bombette->pos.z);
126 N(TweesterPhysicsPtr)->angularVel = 6.0f;
127 N(TweesterPhysicsPtr)->liftoffVelPhase = 50.0f;
128 N(TweesterPhysicsPtr)->countdown = 120;
130 bombette->flags &= ~NPC_FLAG_GRAVITY;
132 sin_cos_rad(DEG_TO_RAD(N(TweesterPhysicsPtr)->angle), &sinAngle, &cosAngle);
133 bombette->pos.x = entity->pos.x + (sinAngle * N(TweesterPhysicsPtr)->radius);
134 bombette->pos.z = entity->pos.z - (cosAngle * N(TweesterPhysicsPtr)->radius);
135 N(TweesterPhysicsPtr)->angle = clamp_angle(N(TweesterPhysicsPtr)->angle - N(TweesterPhysicsPtr)->angularVel);
136
137 if (N(TweesterPhysicsPtr)->radius > 20.0f) {
138 N(TweesterPhysicsPtr)->radius--;
139 } else if (N(TweesterPhysicsPtr)->radius < 19.0f) {
140 N(TweesterPhysicsPtr)->radius++;
141 }
142
143 liftoffVelocity = sin_rad(DEG_TO_RAD(N(TweesterPhysicsPtr)->liftoffVelPhase)) * 3.0f;
144 N(TweesterPhysicsPtr)->liftoffVelPhase += 3.0f;
145
146 if (N(TweesterPhysicsPtr)->liftoffVelPhase > 150.0f) {
147 N(TweesterPhysicsPtr)->liftoffVelPhase = 150.0f;
148 }
149
150 bombette->pos.y += liftoffVelocity;
151 bombette->renderYaw = clamp_angle(360.0f - N(TweesterPhysicsPtr)->angle);
152 N(TweesterPhysicsPtr)->angularVel += 0.8;
153
154 if (N(TweesterPhysicsPtr)->angularVel > 40.0f) {
155 N(TweesterPhysicsPtr)->angularVel = 40.0f;
156 }
157
158 if (--N(TweesterPhysicsPtr)->countdown == 0) {
159 N(TweesterPhysicsPtr)->state++;
160 }
161 break;
163 bombette->flags = N(TweesterPhysicsPtr)->prevFlags;
164 N(TweesterPhysicsPtr)->countdown = 30;
165 N(TweesterPhysicsPtr)->state++;
166 break;
170
171 if (--N(TweesterPhysicsPtr)->countdown == 0) {
172 N(TweesterPhysicsPtr)->state = TWEESTER_PARTNER_INIT;
174 }
175 break;
176 }
177 return ApiStatus_BLOCK;
178}
179
181 Call(N(Update))
182 Return
183 End
184};
185
187 if (TweesterTouchingPartner != NULL) {
189 npc->flags = N(TweesterPhysicsPtr)->prevFlags;
190 N(TweesterPhysicsPtr)->state = TWEESTER_PARTNER_INIT;
192 }
193}
194
195s32 N(can_use_ability)(Npc* npc) {
197 N(TriggeredEarlyDetonation) = TRUE;
198 return FALSE;
199 }
200 return TRUE;
201}
202
206
207API_CALLABLE(N(UseAbility)) {
208 PlayerStatus* playerStatus = &gPlayerStatus;
209 CollisionStatus* collisionStatus = &gCollisionStatus;
210 PartnerStatus* partnerStatus = &gPartnerStatus;
211 Camera* camera = &gCameras[CAM_DEFAULT];
212 Npc* npc = script->owner2.npc;
213 u16 temp_ret;
214 f32 x, y, z;
215 f32 hitDepth;
216 f32 temp_f0;
217 f32 angleToPlayer;
218
219 #define USE_STATE functionTemp[0]
220 enum {
221 BLAST_STATE_BEGIN = 20,
222 BLAST_STATE_GATHER = 21,
223 BLAST_STATE_LIFT = 1,
224 BLAST_STATE_DEPLOY = 2,
225 BLAST_STATE_EXPLODE = 3,
226 BLAST_STATE_LIFTOFF = 4,
227 BLAST_STATE_FLY = 5,
228 BLAST_STATE_FALL = 6,
229 BLAST_STATE_CANCEL = 7,
230 BLAST_STATE_FINISH = 8,
231 };
232
233 if (gCurrentEncounter.unk_08 != 0) {
234 return ApiStatus_BLOCK;
235 }
236
237 if (isInitialCall) {
238 N(try_cancel_tweester)(npc);
239 script->USE_STATE = BLAST_STATE_BEGIN;
240 }
241
242 switch (script->USE_STATE) {
243 case BLAST_STATE_BEGIN:
244 if ((playerStatus->inputDisabledCount != 0) || (playerStatus->flags & PS_FLAG_JUMPING) || !(npc->flags & NPC_FLAG_GROUNDED)) {
245 return ApiStatus_DONE2;
246 }
248 script->functionTemp[3] = playerStatus->inputDisabledCount;
249 N(LockingPlayerInput) = TRUE;
250 N(IsBlasting) = FALSE;
251 N(MaintainPosAfterBlast) = FALSE;
252 N(TriggeredEarlyDetonation) = FALSE;
254 partnerStatus->partnerActionState = PARTNER_ACTION_USE;
255 partnerStatus->actingPartner = PARTNER_BOMBETTE;
256 N(PlayerWasFacingLeft) = partner_force_player_flip_done();
257 enable_npc_blur(npc);
258 npc->duration = 4;
259 npc->yaw = atan2(npc->pos.x, npc->pos.z, playerStatus->pos.x, playerStatus->pos.z);
260 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
261 script->USE_STATE = BLAST_STATE_GATHER;
262 case BLAST_STATE_GATHER:
263 if (playerStatus->actionState == ACTION_STATE_HIT_FIRE || playerStatus->actionState == ACTION_STATE_KNOCKBACK) {
264 disable_npc_blur(npc);
265 script->USE_STATE = BLAST_STATE_CANCEL;
266 break;
267 }
268 if (playerStatus->flags & PS_FLAG_JUMPING) {
269 script->USE_STATE = BLAST_STATE_CANCEL;
270 break;
271 }
272 npc->moveToPos.x = playerStatus->pos.x;
273 npc->moveToPos.y = playerStatus->pos.y;
274 npc->moveToPos.z = playerStatus->pos.z;
275 npc->curAnim = ANIM_WorldBombette_Run;
276 add_vec2D_polar(&npc->moveToPos.x, &npc->moveToPos.z, 0.0f, playerStatus->targetYaw);
277 temp_f0 = clamp_angle(playerStatus->targetYaw + (N(PlayerWasFacingLeft) ? -90.0f : 90.0f));
278 add_vec2D_polar(&npc->moveToPos.x, &npc->moveToPos.z, playerStatus->colliderDiameter / 4, temp_f0);
279 npc->pos.x += (npc->moveToPos.x - npc->pos.x) / npc->duration;
280 npc->pos.y += (npc->moveToPos.y - npc->pos.y) / npc->duration;
281 npc->pos.z += (npc->moveToPos.z - npc->pos.z) / npc->duration;
282 npc->duration--;
283 if (npc->duration != 0) {
284 break;
285 }
286 if (script->functionTemp[3] < playerStatus->inputDisabledCount) {
287 disable_npc_blur(npc);
288 // TODO possible to remove float temp here? should be: evt->USE_STATE = BLAST_STATE_CANCEL
289 temp_f0 = 0;
290 script->functionTemp[(u8)temp_f0] = BLAST_STATE_CANCEL;
291 break;
292 }
293 npc->pos.x = npc->moveToPos.x;
294 npc->pos.y = npc->moveToPos.y;
295 npc->pos.z = npc->moveToPos.z;
296 disable_npc_blur(npc);
297 suggest_player_anim_allow_backward(ANIM_MarioW1_Lift);
298 npc->yaw = playerStatus->targetYaw;
299 npc->curAnim = ANIM_WorldBombette_Walk;
300 script->USE_STATE = BLAST_STATE_LIFT;
301 script->functionTemp[1] = 10;
302 // fallthrough
303 case BLAST_STATE_LIFT:
304 if (playerStatus->actionState == ACTION_STATE_HIT_FIRE || playerStatus->actionState == ACTION_STATE_KNOCKBACK) {
305 script->USE_STATE = BLAST_STATE_CANCEL;
306 break;
307 }
308 npc->pos.y = playerStatus->pos.y + playerStatus->colliderHeight;
309 npc->yaw = playerStatus->targetYaw;
310 if (script->functionTemp[1] == 1) {
311 suggest_player_anim_allow_backward(ANIM_MarioW1_PlaceItem);
312 }
313 if (script->functionTemp[1] != 0) {
314 script->functionTemp[1]--;
315 break;
316 }
318 N(PlayingFuseSound) = TRUE;
319 add_vec2D_polar(&npc->pos.x, &npc->pos.z, 0.0f, npc->yaw);
320 npc->curAnim = ANIM_WorldBombette_WalkLit;
321 npc->jumpVel = 0.0f;
322 N(MovementBlocked) = FALSE;
323 npc->flags |= NPC_FLAG_GRAVITY;
324 npc->flags &= ~NPC_FLAG_IGNORE_PLAYER_COLLISION;
325 npc->moveSpeed = 1.0f;
326 script->USE_STATE = BLAST_STATE_DEPLOY;
327 script->functionTemp[1] = 50;
328 // fallthrough
329 case BLAST_STATE_DEPLOY:
330 if ((playerStatus->animFlags & PA_FLAG_INTERRUPT_USE_PARTNER) || (playerStatus->actionState == ACTION_STATE_HIT_FIRE || playerStatus->actionState == ACTION_STATE_KNOCKBACK)) {
331 script->USE_STATE = BLAST_STATE_CANCEL;
332 break;
333 }
334 if (script->functionTemp[1] < 45) {
335 if (!(npc->flags & NPC_FLAG_COLLDING_WITH_WORLD) && !N(MovementBlocked)) {
336 npc_move_heading(npc, npc->moveSpeed, npc->yaw);
338 } else {
339 N(MovementBlocked) = TRUE;
340 }
341 }
342
343 // start explosion immediately when touching lava or spikes
344 x = npc->pos.x;
345 y = npc->pos.y + 14.0f;
346 z = npc->pos.z;
347 hitDepth = 16.0f;
348 if (npc_raycast_down_around(COLLIDER_FLAG_IGNORE_PLAYER, &x, &y, &z, &hitDepth, npc->yaw, npc->collisionDiameter)) {
350 if (surfaceType == SURFACE_TYPE_SPIKES || surfaceType == SURFACE_TYPE_LAVA) {
351 if (playerStatus->actionState == ACTION_STATE_IDLE) {
352 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
353 }
354 npc->curAnim = ANIM_WorldBombette_AboutToExplode;
355 npc->flags &= ~NPC_FLAG_GRAVITY;
356 script->functionTemp[1] = 2;
357 script->USE_STATE = BLAST_STATE_EXPLODE;
358 if (N(LockingPlayerInput)) {
359 N(LockingPlayerInput) = FALSE;
361 }
362 break;
363 }
364 }
365
366 // play walking sounds
367 if (!(script->functionTemp[1] & 3)) {
368 if (gGameStatusPtr->frameCounter & 1) {
370 } else {
372 }
373 }
374
375 // unlock player movement after 40 frames
376 if (script->functionTemp[1] == 40) {
377 if (playerStatus->actionState == ACTION_STATE_IDLE) {
378 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
379 }
381 N(LockingPlayerInput) = FALSE;
382 }
383
386 if (N(LockingPlayerInput)) {
387 N(LockingPlayerInput) = FALSE;
389 }
390 } else if (!N(TriggeredEarlyDetonation)) {
391 if (script->functionTemp[1] != 0) {
392 script->functionTemp[1]--;
393 break;
394 }
395 }
396 npc->curAnim = ANIM_WorldBombette_AboutToExplode;
397 script->functionTemp[1] = 20;
398 script->USE_STATE = BLAST_STATE_EXPLODE;
399 if (playerStatus->actionState == ACTION_STATE_IDLE) {
400 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
401 }
402 }
403
404 switch (script->USE_STATE) {
405 case BLAST_STATE_EXPLODE:
406 if (script->functionTemp[1] != 0) {
407 script->functionTemp[1]--;
408 break;
409 }
410 if (N(PlayingFuseSound)) {
411 N(PlayingFuseSound) = FALSE;
413 }
414 fx_explosion(gPlayerData.partners[gPlayerData.curPartner].level, npc->pos.x, npc->pos.y + (npc->collisionHeight * 0.5f), npc->pos.z);
418 break;
421 break;
424 break;
425 }
426 exec_ShakeCam1(0, 0, 20);
428 collisionStatus->bombetteExploded = 0;
429 collisionStatus->bombetteExplosionPos.x = npc->pos.x;
430 collisionStatus->bombetteExplosionPos.y = npc->pos.y;
431 collisionStatus->bombetteExplosionPos.z = npc->pos.z;
432 N(blast_affect_entities)(npc);
433 N(IsBlasting) = TRUE;
435 script->functionTemp[1] = 3;
436 script->USE_STATE++;
437 break;
438 case BLAST_STATE_LIFTOFF:
439 if (script->functionTemp[1] != 0) {
440 script->functionTemp[1]--;
441 break;
442 }
444 N(IsBlasting) = FALSE;
445 npc->jumpVel = ((playerStatus->pos.y - npc->pos.y) / 20.0f) + 30.0;
446 npc->moveSpeed = 0.8f;
447 npc->yaw = rand_int(360);
448 npc->jumpScale = 0.8f;
449 npc->pos.y += 10.0f;
450 npc->moveToPos.y = npc->pos.y;
451 collisionStatus->bombetteExploded = -1;
452 collisionStatus->bombetteExplosionPos.x = npc->pos.x;
453 collisionStatus->bombetteExplosionPos.y = npc->pos.y;
454 collisionStatus->bombetteExplosionPos.z = npc->pos.z;
455 npc->curAnim = ANIM_WorldBombette_Aftermath;
456 angleToPlayer = atan2(npc->pos.x, npc->pos.z, playerStatus->pos.x, playerStatus->pos.z);
457 if (!(get_clamped_angle_diff(camera->curYaw, angleToPlayer) < 0.0f)) {
458 script->functionTemp[2] = 1;
459 } else {
460 script->functionTemp[2] = -1;
461 }
462 script->functionTemp[1] = 10;
463 script->USE_STATE = BLAST_STATE_FLY;
464 break;
465 case BLAST_STATE_FLY:
466 npc->pos.y += npc->jumpVel;
467 npc->jumpVel -= npc->jumpScale;
468 npc->rot.z -= (script->functionTemp[2] * 79) / 2;
469 npc->rot.x -= (script->functionTemp[2] * 67) / 2;
470 if (script->functionTemp[1] != 0) {
471 script->functionTemp[1]--;
472 break;
473 }
474 if (!N(MaintainPosAfterBlast)) {
475 npc->pos.x = playerStatus->pos.x;
476 npc->pos.z = playerStatus->pos.z;
477 }
478 npc->yaw = clamp_angle(gCameras[CAM_DEFAULT].curYaw + playerStatus->spriteFacingAngle);
479 add_vec2D_polar(&npc->pos.x, &npc->pos.z, 10.0f, npc->yaw);
480 npc->jumpVel = 0.0f;
481 npc->curAnim = ANIM_WorldBombette_Aftermath;
482 npc->flags |= NPC_FLAG_JUMPING;
483 script->USE_STATE = BLAST_STATE_FALL;
484 break;
485 case BLAST_STATE_FALL:
486 if (npc->pos.y + 10.0f < playerStatus->pos.y + playerStatus->colliderHeight) {
487 npc->flags &= ~NPC_FLAG_JUMPING;
488 if (fabsf(playerStatus->pos.y - npc->pos.y) < 500.0) {
489 script->USE_STATE = BLAST_STATE_FINISH;
490 break;
491 } else if (npc_try_snap_to_ground(npc, npc->jumpVel)) {
492 script->USE_STATE = BLAST_STATE_CANCEL;
493 break;
494 }
495 }
496 npc->pos.y += npc->jumpVel;
497 npc->jumpVel -= npc->jumpScale;
498 if (npc->jumpVel < -8.0) {
499 npc->jumpVel = -8.0f;
500 }
501 npc->rot.z -= (script->functionTemp[2] * 79) / 2;
502 npc->rot.x -= (script->functionTemp[2] * 67) / 2;
503 break;
504 }
505
506 //TODO clean up this return
507 temp_ret = ApiStatus_BLOCK;
508 switch (script->USE_STATE) {
509 case BLAST_STATE_CANCEL:
510 if (playerStatus->actionState == ACTION_STATE_IDLE) {
511 suggest_player_anim_allow_backward(ANIM_Mario1_Idle);
512 }
513 if (N(LockingPlayerInput)) {
514 N(LockingPlayerInput) = FALSE;
516 }
517 partnerStatus->partnerActionState = ACTION_STATE_IDLE;
518 partnerStatus->actingPartner = PARTNER_NONE;
519 npc->jumpVel = 0.0f;
520 N(IsBlasting) = FALSE;
521 N(TriggeredEarlyDetonation) = FALSE;
522 npc->pos.y = playerStatus->pos.y;
523 npc->rot.x = 0.0f;
524 npc->rot.z = 0.0f;
525 npc->curAnim = ANIM_WorldBombette_Idle;
527 if (N(PlayingFuseSound)) {
528 N(PlayingFuseSound) = FALSE;
530 }
531 temp_ret = ApiStatus_DONE2;
532 return temp_ret;
533 case BLAST_STATE_FINISH:
534 if (N(LockingPlayerInput)) {
535 N(LockingPlayerInput) = FALSE;
537 }
539 partnerStatus->actingPartner = PARTNER_NONE;
540 npc->jumpVel = 0.0f;
541 npc->pos.y = playerStatus->pos.y;
542 npc->rot.x = 0.0f;
543 npc->rot.z = 0.0f;
544 npc->curAnim = ANIM_WorldBombette_Idle;
545 npc->pos.x = playerStatus->pos.x;
546 npc->pos.y = playerStatus->pos.y;
547 npc->pos.z = playerStatus->pos.z;
548 N(IsBlasting) = FALSE;
549 N(TriggeredEarlyDetonation) = FALSE;
550 if (!N(PlayerWasFacingLeft)) {
551 add_vec2D_polar(&npc->pos.x, &npc->pos.z, playerStatus->colliderDiameter / 4, clamp_angle(playerStatus->targetYaw + 90.0f));
552 } else {
553 add_vec2D_polar(&npc->pos.x, &npc->pos.z, playerStatus->colliderDiameter / 4, clamp_angle(playerStatus->targetYaw - 90.0f));
554 }
555 npc->jumpVel = 0.0f;
557 temp_ret = ApiStatus_DONE2;
558 if (N(PlayingFuseSound)) {
559 N(PlayingFuseSound) = FALSE;
561 }
562 temp_ret = ApiStatus_DONE2;
563 break;
564 default:
565 return ApiStatus_BLOCK;
566 }
567
568 return temp_ret;
569}
570
572 Call(N(UseAbility))
573 Return
574 End
575};
576
577API_CALLABLE(N(PutAway)) {
578 Npc* bombette = script->owner2.npc;
579
580 if (isInitialCall) {
581 partner_init_put_away(bombette);
582 }
583
584 if (partner_put_away(bombette)) {
585 return ApiStatus_DONE1;
586 } else {
587 return ApiStatus_BLOCK;
588 }
589}
590
592 Call(N(PutAway))
593 Return
594 End
595};
596
597s32 N(test_first_strike)(Npc* bombette, Npc* enemy) {
598 f32 bombetteX, bombetteZ;
599 f32 enemyX, enemyZ;
600 f32 x, y, z, dist;
601 f32 angle, distance;
602 f32 enemyRadius, blastRadius;
603 b32 hasCollision;
604 s32 enemyHit;
605
606 if (!N(IsBlasting)) {
607 return FALSE;
608 }
609
610 enemyX = enemy->pos.x;
611 enemyZ = enemy->pos.z;
612
613 bombetteX = bombette->pos.x;
614 bombetteZ = bombette->pos.z;
615
616 x = enemyX - bombetteX;
617 y = enemy->pos.y + (f32)(enemy->collisionHeight * 0.5) - bombette->pos.y;
618 z = enemyZ - bombetteZ;
619
620 enemyRadius = enemy->collisionDiameter * 0.55;
621 blastRadius = 35.0f;
622 dist = sqrtf(SQ(x) + SQ(y) + SQ(z));
623 enemyHit = FALSE;
624
625 if (dist < (enemyRadius + blastRadius)) {
626 enemyHit = TRUE;
627 }
628
629 angle = atan2(enemyX, enemyZ, bombetteX, bombetteZ);
630 distance = dist2D(enemyX, enemyZ, bombetteX, bombetteZ);
631
632 // check whether the enemy is protected from the explosion
633 x = bombette->pos.x;
634 y = bombette->pos.y;
635 z = bombette->pos.z;
636 hasCollision = npc_test_move_taller_with_slipping(0, &x, &y, &z, distance, angle, 35.0f, 2.0f);
637
638 if (hasCollision) {
639 return FALSE;
640 }
641
642 return enemyHit;
643}
644
645void N(pre_battle)(Npc* bombette) {
646 PlayerStatus* playerStatus = &gPlayerStatus;
647 PartnerStatus* partnerStatus = &gPartnerStatus;
648
649 if (partnerStatus->partnerActionState != PARTNER_ACTION_NONE) {
650 if (N(LockingPlayerInput)) {
652 }
653
654 N(IsBlasting) = FALSE;
655 playerStatus->flags &= ~PS_FLAG_JUMPING;
656 bombette->jumpVel = 0.0f;
657 bombette->flags &= ~NPC_FLAG_JUMPING;
658
661
663 partnerStatus->actingPartner = 0;
664
665 bombette->pos.x = playerStatus->pos.x;
666 bombette->pos.y = playerStatus->pos.y;
667 bombette->pos.z = playerStatus->pos.z;
668
669 if (!N(PlayerWasFacingLeft)) {
670 add_vec2D_polar(&bombette->pos.x, &bombette->pos.z,
671 playerStatus->colliderDiameter / 4, clamp_angle(playerStatus->targetYaw + 90.0f));
672 } else {
673 add_vec2D_polar(&bombette->pos.x, &bombette->pos.z,
674 playerStatus->colliderDiameter / 4, clamp_angle(playerStatus->targetYaw - 90.0f));
675 }
676
677 bombette->jumpVel = 0.0f;
678 bombette->pos.y = playerStatus->pos.y;
679 bombette->rot.x = 0.0f;
680 bombette->rot.z = 0.0f;
681 bombette->curAnim = ANIM_WorldBombette_Idle;
683 disable_npc_blur(bombette);
684
685 if (N(PlayingFuseSound)) {
686 N(PlayingFuseSound) = FALSE;
688 }
689 }
690}
PartnerData partners[12]
s32 partnerUsedTime[12]
s32 b32
Bytecode EvtScript[]
#define sqrtf
#define rand_int
#define clamp_angle
#define atan2
#define mem_clear
@ TWEESTER_PARTNER_HOLD
Definition enums.h:2477
@ TWEESTER_PARTNER_ATTRACT
Definition enums.h:2476
@ TWEESTER_PARTNER_INIT
Definition enums.h:2475
@ TWEESTER_PARTNER_RELEASE
Definition enums.h:2478
@ SURFACE_TYPE_LAVA
Definition enums.h:4673
@ SURFACE_TYPE_SPIKES
Definition enums.h:4672
@ PS_FLAG_JUMPING
Definition enums.h:3035
@ PARTNER_ACTION_BOMBETTE_2
Definition enums.h:2937
@ PARTNER_ACTION_NONE
Definition enums.h:2932
@ PARTNER_ACTION_USE
Definition enums.h:2933
@ PARTNER_ACTION_BOMBETTE_3
Definition enums.h:2938
@ COLLIDER_FLAG_IGNORE_PLAYER
Definition enums.h:4696
@ COLLIDER_FLAGS_SURFACE_TYPE_MASK
Definition enums.h:4693
@ COLLISION_ONLY_ENTITIES
Definition enums.h:4700
@ COLLISION_IGNORE_ENTITIES
Definition enums.h:4698
@ NPC_PARTNER
Definition enums.h:2528
@ PA_FLAG_INTERRUPT_USE_PARTNER
forces actions with bow, parakarry, watt, and lakilester to end (sushie not tested)
Definition enums.h:3093
@ PARTNER_RANK_NORMAL
Definition enums.h:2018
@ PARTNER_RANK_SUPER
Definition enums.h:2019
@ PARTNER_RANK_ULTRA
Definition enums.h:2020
@ SOUND_STEP_NORMAL1
Definition enums.h:759
@ SOUND_BOMBETTE_BLAST_LV2
Definition enums.h:1332
@ SOUND_BOMBETTE_BLAST_LV3
Definition enums.h:1333
@ SOUND_LOOP_BOMBETTE_FUSE
Definition enums.h:1581
@ SOUND_BOMBETTE_BLAST_LV1
Definition enums.h:1331
@ SOUND_STEP_NORMAL2
Definition enums.h:760
@ PARTNER_NONE
Definition enums.h:2885
@ PARTNER_BOMBETTE
Definition enums.h:2888
@ ACTION_STATE_IDLE
Definition enums.h:2426
@ ACTION_STATE_KNOCKBACK
Definition enums.h:2450
@ ACTION_STATE_HIT_FIRE
Causes Mario to fly up and take damage. Used for fire bars.
Definition enums.h:2449
@ SURFACE_INTERACT_WALK
Definition enums.h:4684
@ SURFACE_INTERACT_LAND
Definition enums.h:4686
@ SOUND_SPACE_DEFAULT
Definition enums.h:1737
@ CAM_DEFAULT
Definition enums.h:1800
@ NPC_FLAG_FLYING
Definition enums.h:3001
@ NPC_FLAG_JUMPING
Definition enums.h:3009
@ NPC_FLAG_IGNORE_WORLD_COLLISION
Definition enums.h:3004
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
Definition enums.h:3006
@ NPC_FLAG_COLLIDING_WITH_NPC
Definition enums.h:3023
@ NPC_FLAG_DIRTY_SHADOW
Definition enums.h:3014
@ NPC_FLAG_GRAVITY
Definition enums.h:3007
@ NPC_FLAG_GROUNDED
Definition enums.h:3010
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
Definition enums.h:3016
@ NPC_FLAG_COLLDING_WITH_WORLD
Definition enums.h:3011
#define ApiStatus_DONE2
Definition evt.h:118
#define ApiStatus_DONE1
Definition evt.h:117
#define ApiStatus_BLOCK
Definition evt.h:116
f32 fabsf(f32 f)
b32 npc_raycast_down_around(s32, f32 *, f32 *, f32 *, f32 *, f32, f32)
void disable_npc_blur(Npc *npc)
Definition npc.c:1088
void partner_walking_update_motion(Npc *partner)
Definition partners.c:1202
void partner_clear_player_tracking(Npc *partner)
Definition partners.c:2436
s32 disable_player_input(void)
Definition 77480.c:990
s32 get_collider_flags(s32 colliderID)
Definition collision.c:481
void partner_walking_update_player_tracking(Npc *partner)
Definition partners.c:1175
void enable_npc_blur(Npc *npc)
Definition npc.c:1067
s32 enable_player_input(void)
Definition 77480.c:998
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
Definition 43F0.c:670
void set_action_state(s32 actionState)
Definition 7E9D0.c:209
b32 npc_test_move_taller_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
void exec_ShakeCam1(s32 arg0, s32 arg1, s32 arg2)
Definition cam_api.c:365
void suggest_player_anim_allow_backward(AnimID anim)
Definition 77480.c:894
void partner_walking_enable(Npc *partner, s32 val)
Definition partners.c:1133
f32 sin_rad(f32 x)
Definition 43F0.c:713
void sin_cos_rad(f32 rad, f32 *outSinTheta, f32 *outCosTheta)
Definition 43F0.c:706
void add_vec2D_polar(f32 *x, f32 *y, f32 r, f32 theta)
Definition 43F0.c:685
f32 get_clamped_angle_diff(f32, f32)
Definition 43F0.c:606
s32 npc_try_snap_to_ground(Npc *npc, f32 velocity)
Definition npc.c:581
void npc_surface_spawn_fx(Npc *npc, SurfaceInteractMode mode)
Definition surfaces.c:394
void npc_do_other_npc_collision(Npc *npc)
Definition npc.c:381
EncounterStatus gCurrentEncounter
Definition encounter.c:176
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
Definition npc.c:986
s32 partner_init_get_out(Npc *npc)
Definition partners.c:2252
s32 partner_init_put_away(Npc *partner)
Definition partners.c:2178
s32 partner_put_away(Npc *partner)
Definition partners.c:2185
s32 partner_force_player_flip_done(void)
Definition partners.c:2454
s32 partner_get_out(Npc *partner)
Definition partners.c:2259
void sfx_play_sound_at_npc(s32 soundID, s32 arg1, s32 npcID)
Definition sfx.c:527
void sfx_stop_sound(s32 soundID)
Definition sfx.c:507
#define End
Signals the end of EVT script data. A script missing this will likely crash on load.
Definition macros.h:213
#define COLLISION_WITH_ENTITY_BIT
Definition macros.h:152
#define BSS
Definition macros.h:7
#define DEG_TO_RAD(deg)
Definition macros.h:134
#define SQ(x)
Definition macros.h:166
#define Call(FUNC, ARGS...)
Calls a given C EVT API function with any number of arguments.
Definition macros.h:576
#define Return
Kills the current EVT thread.
Definition macros.h:217
s16 collisionDiameter
f32 jumpScale
f32 jumpVel
s32 flags
f32 renderYaw
AnimID curAnim
Vec3f moveToPos
s16 collisionHeight
Vec3f rot
Vec3f pos
f32 moveSpeed
s16 duration
Entity * TweesterTouchingPartner
Definition 7B440.c:5
CollisionStatus gCollisionStatus
Definition 7BB60.c:6
PartnerStatus gPartnerStatus
Definition partners.c:42
GameStatus * gGameStatusPtr
Definition main_loop.c:32
s32 NpcHitQueryColliderID
Camera gCameras[4]
Definition cam_main.c:17
PlayerData gPlayerData
Definition 77480.c:40
PlayerStatus gPlayerStatus
Definition 77480.c:39
void N try_cancel_tweester(Npc *npc)
Definition bombette.c:186
EvtScript EVS_WorldBombette_TakeOut
Definition bombette.c:87
void entity_try_partner_interaction_trigger(s32 arg0)
Definition entity.c:677
s32 N can_use_ability(Npc *npc)
Definition bombette.c:195
void N blast_affect_entities(Npc *npc)
Definition bombette.c:20
s32 N can_open_menus(Npc *npc)
Definition bombette.c:203
void N pre_battle(Npc *bombette)
Definition bombette.c:645
EvtScript EVS_WorldBombette_Update
Definition bombette.c:180
void N init(Npc *bombette)
Definition bombette.c:66
s32 N test_first_strike(Npc *bombette, Npc *enemy)
Definition bombette.c:597
EvtScript EVS_WorldBombette_PutAway
Definition bombette.c:591
EvtScript EVS_WorldBombette_UseAbility
Definition bombette.c:571