4#include "sprite/npc/WorldBombette.h"
5#include "sprite/player.h"
7#define NAMESPACE world_bombette
9BSS b32 N(PlayerWasFacingLeft);
10BSS b32 N(PlayingFuseSound);
12BSS b32 N(LockingPlayerInput);
13BSS b32 N(MaintainPosAfterBlast);
14BSS b32 N(TriggeredEarlyDetonation);
25 while (angle < 360.0f) {
31 npc->collisionHeight, npc->collisionDiameter)
39 if (angle >= 360.0f) {
42 while (angle < 360.0f) {
48 npc->collisionHeight, npc->collisionDiameter)
55 if (angle >= 360.0f) {
67 bombette->collisionHeight = 28;
68 bombette->collisionDiameter = 24;
69 N(IsBlasting) = FALSE;
70 N(PlayingFuseSound) = FALSE;
73API_CALLABLE(N(TakeOut)) {
74 Npc* bombette = script->owner2.npc;
96API_CALLABLE(N(Update)) {
98 Npc* bombette = script->owner2.npc;
99 f32 sinAngle, cosAngle, liftoffVelocity;
112 if (entity == NULL) {
118 switch (N(TweesterPhysicsPtr)->state) {
120 N(TweesterPhysicsPtr)->state++;
121 N(TweesterPhysicsPtr)->prevFlags = bombette->
flags;
124 N(TweesterPhysicsPtr)->angle =
atan2(entity->
pos.
x, entity->
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;
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);
137 if (N(TweesterPhysicsPtr)->radius > 20.0f) {
138 N(TweesterPhysicsPtr)->radius--;
139 }
else if (N(TweesterPhysicsPtr)->radius < 19.0f) {
140 N(TweesterPhysicsPtr)->radius++;
143 liftoffVelocity =
sin_rad(
DEG_TO_RAD(N(TweesterPhysicsPtr)->liftoffVelPhase)) * 3.0f;
144 N(TweesterPhysicsPtr)->liftoffVelPhase += 3.0f;
146 if (N(TweesterPhysicsPtr)->liftoffVelPhase > 150.0f) {
147 N(TweesterPhysicsPtr)->liftoffVelPhase = 150.0f;
150 bombette->
pos.
y += liftoffVelocity;
152 N(TweesterPhysicsPtr)->angularVel += 0.8;
154 if (N(TweesterPhysicsPtr)->angularVel > 40.0f) {
155 N(TweesterPhysicsPtr)->angularVel = 40.0f;
158 if (--N(TweesterPhysicsPtr)->countdown == 0) {
159 N(TweesterPhysicsPtr)->state++;
163 bombette->
flags = N(TweesterPhysicsPtr)->prevFlags;
164 N(TweesterPhysicsPtr)->countdown = 30;
165 N(TweesterPhysicsPtr)->state++;
171 if (--N(TweesterPhysicsPtr)->countdown == 0) {
189 npc->
flags = N(TweesterPhysicsPtr)->prevFlags;
197 N(TriggeredEarlyDetonation) = TRUE;
207API_CALLABLE(N(UseAbility)) {
212 Npc* npc = script->owner2.npc;
219 #define USE_STATE functionTemp[0]
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,
228 BLAST_STATE_FALL = 6,
229 BLAST_STATE_CANCEL = 7,
230 BLAST_STATE_FINISH = 8,
239 script->USE_STATE = BLAST_STATE_BEGIN;
242 switch (script->USE_STATE) {
243 case BLAST_STATE_BEGIN:
249 N(LockingPlayerInput) = TRUE;
250 N(IsBlasting) = FALSE;
251 N(MaintainPosAfterBlast) = FALSE;
252 N(TriggeredEarlyDetonation) = FALSE;
261 script->USE_STATE = BLAST_STATE_GATHER;
262 case BLAST_STATE_GATHER:
265 script->USE_STATE = BLAST_STATE_CANCEL;
269 script->USE_STATE = BLAST_STATE_CANCEL;
275 npc->
curAnim = ANIM_WorldBombette_Run;
290 script->functionTemp[(u8)temp_f0] = BLAST_STATE_CANCEL;
299 npc->
curAnim = ANIM_WorldBombette_Walk;
300 script->USE_STATE = BLAST_STATE_LIFT;
301 script->functionTemp[1] = 10;
303 case BLAST_STATE_LIFT:
305 script->USE_STATE = BLAST_STATE_CANCEL;
310 if (script->functionTemp[1] == 1) {
313 if (script->functionTemp[1] != 0) {
314 script->functionTemp[1]--;
318 N(PlayingFuseSound) = TRUE;
320 npc->
curAnim = ANIM_WorldBombette_WalkLit;
322 N(MovementBlocked) = FALSE;
324 npc->
flags &= ~NPC_FLAG_IGNORE_PLAYER_COLLISION;
326 script->USE_STATE = BLAST_STATE_DEPLOY;
327 script->functionTemp[1] = 50;
329 case BLAST_STATE_DEPLOY:
331 script->USE_STATE = BLAST_STATE_CANCEL;
334 if (script->functionTemp[1] < 45) {
339 N(MovementBlocked) = TRUE;
345 y = npc->
pos.
y + 14.0f;
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;
367 if (!(script->functionTemp[1] & 3)) {
376 if (script->functionTemp[1] == 40) {
381 N(LockingPlayerInput) = FALSE;
386 if (N(LockingPlayerInput)) {
387 N(LockingPlayerInput) = FALSE;
390 }
else if (!N(TriggeredEarlyDetonation)) {
391 if (script->functionTemp[1] != 0) {
392 script->functionTemp[1]--;
396 npc->
curAnim = ANIM_WorldBombette_AboutToExplode;
397 script->functionTemp[1] = 20;
398 script->USE_STATE = BLAST_STATE_EXPLODE;
404 switch (script->USE_STATE) {
405 case BLAST_STATE_EXPLODE:
406 if (script->functionTemp[1] != 0) {
407 script->functionTemp[1]--;
410 if (N(PlayingFuseSound)) {
411 N(PlayingFuseSound) = FALSE;
433 N(IsBlasting) = TRUE;
435 script->functionTemp[1] = 3;
438 case BLAST_STATE_LIFTOFF:
439 if (script->functionTemp[1] != 0) {
440 script->functionTemp[1]--;
444 N(IsBlasting) = FALSE;
455 npc->
curAnim = ANIM_WorldBombette_Aftermath;
458 script->functionTemp[2] = 1;
460 script->functionTemp[2] = -1;
462 script->functionTemp[1] = 10;
463 script->USE_STATE = BLAST_STATE_FLY;
465 case BLAST_STATE_FLY:
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]--;
474 if (!N(MaintainPosAfterBlast)) {
481 npc->
curAnim = ANIM_WorldBombette_Aftermath;
483 script->USE_STATE = BLAST_STATE_FALL;
485 case BLAST_STATE_FALL:
487 npc->
flags &= ~NPC_FLAG_JUMPING;
489 script->USE_STATE = BLAST_STATE_FINISH;
492 script->USE_STATE = BLAST_STATE_CANCEL;
501 npc->
rot.
z -= (script->functionTemp[2] * 79) / 2;
502 npc->
rot.
x -= (script->functionTemp[2] * 67) / 2;
508 switch (script->USE_STATE) {
509 case BLAST_STATE_CANCEL:
513 if (N(LockingPlayerInput)) {
514 N(LockingPlayerInput) = FALSE;
520 N(IsBlasting) = FALSE;
521 N(TriggeredEarlyDetonation) = FALSE;
525 npc->
curAnim = ANIM_WorldBombette_Idle;
527 if (N(PlayingFuseSound)) {
528 N(PlayingFuseSound) = FALSE;
533 case BLAST_STATE_FINISH:
534 if (N(LockingPlayerInput)) {
535 N(LockingPlayerInput) = FALSE;
544 npc->
curAnim = ANIM_WorldBombette_Idle;
548 N(IsBlasting) = FALSE;
549 N(TriggeredEarlyDetonation) = FALSE;
550 if (!N(PlayerWasFacingLeft)) {
558 if (N(PlayingFuseSound)) {
559 N(PlayingFuseSound) = FALSE;
577API_CALLABLE(N(PutAway)) {
578 Npc* bombette = script->owner2.npc;
598 f32 bombetteX, bombetteZ;
602 f32 enemyRadius, blastRadius;
606 if (!N(IsBlasting)) {
610 enemyX = enemy->pos.x;
611 enemyZ = enemy->pos.z;
613 bombetteX = bombette->pos.x;
614 bombetteZ = bombette->pos.z;
616 x = enemyX - bombetteX;
617 y = enemy->pos.y + (f32)(enemy->collisionHeight * 0.5) - bombette->pos.y;
618 z = enemyZ - bombetteZ;
620 enemyRadius = enemy->collisionDiameter * 0.55;
625 if (dist < (enemyRadius + blastRadius)) {
629 angle =
atan2(enemyX, enemyZ, bombetteX, bombetteZ);
630 distance =
dist2D(enemyX, enemyZ, bombetteX, bombetteZ);
650 if (N(LockingPlayerInput)) {
654 N(IsBlasting) = FALSE;
655 playerStatus->
flags &= ~PS_FLAG_JUMPING;
656 bombette->jumpVel = 0.0f;
657 bombette->flags &= ~NPC_FLAG_JUMPING;
665 bombette->pos.x = playerStatus->
pos.
x;
666 bombette->pos.y = playerStatus->
pos.
y;
667 bombette->pos.z = playerStatus->
pos.
z;
669 if (!N(PlayerWasFacingLeft)) {
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;
685 if (N(PlayingFuseSound)) {
686 N(PlayingFuseSound) = FALSE;
Vec3f bombetteExplosionPos
@ TWEESTER_PARTNER_ATTRACT
@ TWEESTER_PARTNER_RELEASE
@ PARTNER_ACTION_BOMBETTE_2
@ PARTNER_ACTION_BOMBETTE_3
@ COLLIDER_FLAG_IGNORE_PLAYER
@ COLLIDER_FLAGS_SURFACE_TYPE_MASK
@ COLLISION_ONLY_ENTITIES
@ COLLISION_IGNORE_ENTITIES
@ PA_FLAG_INTERRUPT_USE_PARTNER
forces actions with bow, parakarry, watt, and lakilester to end (sushie not tested)
@ SOUND_BOMBETTE_BLAST_LV2
@ SOUND_BOMBETTE_BLAST_LV3
@ SOUND_LOOP_BOMBETTE_FUSE
@ SOUND_BOMBETTE_BLAST_LV1
@ ACTION_STATE_HIT_FIRE
Causes Mario to fly up and take damage. Used for fire bars.
@ NPC_FLAG_IGNORE_WORLD_COLLISION
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
@ NPC_FLAG_COLLIDING_WITH_NPC
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
@ NPC_FLAG_COLLDING_WITH_WORLD
b32 npc_raycast_down_around(s32, f32 *, f32 *, f32 *, f32 *, f32, f32)
void disable_npc_blur(Npc *npc)
void partner_walking_update_motion(Npc *partner)
void partner_clear_player_tracking(Npc *partner)
s32 disable_player_input(void)
s32 get_collider_flags(s32 colliderID)
void partner_walking_update_player_tracking(Npc *partner)
void enable_npc_blur(Npc *npc)
s32 enable_player_input(void)
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
void set_action_state(s32 actionState)
b32 npc_test_move_taller_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
void exec_ShakeCam1(s32 arg0, s32 arg1, s32 arg2)
void suggest_player_anim_allow_backward(AnimID anim)
void partner_walking_enable(Npc *partner, s32 val)
void sin_cos_rad(f32 rad, f32 *outSinTheta, f32 *outCosTheta)
void add_vec2D_polar(f32 *x, f32 *y, f32 r, f32 theta)
f32 get_clamped_angle_diff(f32, f32)
s32 npc_try_snap_to_ground(Npc *npc, f32 velocity)
void npc_surface_spawn_fx(Npc *npc, SurfaceInteractMode mode)
void npc_do_other_npc_collision(Npc *npc)
EncounterStatus gCurrentEncounter
void npc_move_heading(Npc *npc, f32 speed, f32 yaw)
s32 partner_init_get_out(Npc *npc)
s32 partner_init_put_away(Npc *partner)
s32 partner_put_away(Npc *partner)
s32 partner_force_player_flip_done(void)
s32 partner_get_out(Npc *partner)
void sfx_play_sound_at_npc(s32 soundID, s32 arg1, s32 npcID)
void sfx_stop_sound(s32 soundID)
#define End
Signals the end of EVT script data. A script missing this will likely crash on load.
#define COLLISION_WITH_ENTITY_BIT
#define Call(FUNC, ARGS...)
Calls a given C EVT API function with any number of arguments.
#define Return
Kills the current EVT thread.
Entity * TweesterTouchingPartner
CollisionStatus gCollisionStatus
PartnerStatus gPartnerStatus
GameStatus * gGameStatusPtr
s32 NpcHitQueryColliderID
PlayerStatus gPlayerStatus
void N try_cancel_tweester(Npc *npc)
EvtScript EVS_WorldBombette_TakeOut
void entity_try_partner_interaction_trigger(s32 arg0)
s32 N can_use_ability(Npc *npc)
void N blast_affect_entities(Npc *npc)
s32 N can_open_menus(Npc *npc)
void N pre_battle(Npc *bombette)
EvtScript EVS_WorldBombette_Update
void N init(Npc *bombette)
s32 N test_first_strike(Npc *bombette, Npc *enemy)
EvtScript EVS_WorldBombette_PutAway
EvtScript EVS_WorldBombette_UseAbility