From 7dbd31ab0b5b8db369b96ae17a0a0b01ada328ea Mon Sep 17 00:00:00 2001 From: Dragorn421 Date: Mon, 31 Aug 2026 18:22:17 +0200 Subject: [PATCH] [cc0 oot] EnFish (#2792) * [cc0 oot] EnFish * bring changes to external files * EnFish actionFunc typedef * EnFish move variable assigns into decls * format --- src/overlays/actors/ovl_En_Fish/z_en_fish.c | 650 ++++++++---------- src/overlays/actors/ovl_En_Fish/z_en_fish.h | 38 +- src/overlays/actors/ovl_Obj_Mure/z_obj_mure.c | 3 +- .../actors/ovl_player_actor/z_player.c | 2 +- 4 files changed, 316 insertions(+), 377 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 f1efbfa080..46377e3f6a 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); +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); -// Used in the cutscene functions -static Actor* D_80A17010 = NULL; -static f32 D_80A17014 = 0.0f; -static f32 D_80A17018 = 0.0f; +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); + //! @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 ((D_80A17010 != NULL) && (&this->actor == D_80A17010)) { - EnFish_UpdateCutscene(this, play); - } else if (this->respawnTimer > 0) { - this->respawnTimer--; - EnFish_RespawningUpdate(this, play); + 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 8019ff06cb..016ce1fa38 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 238bf69cf6..079660453a 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 84dd1e6f52..812a502f66 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 }, };