2#include "../src/world/partners.h"
3#include "sprite/npc/WorldKooper.h"
4#include "sprite/player.h"
7#define NAMESPACE world_kooper
14BSS s32 N(ShellTossHoldTime);
15BSS s32 N(TriggeredBattle);
16BSS s32 N(PlayerWasFacingLeft);
18BSS s32 N(ShellTossKickFalling);
19BSS b32 N(LockingPlayerInput);
20BSS s32 N(HeldItemIdx);
22BSS f32 N(ShellTossPosX);
23BSS f32 N(ShellTossPosY);
24BSS f32 N(ShellTossPosZ);
62 if (N(HeldItemIdx) < 0) {
73 kooper->collisionHeight = 37;
74 kooper->collisionDiameter = 24;
76 N(TriggeredBattle) = FALSE;
79API_CALLABLE(N(TakeOut)) {
80 Npc* kooper = script->owner2.npc;
102API_CALLABLE(N(Update)) {
104 Npc* kooper = script->owner2.npc;
105 f32 sinAngle, cosAngle, liftoffVelocity;
117 if (entity == NULL) {
123 switch (N(TweesterPhysicsPtr)->state) {
125 N(TweesterPhysicsPtr)->state++;
126 N(TweesterPhysicsPtr)->prevFlags = kooper->
flags;
130 N(TweesterPhysicsPtr)->angularVel = 6.0f;
131 N(TweesterPhysicsPtr)->liftoffVelPhase = 50.0f;
132 N(TweesterPhysicsPtr)->countdown = 120;
134 kooper->
flags &= ~NPC_FLAG_GRAVITY;
138 kooper->
pos.
x = entity->
pos.
x + (sinAngle * N(TweesterPhysicsPtr)->radius);
139 kooper->
pos.
z = entity->
pos.
z - (cosAngle * N(TweesterPhysicsPtr)->radius);
141 N(TweesterPhysicsPtr)->angle =
clamp_angle(N(TweesterPhysicsPtr)->angle - N(TweesterPhysicsPtr)->angularVel);
142 if (N(TweesterPhysicsPtr)->radius > 20.0f) {
143 N(TweesterPhysicsPtr)->radius--;
144 }
else if (N(TweesterPhysicsPtr)->radius < 19.0f) {
145 N(TweesterPhysicsPtr)->radius++;
148 liftoffVelocity =
sin_rad(
DEG_TO_RAD(N(TweesterPhysicsPtr)->liftoffVelPhase)) * 3.0f;
150 N(TweesterPhysicsPtr)->liftoffVelPhase += 3.0f;
152 if (N(TweesterPhysicsPtr)->liftoffVelPhase > 150.0f) {
153 N(TweesterPhysicsPtr)->liftoffVelPhase = 150.0f;
155 kooper->
pos.
y += liftoffVelocity;
158 N(TweesterPhysicsPtr)->angularVel += 0.8;
159 if (N(TweesterPhysicsPtr)->angularVel > 40.0f) {
160 N(TweesterPhysicsPtr)->angularVel = 40.0f;
163 if (--N(TweesterPhysicsPtr)->countdown == 0) {
164 N(TweesterPhysicsPtr)->state++;
168 kooper->
flags = N(TweesterPhysicsPtr)->prevFlags;
169 N(TweesterPhysicsPtr)->countdown = 30;
170 N(TweesterPhysicsPtr)->state++;
176 if (--N(TweesterPhysicsPtr)->countdown == 0) {
188 kooper->
flags = N(TweesterPhysicsPtr)->prevFlags;
200API_CALLABLE(N(UseAbility)) {
205 Npc* kooper = script->owner2.npc;
208 f32 posX, posY, posZ, hitLength;
215 #define USE_STATE functionTemp[0]
217 SHELL_TOSS_STATE_BEGIN = 20,
218 SHELL_TOSS_STATE_GATHER = 21,
219 SHELL_TOSS_STATE_JUMP = 2,
220 SHELL_TOSS_STATE_KICK = 3,
221 SHELL_TOSS_STATE_PICKUP = 4,
222 SHELL_TOSS_STATE_HOLD = 5,
223 SHELL_TOSS_STATE_RETURN = 7,
224 SHELL_TOSS_STATE_FINISH = 0,
227 if (currentEncounter->
unk_08 != 0) {
237 if (!N(TriggeredBattle)) {
243 script->USE_STATE = SHELL_TOSS_STATE_BEGIN;
250 script->USE_STATE = SHELL_TOSS_STATE_HOLD;
251 kooper->
curAnim = ANIM_WorldKooper_SpinShell;
252 N(ShellTossHoldTime) = 30;
256 switch (script->USE_STATE) {
257 case SHELL_TOSS_STATE_BEGIN:
267 N(LockingPlayerInput) = TRUE;
278 playerStatus->
pos.
x, playerStatus->
pos.
z);
282 case SHELL_TOSS_STATE_GATHER:
289 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
297 kooper->
curAnim = ANIM_WorldKooper_Run;
319 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
326 kooper->
curAnim = ANIM_WorldKooper_EnterShell;
342 N(ShellTossKickFalling) = FALSE;
344 script->USE_STATE = SHELL_TOSS_STATE_JUMP;
347 case SHELL_TOSS_STATE_JUMP:
352 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
359 if (!N(ShellTossKickFalling)) {
360 N(ShellTossKickFalling) = TRUE;
365 posX = playerStatus->
pos.
x;
367 posZ = playerStatus->
pos.
z;
378 kooper->
flags &= ~NPC_FLAG_IGNORE_PLAYER_COLLISION;
381 kooper->
rot.
z = 0.0f;
384 kooper->
curAnim = ANIM_WorldKooper_SpinShell;
390 if (N(LockingPlayerInput)) {
392 N(LockingPlayerInput) = FALSE;
395 script->USE_STATE = SHELL_TOSS_STATE_KICK;
396 N(ShellTossKickFalling) = FALSE;
403 case SHELL_TOSS_STATE_KICK:
407 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
412 #define TEST_COLLISION_AT_ANGLE(testAngle) \
414 posX = kooper->pos.x, \
415 posY = kooper->pos.y, \
416 posZ = kooper->pos.z, \
417 npc_test_move_taller_with_slipping(COLLIDER_FLAG_IGNORE_SHELL, \
418 &posX, &posY, &posZ, kooper->moveSpeed, testAngle, \
419 kooper->collisionHeight, kooper->collisionDiameter / 2) \
430 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
442 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
454 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
458 kooper->
pos.
x = posX;
459 kooper->
pos.
y = posY;
460 kooper->
pos.
z = posZ;
470 kooper->
pos.
y += (playerStatus->
pos.
y - kooper->
pos.
y) / 10.0f;
476 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
487 script->USE_STATE = SHELL_TOSS_STATE_PICKUP;
488 N(ShellTossHoldTime) = 8;
496 script->USE_STATE = SHELL_TOSS_STATE_HOLD;
497 N(ShellTossHoldTime) = 30;
502 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
515 case SHELL_TOSS_STATE_PICKUP:
516 posX = kooper->
pos.
x;
517 posY = kooper->
pos.
y;
518 posZ = kooper->
pos.
z;
524 kooper->
pos.
x = posX;
525 kooper->
pos.
y = posY;
526 kooper->
pos.
z = posZ;
537 if (N(ShellTossHoldTime) == 0) {
538 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
540 N(ShellTossHoldTime)--;
543 case SHELL_TOSS_STATE_HOLD:
544 if (N(ShellTossHoldTime) != 0) {
545 N(ShellTossHoldTime)--;
547 script->USE_STATE = SHELL_TOSS_STATE_RETURN;
552 if (script->USE_STATE == SHELL_TOSS_STATE_RETURN) {
557 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
559 angleToStartPos =
atan2(N(ShellTossPosX), N(ShellTossPosZ), kooper->
pos.
x, kooper->
pos.
z);
571 kooper->
pos.
y += (playerStatus->
pos.
y - kooper->
pos.
y) / 10.0f;
574 posX = kooper->
pos.
x;
575 posY = kooper->
pos.
y;
576 posZ = kooper->
pos.
z;
582 kooper->
pos.
x = posX;
583 kooper->
pos.
y = posY;
584 kooper->
pos.
z = posZ;
588 testLength, -1.0f, -
cos_deg(kooper->
yaw + 180.0f), 1);
589 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
593 posX = kooper->
pos.
x;
594 posY = kooper->
pos.
y + 8.0f;
595 posZ = kooper->
pos.
z;
600 heldItem->
pos.
x = posX;
601 heldItem->
pos.
y = posY;
602 heldItem->
pos.
z = posZ;
606 script->USE_STATE = SHELL_TOSS_STATE_FINISH;
617 if (script->USE_STATE == SHELL_TOSS_STATE_FINISH) {
618 if (N(LockingPlayerInput)) {
620 N(LockingPlayerInput) = FALSE;
630 kooper->
curAnim = ANIM_WorldKooper_Walk;
639 N(TriggeredBattle) = FALSE;
653API_CALLABLE(N(PutAway)) {
654 Npc* kooper = script->owner2.npc;
670 f32 xTemp, yTemp, zTemp;
671 f32 enemyX, enemyY, enemyZ;
676 f32 kooperCollHeight;
678 f32 kooperCollRadius;
683 enemyX = enemy->pos.x;
684 enemyY = enemy->pos.y;
685 enemyZ = enemy->pos.z;
687 kooperX = kooper->
pos.
x;
688 kooperY = kooper->
pos.
y;
689 kooperZ = kooper->
pos.
z;
691 enemyCollHeight = enemy->collisionHeight;
692 enemyCollRadius = enemy->collisionDiameter * 0.55;
697 angleToEnemy =
atan2(enemyX, enemyZ, kooperX, kooperZ);
698 distToEnemy =
dist2D(enemyX, enemyZ, kooperX, kooperZ);
700 xTemp = kooper->
pos.
x;
701 yTemp = kooper->
pos.
y;
702 zTemp = kooper->
pos.
z;
705 kooperCollHeight, kooperCollRadius + enemyCollRadius)
710 if (kooperY > enemyY + enemyCollHeight) {
714 if (enemyY > kooperY + kooperCollHeight) {
718 kooperX = enemyX - kooperX;
719 kooperZ = enemyZ - kooperZ;
720 distToEnemy =
SQ(kooperX) +
SQ(kooperZ);
722 if (!(
SQ(kooperCollRadius) +
SQ(enemyCollRadius) <= distToEnemy)) {
733 N(TriggeredBattle) = FALSE;
737 N(TriggeredBattle) = TRUE;
740 if (N(LockingPlayerInput)) {
742 N(LockingPlayerInput) = FALSE;
746 playerStatus->
flags &= ~PS_FLAG_JUMPING;
749 kooper->
flags &= ~NPC_FLAG_JUMPING;
750 kooper->
flags &= ~NPC_FLAG_IGNORE_WORLD_COLLISION;
763 if (N(TriggeredBattle)) {
s32 partner_use_ability(void)
@ TWEESTER_PARTNER_ATTRACT
@ TWEESTER_PARTNER_RELEASE
@ ITEM_ENTITY_FLAG_CANT_COLLECT
@ PARTNER_ACTION_KOOPER_GATHER
@ PARTNER_ACTION_KOOPER_TOSS
@ COLLIDER_FLAG_IGNORE_PLAYER
@ COLLIDER_FLAG_IGNORE_SHELL
@ SOUND_KOOPER_SHELL_SWIRL
@ SOUND_KOOPER_SHELL_KICK
@ SOUND_QUICK_PLAYER_JUMP
@ ACTION_STATE_HIT_FIRE
Causes Mario to fly up and take damage. Used for fire bars.
@ CAMERA_MOVE_IGNORE_PLAYER_Y
@ NPC_FLAG_IGNORE_WORLD_COLLISION
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
@ NPC_FLAG_COLLIDING_WITH_NPC
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
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)
ItemEntity * get_item_entity(s32 itemEntityIndex)
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 start_bounce_b(void)
void set_action_state(s32 actionState)
b32 npc_test_move_taller_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
b32 npc_raycast_up(s32, f32 *, f32 *, f32 *, f32 *)
void suggest_player_anim_allow_backward(AnimID anim)
void partner_walking_enable(Npc *partner, s32 val)
void set_item_entity_flags(s32 itemEntityIndex, s32 flag)
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)
ApiStatus HasItem(Evt *script, b32 isInitialCall)
#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
s32 NpcHitQueryColliderID
PlayerStatus gPlayerStatus
EvtScript EVS_WorldKooper_TakeOut
s32 N check_for_item_collision(Npc *kooper)
void N pre_battle(Npc *kooper)
void fx_damage_stars(s32, f32, f32, f32, f32, f32, f32, s32)
s32 N test_first_strike(Npc *kooper, Npc *enemy)
#define TEST_COLLISION_AT_ANGLE(testAngle)
void auto_collect_item_entity(s32)
EvtScript EVS_WorldKooper_UseAbility
@ SHELL_TOSS_HITBOX_HIT_ENEMY
@ SHELL_TOSS_HITBOX_ENABLED
@ SHELL_TOSS_HITBOX_DISABLED
s32 entity_try_partner_interaction_trigger(s32)
s32 test_item_entity_position(f32, f32, f32, f32)
void N vertical_hit_interactable_entity(Npc *kooper)
void N try_cancel_tweester(Npc *kooper)
void N post_battle(Npc *npc)
EvtScript EVS_WorldKooper_Update
s32 N lateral_hit_interactable_entity(Npc *npc)
EvtScript EVS_WorldKooper_PutAway