diff options
| author | engineer124 <47598039+engineer124@users.noreply.github.com> | 2021-02-03 07:17:51 +1100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-02-02 15:17:51 -0500 |
| commit | cce6880bc043086e41e34bc2abdf1790a06b9d66 (patch) | |
| tree | 203a99f4befcb6ac265183ff144e8a85a3067be6 /src | |
| parent | d1a9775926efbc1564fa0a974ef8ad695ce25fa4 (diff) | |
En_Fr Frogs 47 of 48 func decomped (#576)
* En_Fr 47 of 48 func decomped
* EnFr more cleanup
* uncommented out EnFr_Update
* more cleanup
* added format document
* Update src/overlays/actors/ovl_En_Fr/z_en_fr.c
Null Pointers
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
* Update src/overlays/actors/ovl_En_Fr/z_en_fr.c
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
* Update src/overlays/actors/ovl_En_Fr/z_en_fr.c
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
* Update src/overlays/actors/ovl_En_Fr/z_en_fr.c
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
* Update src/overlays/actors/ovl_En_Fr/z_en_fr.c
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
* Update src/overlays/actors/ovl_En_Fr/z_en_fr.c
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
* Update src/overlays/actors/ovl_En_Fr/z_en_fr.c
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
* Update src/overlays/actors/ovl_En_Fr/z_en_fr.c
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
* feedback from pr
* more cleanup
* more pr feedback
* more cleaning and updates
* remove data.s
* review 2
* review
* missed one
Co-authored-by: petrie911 <69443847+petrie911@users.noreply.github.com>
Co-authored-by: fig <fig02srl@gmail.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/overlays/actors/ovl_En_Fr/z_en_fr.c | 1082 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_En_Fr/z_en_fr.h | 60 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c | 2 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c | 2 |
4 files changed, 1089 insertions, 57 deletions
diff --git a/src/overlays/actors/ovl_En_Fr/z_en_fr.c b/src/overlays/actors/ovl_En_Fr/z_en_fr.c index 4253a7a94..55d15145e 100644 --- a/src/overlays/actors/ovl_En_Fr/z_en_fr.c +++ b/src/overlays/actors/ovl_En_Fr/z_en_fr.c @@ -1,4 +1,5 @@ #include "z_en_fr.h" +#include "vt.h" #define FLAGS 0x02000019 @@ -7,15 +8,125 @@ void EnFr_Init(Actor* thisx, GlobalContext* globalCtx); void EnFr_Destroy(Actor* thisx, GlobalContext* globalCtx); void EnFr_Update(Actor* thisx, GlobalContext* globalCtx); +void EnFr_UpdateIdle(Actor* thisx, GlobalContext* globalCtx); +void EnFr_UpdateActive(Actor* thisx, GlobalContext* globalCtx); +void EnFr_Draw(Actor* thisx, GlobalContext* globalCtx); -extern UNK_TYPE D_05002470; -extern UNK_TYPE D_050036F0; -extern UNK_TYPE D_060007BC; -extern UNK_TYPE D_060011C0; -extern UNK_TYPE D_06001534; -extern UNK_TYPE D_0600B498; +// Animation Functions +void EnFr_SetupJumpingOutOfWater(EnFr* this, GlobalContext* globalCtx); +void EnFr_JumpingOutOfWater(EnFr* this, GlobalContext* globalCtx); +void EnFr_OrientOnLogSpot(EnFr* this, GlobalContext* globalCtx); +void EnFr_ChooseJumpFromLogSpot(EnFr* this, GlobalContext* globalCtx); +void EnFr_JumpingUp(EnFr* this, GlobalContext* globalCtx); +void EnFr_JumpingBackIntoWater(EnFr* this, GlobalContext* globalCtx); +void EnFr_DecrementBlinkTimerUpdate(EnFr* this); + +// Activation +void EnFr_Idle(EnFr* this, GlobalContext* globalCtx); +void EnFr_Activate(EnFr* this, GlobalContext* globalCtx); +void EnFr_ActivateCheckFrogSong(EnFr* this, GlobalContext* globalCtx); + +// Listening for Child Songs +void func_80A1BE98(EnFr* this, GlobalContext* globalCtx); +void EnFr_ListeningToOcarinaNotes(EnFr* this, GlobalContext* globalCtx); +void EnFr_ChildSong(EnFr* this, GlobalContext* globalCtx); +void EnFr_ChildSongFirstTime(EnFr* this, GlobalContext* globalCtx); + +// Frog Song for HP Functions +void EnFr_TalkBeforeFrogSong(EnFr* this, GlobalContext* globalCtx); +void EnFr_SetupFrogSong(EnFr* this, GlobalContext* globalCtx); +void EnFr_ContinueFrogSong(EnFr* this, GlobalContext* globalCtx); +void EnFr_OcarinaMistake(EnFr* this, GlobalContext* globalCtx); + +// Reward Functions +void EnFr_SetupReward(EnFr* this, GlobalContext* globalCtx, u8 unkCondition); +void EnFr_PrintTextBox(EnFr* this, GlobalContext* globalCtx); +void EnFr_TalkBeforeReward(EnFr* this, GlobalContext* globalCtx); +void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx); + +// Deactivate +void EnFr_Deactivate(EnFr* this, GlobalContext* globalCtx); +void EnFr_GiveReward(EnFr* this, GlobalContext* globalCtx); +void EnFr_SetIdle(EnFr* this, GlobalContext* globalCtx); + +extern FlexSkeletonHeader D_0600B498; // Frog +extern AnimationHeader D_06001534; // Frog +extern SkeletonHeader D_050036F0; // Butterfly +extern AnimationHeader D_05002470; // Butterfly +extern AnimationHeader D_060007BC; // Frog Jumping +extern AnimationHeader D_060011C0; // Frog Landing /* +Frogs params WIP docs + +Represents 6 Actor Instances for frogs: + - 1 Prop actor instance set to where Link plays Ocarina, manages 5 frogs + - 5 NPC actor instances for the frogs themselves + +0: Prop Actor Instance (located where link detects ocarina, interacts with Link) +1: Frog 0 (Yellow) +2: Frog 1 (Blue) +3: Frog 2 (Red) +4: Frog 3 (Purple) +5: Frog 4 (White) + +Note that because of the Prop Actor, actor.params is 1 shifted from frogIndex +Therefore, frogIndex = actor.params - 1 + + +sEnFrPointers.flags = 1 + - Activate frogs, frogs will jump out of the water + +sEnFrPointers.flags = 1 to 11: + - Counter: Frogs will sequentially jump out based on counter: + - 1: Frog 1 (Blue) + - 3: frog 3 (Purple) + - 5: frog 0 (Yellow) + - 7: frog 2 (Red) + - 9: frog 4 (White) + - Will proceed when counter reachers 11 + +sEnFrPointers.flags = 12 + - Deactivate frogs, frogs will jump back into the water +*/ + +typedef struct { + u8 flags; + EnFr* frogs[5]; +} EnFrPointers; + +typedef struct { + f32 xzDist; + f32 yaw; + f32 yDist; +} LogSpotToFromWater; + +EnFrPointers sEnFrPointers = { + 0x00, + { + NULL, + NULL, + NULL, + NULL, + NULL, + }, +}; + +// Flags for gSaveContext.eventChkInf[13] +u16 sSongIndex[] = { + 0x0002, 0x0004, 0x0010, 0x0008, 0x0020, 0x0040, 0x0001, 0x0000, +}; + +// Frog to Index for Song Flag (sSongIndex) Mapping +u8 sFrogToSongIndex[] = { + FROG_SARIA, FROG_SUNS, FROG_SOT, FROG_ZL, FROG_EPONA, +}; + +// Song to Frog Index Mapping +static s32 sSongToFrog[] = { + FROG_PURPLE, FROG_WHITE, FROG_YELLOW, FROG_BLUE, FROG_RED, +}; + const ActorInit En_Fr_InitVars = { ACTOR_EN_FR, ACTORCAT_NPC, @@ -27,99 +138,962 @@ const ActorInit En_Fr_InitVars = { (ActorFunc)EnFr_Update, NULL, }; -*/ -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1A9A0.s") -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/EnFr_Init.s") +static Color_RGBA8 sEnFrColor[] = { + { 200, 170, 0, 255 }, { 0, 170, 200, 255 }, { 210, 120, 100, 255 }, { 120, 130, 230, 255 }, { 190, 190, 190, 255 }, +}; + +// Jumping back into water frog animation +// sLogSpotToFromWater[frog].xzDist is magnitude of xz distance frog travels +// sLogSpotToFromWater[frog].yaw is rot around y-axis of jumping back into water +// sLogSpotToFromWater[frog].yDist is change in y distance frog travels +static LogSpotToFromWater sLogSpotToFromWater[] = { + { 0.0f, 0.0f, 0.0f }, // Prop (Where link pulls ocarina) + { 80.0f, -0.375f * M_PI, -80.0f }, // FROG_YELLOW + { 80.0f, -0.5f * M_PI, -80.0f }, // FROG_BLUE + { 80.0f, -0.25f * M_PI, -80.0f }, // FROG_RED + { 80.0f, 0.875f * M_PI, -80.0f }, // FROG_PURPLE + { 80.0f, 0.5f * M_PI, -80.0f }, // FROG_WHITE +}; + +// Timer values for the frog choir song +static s16 sTimerFrogSong[] = { + 40, 20, 15, 12, 12, +}; + +// static InitChainEntry sInitChain[] +InitChainEntry D_80A1D0BC[] = { + ICHAIN_U8(targetMode, 2, ICHAIN_CONTINUE), + ICHAIN_F32(targetArrowOffset, 30, ICHAIN_STOP), +}; + +// Counter to Coordinate Frog jumping out of water one at a time +// Used as part of sEnFrPointers.flags +static u8 sTimerJumpingOutOfWater[] = { + 5, 1, 7, 3, 9, +}; + +// targetScale (default = 150.0) Actor scale target for Math_ApproachF +// Used as a frog grows from hearing a new child song +static f32 sGrowingScale[] = { + 180.0f, + 210.0f, + 240.0f, + 270.0f, +}; + +static u8 sPitchSmallFrog[] = { + 5, // C-Down Ocarina + 2, // A Button Ocarina + 9, // C-Right Ocarina + 11, // C-Left Ocarina + 14, // C Up Ocarina +}; + +static s8 sPitchLargeFrog[] = { + -7, // C-Down Ocarina + -10, // A Button Ocarina + -3, // C-Right Ocarina + -1, // C-Left Ocarina + 2, // C Up Ocarina +}; + +static u8 sJumpOrder[] = { + FROG_BLUE, FROG_YELLOW, FROG_RED, FROG_PURPLE, FROG_WHITE, FROG_BLUE, FROG_YELLOW, FROG_RED, +}; + +// probably can be replaced with a message context enum at a later time +// A, CDOWN, CRIGHT, CLEFT, CUP +static u8 sOcarinaNotes[] = { + 0, 1, 2, 3, 4, +}; + +void EnFr_OrientUnderwater(EnFr* this) { + Vec3f vec1; + Vec3f vec2; + + vec1.x = vec1.y = 0.0f; + vec1.z = this->xzDistToLogSpot = sLogSpotToFromWater[this->actor.params].xzDist; + Matrix_RotateY(sLogSpotToFromWater[this->actor.params].yaw, MTXMODE_NEW); + Matrix_MultVec3f(&vec1, &vec2); + this->actor.world.pos.x = this->posLogSpot.x + vec2.x; + this->actor.world.pos.z = this->posLogSpot.z + vec2.z; + this->actor.world.pos.y = sLogSpotToFromWater[this->actor.params].yDist + this->posLogSpot.y; + this->actor.world.rot.y = this->actor.shape.rot.y = + (s16)(sLogSpotToFromWater[this->actor.params].yaw * ((f32)0x8000 / M_PI)) + 0x8000; + this->actor.speedXZ = 0.0f; + this->actor.velocity.y = 0.0f; + this->actor.gravity = 0.0f; +} + +void EnFr_Init(Actor* thisx, GlobalContext* globalCtx) { + EnFr* this = THIS; + + if (this->actor.params == 0) { + this->actor.destroy = NULL; + this->actor.draw = NULL; + this->actor.update = EnFr_UpdateIdle; + this->actor.flags = this->actor.flags &= ~0x11; + Actor_ChangeCategory(globalCtx, &globalCtx->actorCtx, &this->actor, ACTORCAT_PROP); + this->actor.textId = 0x40AC; + this->actionFunc = EnFr_Idle; + } else { + if ((this->actor.params >= 6) || (this->actor.params < 0)) { + osSyncPrintf(VT_COL(RED, WHITE)); + // Translation: The argument is wrong!! + osSyncPrintf("%s[%d] : 引数が間違っている!!(%d)\n", "../z_en_fr.c", 370, this->actor.params); + osSyncPrintf(VT_RST); + __assert("0", "../z_en_fr.c", 372); + } + + this->objBankIndex = Object_GetIndex(&globalCtx->objectCtx, OBJECT_GAMEPLAY_FIELD_KEEP); + if (this->objBankIndex < 0) { + Actor_Kill(&this->actor); + osSyncPrintf(VT_COL(RED, WHITE)); + // Translation: There is no bank!! + osSyncPrintf("%s[%d] : バンクが無いよ!!\n", "../z_en_fr.c", 380); + osSyncPrintf(VT_RST); + __assert("0", "../z_en_fr.c", 382); + } + } +} + +// Draw only the purple frog when ocarina is not pulled out on the log spot +void EnFr_DrawIdle(EnFr* this) { + this->actor.draw = (this->actor.params - 1) != FROG_PURPLE ? NULL : EnFr_Draw; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1AC0C.s") +void EnFr_DrawActive(EnFr* this) { + this->actor.draw = EnFr_Draw; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1AC34.s") +// Down to regalloc +#ifdef NON_MATCHING +void EnFr_Update(Actor* thisx, GlobalContext* globalCtx) { + EnFr* this = THIS; + LightInfo* lightInfo; + s32 frogIndex; + s16 randomNumber; + if (Object_IsLoaded(&globalCtx->objectCtx, this->objBankIndex)) { + this->actor.flags &= ~0x10; + frogIndex = this->actor.params - 1; + sEnFrPointers.frogs[frogIndex] = this; + Actor_ProcessInitChain(&this->actor, D_80A1D0BC); + // frog + SkelAnime_InitFlex(globalCtx, &this->skelAnime, &D_0600B498, &D_06001534, this->jointTable, this->morphTable, + 24); + // butterfly + SkelAnime_Init(globalCtx, &this->skelAnimeButterfly, &D_050036F0, &D_05002470, this->jointTableButterfly, + this->morphTableButterfly, 8); + // When playing the frogs song for the HP, + // the frog with the next note and the butterfly + // turns on its lightsource + lightInfo = &this->lightInfo; + this->lightNode = LightContext_InsertLight(globalCtx, &globalCtx->lightCtx, lightInfo); + Lights_PointNoGlowSetInfo(lightInfo, this->actor.home.pos.x, this->actor.home.pos.y, this->actor.home.pos.z, + 255, 255, 255, -1); + // Check to see if the song for a particular frog has been played. + // If it has, the frog is larger. If not, the frog is smaller + this->scale = gSaveContext.eventChkInf[13] & sSongIndex[sFrogToSongIndex[frogIndex]] ? 270.0f : 150.0f; + // When the frogs are not active (link doesn't have his ocarina out), + // Then shrink the frogs down by a factor of 10,000 + Actor_SetScale(&this->actor, this->scale * 0.0001f); + this->actor.minVelocityY = -9999.0f; + Actor_SetFocus(&this->actor, 10.0f); + this->eyeTexIndex = 1; + this->blinkTimer = (s16)(Rand_ZeroFloat(60.0f) + 20.0f); + this->blinkFunc = EnFr_DecrementBlinkTimerUpdate; + + // regalloc issues here + this->isBelowWaterSurfaceCurrent = false; + this->isBelowWaterSurfacePrevious = false; + this->isJumpingUp = false; + this->actionFunc = EnFr_SetupJumpingOutOfWater; + this->posLogSpot = this->actor.world.pos; + this->isDeactivating = false; + this->growingScaleIndex = 0; + this->isActive = false; + this->isJumpingToFrogSong = false; + this->songIndex = FROG_NO_SONG; + this->unusedButterflyActor = NULL; + EnFr_OrientUnderwater(this); + EnFr_DrawIdle(this); + this->actor.update = EnFr_UpdateActive; + this->isButterflyDrawn = false; + this->xyAngleButterfly = 0x1000 * (s16)Rand_ZeroFloat(255.0f); + this->posButterflyLight.x = this->posButterfly.x = this->posLogSpot.x; + this->posButterflyLight.y = this->posButterfly.y = this->posLogSpot.y + 50.0f; + this->posButterflyLight.z = this->posButterfly.z = this->posLogSpot.z; + this->actor.flags &= ~1; + } +} +#else #pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/EnFr_Update.s") +#endif + +void EnFr_Destroy(Actor* thisx, GlobalContext* globalCtx) { + EnFr* this = THIS; + + LightContext_RemoveLight(globalCtx, &globalCtx->lightCtx, this->lightNode); +} + +void EnFr_IsDivingIntoWater(EnFr* this, GlobalContext* globalCtx) { + WaterBox* waterBox; + f32 waterSurface; + + if (WaterBox_GetSurfaceImpl(globalCtx, &globalCtx->colCtx, this->actor.world.pos.x, this->actor.world.pos.z, + &waterSurface, &waterBox)) { + this->isBelowWaterSurfacePrevious = this->isBelowWaterSurfaceCurrent; + this->isBelowWaterSurfaceCurrent = this->actor.world.pos.y <= waterSurface ? true : false; + } +} + +void EnFr_DivingIntoWater(EnFr* this, GlobalContext* globalCtx) { + Vec3f vec; + + // Jumping into or out of water + if (this->isBelowWaterSurfaceCurrent != this->isBelowWaterSurfacePrevious) { + vec.x = this->actor.world.pos.x; + vec.y = this->actor.world.pos.y - 10.0f; + vec.z = this->actor.world.pos.z; + EffectSsGSplash_Spawn(globalCtx, &vec, NULL, NULL, 1, 1); + + if (this->isBelowWaterSurfaceCurrent == false) { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_DIVE_INTO_WATER_L); + } else { + Audio_PlayActorSound2(&this->actor, NA_SE_EV_BOMB_DROP_WATER); + } + } +} + +s32 EnFr_IsBelowLogSpot(EnFr* this, f32* yDistToLogSpot) { + yDistToLogSpot[0] = this->actor.world.pos.y - this->posLogSpot.y; + if ((this->actor.velocity.y < 0.0f) && (yDistToLogSpot[0] <= 0.0f)) { + this->actor.velocity.y = 0.0f; + this->actor.world.pos.y = this->posLogSpot.y; + return true; + } else { + return false; + } +} + +s32 EnFr_IsAboveAndWithin30DistXZ(Player* player, EnFr* this) { + f32 xDistToPlayer = player->actor.world.pos.x - this->actor.world.pos.x; + f32 zDistToPlayer = player->actor.world.pos.z - this->actor.world.pos.z; + f32 yDistToPlayer = player->actor.world.pos.y - this->actor.world.pos.y; + + return ((SQ(xDistToPlayer) + SQ(zDistToPlayer)) <= SQ(30.0f)) && (yDistToPlayer >= 0.0f); +} + +void EnFr_DecrementBlinkTimer(EnFr* this) { + if (this->blinkTimer != 0) { + this->blinkTimer--; + } else { + this->blinkFunc = EnFr_DecrementBlinkTimerUpdate; + } +} + +void EnFr_DecrementBlinkTimerUpdate(EnFr* this) { + if (this->blinkTimer != 0) { + this->blinkTimer--; + } else if (this->eyeTexIndex) { + this->eyeTexIndex = 0; + this->blinkTimer = (s16)(Rand_ZeroFloat(60.0f) + 20.0f); + this->blinkFunc = EnFr_DecrementBlinkTimer; + } else { + this->eyeTexIndex = 1; + this->blinkTimer = 1; + } +} + +void EnFr_SetupJumpingOutOfWater(EnFr* this, GlobalContext* globalCtx) { + if (sEnFrPointers.flags == sTimerJumpingOutOfWater[this->actor.params - 1]) { + Animation_Change(&this->skelAnime, &D_060007BC, 1.0f, 0.0f, Animation_GetLastFrame(&D_060007BC), 2, 0.0f); + EnFr_DrawActive(this); + this->actionFunc = EnFr_JumpingOutOfWater; + } +} + +void EnFr_JumpingOutOfWater(EnFr* this, GlobalContext* globalCtx) { + Vec3f vec1; + Vec3f vec2; + + if (this->skelAnime.curFrame == 6.0f) { + sEnFrPointers.flags++; + this->skelAnime.playSpeed = 0.0f; + } else if (this->skelAnime.curFrame == 3.0f) { + this->actor.gravity = -10.0f; + this->actor.speedXZ = 0.0f; + this->actor.velocity.y = 47.0f; + } + + vec1.x = vec1.y = 0.0f; + vec1.z = this->xzDistToLogSpot; + Matrix_RotateY(((this->actor.world.rot.y + 0x8000) / (f32)0x8000) * M_PI, MTXMODE_NEW); + Matrix_MultVec3f(&vec1, &vec2); + this->actor.world.pos.x = this->posLogSpot.x + vec2.x; + this->actor.world.pos.z = this->posLogSpot.z + vec2.z; + if (this->skelAnime.curFrame >= 3.0f) { + Math_ApproachF(&this->xzDistToLogSpot, 0.0f, 1.0f, 10.0f); + } + + if (EnFr_IsBelowLogSpot(this, &vec2.y)) { + this->actor.gravity = 0.0f; + this->actionFunc = EnFr_OrientOnLogSpot; + this->unusedFloat = 0.0f; + } + + if ((this->actor.velocity.y <= 0.0f) && (vec2.y < 40.0f)) { + this->skelAnime.playSpeed = 1.0f; + } +} + +void EnFr_OrientOnLogSpot(EnFr* this, GlobalContext* globalCtx) { + s16 rotYRemaining = Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 10000, 100); + + this->actor.world.rot.y = this->actor.shape.rot.y; + + if ((rotYRemaining == 0) && (this->skelAnime.curFrame == this->skelAnime.endFrame)) { + sEnFrPointers.flags++; + this->actionFunc = EnFr_ChooseJumpFromLogSpot; + Animation_Change(&this->skelAnime, &D_06001534, 1.0f, 0.0f, Animation_GetLastFrame(&D_06001534), 0, 0.0f); + } +} + +void EnFr_ChooseJumpFromLogSpot(EnFr* this, GlobalContext* globalCtx) { + if (sEnFrPointers.flags == 12) { + this->actor.world.rot.y = ((f32)0x8000 / M_PI) * sLogSpotToFromWater[this->actor.params].yaw; + Animation_Change(&this->skelAnime, &D_060007BC, 1.0f, 0.0f, Animation_GetLastFrame(&D_060007BC), 2, 0.0f); + this->actionFunc = EnFr_JumpingBackIntoWater; + } else if (this->isJumpingUp) { + Animation_Change(&this->skelAnime, &D_060007BC, 1.0f, 0.0f, Animation_GetLastFrame(&D_060007BC), 2, 0.0f); + this->actionFunc = EnFr_JumpingUp; + } +} + +void EnFr_JumpingUp(EnFr* this, GlobalContext* globalCtx) { + f32 yDistToLogSpot; + + if (this->skelAnime.curFrame == 6.0f) { + this->skelAnime.playSpeed = 0.0f; + } else if (this->skelAnime.curFrame == 3.0f) { + this->actor.gravity = -10.0f; + this->actor.velocity.y = 25.0f; + if (this->isJumpingToFrogSong) { + this->isJumpingToFrogSong = false; + Audio_PlayActorSound2(&this->actor, NA_SE_EN_DODO_M_EAT); + } + } + + if (EnFr_IsBelowLogSpot(this, &yDistToLogSpot)) { + this->isJumpingUp = false; + this->actor.gravity = 0.0f; + Animation_Change(&this->skelAnime, &D_060011C0, 1.0f, 0.0f, Animation_GetLastFrame(&D_060011C0), 0, 0.0f); + this->actionFunc = EnFr_ChooseJumpFromLogSpot; + } else if ((this->actor.velocity.y <= 0.0f) && (yDistToLogSpot < 40.0f)) { + this->skelAnime.playSpeed = 1.0f; + } +} + +void EnFr_JumpingBackIntoWater(EnFr* this, GlobalContext* globalCtx) { + f32 yUnderwater = sLogSpotToFromWater[this->actor.params].yDist + this->posLogSpot.y; + + Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.world.rot.y, 2, 10000, 100); + if (this->skelAnime.curFrame == 6.0f) { + this->skelAnime.playSpeed = 0.0f; + } else if (this->skelAnime.curFrame == 3.0f) { + this->actor.speedXZ = 6.0f; + this->actor.gravity = -10.0f; + this->actor.velocity.y = 25.0f; + } + + // Final Spot Reached + if ((this->actor.velocity.y < 0.0f) && (this->actor.world.pos.y < yUnderwater)) { + Animation_Change(&this->skelAnime, &D_06001534, 1.0f, 0.0f, Animation_GetLastFrame(&D_06001534), 0, 0.0f); + this->actionFunc = EnFr_SetupJumpingOutOfWater; + EnFr_DrawIdle(this); + this->isDeactivating = true; + EnFr_OrientUnderwater(this); + } +} + +void EnFr_SetScaleActive(EnFr* this, GlobalContext* globalCtx) { + switch (this->isGrowing) { + case false: + Math_ApproachF(&this->scale, sGrowingScale[this->growingScaleIndex], 2.0f, 25.0f); + if (this->scale >= sGrowingScale[this->growingScaleIndex]) { + this->scale = sGrowingScale[this->growingScaleIndex]; + if (this->growingScaleIndex < 3) { + this->isGrowing = true; + } else { + this->isJumpingUp = false; + this->isActive = false; + } + } + break; + case true: + Math_ApproachF(&this->scale, 150.0f, 2.0f, 25.0f); + if (this->scale <= 150.0f) { + this->scale = 150.0f; + this->growingScaleIndex++; + if (this->growingScaleIndex >= 4) { + this->growingScaleIndex = 3; + } + this->isGrowing = false; + } + break; + } +} + +void EnFr_ButterflyPath(EnFr* this, GlobalContext* globalCtx) { + s16 rotY = this->actor.shape.rot.y; + f32 sin; + Vec3f vec1; + Vec3f vec2; + + this->xyAngleButterfly += 0x1000; + Matrix_Translate(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, MTXMODE_NEW); + Matrix_RotateRPY(this->actor.world.rot.x, this->actor.world.rot.y, this->actor.world.rot.z, MTXMODE_APPLY); + vec1.x = vec1.y = 0.0f; + vec1.z = 25.0f; + Matrix_MultVec3f(&vec1, &vec2); + sin = Math_SinS(this->xyAngleButterfly * 2) * 5.0f; + this->posButterfly.x = (Math_SinS(rotY) * sin) + vec2.x; + this->posButterfly.y = (2.0f * Math_CosS(this->xyAngleButterfly)) + (this->posLogSpot.y + 50.0f); + this->posButterfly.z = (Math_CosS(rotY) * sin) + vec2.z; + Matrix_Translate(this->posButterfly.x, this->posButterfly.y, this->posButterfly.z, MTXMODE_NEW); + Matrix_RotateRPY(this->actor.world.rot.x, this->actor.world.rot.y, this->actor.world.rot.z, MTXMODE_APPLY); + vec1.x = 0.0f; + vec1.y = -15.0f; + vec1.z = 20.0f; + Matrix_MultVec3f(&vec1, &this->posButterflyLight); +} + +void EnFr_UpdateActive(Actor* thisx, GlobalContext* globalCtx) { + EnFr* this = THIS; + + this->jumpCounter++; + Actor_SetScale(&this->actor, this->scale * 0.0001f); + + if (this->isActive) { + EnFr_SetScaleActive(this, globalCtx); + } else { + Actor_SetFocus(&this->actor, 10.0f); + this->blinkFunc(this); + this->actionFunc(this, globalCtx); + EnFr_IsDivingIntoWater(this, globalCtx); + EnFr_DivingIntoWater(this, globalCtx); + SkelAnime_Update(&this->skelAnime); + SkelAnime_Update(&this->skelAnimeButterfly); + EnFr_ButterflyPath(this, globalCtx); + Actor_MoveForward(&this->actor); + } +} + +s32 EnFr_SetupJumpingUp(EnFr* this, s32 frogIndex) { + EnFr* frog = sEnFrPointers.frogs[frogIndex]; + u8 audioPitch; + + if (frog != NULL && frog->isJumpingUp == false) { + audioPitch = frog->growingScaleIndex == 3 ? sPitchLargeFrog[frogIndex] : sPitchSmallFrog[frogIndex]; + if (this->songIndex == FROG_CHOIR_SONG) { + frog->isJumpingToFrogSong = true; + } + frog->isJumpingUp = true; + func_800F4BF4(&frog->actor.projectedPos, NA_SE_EV_FROG_JUMP, (s8)audioPitch); + return true; + } else { + return false; + } +} + +void EnFr_Idle(EnFr* this, GlobalContext* globalCtx) { + Player* player = PLAYER; + + if (player->stateFlags2 & 0x2000000) { + if (globalCtx->msgCtx.unk_E3EE == 4) { + globalCtx->msgCtx.unk_E3EE = 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/EnFr_Destroy.s") + func_800800F8(globalCtx, 0x100E, ~0x62, &this->actor, 0); + globalCtx->msgCtx.msgMode = 0x37; + player->actor.world.pos.x = this->actor.world.pos.x; // x = 990.0f + player->actor.world.pos.y = this->actor.world.pos.y; // y = 205.0f + player->actor.world.pos.z = this->actor.world.pos.z; // z = -1220.0f + player->currentYaw = player->actor.world.rot.y = player->actor.shape.rot.y = this->actor.world.rot.y; + this->reward = GI_NONE; + this->actionFunc = EnFr_Activate; + } else if (EnFr_IsAboveAndWithin30DistXZ(player, this)) { + player->unk_6A8 = &this->actor; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1AF6C.s") +void EnFr_Activate(EnFr* this, GlobalContext* globalCtx) { + if (globalCtx->msgCtx.msgMode == 0xC) { + globalCtx->msgCtx.msgMode = 0x37; + sEnFrPointers.flags = 1; + this->actionFunc = EnFr_ActivateCheckFrogSong; + } else if (globalCtx->msgCtx.msgMode == 0x37) { // Goes to Frogs 2 Song + sEnFrPointers.flags = 1; + this->actionFunc = EnFr_ActivateCheckFrogSong; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1AFF0.s") +void EnFr_ActivateCheckFrogSong(EnFr* this, GlobalContext* globalCtx) { + if (sEnFrPointers.flags == 11) { + // Check if all 6 child songs have been played for the frogs + if ((gSaveContext.eventChkInf[13] & 0x2) // ZL + && (gSaveContext.eventChkInf[13] & 0x4) // Epona + && (gSaveContext.eventChkInf[13] & 0x10) // Saria + && (gSaveContext.eventChkInf[13] & 0x8) // Suns + && (gSaveContext.eventChkInf[13] & 0x20) // SoT + && (gSaveContext.eventChkInf[13] & 0x40)) { // SoS + this->actionFunc = EnFr_TalkBeforeFrogSong; + this->songIndex = FROG_CHOIR_SONG; + func_8010B680(globalCtx, 0x40AB, &this->actor); + } else { + this->songIndex = FROG_ZL; + this->actionFunc = func_80A1BE98; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B09C.s") +void func_80A1BE98(EnFr* this, GlobalContext* globalCtx) { + EnFr* frog; + s32 frogIndex; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B0F8.s") + for (frogIndex = 0; frogIndex < ARRAY_COUNT(sEnFrPointers.frogs); frogIndex++) { + frog = sEnFrPointers.frogs[frogIndex]; + if (frog != NULL && frog->actionFunc == EnFr_ChooseJumpFromLogSpot) { + continue; + } else { + return; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B174.s") + func_8010BD58(globalCtx, 0x30); + this->actionFunc = EnFr_ListeningToOcarinaNotes; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B19C.s") +void EnFr_ListeningToOcarinaNotes(EnFr* this, GlobalContext* globalCtx) { + this->songIndex = FROG_NO_SONG; + switch (globalCtx->msgCtx.unk_E3EE) { // Ocarina Song played + case 7: + this->songIndex = FROG_ZL; + break; + case 6: + this->songIndex = FROG_EPONA; + break; + case 5: + this->songIndex = FROG_SARIA; + break; + case 8: + this->songIndex = FROG_SUNS; + break; + case 9: + this->songIndex = FROG_SOT; + break; + case 10: + this->songIndex = FROG_STORMS; + break; + case 4: + EnFr_OcarinaMistake(this, globalCtx); + break; + case 1: // Ocarina note played, but no song played + switch (globalCtx->msgCtx.unk_E410) { // Jumping frogs in open ocarina based on ocarina note played + case 0: + EnFr_SetupJumpingUp(this, FROG_BLUE); + break; + case 1: + EnFr_SetupJumpingUp(this, FROG_YELLOW); + break; + case 2: + EnFr_SetupJumpingUp(this, FROG_RED); + break; + case 3: + EnFr_SetupJumpingUp(this, FROG_PURPLE); + break; + case 4: + EnFr_SetupJumpingUp(this, FROG_WHITE); + break; + } + } + if (this->songIndex != FROG_NO_SONG) { + this->jumpCounter = 0; + this->actionFunc = EnFr_ChildSong; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B22C.s") +void EnFr_ChildSong(EnFr* this, GlobalContext* globalCtx) { + EnFr* frog; + u8 songIndex; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B2C8.s") + if (this->jumpCounter < 48) { + if (this->jumpCounter % 4 == 0) { + EnFr_SetupJumpingUp(this, sJumpOrder[(this->jumpCounter >> 2) & 7]); + } + } else { + songIndex = this->songIndex; + if (songIndex == FROG_STORMS) { + this->actor.textId = 0x40AA; + EnFr_SetupReward(this, globalCtx, false); + } else if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { + frog = sEnFrPointers.frogs[sSongToFrog[songIndex]]; + func_80078884(NA_SE_SY_CORRECT_CHIME); + if (frog->actionFunc == EnFr_ChooseJumpFromLogSpot) { + frog->isJumpingUp = true; + frog->isActive = true; + Audio_PlayActorSound2(&frog->actor, NA_SE_EV_FROG_GROW_UP); + this->actionFunc = EnFr_ChildSongFirstTime; + } else { + this->jumpCounter = 48; + } + } else { + this->actor.textId = 0x40A9; + EnFr_SetupReward(this, globalCtx, true); + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B464.s") +void EnFr_ChildSongFirstTime(EnFr* this, GlobalContext* globalCtx) { + EnFr* frog = sEnFrPointers.frogs[sSongToFrog[this->songIndex]]; + if (frog->isActive == false) { + this->actor.textId = 0x40A9; + EnFr_SetupReward(this, globalCtx, true); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B524.s") +void EnFr_TalkBeforeFrogSong(EnFr* this, GlobalContext* globalCtx) { + if ((func_8010BDBC(&globalCtx->msgCtx) == 5) && (func_80106BC8(globalCtx))) { + func_80106CCC(globalCtx); + this->frogSongTimer = 2; + this->actionFunc = EnFr_SetupFrogSong; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B638.s") +void EnFr_CheckOcarinaInputFrogSong(u8 ocarinaNote) { + EnFr* frog; + s32 frogIndexButterfly; + s32 frogIndex; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B778.s") + switch (ocarinaNote) { + case 0: + frogIndexButterfly = FROG_BLUE; + break; + case 1: + frogIndexButterfly = FROG_YELLOW; + break; + case 2: + frogIndexButterfly = FROG_RED; + break; + case 3: + frogIndexButterfly = FROG_PURPLE; + break; + case 4: + frogIndexButterfly = FROG_WHITE; + } + // Turn on or off butterfly above frog + for (frogIndex = 0; frogIndex < ARRAY_COUNT(sEnFrPointers.frogs); frogIndex++) { + frog = sEnFrPointers.frogs[frogIndex]; + frog->isButterflyDrawn = frogIndex == frogIndexButterfly ? true : false; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B8D0.s") +void EnFr_DeactivateButterfly() { + s32 frogIndex; + EnFr* frog; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1B9D8.s") + for (frogIndex = 0; frogIndex < ARRAY_COUNT(sEnFrPointers.frogs); frogIndex++) { + frog = sEnFrPointers.frogs[frogIndex]; + frog->isButterflyDrawn = false; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1BB34.s") +u8 EnFr_GetNextNoteFrogSong(u8 ocarinaNoteIndex) { + if (!(gSaveContext.eventChkInf[13] & 1)) { + return gFrogsSongPtr[ocarinaNoteIndex]; + } else { + return sOcarinaNotes[(s32)Rand_ZeroFloat(60.0f) % 5]; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1BC14.s") +void EnFr_SetupFrogSong(EnFr* this, GlobalContext* globalCtx) { + if (this->frogSongTimer != 0) { + this->frogSongTimer--; + } else { + this->frogSongTimer = 40; + this->ocarinaNoteIndex = 0; + func_8010BD58(globalCtx, 0x2F); + this->ocarinaNote = EnFr_GetNextNoteFrogSong(this->ocarinaNoteIndex); + EnFr_CheckOcarinaInputFrogSong(this->ocarinaNote); + this->actionFunc = EnFr_ContinueFrogSong; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1BCB4.s") +s32 EnFr_IsFrogSongComplete(EnFr* this, GlobalContext* globalCtx) { + u8 index; + u8 ocarinaNote; + MessageContext* msgCtx = &globalCtx->msgCtx; + u8 ocarinaNoteIndex; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1BD94.s") + if (this->ocarinaNote == (*msgCtx).unk_E410) { // required to match, possibly an array? + this->ocarinaNoteIndex++; + ocarinaNoteIndex = this->ocarinaNoteIndex; + if (1) {} + if (ocarinaNoteIndex >= 14) { // Frog Song is completed + this->ocarinaNoteIndex = 13; + return true; + } + // The first four notes have more frames to receive an input + index = ocarinaNoteIndex < 4 ? (s32)ocarinaNoteIndex : 4; + ocarinaNote = EnFr_GetNextNoteFrogSong(ocarinaNoteIndex); + this->ocarinaNote = ocarinaNote; + EnFr_CheckOcarinaInputFrogSong(ocarinaNote); + this->frogSongTimer = sTimerFrogSong[index]; + } + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1BDFC.s") +void EnFr_OcarinaMistake(EnFr* this, GlobalContext* globalCtx) { + func_80106CCC(globalCtx); + this->reward = GI_NONE; + func_80078884(NA_SE_SY_OCARINA_ERROR); + func_800ED858(0); + sEnFrPointers.flags = 12; + EnFr_DeactivateButterfly(); + this->actionFunc = EnFr_Deactivate; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1BE98.s") +void EnFr_ContinueFrogSong(EnFr* this, GlobalContext* globalCtx) { + s32 counter; + EnFr* frog; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1BF10.s") + if (this->frogSongTimer == 0) { + EnFr_OcarinaMistake(this, globalCtx); + } else { + this->frogSongTimer--; + if (globalCtx->msgCtx.msgMode == 0x32) { + counter = 0; + for (i = 0; i < ARRAY_COUNT(sEnFrPointers.frogs); i++) { + frog = sEnFrPointers.frogs[i]; + if (frog != NULL && frog->actionFunc == EnFr_ChooseJumpFromLogSpot) { + continue; + } else { + counter++; + } + } + if (counter == 0 && CHECK_BTN_ALL(globalCtx->state.input[0].press.button, BTN_B)) { + EnFr_OcarinaMistake(this, globalCtx); + return; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C05C.s") + if (globalCtx->msgCtx.msgMode == 0x33) { + globalCtx->msgCtx.msgMode = 0x31; + switch (globalCtx->msgCtx.unk_E410) { + case 0: + EnFr_SetupJumpingUp(this, FROG_BLUE); + break; + case 1: + EnFr_SetupJumpingUp(this, FROG_YELLOW); + break; + case 2: + EnFr_SetupJumpingUp(this, FROG_RED); + break; + case 3: + EnFr_SetupJumpingUp(this, FROG_PURPLE); + break; + case 4: + EnFr_SetupJumpingUp(this, FROG_WHITE); + } + if (EnFr_IsFrogSongComplete(this, globalCtx)) { + this->actor.textId = 0x40AC; + EnFr_SetupReward(this, globalCtx, false); + } + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C18C.s") +void EnFr_SetupReward(EnFr* this, GlobalContext* globalCtx, u8 unkCondition) { + EnFr_DeactivateButterfly(); + if (unkCondition) { + func_80078884(NA_SE_SY_TRE_BOX_APPEAR); + } else { + func_80078884(NA_SE_SY_CORRECT_CHIME); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C1E4.s") + func_800ED858(0); + globalCtx->msgCtx.msgMode = 0x37; + this->actionFunc = EnFr_PrintTextBox; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C248.s") +void EnFr_PrintTextBox(EnFr* this, GlobalContext* globalCtx) { + func_8010B680(globalCtx, this->actor.textId, &this->actor); + this->actionFunc = EnFr_TalkBeforeReward; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C344.s") +void EnFr_TalkBeforeReward(EnFr* this, GlobalContext* globalCtx) { + if ((func_8010BDBC(&globalCtx->msgCtx) == 5) && func_80106BC8(globalCtx)) { + this->frogSongTimer = 100; + func_80106CCC(globalCtx); + this->actionFunc = EnFr_SetReward; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C388.s") +void EnFr_SetReward(EnFr* this, GlobalContext* globalCtx) { + u16 songIndex; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C400.s") + sEnFrPointers.flags = 12; + songIndex = this->songIndex; + this->actionFunc = EnFr_Deactivate; + this->reward = GI_NONE; + if ((songIndex >= FROG_ZL) && (songIndex <= FROG_SOT)) { + if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { + gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; + this->reward = GI_RUPEE_PURPLE; + } else { + this->reward = GI_RUPEE_BLUE; + } + } else if (songIndex == FROG_STORMS) { + if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { + gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; + this->reward = GI_HEART_PIECE; + } else { + this->reward = GI_RUPEE_BLUE; + } + } else if (songIndex == FROG_CHOIR_SONG) { + if (!(gSaveContext.eventChkInf[13] & sSongIndex[songIndex])) { + gSaveContext.eventChkInf[13] |= sSongIndex[songIndex]; + this->reward = GI_HEART_PIECE; + } else { + this->reward = GI_RUPEE_PURPLE; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C474.s") +void EnFr_Deactivate(EnFr* this, GlobalContext* globalCtx) { + EnFr* frogLoop1; + EnFr* frogLoop2; + s32 frogIndex; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C524.s") + // Originally was going to have separate butterfly actor + // Changed to include butterfly as part of frog actor + // This unused code would have frozen the butterfly actor above frog + if (this->unusedButterflyActor != NULL) { + this->unusedButterflyActor->freezeTimer = 10; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C580.s") + for (frogIndex = 0; frogIndex < ARRAY_COUNT(sEnFrPointers.frogs); frogIndex++) { + frogLoop1 = sEnFrPointers.frogs[frogIndex]; + if (frogLoop1 == NULL) { + osSyncPrintf(VT_COL(RED, WHITE)); + // Translation: There are no frogs!? + osSyncPrintf("%s[%d]カエルがいない!?\n", "../z_en_fr.c", 1604); + osSyncPrintf(VT_RST); + return; + } else if (frogLoop1->isDeactivating != true) { + return; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C718.s") + for (frogIndex = 0; frogIndex < ARRAY_COUNT(sEnFrPointers.frogs); frogIndex++) { + frogLoop2 = sEnFrPointers.frogs[frogIndex]; + if (frogLoop2 == NULL) { + osSyncPrintf(VT_COL(RED, WHITE)); + // Translation: There are no frogs!? + osSyncPrintf("%s[%d]カエルがいない!?\n", "../z_en_fr.c", 1618); + osSyncPrintf(VT_RST); + return; + } + frogLoop2->isDeactivating = false; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C790.s") + globalCtx->msgCtx.unk_E3EE = 4; + Audio_PlayActorSound2(&this->actor, NA_SE_EV_FROG_CRY_0); + if (this->reward == GI_NONE) { + this->actionFunc = EnFr_Idle; + } else { + this->actionFunc = EnFr_GiveReward; + func_8002F434(&this->actor, globalCtx, this->reward, 30.0f, 100.0f); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C7CC.s") +void EnFr_GiveReward(EnFr* this, GlobalContext* globalCtx) { + if (Actor_HasParent(&this->actor, globalCtx)) { + this->actor.parent = NULL; + this->actionFunc = EnFr_SetIdle; + } else { + func_8002F434(&this->actor, globalCtx, this->reward, 30.0f, 100.0f); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C830.s") +void EnFr_SetIdle(EnFr* this, GlobalContext* globalCtx) { + if ((func_8010BDBC(&globalCtx->msgCtx) == 6) && (func_80106BC8(globalCtx))) { + this->actionFunc = EnFr_Idle; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1C944.s") +void EnFr_UpdateIdle(Actor* thisx, GlobalContext* globalCtx) { + EnFr* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1CAAC.s") + if (BREG(0)) { + DebugDisplay_AddObject(this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, + this->actor.world.rot.x, this->actor.world.rot.y, this->actor.world.rot.z, 1.0f, 1.0f, + 1.0f, 255, 0, 0, 255, 4, globalCtx->state.gfxCtx); + } + this->jumpCounter++; + this->actionFunc(this, globalCtx); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1CB08.s") +s32 EnFr_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { + if ((limbIndex == 7) || (limbIndex == 8)) { + *dList = NULL; + } + return 0; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1CB58.s") +void EnFr_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { + EnFr* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1CC04.s") + if ((limbIndex == 7) || (limbIndex == 8)) { + OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_fr.c", 1735); + Matrix_Push(); + func_800D1FD4(&globalCtx->mf_11DA0); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_fr.c", 1738), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_OPA_DISP++, *dList); + Matrix_Pull(); + CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_fr.c", 1741); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1CC2C.s") +void EnFr_Draw(Actor* thisx, GlobalContext* globalCtx) { + static u64* eyeTextures[] = { 0x060059A0, 0x06005BA0 }; + s16 lightRadius; + EnFr* this = THIS; + s16 frogIndex = this->actor.params - 1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fr/func_80A1CD24.s") + OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_fr.c", 1754); + func_80093D18(globalCtx->state.gfxCtx); + // For the frogs 2 HP, the frog with the next note and the butterfly lights up + lightRadius = this->isButterflyDrawn ? 95 : -1; + gDPPipeSync(POLY_OPA_DISP++); + gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255); + Lights_PointNoGlowSetInfo(&this->lightInfo, this->posButterflyLight.x, this->posButterflyLight.y, + this->posButterflyLight.z, 255, 255, 255, lightRadius); + gDPSetEnvColor(POLY_OPA_DISP++, sEnFrColor[frogIndex].r, sEnFrColor[frogIndex].g, sEnFrColor[frogIndex].b, 255); + gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL(eyeTextures[this->eyeTexIndex])); + gSPSegment(POLY_OPA_DISP++, 0x09, SEGMENTED_TO_VIRTUAL(eyeTextures[this->eyeTexIndex])); + SkelAnime_DrawFlexOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, + EnFr_OverrideLimbDraw, EnFr_PostLimbDraw, this); + if (this->isButterflyDrawn) { + Matrix_Translate(this->posButterfly.x, this->posButterfly.y, this->posButterfly.z, MTXMODE_NEW); + Matrix_Scale(0.015f, 0.015f, 0.015f, MTXMODE_APPLY); + Matrix_RotateRPY(this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, MTXMODE_APPLY); + SkelAnime_DrawOpa(globalCtx, this->skelAnimeButterfly.skeleton, this->skelAnimeButterfly.jointTable, NULL, NULL, + NULL); + } + CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_fr.c", 1816); +} diff --git a/src/overlays/actors/ovl_En_Fr/z_en_fr.h b/src/overlays/actors/ovl_En_Fr/z_en_fr.h index 1eb0b2bda..774a60c75 100644 --- a/src/overlays/actors/ovl_En_Fr/z_en_fr.h +++ b/src/overlays/actors/ovl_En_Fr/z_en_fr.h @@ -6,9 +6,67 @@ struct EnFr; +typedef void (*EnFrActionFunc)(struct EnFr*, GlobalContext*); +typedef void (*EnFrBlinkFunc)(struct EnFr*); + +typedef enum { + /* 00 */ FROG_YELLOW, // Middle + /* 01 */ FROG_BLUE, // Front Left + /* 02 */ FROG_RED, // Front Right + /* 03 */ FROG_PURPLE, // Back Left + /* 04 */ FROG_WHITE // Back Right +} FrogType; + +typedef enum { + /* 00 */ FROG_ZL, + /* 01 */ FROG_EPONA, + /* 02 */ FROG_SARIA, + /* 03 */ FROG_SUNS, + /* 04 */ FROG_SOT, + /* 05 */ FROG_STORMS, + /* 06 */ FROG_CHOIR_SONG, + /* 07 */ FROG_NO_SONG +} FrogSongType; + typedef struct EnFr { /* 0x0000 */ Actor actor; - /* 0x014C */ char unk_14C[0x278]; + /* 0x014C */ SkelAnime skelAnime; // Frog Skeleton + /* 0x0190 */ Vec3s jointTable[24]; + /* 0x0220 */ Vec3s morphTable[24]; + /* 0x02B0 */ SkelAnime skelAnimeButterfly; // Butterfly Skeleton above Frog during Frog Song + /* 0x02F4 */ Vec3s jointTableButterfly[8]; + /* 0x0324 */ Vec3s morphTableButterfly[8]; + /* 0x0354 */ EnFrActionFunc actionFunc; + /* 0x0358 */ LightNode* lightNode; // Frogs light up during the Frog Song, specifically the frog with the next note. + /* 0x035C */ LightInfo lightInfo; + /* 0x036A */ s8 objBankIndex; + /* 0x036C */ s32 jumpCounter; // cyclic clock used to time celebratory frog jumps every 4 frames when child song is played. + /* 0x0370 */ s32 blinkTimer; // blinking timer + /* 0x0374 */ EnFrBlinkFunc blinkFunc; // unique case of using a function pointer for blinking + /* 0x0378 */ u8 eyeTexIndex; // index for blinking graphics + /* 0x0379 */ u8 isJumpingUp; // Conditional for jumping up from the log back onto the log + /* 0x037A */ u8 isBelowWaterSurfaceCurrent; // Used for diving effects + /* 0x037B */ u8 isBelowWaterSurfacePrevious; + /* 0x037C */ u8 isDeactivating; // Related to debugging (osSyncPrintf) + /* 0x037D */ u8 isActive; // Each Frog grows when their specific song is played. + /* 0x037E */ u8 growingScaleIndex; // Target Scale Level 0-3 while growing (3 highest smooth) + /* 0x037F */ u8 isGrowing; // While growing, the frog will switch between its larger size and its original size every frame + /* 0x0380 */ u8 ocarinaNoteIndex; // Related to unk_381 + /* 0x0381 */ u8 ocarinaNote; // Ocarina Note to Play for Frogs 2. Related to globalCtx->msgCtx.unk_E410 + /* 0x0382 */ u8 songIndex; // Song index 1-7 (6 songs + custom HP Song): 5 = sos, 6 = all songs + /* 0x0383 */ u8 isJumpingToFrogSong; // Conditional: + /* 0x0384 */ char unk_384[0x02]; + /* 0x0386 */ s16 frogSongTimer; // timer #2 for frogs 2 HP + /* 0x0388 */ s32 reward; // Prize for completing a song + /* 0x038C */ Vec3f posLogSpot; // Where the frog goes when activated + /* 0x0398 */ f32 xzDistToLogSpot; // z position or axis + /* 0x039C */ f32 unusedFloat; // Unused float, only set to zero. + /* 0x03A0 */ f32 scale; //scale + /* 0x03A4 */ Actor* unusedButterflyActor; // unused pointer to Actor. Likely intended for butterfly + /* 0x03A8 */ u8 isButterflyDrawn; // isButterflyDrawn + /* 0x03AA */ s16 xyAngleButterfly; // Butterfly Travels along random angles in the x-y plane + /* 0x03AC */ Vec3f posButterfly; // Position/Coordinates of the Butterfly + /* 0x03B8 */ Vec3f posButterflyLight; // Used in Lights_PointNoGlowSetInfo() } EnFr; // size = 0x03C4 extern const ActorInit En_Fr_InitVars; diff --git a/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c b/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c index fdd7e6eb5..ceb9cb4c6 100644 --- a/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c +++ b/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c @@ -99,7 +99,7 @@ void func_80A8F320(EnKakasi* this, GlobalContext* globalCtx, s16 arg) { s16 phi_v0; s16 currentFrame; - phi_v0 = globalCtx->msgCtx.unk_E410[0]; + phi_v0 = globalCtx->msgCtx.unk_E410; if (arg != 0) { if (this->unk_19C[3] == 0) { this->unk_19C[3] = (s16)Rand_ZeroFloat(10.99f) + 30; diff --git a/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c b/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c index 407e1a8b0..0c93f4b66 100644 --- a/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c +++ b/src/overlays/actors/ovl_En_Kakasi3/z_en_kakasi3.c @@ -102,7 +102,7 @@ void func_80A90EBC(EnKakasi3* this, GlobalContext* globalCtx, s32 arg) { s16 currentFrame; s16 phi_v0; - phi_v0 = globalCtx->msgCtx.unk_E410[0]; + phi_v0 = globalCtx->msgCtx.unk_E410; if (arg != 0) { if (this->unk_19C[3] == 0) { this->unk_19C[3] = (s16)Rand_ZeroFloat(10.99f) + 30; |
