Ovl_En_Minifrog OK with partial documentation (#166)

* En_Minifrog first few funcs decompiled

* more matching

* En_Minifrog 3 non_matching functions left

* two functions left

* Start Documentation

* Fully Matching!

* Documentation

* Fix merge with master

* minor pr changes

* Minor improvements

* PR Suggestions + Minor docs

* Fix bool

* PR suggestions

Co-authored-by: engineer124 <engineer124enginer124@gmail.com>
This commit is contained in:
engineer124 2021-06-10 11:03:42 +10:00 committed by GitHub
parent 5110943377
commit 9102481fc2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 663 additions and 60 deletions

View File

@ -601,7 +601,8 @@ void EffectSsDust_Spawn(GlobalContext* globalCtx, u16 drawFlags, Vec3f* pos, Vec
// void func_800B0E48(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE2 param_7, UNK_TYPE2 param_8);
// void func_800B0EB0(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE2 param_7, UNK_TYPE2 param_8, UNK_TYPE2 param_9);
// void func_800B0F18(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE2 param_7, UNK_TYPE2 param_8, UNK_TYPE2 param_9);
// void func_800B0F80(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE2 param_7, UNK_TYPE2 param_8, UNK_TYPE2 param_9);
void func_800B0F80(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, Color_RGBA8* primColor,
Color_RGBA8* envColor, s16 scale, s16 scaleStep, s16 life);
// void func_800B0FE8(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE2 param_7, UNK_TYPE2 param_8);
// void func_800B1054(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE2 param_7, UNK_TYPE2 param_8);
// void func_800B10C0(void);
@ -3923,7 +3924,7 @@ void func_801A31EC(UNK_TYPE1 arg1, UNK_TYPE4 arg2, u8 arg3);
// void func_801A32CC(void);
// void func_801A3590(void);
// void func_801A3950(void);
// void func_801A39F8(void);
u8 func_801A39F8(void);
// void func_801A3A7C(void);
// void func_801A3AC0(void);
// void func_801A3AEC(void);

View File

@ -1530,7 +1530,9 @@ struct GlobalContext {
/* 0x17D88 */ ObjectContext objectCtx;
/* 0x186E0 */ RoomContext roomContext;
/* 0x18760 */ TransitionContext transitionCtx;
/* 0x18768 */ UNK_TYPE1 pad18768[0x48];
/* 0x18768 */ UNK_TYPE1 pad18768[0x30];
/* 0x18798 */ void (*func_18798)(struct GlobalContext* globalCtx, void* arg1, s32 arg2);
/* 0x1879C */ UNK_TYPE1 pad1879C[0x14];
/* 0x187B0 */ MtxF unk187B0;
/* 0x187F0 */ UNK_TYPE1 pad187F0[0xC];
/* 0x187FC */ MtxF unk187FC;

View File

@ -1212,9 +1212,9 @@ SECTIONS
ovl_En_Minifrog : AT(RomLocation)
{
build/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.o(.text)
build/asm/overlays/ovl_En_Minifrog_data.o(.data)
build/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.o(.data)
build/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.o(.rodata)
build/asm/overlays/ovl_En_Minifrog_rodata.o(.rodata)
build/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog_overlay.o(.ovl)
}
SegmentEnd = .;
SegmentSize = SegmentEnd - SegmentStart;

View File

@ -1,5 +1,7 @@
/* gameplay_keep */
D_040008D0 = 0x040008D0;
D_0400DEA8 = 0x0400DEA8;
D_0400E2A8 = 0x0400E2A8;
D_04029CB0 = 0x04029CB0;
D_04029CF0 = 0x04029CF0;
D_04058BA0 = 0x04058BA0;
@ -264,6 +266,13 @@ D_04054A90 = 0x04054A90;
D_06000AD0 = 0x06000AD0;
D_06000140 = 0x06000140;
/* en_minifrog */
D_060007BC = 0x060007BC;
D_06001534 = 0x06001534;
D_060059A0 = 0x060059A0;
D_06005BA0 = 0x06005BA0;
D_0600B538 = 0x0600B538;
/* bg_lotus */
D_06000A20 = 0x06000A20;
D_06000040 = 0x06000040;

View File

@ -1,3 +1,9 @@
/*
* File: z_en_minifrog.c
* Overlay: ovl_En_Minifrog
* Description: Five Frogs of the Frog Choir
*/
#include "z_en_minifrog.h"
#define FLAGS 0x00000019
@ -9,7 +15,23 @@ void EnMinifrog_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnMinifrog_Update(Actor* thisx, GlobalContext* globalCtx);
void EnMinifrog_Draw(Actor* thisx, GlobalContext* globalCtx);
/*
EnMinifrog* EnMinifrog_GetFrog(GlobalContext* globalCtx);
void EnMinifrog_SpawnGrowAndShrink(EnMinifrog* this, GlobalContext* globalCtx);
void EnMinifrog_Idle(EnMinifrog* this, GlobalContext* globalCtx);
void EnMinifrog_SetupNextFrogInit(EnMinifrog* this, GlobalContext* globalCtx);
void EnMinifrog_UpdateMissingFrog(Actor* thisx, GlobalContext* globalCtx);
void EnMinifrog_YellowFrogDialog(EnMinifrog* this, GlobalContext* globalCtx);
void EnMinifrog_SetupYellowFrogDialog(EnMinifrog* this, GlobalContext* globalCtx);
extern AnimationHeader D_060007BC;
extern AnimationHeader D_06001534;
extern FlexSkeletonHeader D_0600B538;
extern UNK_TYPE4 D_060059A0;
extern UNK_TYPE4 D_06005BA0;
extern UNK_TYPE1 D_0400DEA8;
extern UNK_TYPE1 D_0400E2A8;
const ActorInit En_Minifrog_InitVars = {
ACTOR_EN_MINIFROG,
ACTORCAT_NPC,
@ -21,60 +43,601 @@ const ActorInit En_Minifrog_InitVars = {
(ActorFunc)EnMinifrog_Update,
(ActorFunc)EnMinifrog_Draw,
};
*/
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/EnMinifrog_Init.asm")
static ColliderCylinderInit sCylinderInit = {
{
COLTYPE_NONE,
AT_NONE,
AC_NONE,
OC1_ON | OC1_TYPE_ALL,
OC2_TYPE_1,
COLSHAPE_CYLINDER,
},
{
ELEMTYPE_UNK1,
{ 0xF7CFFFFF, 0x00, 0x00 },
{ 0xF7CFFFFF, 0x00, 0x00 },
TOUCH_NONE | TOUCH_SFX_NORMAL,
BUMP_NONE,
OCELEM_ON,
},
{ 12, 14, 0, { 0, 0, 0 } },
};
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/EnMinifrog_Destroy.asm")
static CollisionCheckInfoInit sColChkInfoInit = { 1, 12, 14, MASS_IMMOVABLE };
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A3930.asm")
// sEyeTextures???
static UNK_TYPE4* D_808A4D74[] = {
&D_060059A0,
&D_06005BA0,
};
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A3980.asm")
// gSaveContext.weekEventReg[KEY] = VALUE
// KEY | VALUE
static u16 isFrogReturnedFlags[] = {
(0 << 8) | 0x00, // NULL
(32 << 8) | 0x40, // Woodfall Temple Frog Returned
(32 << 8) | 0x80, // Great Bay Temple Frog Returned
(33 << 8) | 0x01, // Southern Swamp Frog Returned
(33 << 8) | 0x02, // Laundry Pool Frog Returned
};
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A39EC.asm")
static s32 isInitialized = false;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A3A44.asm")
static InitChainEntry sInitChain[] = {
ICHAIN_F32_DIV1000(gravity, -800, ICHAIN_STOP),
};
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A3B04.asm")
void EnMinifrog_Init(Actor* thisx, GlobalContext* globalCtx) {
EnMinifrog* this = THIS;
int i;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A3B3C.asm")
Actor_ProcessInitChain(&this->actor, sInitChain);
ActorShape_Init(&this->actor.shape, 0.0f, func_800B3FC0, 15.0f);
SkelAnime_InitSV(globalCtx, &this->skelAnime, &D_0600B538, &D_06001534, this->limbDrawTable, this->transitionDrawTable, 24);
CollisionCheck_SetInfo(&this->actor.colChkInfo, NULL, &sColChkInfoInit);
Collider_InitAndSetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A3B74.asm")
if (!isInitialized) {
for (i = 0; i < 2; i++) {
D_808A4D74[i] = Lib_SegmentedToVirtual(D_808A4D74[i]);
}
isInitialized = true;
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A3DA8.asm")
this->frogIndex = (this->actor.params & 0xF);
if (this->frogIndex >= 5) {
this->frogIndex = MINIFROG_YELLOW;
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A3F88.asm")
this->actor.speedXZ = 0.0f;
this->actionFunc = EnMinifrog_Idle;
this->jumpState = MINIFROG_STATE_GROUND;
this->flags = 0;
this->timer = 0;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A4040.asm")
if (1) {}
if (!EN_MINIFROG_IS_RETURNED(this)) {
if ((this->frogIndex == MINIFROG_YELLOW) || ((gSaveContext.weekEventReg[isFrogReturnedFlags[this->frogIndex] >> 8] & (u8)isFrogReturnedFlags[this->frogIndex]))) {
Actor_MarkForDeath(&this->actor);
} else {
this->timer = 30;
this->actionFunc = EnMinifrog_SpawnGrowAndShrink;
this->actor.textId = 0xD81; // "Ah! Don Gero! It has been so long."
this->actor.colChkInfo.mass = 30;
}
} else { // Frogs in mountain village
if (this->frogIndex == MINIFROG_YELLOW) {
this->actor.textId = 0;
this->actionFunc = EnMinifrog_SetupYellowFrogDialog;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A410C.asm")
// Not spoken to MINIFROG_YELLOW
if (!(gSaveContext.weekEventReg[34] & 1)) {
this->actor.flags |= 0x10000;
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A41A0.asm")
this->actor.home.rot.x = this->actor.home.rot.z = 0;
this->frog = NULL;
} else {
this->frog = EnMinifrog_GetFrog(globalCtx);
this->actor.flags &= ~1;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A4214.asm")
// Frog has been returned
if ((gSaveContext.weekEventReg[isFrogReturnedFlags[this->frogIndex] >> 8] & (u8)isFrogReturnedFlags[this->frogIndex])) {
this->actionFunc = EnMinifrog_SetupNextFrogInit;
} else {
this->actor.draw = NULL;
this->actor.update = EnMinifrog_UpdateMissingFrog;
}
}
}
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A42D8.asm")
void EnMinifrog_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnMinifrog* this = THIS;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A4328.asm")
Collider_DestroyCylinder(globalCtx, &this->collider);
if (this->flags & 0x100) {
func_801A1F88();
}
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A43A4.asm")
EnMinifrog* EnMinifrog_GetFrog(GlobalContext* globalCtx) {
EnMinifrog* frog = (EnMinifrog*)globalCtx->actorCtx.actorList[ACTORCAT_NPC].first;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A44BC.asm")
while (frog != NULL) {
if ((frog->actor.id != ACTOR_EN_MINIFROG) || (frog->actor.params & 0xF)) {
frog = (EnMinifrog*)frog->actor.next;
} else {
return frog;
}
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A45A8.asm")
return NULL;
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A4634.asm")
void EnMinifrog_SetJumpState(EnMinifrog* this) {
if (this->jumpState == MINIFROG_STATE_GROUND) {
this->jumpState = MINIFROG_STATE_JUMP;
SkelAnime_ChangeAnim(&this->skelAnime, &D_060007BC, 1.0f, 0.0f, 7.0f, 2, -5.0f);
}
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A46E8.asm")
void EnMinifrog_JumpTimer(EnMinifrog* this) {
if (this->timer > 0) {
this->timer--;
} else {
this->timer = 60 + (s32)Rand_ZeroFloat(40.0f);
EnMinifrog_SetJumpState(this);
}
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A4914.asm")
void EnMinifrog_Jump(EnMinifrog* this) {
SkelAnime_FrameUpdateMatrix(&this->skelAnime);
switch (this->jumpState) {
case MINIFROG_STATE_JUMP:
if (func_801378B8(&this->skelAnime, 4.0f)) {
this->actor.bgCheckFlags &= ~1;
this->actor.velocity.y = 6.0f;
Audio_PlayActorSound2(this, 0x28B1);
this->jumpState = MINIFROG_STATE_AIR;
}
break;
case MINIFROG_STATE_AIR:
if (this->actor.bgCheckFlags & 1) {
this->jumpState = MINIFROG_STATE_GROUND;
SkelAnime_ChangeAnimTransitionRepeat(&this->skelAnime, &D_06001534, -2.5f);
SkelAnime_FrameUpdateMatrix(&this->skelAnime);
}
break;
}
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/EnMinifrog_Update.asm")
void EnMinifrog_TurnToPlayer(EnMinifrog* this) {
Math_ScaledStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0x400);
this->actor.world.rot.y = this->actor.shape.rot.y;
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A4AC8.asm")
void EnMinifrog_TurnToMissingFrog(EnMinifrog* this) {
Math_ScaledStepToS(&this->actor.shape.rot.y, this->actor.home.rot.y, 0x400);
this->actor.world.rot.y = this->actor.shape.rot.y;
}
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A4AF8.asm")
static Color_RGBA8 sPrimColor = { 255, 255, 255, 255 };
static Color_RGBA8 sEnvColor = { 80, 80, 80, 255 };
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/func_808A4B3C.asm")
void EnMinifrog_SetCamera(EnMinifrog* this, GlobalContext* globalCtx) {
Vec3f pos;
Vec3f vec5;
Vec3f vel;
Vec3f accel;
s16 yaw;
s16 pitch;
Vec3f eye;
s32 i;
#pragma GLOBAL_ASM("./asm/non_matchings/overlays/ovl_En_Minifrog_0x808A3670/EnMinifrog_Draw.asm")
eye = ACTIVE_CAM->eye;
yaw = Math_Vec3f_Yaw(&eye, &this->actor.world.pos);
pitch = -Math_Vec3f_Pitch(&eye, &this->actor.world.pos);
vec5.x = this->actor.world.pos.x - (5.0f * Math_SinS(yaw) * Math_CosS(pitch));
vec5.y = this->actor.world.pos.y - (5.0f * Math_SinS(pitch));
vec5.z = this->actor.world.pos.z - (5.0f * Math_CosS(yaw) * Math_CosS(pitch));
for (i = 0; i < 5; i++) {
vel.x = randPlusMinusPoint5Scaled(4.0f);
vel.y = randPlusMinusPoint5Scaled(4.0f);
vel.z = randPlusMinusPoint5Scaled(4.0f);
accel.x = -vel.x * 0.1f;
accel.y = -vel.y * 0.1f;
accel.z = -vel.z * 0.1f;
pos.x = vec5.x + vel.x;
pos.y = vec5.y + vel.y;
pos.z = vec5.z + vel.z;
func_800B0F80(globalCtx, &pos, &vel, &accel, &sPrimColor, &sEnvColor, 300, 30, 10);
}
}
void EnMinifrog_ReturnFrogCutscene(EnMinifrog* this, GlobalContext* globalCtx) {
u8 flag;
EnMinifrog_TurnToPlayer(this);
EnMinifrog_Jump(this);
if ((func_80152498(&globalCtx->msgCtx) == 5) && func_80147624(globalCtx)) {
EnMinifrog_SetJumpState(this);
switch (globalCtx->msgCtx.unk11F04) {
case 0xD81: // "Ah! Don Gero! It has been so long."
case 0xD83: // "Could it be... Has spring finally come to the mountains?"
case 0xD84: // "That look...It is true! Winter was so long that I began to lose all hope."
case 0xD86: // "Could it be... You came all this way looking for me?"
case 0xD87: // "Ah! You need not say a thing. Upon seeing that face, I understand!" ...
func_80151938(globalCtx, globalCtx->msgCtx.unk11F04 + 1);
break;
case 0xD82: // "What has brought you all this way?"
if (gSaveContext.weekEventReg[33] & 0x80) { // Mountain village is unfrozen
func_80151938(globalCtx, 0xD83); // "Could it be... Has spring finally come to the mountains?"
} else {
func_80151938(globalCtx, 0xD86); // "Could it be... You came all this way looking for me?"
}
flag = gSaveContext.weekEventReg[isFrogReturnedFlags[this->frogIndex] >> 8];
gSaveContext.weekEventReg[isFrogReturnedFlags[this->frogIndex] >> 8] = flag | (u8)isFrogReturnedFlags[this->frogIndex];
break;
case 0xD85: // "I understand. I shall head for the mountains immediately."
default:
func_801477B4(globalCtx);
EnMinifrog_SetCamera(this, globalCtx);
func_800F0568(globalCtx, &this->actor.world.pos, 30, 0x3A87);
if (this->actor.cutscene != -1) {
if (ActorCutscene_GetCurrentIndex() == this->actor.cutscene) {
ActorCutscene_Stop(this->actor.cutscene);
}
}
Actor_MarkForDeath(&this->actor);
return;
}
}
if (this->flags & 1) {
if (ActorCutscene_GetCurrentIndex() == 0x7C) {
ActorCutscene_Stop(0x7C);
ActorCutscene_SetIntentToPlay(this->actor.cutscene);
} else if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) {
ActorCutscene_Start(this->actor.cutscene, &this->actor);
this->flags &= ~1;
} else {
ActorCutscene_SetIntentToPlay(this->actor.cutscene);
}
}
}
// This can be seen when the Cyan and Pink frogs spawn after their respective minibosses
void EnMinifrog_SpawnGrowAndShrink(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog_Jump(this);
if (this->timer > 0) {
Actor_SetScale(&this->actor, (0.01f + 0.0003f * this->timer * Math_SinS(0x1000 * (this->timer & 7))));
this->timer--;
} else {
Actor_SetScale(&this->actor, 0.01f);
this->actionFunc = EnMinifrog_Idle;
}
}
void EnMinifrog_Idle(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog_TurnToPlayer(this);
EnMinifrog_Jump(this);
EnMinifrog_JumpTimer(this);
if (func_800B84D0(&this->actor, globalCtx)) {
this->actionFunc = EnMinifrog_ReturnFrogCutscene;
if (this->actor.cutscene != -1) {
this->flags |= 1;
}
} else if ((this->actor.xzDistToPlayer < 100.0f) && Actor_IsLinkFacingActor(&this->actor, 0x3000, globalCtx) && (func_8012403C(globalCtx) == 0xD)) {
func_800B8614(&this->actor, globalCtx, 110.0f);
}
}
void EnMinifrog_SetupNextFrogInit(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog* nextFrog;
EnMinifrog* missingFrog;
EnMinifrog_Jump(this);
nextFrog = this->frog;
if (nextFrog != NULL) {
missingFrog = nextFrog->frog;
if (nextFrog->frog != NULL) {
this->actor.home.rot.y = (s16)Actor_YawBetweenActors(&this->actor, &missingFrog->actor); // Set home to missing frog
EnMinifrog_TurnToMissingFrog(this);
} else {
EnMinifrog_TurnToPlayer(this);
}
if (this->frog->actor.home.rot.z == (this->actor.params & 0xF)) {
EnMinifrog_SetJumpState(this);
this->frog->actor.home.rot.z = 0;
}
}
}
void EnMinifrog_CheckChoirSuccess(EnMinifrog* this, GlobalContext* globalCtx) {
this->actionFunc = EnMinifrog_YellowFrogDialog;
if (this->frog != NULL) {
func_80151938(globalCtx, 0xD78); // "Unfortunately, it seems not all of our members have gathered."
} else {
func_80151938(globalCtx, 0xD7C); // "The conducting was spectacular. And all of our members rose to the occasion!"
}
EnMinifrog_SetJumpState(this);
this->frog = NULL;
this->actor.home.rot.z = 0;
}
void EnMinifrog_ContinueChoirCutscene(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog_Jump(this);
if (ActorCutscene_GetCurrentIndex() == 0x7C) {
EnMinifrog_CheckChoirSuccess(this, globalCtx);
return; // necessary to match
} else if (ActorCutscene_GetCanPlayNext(0x7C)) {
ActorCutscene_Start(0x7C, NULL);
EnMinifrog_CheckChoirSuccess(this, globalCtx);
return; // necessary to match
} else if (this->actor.cutscene != -1 && ActorCutscene_GetCurrentIndex() == this->actor.cutscene) {
ActorCutscene_Stop(this->actor.cutscene);
ActorCutscene_SetIntentToPlay(0x7C);
return; // necessary to match
} else {
ActorCutscene_SetIntentToPlay(0x7C);
}
}
void EnMinifrog_NextFrogMissing(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog_TurnToMissingFrog(this);
EnMinifrog_Jump(this);
if (this->timer > 0) {
this->timer--;
} else {
this->actionFunc = EnMinifrog_ContinueChoirCutscene;
}
}
void EnMinifrog_NextFrogReturned(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog_Jump(this);
if (this->timer > 0) {
this->timer--;
} else {
this->actionFunc = EnMinifrog_ContinueChoirCutscene;
this->flags &= ~(0x2 << MINIFROG_YELLOW | 0x2 << MINIFROG_CYAN | 0x2 << MINIFROG_PINK | 0x2 << MINIFROG_BLUE |
0x2 << MINIFROG_WHITE);
globalCtx->func_18798(globalCtx, &D_0400DEA8, 0);
}
}
void EnMinifrog_SetupNextFrogChoir(EnMinifrog* this, GlobalContext* globalCtx) {
u8 frogIndex;
EnMinifrog_Jump(this);
frogIndex = func_801A39F8();
if (frogIndex != MINIFROG_INVALID) {
if (frogIndex == MINIFROG_YELLOW) {
EnMinifrog_SetJumpState(this);
} else {
this->actor.home.rot.z = frogIndex; // This is strange to store the frog index in home z rotation
}
if (!(this->flags & (0x2 << frogIndex))) {
this->flags |= (0x2 << frogIndex);
this->timer--;
}
}
if (this->frog != NULL) {
this->actor.home.rot.z = 0;
this->actionFunc = EnMinifrog_NextFrogMissing;
this->timer = 60;
this->actor.home.rot.y = Actor_YawBetweenActors(&this->actor, &this->frog->actor);
func_801A1F88();
this->flags &= ~0x100;
this->flags &= ~(0x2 << MINIFROG_YELLOW | 0x2 << MINIFROG_CYAN | 0x2 << MINIFROG_PINK | 0x2 << MINIFROG_BLUE |
0x2 << MINIFROG_WHITE);
globalCtx->func_18798(globalCtx, &D_0400DEA8, 0);
} else if (this->timer <= 0) {
this->actionFunc = EnMinifrog_NextFrogReturned;
this->timer = 30;
}
}
void EnMinifrog_BeginChoirCutscene(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog_Jump(this);
if (this->actor.cutscene == -1) {
this->actionFunc = EnMinifrog_SetupNextFrogChoir;
} else if (ActorCutscene_GetCurrentIndex() == 0x7C) {
ActorCutscene_Stop(0x7C);
ActorCutscene_SetIntentToPlay(this->actor.cutscene);
} else if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) {
ActorCutscene_Start(this->actor.cutscene, &this->actor);
this->actionFunc = EnMinifrog_SetupNextFrogChoir;
this->timer = 5;
func_801A1F00(3, 0x5A);
this->flags |= 0x100;
globalCtx->func_18798(globalCtx, &D_0400E2A8, 0);
} else {
ActorCutscene_SetIntentToPlay(this->actor.cutscene);
}
}
void EnMinifrog_EndChoir(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog_TurnToPlayer(this);
EnMinifrog_Jump(this);
if (func_800B84D0(&this->actor, globalCtx)) {
func_801518B0(globalCtx, 0xD7E, &this->actor); // "Let us do it again sometime."
this->actionFunc = EnMinifrog_YellowFrogDialog;
} else {
func_800B8500(&this->actor, globalCtx, 1000.0f, 1000.0f, -1);
}
}
void EnMinifrog_GetFrogHP(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog_TurnToPlayer(this);
EnMinifrog_Jump(this);
if (Actor_HasParent(&this->actor, globalCtx)) {
this->actor.parent = NULL;
this->actionFunc = EnMinifrog_EndChoir;
this->actor.flags |= 0x10000;
func_800B8500(&this->actor, globalCtx, 1000.0f, 1000.0f, 0);
} else {
func_800B8A1C(&this->actor, globalCtx, GI_HEART_PIECE, 10000.0f, 50.0f);
}
}
void EnMinifrog_YellowFrogDialog(EnMinifrog* this, GlobalContext* globalCtx) {
EnMinifrog_TurnToPlayer(this);
EnMinifrog_Jump(this);
switch (func_80152498(&globalCtx->msgCtx)) {
case 4:
if (func_80147624(globalCtx)) {
switch (globalCtx->msgCtx.choiceIndex) {
case 0: // Yes
func_8019F208();
this->actionFunc = EnMinifrog_BeginChoirCutscene;
globalCtx->msgCtx.unk11F10 = 0;
break;
case 1: // No
func_8019F230();
func_80151938(globalCtx, 0xD7E); // "Let us do it again sometime."
break;
}
}
break;
case 5:
if (func_80147624(globalCtx)) {
EnMinifrog_SetJumpState(this);
switch (globalCtx->msgCtx.unk11F04) {
case 0xD76: // "I have been waiting for you, Don Gero. Forgive me if I'm mistaken, but it looks like
// you've lost a little weight..."
func_80151938(globalCtx, globalCtx->msgCtx.unk11F04 + 1);
this->actor.flags &= ~0x10000;
gSaveContext.weekEventReg[34] |= 1; // Spoken to MINIFROG_YELLOW
break;
case 0xD78: // "Unfortunately, it seems not all of our members have gathered."
case 0xD79: // "Perhaps it is because winter was too long? They must not have realized that spring
// has come to the mountains..."
case 0xD7A: // "And when the great Don Gero has come for us, too...What a pity."
case 0xD7F: // "Well, if it isn't the great Don Gero."
func_80151938(globalCtx, globalCtx->msgCtx.unk11F04 + 1);
break;
case 0xD77: // "Let us begin our chorus"
this->actionFunc = EnMinifrog_BeginChoirCutscene;
globalCtx->msgCtx.unk11F10 = 0;
break;
case 0xD7C: // "The conducting was spectacular. And all of our members rose to the occasion!"
if (gSaveContext.weekEventReg[35] & 0x80) { // Obtained Heart Piece
func_80151938(globalCtx, 0xD7E);
} else {
func_80151938(globalCtx, 0xD7D); // Get Heart Piece
gSaveContext.weekEventReg[35] |= 0x80;
}
break;
case 0xD7D: // "This is how deeply we were moved by your spectacular conducting..."
func_801477B4(globalCtx);
this->actionFunc = EnMinifrog_GetFrogHP;
EnMinifrog_GetFrogHP(this, globalCtx);
break;
case 0xD7B: // "Where in the world could the other members be, and what could they be doing?"
case 0xD7E: // "Let us do it again sometime."
default:
func_801477B4(globalCtx);
this->actionFunc = EnMinifrog_SetupYellowFrogDialog;
this->actor.flags &= ~0x10000;
break;
}
}
}
}
void EnMinifrog_SetupYellowFrogDialog(EnMinifrog* this, GlobalContext* globalCtx) {
Math_ScaledStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 0x180);
this->actor.world.rot.y = this->actor.shape.rot.y;
EnMinifrog_TurnToPlayer(this);
EnMinifrog_Jump(this);
EnMinifrog_JumpTimer(this);
if (func_800B84D0(&this->actor, globalCtx)) {
this->actionFunc = EnMinifrog_YellowFrogDialog;
if (!(gSaveContext.weekEventReg[34] & 1)) { // Not spoken with MINIFROG_YELLOW
func_801518B0(globalCtx, 0xD76, &this->actor); // "I have been waiting for you, Don Gero. Forgive me if I'm mistaken, but it
// looks like you've lost a little weight..."
} else {
func_801518B0(globalCtx, 0xD7F, &this->actor); // "Well, if it isn't the great Don Gero."
}
} else if ((this->actor.xzDistToPlayer < 150.0f) && (Actor_IsLinkFacingActor(&this->actor, 0x3000, globalCtx) || ((this->actor.flags & 0x10000) == 0x10000)) && func_8012403C(globalCtx) == 0xD) {
func_800B8614(&this->actor, globalCtx, 160.0f);
}
}
void EnMinifrog_Update(Actor* thisx, GlobalContext* globalCtx) {
EnMinifrog* this = THIS;
s32 pad;
this->actionFunc(this, globalCtx);
Actor_SetVelocityAndMoveYRotationAndGravity(&this->actor);
func_800B78B8(globalCtx, &this->actor, 25.0f, 12.0f, 0.0f, 0x1D);
Collider_UpdateCylinder(&this->actor, &this->collider);
CollisionCheck_SetOC(globalCtx, &globalCtx->colCheckCtx, &this->collider.base);
this->actor.focus.rot.y = this->actor.shape.rot.y;
}
void EnMinifrog_UpdateMissingFrog(Actor* thisx, GlobalContext* globalCtx) {
EnMinifrog* this = THIS;
EnMinifrog* missingFrog;
missingFrog = this->frog;
if ((missingFrog != NULL) && (missingFrog->actor.home.rot.z == (this->actor.params & 0xF))) {
missingFrog->frog = this;
}
}
s32 EnMinifrog_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
if (limbIndex == 1) {
pos->z -= 500.0f;
}
if ((limbIndex == 7) || (limbIndex == 8)) {
*dList = NULL;
}
return 0;
}
void EnMinifrog_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
EnMinifrog* this = THIS;
if ((limbIndex == 7) || (limbIndex == 8)) {
OPEN_DISPS(globalCtx->state.gfxCtx);
SysMatrix_NormalizeXYZ(&globalCtx->unk187FC);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_OPA_DISP++, *dList);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}
if (limbIndex == 4) {
SysMatrix_GetStateTranslation(&this->actor.focus.pos);
}
}
static Color_RGBA8 sEnMinifrogColor[] = {
{ 200, 170, 0, 255 }, { 0, 170, 200, 255 }, { 210, 120, 100, 255 }, { 120, 130, 230, 255 }, { 190, 190, 190, 255 },
};
void EnMinifrog_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnMinifrog* this = THIS;
Color_RGBA8* envColor;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C28C(globalCtx->state.gfxCtx);
envColor = &sEnMinifrogColor[this->frogIndex];
gSPSegment(POLY_OPA_DISP++, 0x08, D_808A4D74[0]);
gSPSegment(POLY_OPA_DISP++, 0x09, D_808A4D74[0]);
gDPSetEnvColor(POLY_OPA_DISP++, envColor->r, envColor->g, envColor->b, envColor->a);
SkelAnime_DrawSV(globalCtx, this->skelAnime.skeleton, this->skelAnime.limbDrawTbl, this->skelAnime.dListCount,
EnMinifrog_OverrideLimbDraw, EnMinifrog_PostLimbDraw, &this->actor);
CLOSE_DISPS(globalCtx->state.gfxCtx);
}

View File

@ -5,9 +5,37 @@
struct EnMinifrog;
typedef void (*EnMinifrogActionFunc)(struct EnMinifrog*, GlobalContext*);
#define EN_MINIFROG_IS_RETURNED(this) ((((this)->actor.params)&0xF0) >> 4)
typedef enum {
/* 0x00 */ MINIFROG_YELLOW, // Mountain Village
/* 0x01 */ MINIFROG_CYAN, // Woodfall Temple
/* 0x02 */ MINIFROG_PINK, // Great Bay Temple
/* 0x03 */ MINIFROG_BLUE, // Southern Swamp
/* 0x04 */ MINIFROG_WHITE, // Laundry Pool
/* 0xFF */ MINIFROG_INVALID = 0xFF // -1
} MinifrogType;
typedef enum {
/* 0x00 */ MINIFROG_STATE_JUMP,
/* 0x01 */ MINIFROG_STATE_AIR,
/* 0x02 */ MINIFROG_STATE_GROUND
} MinifrogJumpState;
typedef struct EnMinifrog {
/* 0x000 */ Actor actor;
/* 0x144 */ char unk_144[0x1C0];
/* 0x144 */ SkelAnime skelAnime;
/* 0x188 */ Vec3s limbDrawTable[24];
/* 0x218 */ Vec3s transitionDrawTable[24];
/* 0x2A8 */ EnMinifrogActionFunc actionFunc;
/* 0x2AC */ struct EnMinifrog* frog;
/* 0x2B0 */ s16 frogIndex;
/* 0x2B2 */ s16 jumpState;
/* 0x2B4 */ s16 timer;
/* 0x2B6 */ u16 flags;
/* 0x2B8 */ ColliderCylinder collider;
} EnMinifrog; // size = 0x304
extern const ActorInit En_Minifrog_InitVars;

View File

@ -5695,31 +5695,31 @@
0x808A34B8:("EnTorch2_Draw",),
0x808A3670:("EnMinifrog_Init",),
0x808A38E4:("EnMinifrog_Destroy",),
0x808A3930:("func_808A3930",),
0x808A3980:("func_808A3980",),
0x808A39EC:("func_808A39EC",),
0x808A3A44:("func_808A3A44",),
0x808A3B04:("func_808A3B04",),
0x808A3B3C:("func_808A3B3C",),
0x808A3B74:("func_808A3B74",),
0x808A3DA8:("func_808A3DA8",),
0x808A3F88:("func_808A3F88",),
0x808A4040:("func_808A4040",),
0x808A410C:("func_808A410C",),
0x808A41A0:("func_808A41A0",),
0x808A4214:("func_808A4214",),
0x808A42D8:("func_808A42D8",),
0x808A4328:("func_808A4328",),
0x808A43A4:("func_808A43A4",),
0x808A44BC:("func_808A44BC",),
0x808A45A8:("func_808A45A8",),
0x808A4634:("func_808A4634",),
0x808A46E8:("func_808A46E8",),
0x808A4914:("func_808A4914",),
0x808A3930:("EnMinifrog_GetFrog",),
0x808A3980:("EnMinifrog_SetJumpState",),
0x808A39EC:("EnMinifrog_JumpTimer",),
0x808A3A44:("EnMinifrog_Jump",),
0x808A3B04:("EnMinifrog_TurnToPlayer",),
0x808A3B3C:("EnMinifrog_TurnToMissingFrog",),
0x808A3B74:("EnMinifrog_SetCamera",),
0x808A3DA8:("EnMinifrog_ReturnFrogCutscene",),
0x808A3F88:("EnMinifrog_SpawnGrowAndShrink",),
0x808A4040:("EnMinifrog_Idle",),
0x808A410C:("EnMinifrog_SetupNextFrogInit",),
0x808A41A0:("EnMinifrog_CheckChoirSuccess",),
0x808A4214:("EnMinifrog_ContinueChoirCutscene",),
0x808A42D8:("EnMinifrog_NextFrogMissing",),
0x808A4328:("EnMinifrog_NextFrogReturned",),
0x808A43A4:("EnMinifrog_SetupNextFrogChoir",),
0x808A44BC:("EnMinifrog_BeginChoirCutscene",),
0x808A45A8:("EnMinifrog_EndChoir",),
0x808A4634:("EnMinifrog_GetFrogHP",),
0x808A46E8:("EnMinifrog_YellowFrogDialog",),
0x808A4914:("EnMinifrog_SetupYellowFrogDialog",),
0x808A4A30:("EnMinifrog_Update",),
0x808A4AC8:("func_808A4AC8",),
0x808A4AF8:("func_808A4AF8",),
0x808A4B3C:("func_808A4B3C",),
0x808A4AC8:("EnMinifrog_UpdateMissingFrog",),
0x808A4AF8:("EnMinifrog_OverrideLimbDraw",),
0x808A4B3C:("EnMinifrog_PostLimbDraw",),
0x808A4C14:("EnMinifrog_Draw",),
0x808A5050:("func_808A5050",),
0x808A52A8:("func_808A52A8",),