5#include "sprite/npc/WorldSushie.h"
7#include "sprite/player.h"
9#define NAMESPACE world_sushie
11BSS f32 N(WaterSurfaceY);
15BSS s32 N(TouchDockTime);
17BSS f32 N(InertialMoveSpeed);
18BSS f32 N(InertialMoveAngle);
19BSS f32 N(UnusedMoveX);
20BSS f32 N(UnusedMoveZ);
21BSS f32 N(ResurfaceVelY);
22BSS s32 N(bss_802BFF0C);
32f32 N(InputStickX) = 0.0f;
33f32 N(InputStickY) = 0.0f;
34f32 N(InertialStickX) = 0.0f;
35f32 N(InertialStickY) = 0.0f;
45 playerStatus->
pos.
x = partnerNPC->
pos.
x;
46 playerStatus->
pos.
y = partnerNPC->
pos.
y + 16.0f;
47 playerStatus->
pos.
z = partnerNPC->
pos.
z;
66 N(InputStickX) = stickX;
67 N(InputStickY) = stickY;
71 if (
dist2D(0.0f, 0.0f, N(InputStickX), -N(InputStickY)) >= 1.0) {
72 if (
SQ(N(InputStickX)) +
SQ(N(InputStickY)) >
SQ(55)) {
83 *outAngle = moveAngle;
84 *outSpeed = moveSpeed;
98 N(WaterSurfaceY) = posY;
106 f32 moveSpeedDamping;
107 f32 moveAngle, moveSpeed;
108 f32 sinAngle, cosAngle;
118 moveSpeedDamping = 80.0f;
120 moveSpeedDamping = 32.0f;
123 if (moveSpeed != 0.0f) {
124 f32 changeDirDamping = 8.0f;
125 f32 sameDirDamping = 32.0f;
127 if (N(InputStickX) * N(InertialStickX) > 0.0f) {
128 N(InertialStickX) += N(InputStickX) / sameDirDamping;
130 N(InertialStickX) += N(InputStickX) / changeDirDamping;
132 if (N(InputStickX) > 0.0f) {
133 if (N(InputStickX) < N(InertialStickX)) {
134 N(InertialStickX) = N(InputStickX);
137 if (N(InertialStickX) < N(InputStickX)) {
138 N(InertialStickX) = N(InputStickX);
142 if (N(InputStickY) * N(InertialStickY) > 0.0f) {
143 N(InertialStickY) += N(InputStickY) / sameDirDamping;
145 N(InertialStickY) += N(InputStickY) / changeDirDamping;
147 if (N(InputStickY) > 0.0f) {
148 if (N(InputStickY) < N(InertialStickY)) {
149 N(InertialStickY) = N(InputStickY);
152 if (N(InertialStickY) < N(InputStickY)) {
153 N(InertialStickY) = N(InputStickY);
158 if (N(InertialMoveSpeed) <= moveSpeed) {
159 N(InertialMoveSpeed) += (moveSpeed - N(InertialMoveSpeed)) / moveSpeedDamping;
160 if (N(InertialMoveSpeed) > moveSpeed) {
161 N(InertialMoveSpeed) = moveSpeed;
164 N(InertialMoveSpeed) += (moveSpeed - N(InertialMoveSpeed)) / moveSpeedDamping;
166 moveSpeed = N(InertialMoveSpeed);
167 N(InertialMoveAngle) = moveAngle;
169 N(UnusedMoveX) += ( moveSpeed * sinAngle) / moveSpeedDamping;
170 N(UnusedMoveZ) += (-moveSpeed * cosAngle) / moveSpeedDamping;
172 N(InertialMoveSpeed) -= 0.15;
173 if (N(InertialMoveSpeed) < 0.0f) {
174 N(InertialMoveSpeed) = 0.0f;
175 N(InertialStickY) = 0.0f;
176 N(InertialStickX) = 0.0f;
178 moveSpeed = N(InertialMoveSpeed);
179 moveAngle = N(InertialMoveAngle);
181 N(UnusedMoveX) = moveSpeed * sinAngle;
182 N(UnusedMoveZ) = -moveSpeed * cosAngle;
188 sushie->moveSpeed = moveSpeed;
189 if (moveSpeed != 0.0f) {
190 sushie->yaw = moveAngle;
193 y = sushie->moveToPos.y + -6.0f;
194 depth = (sushie->collisionHeight * 0.5f) + (playerStatus->
colliderHeight * 0.8f);
196 sushie->moveSpeed, moveAngle, depth, sushie->collisionDiameter))
202 N(TouchDockTime) = 0;
204 sushie->pos.x += (x - sushie->pos.x) * 0.5f;
205 sushie->pos.z += (z - sushie->pos.z) * 0.5f;
214 y = sushie->moveToPos.y + -6.0f;
215 depth = (sushie->collisionHeight * 0.5f) + (playerStatus->
colliderHeight * 0.8f);
217 moveSpeed, moveAngle, depth, sushie->collisionDiameter))
219 sushie->pos.x += (x - sushie->pos.x) / 5.0f;
220 sushie->pos.z += (z - sushie->pos.z) / 5.0f;
225 y = sushie->moveToPos.y + -6.0f;
226 depth = (sushie->collisionHeight * 0.5f) + (playerStatus->
colliderHeight * 0.8f);
228 moveSpeed, moveAngle, depth, sushie->collisionDiameter))
230 sushie->pos.x += (x - sushie->pos.x) / 5.0f;
231 sushie->pos.z += (z - sushie->pos.z) / 5.0f;
240 sushie->yaw, sushie->collisionDiameter * 0.5f);
242 sushie->moveSpeed = 3.0f;
243 sushie->moveToPos.y = N(WaterSurfaceY) - (sushie->collisionHeight * 0.5f);
247 sushie->moveSpeed = 2.0f;
263 depth = sushie->collisionHeight;
264 if (
npc_raycast_down_around(sushie->collisionChannel, &x, &y, &z, &depth, sushie->yaw, sushie->collisionDiameter)) {
265 moveSpeedDamping = ((N(WaterSurfaceY) - (playerStatus->
colliderHeight * 2)) - sushie->moveToPos.y) * 0.1f;
266 sushie->moveToPos.y += moveSpeedDamping;
267 if (sushie->moveToPos.y < y + 5.0f) {
268 sushie->moveToPos.y = y + 5.0f;
271 moveSpeedDamping = ((N(WaterSurfaceY) - (playerStatus->
colliderHeight * 2)) - sushie->moveToPos.y) * 0.1f;
272 sushie->moveToPos.y += moveSpeedDamping;
274 if (N(DiveTime) % 6 == 0) {
275 fx_rising_bubble(0, sushie->pos.x, sushie->moveToPos.y + (sushie->collisionHeight * 0.5f), sushie->pos.z,
276 (N(WaterSurfaceY) - sushie->moveToPos.y) - (sushie->collisionHeight * 0.5f));
278 if (N(DiveTime) == 1) {
280 sushie->curAnim = ANIM_WorldSushie_Ride;
282 if (!N(IsUnderwater) && (playerStatus->
pos.
y + (playerStatus->
colliderHeight * 0.5f) < N(WaterSurfaceY))) {
283 N(IsUnderwater) = TRUE;
288 if (N(DiveTime) >= 10) {
290 sushie->curAnim = ANIM_WorldSushie_Rise;
298 y = sushie->moveToPos.y;
300 depth = (sushie->collisionHeight * 0.5f) + playerStatus->
colliderHeight;
303 sushie->moveToPos.y = y;
305 sushie->moveToPos.y += (((sushie->moveToPos.y - y) + depth) - ((sushie->collisionHeight * 0.5f) + playerStatus->
colliderHeight)) * 0.2f;
307 if (N(DiveTime) % 9 == 0) {
308 fx_rising_bubble(0, sushie->pos.x, sushie->moveToPos.y + (sushie->collisionHeight * 0.5f), sushie->pos.z,
309 (N(WaterSurfaceY) - sushie->moveToPos.y) - (sushie->collisionHeight * 0.5f));
312 N(ResurfaceVelY) += 0.14;
313 if (N(ResurfaceVelY) > 1.8) {
314 N(ResurfaceVelY) = 1.8f;
316 sushie->moveToPos.y += N(ResurfaceVelY);
317 if (N(DiveTime) % 9 == 0) {
318 fx_rising_bubble(0, sushie->pos.x, sushie->moveToPos.y + sushie->collisionHeight * 0.5f, sushie->pos.z,
319 (N(WaterSurfaceY) - sushie->moveToPos.y) - sushie->collisionHeight * 0.5f);
321 if ((N(WaterSurfaceY) - sushie->moveToPos.y) - (sushie->collisionHeight * 0.5f) <= 0.0f) {
322 if (N(IsUnderwater)) {
323 N(IsUnderwater) = FALSE;
328 sushie->curAnim = ANIM_WorldSushie_Ride;
329 sushie->moveToPos.y = N(WaterSurfaceY) - (sushie->collisionHeight * 0.5f);
336 f32 sinAngle, cosAngle, totalLength;
337 f32 hitX, hitY, hitZ;
338 f32 hitNx, hitNy, hitNz;
342 cosAngle = -cosAngle;
343 totalLength = radius + length;
345 &hitX, &hitY, &hitZ, &totalLength, &hitNx, &hitNy, &hitNz);
348 *yaw =
atan2(0.0f, 0.0f, hitNx, hitNz);
354API_CALLABLE(N(UseAbility)) {
359 Npc* sushie = script->owner2.npc;
363 f32 sinAngle, cosAngle;
366 #define USE_STATE functionTemp[0]
369 SWIM_STATE_BEGIN = 20,
370 SWIM_STATE_ENTER_WATER = 21,
371 SWIM_STATE_EMBARK_1 = 22,
372 SWIM_STATE_EMBARK_2 = 23,
373 SWIM_STATE_EMBARK_3 = 24,
374 SWIM_STATE_EMBARK_4 = 25,
375 SWIM_STATE_RIDING = 1,
376 SWIM_STATE_DISEMBARK_1 = 3,
377 SWIM_STATE_DISEMBARK_2 = 4,
378 SWIM_STATE_DISEMBARK_3 = 5,
379 SWIM_STATE_EXIT_WATER = 10,
384 N(InertialMoveAngle) = 0.0f;
385 N(InertialMoveSpeed) = 0.0f;
386 N(UnusedMoveX) = 0.0f;
387 N(UnusedMoveZ) = 0.0f;
388 N(ResurfaceVelY) = 0.0f;
389 script->USE_STATE = SWIM_STATE_INIT;
392 playerStatus->
animFlags &= ~PA_FLAG_RIDING_PARTNER;
394 switch (script->USE_STATE) {
395 case SWIM_STATE_INIT:
398 collider = collisionStatus->
curWall;
407 script->USE_STATE = SWIM_STATE_BEGIN;
414 sushie->
flags &= ~NPC_FLAG_GRAVITY;
420 sushie->
curAnim = ANIM_WorldSushie_Ride;
428 script->functionTemp[2] = 0;
429 script->USE_STATE = SWIM_STATE_RIDING;
433 case SWIM_STATE_BEGIN:
439 angle =
atan2(x, z, playerStatus->
pos.
x, playerStatus->
pos.
z);
440 x = playerStatus->
pos.
x;
441 y = playerStatus->
pos.
y;
442 z = playerStatus->
pos.
z;
472 sushie->
curAnim = ANIM_WorldSushie_Run;
479 case SWIM_STATE_ENTER_WATER:
496 sushie->
curAnim = ANIM_WorldSushie_Ride;
510 case SWIM_STATE_EMBARK_2:
513 case SWIM_STATE_EMBARK_1:
514 case SWIM_STATE_EMBARK_3:
517 case SWIM_STATE_EMBARK_4:
534 playerStatus->
flags &= ~PS_FLAG_MOVEMENT_LOCKED;
537 playerStatus->
pos.
x = sushie->
pos.
x;
538 playerStatus->
pos.
y = sushie->
pos.
y;
539 playerStatus->
pos.
z = sushie->
pos.
z;
547 script->functionTemp[2] = 0;
548 script->USE_STATE = SWIM_STATE_RIDING;
551 case SWIM_STATE_RIDING:
555 script->functionTemp[2]++;
556 if (script->functionTemp[2] > 20) {
557 script->functionTemp[2] -= 40;
559 sushie->
pos.
y = sushie->
moveToPos.
y + abs(script->functionTemp[2]) / 8.0f;
560 if (script->functionTemp[2] == 5) {
590 N(WaterSurfaceY) - sushie->
pos.
y);
606 if (N(IsUnderwater)) {
634 N(TouchDockTime) = 0;
646 x = sushie->
pos.
x + ((sinAngle * dist) * 0.6);
647 z = sushie->
pos.
z - ((cosAngle * dist) * 0.6);
665 script->USE_STATE = SWIM_STATE_DISEMBARK_1;
669 case SWIM_STATE_DISEMBARK_1:
673 case SWIM_STATE_DISEMBARK_2:
679 case SWIM_STATE_DISEMBARK_3:
698 playerStatus->
flags &= ~PS_FLAG_MOVEMENT_LOCKED;
710 script->USE_STATE = SWIM_STATE_EXIT_WATER;
713 case SWIM_STATE_EXIT_WATER:
724 sushie->
flags &= ~NPC_FLAG_FLYING;
726 sushie->
flags &= ~NPC_FLAG_IGNORE_WORLD_COLLISION;
753 N(TouchDockTime) = 0;
754 N(IsUnderwater) = FALSE;
757API_CALLABLE(N(TakeOut)) {
758 Npc* sushie = script->owner2.npc;
779API_CALLABLE(N(Update)) {
780 Npc* sushie = script->owner2.npc;
781 f32 sinAngle, cosAngle, liftoffVelocity;
792 if (entity == NULL) {
798 switch (N(TweesterPhysicsPtr)->state) {
800 N(TweesterPhysicsPtr)->state++;
801 N(TweesterPhysicsPtr)->prevFlags = sushie->
flags;
805 N(TweesterPhysicsPtr)->angularVel = 6.0f;
806 N(TweesterPhysicsPtr)->liftoffVelPhase = 50.0f;
807 N(TweesterPhysicsPtr)->countdown = 120;
809 sushie->
flags &= ~NPC_FLAG_GRAVITY;
812 sushie->
pos.
x = entity->
pos.
x + (sinAngle * N(TweesterPhysicsPtr)->radius);
813 sushie->
pos.
z = entity->
pos.
z - (cosAngle * N(TweesterPhysicsPtr)->radius);
814 N(TweesterPhysicsPtr)->angle =
clamp_angle(N(TweesterPhysicsPtr)->angle - N(TweesterPhysicsPtr)->angularVel);
816 if (N(TweesterPhysicsPtr)->radius > 20.0f) {
817 N(TweesterPhysicsPtr)->radius--;
818 }
else if (N(TweesterPhysicsPtr)->radius < 19.0f) {
819 N(TweesterPhysicsPtr)->radius++;
822 liftoffVelocity =
sin_rad(
DEG_TO_RAD(N(TweesterPhysicsPtr)->liftoffVelPhase)) * 3.0f;
823 N(TweesterPhysicsPtr)->liftoffVelPhase += 3.0f;
825 if (N(TweesterPhysicsPtr)->liftoffVelPhase > 150.0f) {
826 N(TweesterPhysicsPtr)->liftoffVelPhase = 150.0f;
829 sushie->
pos.
y += liftoffVelocity;
831 N(TweesterPhysicsPtr)->angularVel += 0.8;
833 if (N(TweesterPhysicsPtr)->angularVel > 40.0f) {
834 N(TweesterPhysicsPtr)->angularVel = 40.0f;
837 if (--N(TweesterPhysicsPtr)->countdown == 0) {
838 N(TweesterPhysicsPtr)->state++;
842 sushie->
flags = N(TweesterPhysicsPtr)->prevFlags;
843 N(TweesterPhysicsPtr)->countdown = 30;
844 N(TweesterPhysicsPtr)->state++;
850 if (--N(TweesterPhysicsPtr)->countdown == 0) {
869 sushie->
flags = N(TweesterPhysicsPtr)->prevFlags;
875API_CALLABLE(N(PutAway)) {
876 Npc* sushie = script->owner2.npc;
896 partnerStatus->
npc = *sushie;
911 *sushie = partnerStatus->
npc;
916API_CALLABLE(N(EnterMap)) {
921 script->functionTemp[0] = 0;
922 N(WaterSurfaceY) = playerStatus->
pos.
y;
925 switch (script->functionTemp[0]) {
930 partnerNPC->
pos.
x = playerStatus->
pos.
x;
931 partnerNPC->
pos.
z = playerStatus->
pos.
z;
932 partnerNPC->
pos.
y = playerStatus->
pos.
y;
936 partnerNPC->
yaw =
atan2(partnerNPC->
pos.
x, partnerNPC->
pos.
z, script->varTable[1], script->varTable[3]);
937 partnerNPC->
curAnim = ANIM_WorldSushie_Ride;
944 partnerNPC->
flags &= ~NPC_FLAG_GRAVITY;
948 if (script->varTable[12] == 0) {
952 if ((partnerNPC->
yaw >= 0.0f) && (partnerNPC->
yaw <= 180.0f)) {
957 script->functionTemp[1] = 25;
958 script->functionTemp[0] = 1;
964 if (!(script->functionTemp[1] & 3)) {
969 script->functionTemp[1]--;
970 if (script->functionTemp[1] == 0) {
971 if (script->varTable[12] == 1) {
s32 partner_use_ability(void)
b8 keepUsingPartnerOnMapChange
AnimID trueAnimation
Encoding back-facing sprite.
@ TWEESTER_PARTNER_ATTRACT
@ TWEESTER_PARTNER_RELEASE
@ PS_FLAG_MOVEMENT_LOCKED
@ COLLIDER_FLAG_DOCK_WALL
@ COLLIDER_FLAG_IGNORE_PLAYER
@ COLLIDER_FLAGS_SURFACE_TYPE_MASK
@ SOUND_ID_TRIGGER_CHANGE_SOUND
@ SOUND_QUICK_PLAYER_JUMP
@ SOUND_SUSHIE_RIDE_MOVING
@ NPC_FLAG_IGNORE_WORLD_COLLISION
@ NPC_FLAG_IGNORE_PLAYER_COLLISION
@ NPC_FLAG_IGNORE_CAMERA_FOR_YAW
b32 npc_raycast_down_around(s32, f32 *, f32 *, f32 *, f32 *, f32, f32)
void suggest_player_anim_always_forward(AnimID anim)
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)
f32 player_check_collision_below(f32, s32 *colliderID)
void partner_walking_update_player_tracking(Npc *partner)
s32 disable_player_static_collisions(void)
s32 enable_player_input(void)
f32 dist2D(f32 ax, f32 ay, f32 bx, f32 by)
void partner_kill_ability_script(void)
void enable_player_shadow(void)
void set_action_state(s32 actionState)
HitID npc_raycast_up_corners(s32 ignoreFlags, f32 *posX, f32 *posY, f32 *posZ, f32 *hitDepth, f32 yaw, f32 radius)
b32 npc_test_move_taller_with_slipping(s32, f32 *, f32 *, f32 *, f32, f32, f32, f32)
void get_collider_center(s32 colliderID, f32 *x, f32 *y, f32 *z)
void suggest_player_anim_allow_backward(AnimID anim)
s32 test_ray_colliders(s32 ignoreFlags, f32 startX, f32 startY, f32 startZ, f32 dirX, f32 dirY, f32 dirZ, f32 *hitX, f32 *hitY, f32 *hitZ, f32 *hitDepth, f32 *hitNx, f32 *hitNy, f32 *hitNz)
void partner_walking_enable(Npc *partner, s32 val)
s32 enable_player_static_collisions(void)
void sin_cos_rad(f32 rad, f32 *outSinTheta, f32 *outCosTheta)
void add_vec2D_polar(f32 *x, f32 *y, f32 r, f32 theta)
void disable_player_shadow(void)
void enable_npc_shadow(Npc *npc)
void disable_npc_shadow(Npc *npc)
void npc_set_imgfx_params(Npc *npc, s32 arg1, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6)
Npc * get_npc_unsafe(s32 npcID)
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_get_out(Npc *partner)
void sfx_play_sound_at_npc(s32 soundID, s32 arg1, s32 npcID)
#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.
void set_player_imgfx_all(s32 animID, ImgFXType imgfxType, s32 arg2, s32 arg3, s32 arg4, s32 arg5, s32 arg6)
Entity * TweesterTouchingPartner
PlayerStatus * gPlayerStatusPtr
CollisionStatus gCollisionStatus
PartnerStatus gPartnerStatus
GameStatus * gGameStatusPtr
s32 NpcHitQueryColliderID
PlayerStatus gPlayerStatus
void N sync_player_position(void)
EvtScript EVS_WorldSushie_PutAway
void N try_cancel_tweester(Npc *sushie)
EvtScript EVS_WorldSushie_EnterMap
void N post_battle(Npc *sushie)
EvtScript EVS_WorldSushie_TakeOut
void N test_for_water_level(s32 ignoreFlags, f32 posX, f32 posY, f32 posZ, f32 yaw, f32 radius)
EvtScript EVS_WorldSushie_UseAbility
void N update_riding_physics(Npc *sushie)
EvtScript EVS_WorldSushie_Update
HitID N test_ray_to_wall_center(s32 unused, f32 *x, f32 *y, f32 *z, f32 length, f32 radius, f32 *yaw)
void N pre_battle(Npc *sushie)
void N get_movement_from_input(f32 *outAngle, f32 *outSpeed)