diff --git a/assets/xml/objects/object_hs.xml b/assets/xml/objects/object_hs.xml
index 0d36c4ff1a..ae025f327c 100644
--- a/assets/xml/objects/object_hs.xml
+++ b/assets/xml/objects/object_hs.xml
@@ -1,8 +1,9 @@
+
-
-
-
+
+
+
@@ -13,35 +14,38 @@
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
+
diff --git a/assets/xml/objects/object_niw.xml b/assets/xml/objects/object_niw.xml
index e494265608..0e533fb6e6 100644
--- a/assets/xml/objects/object_niw.xml
+++ b/assets/xml/objects/object_niw.xml
@@ -1,38 +1,40 @@
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/xml/objects/object_nwc.xml b/assets/xml/objects/object_nwc.xml
index 77b395b581..8c67159cef 100644
--- a/assets/xml/objects/object_nwc.xml
+++ b/assets/xml/objects/object_nwc.xml
@@ -1,29 +1,57 @@
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
diff --git a/include/functions.h b/include/functions.h
index e3f700d723..0e12b35a5f 100644
--- a/include/functions.h
+++ b/include/functions.h
@@ -3498,7 +3498,7 @@ void func_801A0238(s32 arg0, s32 arg1);
// void func_801A05F0(void);
void func_801A0654(Vec3f* arg0, u16 sfxId, s32 arg2);
void func_801A0810(Vec3f* arg0, u16 sfxId, u8 arg2);
-// void func_801A0868(void);
+void func_801A0868(Vec3f* pos, u16 sfxId, u8 val);
// void func_801A09D4(void);
// void Audio_SplitBgmChannels(void);
// void func_801A0E44(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_TYPE4 param_7);
diff --git a/spec b/spec
index a92016e254..5cb8e71236 100644
--- a/spec
+++ b/spec
@@ -1510,8 +1510,7 @@ beginseg
name "ovl_En_Nwc"
compress
include "build/src/overlays/actors/ovl_En_Nwc/z_en_nwc.o"
- include "build/data/ovl_En_Nwc/ovl_En_Nwc.data.o"
- include "build/data/ovl_En_Nwc/ovl_En_Nwc.reloc.o"
+ include "build/src/overlays/actors/ovl_En_Nwc/ovl_En_Nwc_reloc.o"
endseg
beginseg
diff --git a/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c b/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c
index b100f692ff..548e1e68df 100644
--- a/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c
+++ b/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.c
@@ -1,7 +1,7 @@
/*
* File: z_en_attack_niw.c
* Overlay: ovl_En_Attack_Niw
- * Description: Attacking cucco
+ * Description: Attacking Cucco
*/
#include "z_en_attack_niw.h"
@@ -16,9 +16,9 @@ void EnAttackNiw_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnAttackNiw_Update(Actor* thisx, GlobalContext* globalCtx);
void EnAttackNiw_Draw(Actor* thisx, GlobalContext* globalCtx);
-void func_80958634(EnAttackNiw* this, GlobalContext* globalCtx);
-void func_80958974(EnAttackNiw* this, GlobalContext* globalCtx);
-void func_80958BE4(EnAttackNiw* this, GlobalContext* globalCtx);
+void EnAttackNiw_EnterViewFromOffscreen(EnAttackNiw* this, GlobalContext* globalCtx);
+void EnAttackNiw_AimAtPlayer(EnAttackNiw* this, GlobalContext* globalCtx);
+void EnAttackNiw_FlyAway(EnAttackNiw* this, GlobalContext* globalCtx);
const ActorInit En_Attack_Niw_InitVars = {
ACTOR_EN_ATTACK_NIW,
@@ -43,289 +43,305 @@ void EnAttackNiw_Init(Actor* thisx, GlobalContext* globalCtx) {
Actor_ProcessInitChain(&this->actor, sInitChain);
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 25.0f);
- SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_niw_Skel_002530, &object_niw_Anim_0000E8, this->jointTable,
- this->morphTable, OBJECT_NIW_LIMB_MAX);
+ SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gNiwSkeleton, &gNiwIdleAnim, this->jointTable, this->morphTable,
+ NIW_LIMB_MAX);
+ // probably copy pasted from EnNiw, which has this same code, but AttackNiw has no params
if (this->actor.params < 0) {
- this->actor.params = 0;
+ this->actor.params = ATTACK_NIW_REGULAR;
}
Actor_SetScale(&this->actor, 0.01f);
this->actor.gravity = 0.0f;
- this->unk_290.x = randPlusMinusPoint5Scaled(100.0f);
- this->unk_290.y = randPlusMinusPoint5Scaled(10.0f);
- this->unk_290.z = randPlusMinusPoint5Scaled(100.0f);
+ this->randomTargetCenterOffset.x = randPlusMinusPoint5Scaled(100.0f);
+ this->randomTargetCenterOffset.y = randPlusMinusPoint5Scaled(10.0f);
+ this->randomTargetCenterOffset.z = randPlusMinusPoint5Scaled(100.0f);
Actor_SetScale(&this->actor, 0.01f);
- this->actor.flags &= ~ACTOR_FLAG_1;
+ this->actor.flags &= ~ACTOR_FLAG_1; // Unnecessary: this actor does not start with this flag
this->actor.shape.rot.y = this->actor.world.rot.y = (Rand_ZeroOne() - 0.5f) * 60000.0f;
- this->actionFunc = func_80958634;
+ this->actionFunc = EnAttackNiw_EnterViewFromOffscreen;
}
void EnAttackNiw_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnAttackNiw* this = THIS;
EnNiw* parent = (EnNiw*)this->actor.parent;
- if ((thisx->parent != NULL) && (thisx->parent->update != NULL)) {
- if (parent->unk290 > 0) {
- parent->unk290--;
+ if (this->actor.parent != NULL && this->actor.parent->update != NULL) {
+ if (parent->attackNiwCount > 0) {
+ parent->attackNiwCount--;
}
}
}
-void func_80958228(EnAttackNiw* this, GlobalContext* globalCtx, s16 arg2) {
- if (this->unk_24C == 0) {
- if (arg2 == 0) {
- this->unk_25C = 0.0f;
+/**
+ * Summary: instead of using SkelAnime animations AttackNiw modifies head+wings directly to create animations
+ *
+ * EnNiw has its own version of this function, probably copy paste since AttackNiw only uses two animationState (2/5)
+ */
+void EnAttackNiw_AnimateWingHead(EnAttackNiw* this, GlobalContext* globalCtx, s16 animationState) {
+ if (this->unkTimer24C == 0) {
+ if (animationState == 0) {
+ this->targetBodyRotY = 0.0f;
} else {
- this->unk_25C = -10000.0f;
+ this->targetBodyRotY = -10000.0f;
}
- this->unk_286++;
- this->unk_24C = 3;
- if ((this->unk_286 % 2) == 0) {
- this->unk_25C = 0.0f;
- if (arg2 == 0) {
- this->unk_24C = Rand_ZeroFloat(30.0f);
+
+ this->clearRotYToggleTimer++;
+ this->unkTimer24C = 3;
+ if ((this->clearRotYToggleTimer % 2) == 0) {
+ this->targetBodyRotY = 0.0f;
+ if (animationState == 0) {
+ this->unkTimer24C = Rand_ZeroFloat(30.0f);
}
}
}
- if (this->unk_250 == 0) {
- this->unk_28A++;
- this->unk_28A &= 1;
+ if (this->unkTimer250 == 0) {
+ this->unkToggle28A++;
+ this->unkToggle28A &= 1;
- switch (arg2) {
- case 0:
- this->unk_264 = 0.0f;
- this->unk_260 = 0.0f;
+ switch (animationState) { // only case 2 and 5 are ever called in AttackNiw
+ case NIW_ANIMATION_STILL:
+ this->targetLeftWingRotZ = 0.0f;
+ this->targetRightWingRotZ = 0.0f;
break;
- case 1:
- this->unk_250 = 3;
- this->unk_264 = 7000.0f;
- this->unk_260 = 7000.0f;
- if (this->unk_28A == 0) {
- this->unk_264 = 0.0f;
- this->unk_260 = 0.0f;
+ case NIW_ANIMATION_HEAD_PECKING:
+ this->unkTimer250 = 3;
+ this->targetLeftWingRotZ = 7000.0f;
+ this->targetRightWingRotZ = 7000.0f;
+ if (this->unkToggle28A == 0) {
+ this->targetLeftWingRotZ = 0.0f;
+ this->targetRightWingRotZ = 0.0f;
}
break;
- case 2:
- this->unk_250 = 2;
- this->unk_264 = -10000.0f;
- this->unk_260 = -10000.0f;
- this->unk_278 = 25000.0f;
- this->unk_270 = 25000.0f;
- this->unk_27C = 6000.0f;
- this->unk_274 = 6000.0f;
- if (this->unk_28A == 0) {
- this->unk_270 = 8000.0f;
- this->unk_278 = 8000.0f;
+ case NIW_ANIMATION_PECKING_AND_WAVING:
+ this->unkTimer250 = 2;
+ this->targetLeftWingRotZ = -10000.0f;
+ this->targetRightWingRotZ = -10000.0f;
+ this->targetLeftWingRotY = 25000.0f;
+ this->targetRightWingRotY = 25000.0f;
+ this->targetLeftWingRotX = 6000.0f;
+ this->targetRightWingRotX = 6000.0f;
+ if (this->unkToggle28A == 0) {
+ this->targetRightWingRotY = 8000.0f;
+ this->targetLeftWingRotY = 8000.0f;
}
break;
- case 3:
- this->unk_250 = 2;
- this->unk_270 = 10000.0f;
- this->unk_278 = 10000.0f;
- if (this->unk_28A == 0) {
- this->unk_270 = 3000.0f;
- this->unk_278 = 3000.0f;
+ case NIW_ANIMATION_PECKING_AND_FORFLAPPING:
+ this->unkTimer250 = 2;
+ this->targetRightWingRotY = 10000.0f;
+ this->targetLeftWingRotY = 10000.0f;
+ if (this->unkToggle28A == 0) {
+ this->targetRightWingRotY = 3000.0f;
+ this->targetLeftWingRotY = 3000.0f;
}
break;
- case 4:
- this->unk_24E = 5;
- this->unk_24C = this->unk_24E;
+ case NIW_ANIMATION_FREEZE:
+ this->unusedTimer24E = 5;
+ this->unkTimer24C = this->unusedTimer24E;
break;
- case 5:
- this->unk_250 = 5;
- this->unk_270 = 14000.0f;
- this->unk_278 = 14000.0f;
- if (this->unk_28A == 0) {
- this->unk_270 = 10000.0f;
- this->unk_278 = 10000.0f;
+ case NIW_ANIMATION_PECKING_SLOW_FORFLAPPING:
+ this->unkTimer250 = 5;
+ this->targetRightWingRotY = 14000.0f;
+ this->targetLeftWingRotY = 14000.0f;
+ if (this->unkToggle28A == 0) {
+ this->targetRightWingRotY = 10000.0f;
+ this->targetLeftWingRotY = 10000.0f;
}
break;
}
}
- if (this->unk_280 != this->unk_2B8) {
- Math_ApproachF(&this->unk_2B8, this->unk_280, 0.5f, 4000.0f);
+ if (this->targetHeadRotZ != this->headRotZ) {
+ Math_ApproachF(&this->headRotZ, this->targetHeadRotZ, 0.5f, 4000.0f);
}
- if (this->unk_25C != this->unk_2B4) {
- Math_ApproachF(&this->unk_2B4, this->unk_25C, 0.5f, 4000.0f);
+ if (this->targetBodyRotY != this->upperBodyRotY) {
+ Math_ApproachF(&this->upperBodyRotY, this->targetBodyRotY, 0.5f, 4000.0f);
}
- if (this->unk_264 != this->unk_29C) {
- Math_ApproachF(&this->unk_29C, this->unk_264, 0.8f, 7000.0f);
+ if (this->targetLeftWingRotZ != this->leftWingRotZ) {
+ Math_ApproachF(&this->leftWingRotZ, this->targetLeftWingRotZ, 0.8f, 7000.0f);
}
- if (this->unk_278 != this->unk_2A0) {
- Math_ApproachF(&this->unk_2A0, this->unk_278, 0.8f, 7000.0f);
+ if (this->targetLeftWingRotY != this->leftWingRotY) {
+ Math_ApproachF(&this->leftWingRotY, this->targetLeftWingRotY, 0.8f, 7000.0f);
}
- if (this->unk_27C != this->unk_2A4) {
- Math_ApproachF(&this->unk_2A4, this->unk_27C, 0.8f, 7000.0f);
+ if (this->targetLeftWingRotX != this->leftWingRotX) {
+ Math_ApproachF(&this->leftWingRotX, this->targetLeftWingRotX, 0.8f, 7000.0f);
}
- if (this->unk_260 != this->unk_2A8) {
- Math_ApproachF(&this->unk_2A8, this->unk_260, 0.8f, 7000.0f);
+ if (this->targetRightWingRotZ != this->rightWingRotZ) {
+ Math_ApproachF(&this->rightWingRotZ, this->targetRightWingRotZ, 0.8f, 7000.0f);
}
- if (this->unk_270 != this->unk_2AC) {
- Math_ApproachF(&this->unk_2AC, this->unk_270, 0.8f, 7000.0f);
+ if (this->targetRightWingRotY != this->rightWingRotY) {
+ Math_ApproachF(&this->rightWingRotY, this->targetRightWingRotY, 0.8f, 7000.0f);
}
- if (this->unk_274 != this->unk_2B0) {
- Math_ApproachF(&this->unk_2B0, this->unk_274, 0.8f, 7000.0f);
+ if (this->targetRightWingRotX != this->rightWingRotX) {
+ Math_ApproachF(&this->rightWingRotX, this->targetRightWingRotX, 0.8f, 7000.0f);
}
}
-s32 func_809585B0(EnAttackNiw* this, GlobalContext* globalCtx) {
- s16 sp1E;
- s16 sp1C;
+s32 EnAttackNiw_IsOnScreen(EnAttackNiw* this, GlobalContext* globalCtx) {
+ s16 posX;
+ s16 posY;
- Actor_SetFocus(&this->actor, this->unk_2DC);
- Actor_GetScreenPos(globalCtx, &this->actor, &sp1E, &sp1C);
+ Actor_SetFocus(&this->actor, this->targetHeight);
+ Actor_GetScreenPos(globalCtx, &this->actor, &posX, &posY);
- if ((this->actor.projectedPos.z < -20.0f) || (sp1E < 0) || (sp1E > SCREEN_WIDTH) || (sp1C < 0) ||
- (sp1C > SCREEN_HEIGHT)) {
+ if ((this->actor.projectedPos.z < -20.0f) || (posX < 0) || (posX > SCREEN_WIDTH) || (posY < 0) ||
+ (posY > SCREEN_HEIGHT)) {
return false;
}
return true;
}
-void func_80958634(EnAttackNiw* this, GlobalContext* globalCtx) {
- s16 sp4E;
- s16 sp4C;
- Vec3f temp;
- Vec3f sp34;
+void EnAttackNiw_EnterViewFromOffscreen(EnAttackNiw* this, GlobalContext* globalCtx) {
+ s16 posX;
+ s16 posY;
+ Vec3f viewOffset;
+ Vec3f flightTarget;
s32 pad;
this->actor.speedXZ = 10.0f;
- temp.x = (this->unk_290.x + globalCtx->view.at.x) - globalCtx->view.eye.x;
- temp.y = (this->unk_290.y + globalCtx->view.at.y) - globalCtx->view.eye.y;
- temp.z = (this->unk_290.z + globalCtx->view.at.z) - globalCtx->view.eye.z;
+ // randomTargetCenterOffset is set in _Init, only needs to be set once
+ // but the view is moving, so now we need to re-calculate the spot in space
+ viewOffset.x = this->randomTargetCenterOffset.x + globalCtx->view.at.x - globalCtx->view.eye.x;
+ viewOffset.y = this->randomTargetCenterOffset.y + globalCtx->view.at.y - globalCtx->view.eye.y;
+ viewOffset.z = this->randomTargetCenterOffset.z + globalCtx->view.at.z - globalCtx->view.eye.z;
- sp34.x = globalCtx->view.at.x + temp.x;
- sp34.y = globalCtx->view.at.y + temp.y;
- sp34.z = globalCtx->view.at.z + temp.z;
+ // this is the 3D spot in space where the cucco is trying to fly into (until it lands or gets close)
+ flightTarget.x = globalCtx->view.at.x + viewOffset.x;
+ flightTarget.y = globalCtx->view.at.y + viewOffset.y;
+ flightTarget.z = globalCtx->view.at.z + viewOffset.z;
- this->unk_2CC = Math_Vec3f_Yaw(&this->actor.world.pos, &sp34);
- this->unk_2C8 = Math_Vec3f_Pitch(&this->actor.world.pos, &sp34) * -1.0f;
+ this->targetRotY = Math_Vec3f_Yaw(&this->actor.world.pos, &flightTarget);
+ this->targetRotX = Math_Vec3f_Pitch(&this->actor.world.pos, &flightTarget) * -1.0f;
- Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_2CC, 5, this->unk_2D4, 0);
- Math_SmoothStepToS(&this->actor.world.rot.x, this->unk_2C8, 5, this->unk_2D4, 0);
- Math_ApproachF(&this->unk_2D4, 5000.0f, 1.0f, 100.0f);
+ Math_SmoothStepToS(&this->actor.world.rot.y, this->targetRotY, 5, this->rotStep, 0);
+ Math_SmoothStepToS(&this->actor.world.rot.x, this->targetRotX, 5, this->rotStep, 0);
+ Math_ApproachF(&this->rotStep, 5000.0f, 1.0f, 100.0f);
- Actor_SetFocus(&this->actor, this->unk_2DC);
- Actor_GetScreenPos(globalCtx, &this->actor, &sp4E, &sp4C);
+ Actor_SetFocus(&this->actor, this->targetHeight);
+ Actor_GetScreenPos(globalCtx, &this->actor, &posX, &posY);
- if (this->actor.bgCheckFlags & 8) {
- this->unk_2CC = this->actor.yawTowardsPlayer;
- this->unk_2C8 = this->actor.world.rot.x - 3000.0f;
- this->unk_252 = 0;
- this->unk_254 = 100;
- this->unk_2D4 = 0.0f;
- this->unk_27C = 0.0f;
- this->unk_274 = 0.0f;
- this->unk_250 = this->unk_252;
- this->unk_24E = this->unk_252;
- this->unk_24C = this->unk_252;
+ if (this->actor.bgCheckFlags & 8) { // touching a wall
+ this->targetRotY = this->actor.yawTowardsPlayer;
+ this->targetRotX = this->actor.world.rot.x - 3000.0f;
+ this->hopTimer = 0;
+ this->randomAngleChangeTimer = 100;
+ this->rotStep = 0.0f;
+ this->targetLeftWingRotX = 0.0f;
+ this->targetRightWingRotX = 0.0f;
+ this->unkTimer250 = this->hopTimer;
+ this->unusedTimer24E = this->hopTimer;
+ this->unkTimer24C = this->hopTimer;
this->actor.gravity = -0.2f;
- this->unk_280 = 0.0f;
- this->actionFunc = func_80958974;
- this->unk_2D8 = 5.0f;
- } else if (((this->actor.projectedPos.z > 0.0f) && (fabsf(sp34.x - this->actor.world.pos.x) < 50.0f) &&
- (fabsf(sp34.y - this->actor.world.pos.y) < 50.0f) &&
- (fabsf(sp34.z - this->actor.world.pos.z) < 50.0f)) ||
- (this->actor.bgCheckFlags & 1)) {
- this->unk_252 = 0;
- this->unk_250 = this->unk_252;
- this->unk_24E = this->unk_252;
- this->unk_24C = this->unk_252;
- this->unk_2D4 = 0.0f;
- this->unk_274 = 0.0f;
- this->unk_27C = 0.0f;
- this->unk_2CC = this->actor.yawTowardsPlayer;
- this->unk_2C8 = this->actor.world.rot.x - 2000.0f;
- this->actor.gravity = -0.2f;
- this->unk_280 = 0.0f;
- this->actionFunc = func_80958974;
- this->unk_2D8 = 5.0f;
- } else {
- this->unk_24C = 10;
- this->unk_25C = -10000.0f;
- this->unk_280 = -3000.0f;
- func_80958228(this, globalCtx, 2);
+ this->targetHeadRotZ = 0.0f;
+ this->actionFunc = EnAttackNiw_AimAtPlayer;
+ this->targetXZSpeed = 5.0f;
+
+ } else if (((this->actor.projectedPos.z > 0.0f) && (fabsf(flightTarget.x - this->actor.world.pos.x) < 50.0f) &&
+ (fabsf(flightTarget.y - this->actor.world.pos.y) < 50.0f) &&
+ (fabsf(flightTarget.z - this->actor.world.pos.z) < 50.0f)) ||
+ (this->actor.bgCheckFlags & 1)) { // touching ground or with close distance of target
+ // reset state
+ this->hopTimer = 0;
+ this->unkTimer250 = this->hopTimer;
+ this->unusedTimer24E = this->hopTimer;
+ this->unkTimer24C = this->hopTimer;
+ this->rotStep = 0.0f;
+ this->targetRightWingRotX = 0.0f;
+ this->targetLeftWingRotX = 0.0f;
+
+ this->targetRotY = this->actor.yawTowardsPlayer; // start turn to face player
+ this->targetRotX = this->actor.world.rot.x - 2000.0f; // bank into the turn
+ this->actor.gravity = -0.2f; // start gentle decent (no longer flying without gravity)
+ this->targetHeadRotZ = 0.0f;
+ this->actionFunc = EnAttackNiw_AimAtPlayer;
+ this->targetXZSpeed = 5.0f;
+
+ } else { // keep flying at the flightTarget for now
+ this->unkTimer24C = 10;
+ this->targetBodyRotY = -10000.0f;
+ this->targetHeadRotZ = -3000.0f;
+ EnAttackNiw_AnimateWingHead(this, globalCtx, NIW_ANIMATION_PECKING_AND_WAVING);
}
}
-void func_80958974(EnAttackNiw* this, GlobalContext* globalCtx) {
- if (!func_809585B0(this, globalCtx)) {
+void EnAttackNiw_AimAtPlayer(EnAttackNiw* this, GlobalContext* globalCtx) {
+ if (!EnAttackNiw_IsOnScreen(this, globalCtx)) {
Actor_MarkForDeath(&this->actor);
return;
}
- if (this->actor.bgCheckFlags & 1) {
- if (this->unk_252 == 0) {
- this->unk_252 = 3;
+ if (this->actor.bgCheckFlags & 1) { // touching floor
+ if (this->hopTimer == 0) {
+ this->hopTimer = 3;
this->actor.velocity.y = 3.5f;
}
- if (this->actor.gravity != -2.0f) {
- this->unk_2CC = this->actor.yawTowardsPlayer;
- this->unk_25A = 50;
- this->unk_254 = 100;
- this->unk_270 = 14000.0f;
- this->unk_278 = 14000.0f;
- this->unk_274 = 0.0f;
- this->unk_27C = 0.0f;
- this->unk_260 = 0.0f;
- this->unk_264 = 0.0f;
- this->unk_2C8 = 0.0f;
+ if (this->actor.gravity != -2.0f) { // first landing
+ this->targetRotY = this->actor.yawTowardsPlayer;
+ this->unkTimer25A = 50;
+ this->randomAngleChangeTimer = 100;
+ this->targetRightWingRotY = 14000.0f;
+ this->targetLeftWingRotY = 14000.0f;
+ this->targetRightWingRotX = 0.0f;
+ this->targetLeftWingRotX = 0.0f;
+ this->targetRightWingRotZ = 0.0f;
+ this->targetLeftWingRotZ = 0.0f;
+ this->targetRotX = 0.0f;
this->actor.gravity = -2.0f;
}
}
- if (this->unk_254 == 50) {
- this->unk_2CC = randPlusMinusPoint5Scaled(200.0f) + this->actor.yawTowardsPlayer;
+ if (this->randomAngleChangeTimer == 50) {
+ this->targetRotY = randPlusMinusPoint5Scaled(200.0f) + this->actor.yawTowardsPlayer;
}
- Math_SmoothStepToS(&this->actor.world.rot.y, this->unk_2CC, 2, this->unk_2D4, 0);
- Math_SmoothStepToS(&this->actor.world.rot.x, this->unk_2C8, 2, this->unk_2D4, 0);
- Math_ApproachF(&this->unk_2D4, 10000.0f, 1.0f, 1000.0f);
- Math_ApproachF(&this->actor.speedXZ, this->unk_2D8, 0.9f, 1.0f);
+ Math_SmoothStepToS(&this->actor.world.rot.y, this->targetRotY, 2, this->rotStep, 0);
+ Math_SmoothStepToS(&this->actor.world.rot.x, this->targetRotX, 2, this->rotStep, 0);
+ Math_ApproachF(&this->rotStep, 10000.0f, 1.0f, 1000.0f);
+ Math_ApproachF(&this->actor.speedXZ, this->targetXZSpeed, 0.9f, 1.0f);
- if ((this->actor.gravity == -2.0f) && (this->unk_25A == 0) &&
- ((this->actor.bgCheckFlags & 8) || (this->unk_254 == 0))) {
- this->unk_2D8 = 0.0f;
+ if (this->actor.gravity == -2.0f && this->unkTimer25A == 0 &&
+ (this->actor.bgCheckFlags & 8 || this->randomAngleChangeTimer == 0)) {
+ this->targetXZSpeed = 0.0f;
this->actor.gravity = 0.0f;
- this->unk_2D4 = 0.0f;
- this->unk_2C8 = this->actor.world.rot.x - 5000.0f;
- this->actionFunc = func_80958BE4;
- } else if (this->actor.bgCheckFlags & 1) {
- func_80958228(this, globalCtx, 5);
+ this->rotStep = 0.0f;
+ this->targetRotX = this->actor.world.rot.x - 5000.0f;
+ this->actionFunc = EnAttackNiw_FlyAway;
+
+ } else if (this->actor.bgCheckFlags & 1) { // touching floor
+ EnAttackNiw_AnimateWingHead(this, globalCtx, NIW_ANIMATION_PECKING_SLOW_FORFLAPPING);
+
} else {
- func_80958228(this, globalCtx, 2);
+ EnAttackNiw_AnimateWingHead(this, globalCtx, NIW_ANIMATION_PECKING_AND_WAVING);
}
}
-void func_80958BE4(EnAttackNiw* this, GlobalContext* globalCtx) {
- if (!func_809585B0(this, globalCtx)) {
+void EnAttackNiw_FlyAway(EnAttackNiw* this, GlobalContext* globalCtx) {
+ if (!EnAttackNiw_IsOnScreen(this, globalCtx)) {
Actor_MarkForDeath(&this->actor);
return;
}
- Math_SmoothStepToS(&this->actor.world.rot.x, this->unk_2C8, 5, this->unk_2D4, 0);
- Math_ApproachF(&this->unk_2D4, 5000.0f, 1.0f, 100.0f);
+ Math_SmoothStepToS(&this->actor.world.rot.x, this->targetRotX, 5, this->rotStep, 0);
+ Math_ApproachF(&this->rotStep, 5000.0f, 1.0f, 100.0f);
Math_ApproachF(&this->actor.velocity.y, 5.0f, 0.3f, 1.0f);
- func_80958228(this, globalCtx, 2);
+ EnAttackNiw_AnimateWingHead(this, globalCtx, NIW_ANIMATION_PECKING_AND_WAVING);
}
void EnAttackNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
@@ -334,37 +350,17 @@ void EnAttackNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
EnNiw* parent;
Player* player = GET_PLAYER(globalCtx);
s32 pad2;
- Vec3f sp30;
+ Vec3f splashPos;
- this->unk_284++;
+ this->unusedCounter284++;
- if (this->unk_24C != 0) {
- this->unk_24C--;
- }
-
- if (this->unk_250 != 0) {
- this->unk_250--;
- }
-
- if (this->unk_252 != 0) {
- this->unk_252--;
- }
-
- if (this->unk_256 != 0) {
- this->unk_256--;
- }
-
- if (this->unk_258 != 0) {
- this->unk_258--;
- }
-
- if (this->unk_254 != 0) {
- this->unk_254--;
- }
-
- if (this->unk_25A != 0) {
- this->unk_25A--;
- }
+ DECR(this->unkTimer24C);
+ DECR(this->unkTimer250);
+ DECR(this->hopTimer);
+ DECR(this->crySfxTimer);
+ DECR(this->flutterSfxTimer);
+ DECR(this->randomAngleChangeTimer);
+ DECR(this->unkTimer25A);
this->actor.shape.rot = this->actor.world.rot;
this->actor.shape.shadowScale = 15.0f;
@@ -373,45 +369,48 @@ void EnAttackNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, 20.0f, 60.0f, 0x1D);
- if (this->actionFunc == func_80958634) {
+ if (this->actionFunc == EnAttackNiw_EnterViewFromOffscreen) {
Actor_MoveWithoutGravity(&this->actor);
} else {
Actor_MoveWithGravity(&this->actor);
}
- if (this->actor.floorHeight <= -32000.0f) {
+ if (this->actor.floorHeight <= BGCHECK_Y_MIN) { // under the world
Actor_MarkForDeath(&this->actor);
- } else if ((this->actor.bgCheckFlags & 0x20) && (this->actionFunc != func_80958BE4)) {
- Math_Vec3f_Copy(&sp30, &this->actor.world.pos);
- sp30.y += this->actor.depthInWater;
- EffectSsGSplash_Spawn(globalCtx, &sp30, NULL, NULL, 0, 400);
- this->unk_2D4 = 0.0f;
+ } else if ((this->actor.bgCheckFlags & 0x20) && // on or below water
+ (this->actionFunc != EnAttackNiw_FlyAway)) {
+ Math_Vec3f_Copy(&splashPos, &this->actor.world.pos);
+ splashPos.y += this->actor.depthInWater;
+ EffectSsGSplash_Spawn(globalCtx, &splashPos, NULL, NULL, 0, 400);
+ this->rotStep = 0.0f;
this->actor.gravity = 0.0f;
- this->unk_2D8 = 0.0f;
- this->unk_2C8 = this->actor.world.rot.x - 5000.0f;
- this->actionFunc = func_80958BE4;
+ this->targetXZSpeed = 0.0f;
+ this->targetRotX = this->actor.world.rot.x - 5000.0f;
+ this->actionFunc = EnAttackNiw_FlyAway;
+
} else {
- f32 temp = 20.0f;
+ f32 viewOffset = 20.0f;
label:
- if (this->actor.xyzDistToPlayerSq < SQ(temp)) {
+ if (this->actor.xyzDistToPlayerSq < SQ(viewOffset)) {
parent = (EnNiw*)this->actor.parent;
if ((this->actor.parent->update != NULL) && (this->actor.parent != NULL) && (parent != NULL) &&
- (parent->unusedTimer25E == 0) && (player->invincibilityTimer == 0)) {
+ (parent->unkAttackNiwTimer == 0) && (player->invincibilityTimer == 0)) {
+ // this updates some player values based on what we pass, need player decomp to know what this is doing
func_800B8D50(globalCtx, &this->actor, 2.0f, this->actor.world.rot.y, 0.0f, 0x10);
- parent->unusedTimer25E = 70;
+ parent->unkAttackNiwTimer = 70;
}
}
- if (this->unk_256 == 0) {
- this->unk_256 = 30;
+ if (this->crySfxTimer == 0) {
+ this->crySfxTimer = 30;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_A);
}
- if (this->unk_258 == 0) {
- this->unk_258 = 7;
+ if (this->flutterSfxTimer == 0) {
+ this->flutterSfxTimer = 7;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_CHICKEN_FLUTTER);
}
}
@@ -421,24 +420,24 @@ s32 EnAttackNiw_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx**
Actor* thisx) {
EnAttackNiw* this = THIS;
- if (limbIndex == OBJECT_NIW_LIMB_0D) {
- rot->y += (s16)this->unk_2B4;
+ if (limbIndex == NIW_LIMB_UPPER_BODY) {
+ rot->y += (s16)this->upperBodyRotY;
}
- if (limbIndex == OBJECT_NIW_LIMB_0F) {
- rot->z += (s16)this->unk_2B8;
+ if (limbIndex == NIW_LIMB_HEAD) {
+ rot->z += (s16)this->headRotZ;
}
- if (limbIndex == OBJECT_NIW_LIMB_0B) {
- rot->x += (s16)this->unk_2B0;
- rot->y += (s16)this->unk_2AC;
- rot->z += (s16)this->unk_2A8;
+ if (limbIndex == NIW_LIMB_RIGHT_WING_ROOT) {
+ rot->x += (s16)this->rightWingRotX;
+ rot->y += (s16)this->rightWingRotY;
+ rot->z += (s16)this->rightWingRotZ;
}
- if (limbIndex == OBJECT_NIW_LIMB_07) {
- rot->x += (s16)this->unk_2A4;
- rot->y += (s16)this->unk_2A0;
- rot->z += (s16)this->unk_29C;
+ if (limbIndex == NIW_LIMB_LEFT_WING_ROOT) {
+ rot->x += (s16)this->leftWingRotX;
+ rot->y += (s16)this->leftWingRotY;
+ rot->z += (s16)this->leftWingRotZ;
}
return false;
}
diff --git a/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.h b/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.h
index 4d3243ef5c..c4dcaf8d0e 100644
--- a/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.h
+++ b/src/overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.h
@@ -11,49 +11,52 @@ typedef void (*EnAttackNiwActionFunc)(struct EnAttackNiw*, GlobalContext*);
typedef struct EnAttackNiw {
/* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelAnime;
- /* 0x188 */ Vec3s jointTable[OBJECT_NIW_LIMB_MAX];
- /* 0x1E8 */ Vec3s morphTable[OBJECT_NIW_LIMB_MAX];
+ /* 0x188 */ Vec3s jointTable[NIW_LIMB_MAX];
+ /* 0x1E8 */ Vec3s morphTable[NIW_LIMB_MAX];
/* 0x248 */ EnAttackNiwActionFunc actionFunc;
- /* 0x24C */ s16 unk_24C;
- /* 0x24E */ s16 unk_24E;
- /* 0x250 */ s16 unk_250;
- /* 0x252 */ s16 unk_252;
- /* 0x254 */ s16 unk_254;
- /* 0x256 */ s16 unk_256;
- /* 0x258 */ s16 unk_258;
- /* 0x25A */ s16 unk_25A;
- /* 0x25C */ f32 unk_25C;
- /* 0x260 */ f32 unk_260;
- /* 0x264 */ f32 unk_264;
- /* 0x268 */ UNK_TYPE1 unk268[8];
- /* 0x270 */ f32 unk_270;
- /* 0x274 */ f32 unk_274;
- /* 0x278 */ f32 unk_278;
- /* 0x27C */ f32 unk_27C;
- /* 0x280 */ f32 unk_280;
- /* 0x284 */ s16 unk_284;
- /* 0x286 */ s16 unk_286;
- /* 0x288 */ UNK_TYPE1 unk288[2];
- /* 0x28A */ s16 unk_28A;
- /* 0x28C */ UNK_TYPE1 unk28C[4];
- /* 0x290 */ Vec3f unk_290;
- /* 0x29C */ f32 unk_29C;
- /* 0x2A0 */ f32 unk_2A0;
- /* 0x2A4 */ f32 unk_2A4;
- /* 0x2A8 */ f32 unk_2A8;
- /* 0x2AC */ f32 unk_2AC;
- /* 0x2B0 */ f32 unk_2B0;
- /* 0x2B4 */ f32 unk_2B4;
- /* 0x2B8 */ f32 unk_2B8;
- /* 0x2BC */ UNK_TYPE1 unk2BC[0xC];
- /* 0x2C8 */ f32 unk_2C8;
- /* 0x2CC */ f32 unk_2CC;
- /* 0x2D0 */ UNK_TYPE1 unk2D0[4];
- /* 0x2D4 */ f32 unk_2D4;
- /* 0x2D8 */ f32 unk_2D8;
- /* 0x2DC */ f32 unk_2DC;
+ /* 0x24C */ s16 unkTimer24C; // control behavior in _UpdateRotations
+ /* 0x24E */ s16 unusedTimer24E; // set never read
+ /* 0x250 */ s16 unkTimer250; // control behavior in _UpdateRotations
+ /* 0x252 */ s16 hopTimer;
+ /* 0x254 */ s16 randomAngleChangeTimer;
+ /* 0x256 */ s16 crySfxTimer;
+ /* 0x258 */ s16 flutterSfxTimer;
+ /* 0x25A */ s16 unkTimer25A; // set to 50 in run at player, locks fly away without water?
+ /* 0x25C */ f32 targetBodyRotY;
+ /* 0x260 */ f32 targetRightWingRotZ;
+ /* 0x264 */ f32 targetLeftWingRotZ;
+ /* 0x268 */ f32 unusedRotations[2]; // in EnNiw this is an array of targetRot
+ /* 0x270 */ f32 targetRightWingRotY;
+ /* 0x274 */ f32 targetRightWingRotX;
+ /* 0x278 */ f32 targetLeftWingRotY;
+ /* 0x27C */ f32 targetLeftWingRotX;
+ /* 0x280 */ f32 targetHeadRotZ;
+ /* 0x284 */ s16 unusedCounter284; // incremented in _Update, never read
+ /* 0x286 */ s16 clearRotYToggleTimer;
+ /* 0x288 */ UNK_TYPE1 pad288[2];
+ /* 0x28A */ s16 unkToggle28A;
+ /* 0x28C */ UNK_TYPE1 pad28C[4];
+ /* 0x290 */ Vec3f randomTargetCenterOffset; // see EnAttackNiw_EnterViewFromOffscreen
+ /* 0x29C */ f32 leftWingRotZ;
+ /* 0x2A0 */ f32 leftWingRotY;
+ /* 0x2A4 */ f32 leftWingRotX;
+ /* 0x2A8 */ f32 rightWingRotZ;
+ /* 0x2AC */ f32 rightWingRotY;
+ /* 0x2B0 */ f32 rightWingRotX;
+ /* 0x2B4 */ f32 upperBodyRotY;
+ /* 0x2B8 */ f32 headRotZ;
+ /* 0x2BC */ UNK_TYPE1 pad2BC[0xC]; // unused rotations?
+ /* 0x2C8 */ f32 targetRotX;
+ /* 0x2CC */ f32 targetRotY;
+ /* 0x2D0 */ UNK_TYPE1 pad2D0[4];
+ /* 0x2D4 */ f32 rotStep;
+ /* 0x2D8 */ f32 targetXZSpeed;
+ /* 0x2DC */ f32 targetHeight; // never set, but sent to Actor_SetFocus
} EnAttackNiw; // size = 0x2E0
extern const ActorInit En_Attack_Niw_InitVars;
+
+#define ATTACK_NIW_REGULAR 0 // spawned by EnNiw
+
#endif // Z_EN_ATTACK_NIW_H
diff --git a/src/overlays/actors/ovl_En_Hs/z_en_hs.c b/src/overlays/actors/ovl_En_Hs/z_en_hs.c
index e15e3adb3c..5e886bcc01 100644
--- a/src/overlays/actors/ovl_En_Hs/z_en_hs.c
+++ b/src/overlays/actors/ovl_En_Hs/z_en_hs.c
@@ -18,8 +18,8 @@ void EnHs_Draw(Actor* thisx, GlobalContext* globalCtx);
void func_80952FE0(EnHs* this, GlobalContext* globalCtx);
void func_80953098(EnHs* this, GlobalContext* globalCtx);
void func_80953180(EnHs* this, GlobalContext* globalCtx);
-void func_809532C0(EnHs* this, GlobalContext* globalCtx);
-void func_809532D0(EnHs* this, GlobalContext* globalCtx);
+void EnHs_DoNothing(EnHs* this, GlobalContext* globalCtx);
+void EnHs_SceneTransitToBunnyHoodDialogue(EnHs* this, GlobalContext* globalCtx);
void func_80953354(EnHs* this, GlobalContext* globalCtx);
void func_8095345C(EnHs* this, GlobalContext* globalCtx);
@@ -61,12 +61,12 @@ void func_80952C50(EnHs* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
s32 i;
- for (i = 0; i < ARRAY_COUNT(this->unk_2A4); i++) {
- Math_Vec3f_Copy(&this->unk_2A4[i], &player->actor.world.pos);
+ for (i = 0; i < ARRAY_COUNT(this->nwcPos); i++) {
+ Math_Vec3f_Copy(&this->nwcPos[i], &player->actor.world.pos);
}
- this->actor.home.rot.x = 0;
- this->actor.home.rot.z = 0;
+ this->actor.home.rot.x = 0; // reset adult transformed count
+ this->actor.home.rot.z = 0; // reset chick count
}
void EnHs_Init(Actor* thisx, GlobalContext* globalCtx) {
@@ -74,17 +74,19 @@ void EnHs_Init(Actor* thisx, GlobalContext* globalCtx) {
EnHs* this = THIS;
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 36.0f);
- SkelAnime_InitFlex(globalCtx, &this->skelAnime, &object_hs_Skel_006260, &object_hs_Anim_0005C0, this->jointTable,
- this->morphTable, OBJECT_HS_LIMB_MAX);
- Animation_PlayLoop(&this->skelAnime, &object_hs_Anim_0005C0);
+ SkelAnime_InitFlex(globalCtx, &this->skelAnime, &gHsSkeleton, &gHsIdleAnim, this->jointTable, this->morphTable,
+ OBJECT_HS_LIMB_MAX);
+ Animation_PlayLoop(&this->skelAnime, &gHsIdleAnim);
Collider_InitAndSetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
Actor_SetScale(&this->actor, 0.01f);
this->actionFunc = func_8095345C;
+
if (globalCtx->curSpawn == 1) {
this->actor.flags |= ACTOR_FLAG_10000;
}
- this->unk_2A0 = 0;
+
+ this->stateFlags = 0;
this->actor.targetMode = 6;
func_80952C50(this, globalCtx);
}
@@ -102,56 +104,56 @@ void func_80952DFC(GlobalContext* globalCtx) {
func_80151BB4(globalCtx, 0x10);
}
-void func_80952E50(Vec3f* dst, Vec3f src, f32 arg2) {
- Vec3f sp1C;
- f32 temp_f0;
+void EnHs_UpdateChickPos(Vec3f* dst, Vec3f src, f32 offset) {
+ Vec3f diff;
+ f32 distance;
- Math_Vec3f_Diff(&src, dst, &sp1C);
+ Math_Vec3f_Diff(&src, dst, &diff);
- temp_f0 = SQ(sp1C.x) + SQ(sp1C.z);
+ distance = SQ(diff.x) + SQ(diff.z); // gets un-squared after we check if we are too close
- if (SQ(arg2) > temp_f0) {
+ if (SQ(offset) > distance) {
return;
}
- temp_f0 = sqrtf(temp_f0);
- sp1C.x *= (temp_f0 - arg2) / temp_f0;
- sp1C.z *= (temp_f0 - arg2) / temp_f0;
+ distance = sqrtf(distance);
+ diff.x *= (distance - offset) / distance;
+ diff.z *= (distance - offset) / distance;
- dst->x += sp1C.x;
- dst->z += sp1C.z;
+ dst->x += diff.x;
+ dst->z += diff.z;
}
void func_80952F00(EnHs* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
s32 i;
- f32 phi_f20;
+ f32 offset;
- if (this->actor.home.rot.z >= 20) {
- phi_f20 = 15.0f;
+ if (this->actor.home.rot.z >= 20) { // current chick count >= 10
+ offset = 15.0f;
} else {
- phi_f20 = 10.0f;
+ offset = 10.0f;
}
- func_80952E50(&this->unk_2A4[0], player->actor.world.pos, phi_f20);
+ EnHs_UpdateChickPos(&this->nwcPos[0], player->actor.world.pos, offset);
- for (i = 1; i < ARRAY_COUNT(this->unk_2A4); i++) {
- func_80952E50(&this->unk_2A4[i], this->unk_2A4[i - 1], phi_f20);
+ for (i = 1; i < ARRAY_COUNT(this->nwcPos); i++) {
+ EnHs_UpdateChickPos(&this->nwcPos[i], this->nwcPos[i - 1], offset);
}
}
void func_80952FE0(EnHs* this, GlobalContext* globalCtx) {
- if (this->unk_2A2 < 40) {
- Math_SmoothStepToS(&this->unk_294.y, 0x1F40, 6, 0x1838, 0x64);
- } else if (this->unk_2A2 < 80) {
- Math_SmoothStepToS(&this->unk_294.y, -0x1F40, 6, 0x1838, 0x64);
+ if (this->stateTimer < 40) {
+ Math_SmoothStepToS(&this->headRot.y, 0x1F40, 6, 0x1838, 0x64);
+ } else if (this->stateTimer < 80) {
+ Math_SmoothStepToS(&this->headRot.y, -0x1F40, 6, 0x1838, 0x64);
} else {
this->actionFunc = func_80953180;
- this->unk_2A0 &= ~4;
+ this->stateFlags &= ~4;
func_80151938(globalCtx, 0x33F6);
func_80952DFC(globalCtx);
}
- this->unk_2A2++;
+ this->stateTimer++;
}
void func_80953098(EnHs* this, GlobalContext* globalCtx) {
@@ -159,10 +161,10 @@ void func_80953098(EnHs* this, GlobalContext* globalCtx) {
this->actor.parent = NULL;
this->actionFunc = func_8095345C;
this->actor.flags |= ACTOR_FLAG_10000;
- this->unk_2A0 |= 0x10;
+ this->stateFlags |= 0x10;
func_800B8500(&this->actor, globalCtx, 1000.0f, 1000.0f, -1);
} else {
- this->unk_2A0 |= 8;
+ this->stateFlags |= 8;
if (INV_CONTENT(ITEM_MASK_BUNNY) == ITEM_MASK_BUNNY) {
Actor_PickUp(&this->actor, globalCtx, GI_RUPEE_RED, 10000.0f, 50.0f);
} else {
@@ -174,31 +176,31 @@ void func_80953098(EnHs* this, GlobalContext* globalCtx) {
void func_80953180(EnHs* this, GlobalContext* globalCtx) {
if ((Message_GetState(&globalCtx->msgCtx) == 5) && Message_ShouldAdvance(globalCtx)) {
switch (globalCtx->msgCtx.currentTextId) {
- case 0x33F4:
- case 0x33F6:
+ case 0x33F4: // text: laughing that they are all roosters (!)
+ case 0x33F6: // text: Grog regrets not being able to see his chicks reach adult hood
func_801477B4(globalCtx);
this->actionFunc = func_8095345C;
break;
- case 0x33F7:
+ case 0x33F7: // text: notice his chicks are grown up, happy, wants to give you bunny hood
this->actor.flags &= ~ACTOR_FLAG_10000;
func_801477B4(globalCtx);
this->actionFunc = func_80953098;
func_80953098(this, globalCtx);
break;
- case 0x33F9:
+ case 0x33F9: // text: laughing that they are all roosters (.)
this->actor.flags &= ~ACTOR_FLAG_10000;
func_801477B4(globalCtx);
this->actionFunc = func_8095345C;
break;
- case 0x33F5:
+ case 0x33F5: // He heard from his gramps (?) the moon is going to fall
globalCtx->msgCtx.unk11F10 = 0;
this->actionFunc = func_80952FE0;
- this->unk_2A2 = 0;
- this->unk_294.z = 0;
- this->unk_2A0 |= 4;
+ this->stateTimer = 0;
+ this->headRot.z = 0;
+ this->stateFlags |= 4;
break;
default:
@@ -209,34 +211,34 @@ void func_80953180(EnHs* this, GlobalContext* globalCtx) {
}
}
-void func_809532C0(EnHs* this, GlobalContext* globalCtx) {
+void EnHs_DoNothing(EnHs* this, GlobalContext* globalCtx) {
}
-void func_809532D0(EnHs* this, GlobalContext* globalCtx) {
- if (DECR(this->unk_2A2) == 0) {
- globalCtx->nextEntranceIndex = globalCtx->setupExitList[ENHS_GET_F(&this->actor)];
+void EnHs_SceneTransitToBunnyHoodDialogue(EnHs* this, GlobalContext* globalCtx) {
+ if (DECR(this->stateTimer) == 0) {
+ globalCtx->nextEntranceIndex = globalCtx->setupExitList[HS_GET_EXIT_INDEX(&this->actor)];
globalCtx->sceneLoadFlag = 0x14;
gSaveContext.save.weekEventReg[25] |= 8;
- this->actionFunc = func_809532C0;
+ this->actionFunc = EnHs_DoNothing;
}
}
void func_80953354(EnHs* this, GlobalContext* globalCtx) {
if (!Play_InCsMode(globalCtx)) {
func_800B7298(globalCtx, &this->actor, 7);
- this->actionFunc = func_809532D0;
+ this->actionFunc = EnHs_SceneTransitToBunnyHoodDialogue;
}
}
void func_809533A0(EnHs* this, GlobalContext* globalCtx) {
u16 sp1E;
- if ((globalCtx->curSpawn == 1) && !(this->unk_2A0 & 0x20)) {
+ if ((globalCtx->curSpawn == 1) && !(this->stateFlags & 0x20)) {
sp1E = 0x33F7;
- this->unk_2A0 |= 0x20;
- } else if (this->unk_2A0 & 0x10) {
+ this->stateFlags |= 0x20;
+ } else if (this->stateFlags & 0x10) {
sp1E = 0x33F9;
- this->unk_2A0 &= ~0x10;
+ this->stateFlags &= ~0x10;
} else if (gSaveContext.save.weekEventReg[25] & 8) {
sp1E = 0x33F4;
} else {
@@ -254,21 +256,21 @@ void func_8095345C(EnHs* this, GlobalContext* globalCtx) {
if (Actor_ProcessTalkRequest(&this->actor, &globalCtx->state)) {
this->actionFunc = func_80953180;
func_809533A0(this, globalCtx);
- if (this->unk_2A0 & 8) {
+ if (this->stateFlags & 8) {
func_80952DFC(globalCtx);
- this->unk_2A0 &= ~8;
+ this->stateFlags &= ~8;
}
- } else if (this->actor.home.rot.x >= 20) {
+ } else if (this->actor.home.rot.x >= 20) { // chicks turned adult >= 10
this->actionFunc = func_80953354;
- this->unk_2A2 = 40;
+ this->stateTimer = 40;
} else if (CHECK_FLAG_ALL(this->actor.flags, ACTOR_FLAG_10000)) {
func_800B8500(&this->actor, globalCtx, 1000.0f, 1000.0f, -1);
- this->unk_2A0 |= 1;
+ this->stateFlags |= 1;
} else if ((this->actor.xzDistToPlayer < 120.0f) && Player_IsFacingActor(&this->actor, 0x2000, globalCtx)) {
func_800B8614(&this->actor, globalCtx, 130.0f);
- this->unk_2A0 |= 1;
+ this->stateFlags |= 1;
} else {
- this->unk_2A0 &= ~1;
+ this->stateFlags &= ~1;
}
}
@@ -290,17 +292,17 @@ void EnHs_Update(Actor* thisx, GlobalContext* globalCtx) {
func_80952F00(this, globalCtx);
- if (this->unk_2A0 & 4) {
- Math_SmoothStepToS(&this->unk_294.x, 0, 6, 0x1838, 0x64);
- Math_SmoothStepToS(&this->unk_29A.x, 0, 6, 0x1838, 0x64);
- Math_SmoothStepToS(&this->unk_29A.y, 0, 6, 0x1838, 0x64);
- } else if (this->unk_2A0 & 1) {
- func_800E9250(globalCtx, &this->actor, &this->unk_294, &this->unk_29A, this->actor.focus.pos);
+ if (this->stateFlags & 4) {
+ Math_SmoothStepToS(&this->headRot.x, 0, 6, 0x1838, 0x64);
+ Math_SmoothStepToS(&this->unusedRot.x, 0, 6, 0x1838, 0x64);
+ Math_SmoothStepToS(&this->unusedRot.y, 0, 6, 0x1838, 0x64);
+ } else if (this->stateFlags & 1) {
+ func_800E9250(globalCtx, &this->actor, &this->headRot, &this->unusedRot, this->actor.focus.pos);
} else {
- Math_SmoothStepToS(&this->unk_294.x, 0x3200, 6, 0x1838, 0x64);
- Math_SmoothStepToS(&this->unk_294.y, 0, 6, 0x1838, 0x64);
- Math_SmoothStepToS(&this->unk_29A.x, 0, 6, 0x1838, 0x64);
- Math_SmoothStepToS(&this->unk_29A.y, 0, 6, 0x1838, 0x64);
+ Math_SmoothStepToS(&this->headRot.x, 0x3200, 6, 0x1838, 0x64);
+ Math_SmoothStepToS(&this->headRot.y, 0, 6, 0x1838, 0x64);
+ Math_SmoothStepToS(&this->unusedRot.x, 0, 6, 0x1838, 0x64);
+ Math_SmoothStepToS(&this->unusedRot.y, 0, 6, 0x1838, 0x64);
}
}
@@ -308,29 +310,33 @@ s32 EnHs_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList,
EnHs* this = THIS;
switch (limbIndex) {
- case OBJECT_HS_LIMB_09:
- rot->x += this->unk_294.y;
- rot->z += this->unk_294.x;
+ case HS_LIMB_HEAD:
+ rot->x += this->headRot.y;
+ rot->z += this->headRot.x;
break;
- case OBJECT_HS_LIMB_0A:
- rot->x += this->unk_294.y;
- rot->z += this->unk_294.x;
+ case HS_LIMB_HAIR_SPIKES:
+ rot->x += this->headRot.y;
+ rot->z += this->headRot.x;
break;
- case OBJECT_HS_LIMB_0B:
+ case HS_LIMB_HIDDEN_HAIR:
+ // for some reason this hair is always removed here in the Override limb
+ // if you do re-enable, make sure you add the head rot like above
*dList = NULL;
return false;
+ // these two limbs both have empty enddisplaylist, they do nothing
+ // at the same time (params == HS_TYPE_UNK1) is always false, because vanilla params is 0xFE01
case OBJECT_HS_LIMB_0C:
- if (this->actor.params == ENHS_1) {
+ if (this->actor.params == HS_TYPE_UNK1) {
*dList = NULL;
return false;
}
break;
case OBJECT_HS_LIMB_0D:
- if (this->actor.params == ENHS_1) {
+ if (this->actor.params == HS_TYPE_UNK1) {
*dList = NULL;
return false;
}
@@ -342,7 +348,7 @@ s32 EnHs_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList,
void EnHs_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
EnHs* this = THIS;
- if (limbIndex == OBJECT_HS_LIMB_09) {
+ if (limbIndex == HS_LIMB_HEAD) {
Matrix_MultiplyVector3fByState(&D_8095393C, &this->actor.focus.pos);
}
}
diff --git a/src/overlays/actors/ovl_En_Hs/z_en_hs.h b/src/overlays/actors/ovl_En_Hs/z_en_hs.h
index 0a50ee3607..62fc1d2a14 100644
--- a/src/overlays/actors/ovl_En_Hs/z_en_hs.h
+++ b/src/overlays/actors/ovl_En_Hs/z_en_hs.h
@@ -8,9 +8,17 @@ struct EnHs;
typedef void (*EnHsActionFunc)(struct EnHs*, GlobalContext*);
-#define ENHS_GET_F(thisx) ((thisx)->params & 0xF)
+#define HS_GET_EXIT_INDEX(thisx) ((thisx)->params & 0xF)
-#define ENHS_1 1
+#define HS_TYPE_UNK1 1
+
+// params mystery: Vanilla Grog is 0xFE01
+// 0xFE00 space is never checked in Grog code
+// at the same time, type UNK1 is only checked directly with params == 1, no &F
+// so HS_TYPE_UNK1 is never valid and is unused, as 0xFE00 is still present even if its not doing anything else
+
+// The count of [chicks following the player] is stored in [this->actor.home.rot.z] (incremented by 2)
+// The count of [chicks transformed into adult] is stored in [this->actor.home.rot.x] (incremented by 2)
typedef struct EnHs {
/* 0x0000 */ Actor actor;
@@ -18,11 +26,11 @@ typedef struct EnHs {
/* 0x0190 */ SkelAnime skelAnime;
/* 0x01D4 */ Vec3s jointTable[OBJECT_HS_LIMB_MAX];
/* 0x0234 */ Vec3s morphTable[OBJECT_HS_LIMB_MAX];
- /* 0x0294 */ Vec3s unk_294;
- /* 0x029A */ Vec3s unk_29A;
- /* 0x02A0 */ u16 unk_2A0;
- /* 0x02A2 */ s16 unk_2A2;
- /* 0x02A4 */ Vec3f unk_2A4[20];
+ /* 0x0294 */ Vec3s headRot;
+ /* 0x029A */ Vec3s unusedRot; // probably not chest, as chest is same limb as lower body
+ /* 0x02A0 */ u16 stateFlags;
+ /* 0x02A2 */ s16 stateTimer; // reused for different actionFunc
+ /* 0x02A4 */ Vec3f nwcPos[20]; // actual chick position are even values, odd values seem to be extra values for smoother chain
/* 0x0394 */ EnHsActionFunc actionFunc;
} EnHs; // size = 0x398
diff --git a/src/overlays/actors/ovl_En_Niw/z_en_niw.c b/src/overlays/actors/ovl_En_Niw/z_en_niw.c
index f6e398a33d..e3be9ae03d 100644
--- a/src/overlays/actors/ovl_En_Niw/z_en_niw.c
+++ b/src/overlays/actors/ovl_En_Niw/z_en_niw.c
@@ -5,7 +5,7 @@
*/
#include "z_en_niw.h"
-#include "objects/object_niw/object_niw.h"
+#include "overlays/actors/ovl_En_Attack_Niw/z_en_attack_niw.h"
#define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_800000)
@@ -30,12 +30,23 @@ void EnNiw_Held(EnNiw* this, GlobalContext* globalCtx);
void EnNiw_UpdateFeather(EnNiw* this, GlobalContext* globalCtx);
void EnNiw_DrawFeathers(EnNiw* this, GlobalContext* globalCtx);
void EnNiw_CheckRage(EnNiw* this, GlobalContext* globalCtx);
-void func_80891320(EnNiw* this, GlobalContext* globalCtx, s16 arg2);
+void EnNiw_AnimateWingHead(EnNiw* this, GlobalContext* globalCtx, s16 animationState);
void EnNiw_SpawnFeather(EnNiw* this, Vec3f* pos, Vec3f* vel, Vec3f* accel, f32 scale);
-// turned on during cucco storm, but not read by anything?
-// maybe read by En_Attack_Niw
-s16 D_80893460 = false;
+s16 sCuccoStormActive = false;
+
+// why wouldnt they just use actionFunc?
+enum EnNiwState {
+ /* 0 */ NIW_STATE_IDLE,
+ /* 1 */ NIW_STATE_ANGRY1, // 1/2/3 are stages of summoning cucco storm
+ /* 2 */ NIW_STATE_ANGRY2,
+ /* 3 */ NIW_STATE_ANGRY3,
+ /* 4 */ NIW_STATE_HELD,
+ /* 5 */ NIW_STATE_FALLING,
+ /* 6 */ NIW_STATE_SWIMMING,
+ /* 7 */ NIW_STATE_RUNNING,
+ /* 8 */ NIW_STATE_HOPPING,
+};
const ActorInit En_Niw_InitVars = {
ACTOR_EN_NIW,
@@ -49,15 +60,11 @@ const ActorInit En_Niw_InitVars = {
(ActorFunc)EnNiw_Draw,
};
-static f32 D_80893484[] = {
- 5000.0f,
- -5000.0f,
-};
-static f32 D_80893486[] = {
- 5000.0f,
- 3000.0f,
- 4000.0f,
-};
+static f32 sHeadRotations[] = { 5000.0f, -5000.0f };
+
+static f32 sRunningAngles[] = { 5000.0f, 3000.0f };
+
+static f32 sUnusedValue = 4000.0f;
static ColliderCylinderInit sCylinderInit = {
{
@@ -109,8 +116,8 @@ void EnNiw_Init(Actor* thisx, GlobalContext* globalCtx) {
EnNiw* this = THIS;
Vec3f dTemp = D_808934C4;
- if (this->actor.params < 0) { // all neg values become zero
- this->actor.params = ENNIW_TYPE_REGULAR;
+ if (this->actor.params < 0) { // all scene spawned cucco are (-1)
+ this->actor.params = NIW_TYPE_REGULAR;
}
Math_Vec3f_Copy(&this->unk2BC, &dTemp);
@@ -122,32 +129,36 @@ void EnNiw_Init(Actor* thisx, GlobalContext* globalCtx) {
ActorShape_Init(&thisx->shape, 0.0f, ActorShadow_DrawCircle, 25.0f);
- SkelAnime_InitFlex(globalCtx, &this->skelanime, &object_niw_Skel_002530, &object_niw_Anim_0000E8, this->jointTable,
- this->morphTable, ENNIW_LIMBCOUNT);
+ SkelAnime_InitFlex(globalCtx, &this->skelanime, &gNiwSkeleton, &gNiwIdleAnim, this->jointTable, this->morphTable,
+ NIW_LIMB_MAX);
Math_Vec3f_Copy(&this->unk2A4, &this->actor.world.pos);
Math_Vec3f_Copy(&this->unk2B0, &this->actor.world.pos);
this->unk308 = 10.0f;
Actor_SetScale(&this->actor, 0.01f);
- if (this->niwType == ENNIW_TYPE_UNK1) {
+ if (this->niwType == NIW_TYPE_UNK1) {
+ // @Bug this unused variant is broken and crashes on spawn (EnNiw_Update expects a parent, NULL)
+ // if modified to change niwType to TYPE_REGULAR here, new size is smaller than normal
+ // theory: was meant to be a small hand held cucco for grog to show the player
Actor_SetScale(&this->actor, (BREG(86) / 10000.0f) + 0.004f);
}
// random health between 10-20
+ // health at zero triggers cucco storm not death
this->actor.colChkInfo.health = Rand_ZeroFloat(9.99f) + 10.0f;
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
- if (this->niwType == ENNIW_TYPE_REGULAR) {
+ if (this->niwType == NIW_TYPE_REGULAR) {
Collider_InitAndSetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
}
- if (this->niwType == ENNIW_TYPE_UNK2) {
- Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_M); // crow
+ if (this->niwType == NIW_TYPE_HELD) {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_M);
this->sfxTimer1 = 30;
- this->unkTimer250 = 30;
+ this->heldTimer = 30;
this->actor.flags &= ~ACTOR_FLAG_1; // targetable OFF
- this->unknownState28E = 4;
+ this->niwState = NIW_STATE_HELD;
this->actionFunc = EnNiw_Held;
this->actor.speedXZ = 0.0f;
this->unk2BC.z = 0.0f;
@@ -161,105 +172,119 @@ void EnNiw_Init(Actor* thisx, GlobalContext* globalCtx) {
void EnNiw_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnNiw* this = THIS;
- if (this->niwType == ENNIW_TYPE_REGULAR) {
+ if (this->niwType == NIW_TYPE_REGULAR) {
Collider_DestroyCylinder(globalCtx, &this->collider);
}
}
-void func_80891320(EnNiw* this, GlobalContext* globalCtx, s16 arg2) {
- f32 tempOne = 1.0f;
+/**
+ * Summary: instead of using SkelAnime animations, Niw modifies head+wings directly to create animations
+ *
+ * AttackNiw has a copy of this function that it barely uses
+ */
+void EnNiw_AnimateWingHead(EnNiw* this, GlobalContext* globalCtx, s16 animationState) {
+ f32 tempOne = 1.0f; // hopefully fake match, but no luck
if (this->unkTimer24C == 0) {
- if (arg2 == 0) {
- this->unk264[0] = 0.0f;
+ // targetLimbRots[0] is bodyRotY
+ if (animationState == NIW_ANIMATION_STILL) {
+ this->targetLimbRots[0] = 0.0f;
} else {
- this->unk264[0] = (-10000.0f) * tempOne;
+ this->targetLimbRots[0] = -10000.0f * tempOne;
}
+
this->unk292 += 1;
this->unkTimer24C = 3;
if ((this->unk292 % 2) == 0) {
- this->unk264[0] = 0.0f;
- if (arg2 == 0) {
+ this->targetLimbRots[0] = 0.0f;
+ if (animationState == NIW_ANIMATION_STILL) {
this->unkTimer24C = Rand_ZeroFloat(30.0f);
}
}
}
+
if (this->unkTimer24E == 0) {
- this->unk296++;
- this->unk296 &= 1;
- switch (arg2) {
- case 0:
- this->unk264[2] = 0.0f;
- this->unk264[1] = 0.0f;
+ this->unkToggle296++;
+ this->unkToggle296 &= 1;
+
+ switch (animationState) {
+ case NIW_ANIMATION_STILL:
+ this->targetLimbRots[2] = 0.0f; // both wingRotZ
+ this->targetLimbRots[1] = 0.0f;
break;
- case 1:
+ case NIW_ANIMATION_HEAD_PECKING:
this->unkTimer24E = 3;
- this->unk264[2] = 7000.0f * tempOne;
- this->unk264[1] = 7000.0f * tempOne;
- if (this->unk296 == 0) {
- this->unk264[2] = 0.0f;
- this->unk264[1] = 0.0f;
+ this->targetLimbRots[2] = 7000.0f * tempOne; // both wingRotZ
+ this->targetLimbRots[1] = 7000.0f * tempOne;
+ if (this->unkToggle296 == 0) {
+ this->targetLimbRots[2] = 0.0f; // both wingRotZ
+ this->targetLimbRots[1] = 0.0f;
}
break;
- case 2:
+
+ case NIW_ANIMATION_PECKING_AND_WAVING:
this->unkTimer24E = 2;
- this->unk264[2] = -10000.0f;
- this->unk264[1] = -10000.0f;
- this->unk264[7] = 25000.0f;
- this->unk264[5] = 25000.0f;
- this->unk264[8] = 6000.0f;
- this->unk264[6] = 6000.0f;
- if (this->unk296 == 0) {
- this->unk264[7] = 8000.0f;
- this->unk264[5] = 8000.0f;
+ this->targetLimbRots[2] = -10000.0f; // both wingRotZ
+ this->targetLimbRots[1] = -10000.0f;
+ this->targetLimbRots[7] = 25000.0f; // both wingRotY
+ this->targetLimbRots[5] = 25000.0f;
+ this->targetLimbRots[8] = 6000.0f; // both wingRotX
+ this->targetLimbRots[6] = 6000.0f;
+ if (this->unkToggle296 == 0) {
+ this->targetLimbRots[7] = 8000.0f; // both wingRotY
+ this->targetLimbRots[5] = 8000.0f;
}
break;
- case 3:
+
+ case NIW_ANIMATION_PECKING_AND_FORFLAPPING:
this->unkTimer24E = 2;
- this->unk264[5] = 10000.0f;
- this->unk264[7] = 10000.0f;
- if (this->unk296 == 0) {
- this->unk264[5] = 3000.0f;
- this->unk264[7] = 3000.0f;
+ this->targetLimbRots[5] = 10000.0f; // both wingRotY
+ this->targetLimbRots[7] = 10000.0f;
+ if (this->unkToggle296 == 0) {
+ this->targetLimbRots[5] = 3000.0f; // both wingRotY
+ this->targetLimbRots[7] = 3000.0f;
}
break;
- case 4:
+
+ case NIW_ANIMATION_FREEZE:
this->unkTimer24C = 5;
break;
- case 5:
+
+ case NIW_ANIMATION_PECKING_SLOW_FORFLAPPING:
this->unkTimer24E = 5;
- this->unk264[5] = 14000.0f;
- this->unk264[7] = 14000.0f;
- if (this->unk296 == 0) {
- this->unk264[5] = 10000.0f;
- this->unk264[7] = 10000.0f;
+ this->targetLimbRots[5] = 14000.0f; // both wingRotY
+ this->targetLimbRots[7] = 14000.0f;
+ if (this->unkToggle296 == 0) {
+ this->targetLimbRots[5] = 10000.0f; // both wingRotY
+ this->targetLimbRots[7] = 10000.0f;
}
break;
}
}
- if (this->unk264[9] != this->limbFRot) {
- Math_ApproachF(&this->limbFRot, this->unk264[9], 0.5f, 4000.0f);
+
+ if (this->targetLimbRots[9] != this->headRotY) {
+ Math_ApproachF(&this->headRotY, this->targetLimbRots[9], 0.5f, 4000.0f);
}
- if (this->unk264[0] != this->limbDRot) {
- Math_ApproachF(&this->limbDRot, this->unk264[0], 0.5f, 4000.0f);
+ if (this->targetLimbRots[0] != this->upperBodyRotY) {
+ Math_ApproachF(&this->upperBodyRotY, this->targetLimbRots[0], 0.5f, 4000.0f);
}
- if (this->unk264[2] != this->limb7Rotz) {
- Math_ApproachF(&this->limb7Rotz, this->unk264[2], 0.8f, 7000.0f);
+ if (this->targetLimbRots[2] != this->leftWingRotZ) {
+ Math_ApproachF(&this->leftWingRotZ, this->targetLimbRots[2], 0.8f, 7000.0f);
}
- if (this->unk264[7] != this->limb7Roty) {
- Math_ApproachF(&this->limb7Roty, this->unk264[7], 0.8f, 7000.0f);
+ if (this->targetLimbRots[7] != this->leftWingRotY) {
+ Math_ApproachF(&this->leftWingRotY, this->targetLimbRots[7], 0.8f, 7000.0f);
}
- if (this->unk264[8] != this->limb7Rotx) {
- Math_ApproachF(&this->limb7Rotx, this->unk264[8], 0.8f, 7000.0f);
+ if (this->targetLimbRots[8] != this->leftWingRotX) {
+ Math_ApproachF(&this->leftWingRotX, this->targetLimbRots[8], 0.8f, 7000.0f);
}
- if (this->unk264[1] != this->limbBRotz) {
- Math_ApproachF(&this->limbBRotz, this->unk264[1], 0.8f, 7000.0f);
+ if (this->targetLimbRots[1] != this->rightWingRotZ) {
+ Math_ApproachF(&this->rightWingRotZ, this->targetLimbRots[1], 0.8f, 7000.0f);
}
- if (this->unk264[5] != this->limbBRoty) {
- Math_ApproachF(&this->limbBRoty, this->unk264[5], 0.8f, 7000.0f);
+ if (this->targetLimbRots[5] != this->rightWingRotY) {
+ Math_ApproachF(&this->rightWingRotY, this->targetLimbRots[5], 0.8f, 7000.0f);
}
- if (this->unk264[6] != this->limbBRotx) {
- Math_ApproachF(&this->limbBRotx, this->unk264[6], 0.8f, 7000.0f);
+ if (this->targetLimbRots[6] != this->rightWingRotX) {
+ Math_ApproachF(&this->rightWingRotX, this->targetLimbRots[6], 0.8f, 7000.0f);
}
}
@@ -270,7 +295,7 @@ void EnNiw_SpawnAttackNiw(EnNiw* this, GlobalContext* globalCtx) {
Vec3f newNiwPos;
Actor* attackNiw;
- if ((this->unkTimer252 == 0) && (this->unk290 < 7)) {
+ if (this->attackNiwSpawnTimer == 0 && this->attackNiwCount < 7) {
xView = globalCtx->view.at.x - globalCtx->view.eye.x;
yView = globalCtx->view.at.y - globalCtx->view.eye.y;
zView = globalCtx->view.at.z - globalCtx->view.eye.z;
@@ -278,54 +303,57 @@ void EnNiw_SpawnAttackNiw(EnNiw* this, GlobalContext* globalCtx) {
newNiwPos.y = randPlusMinusPoint5Scaled(0.3f) + (globalCtx->view.eye.y + 50.0f + (yView * 0.5f));
newNiwPos.z = ((Rand_ZeroOne() - 0.5f) * zView) + globalCtx->view.eye.z;
attackNiw = Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_ATTACK_NIW, newNiwPos.x,
- newNiwPos.y, newNiwPos.z, 0, 0, 0, 0);
+ newNiwPos.y, newNiwPos.z, 0, 0, 0, ATTACK_NIW_REGULAR);
- if (attackNiw) {
- this->unk290++;
- this->unkTimer252 = 10;
+ if (attackNiw != NULL) {
+ this->attackNiwCount++;
+ this->attackNiwSpawnTimer = 10;
}
}
}
-void func_808917F8(EnNiw* this, GlobalContext* globalCtx, s32 arg2) {
- f32 phi_f2;
+void EnNiw_UpdateRunning(EnNiw* this, GlobalContext* globalCtx, s32 isStormCucco) {
+ f32 runningDirection;
f32 targetRotY;
- f32* D_8089348CPtr = D_80893486;
+ f32* runningAngles = sRunningAngles;
- if (this->unkTimer250 == 0) {
- this->unkTimer250 = 3;
- if (this->actor.bgCheckFlags & 1) {
- // hit floor
- this->actor.velocity.y = 3.5f; // hop up?
+ if (this->hopTimer == 0) {
+ this->hopTimer = 3;
+ if (this->actor.bgCheckFlags & 1) { // hit floor
+ this->actor.velocity.y = 3.5f; // hopping up while running away
}
}
- if (this->unkTimer252 == 0) {
- this->unk29A++;
- this->unk29A &= 1;
- this->unkTimer252 = 5;
+
+ if (this->runningDirectionTimer == 0) {
+ this->isRunningRight++;
+ this->isRunningRight &= 1;
+ this->runningDirectionTimer = 5;
}
- if (this->unk29A == 0) {
- phi_f2 = D_8089348CPtr[arg2];
+
+ if (this->isRunningRight == false) {
+ runningDirection = runningAngles[isStormCucco];
} else {
- phi_f2 = -D_8089348CPtr[arg2];
+ runningDirection = -runningAngles[isStormCucco];
}
- if (arg2 == 1 && (this->unkTimer254 == 0 || (this->actor.bgCheckFlags & 8))) {
- this->unkTimer254 = 150;
+
+ if (isStormCucco == true &&
+ (this->runAwayTimer == 0 || (this->actor.bgCheckFlags & 8))) { // bgCheckFlags 8: hit a wall
+ this->runAwayTimer = 150;
if (this->yawTimer == 0) {
this->yawTimer = 70;
this->yawTowardsPlayer = this->actor.yawTowardsPlayer;
}
}
- targetRotY = this->yawTowardsPlayer + phi_f2;
+
+ targetRotY = this->yawTowardsPlayer + runningDirection;
Math_SmoothStepToS(&this->actor.world.rot.y, targetRotY, 3, this->unk300, 0);
Math_ApproachF(&this->unk300, 3000.0f, 1.0f, 500.0f);
- func_80891320(this, globalCtx, 5);
+ EnNiw_AnimateWingHead(this, globalCtx, NIW_ANIMATION_PECKING_SLOW_FORFLAPPING);
}
void EnNiw_SetupIdle(EnNiw* this) {
- Animation_Change(&this->skelanime, &object_niw_Anim_0000E8, 1.0f, 0.0f,
- Animation_GetLastFrame(&object_niw_Anim_0000E8), 0, -10.0f);
- this->unknownState28E = 0;
+ Animation_Change(&this->skelanime, &gNiwIdleAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gNiwIdleAnim), 0, -10.0f);
+ this->niwState = NIW_STATE_IDLE;
this->actionFunc = EnNiw_Idle;
}
@@ -334,40 +362,39 @@ void EnNiw_Idle(EnNiw* this, GlobalContext* globalCtx) {
f32 posZ2;
f32 posX1 = randPlusMinusPoint5Scaled(100.0f);
f32 posZ1 = randPlusMinusPoint5Scaled(100.0f);
- s16 s16tmp;
+ s16 nextAnimation;
- if (this->niwType == ENNIW_TYPE_REGULAR) {
- if (Actor_HasParent(&this->actor, globalCtx)) {
- // picked up
+ if (this->niwType == NIW_TYPE_REGULAR) {
+ if (Actor_HasParent(&this->actor, globalCtx)) { // picked up
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_M); // crow
this->sfxTimer1 = 30;
- this->unkTimer250 = 30;
+ this->heldTimer = 30;
this->actor.flags &= ~ACTOR_FLAG_1; // targetable OFF
- this->unknownState28E = 4;
+ this->niwState = NIW_STATE_HELD;
this->actor.speedXZ = 0.0f;
this->actionFunc = EnNiw_Held;
return;
} else {
Actor_LiftActor(&this->actor, globalCtx);
}
- } else {
- this->unkTimer252 = 10;
+ } else { // NIW_TYPE_UNK1 || NIW_TYPE_HELD
+ this->unkIdleTimer2 = 10;
}
- s16tmp = 0;
- if (this->unkTimer252 != 0) {
+ nextAnimation = NIW_ANIMATION_STILL; // probably a scoped variable here, where their scope was different
+ if (this->unkIdleTimer2 != 0) {
if (Rand_ZeroFloat(3.99f) < 1.0f) {
- this->unk2EA++;
- this->unk2EA &= 1;
+ this->headRotationToggle++;
+ this->headRotationToggle &= 1;
}
- Math_ApproachF(&this->unk264[9], D_80893484[this->unk2EA], 0.5f, 4000.0f);
+
+ Math_ApproachF(&this->targetLimbRots[9], sHeadRotations[this->headRotationToggle], 0.5f, 4000.0f); // head rot
}
- if ((this->unkTimer252 == 0) && (this->unkTimer250 == 0)) {
+ if (this->unkIdleTimer2 == 0 && this->unkIdleTimer == 0) {
this->unk298++;
-
if (this->unk298 > 7) {
- this->unkTimer252 = Rand_ZeroFloat(30.0f);
+ this->unkIdleTimer2 = Rand_ZeroFloat(30.0f);
this->unk298 = Rand_ZeroFloat(3.99f);
if (posX1 < 0.0f) {
@@ -385,17 +412,17 @@ void EnNiw_Idle(EnNiw* this, GlobalContext* globalCtx) {
this->unk2B0.z = this->unk2A4.z + posZ1;
} else {
- this->unkTimer250 = 4;
- if (this->actor.bgCheckFlags & 1) {
+ this->unkIdleTimer = 4;
+ if (this->actor.bgCheckFlags & 1) { // hit floor
this->actor.speedXZ = 0.0f;
- this->actor.velocity.y = 3.5f;
+ this->actor.velocity.y = 3.5f; // hopping up and down
}
}
}
- if (this->unkTimer250 != 0) {
- Math_ApproachZeroF(&this->unk264[9], 0.5f, 4000.0f);
- s16tmp = 1;
+ if (this->unkIdleTimer != 0) {
+ Math_ApproachZeroF(&this->targetLimbRots[9], 0.5f, 4000.0f); // head rot
+ nextAnimation = NIW_ANIMATION_HEAD_PECKING;
Math_ApproachF(&this->actor.world.pos.x, this->unk2B0.x, 1.0f, this->unk300);
Math_ApproachF(&this->actor.world.pos.z, this->unk2B0.z, 1.0f, this->unk300);
Math_ApproachF(&this->unk300, 3.0f, 1.0f, 0.3f);
@@ -411,33 +438,34 @@ void EnNiw_Idle(EnNiw* this, GlobalContext* globalCtx) {
}
if ((posX2 == 0.0f) && (posZ2 == 0.0f)) {
- this->unkTimer250 = 0;
+ this->unkIdleTimer = 0;
this->unk298 = 7;
}
Math_SmoothStepToS(&this->actor.world.rot.y, Math_Atan2S(posX2, posZ2), 3, this->unk304, 0);
Math_ApproachF(&this->unk304, 10000.0f, 1.0f, 1000.0f);
}
- func_80891320(this, globalCtx, s16tmp);
+
+ EnNiw_AnimateWingHead(this, globalCtx, nextAnimation);
}
void EnNiw_Held(EnNiw* this, GlobalContext* globalCtx) {
Vec3f vec3fcopy = D_808934DC;
s16 rotZ;
- if (this->unkTimer250 == 0) {
+ if (this->heldTimer == 0) {
this->unk29E = 2;
- this->unkTimer250 = (s32)(Rand_ZeroFloat(1.0f) * 10.0f) + 10;
+ this->heldTimer = (s32)(Rand_ZeroFloat(1.0f) * 10.0f) + 10;
}
this->actor.shape.rot.x = (s16)randPlusMinusPoint5Scaled(5000.0f) + this->actor.world.rot.x;
this->actor.shape.rot.y = (s16)randPlusMinusPoint5Scaled(5000.0f) + this->actor.world.rot.y;
this->actor.shape.rot.z = (s16)randPlusMinusPoint5Scaled(5000.0f) + this->actor.world.rot.z;
- if (this->niwType == ENNIW_TYPE_REGULAR) {
+ if (this->niwType == NIW_TYPE_REGULAR) {
if (Actor_HasNoParent(&this->actor, globalCtx)) {
this->actor.shape.rot.z = 0;
rotZ = this->actor.shape.rot.z;
- this->unknownState28E = 5;
+ this->niwState = NIW_STATE_FALLING;
this->actor.flags |= ACTOR_FLAG_1; // targetable ON
this->actionFunc = EnNiw_Thrown;
this->actor.shape.rot.y = rotZ;
@@ -449,9 +477,9 @@ void EnNiw_Held(EnNiw* this, GlobalContext* globalCtx) {
this->actor.velocity.y = 8.0f;
this->actor.speedXZ = 4.0f;
this->actor.gravity = -2.0f;
- this->unknownState28E = 5;
+ this->niwState = NIW_STATE_FALLING;
this->unk2EC = 0;
- this->niwType = ENNIW_TYPE_REGULAR;
+ this->niwType = NIW_TYPE_REGULAR;
this->actor.shape.rot.y = rotZ;
this->actor.shape.rot.x = rotZ;
Collider_InitAndSetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
@@ -459,29 +487,29 @@ void EnNiw_Held(EnNiw* this, GlobalContext* globalCtx) {
this->actor.flags |= ACTOR_FLAG_1; // targetable ON
this->actionFunc = EnNiw_Thrown;
}
- func_80891320(this, globalCtx, 2);
+
+ EnNiw_AnimateWingHead(this, globalCtx, NIW_ANIMATION_PECKING_AND_WAVING);
}
-// action function: recently thrown, and also hopping on the floor
void EnNiw_Thrown(EnNiw* this, GlobalContext* globalCtx) {
if (this->unk2EC == 0) {
- if (this->actor.bgCheckFlags & 1) {
+ if (this->actor.bgCheckFlags & 1) { // hit floor
this->unk2EC = 1;
- this->unkTimer252 = 80; // hop timer
+ this->hoppingTimer = 80; // hop timer
this->actor.speedXZ = 0.0f;
this->actor.velocity.y = 4.0f;
} else {
return; // wait until back on floor
}
} else {
- if (this->actor.bgCheckFlags & 1) {
+ if (this->actor.bgCheckFlags & 1) { // hit floor
this->sfxTimer1 = 0;
this->actor.velocity.y = 4.0f; // vertical hop
this->unk29E = 1;
}
- if (this->unkTimer252 == 0) {
- this->unkTimer254 = 100;
- this->unkTimer250 = 0;
+ if (this->hoppingTimer == 0) {
+ this->runAwayTimer = 100;
+ this->heldTimer = 0;
this->unk2EC = 0;
EnNiw_SetupRunAway(this);
return;
@@ -493,20 +521,19 @@ void EnNiw_Thrown(EnNiw* this, GlobalContext* globalCtx) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_M); // crow
this->sfxTimer1 = 30;
this->unk2EC = 0;
- this->unkTimer250 = 30;
+ this->heldTimer = 30;
this->actor.flags &= ~ACTOR_FLAG_1; // targetable OFF
- this->unknownState28E = 4;
+ this->niwState = NIW_STATE_HELD;
this->actionFunc = EnNiw_Held;
this->actor.speedXZ = 0.0f;
} else {
- if (this->unkTimer252 > 5) {
+ if (this->hoppingTimer > 5) {
Actor_LiftActor(&this->actor, globalCtx);
}
- func_80891320(this, globalCtx, 2);
+ EnNiw_AnimateWingHead(this, globalCtx, NIW_ANIMATION_PECKING_AND_WAVING);
}
}
-// action func: swimming and flying away after swimming
void EnNiw_Swimming(EnNiw* this, GlobalContext* globalCtx) {
Vec3f ripplePos;
@@ -517,73 +544,74 @@ void EnNiw_Swimming(EnNiw* this, GlobalContext* globalCtx) {
}
this->actor.speedXZ = 2.0f;
- if (this->actor.bgCheckFlags & 0x20) {
- // still touching water
+ if (this->actor.bgCheckFlags & 0x20) { // touching water
this->actor.gravity = 0.0f;
if (this->actor.depthInWater > 15.0f) {
this->actor.world.pos.y += 2.0f;
}
- if (this->unkTimer250 == 0) {
- this->unkTimer250 = 30;
+ if (this->swimRippleTimer == 0) {
+ this->swimRippleTimer = 30;
Math_Vec3f_Copy(&ripplePos, &this->actor.world.pos);
ripplePos.y += this->actor.depthInWater;
EffectSsGRipple_Spawn(globalCtx, &ripplePos, 100, 500, 30);
}
- if (this->actor.bgCheckFlags & 8) {
- this->actor.velocity.y = 10.0f;
+ if (this->actor.bgCheckFlags & 8) { // hit a wall
+ this->actor.velocity.y = 10.0f; // fly up in straight line
this->actor.speedXZ = 1.0f;
}
} else {
this->actor.gravity = -2.0f;
- if (this->actor.bgCheckFlags & 8) {
- // has hit a wall
- this->actor.velocity.y = 10.0f; // to the moon
+ if (this->actor.bgCheckFlags & 8) { // hit a wall
+ this->actor.velocity.y = 10.0f; // fly up in straight line
this->actor.speedXZ = 1.0f;
this->actor.gravity = 0.0f;
} else {
this->actor.speedXZ = 4.0f;
}
- if (this->actor.bgCheckFlags & 1) {
+ if (this->actor.bgCheckFlags & 1) { // hit floor
this->actor.gravity = -2.0f;
- this->unkTimer254 = 100;
- this->unkTimer250 = 0;
+ this->runAwayTimer = 100;
+ this->swimRippleTimer = 0;
this->actor.velocity.y = 0.0f;
if (!this->isStormActive) {
EnNiw_SetupRunAway(this);
} else {
- this->unknownState28E = 3;
+ this->niwState = NIW_STATE_ANGRY3;
this->actionFunc = EnNiw_CuccoStorm;
}
}
}
- func_80891320(this, globalCtx, 2);
+
+ EnNiw_AnimateWingHead(this, globalCtx, NIW_ANIMATION_PECKING_AND_WAVING);
}
void EnNiw_Trigger(EnNiw* this, GlobalContext* globalCtx) {
- s32 value;
+ s32 state;
+
+ // Possible Fake Match: the weird way this state is set
if (1) {
- value = 1;
+ state = NIW_STATE_ANGRY1;
}
- this->unkTimer252 = 10;
- this->unknownState28E = this->unk29C = value;
+ this->cuccoStormTimer = 10;
+ this->niwState = this->nextAnimation = state; // NIW_ANIMATION_HEAD_PECKING
this->actionFunc = EnNiw_Upset;
}
void EnNiw_Upset(EnNiw* this, GlobalContext* globalCtx) {
// assumption: CuccoStorm is split into smaller parts because it used to be a cutscene in OOT
this->sfxTimer1 = 100;
- if (this->unkTimer252 == 0) {
- this->unkTimer252 = 60;
+ if (this->cuccoStormTimer == 0) {
+ this->cuccoStormTimer = 60;
this->unkTimer24C = 10;
- this->unk29C = 4;
- this->unknownState28E = 2;
+ this->nextAnimation = NIW_ANIMATION_FREEZE;
+ this->niwState = NIW_STATE_ANGRY2;
this->actionFunc = EnNiw_SetupCuccoStorm;
}
- func_80891320(this, globalCtx, this->unk29C);
+ EnNiw_AnimateWingHead(this, globalCtx, this->nextAnimation);
}
// the long crow with head back before they descend
@@ -591,45 +619,46 @@ void EnNiw_SetupCuccoStorm(EnNiw* this, GlobalContext* globalCtx) {
f32 viewY;
this->sfxTimer1 = 100;
- if (this->unkTimer252 == 40) {
+ if (this->cuccoStormTimer == 40) {
viewY = 14000.0f;
- this->unk264[0] = 10000.0f;
- this->unk264[7] = this->unk264[5] = viewY;
- this->unk264[6] = 0.0f;
- this->unk264[8] = 0.0f;
- this->unk264[1] = 0.0f;
- this->unk264[2] = 0.0f;
+ this->targetLimbRots[0] = 10000.0f; // body rot
+ this->targetLimbRots[7] = this->targetLimbRots[5] = viewY;
+ this->targetLimbRots[6] = 0.0f;
+ this->targetLimbRots[8] = 0.0f;
+ this->targetLimbRots[1] = 0.0f;
+ this->targetLimbRots[2] = 0.0f;
this->unkTimer24C = 10;
- Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_M); // crow
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_M);
}
- if (this->unkTimer252 == 0) {
- this->unkTimer252 = 10;
+
+ if (this->cuccoStormTimer == 0) {
+ this->cuccoStormTimer = 10;
this->yawTowardsPlayer = this->actor.yawTowardsPlayer;
this->actor.flags &= ~ACTOR_FLAG_1; // targetable OFF
- this->unknownState28E = 3;
+ this->niwState = NIW_STATE_ANGRY3;
this->actionFunc = EnNiw_CuccoStorm;
}
- func_80891320(this, globalCtx, this->unk29C);
+
+ EnNiw_AnimateWingHead(this, globalCtx, this->nextAnimation);
}
void EnNiw_CuccoStorm(EnNiw* this, GlobalContext* globalCtx) {
EnNiw_SpawnAttackNiw(this, globalCtx);
- if (this->unkTimer252 == 1) {
+ if (this->cuccoStormTimer == 1) { // not countdown to 0? mistype?
this->actor.speedXZ = 3.0f;
- this->unk29A = Rand_ZeroFloat(1.99f);
- this->unkTimer250 = 0;
- this->unkTimer24E = this->unkTimer250;
- this->unkTimer24C = this->unkTimer250;
+ this->isRunningRight = Rand_ZeroFloat(1.99f);
+ this->generalTimer1 = 0;
+ this->unkTimer24E = this->generalTimer1;
+ this->unkTimer24C = this->generalTimer1;
} else {
- func_808917F8(this, globalCtx, 1);
+ EnNiw_UpdateRunning(this, globalCtx, true);
}
}
void EnNiw_SetupRunAway(EnNiw* this) {
- Animation_Change(&this->skelanime, &object_niw_Anim_0000E8, 1.0f, 0.0f,
- Animation_GetLastFrame(&object_niw_Anim_0000E8), 0, -10.0f);
- this->unk29A = Rand_ZeroFloat(1.99f);
- this->unknownState28E = 7;
+ Animation_Change(&this->skelanime, &gNiwIdleAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gNiwIdleAnim), 0, -10.0f);
+ this->isRunningRight = Rand_ZeroFloat(1.99f);
+ this->niwState = NIW_STATE_RUNNING;
this->actionFunc = EnNiw_RunAway;
this->actor.speedXZ = 4.0f;
}
@@ -641,22 +670,21 @@ void EnNiw_RunAway(EnNiw* this, GlobalContext* globalCtx) {
f32 dX;
f32 dZ;
- if (this->unkTimer254 == 0) {
+ if (this->runAwayTimer == 0) {
this->unk2A4.x = this->unk2B0.x = this->actor.world.pos.x;
this->unk2A4.y = this->unk2B0.y = this->actor.world.pos.y;
this->unk2A4.z = this->unk2B0.z = this->actor.world.pos.z;
-
- this->unkTimer252 = this->unkTimer250 = this->unk298 = 0;
+ this->generalTimer2 = this->generalTimer1 = this->unk298 = 0;
this->unk300 = this->unk304 = 0;
-
this->actor.speedXZ = 0;
-
- this->unk264[8] = 0;
- this->unk264[6] = 0;
- this->unk264[5] = 0;
- this->unk264[7] = 0;
+ this->targetLimbRots[8] = 0;
+ this->targetLimbRots[6] = 0;
+ this->targetLimbRots[5] = 0;
+ this->targetLimbRots[7] = 0;
Math_Vec3f_Copy(&this->unk2BC, &tempVec3f);
+
EnNiw_SetupIdle(this);
+
} else {
if (this->unk2BC.x != 90000.0f) {
dX = this->actor.world.pos.x - this->unk2BC.x;
@@ -666,25 +694,27 @@ void EnNiw_RunAway(EnNiw* this, GlobalContext* globalCtx) {
dZ = this->actor.world.pos.z - player->actor.world.pos.z;
}
this->yawTowardsPlayer = Math_Atan2S(dX, dZ);
- func_808917F8(this, globalCtx, 0);
- func_80891320(this, globalCtx, 2);
+ EnNiw_UpdateRunning(this, globalCtx, false);
+ EnNiw_AnimateWingHead(this, globalCtx, NIW_ANIMATION_PECKING_AND_WAVING);
}
}
void EnNiw_LandBeforeIdle(EnNiw* this, GlobalContext* globalCtx) {
- if (this->actor.bgCheckFlags & 1) {
+ if (this->actor.bgCheckFlags & 1) { // hit floor
EnNiw_SetupIdle(this);
}
}
void EnNiw_CheckRage(EnNiw* this, GlobalContext* globalCtx) {
- if (!this->isStormActive && (this->unkTimer260 == 0) && (this->niwType == ENNIW_TYPE_REGULAR)) {
- if ((this->unknownState28E != 7) && (this->unk2BC.x != 90000.0f)) {
- this->unkTimer260 = 10;
+ if (!this->isStormActive && this->iframeTimer == 0 && this->niwType == NIW_TYPE_REGULAR) {
+
+ // is this used? this is before we even know if we've been hit
+ if (this->niwState != NIW_STATE_RUNNING && this->unk2BC.x != 90000.0f) {
+ this->iframeTimer = 10;
this->sfxTimer1 = 30;
this->unk29E = 1;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_M); // crow
- this->unkTimer254 = 100;
+ this->runAwayTimer = 100;
this->unk2EC = 0;
EnNiw_SetupRunAway(this);
}
@@ -696,32 +726,32 @@ void EnNiw_CheckRage(EnNiw* this, GlobalContext* globalCtx) {
this->actor.colChkInfo.health--;
}
- if ((!D_80893460) && (this->actor.colChkInfo.health == 0)) {
- // now you've done it
- this->unkTimer254 = 100;
- D_80893460 = true;
+ if (!sCuccoStormActive && this->actor.colChkInfo.health == 0) {
+ this->runAwayTimer = 100; // main cucco will run away after storm starts
+ sCuccoStormActive = true;
this->unk298 = 0;
this->sfxTimer1 = 10000;
this->unk2A4.x = this->unk2B0.x = this->actor.world.pos.x;
this->unk2A4.y = this->unk2B0.y = this->actor.world.pos.y;
this->unk2A4.z = this->unk2B0.z = this->actor.world.pos.z;
- this->unkTimer252 = this->unkTimer250 = this->unk298;
+ this->generalTimer2 = this->generalTimer1 = this->unk298;
- this->unk264[8] = 0.0f;
- this->unk264[6] = 0.0f;
- this->unk264[5] = 0.0f;
- this->unk264[7] = 0.0f;
+ this->targetLimbRots[8] = 0.0f;
+ this->targetLimbRots[6] = 0.0f;
+ this->targetLimbRots[5] = 0.0f;
+ this->targetLimbRots[7] = 0.0f;
this->isStormActive = true;
this->actionFunc = EnNiw_Trigger;
this->unk304 = 0.0f;
this->unk300 = 0.0f;
this->actor.speedXZ = 0.0f;
+
} else {
- this->unkTimer260 = 10;
+ this->iframeTimer = 10;
this->sfxTimer1 = 30;
this->unk29E = 1;
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_M); // crow
- this->unkTimer254 = 100;
+ this->runAwayTimer = 100;
this->unk2EC = 0;
EnNiw_SetupRunAway(this);
}
@@ -737,10 +767,9 @@ void EnNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
s16 pad1;
s16 featherCount;
Vec3f pos;
- Vec3f spB8;
- Vec3f spAC;
- s32 pad2[9];
- s16 temp29C;
+ Vec3f vel;
+ Vec3f accel;
+ s32 pad2[10];
f32 featherScale;
f32 viewAtToEyeNormY;
f32 floorHeight;
@@ -749,16 +778,16 @@ void EnNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
this->unusedCounter28C++;
- if (this->niwType == ENNIW_TYPE_UNK1) {
+ if (this->niwType == NIW_TYPE_UNK1) {
this->actor.shape.rot.y = this->actor.world.rot.y = this->actor.parent->shape.rot.y;
}
- if (this->unknownState28E != 0) {
- this->unk264[9] = 0.0f;
+ if (this->niwState != NIW_STATE_IDLE) {
+ this->targetLimbRots[9] = 0.0f; // head rot
}
if (this->unk29E != 0) {
- featherCount = ENNIW_FEATHERCOUNT;
+ featherCount = NIW_FEATHER_COUNT;
if (this->unk29E == 2) {
featherCount = 4;
}
@@ -768,20 +797,20 @@ void EnNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
pos.z = randPlusMinusPoint5Scaled(10.0f) + this->actor.world.pos.z;
featherScale = Rand_ZeroFloat(6.0f) + 6.0f;
- if ((this->unk29E == 2) && (this->unk308 != 0)) {
+ if (this->unk29E == 2 && this->unk308 != 0) {
pos.y += 10.0f;
}
if (this->unk308 == 0) {
featherScale = Rand_ZeroFloat(2.0f) + 2.0f;
}
- spB8.x = randPlusMinusPoint5Scaled(3.0f);
- spB8.y = (Rand_ZeroFloat(2.0f) * 0.5f) + 2.0f;
- spB8.z = randPlusMinusPoint5Scaled(3.0f);
- spAC.z = spAC.x = 0.0f;
- spAC.y = -0.15000000596f;
+ vel.x = randPlusMinusPoint5Scaled(3.0f);
+ vel.y = Rand_ZeroFloat(2.0f) * 0.5f + 2.0f;
+ vel.z = randPlusMinusPoint5Scaled(3.0f);
+ accel.z = accel.x = 0.0f;
+ accel.y = -0.15f;
- EnNiw_SpawnFeather(this, &pos, &spB8, &spAC, featherScale);
+ EnNiw_SpawnFeather(this, &pos, &vel, &accel, featherScale);
}
this->unk29E = 0;
}
@@ -790,15 +819,15 @@ void EnNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
DECR(this->unkTimer24C);
DECR(this->unkTimer24E);
- DECR(this->unkTimer250);
- DECR(this->unkTimer252);
- DECR(this->unkTimer254);
+ DECR(this->generalTimer1);
+ DECR(this->generalTimer2);
+ DECR(this->runAwayTimer);
DECR(this->sfxTimer1);
DECR(this->flutterSfxTimer);
DECR(this->unusedTimer25A);
DECR(this->yawTimer);
- DECR(this->unusedTimer25E);
- DECR(this->unkTimer260);
+ DECR(this->unkAttackNiwTimer);
+ DECR(this->iframeTimer);
this->actor.shape.rot = this->actor.world.rot;
this->actor.shape.shadowScale = 15.0f;
@@ -808,7 +837,7 @@ void EnNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, 20.0f, 60.0f, 0x1F);
- // if cucco is off the map?
+ // if cucco is off the map
if (this->actor.floorHeight <= BGCHECK_Y_MIN || this->actor.floorHeight >= BGCHECK_Y_MAX) {
Vec3f viewAtToEye;
@@ -820,7 +849,7 @@ void EnNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
this->actor.world.pos.x = this->actor.home.pos.x;
this->actor.world.pos.z = this->actor.home.pos.z;
- this->actor.world.pos.y = (this->actor.home.pos.y + globalCtx->view.eye.y) + (viewAtToEyeNormY * 160.0f);
+ this->actor.world.pos.y = this->actor.home.pos.y + globalCtx->view.eye.y + (viewAtToEyeNormY * 160.0f);
if (this->actor.world.pos.y < this->actor.home.pos.y) {
this->actor.world.pos.y = this->actor.home.pos.y + 300.0f;
@@ -833,75 +862,74 @@ void EnNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
this->unk304 = 0.0f;
this->unk300 = 0.0f;
- this->unusedFloat2FC = 0.0f;
+ this->unusedFloat2FC = 0.0f; // assigned here but never used after
this->unusedFloat2F8 = 0.0f;
this->unusedFloat2F4 = 0.0f;
- this->limbBRotx = 0.0f;
- this->limbBRoty = 0.0f;
- this->limbBRotz = 0.0f;
- this->limb7Rotx = 0.0f;
- this->limb7Roty = 0.0f;
- this->limb7Rotz = 0.0f;
- this->limbDRot = 0.0f;
- this->limbFRot = 0.0f;
+ this->rightWingRotX = 0.0f;
+ this->rightWingRotY = 0.0f;
+ this->rightWingRotZ = 0.0f;
+ this->leftWingRotX = 0.0f;
+ this->leftWingRotY = 0.0f;
+ this->leftWingRotZ = 0.0f;
+ this->upperBodyRotY = 0.0f;
+ this->headRotY = 0.0f;
// clang-format off
- this->isStormActive = this->unusedCounter28C = this->unk292 = this->unk29E = this->unk298 = this->unk29A = this->unk29C = 0;
+ this->isStormActive = this->unusedCounter28C = this->unk292 = this->unk29E = this->unk298 = this->isRunningRight = this->nextAnimation = 0;
// clang-format on
for (i = 0; i < 10; i++) {
- this->unk264[i] = 0.0f;
+ this->targetLimbRots[i] = 0.0f;
}
- this->unknownState28E = 8;
+ this->niwState = NIW_STATE_HOPPING;
this->isStormActive = false;
this->actionFunc = EnNiw_LandBeforeIdle;
return;
+ }
- } else if ((this->actor.bgCheckFlags & 0x20) && (this->actor.depthInWater > 15.0f) &&
- (this->unknownState28E != 6)) {
+ if ((this->actor.bgCheckFlags & 0x20) && // touching water
+ this->actor.depthInWater > 15.0f && this->niwState != NIW_STATE_SWIMMING) {
this->actor.velocity.y = 0.0f;
this->actor.gravity = 0.0f;
Math_Vec3f_Copy(&pos, &this->actor.world.pos);
pos.y += this->actor.depthInWater;
- this->unkTimer250 = 30;
+ this->swimRippleTimer = 30;
EffectSsGSplash_Spawn(globalCtx, &pos, 0, 0, 0, 400);
- this->unkTimer252 = 0;
- this->unknownState28E = 6;
+ this->generalTimer2 = 0;
+ this->niwState = NIW_STATE_SWIMMING;
this->actionFunc = EnNiw_Swimming;
+ return;
+ }
- } else {
- if (this->isStormActive && (this->actor.xyzDistToPlayerSq < (SQ(dist))) && (player->invincibilityTimer == 0)) {
- func_800B8D50(globalCtx, &this->actor, 2.0f, this->actor.world.rot.y, 0.0f, 0x10);
+ if (this->isStormActive && (this->actor.xyzDistToPlayerSq < SQ(dist)) && player->invincibilityTimer == 0) {
+ func_800B8D50(globalCtx, &this->actor, 2.0f, this->actor.world.rot.y, 0.0f, 0x10);
+ }
+
+ EnNiw_CheckRage(this, globalCtx);
+ if (this->flutterSfxTimer == 0 && this->niwState == NIW_STATE_HELD) {
+ this->flutterSfxTimer = 7;
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_CHICKEN_FLUTTER);
+ }
+
+ if (this->sfxTimer1 == 0) {
+ if (this->niwState != NIW_STATE_IDLE) {
+ this->sfxTimer1 = 30;
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_A);
+ } else {
+ this->sfxTimer1 = 300;
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_N);
}
+ }
- EnNiw_CheckRage(this, globalCtx);
- if ((this->flutterSfxTimer == 0) && (this->unknownState28E == 4)) {
- this->flutterSfxTimer = 7;
- Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_CHICKEN_FLUTTER);
- }
+ if (!this->isStormActive && this->niwType == NIW_TYPE_REGULAR) {
+ Collider_UpdateCylinder(&this->actor, &this->collider);
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
- if (this->sfxTimer1 == 0) {
- if (this->unknownState28E != 0) {
- this->sfxTimer1 = 30;
- Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_A); // attack cluck
- } else {
- this->sfxTimer1 = 300;
- Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_N); // cluck
- }
- }
+ if (globalCtx) {}
- if (!this->isStormActive) {
- if (this->niwType == ENNIW_TYPE_REGULAR) {
- Collider_UpdateCylinder(&this->actor, &this->collider);
- CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
-
- if (globalCtx) {}
-
- if ((this->unknownState28E != 4) && (this->unknownState28E != 5)) {
- CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
- }
- }
+ if (this->niwState != NIW_STATE_HELD && this->niwState != NIW_STATE_FALLING) {
+ CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
}
}
@@ -909,21 +937,21 @@ void EnNiw_Update(Actor* thisx, GlobalContext* globalCtx) {
s32 EnNiw_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
EnNiw* this = THIS;
- if (limbIndex == 13) {
- rot->y += (s16)this->limbDRot;
+ if (limbIndex == NIW_LIMB_UPPER_BODY) {
+ rot->y += (s16)this->upperBodyRotY;
}
- if (limbIndex == 15) {
- rot->y += (s16)this->limbFRot;
+ if (limbIndex == NIW_LIMB_HEAD) {
+ rot->y += (s16)this->headRotY;
}
- if (limbIndex == 11) {
- rot->x += (s16)this->limbBRotx;
- rot->y += (s16)this->limbBRoty;
- rot->z += (s16)this->limbBRotz;
+ if (limbIndex == NIW_LIMB_RIGHT_WING_ROOT) {
+ rot->x += (s16)this->rightWingRotX;
+ rot->y += (s16)this->rightWingRotY;
+ rot->z += (s16)this->rightWingRotZ;
}
- if (limbIndex == 7) {
- rot->x += (s16)this->limb7Rotx;
- rot->y += (s16)this->limb7Roty;
- rot->z += (s16)this->limb7Rotz;
+ if (limbIndex == NIW_LIMB_LEFT_WING_ROOT) {
+ rot->x += (s16)this->leftWingRotX;
+ rot->y += (s16)this->leftWingRotY;
+ rot->z += (s16)this->leftWingRotZ;
}
return false;
}
@@ -939,7 +967,7 @@ void EnNiw_Draw(Actor* thisx, GlobalContext* globalCtx) {
void EnNiw_SpawnFeather(EnNiw* this, Vec3f* pos, Vec3f* vel, Vec3f* accel, f32 scale) {
s16 i;
- EnNiwFeather* feather = this->feathers;
+ EnNiwFeather* feather = &this->feathers[0];
for (i = 0; i < ARRAY_COUNT(this->feathers); i++, feather++) {
if (feather->isEnabled == false) {
@@ -957,7 +985,7 @@ void EnNiw_SpawnFeather(EnNiw* this, Vec3f* pos, Vec3f* vel, Vec3f* accel, f32 s
}
void EnNiw_UpdateFeather(EnNiw* this, GlobalContext* globalCtx) {
- EnNiwFeather* feather = this->feathers;
+ EnNiwFeather* feather = &this->feathers[0];
f32 featherVelocityGoal = 0.05f;
s16 i;
@@ -988,7 +1016,6 @@ void EnNiw_UpdateFeather(EnNiw* this, GlobalContext* globalCtx) {
}
}
-// feather draw function
void EnNiw_DrawFeathers(EnNiw* this, GlobalContext* globalCtx) {
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
u8 isMaterialApplied = false;
diff --git a/src/overlays/actors/ovl_En_Niw/z_en_niw.h b/src/overlays/actors/ovl_En_Niw/z_en_niw.h
index 5a03215bcb..7c8b3e07e8 100644
--- a/src/overlays/actors/ovl_En_Niw/z_en_niw.h
+++ b/src/overlays/actors/ovl_En_Niw/z_en_niw.h
@@ -2,6 +2,7 @@
#define Z_EN_NIW_H
#include "global.h"
+#include "objects/object_niw/object_niw.h"
struct EnNiw;
@@ -19,55 +20,67 @@ typedef struct {
/* 0x0034 */ u8 timer;
} EnNiwFeather; // size = 0x38
-#define ENNIW_LIMBCOUNT 16
-#define ENNIW_FEATHERCOUNT 20
+#define NIW_FEATHER_COUNT 20
typedef struct EnNiw {
/* 0x000 */ Actor actor;
/* 0x144 */ SkelAnime skelanime;
- /* 0x188 */ Vec3s jointTable[ENNIW_LIMBCOUNT];
- /* 0x1E8 */ Vec3s morphTable[ENNIW_LIMBCOUNT];
+ /* 0x188 */ Vec3s jointTable[NIW_LIMB_MAX];
+ /* 0x1E8 */ Vec3s morphTable[NIW_LIMB_MAX];
/* 0x248 */ EnNiwActionFunc actionFunc;
- /* 0x24C */ s16 unkTimer24C;
+ /* 0x24C */ s16 unkTimer24C; // set to 10, checked in mystery func
/* 0x24E */ s16 unkTimer24E;
- /* 0x250 */ s16 unkTimer250;
- /* 0x252 */ s16 unkTimer252;
- /* 0x254 */ s16 unkTimer254;
+ /* 0x250 */ union {
+ s16 generalTimer1; // default name for reset/decr
+ s16 hopTimer; // every 3 frames while running/idling
+ s16 swimRippleTimer; // how often swimming cucco spawns ripples
+ s16 heldTimer; // timer until updating unk29E
+ s16 unkIdleTimer; // not sure what _Idle is doing with it yet
+ };
+ /* 0x252 */ union {
+ s16 generalTimer2; // default name for reset/decr
+ s16 hoppingTimer; // hopping after being thrown before running
+ s16 attackNiwSpawnTimer; // delay between re-attempting to spawn more attack_niw
+ s16 runningDirectionTimer; // delay between direction changes when running
+ s16 cuccoStormTimer; // delay between stages of summoning the storm
+ s16 unkIdleTimer2; // not sure what _Idle is doing with it yet
+ };
+ /* 0x254 */ s16 runAwayTimer;
/* 0x256 */ s16 sfxTimer1;
/* 0x258 */ s16 flutterSfxTimer;
/* 0x25A */ s16 unusedTimer25A;
- /* 0x25C */ s16 yawTimer; // every 70 frames rechecks yawToPlayer
- /* 0x25E */ s16 unusedTimer25E;
- /* 0x260 */ s16 unkTimer260;
- /* 0x264 */ f32 unk264[10];
+ /* 0x25C */ s16 yawTimer; // every 70 frames rechecks yawToPlayer
+ /* 0x25E */ s16 unkAttackNiwTimer; // every 70 frames, updates some player unk values
+ /* 0x260 */ s16 iframeTimer;
+ /* 0x264 */ f32 targetLimbRots[10];
/* 0x28C */ s16 unusedCounter28C;
- /* 0x28E */ s16 unknownState28E;
- /* 0x290 */ s16 unk290;
+ /* 0x28E */ s16 niwState;
+ /* 0x290 */ s16 attackNiwCount;
/* 0x292 */ s16 unk292;
/* 0x294 */ s16 pad294;
- /* 0x296 */ s16 unk296;
+ /* 0x296 */ s16 unkToggle296;
/* 0x298 */ s16 unk298;
- /* 0x29C */ s16 unk29A;
- /* 0x29C */ u16 unk29C;
- /* 0x29E */ s16 unk29E;
- /* 0x2A0 */ s16 isStormActive;
+ /* 0x29C */ s16 isRunningRight; // toggle (direction cucco is turning while running)
+ /* 0x29C */ u16 nextAnimation;
+ /* 0x29E */ s16 unk29E; // three states 0/1/2
+ /* 0x2A0 */ s16 isStormActive; // we have a data value shared between all cucco, this shouldn't need to exist
/* 0x2A2 */ s16 niwType;
/* 0x2A4 */ Vec3f unk2A4;
/* 0x2B0 */ Vec3f unk2B0;
- /* 0x2BC */ Vec3f unk2BC;
- /* 0x2C8 */ f32 limb7Rotz;
- /* 0x2CC */ f32 limb7Roty;
- /* 0x2D0 */ f32 limb7Rotx;
- /* 0x2D4 */ f32 limbBRotz;
- /* 0x2D8 */ f32 limbBRoty;
- /* 0x2DC */ f32 limbBRotx;
- /* 0x2E0 */ f32 limbDRot;
- /* 0x2E4 */ f32 limbFRot;
+ /* 0x2BC */ Vec3f unk2BC; // init from data (90000 on all three)
+ /* 0x2C8 */ f32 leftWingRotZ;
+ /* 0x2CC */ f32 leftWingRotY;
+ /* 0x2D0 */ f32 leftWingRotX;
+ /* 0x2D4 */ f32 rightWingRotZ;
+ /* 0x2D8 */ f32 rightWingRotY;
+ /* 0x2DC */ f32 rightWingRotX;
+ /* 0x2E0 */ f32 upperBodyRotY;
+ /* 0x2E4 */ f32 headRotY;
/* 0x2E8 */ s16 yawTowardsPlayer;
- /* 0x2EA */ s16 unk2EA;
+ /* 0x2EA */ s16 headRotationToggle;
/* 0x2EC */ s16 unk2EC;
/* 0x2EE */ UNK_TYPE1 pad2EE[0x6];
- /* 0x2F4 */ f32 unusedFloat2F4;
+ /* 0x2F4 */ f32 unusedFloat2F4; // set in EnNiw_Update if Cucco falls off map, never read
/* 0x2F8 */ f32 unusedFloat2F8;
/* 0x2FC */ f32 unusedFloat2FC;
/* 0x300 */ f32 unk300;
@@ -75,16 +88,26 @@ typedef struct EnNiw {
/* 0x308 */ f32 unk308;
/* 0x30C */ s32 pad30C;
/* 0x310 */ ColliderCylinder collider;
- /* 0x35C */ EnNiwFeather feathers[ENNIW_FEATHERCOUNT];
+ /* 0x35C */ EnNiwFeather feathers[NIW_FEATHER_COUNT];
} EnNiw; // size = 0x7BC
// in init, any value below zero becomes zero
-// however, in vanilla, only 0xFFFF (-1) exists
-#define ENNIW_TYPE_VANILLA 0xFFFF
-#define ENNIW_TYPE_REGULAR 0
-#define ENNIW_TYPE_UNK1 1
-#define ENNIW_TYPE_UNK2 2
-// the attacking cuccos are not here, they are a different actor:
-// ovl_En_Attack_Niw
+// however, in vanilla, only 0xFFFF (-1) exists in scene spawns, actors can spawn 0x0
+#define NIW_TYPE_VANILLA 0xFFFF
+#define NIW_TYPE_REGULAR 0
+#define NIW_TYPE_UNK1 1
+#define NIW_TYPE_HELD 2 // spawns held by the bomber kid in east clock town during hide and seek
+// the attacking cuccos are not here, they are a different actor: [ ovl_En_Attack_Niw ]
+
+typedef enum {
+ /* 0 */ NIW_ANIMATION_STILL,
+ /* 1 */ NIW_ANIMATION_HEAD_PECKING, // forward and backward, feeding
+ /* 2 */ NIW_ANIMATION_PECKING_AND_WAVING, // wings move along their axis, like human hand waving
+ /* 3 */ NIW_ANIMATION_PECKING_AND_FORFLAPPING, // (unused) low (yaw based) flapping, forward and back
+ /* 4 */ NIW_ANIMATION_FREEZE, // used during Cucco Storm
+ /* 5 */ NIW_ANIMATION_PECKING_SLOW_FORFLAPPING, // wing speed half that of 3
+
+} EnNiwHeadAndWingAnimationState;
+
#endif // Z_EN_NIW_H
diff --git a/src/overlays/actors/ovl_En_Nwc/z_en_nwc.c b/src/overlays/actors/ovl_En_Nwc/z_en_nwc.c
index 4c0fdce1ef..8d254b7287 100644
--- a/src/overlays/actors/ovl_En_Nwc/z_en_nwc.c
+++ b/src/overlays/actors/ovl_En_Nwc/z_en_nwc.c
@@ -2,9 +2,14 @@
* File: z_en_nwc.c
* Overlay: ovl_En_Nwc
* Description: Cucco chick
+ *
+ * This actor requires object_niw to be present for the transformation during Breman Mask March
+ * EnHs (Grog) must also be present to maintain the count of the EnNwc in the march
*/
#include "z_en_nwc.h"
+#include "overlays/actors/ovl_En_Niw/z_en_niw.h"
+#include "objects/object_nwc/object_nwc.h"
#define FLAGS (ACTOR_FLAG_10)
@@ -15,15 +20,27 @@ void EnNwc_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnNwc_Update(Actor* thisx, GlobalContext* globalCtx);
void EnNwc_Draw(Actor* thisx, GlobalContext* globalCtx);
-void func_809448A4(EnNwc* this, GlobalContext* globalCtx);
-void func_809449D0(EnNwc* this, GlobalContext* globalCtx);
-void func_80944A50(EnNwc* this, GlobalContext* globalCtx);
-void func_80944E44(EnNwc* this, GlobalContext* globalCtx);
-void func_80944EFC(EnNwc* this, GlobalContext* globalCtx);
-void func_80944FA8(EnNwc* this, GlobalContext* globalCtx);
-void func_8094506C(EnNwc* this, GlobalContext* globalCtx);
+void EnNwc_LoadNiwSkeleton(EnNwc* this, GlobalContext* globalCtx);
+void EnNwc_CrowAtTheEnd(EnNwc* this, GlobalContext* globalCtx);
+void EnNwc_Follow(EnNwc* this, GlobalContext* globalCtx);
+void EnNwc_HopForward(EnNwc* this, GlobalContext* globalCtx);
+void EnNwc_RunAway(EnNwc* this, GlobalContext* globalCtx);
+void EnNwc_Turn(EnNwc* this, GlobalContext* globalCtx);
+void EnNwc_CheckForBreman(EnNwc* this, GlobalContext* globalCtx);
+
+void EnNwc_DrawAdultBody(Actor* thisx, GlobalContext* globalCtx);
+s32 EnNwc_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx);
+EnHs* EnNwc_FindGrog(GlobalContext* globalCtx);
+
+enum EnNiwState {
+ /* -1 */ NWC_STATE_NIW_LOADED = -1, // set after loading object_niw
+ /* 0 */ NWC_STATE_CHECK_BREMAN = 0, // checking for breman mask
+ /* 1 */ NWC_STATE_TURNING, // turning to face a new direction to explore
+ /* 2 */ NWC_STATE_HOPPING_FORWARD, // hopping to go explore
+ /* 3 */ NWC_STATE_FOLLOWING, // following the player
+ /* 4 */ NWC_STATE_RUNNING, // running from the player after failed breman march
+};
-#if 0
const ActorInit En_Nwc_InitVars = {
ACTOR_EN_NWC,
ACTORCAT_PROP,
@@ -36,47 +53,474 @@ const ActorInit En_Nwc_InitVars = {
(ActorFunc)EnNwc_Draw,
};
-#endif
+Color_RGBA8 sPrimColor = { 255, 255, 255, 255 };
-extern UNK_TYPE D_060000E8;
-extern UNK_TYPE D_060002E8;
+Color_RGBA8 sEnvColor = { 80, 80, 80, 255 };
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/EnNwc_Init.s")
+void EnNwc_Init(Actor* thisx, GlobalContext* globalCtx) {
+ s32 niwObjectIndex;
+ EnNwc* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/EnNwc_Destroy.s")
+ niwObjectIndex = Object_GetIndex(&globalCtx->objectCtx, OBJECT_NIW);
+ if (niwObjectIndex < 0) {
+ // niw object does not exist, we need it for tranformation, despawn
+ Actor_MarkForDeath(&this->actor);
+ return;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80944320.s")
+ if (gSaveContext.save.weekEventReg[25] & 8) {
+ // if breman mask was already used, replace with adult EnNiw
+ Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_NIW, this->actor.world.pos.x, this->actor.world.pos.y,
+ this->actor.world.pos.z, 0, this->actor.world.rot.y, 0, NIW_TYPE_REGULAR);
+ Actor_MarkForDeath(&this->actor);
+ return;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80944554.s")
+ this->niwObjectIndex = niwObjectIndex;
+ this->nwcObjectIndex = this->actor.objBankIndex;
+ this->grog = EnNwc_FindGrog(globalCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80944590.s")
+ this->footRotY = this->footRotZ = 0;
+ Actor_SetScale(&this->actor, 0.01f);
+ this->actionFunc = EnNwc_LoadNiwSkeleton;
+ this->hasGrownUp = false;
+ ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 6.0f);
+ this->actor.velocity.y = 0.0f;
+ this->actor.terminalVelocity = -9.0f;
+ this->actor.gravity = -1.0f;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_809445D4.s")
+void EnNwc_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+ EnNwc* this = THIS;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80944630.s")
+void EnNwc_SpawnDust(EnNwc* this, GlobalContext* globalCtx) {
+ Vec3f pos;
+ Vec3f vec5;
+ Vec3f vel;
+ Vec3f accel;
+ s16 yaw;
+ s16 pitch;
+ Vec3f eye = GET_ACTIVE_CAM(globalCtx)->eye;
+ s32 i;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_809447A8.s")
+ 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);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80944818.s")
+ 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;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_809448A4.s")
+ func_800B0F80(globalCtx, &pos, &vel, &accel, &sPrimColor, &sEnvColor, 300, 30, 10);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_809449D0.s")
+EnHs* EnNwc_FindGrog(GlobalContext* globalCtx) {
+ Actor* grogSearch = globalCtx->actorCtx.actorLists[ACTORCAT_NPC].first;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80944A50.s")
+ while (grogSearch != NULL) {
+ if (grogSearch->id == ACTOR_EN_HS) {
+ return (EnHs*)grogSearch;
+ }
+ grogSearch = grogSearch->next;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80944E44.s")
+ return NULL;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80944EFC.s")
+s32 EnNwc_PlayerReleasedBremanMarch(EnNwc* this, GlobalContext* globalCtx) {
+ Player* player = GET_PLAYER(globalCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80944FA8.s")
+ // Weird: home.rot.x holds count of chicks having transformed into adult.
+ // Weird: Its incremented by 1 unlike chicks following, so it should max at 10.
+ if (this->grog->actor.home.rot.x >= 20) {
+ return false;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_8094506C.s")
+ if (player->stateFlags3 & 0x20000000) { // breman mask march
+ return false;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/EnNwc_Update.s")
+ return true;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/EnNwc_Draw.s")
+/**
+ * Summary: Checks 1) if grog exists, 2) player is using breman mask, 3) and within range.
+ * Used to identify if the chick should be captured by breman mask.
+ */
+s32 EnNwc_IsFound(EnNwc* this, GlobalContext* globalCtx) {
+ Player* player = GET_PLAYER(globalCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_8094529C.s")
+ if (this->grog == NULL) {
+ return false;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Nwc/func_80945310.s")
+ if (player->stateFlags3 & 0x20000000 && // breman mask march
+ this->actor.xzDistToPlayer < 100.0f) {
+ return true;
+ }
+
+ return false;
+}
+
+void EnNwc_ChangeState(EnNwc* this, s16 newState) {
+ this->actor.speedXZ = 0.0f;
+ switch (newState) {
+ case NWC_STATE_CHECK_BREMAN:
+ this->stateTimer = 10;
+ this->actionFunc = EnNwc_CheckForBreman;
+ break;
+ case NWC_STATE_TURNING:
+ this->stateTimer = Rand_ZeroFloat(20.0f) + 15.0f;
+ this->actionFunc = EnNwc_Turn;
+ this->fallingRotY = (s16)(s32)randPlusMinusPoint5Scaled(65536.0f);
+ break;
+ case NWC_STATE_HOPPING_FORWARD:
+ this->stateTimer = Rand_ZeroFloat(20.0f) + 15.0f;
+ this->actionFunc = EnNwc_HopForward;
+ break;
+ case NWC_STATE_FOLLOWING:
+ this->actionFunc = EnNwc_Follow;
+ this->transformTimer = 0;
+ this->randomRot = (s16)(s32)randPlusMinusPoint5Scaled(10000.0f);
+ break;
+ case NWC_STATE_RUNNING:
+ this->actor.world.rot.y = this->actor.home.rot.z * 0x3000 & 0xFFFF; // Fake Match?: & 0xFFFF
+ this->actor.shape.rot.y = this->actor.world.rot.y;
+ this->stateTimer = Rand_ZeroFloat(40.0f) + 120.0f;
+ this->actionFunc = EnNwc_RunAway;
+ break;
+ }
+
+ this->state = newState;
+}
+
+/**
+ * Summary: Changes the current actor state
+ * If previously random behavior -> check if breman mask is active
+ * If previously checking for breman -> select random (NWC_STATE_TURNING, NWC_STATE_HOPPING_FORWARD)
+ */
+void EnNwc_ToggleState(EnNwc* this) {
+ this->actor.speedXZ = 0.0f;
+ if (this->state != NWC_STATE_CHECK_BREMAN) {
+ EnNwc_ChangeState(this, NWC_STATE_CHECK_BREMAN);
+ } else {
+ EnNwc_ChangeState(this, Rand_ZeroFloat(2.0f) + 1.0f);
+ }
+}
+
+void EnNwc_CheckFound(EnNwc* this, GlobalContext* globalCtx) {
+ if (EnNwc_IsFound(this, globalCtx)) {
+ u8 currentChickCount = (this->grog->actor.home.rot.z / 2);
+
+ if (currentChickCount > 9) {
+ currentChickCount = 9;
+ }
+
+ // save our current chick order
+ this->actor.home.rot.z = this->grog->actor.home.rot.z + 1;
+
+ // if < 10 chicks, increment grog's chick counter
+ if (this->grog->actor.home.rot.z < 20) {
+ this->grog->actor.home.rot.z += 2;
+ }
+
+ EnNwc_ChangeState(this, NWC_STATE_FOLLOWING);
+ func_801A0868(&D_801DB4A4, NA_SE_SY_CHICK_JOIN_CHIME, currentChickCount);
+ }
+}
+
+void EnNwc_LoadNiwSkeleton(EnNwc* this, GlobalContext* globalCtx) {
+ if (Object_IsLoaded(&globalCtx->objectCtx, this->niwObjectIndex)) {
+ gSegments[6] = PHYSICAL_TO_VIRTUAL(globalCtx->objectCtx.status[this->niwObjectIndex].segment);
+
+ SkelAnime_InitFlex(globalCtx, &this->niwSkeleton, &gNiwSkeleton, &gNiwIdleAnim, this->jointTable,
+ this->morphTable, NIW_LIMB_MAX);
+ Animation_Change(&this->niwSkeleton, &gNiwIdleAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gNiwIdleAnim), 0, 0.0f);
+
+ gSegments[6] = PHYSICAL_TO_VIRTUAL(globalCtx->objectCtx.status[this->nwcObjectIndex].segment);
+ this->state = NWC_STATE_NIW_LOADED;
+ EnNwc_ToggleState(this);
+ }
+}
+
+void EnNwc_CrowAtTheEnd(EnNwc* this, GlobalContext* globalCtx) {
+ // I guess grog handles the scene transit?
+ Math_SmoothStepToS(&this->upperBodyRotY, 0x2710, 2, 0x1B58, 0x3E8);
+ Math_SmoothStepToS(&this->footRotZ, 0, 2, 0x1B58, 0x3E8);
+ Math_SmoothStepToS(&this->footRotY, 0x36B0, 2, 0x1B58, 0x3E8);
+}
+
+/**
+ * Summary: Controls the Chick when following Breman Mask.
+ *
+ * ActionFunc for NWC Type: NWC_STATE_FOLLOWING
+ */
+void EnNwc_Follow(EnNwc* this, GlobalContext* globalCtx) {
+ Vec3f* chickCoords = this->grog->nwcPos;
+ Vec3f targetVector;
+ s32 pad;
+ s16 newRotY;
+
+ this->stateTimer++;
+ if (this->hasGrownUp & 1) {
+ s16 targetUpperBodyRot = 0;
+ s16 targetFootRot = 0;
+
+ if (this->actor.speedXZ > 0.0f) {
+ if (this->stateTimer & 4) {
+ targetFootRot = 0x1B58;
+ targetUpperBodyRot = -0x2710;
+ }
+ if ((this->stateTimer & 3) == 3) {
+ this->actor.velocity.y = 2.0f; // hop up and down
+ }
+ }
+ Math_SmoothStepToS(&this->footRotZ, targetFootRot, 2, 0x1B58, 0x3E8);
+ Math_SmoothStepToS(&this->upperBodyRotY, targetUpperBodyRot, 2, 0x1B58, 0x3E8);
+
+ } else { // NOT grown up
+ if ((this->stateTimer & 3) == 3 && this->stateTimer & 20) {
+ this->actor.velocity.y = 2.0f; // hop up and down
+ }
+ if ((this->stateTimer & 0x1B) == 24) {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICK_SONG);
+ }
+ }
+
+ if (this->grog->actor.home.rot.z >= 20 && // all 10 chicks have been found
+ (this->hasGrownUp & 1) == false) {
+ this->transformTimer += 2;
+ if (this->transformTimer >= (s32)(s16)((this->actor.home.rot.z * 0x1E) + 0x1E)) {
+ // it is our turn to transform
+ this->hasGrownUp |= 1;
+ this->grog->actor.home.rot.x += 2; // increment grog's adult tranformation counter
+ EnNwc_SpawnDust(this, globalCtx);
+ Actor_SetScale(&this->actor, 0.002f);
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICK_TO_CHICKEN);
+ }
+ }
+
+ Math_Vec3f_Diff(&chickCoords[this->actor.home.rot.z], &this->actor.world.pos, &targetVector);
+ if (SQXZ(targetVector) < SQ(5.0f)) { // too close to keep moving, stop
+ this->actor.speedXZ = 0.0f;
+
+ // first nwc in the line follows player, the rest follow the previous one
+ if (this->actor.home.rot.z == 1) {
+ newRotY = this->actor.yawTowardsPlayer;
+ } else {
+ // for some reason the array is 10 * 2, incremented by 2, so this is "index - 1"
+ newRotY = Math_Vec3f_Yaw(&this->actor.world.pos, &chickCoords[this->actor.home.rot.z - 2]);
+ }
+
+ } else { // not too close: keep moving
+ this->randomRot += (s16)randPlusMinusPoint5Scaled(1500.0f);
+ if (this->randomRot > 0x1388) {
+ this->randomRot = 0x1388;
+ } else if (this->randomRot < -0x1388) {
+ this->randomRot = -0x1388;
+ }
+ this->actor.speedXZ = 2.0f;
+ newRotY = Math_Vec3f_Yaw(&this->actor.world.pos, &chickCoords[this->actor.home.rot.z]) + this->randomRot;
+ }
+
+ this->actor.world.rot.y = newRotY;
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.world.rot.y, 2, 0xBB8, 0xC8);
+
+ if (EnNwc_PlayerReleasedBremanMarch(this, globalCtx)) {
+ this->grog->actor.home.rot.x = 0; // reset adult count
+ this->grog->actor.home.rot.z = 0; // reset chick follow count
+
+ EnNwc_ChangeState(this, NWC_STATE_RUNNING);
+
+ if (this->hasGrownUp & 1) {
+ EnNwc_SpawnDust(this, globalCtx);
+ }
+
+ this->hasGrownUp &= ~1;
+ Actor_SetScale(&this->actor, 0.01f);
+ }
+
+ if (this->actor.scale.x < 0.01f) {
+ this->actor.scale.x += 0.002f;
+ Actor_SetScale(&this->actor, this->actor.scale.x);
+ }
+
+ if (this->grog->actor.home.rot.x >= 20) { // all chicks have turned into adult cucco, stop and crow
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICKEN_CRY_M);
+ this->actionFunc = EnNwc_CrowAtTheEnd;
+ this->actor.speedXZ = 0.0f;
+ Actor_SetScale(&this->actor, 0.01f);
+ }
+}
+
+/**
+ * Summary: Chick is Walking (Hopping) in a straight line.
+ *
+ * ActionFunc for NWC Type: NWC_STATE_HOPPING_FORWARD
+ */
+void EnNwc_HopForward(EnNwc* this, GlobalContext* globalCtx) {
+ if (DECR(this->stateTimer) == 0) {
+ EnNwc_ToggleState(this);
+ return;
+ }
+
+ if ((this->stateTimer & 3) == 3) {
+ this->actor.velocity.y = 2.0f; // hop up and down
+ }
+ if ((this->stateTimer & 0xB) == 8) {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICK_SONG);
+ }
+
+ // they only move forward while off the ground, which gives the visual of them hopping to move
+ if (this->actor.bgCheckFlags & 0x1) { // touching floor
+ this->actor.speedXZ = 0.0f;
+ } else {
+ this->actor.speedXZ = 2.0f;
+ }
+}
+
+/**
+ * Summary: Chick is Running Away from player (Breman Mask was dropped).
+ *
+ * ActionFunc for NWC Type: NWC_STATE_RUNNING
+ */
+void EnNwc_RunAway(EnNwc* this, GlobalContext* globalCtx) {
+ if (DECR(this->stateTimer) == 0) {
+ EnNwc_ToggleState(this);
+ return;
+ }
+
+ if ((this->stateTimer & 3) == 3) {
+ this->actor.velocity.y = 2.0f; // hop up and down
+ }
+ if ((this->stateTimer & 0xB) == 8) {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICK_SONG);
+ }
+
+ this->actor.speedXZ = 2.0f;
+ if (this->actor.bgCheckFlags & 0x8) { // touching wall
+ EnNwc_ToggleState(this);
+ }
+}
+
+/**
+ * Summary: Chick is turning to face a new direction.
+ *
+ * ActionFunc for NWC Type: NWC_STATE_TURNING
+ */
+void EnNwc_Turn(EnNwc* this, GlobalContext* globalCtx) {
+ if (DECR(this->stateTimer) == 0) {
+ EnNwc_ToggleState(this);
+ return;
+ }
+
+ if ((this->stateTimer & 7) == 7) {
+ this->actor.velocity.y = 2.0f; // vertical hop
+ }
+
+ if ((this->stateTimer & 0xB) == 8) {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_CHICK_SONG);
+ }
+
+ // they only rotate when off the ground, giving the visual that they turn by hopping
+ if (!(this->actor.bgCheckFlags & 0x1)) { // NOT touching floor
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->fallingRotY, 0xA, 0x1000, 0x800);
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+ }
+}
+
+/**
+ * Summary: Chick is standing still.
+ * Looking around, can see the player with the Breman Mask
+ *
+ * ActionFunc for NWC Type: NWC_STATE_CHECK_BREMAN
+ */
+void EnNwc_CheckForBreman(EnNwc* this, GlobalContext* globalCtx) {
+ if (DECR(this->stateTimer) == 0) {
+ EnNwc_ToggleState(this);
+ }
+
+ EnNwc_CheckFound(this, globalCtx);
+}
+
+void EnNwc_Update(Actor* thisx, GlobalContext* globalCtx) {
+ EnNwc* this = THIS;
+
+ Actor_MoveWithGravity(&this->actor);
+ Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 10.0f, 10.0f, 10.0f, 5);
+ this->actionFunc(this, globalCtx);
+ if (this->hasGrownUp & 1) {
+ this->actor.objBankIndex = this->niwObjectIndex;
+ this->actor.draw = EnNwc_DrawAdultBody;
+ this->actor.shape.shadowScale = 15.0f;
+ } else {
+ this->actor.objBankIndex = this->nwcObjectIndex;
+ this->actor.draw = EnNwc_Draw;
+ this->actor.shape.shadowScale = 6.0f;
+ }
+
+ if (DECR(this->blinkTimer) == 0) {
+ this->blinkTimer = Rand_S16Offset(0x3C, 0x3C);
+ }
+
+ if (this->blinkTimer == 1 || this->blinkTimer == 3) {
+ this->blinkState = true;
+ } else {
+ this->blinkState = false;
+ }
+}
+
+void EnNwc_Draw(Actor* thisx, GlobalContext* globalCtx) {
+ TexturePtr eyeTextures[] = { gNwcEyeOpenTex, gNwcEyeClosedTex };
+ EnNwc* this = THIS;
+ Gfx* dispHead;
+
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+
+ func_8012C28C(globalCtx->state.gfxCtx);
+
+ dispHead = POLY_OPA_DISP;
+
+ gSPSegment(&dispHead[0], 0x08, Lib_SegmentedToVirtual(eyeTextures[this->blinkState]));
+
+ gSPMatrix(&dispHead[1], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ gSPDisplayList(&dispHead[2], &gNwcBodyDL);
+
+ POLY_OPA_DISP = &dispHead[3];
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
+}
+
+s32 EnNwc_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
+ EnNwc* this = THIS;
+
+ if (limbIndex == NIW_LIMB_UPPER_BODY) {
+ rot->y += this->upperBodyRotY;
+ }
+ if (limbIndex == NIW_LIMB_RIGHT_WING_ROOT || limbIndex == NIW_LIMB_LEFT_WING_ROOT) {
+ rot->y += this->footRotY;
+ rot->z += this->footRotZ;
+ }
+
+ return false;
+}
+
+void EnNwc_DrawAdultBody(Actor* thisx, GlobalContext* globalCtx) {
+ EnNwc* this = THIS;
+
+ func_8012C28C(globalCtx->state.gfxCtx);
+ SkelAnime_DrawFlexOpa(globalCtx, this->niwSkeleton.skeleton, this->niwSkeleton.jointTable,
+ this->niwSkeleton.dListCount, EnNwc_OverrideLimbDraw, NULL, &this->actor);
+}
diff --git a/src/overlays/actors/ovl_En_Nwc/z_en_nwc.h b/src/overlays/actors/ovl_En_Nwc/z_en_nwc.h
index ccdfb59bb0..3815852af4 100644
--- a/src/overlays/actors/ovl_En_Nwc/z_en_nwc.h
+++ b/src/overlays/actors/ovl_En_Nwc/z_en_nwc.h
@@ -2,15 +2,37 @@
#define Z_EN_NWC_H
#include "global.h"
+#include "objects/object_niw/object_niw.h"
+#include "overlays/actors/ovl_En_Hs/z_en_hs.h" // grog
+
struct EnNwc;
typedef void (*EnNwcActionFunc)(struct EnNwc*, GlobalContext*);
typedef struct EnNwc {
- /* 0x0000 */ Actor actor;
- /* 0x0144 */ char unk_144[0x120];
- /* 0x0264 */ EnNwcActionFunc actionFunc;
+ /* 0x000 */ Actor actor;
+ /* 0x144 */ SkelAnime niwSkeleton; // this skeleton is for when the chicks grow up into adults during the breman march
+ /* 0x188 */ Vec3s jointTable[NIW_LIMB_MAX];
+ /* 0x1E8 */ Vec3s morphTable[NIW_LIMB_MAX];
+ /* 0x248 */ s8 niwObjectIndex;
+ /* 0x249 */ s8 nwcObjectIndex;
+ /* 0x24A */ s16 blinkState;
+ /* 0x24C */ s16 blinkTimer;
+ /* 0x250 */ EnHs* grog;
+ /* 0x254 */ s16 stateTimer; // count frames to next state change
+ /* 0x256 */ union {
+ s16 mixedValue256; // default name for reset
+ s16 transformTimer; // frames since transformation sequence started
+ s16 fallingRotY; // target rotation if off the ground in state 1
+ };
+ /* 0x258 */ s16 randomRot;
+ /* 0x25A */ s16 state;
+ /* 0x25C */ u16 hasGrownUp; // treated as both a boolean and a flag variable (0x1)
+ /* 0x25E */ s16 footRotY;
+ /* 0x260 */ s16 footRotZ;
+ /* 0x262 */ s16 upperBodyRotY;
+ /* 0x264 */ EnNwcActionFunc actionFunc;
} EnNwc; // size = 0x268
extern const ActorInit En_Nwc_InitVars;
diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt
index c4f1a053b7..e552ca3367 100644
--- a/tools/disasm/functions.txt
+++ b/tools/disasm/functions.txt
@@ -5424,9 +5424,9 @@
0x808908D0:("func_808908D0",),
0x80891060:("EnNiw_Init",),
0x808912E8:("EnNiw_Destroy",),
- 0x80891320:("func_80891320",),
+ 0x80891320:("EnNiw_AnimateWingHead",),
0x808916B0:("EnNiw_SpawnAttackNiw",),
- 0x808917F8:("func_808917F8",),
+ 0x808917F8:("EnNiw_UpdateRunning",),
0x80891974:("EnNiw_SetupIdle",),
0x808919E8:("EnNiw_Idle",),
0x80891D78:("EnNiw_Held",),
@@ -7514,24 +7514,24 @@
0x80943EE4:("EnDaiku_Draw",),
0x809441E0:("EnNwc_Init",),
0x80944310:("EnNwc_Destroy",),
- 0x80944320:("func_80944320",),
- 0x80944554:("func_80944554",),
- 0x80944590:("func_80944590",),
- 0x809445D4:("func_809445D4",),
- 0x80944630:("func_80944630",),
- 0x809447A8:("func_809447A8",),
- 0x80944818:("func_80944818",),
- 0x809448A4:("func_809448A4",),
- 0x809449D0:("func_809449D0",),
- 0x80944A50:("func_80944A50",),
- 0x80944E44:("func_80944E44",),
- 0x80944EFC:("func_80944EFC",),
- 0x80944FA8:("func_80944FA8",),
- 0x8094506C:("func_8094506C",),
+ 0x80944320:("EnNwc_SpawnDust",),
+ 0x80944554:("EnNwc_FindGrog",),
+ 0x80944590:("EnNwc_PlayerReleasedBremanMarch",),
+ 0x809445D4:("EnNwc_IsFound",),
+ 0x80944630:("EnNwc_ChangeState",),
+ 0x809447A8:("EnNwc_ToggleState",),
+ 0x80944818:("EnNwc_CheckFound",),
+ 0x809448A4:("EnNwc_LoadNiwSkeleton",),
+ 0x809449D0:("EnNwc_CrowAtTheEnd",),
+ 0x80944A50:("EnNwc_Follow",),
+ 0x80944E44:("EnNwc_HopForward",),
+ 0x80944EFC:("EnNwc_RunAway",),
+ 0x80944FA8:("EnNwc_Turn",),
+ 0x8094506C:("EnNwc_CheckForBreman",),
0x809450C0:("EnNwc_Update",),
0x809451D8:("EnNwc_Draw",),
- 0x8094529C:("func_8094529C",),
- 0x80945310:("func_80945310",),
+ 0x8094529C:("EnNwc_OverrideLimbDraw",),
+ 0x80945310:("EnNwc_DrawAdultBody",),
0x809454F0:("ItemInbox_Init",),
0x80945524:("ItemInbox_Destroy",),
0x80945534:("ItemInbox_Idle",),
@@ -7641,13 +7641,13 @@
0x80952CC8:("EnHs_Init",),
0x80952DD0:("EnHs_Destroy",),
0x80952DFC:("func_80952DFC",),
- 0x80952E50:("func_80952E50",),
+ 0x80952E50:("EnHs_UpdateChickPos",),
0x80952F00:("func_80952F00",),
0x80952FE0:("func_80952FE0",),
0x80953098:("func_80953098",),
0x80953180:("func_80953180",),
- 0x809532C0:("func_809532C0",),
- 0x809532D0:("func_809532D0",),
+ 0x809532C0:("EnHs_DoNothing",),
+ 0x809532D0:("EnHs_SceneTransitToBunnyHoodDialogue",),
0x80953354:("func_80953354",),
0x809533A0:("func_809533A0",),
0x8095345C:("func_8095345C",),
@@ -7680,11 +7680,11 @@
0x80956954:("EnKanban_Draw",),
0x809580C0:("EnAttackNiw_Init",),
0x809581F4:("EnAttackNiw_Destroy",),
- 0x80958228:("func_80958228",),
- 0x809585B0:("func_809585B0",),
- 0x80958634:("func_80958634",),
- 0x80958974:("func_80958974",),
- 0x80958BE4:("func_80958BE4",),
+ 0x80958228:("EnAttackNiw_AnimateWingHead",),
+ 0x809585B0:("EnAttackNiw_IsOnScreen",),
+ 0x80958634:("EnAttackNiw_EnterViewFromOffscreen",),
+ 0x80958974:("EnAttackNiw_AimAtPlayer",),
+ 0x80958BE4:("EnAttackNiw_FlyAway",),
0x80958CA8:("EnAttackNiw_Update",),
0x80958F6C:("EnAttackNiw_OverrideLimbDraw",),
0x8095909C:("EnAttackNiw_Draw",),