summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDragorn421 <Dragorn421@users.noreply.github.com>2026-08-31 18:22:17 +0200
committerGitHub <noreply@github.com>2026-08-31 18:22:17 +0200
commit7dbd31ab0b5b8db369b96ae17a0a0b01ada328ea (patch)
tree45371681ae98e90697a7d83279bec751cfe44fcc /src
parent1e2bd9e46a30551b99e53b5626a8082e4f01be48 (diff)
[cc0 oot] EnFish (#2792)
* [cc0 oot] EnFish * bring changes to external files * EnFish actionFunc typedef * EnFish move variable assigns into decls * format
Diffstat (limited to 'src')
-rw-r--r--src/overlays/actors/ovl_En_Fish/z_en_fish.c654
-rw-r--r--src/overlays/actors/ovl_En_Fish/z_en_fish.h38
-rw-r--r--src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c3
-rw-r--r--src/overlays/actors/ovl_player_actor/z_player.c2
4 files changed, 318 insertions, 379 deletions
diff --git a/src/overlays/actors/ovl_En_Fish/z_en_fish.c b/src/overlays/actors/ovl_En_Fish/z_en_fish.c
index f1efbfa08..46377e3f6 100644
--- a/src/overlays/actors/ovl_En_Fish/z_en_fish.c
+++ b/src/overlays/actors/ovl_En_Fish/z_en_fish.c
@@ -1,27 +1,18 @@
-/*
- * File: z_en_fish.c
- * Overlay: ovl_En_Fish
- * Description: Fish
- */
-
#include "z_en_fish.h"
#include "libc64/qrand.h"
#include "array_count.h"
-#include "gfx.h"
#include "gfx_setupdl.h"
#include "ichain.h"
#include "printf.h"
#include "sfx.h"
-#include "terminal.h"
-#include "translation.h"
#include "z_lib.h"
#include "item.h"
#include "play_state.h"
#include "player.h"
-#include "assets/objects/gameplay_keep/gFishInWaterAnim.h"
#include "assets/objects/gameplay_keep/gFishInAirAnim.h"
+#include "assets/objects/gameplay_keep/gFishInWaterAnim.h"
#include "assets/objects/gameplay_keep/gameplay_keep_0x18610.h"
#define FLAGS 0
@@ -31,27 +22,31 @@ void EnFish_Destroy(Actor* thisx, PlayState* play2);
void EnFish_Update(Actor* thisx, PlayState* play);
void EnFish_Draw(Actor* thisx, PlayState* play);
-void EnFish_Respawning_SetupSlowDown(EnFish* this);
-void EnFish_Respawning_SlowDown(EnFish* this, PlayState* play);
-void EnFish_Respawning_SetupFollowChild(EnFish* this);
-void EnFish_Respawning_FollowChild(EnFish* this, PlayState* play);
-void EnFish_Respawning_SetupFleePlayer(EnFish* this);
-void EnFish_Respawning_FleePlayer(EnFish* this, PlayState* play);
-void EnFish_Respawning_SetupApproachPlayer(EnFish* this);
-void EnFish_Respawning_ApproachPlayer(EnFish* this, PlayState* play);
+void EnFish_Normal_SetupStay(EnFish* this);
+void EnFish_Normal_Stay(EnFish* this, PlayState* play);
+void EnFish_Normal_SetupSwim(EnFish* this);
+void EnFish_Normal_Swim(EnFish* this, PlayState* play);
+void EnFish_Normal_SetupFleePlayer(EnFish* this);
+void EnFish_Normal_FleePlayer(EnFish* this, PlayState* play);
+void EnFish_Normal_SetupFollowPlayer(EnFish* this);
+void EnFish_Normal_FollowPlayer(EnFish* this, PlayState* play);
void EnFish_Dropped_SetupFall(EnFish* this);
void EnFish_Dropped_Fall(EnFish* this, PlayState* play);
-void EnFish_Dropped_SetupFlopOnGround(EnFish* this);
-void EnFish_Dropped_FlopOnGround(EnFish* this, PlayState* play);
-void EnFish_Dropped_SetupSwimAway(EnFish* this);
-void EnFish_Dropped_SwimAway(EnFish* this, PlayState* play);
-void EnFish_Unique_SetupSwimIdle(EnFish* this);
-void EnFish_Unique_SwimIdle(EnFish* this, PlayState* play);
-
-// Used in the cutscene functions
-static Actor* D_80A17010 = NULL;
-static f32 D_80A17014 = 0.0f;
-static f32 D_80A17018 = 0.0f;
+void EnFish_Dropped_SetupFlapOnGround(EnFish* this);
+void EnFish_Dropped_FlapOnGround(EnFish* this, PlayState* play);
+void EnFish_Dropped_SetupSwim(EnFish* this);
+void EnFish_Dropped_Swim(EnFish* this, PlayState* play);
+void EnFish_TinyPond_SetupSwim(EnFish* this);
+void EnFish_TinyPond_Swim(EnFish* this, PlayState* play);
+void EnFish_JabuCutscene_CueFlapOnGround(EnFish* this, PlayState* play);
+void EnFish_JabuCutscene_CueFly(EnFish* this, PlayState* play);
+void EnFish_JabuCutscene_Update(EnFish* this, PlayState* play);
+void EnFish_UpdateImpl(EnFish* this, PlayState* play);
+void EnFish_UpdateWaitReappear(EnFish* this, PlayState* play);
+
+static EnFish* sJabuCutsceneFish = NULL;
+static f32 sJabuCutsceneOffsetY = 0.0f;
+static f32 sJabuCutsceneOffsetYSpeed = 0.0f;
static ColliderJntSphElementInit sJntSphElementsInit[] = {
{
@@ -92,77 +87,87 @@ ActorProfile En_Fish_Profile = {
/**/ EnFish_Draw,
};
-static InitChainEntry sInitChain[] = {
+static InitChainEntry sInitChain[4] = {
ICHAIN_VEC3F_DIV1000(scale, 10, ICHAIN_CONTINUE),
ICHAIN_F32(cullingVolumeDistance, 900, ICHAIN_CONTINUE),
ICHAIN_F32(cullingVolumeScale, 40, ICHAIN_CONTINUE),
ICHAIN_F32(cullingVolumeDownward, 700, ICHAIN_STOP),
};
-f32 EnFish_XZDistanceSquared(Vec3f* v1, Vec3f* v2) {
- return SQ(v1->x - v2->x) + SQ(v1->z - v2->z);
+typedef struct struct_80A17080 {
+ /* 0x0 */ f32 target;
+ /* 0x4 */ f32 fraction;
+ /* 0x8 */ f32 step;
+} EnFishSpeedParams; // size = 0xC
+static EnFishSpeedParams sStaySpeedParams = { 0.0f, 0.04f, 0.09f };
+static EnFishSpeedParams sMoveSpeedParams = { 0.5f, 0.1f, 0.15f };
+
+f32 EnFish_DistXZSq(Vec3f* posA, Vec3f* posB) {
+ f32 dx = posA->x - posB->x;
+ f32 dz = posA->z - posB->z;
+
+ return SQ(dx) + SQ(dz);
}
-void EnFish_SetInWaterAnimation(EnFish* this) {
+void EnFish_ChangeAnimInWater(EnFish* this) {
Animation_Change(&this->skelAnime, &gFishInWaterAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gFishInWaterAnim),
ANIMMODE_LOOP_INTERP, 2.0f);
}
-void EnFish_SetOutOfWaterAnimation(EnFish* this) {
+void EnFish_ChangeAnimInAir(EnFish* this) {
Animation_Change(&this->skelAnime, &gFishInAirAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gFishInAirAnim),
ANIMMODE_LOOP_INTERP, 2.0f);
}
-void EnFish_BeginRespawn(EnFish* this) {
- this->respawnTimer = 400;
+void EnFish_Disappear(EnFish* this) {
+ this->reappearTimer = 400;
Actor_SetScale(&this->actor, 0.001f);
this->actor.draw = NULL;
}
-void EnFish_SetCutsceneData(EnFish* this) {
- Actor* thisx = &this->actor;
+void EnFish_JabuCutscene_Enter(EnFish* this2) {
+ EnFish* this = this2;
- if (D_80A17010 == NULL) {
- D_80A17010 = thisx;
- Actor_SetScale(thisx, 0.01f);
- thisx->draw = EnFish_Draw;
- thisx->shape.rot.x = 0;
- thisx->shape.rot.y = -0x6410;
- thisx->shape.rot.z = 0x4000;
- thisx->shape.yOffset = 600.0f;
- D_80A17014 = 10.0f;
- D_80A17018 = 0.0f;
- thisx->flags |= ACTOR_FLAG_UPDATE_CULLING_DISABLED;
- EnFish_SetOutOfWaterAnimation(this);
+ if (sJabuCutsceneFish == NULL) {
+ sJabuCutsceneFish = this;
+ Actor_SetScale(&this->actor, 0.01f);
+ this->actor.draw = EnFish_Draw;
+ this->actor.shape.rot.x = 0;
+ this->actor.shape.rot.y = -0x6410;
+ this->actor.shape.rot.z = 0x4000;
+ this->actor.shape.yOffset = 600.0f;
+ sJabuCutsceneOffsetY = 10.0f;
+ sJabuCutsceneOffsetYSpeed = 0.0f;
+ this->actor.flags |= ACTOR_FLAG_UPDATE_CULLING_DISABLED;
+ EnFish_ChangeAnimInAir(this);
}
}
-void EnFish_ClearCutsceneData(EnFish* this) {
- D_80A17010 = NULL;
- D_80A17014 = 0.0f;
- D_80A17018 = 0.0f;
+void EnFish_JabuCutscene_Clear(EnFish* this) {
+ sJabuCutsceneFish = NULL;
+ sJabuCutsceneOffsetY = 0.0f;
+ sJabuCutsceneOffsetYSpeed = 0.0f;
}
void EnFish_Init(Actor* thisx, PlayState* play) {
EnFish* this = (EnFish*)thisx;
- s16 params = this->actor.params;
+ s16 type = this->actor.params;
Actor_ProcessInitChain(&this->actor, sInitChain);
SkelAnime_InitFlex(play, &this->skelAnime, &gFishSkel, &gFishInWaterAnim, this->jointTable, this->morphTable, 7);
Collider_InitJntSph(play, &this->collider);
Collider_SetJntSph(play, &this->collider, &this->actor, &sJntSphInit, this->colliderElements);
this->actor.colChkInfo.mass = 50;
- this->slowPhase = Rand_ZeroOne() * (0xFFFF + 0.5f);
- this->fastPhase = Rand_ZeroOne() * (0xFFFF + 0.5f);
-
- if (params == FISH_DROPPED) {
+ this->phase1 = (s16)(s32)(Rand_ZeroOne() * 65535.5f);
+ this->phase2 = (s16)(s32)(Rand_ZeroOne() * 65535.5f);
+ if (type == EN_FISH_TYPE_DROPPED) {
this->actor.flags |= ACTOR_FLAG_UPDATE_CULLING_DISABLED;
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 8.0f);
EnFish_Dropped_SetupFall(this);
- } else if (params == FISH_SWIMMING_UNIQUE) {
- EnFish_Unique_SetupSwimIdle(this);
- } else {
- EnFish_Respawning_SetupSlowDown(this);
+ } else if (type == EN_FISH_TYPE_TINY_POND) {
+ EnFish_TinyPond_SetupSwim(this);
+ } else { // EN_FISH_TYPE_NORMAL
+ EnFish_Normal_SetupStay(this);
}
}
@@ -173,131 +178,125 @@ void EnFish_Destroy(Actor* thisx, PlayState* play2) {
Collider_DestroyJntSph(play, &this->collider);
}
-void EnFish_SetYOffset(EnFish* this) {
- this->actor.shape.yOffset += (Math_SinS(this->slowPhase) * 10.0f + Math_SinS(this->fastPhase) * 5.0f);
+void EnFish_UpdateBobbingUpDown(EnFish* this) {
+ this->actor.shape.yOffset += (Math_SinS(this->phase1) * 10.0f) + (Math_SinS(this->phase2) * 5.0f);
this->actor.shape.yOffset = CLAMP(this->actor.shape.yOffset, -200.0f, 200.0f);
}
-s32 EnFish_InBottleRange(EnFish* this, PlayState* play) {
+s32 EnFish_IsInRangeForCatch(EnFish* this, PlayState* play) {
s32 pad;
Player* player = GET_PLAYER(play);
- Vec3f sp1C;
+ Vec3f playerPos;
if (this->actor.xzDistToPlayer < 32.0f) {
- sp1C.x = (Math_SinS(this->actor.yawTowardsPlayer + 0x8000) * 16.0f) + player->actor.world.pos.x;
- sp1C.y = player->actor.world.pos.y;
- sp1C.z = (Math_CosS(this->actor.yawTowardsPlayer + 0x8000) * 16.0f) + player->actor.world.pos.z;
-
- //! @bug: this check is superfluous: it is automatically satisfied if the coarse check is satisfied. It may have
- //! been intended to check the actor is in front of Player, but yawTowardsPlayer does not depend on Player's
- //! world rotation.
- if (EnFish_XZDistanceSquared(&sp1C, &this->actor.world.pos) <= SQ(20.0f)) {
+ // Add a slight offset towards the fish to the player position.
+ playerPos.x = (Math_SinS(this->actor.yawTowardsPlayer + 0x8000) * 16.0f) + player->actor.world.pos.x;
+ playerPos.y = player->actor.world.pos.y;
+ playerPos.z = (Math_CosS(this->actor.yawTowardsPlayer + 0x8000) * 16.0f) + player->actor.world.pos.z;
+ if (EnFish_DistXZSq(&playerPos, &this->actor.world.pos) <= SQ(20.0f)) {
return true;
}
}
-
return false;
}
-s32 EnFish_CheckXZDistanceToPlayer(EnFish* this, PlayState* play) {
- return (this->actor.xzDistToPlayer < 60.0f);
+s32 EnFish_IsCloseToPlayer(EnFish* this, PlayState* play) {
+ return this->actor.xzDistToPlayer < 60.0f;
}
-// Respawning type functions
-
-void EnFish_Respawning_SetupSlowDown(EnFish* this) {
+void EnFish_Normal_SetupStay(EnFish* this) {
this->actor.gravity = 0.0f;
this->actor.minVelocityY = 0.0f;
this->timer = Rand_S16Offset(5, 35);
- this->unk_250 = 0;
- EnFish_SetInWaterAnimation(this);
- this->actionFunc = EnFish_Respawning_SlowDown;
+ this->updBgCheckInfoFlags = 0;
+ EnFish_ChangeAnimInWater(this);
+ this->actionFunc = EnFish_Normal_Stay;
}
-void EnFish_Respawning_SlowDown(EnFish* this, PlayState* play) {
- EnFish_SetYOffset(this);
+void EnFish_Normal_Stay(EnFish* this, PlayState* play) {
+ EnFish_UpdateBobbingUpDown(this);
Math_SmoothStepToF(&this->actor.speed, 0.0f, 0.05f, 0.3f, 0.0f);
- this->skelAnime.playSpeed = CLAMP_MAX(this->actor.speed * 1.4f + 0.8f, 2.0f);
+ this->skelAnime.playSpeed = CLAMP_MAX((this->actor.speed * 1.4f) + 0.8f, 2.0f);
SkelAnime_Update(&this->skelAnime);
this->actor.shape.rot.y = this->actor.world.rot.y;
-
if (this->timer <= 0) {
- EnFish_Respawning_SetupFollowChild(this);
- } else if (&this->actor == this->actor.child) {
- EnFish_Respawning_SetupApproachPlayer(this);
- } else if (EnFish_CheckXZDistanceToPlayer(this, play)) {
- EnFish_Respawning_SetupFleePlayer(this);
+ EnFish_Normal_SetupSwim(this);
+ } else if (this->actor.child == &this->actor) { // see ObjMure
+ EnFish_Normal_SetupFollowPlayer(this);
+ } else if (EnFish_IsCloseToPlayer(this, play)) {
+ EnFish_Normal_SetupFleePlayer(this);
}
}
-// The three following actionfunctions also turn the yaw to home if the fish is too far from it.
-
-void EnFish_Respawning_SetupFollowChild(EnFish* this) {
+void EnFish_Normal_SetupSwim(EnFish* this) {
this->actor.gravity = 0.0f;
this->actor.minVelocityY = 0.0f;
this->timer = Rand_S16Offset(15, 45);
- this->unk_250 = 0;
- EnFish_SetInWaterAnimation(this);
- this->actionFunc = EnFish_Respawning_FollowChild;
+ this->updBgCheckInfoFlags = 0;
+ EnFish_ChangeAnimInWater(this);
+ this->actionFunc = EnFish_Normal_Swim;
}
-void EnFish_Respawning_FollowChild(EnFish* this, PlayState* play) {
+void EnFish_Normal_Swim(EnFish* this, PlayState* play) {
s32 pad;
- EnFish_SetYOffset(this);
+ EnFish_UpdateBobbingUpDown(this);
Math_SmoothStepToF(&this->actor.speed, 1.8f, 0.08f, 0.4f, 0.0f);
-
- if ((EnFish_XZDistanceSquared(&this->actor.world.pos, &this->actor.home.pos) > SQ(80.0f)) || (this->timer < 4)) {
+ if ((EnFish_DistXZSq(&this->actor.world.pos, &this->actor.home.pos) > SQ(80.0f)) || (this->timer < 4)) {
+ // Move towards home
Math_StepToAngleS(&this->actor.world.rot.y, Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.home.pos),
- 3000);
- } else if ((this->actor.child != NULL) && (&this->actor != this->actor.child)) {
+ 0xBB8);
+ } else if ((this->actor.child != NULL) && (this->actor.child != &this->actor)) {
+ // Follow another fish
Math_StepToAngleS(&this->actor.world.rot.y,
- Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.child->world.pos), 3000);
+ Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.child->world.pos), 0xBB8);
}
-
this->actor.shape.rot.y = this->actor.world.rot.y;
- this->skelAnime.playSpeed = CLAMP_MAX(this->actor.speed * 1.5f + 0.8f, 4.0f);
+ this->skelAnime.playSpeed = CLAMP_MAX((this->actor.speed * 1.5f) + 0.8f, 4.0f);
SkelAnime_Update(&this->skelAnime);
-
if (this->timer <= 0) {
- EnFish_Respawning_SetupSlowDown(this);
- } else if (&this->actor == this->actor.child) {
- EnFish_Respawning_SetupApproachPlayer(this);
- } else if (EnFish_CheckXZDistanceToPlayer(this, play)) {
- EnFish_Respawning_SetupFleePlayer(this);
+ EnFish_Normal_SetupStay(this);
+ } else if (this->actor.child == &this->actor) {
+ EnFish_Normal_SetupFollowPlayer(this);
+ } else if (EnFish_IsCloseToPlayer(this, play)) {
+ EnFish_Normal_SetupFleePlayer(this);
}
}
-void EnFish_Respawning_SetupFleePlayer(EnFish* this) {
+void EnFish_Normal_SetupFleePlayer(EnFish* this) {
this->actor.gravity = 0.0f;
this->actor.minVelocityY = 0.0f;
this->timer = Rand_S16Offset(10, 40);
- this->unk_250 = 0;
- EnFish_SetInWaterAnimation(this);
- this->actionFunc = EnFish_Respawning_FleePlayer;
+ this->updBgCheckInfoFlags = 0;
+ EnFish_ChangeAnimInWater(this);
+ this->actionFunc = EnFish_Normal_FleePlayer;
}
-void EnFish_Respawning_FleePlayer(EnFish* this, PlayState* play) {
- s32 pad;
- s16 pad2;
+/**
+ * Swim much faster until the player is not close or ObjMure signals to follow the player.
+ */
+void EnFish_Normal_FleePlayer(EnFish* this, PlayState* play) {
s16 frames;
s16 yaw;
- s16 playerClose;
+ s32 pad2;
+ s16 pad;
+ s16 isCloseToPlayer;
- EnFish_SetYOffset(this);
- playerClose = EnFish_CheckXZDistanceToPlayer(this, play);
+ EnFish_UpdateBobbingUpDown(this);
+ isCloseToPlayer = EnFish_IsCloseToPlayer(this, play);
Math_SmoothStepToF(&this->actor.speed, 4.2f, 0.08f, 1.4f, 0.0f);
-
- if (EnFish_XZDistanceSquared(&this->actor.world.pos, &this->actor.home.pos) > SQ(160.0f)) {
+ if (EnFish_DistXZSq(&this->actor.world.pos, &this->actor.home.pos) > SQ(160.0f)) {
+ // Too far from home
yaw = Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.home.pos);
- Math_StepToAngleS(&this->actor.world.rot.y, yaw, 3000);
- } else if ((this->actor.child != NULL) && (&this->actor != this->actor.child)) {
+ Math_StepToAngleS(&this->actor.world.rot.y, yaw, 0xBB8);
+ } else if ((this->actor.child != NULL) && (this->actor.child != &this->actor)) {
+ // Follow another fish
yaw = Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.child->world.pos);
- Math_StepToAngleS(&this->actor.world.rot.y, yaw, 2000);
- } else if (playerClose) {
- yaw = this->actor.yawTowardsPlayer + 0x8000;
+ Math_StepToAngleS(&this->actor.world.rot.y, yaw, 0x7D0);
+ } else if (isCloseToPlayer) {
frames = play->state.frames;
-
+ if (play) {}
+ yaw = this->actor.yawTowardsPlayer + 0x8000;
if (frames & 0x10) {
if (frames & 0x20) {
yaw += 0x2000;
@@ -307,451 +306,389 @@ void EnFish_Respawning_FleePlayer(EnFish* this, PlayState* play) {
yaw -= 0x2000;
}
}
- if (play) {}
- Math_StepToAngleS(&this->actor.world.rot.y, yaw, 2000);
+ Math_StepToAngleS(&this->actor.world.rot.y, yaw, 0x7D0);
}
-
this->actor.shape.rot.y = this->actor.world.rot.y;
- this->skelAnime.playSpeed = CLAMP_MAX(this->actor.speed * 1.5f + 0.8f, 4.0f);
-
+ this->skelAnime.playSpeed = CLAMP_MAX((this->actor.speed * 1.5f) + 0.8f, 4.0f);
SkelAnime_Update(&this->skelAnime);
-
- if ((this->timer <= 0) || !playerClose) {
- EnFish_Respawning_SetupSlowDown(this);
- } else if (&this->actor == this->actor.child) {
- EnFish_Respawning_SetupApproachPlayer(this);
+ if ((this->timer <= 0) || !isCloseToPlayer) {
+ EnFish_Normal_SetupStay(this);
+ } else if (this->actor.child == &this->actor) {
+ EnFish_Normal_SetupFollowPlayer(this);
}
}
-void EnFish_Respawning_SetupApproachPlayer(EnFish* this) {
+void EnFish_Normal_SetupFollowPlayer(EnFish* this) {
this->actor.gravity = 0.0f;
this->actor.minVelocityY = 0.0f;
- EnFish_SetInWaterAnimation(this);
+ EnFish_ChangeAnimInWater(this);
this->timer = Rand_S16Offset(10, 40);
- this->unk_250 = 0;
- this->actionFunc = EnFish_Respawning_ApproachPlayer;
+ this->updBgCheckInfoFlags = 0;
+ this->actionFunc = EnFish_Normal_FollowPlayer;
}
-void EnFish_Respawning_ApproachPlayer(EnFish* this, PlayState* play) {
+void EnFish_Normal_FollowPlayer(EnFish* this, PlayState* play) {
s32 pad;
Player* player = GET_PLAYER(play);
s32 pad2;
- Vec3f sp38;
+ Vec3f playerPos;
s16 yaw;
- s16 temp_a0_2;
+ s16 angle;
- EnFish_SetYOffset(this);
+ EnFish_UpdateBobbingUpDown(this);
Math_SmoothStepToF(&this->actor.speed, 1.8f, 0.1f, 0.5f, 0.0f);
-
- if (EnFish_XZDistanceSquared(&this->actor.world.pos, &this->actor.home.pos) > SQ(80.0f)) {
+ if (EnFish_DistXZSq(&this->actor.world.pos, &this->actor.home.pos) > SQ(80.0f)) {
+ // Too far from home
yaw = Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.home.pos);
- Math_StepToAngleS(&this->actor.world.rot.y, yaw, 3000);
+ Math_StepToAngleS(&this->actor.world.rot.y, yaw, 0xBB8);
} else {
+ // Follow the player
if ((s16)play->state.frames & 0x40) {
- temp_a0_2 = (this->actor.yawTowardsPlayer + 0x9000);
+ angle = (this->actor.yawTowardsPlayer + 0x9000);
} else {
- temp_a0_2 = (this->actor.yawTowardsPlayer + 0x7000);
+ angle = (this->actor.yawTowardsPlayer + 0x7000);
}
-
- sp38.x = player->actor.world.pos.x + (Math_SinS(temp_a0_2) * 20.0f);
- sp38.y = player->actor.world.pos.y;
- sp38.z = player->actor.world.pos.z + (Math_CosS(temp_a0_2) * 20.0f);
-
- yaw = Math_Vec3f_Yaw(&this->actor.world.pos, &sp38);
- Math_StepToAngleS(&this->actor.world.rot.y, yaw, 3000);
+ // Add a slight offset approximately towards the fish to the player position.
+ playerPos.x = (Math_SinS(angle) * 20.0f) + player->actor.world.pos.x;
+ playerPos.y = player->actor.world.pos.y;
+ playerPos.z = (Math_CosS(angle) * 20.0f) + player->actor.world.pos.z;
+ yaw = Math_Vec3f_Yaw(&this->actor.world.pos, &playerPos);
+ Math_StepToAngleS(&this->actor.world.rot.y, yaw, 0xBB8);
}
-
this->actor.shape.rot.y = this->actor.world.rot.y;
this->skelAnime.playSpeed = CLAMP_MAX((this->actor.speed * 1.5f) + 0.8f, 4.0f);
-
SkelAnime_Update(&this->skelAnime);
-
if (this->timer <= 0) {
- EnFish_Respawning_SetupSlowDown(this);
+ EnFish_Normal_SetupStay(this);
}
}
-// Dropped type functions
-
void EnFish_Dropped_SetupFall(EnFish* this) {
this->actor.gravity = -1.0f;
this->actor.minVelocityY = -10.0f;
this->actor.shape.yOffset = 0.0f;
- EnFish_SetOutOfWaterAnimation(this);
- this->unk_250 = UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2;
+ EnFish_ChangeAnimInAir(this);
+ this->updBgCheckInfoFlags = UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2;
this->actionFunc = EnFish_Dropped_Fall;
this->timer = 300;
}
void EnFish_Dropped_Fall(EnFish* this, PlayState* play) {
Math_SmoothStepToF(&this->actor.speed, 0.0f, 0.1f, 0.1f, 0.0f);
- Math_StepToAngleS(&this->actor.world.rot.x, 0x4000, 100);
- Math_StepToAngleS(&this->actor.world.rot.z, -0x4000, 100);
+ Math_StepToAngleS(&this->actor.world.rot.x, 0x4000, 0x64);
+ Math_StepToAngleS(&this->actor.world.rot.z, -0x4000, 0x64);
this->actor.shape.rot.x = this->actor.world.rot.x;
this->actor.shape.rot.y = this->actor.world.rot.y;
this->actor.shape.rot.z = this->actor.world.rot.z;
SkelAnime_Update(&this->skelAnime);
-
if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) {
this->timer = 400;
- EnFish_Dropped_SetupFlopOnGround(this);
+ EnFish_Dropped_SetupFlapOnGround(this);
} else if (this->actor.bgCheckFlags & BGCHECKFLAG_WATER) {
- EnFish_Dropped_SetupSwimAway(this);
- } else if ((this->timer <= 0) && (this->actor.params == FISH_DROPPED) &&
- (this->actor.floorHeight < BGCHECK_Y_MIN + 10.0f)) {
+ EnFish_Dropped_SetupSwim(this);
+ } else if ((this->timer <= 0) && (this->actor.params == EN_FISH_TYPE_DROPPED) &&
+ (this->actor.floorHeight < (BGCHECK_Y_MIN + 10.0f))) {
PRINTF_COLOR_WARNING();
- PRINTF(T("BG 抜け? Actor_delete します(%s %d)\n", "BG missing? Running Actor_delete (%s %d)\n"),
- "../z_en_sakana.c", 822);
+ PRINTF("BG 抜け? Actor_delete します(%s %d)\n", "../z_en_sakana.c", 822);
PRINTF_RST();
Actor_Kill(&this->actor);
}
}
-/**
- * If the fish is on a floor, this function is looped back to by EnFish_Dropped_FlopOnGround to set a new flopping
- * height and whether the sound should play again.
- */
-void EnFish_Dropped_SetupFlopOnGround(EnFish* this) {
- s32 pad;
- f32 randomFloat;
- s32 playSfx;
+void EnFish_Dropped_SetupFlapOnGround(EnFish* this) {
+ s32 pad[2];
+ s32 playLeapSfx;
+ f32 rng;
this->actor.gravity = -1.0f;
this->actor.minVelocityY = -10.0f;
- randomFloat = Rand_ZeroOne();
-
- if (randomFloat < 0.1f) {
+ rng = Rand_ZeroOne();
+ if (rng < 0.1f) {
this->actor.velocity.y = (Rand_ZeroOne() * 3.0f) + 2.5f;
- playSfx = true;
- } else if (randomFloat < 0.2f) {
+ playLeapSfx = true;
+ } else if (rng < 0.2f) {
this->actor.velocity.y = (Rand_ZeroOne() * 1.2f) + 0.2f;
- playSfx = true;
+ playLeapSfx = true;
} else {
this->actor.velocity.y = 0.0f;
-
if (Rand_ZeroOne() < 0.2f) {
- playSfx = true;
+ playLeapSfx = true;
} else {
- playSfx = false;
+ playLeapSfx = false;
}
}
-
this->actor.shape.yOffset = 300.0f;
- EnFish_SetOutOfWaterAnimation(this);
- this->actionFunc = EnFish_Dropped_FlopOnGround;
- this->unk_250 = UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2;
-
- if (playSfx && (this->actor.draw != NULL)) {
+ EnFish_ChangeAnimInAir(this);
+ this->actionFunc = EnFish_Dropped_FlapOnGround;
+ this->updBgCheckInfoFlags = UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2;
+ if (playLeapSfx && (this->actor.draw != NULL)) {
Actor_PlaySfx(&this->actor, NA_SE_EV_FISH_LEAP);
}
}
-void EnFish_Dropped_FlopOnGround(EnFish* this, PlayState* play) {
- s32 pad;
+void EnFish_Dropped_FlapOnGround(EnFish* this, PlayState* play) {
+ s16 targetRotX;
+ s16 pad;
s16 frames = play->state.frames;
- s16 targetXRot;
Math_SmoothStepToF(&this->actor.speed, Rand_ZeroOne() * 0.2f, 0.1f, 0.1f, 0.0f);
-
- targetXRot = (s16)((((frames >> 5) & 2) | ((frames >> 2) & 1)) << 0xB) * 0.3f;
-
+ targetRotX = (s16)(s32)((s16)((((frames >> 5) & 2) | ((frames >> 2) & 1)) * 0x800) * 0.3f);
if (frames & 4) {
- targetXRot = -targetXRot;
+ targetRotX *= -1;
}
-
- Math_StepToAngleS(&this->actor.world.rot.x, targetXRot, 4000);
- Math_StepToAngleS(&this->actor.world.rot.z, 0x4000, 1000);
+ Math_StepToAngleS(&this->actor.world.rot.x, targetRotX, 0xFA0);
+ Math_StepToAngleS(&this->actor.world.rot.z, 0x4000, 0x3E8);
this->actor.world.rot.y +=
- (s16)(((Math_SinS(this->slowPhase) * 2000.0f) + (Math_SinS(this->fastPhase) * 1000.0f)) * Rand_ZeroOne());
+ (s16)(s32)(((Math_SinS(this->phase1) * 2000.0f) + (Math_SinS(this->phase2) * 1000.0f)) * Rand_ZeroOne());
this->actor.shape.rot = this->actor.world.rot;
-
SkelAnime_Update(&this->skelAnime);
-
if (this->timer <= 0) {
Actor_Kill(&this->actor);
return;
}
-
if (this->timer <= 60) {
- // Blink when about to disappear
if (frames & 4) {
this->actor.draw = EnFish_Draw;
} else {
this->actor.draw = NULL;
}
} else if (this->actor.bgCheckFlags & BGCHECKFLAG_WATER) {
- EnFish_Dropped_SetupSwimAway(this);
+ EnFish_Dropped_SetupSwim(this);
} else if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) {
- EnFish_Dropped_SetupFlopOnGround(this);
+ EnFish_Dropped_SetupFlapOnGround(this);
}
}
-void EnFish_Dropped_SetupSwimAway(EnFish* this) {
+void EnFish_Dropped_SetupSwim(EnFish* this) {
this->actor.home.pos = this->actor.world.pos;
this->actor.gravity = 0.0f;
this->actor.minVelocityY = 0.0f;
this->actor.shape.yOffset = 0.0f;
this->actor.flags |= ACTOR_FLAG_UPDATE_CULLING_DISABLED;
this->timer = 200;
- EnFish_SetInWaterAnimation(this);
- this->actionFunc = EnFish_Dropped_SwimAway;
- this->unk_250 = UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2;
+ EnFish_ChangeAnimInWater(this);
+ this->actionFunc = EnFish_Dropped_Swim;
+ this->updBgCheckInfoFlags = UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2;
}
-void EnFish_Dropped_SwimAway(EnFish* this, PlayState* play) {
+void EnFish_Dropped_Swim(EnFish* this, PlayState* play) {
s32 pad;
Math_SmoothStepToF(&this->actor.speed, 2.8f, 0.1f, 0.4f, 0.0f);
-
- // If touching wall or not in water, turn back and slow down for one frame.
if ((this->actor.bgCheckFlags & BGCHECKFLAG_WALL) || !(this->actor.bgCheckFlags & BGCHECKFLAG_WATER)) {
this->actor.home.rot.y = Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.home.pos);
this->actor.speed *= 0.5f;
}
-
- Math_StepToAngleS(&this->actor.world.rot.x, 0, 1500);
- Math_StepToAngleS(&this->actor.world.rot.y, this->actor.home.rot.y, 3000);
- Math_StepToAngleS(&this->actor.world.rot.z, 0, 1000);
-
+ Math_StepToAngleS(&this->actor.world.rot.x, 0, 0x5DC);
+ Math_StepToAngleS(&this->actor.world.rot.y, this->actor.home.rot.y, 0xBB8);
+ Math_StepToAngleS(&this->actor.world.rot.z, 0, 0x3E8);
this->actor.shape.rot = this->actor.world.rot;
-
- // Raise if on a floor.
if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) {
Math_StepToF(&this->actor.world.pos.y, this->actor.home.pos.y - 4.0f, 2.0f);
} else {
Math_StepToF(&this->actor.world.pos.y, this->actor.home.pos.y - 10.0f, 2.0f);
}
-
- // Shrink when close to disappearing.
if (this->timer < 100) {
Actor_SetScale(&this->actor, this->actor.scale.x * 0.982f);
}
-
this->skelAnime.playSpeed = CLAMP_MAX((this->actor.speed * 1.5f) + 1.0f, 4.0f);
SkelAnime_Update(&this->skelAnime);
-
if (this->timer <= 0) {
Actor_Kill(&this->actor);
}
}
-// Unique type functions
-
-void EnFish_Unique_SetupSwimIdle(EnFish* this) {
+void EnFish_TinyPond_SetupSwim(EnFish* this) {
this->actor.gravity = 0.0f;
this->actor.minVelocityY = 0.0f;
this->timer = Rand_S16Offset(5, 35);
- this->unk_250 = 0;
- EnFish_SetInWaterAnimation(this);
- this->actionFunc = EnFish_Unique_SwimIdle;
+ this->updBgCheckInfoFlags = 0;
+ EnFish_ChangeAnimInWater(this);
+ this->actionFunc = EnFish_TinyPond_Swim;
}
-void EnFish_Unique_SwimIdle(EnFish* this, PlayState* play) {
- static f32 speedStopping[] = { 0.0f, 0.04f, 0.09f };
- static f32 speedMoving[] = { 0.5f, 0.1f, 0.15f };
- f32 playSpeed;
- u32 frames = play->gameplayFrames;
- f32* speed;
+void EnFish_TinyPond_Swim(EnFish* this, PlayState* play) {
s32 pad2;
- f32 extraPlaySpeed;
+ u32 frames = play->gameplayFrames;
+ EnFishSpeedParams* speedParams;
s32 pad3;
+ f32 animPlaySpeedBoost;
+ s32 pad;
if (this->actor.xzDistToPlayer < 60.0f) {
if (this->timer < 12) {
- speed = speedMoving;
+ speedParams = &sMoveSpeedParams;
} else {
- speed = speedStopping;
+ speedParams = &sStaySpeedParams;
}
} else {
if (this->timer < 4) {
- speed = speedMoving;
+ speedParams = &sMoveSpeedParams;
} else {
- speed = speedStopping;
+ speedParams = &sStaySpeedParams;
}
}
-
- EnFish_SetYOffset(this);
- Math_SmoothStepToF(&this->actor.speed, speed[0], speed[1], speed[2], 0.0f);
-
- extraPlaySpeed = 0.0f;
-
- if ((EnFish_XZDistanceSquared(&this->actor.world.pos, &this->actor.home.pos) > SQ(15.0f))) {
+ EnFish_UpdateBobbingUpDown(this);
+ Math_SmoothStepToF(&this->actor.speed, speedParams->target, speedParams->fraction, speedParams->step, 0.0f);
+ animPlaySpeedBoost = 0.0f;
+ if (EnFish_DistXZSq(&this->actor.world.pos, &this->actor.home.pos) > SQ(15.0f)) {
if (!Math_ScaledStepToS(&this->actor.world.rot.y, Math_Vec3f_Yaw(&this->actor.world.pos, &this->actor.home.pos),
- 200)) {
- extraPlaySpeed = 0.5f;
+ 0xC8)) {
+ animPlaySpeedBoost = 0.5f;
+ }
+ } else if (this->timer < 4) {
+ if (!Math_ScaledStepToS(&this->actor.world.rot.y, frames * 0x80, 0x64)) {
+ animPlaySpeedBoost = 0.5f;
}
- } else if ((this->timer < 4) && !Math_ScaledStepToS(&this->actor.world.rot.y, frames * 0x80, 100)) {
- extraPlaySpeed = 0.5f;
}
-
this->actor.shape.rot.y = this->actor.world.rot.y;
- playSpeed = (this->actor.speed * 1.2f) + 0.2f + extraPlaySpeed;
- this->skelAnime.playSpeed = CLAMP(playSpeed, 1.5f, 0.5);
+ //! @bug swapped min and max clamp bounds
+ this->skelAnime.playSpeed = CLAMP((this->actor.speed * 1.2f) + 0.2f + animPlaySpeedBoost, 1.5f, 0.5);
SkelAnime_Update(&this->skelAnime);
-
if (this->timer <= 0) {
this->timer = Rand_S16Offset(5, 80);
}
}
-// Cutscene functions
-
-void EnFish_Cutscene_FlopOnGround(EnFish* this, PlayState* play) {
- f32 sp24 = Math_SinS(this->slowPhase);
- f32 sp20 = Math_SinS(this->fastPhase);
-
- D_80A17014 += D_80A17018;
-
- if (D_80A17014 <= 1.0f) {
- D_80A17014 = 1.0f;
+void EnFish_JabuCutscene_CueFlapOnGround(EnFish* this, PlayState* play) {
+ f32 sp24 = Math_SinS(this->phase1);
+ f32 sp20 = Math_SinS(this->phase2);
+ sJabuCutsceneOffsetY += sJabuCutsceneOffsetYSpeed;
+ if (sJabuCutsceneOffsetY <= 1.0f) {
+ sJabuCutsceneOffsetY = 1.0f;
if (Rand_ZeroOne() < 0.1f) {
- D_80A17018 = (Rand_ZeroOne() * 3.0f) + 2.0f;
+ sJabuCutsceneOffsetYSpeed = (Rand_ZeroOne() * 3.0f) + 2.0f;
Actor_PlaySfx(&this->actor, NA_SE_EV_FISH_LEAP);
} else {
- D_80A17018 = 0.0f;
+ sJabuCutsceneOffsetYSpeed = 0.0f;
}
} else {
- D_80A17018 -= 0.4f;
+ sJabuCutsceneOffsetYSpeed -= 0.4f;
}
-
this->skelAnime.playSpeed = ((sp24 + sp20) * 0.5f) + 2.0f;
SkelAnime_Update(&this->skelAnime);
}
-void EnFish_Cutscene_WiggleFlyingThroughAir(EnFish* this, PlayState* play) {
+void EnFish_JabuCutscene_CueFly(EnFish* this, PlayState* play) {
s32 pad;
- f32 sp28 = Math_SinS(this->slowPhase);
- f32 sp24 = Math_SinS(this->fastPhase);
+ f32 sp28 = Math_SinS(this->phase1);
+ f32 sp24 = Math_SinS(this->phase2);
- this->actor.shape.rot.x -= 500;
- this->actor.shape.rot.z += 100;
- Math_StepToF(&D_80A17014, 0.0f, 1.0f);
+ this->actor.shape.rot.x -= 0x1F4;
+ this->actor.shape.rot.z += 0x64;
+ Math_StepToF(&sJabuCutsceneOffsetY, 0.0f, 1.0f);
this->skelAnime.playSpeed = ((sp28 + sp24) * 0.5f) + 2.0f;
SkelAnime_Update(&this->skelAnime);
}
-void EnFish_UpdateCutscene(EnFish* this, PlayState* play) {
+void EnFish_JabuCutscene_Update(EnFish* this, PlayState* play) {
+ f32 factor;
s32 pad;
- s32 pad2;
CsCmdActorCue* cue = play->csCtx.actorCues[1];
Vec3f startPos;
Vec3f endPos;
- f32 lerp;
+ s32 pad2;
s32 bgId;
if (play) {}
+ if (play) {}
if (cue == NULL) {
- PRINTF(T("Warning : dousa 3 消滅 が呼ばれずにデモが終了した(%s %d)(arg_data 0x%04x)\n",
- "Warning : Demo ended without action 3 being called (%s %d)(arg_data 0x%04x)\n"),
- "../z_en_sakana.c", 1169, this->actor.params);
- EnFish_ClearCutsceneData(this);
+ if (1) {}
+ PRINTF("Warning : dousa 3 消滅 が呼ばれずにデモが終了した(%s %d)(arg_data 0x%04x)\n", "../z_en_sakana.c", 1169,
+ this->actor.params);
+ EnFish_JabuCutscene_Clear(this);
Actor_Kill(&this->actor);
return;
}
-
- this->slowPhase += 0x111;
- this->fastPhase += 0x500;
-
+ this->phase1 += 0x111;
+ this->phase2 += 0x500;
switch (cue->id) {
case 1:
- EnFish_Cutscene_FlopOnGround(this, play);
+ EnFish_JabuCutscene_CueFlapOnGround(this, play);
break;
+
case 2:
- EnFish_Cutscene_WiggleFlyingThroughAir(this, play);
+ EnFish_JabuCutscene_CueFly(this, play);
break;
+
case 3:
- PRINTF(T("デモ魚消滅\n", "Demo fish disappearance\n"));
- EnFish_ClearCutsceneData(this);
+ PRINTF("デモ魚消滅\n");
+ EnFish_JabuCutscene_Clear(this);
Actor_Kill(&this->actor);
return;
+
default:
- PRINTF(T("不正なデモ動作(%s %d)(arg_data 0x%04x)\n", "Incorrect demo behavior (%s %d)(arg_data 0x%04x)\n"),
- "../z_en_sakana.c", 1200, this->actor.params);
+ PRINTF("不正なデモ動作(%s %d)(arg_data 0x%04x)\n", "../z_en_sakana.c", 1200, this->actor.params);
break;
}
-
startPos.x = cue->startPos.x;
startPos.y = cue->startPos.y;
startPos.z = cue->startPos.z;
-
endPos.x = cue->endPos.x;
endPos.y = cue->endPos.y;
endPos.z = cue->endPos.z;
-
- lerp = Environment_LerpWeight(cue->endFrame, cue->startFrame, play->csCtx.curFrame);
-
- this->actor.world.pos.x = (endPos.x - startPos.x) * lerp + startPos.x;
- this->actor.world.pos.y = (endPos.y - startPos.y) * lerp + startPos.y + D_80A17014;
- this->actor.world.pos.z = (endPos.z - startPos.z) * lerp + startPos.z;
-
+ factor = Environment_LerpWeight(cue->endFrame, cue->startFrame, play->csCtx.curFrame);
+ this->actor.world.pos.x = ((endPos.x - startPos.x) * factor) + startPos.x;
+ this->actor.world.pos.y = ((endPos.y - startPos.y) * factor) + startPos.y + sJabuCutsceneOffsetY;
+ this->actor.world.pos.z = ((endPos.z - startPos.z) * factor) + startPos.z;
this->actor.floorHeight =
BgCheck_EntityRaycastDown4(&play->colCtx, &this->actor.floorPoly, &bgId, &this->actor, &this->actor.world.pos);
}
-// Update functions and Draw
-
-void EnFish_OrdinaryUpdate(EnFish* this, PlayState* play) {
+void EnFish_UpdateImpl(EnFish* this, PlayState* play) {
if (this->timer > 0) {
this->timer--;
}
-
- this->slowPhase += 0x111;
- this->fastPhase += 0x500;
-
- if ((this->actor.child != NULL) && (this->actor.child->update == NULL) && (&this->actor != this->actor.child)) {
+ this->phase1 += 0x111;
+ this->phase2 += 0x500;
+ if ((this->actor.child != NULL) && (this->actor.child->update == NULL) && (this->actor.child != &this->actor)) {
this->actor.child = NULL;
}
-
if ((this->actionFunc == NULL) || (this->actionFunc(this, play), (this->actor.update != NULL))) {
Actor_MoveXZGravity(&this->actor);
-
- if (this->unk_250 != 0) {
- Actor_UpdateBgCheckInfo(play, &this->actor, 17.5f, 4.0f, 0.0f, this->unk_250);
+ if (this->updBgCheckInfoFlags != 0) {
+ Actor_UpdateBgCheckInfo(play, &this->actor, 17.5f, 4.0f, 0.0f, this->updBgCheckInfoFlags);
}
-
if (this->actor.xzDistToPlayer < 70.0f) {
CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base);
}
-
Actor_SetFocus(&this->actor, this->actor.shape.yOffset * 0.01f);
-
if (Actor_HasParent(&this->actor, play)) {
this->actor.parent = NULL;
-
- if (this->actor.params == FISH_DROPPED) {
+ if (this->actor.params == EN_FISH_TYPE_DROPPED) {
Actor_Kill(&this->actor);
- return;
+ } else {
+ EnFish_Disappear(this);
}
-
- EnFish_BeginRespawn(this);
- } else if (EnFish_InBottleRange(this, play)) {
- // GI_MAX in this case allows the player to catch the actor in a bottle
+ } else if (EnFish_IsInRangeForCatch(this, play)) {
Actor_OfferGetItem(&this->actor, play, GI_MAX, 80.0f, 20.0f);
}
}
}
-void EnFish_RespawningUpdate(EnFish* this, PlayState* play) {
- if (this->actor.params == FISH_SWIMMING_UNIQUE) {
+void EnFish_UpdateWaitReappear(EnFish* this, PlayState* play) {
+ f32 scale;
+
+ if (this->actor.params == EN_FISH_TYPE_TINY_POND) {
Actor_Kill(&this->actor);
return;
}
-
- if ((this->actor.child != NULL) && (this->actor.child->update == NULL) && (&this->actor != this->actor.child)) {
+ if ((this->actor.child != NULL) && (this->actor.child->update == NULL) && (this->actor.child != &this->actor)) {
this->actor.child = NULL;
}
-
+ // Note the actionFunc keeps running and the fish keeps moving
+ // in this state where the fish has disappeared (is invisible)
if ((this->actionFunc == NULL) || (this->actionFunc(this, play), (this->actor.update != NULL))) {
Actor_MoveXZGravity(&this->actor);
-
- if (this->respawnTimer == 20) {
+ if (this->reappearTimer == 20) {
this->actor.draw = EnFish_Draw;
- } else if (this->respawnTimer == 0) {
+ } else if (this->reappearTimer == 0) {
Actor_SetScale(&this->actor, 0.01f);
- } else if (this->respawnTimer < 20) {
- Actor_SetScale(&this->actor, CLAMP_MAX(this->actor.scale.x + 0.001f, 0.01f));
+ } else if (this->reappearTimer < 20) {
+ scale = CLAMP_MAX(this->actor.scale.x + 0.001f, 0.01f);
+ Actor_SetScale(&this->actor, scale);
}
}
}
@@ -759,18 +696,19 @@ void EnFish_RespawningUpdate(EnFish* this, PlayState* play) {
void EnFish_Update(Actor* thisx, PlayState* play) {
EnFish* this = (EnFish*)thisx;
- if ((D_80A17010 == NULL) && (this->actor.params == FISH_DROPPED) && (play->csCtx.state != CS_STATE_IDLE) &&
- (play->csCtx.actorCues[1] != NULL)) {
- EnFish_SetCutsceneData(this);
- }
-
- if ((D_80A17010 != NULL) && (&this->actor == D_80A17010)) {
- EnFish_UpdateCutscene(this, play);
- } else if (this->respawnTimer > 0) {
- this->respawnTimer--;
- EnFish_RespawningUpdate(this, play);
+ //! @bug The cutscene stuff is meant for the "give a fish to Jabu" cutscene,
+ //! but there is no e.g. scene check so the fish can react to other cutscenes too
+ if ((sJabuCutsceneFish == NULL) && (this->actor.params == EN_FISH_TYPE_DROPPED) &&
+ (play->csCtx.state != CS_STATE_IDLE) && (play->csCtx.actorCues[1] != NULL)) {
+ EnFish_JabuCutscene_Enter(this);
+ }
+ if ((sJabuCutsceneFish != NULL) && (sJabuCutsceneFish == this)) {
+ EnFish_JabuCutscene_Update(this, play);
+ } else if (this->reappearTimer > 0) {
+ this->reappearTimer--;
+ EnFish_UpdateWaitReappear(this, play);
} else {
- EnFish_OrdinaryUpdate(this, play);
+ EnFish_UpdateImpl(this, play);
}
}
diff --git a/src/overlays/actors/ovl_En_Fish/z_en_fish.h b/src/overlays/actors/ovl_En_Fish/z_en_fish.h
index 8019ff06c..016ce1fa3 100644
--- a/src/overlays/actors/ovl_En_Fish/z_en_fish.h
+++ b/src/overlays/actors/ovl_En_Fish/z_en_fish.h
@@ -4,29 +4,29 @@
#include "ultra64.h"
#include "actor.h"
+typedef enum EnFishType {
+ EN_FISH_TYPE_NORMAL = -1, // Typically ObjMure-handled (also used in some Zora's fountain cutscene layers)
+ EN_FISH_TYPE_DROPPED, // Dropped by the player
+ EN_FISH_TYPE_TINY_POND // Used in grottos, the fish doesn't reappear
+} EnFishType;
+
struct EnFish;
typedef void (*EnFishActionFunc)(struct EnFish*, struct PlayState*);
typedef struct EnFish {
- /* 0x0000 */ Actor actor;
- /* 0x014C */ ColliderJntSph collider;
- /* 0x016C */ ColliderJntSphElement colliderElements[1];
- /* 0x01AC */ SkelAnime skelAnime;
- /* 0x01F0 */ Vec3s jointTable[7];
- /* 0x021A */ Vec3s morphTable[7];
- /* 0x0244 */ EnFishActionFunc actionFunc;
- /* 0x0248 */ s16 timer;
- /* 0x024A */ s16 respawnTimer;
- /* 0x024C */ s16 slowPhase;
- /* 0x024E */ s16 fastPhase;
- /* 0x0250 */ s32 unk_250; // Set to 0 or 5, arg5 of Actor_UpdateBgCheckInfo
-} EnFish; // size = 0x0254
-
-typedef enum EnFishType {
- /* -1 */ FISH_SWIMMING_RESPAWNING = -1, // Used in Zora's Domain; code only uses not 0 or 1, runs away from Player
- /* 0 */ FISH_DROPPED,
- /* 1 */ FISH_SWIMMING_UNIQUE // Used in grottos
-} EnFishType;
+ /* 0x000 */ Actor actor;
+ /* 0x14C */ ColliderJntSph collider;
+ /* 0x16C */ ColliderJntSphElement colliderElements[1];
+ /* 0x1AC */ SkelAnime skelAnime;
+ /* 0x1F0 */ Vec3s jointTable[7];
+ /* 0x21A */ Vec3s morphTable[7];
+ /* 0x244 */ EnFishActionFunc actionFunc;
+ /* 0x248 */ s16 timer;
+ /* 0x24A */ s16 reappearTimer;
+ /* 0x24C */ s16 phase1;
+ /* 0x24E */ s16 phase2;
+ /* 0x250 */ s32 updBgCheckInfoFlags;
+} EnFish; // size = 0x254
#endif
diff --git a/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c b/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c
index 238bf69cf..079660453 100644
--- a/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c
+++ b/src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c
@@ -5,6 +5,7 @@
*/
#include "z_obj_mure.h"
+#include "overlays/actors/ovl_En_Fish/z_en_fish.h"
#include "overlays/actors/ovl_En_Insect/z_en_insect.h"
#include "libc64/qrand.h"
@@ -57,7 +58,7 @@ static s32 sMaxChildSpawns[] = { 12, 9, 8, 0 };
static s16 sSpawnActorIds[] = { ACTOR_EN_KUSA, 0, ACTOR_EN_FISH, ACTOR_EN_INSECT, ACTOR_EN_BUTTE };
-static s16 sSpawnParams[] = { 0, 2, -1, INSECT_TYPE_PERMANENT, -1 };
+static s16 sSpawnParams[] = { 0, 2, EN_FISH_TYPE_NORMAL, INSECT_TYPE_PERMANENT, -1 };
static InitChainEntry sInitChain[] = {
ICHAIN_F32(cullingVolumeDistance, 1200, ICHAIN_CONTINUE),
diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c
index 84dd1e6f5..812a502f6 100644
--- a/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/src/overlays/actors/ovl_player_actor/z_player.c
@@ -14147,7 +14147,7 @@ void Player_Action_8084EED8(Player* this, PlayState* play) {
}
static BottleDropInfo D_80854A28[] = {
- { ACTOR_EN_FISH, FISH_DROPPED },
+ { ACTOR_EN_FISH, EN_FISH_TYPE_DROPPED },
{ ACTOR_EN_ICE_HONO, 0 },
{ ACTOR_EN_INSECT, INSECT_TYPE_FIRST_DROPPED },
};