summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorgamestabled <55638330+gamestabled@users.noreply.github.com>2021-02-12 17:22:48 -0500
committerGitHub <noreply@github.com>2021-02-12 17:22:48 -0500
commitef272322eb42061e4ddddf809cf0f2f0b1db82ca (patch)
treec943089feacc0627ccdc56f61421b110cf1ef181 /src
parentda55eaa2d8c05d8eaf2ad8d320189526268e7d59 (diff)
dekunuts OK (#664)
* dekunuts OK * named unk_19A * improved the match, got rid of volatile * one unaccounted blob * finished object_dekunuts * capitalization consistency * suggested changes * suggested changes again
Diffstat (limited to 'src')
-rw-r--r--src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c553
-rw-r--r--src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.h13
2 files changed, 498 insertions, 68 deletions
diff --git a/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c b/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c
index dd575c164..4212808d1 100644
--- a/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c
+++ b/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.c
@@ -5,30 +5,33 @@
*/
#include "z_en_dekunuts.h"
+#include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h"
+#include "objects/object_dekunuts/object_dekunuts.h"
#define FLAGS 0x00000005
#define THIS ((EnDekunuts*)thisx)
+#define DEKUNUTS_FLOWER 10
+
void EnDekunuts_Init(Actor* thisx, GlobalContext* globalCtx);
void EnDekunuts_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnDekunuts_Update(Actor* thisx, GlobalContext* globalCtx);
void EnDekunuts_Draw(Actor* thisx, GlobalContext* globalCtx);
-extern UNK_TYPE D_060001C4;
-extern UNK_TYPE D_06000368;
-extern UNK_TYPE D_060004D8;
-extern UNK_TYPE D_060006B0;
-extern UNK_TYPE D_060008C4;
-extern UNK_TYPE D_06000AF0;
-extern UNK_TYPE D_06000D1C;
-extern UNK_TYPE D_06000E6C;
-extern UNK_TYPE D_06001024;
-extern UNK_TYPE D_06002298;
-extern UNK_TYPE D_06003268;
-extern UNK_TYPE D_06003650;
+void EnDekunuts_SetupWait(EnDekunuts* this);
+void EnDekunuts_Wait(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_LookAround(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_Stand(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_ThrowNut(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_Burrow(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_BeginRun(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_Run(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_Gasp(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_BeDamaged(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_BeStunned(EnDekunuts* this, GlobalContext* globalCtx);
+void EnDekunuts_Die(EnDekunuts* this, GlobalContext* globalCtx);
-/*
const ActorInit En_Dekunuts_InitVars = {
ACTOR_EN_DEKUNUTS,
ACTORCAT_ENEMY,
@@ -41,7 +44,7 @@ const ActorInit En_Dekunuts_InitVars = {
(ActorFunc)EnDekunuts_Draw,
};
-static ColliderCylinderInit D_809EAB50 = {
+static ColliderCylinderInit sCylinderInit = {
{
COLTYPE_HIT6,
AT_NONE,
@@ -60,59 +63,475 @@ static ColliderCylinderInit D_809EAB50 = {
},
{ 18, 32, 0, { 0, 0, 0 } },
};
-*/
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/EnDekunuts_Init.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/EnDekunuts_Destroy.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E96FC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9770.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E97B8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9800.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9868.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E98B4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9920.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9978.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E99D8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9AB4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9B48.s")
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9B98.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9DFC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9E80.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809E9F6C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809EA0C4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809EA1D8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809EA240.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809EA480.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809EA4E8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809EA534.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809EA5B0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809EA70C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/EnDekunuts_Update.s")
+static CollisionCheckInfoInit sColChkInfoInit = { 0x01, 0x0012, 0x0020, MASS_IMMOVABLE };
+
+static DamageTable sDamageTable = {
+ /* Deku nut */ DMG_ENTRY(0, 0x1),
+ /* Deku stick */ DMG_ENTRY(2, 0x0),
+ /* Slingshot */ DMG_ENTRY(1, 0x0),
+ /* Explosive */ DMG_ENTRY(2, 0x0),
+ /* Boomerang */ DMG_ENTRY(1, 0x0),
+ /* Normal arrow */ DMG_ENTRY(2, 0x0),
+ /* Hammer swing */ DMG_ENTRY(2, 0x0),
+ /* Hookshot */ DMG_ENTRY(2, 0x0),
+ /* Kokiri sword */ DMG_ENTRY(1, 0x0),
+ /* Master sword */ DMG_ENTRY(2, 0x0),
+ /* Giant's Knife */ DMG_ENTRY(4, 0x0),
+ /* Fire arrow */ DMG_ENTRY(4, 0x2),
+ /* Ice arrow */ DMG_ENTRY(2, 0x0),
+ /* Light arrow */ DMG_ENTRY(2, 0x0),
+ /* Unk arrow 1 */ DMG_ENTRY(2, 0x0),
+ /* Unk arrow 2 */ DMG_ENTRY(2, 0x0),
+ /* Unk arrow 3 */ DMG_ENTRY(2, 0x0),
+ /* Fire magic */ DMG_ENTRY(4, 0x2),
+ /* Ice magic */ DMG_ENTRY(0, 0x0),
+ /* Light magic */ DMG_ENTRY(0, 0x0),
+ /* Shield */ DMG_ENTRY(0, 0x0),
+ /* Mirror Ray */ DMG_ENTRY(0, 0x0),
+ /* Kokiri spin */ DMG_ENTRY(1, 0x0),
+ /* Giant spin */ DMG_ENTRY(4, 0x0),
+ /* Master spin */ DMG_ENTRY(2, 0x0),
+ /* Kokiri jump */ DMG_ENTRY(2, 0x0),
+ /* Giant jump */ DMG_ENTRY(8, 0x0),
+ /* Master jump */ DMG_ENTRY(4, 0x0),
+ /* Unknown 1 */ DMG_ENTRY(0, 0x0),
+ /* Unblockable */ DMG_ENTRY(0, 0x0),
+ /* Hammer jump */ DMG_ENTRY(4, 0x0),
+ /* Unknown 2 */ DMG_ENTRY(0, 0x0),
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/func_809EA98C.s")
+static InitChainEntry sInitChain[] = {
+ ICHAIN_S8(naviEnemyId, 0x4D, ICHAIN_CONTINUE),
+ ICHAIN_F32(gravity, -1, ICHAIN_CONTINUE),
+ ICHAIN_F32(targetArrowOffset, 2600, ICHAIN_STOP),
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Dekunuts/EnDekunuts_Draw.s")
+void EnDekunuts_Init(Actor* thisx, GlobalContext* globalCtx) {
+ EnDekunuts* this = THIS;
+ s32 pad;
+
+ Actor_ProcessInitChain(&this->actor, sInitChain);
+ if (thisx->params == DEKUNUTS_FLOWER) {
+ thisx->flags &= ~0x5;
+ } else {
+ ActorShape_Init(&thisx->shape, 0.0f, ActorShadow_DrawCircle, 35.0f);
+ SkelAnime_Init(globalCtx, &this->skelAnime, &gDekuNutsSkel, &gDekuNutsStandAnim, this->jointTable,
+ this->morphTable, 25);
+ Collider_InitCylinder(globalCtx, &this->collider);
+ Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
+ CollisionCheck_SetInfo(&thisx->colChkInfo, &sDamageTable, &sColChkInfoInit);
+ this->shotsPerRound = ((thisx->params >> 8) & 0xFF);
+ thisx->params &= 0xFF;
+ if ((this->shotsPerRound == 0xFF) || (this->shotsPerRound == 0)) {
+ this->shotsPerRound = 1;
+ }
+ EnDekunuts_SetupWait(this);
+ Actor_SpawnAsChild(&globalCtx->actorCtx, thisx, globalCtx, ACTOR_EN_DEKUNUTS, thisx->world.pos.x,
+ thisx->world.pos.y, thisx->world.pos.z, 0, thisx->world.rot.y, 0, DEKUNUTS_FLOWER);
+ }
+}
+
+void EnDekunuts_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+ EnDekunuts* this = THIS;
+
+ if (this->actor.params != DEKUNUTS_FLOWER) {
+ Collider_DestroyCylinder(globalCtx, &this->collider);
+ }
+}
+
+void EnDekunuts_SetupWait(EnDekunuts* this) {
+ Animation_PlayOnceSetSpeed(&this->skelAnime, &gDekuNutsUpAnim, 0.0f);
+ this->animFlagAndTimer = Rand_S16Offset(100, 50);
+ this->collider.dim.height = 5;
+ Math_Vec3f_Copy(&this->actor.world.pos, &this->actor.home.pos);
+ this->collider.base.acFlags &= ~AC_ON;
+ this->actionFunc = EnDekunuts_Wait;
+}
+
+void EnDekunuts_SetupLookAround(EnDekunuts* this) {
+ Animation_PlayLoop(&this->skelAnime, &gDekuNutsLookAroundAnim);
+ this->animFlagAndTimer = 2;
+ this->actionFunc = EnDekunuts_LookAround;
+}
+
+void EnDekunuts_SetupThrowNut(EnDekunuts* this) {
+ Animation_PlayOnce(&this->skelAnime, &gDekuNutsSpitAnim);
+ this->animFlagAndTimer = this->shotsPerRound;
+ this->actionFunc = EnDekunuts_ThrowNut;
+}
+
+void EnDekunuts_SetupStand(EnDekunuts* this) {
+ Animation_MorphToLoop(&this->skelAnime, &gDekuNutsStandAnim, -3.0f);
+ if (this->actionFunc == EnDekunuts_ThrowNut) {
+ this->animFlagAndTimer = 2 | 0x1000; // sets timer and flag
+ } else {
+ this->animFlagAndTimer = 1;
+ }
+ this->actionFunc = EnDekunuts_Stand;
+}
+
+void EnDekunuts_SetupBurrow(EnDekunuts* this) {
+ Animation_MorphToPlayOnce(&this->skelAnime, &gDekuNutsBurrowAnim, -5.0f);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_DOWN);
+ this->actionFunc = EnDekunuts_Burrow;
+}
+
+void EnDekunuts_SetupBeginRun(EnDekunuts* this) {
+ Animation_MorphToPlayOnce(&this->skelAnime, &gDekuNutsUnburrowAnim, -3.0f);
+ this->collider.dim.height = 0x25;
+ this->actor.colChkInfo.mass = 0x32;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_DAMAGE);
+ this->collider.base.acFlags &= ~AC_ON;
+ this->actionFunc = EnDekunuts_BeginRun;
+}
+
+void EnDekunuts_SetupRun(EnDekunuts* this) {
+ Animation_PlayLoop(&this->skelAnime, &gDekuNutsRunAnim);
+ this->animFlagAndTimer = 2;
+ this->playWalkSound = false;
+ this->collider.base.acFlags |= AC_ON;
+ this->actionFunc = EnDekunuts_Run;
+}
+
+void EnDekunuts_SetupGasp(EnDekunuts* this) {
+ Animation_PlayLoop(&this->skelAnime, &gDekuNutsGaspAnim);
+ this->animFlagAndTimer = 3;
+ this->actor.speedXZ = 0.0f;
+ if (this->runAwayCount != 0) {
+ this->runAwayCount--;
+ }
+ this->actionFunc = EnDekunuts_Gasp;
+}
+
+void EnDekunuts_SetupBeDamaged(EnDekunuts* this) {
+ Animation_MorphToPlayOnce(&this->skelAnime, &gDekuNutsDamageAnim, -3.0f);
+ if ((this->collider.info.acHitInfo->toucher.dmgFlags & 0x1F824) != 0) {
+ this->actor.world.rot.y = this->collider.base.ac->world.rot.y;
+ } else {
+ this->actor.world.rot.y = Actor_WorldYawTowardActor(&this->actor, this->collider.base.ac) + 0x8000;
+ }
+ this->collider.base.acFlags &= ~AC_ON;
+ this->actionFunc = EnDekunuts_BeDamaged;
+ this->actor.speedXZ = 10.0f;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_DAMAGE);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_CUTBODY);
+ func_8003426C(&this->actor, 0x4000, 0xFF, 0, Animation_GetLastFrame(&gDekuNutsDamageAnim));
+}
+
+void EnDekunuts_SetupBeStunned(EnDekunuts* this) {
+ Animation_MorphToLoop(&this->skelAnime, &gDekuNutsDamageAnim, -3.0f);
+ this->animFlagAndTimer = 5;
+ this->actionFunc = EnDekunuts_BeStunned;
+ this->actor.speedXZ = 0.0f;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_JR_FREEZE);
+ func_8003426C(&this->actor, 0, 0xFF, 0, Animation_GetLastFrame(&gDekuNutsDamageAnim) * this->animFlagAndTimer);
+}
+
+void EnDekunuts_SetupDie(EnDekunuts* this) {
+ Animation_PlayOnce(&this->skelAnime, &gDekuNutsDieAnim);
+ this->actionFunc = EnDekunuts_Die;
+ this->actor.speedXZ = 0.0f;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_DEAD);
+}
+
+void EnDekunuts_Wait(EnDekunuts* this, GlobalContext* globalCtx) {
+ s32 hasSlowPlaybackSpeed = false;
+
+ if (this->skelAnime.playSpeed < 0.5f) {
+ hasSlowPlaybackSpeed = true;
+ }
+ if (hasSlowPlaybackSpeed && (this->animFlagAndTimer != 0)) {
+ this->animFlagAndTimer--;
+ }
+ if (Animation_OnFrame(&this->skelAnime, 9.0f)) {
+ this->collider.base.acFlags |= AC_ON;
+ } else if (Animation_OnFrame(&this->skelAnime, 8.0f)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_UP);
+ }
+
+ this->collider.dim.height = ((CLAMP(this->skelAnime.curFrame, 9.0f, 12.0f) - 9.0f) * 9.0f) + 5.0f;
+ if (!hasSlowPlaybackSpeed && (this->actor.xzDistToPlayer < 120.0f)) {
+ EnDekunuts_SetupBurrow(this);
+ } else if (SkelAnime_Update(&this->skelAnime)) {
+ if (this->actor.xzDistToPlayer < 120.0f) {
+ EnDekunuts_SetupBurrow(this);
+ } else if ((this->animFlagAndTimer == 0) && (this->actor.xzDistToPlayer > 320.0f)) {
+ EnDekunuts_SetupLookAround(this);
+ } else {
+ EnDekunuts_SetupStand(this);
+ }
+ }
+ if (hasSlowPlaybackSpeed &&
+ ((this->actor.xzDistToPlayer > 160.0f) && (fabsf(this->actor.yDistToPlayer) < 120.0f)) &&
+ ((this->animFlagAndTimer == 0) || (this->actor.xzDistToPlayer < 480.0f))) {
+ this->skelAnime.playSpeed = 1.0f;
+ }
+}
+
+void EnDekunuts_LookAround(EnDekunuts* this, GlobalContext* globalCtx) {
+ SkelAnime_Update(&this->skelAnime);
+ if (Animation_OnFrame(&this->skelAnime, 0.0f) && (this->animFlagAndTimer != 0)) {
+ this->animFlagAndTimer--;
+ }
+ if ((this->actor.xzDistToPlayer < 120.0f) || (this->animFlagAndTimer == 0)) {
+ EnDekunuts_SetupBurrow(this);
+ }
+}
+
+void EnDekunuts_Stand(EnDekunuts* this, GlobalContext* globalCtx) {
+ SkelAnime_Update(&this->skelAnime);
+ if (Animation_OnFrame(&this->skelAnime, 0.0f) && (this->animFlagAndTimer != 0)) {
+ this->animFlagAndTimer--;
+ }
+ if (!(this->animFlagAndTimer & 0x1000)) {
+ Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0xE38);
+ }
+ if (this->animFlagAndTimer == 0x1000) {
+ if ((this->actor.xzDistToPlayer > 480.0f) || (this->actor.xzDistToPlayer < 120.0f)) {
+ EnDekunuts_SetupBurrow(this);
+ } else {
+ EnDekunuts_SetupThrowNut(this);
+ }
+ } else if (this->animFlagAndTimer == 0) {
+ EnDekunuts_SetupThrowNut(this);
+ }
+}
+
+void EnDekunuts_ThrowNut(EnDekunuts* this, GlobalContext* globalCtx) {
+ Vec3f spawnPos;
+
+ Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0xE38);
+ if (SkelAnime_Update(&this->skelAnime)) {
+ EnDekunuts_SetupStand(this);
+ } else if (Animation_OnFrame(&this->skelAnime, 6.0f)) {
+ spawnPos.x = this->actor.world.pos.x + (Math_SinS(this->actor.shape.rot.y) * 23.0f);
+ spawnPos.y = this->actor.world.pos.y + 12.0f;
+ spawnPos.z = this->actor.world.pos.z + (Math_CosS(this->actor.shape.rot.y) * 23.0f);
+ if (Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_EN_NUTSBALL, spawnPos.x, spawnPos.y, spawnPos.z,
+ this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, 0) != NULL) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_THROW);
+ }
+ } else if ((this->animFlagAndTimer > 1) && Animation_OnFrame(&this->skelAnime, 12.0f)) {
+ Animation_MorphToPlayOnce(&this->skelAnime, &gDekuNutsSpitAnim, -3.0f);
+ if (this->animFlagAndTimer != 0) {
+ this->animFlagAndTimer--;
+ }
+ }
+}
+
+void EnDekunuts_Burrow(EnDekunuts* this, GlobalContext* globalCtx) {
+ if (SkelAnime_Update(&this->skelAnime)) {
+ EnDekunuts_SetupWait(this);
+ } else {
+ this->collider.dim.height = ((3.0f - CLAMP(this->skelAnime.curFrame, 1.0f, 3.0f)) * 12.0f) + 5.0f;
+ }
+ if (Animation_OnFrame(&this->skelAnime, 4.0f)) {
+ this->collider.base.acFlags &= ~AC_ON;
+ }
+ Math_ApproachF(&this->actor.world.pos.x, this->actor.home.pos.x, 0.5f, 3.0f);
+ Math_ApproachF(&this->actor.world.pos.z, this->actor.home.pos.z, 0.5f, 3.0f);
+}
+
+void EnDekunuts_BeginRun(EnDekunuts* this, GlobalContext* globalCtx) {
+ if (SkelAnime_Update(&this->skelAnime)) {
+ this->runDirection = this->actor.yawTowardsPlayer + 0x8000;
+ this->runAwayCount = 3;
+ EnDekunuts_SetupRun(this);
+ }
+ Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 2, 0xE38);
+}
+
+void EnDekunuts_Run(EnDekunuts* this, GlobalContext* globalCtx) {
+ s16 diffRotInit;
+ s16 diffRot;
+ f32 phi_f0;
+
+ SkelAnime_Update(&this->skelAnime);
+ if (Animation_OnFrame(&this->skelAnime, 0.0f) && (this->animFlagAndTimer != 0)) {
+ this->animFlagAndTimer--;
+ }
+ if (this->playWalkSound) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_WALK);
+ this->playWalkSound = false;
+ } else {
+ this->playWalkSound = true;
+ }
+
+ Math_StepToF(&this->actor.speedXZ, 7.5f, 1.0f);
+ if (Math_SmoothStepToS(&this->actor.world.rot.y, this->runDirection, 1, 0xE38, 0xB6) == 0) {
+ if (this->actor.bgCheckFlags & 0x20) {
+ this->runDirection = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos);
+ } else if (this->actor.bgCheckFlags & 8) {
+ this->runDirection = this->actor.wallYaw;
+ } else if (this->runAwayCount == 0) {
+ diffRotInit = Actor_WorldYawTowardPoint(&this->actor, &this->actor.home.pos);
+ diffRot = diffRotInit - this->actor.yawTowardsPlayer;
+ if (ABS(diffRot) > 0x2000) {
+ this->runDirection = diffRotInit;
+ } else {
+ phi_f0 = (diffRot >= 0.0f) ? 1.0f : -1.0f;
+ this->runDirection = (phi_f0 * -0x2000) + this->actor.yawTowardsPlayer;
+ }
+ } else {
+ this->runDirection = this->actor.yawTowardsPlayer + 0x8000;
+ }
+ }
+
+ this->actor.shape.rot.y = this->actor.world.rot.y + 0x8000;
+ if ((this->runAwayCount == 0) && Actor_WorldDistXZToPoint(&this->actor, &this->actor.home.pos) < 20.0f &&
+ fabsf(this->actor.world.pos.y - this->actor.home.pos.y) < 2.0f) {
+ this->actor.colChkInfo.mass = MASS_IMMOVABLE;
+ this->actor.speedXZ = 0.0f;
+ EnDekunuts_SetupBurrow(this);
+ } else if (this->animFlagAndTimer == 0) {
+ EnDekunuts_SetupGasp(this);
+ }
+}
+
+void EnDekunuts_Gasp(EnDekunuts* this, GlobalContext* globalCtx) {
+ SkelAnime_Update(&this->skelAnime);
+ if (Animation_OnFrame(&this->skelAnime, 0.0f) && (this->animFlagAndTimer != 0)) {
+ this->animFlagAndTimer--;
+ }
+ if (this->animFlagAndTimer == 0) {
+ EnDekunuts_SetupRun(this);
+ }
+}
+
+void EnDekunuts_BeDamaged(EnDekunuts* this, GlobalContext* globalCtx) {
+ Math_StepToF(&this->actor.speedXZ, 0.0f, 1.0f);
+ if (SkelAnime_Update(&this->skelAnime)) {
+ EnDekunuts_SetupDie(this);
+ }
+}
+
+void EnDekunuts_BeStunned(EnDekunuts* this, GlobalContext* globalCtx) {
+ SkelAnime_Update(&this->skelAnime);
+ if (Animation_OnFrame(&this->skelAnime, 0.0f)) {
+ if (this->animFlagAndTimer != 0) {
+ this->animFlagAndTimer--;
+ }
+ if (this->animFlagAndTimer == 0) {
+ EnDekunuts_SetupRun(this);
+ } else {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_NUTS_FAINT);
+ }
+ }
+}
+
+void EnDekunuts_Die(EnDekunuts* this, GlobalContext* globalCtx) {
+ static Vec3f effectVelAndAccel = { 0.0f, 0.0f, 0.0f };
+
+ s32 pad;
+ Vec3f effectPos;
+
+ if (SkelAnime_Update(&this->skelAnime)) {
+ effectPos.x = this->actor.world.pos.x;
+ effectPos.y = this->actor.world.pos.y + 18.0f;
+ effectPos.z = this->actor.world.pos.z;
+ EffectSsDeadDb_Spawn(globalCtx, &effectPos, &effectVelAndAccel, &effectVelAndAccel, 200, 0, 255, 255, 255, 255,
+ 150, 150, 150, 1, 13, 1);
+ effectPos.y = this->actor.world.pos.y + 10.0f;
+ EffectSsHahen_SpawnBurst(globalCtx, &effectPos, 3.0f, 0, 12, 3, 15, HAHEN_OBJECT_DEFAULT, 10, NULL);
+ Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 0x30);
+ if (this->actor.child != NULL) {
+ Actor_ChangeCategory(globalCtx, &globalCtx->actorCtx, this->actor.child, ACTORCAT_PROP);
+ }
+ Actor_Kill(&this->actor);
+ }
+}
+
+void EnDekunuts_ColliderCheck(EnDekunuts* this, GlobalContext* globalCtx) {
+ if (this->collider.base.acFlags & AC_HIT) {
+ this->collider.base.acFlags &= ~AC_HIT;
+ func_80035650(&this->actor, &this->collider.info, 1);
+ if (this->actor.colChkInfo.mass == 0x32) {
+ if ((this->actor.colChkInfo.damageEffect != 0) || (this->actor.colChkInfo.damage != 0)) {
+ if (this->actor.colChkInfo.damageEffect != 1) {
+ if (this->actor.colChkInfo.damageEffect == 2) {
+ EffectSsFCircle_Spawn(globalCtx, &this->actor, &this->actor.world.pos, 40, 50);
+ }
+ EnDekunuts_SetupBeDamaged(this);
+ if (Actor_ApplyDamage(&this->actor) == 0) {
+ func_80032C7C(globalCtx, &this->actor);
+ }
+ } else if (this->actionFunc != EnDekunuts_BeStunned) {
+ EnDekunuts_SetupBeStunned(this);
+ }
+ }
+ } else {
+ EnDekunuts_SetupBeginRun(this);
+ }
+ } else if ((this->actor.colChkInfo.mass == MASS_IMMOVABLE) && (globalCtx->actorCtx.unk_02 != 0)) {
+ EnDekunuts_SetupBeginRun(this);
+ }
+}
+
+void EnDekunuts_Update(Actor* thisx, GlobalContext* globalCtx) {
+ EnDekunuts* this = THIS;
+ s32 pad;
+
+ if (this->actor.params != DEKUNUTS_FLOWER) {
+ EnDekunuts_ColliderCheck(this, globalCtx);
+ this->actionFunc(this, globalCtx);
+ Actor_MoveForward(&this->actor);
+ Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, this->collider.dim.radius, this->collider.dim.height,
+ 0x1D);
+ Collider_UpdateCylinder(&this->actor, &this->collider);
+ if (this->collider.base.acFlags & AC_ON) {
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
+ }
+ CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
+ if (this->actionFunc == EnDekunuts_Wait) {
+ Actor_SetFocus(&this->actor, this->skelAnime.curFrame);
+ } else if (this->actionFunc == EnDekunuts_Burrow) {
+ Actor_SetFocus(&this->actor,
+ 20.0f - ((this->skelAnime.curFrame * 20.0f) / Animation_GetLastFrame(&gDekuNutsBurrowAnim)));
+ } else {
+ Actor_SetFocus(&this->actor, 20.0f);
+ }
+ }
+}
+
+s32 EnDekunuts_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
+ void* thisx) {
+ EnDekunuts* this = THIS;
+ f32 x;
+ f32 y;
+ f32 z;
+ f32 curFrame;
+
+ if ((limbIndex == 7) && (this->actionFunc == EnDekunuts_ThrowNut)) {
+ curFrame = this->skelAnime.curFrame;
+ if (curFrame <= 6.0f) {
+ x = 1.0f - (curFrame * 0.0833f);
+ z = 1.0f + (curFrame * 0.1167f);
+ y = 1.0f + (curFrame * 0.1167f);
+ } else if (curFrame <= 7.0f) {
+ curFrame -= 6.0f;
+ x = 0.5f + curFrame;
+ z = 1.7f - (curFrame * 0.7f);
+ y = 1.7f - (curFrame * 0.7f);
+ } else if (curFrame <= 10.0f) {
+ x = 1.5f - ((curFrame - 7.0f) * 0.1667f);
+ z = 1.0f;
+ y = 1.0f;
+ } else {
+ return false;
+ }
+ Matrix_Scale(x, y, z, MTXMODE_APPLY);
+ }
+ return false;
+}
+
+void EnDekunuts_Draw(Actor* thisx, GlobalContext* globalCtx) {
+ EnDekunuts* this = THIS;
+
+ if (this->actor.params == DEKUNUTS_FLOWER) {
+ Gfx_DrawDListOpa(globalCtx, gDekuNutsFlowerDL);
+ } else {
+ SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, EnDekunuts_OverrideLimbDraw,
+ NULL, this);
+ }
+}
diff --git a/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.h b/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.h
index 18a221aa1..3a43fc167 100644
--- a/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.h
+++ b/src/overlays/actors/ovl_En_Dekunuts/z_en_dekunuts.h
@@ -6,9 +6,20 @@
struct EnDekunuts;
+typedef void (*EnDekunutsActionFunc)(struct EnDekunuts*, GlobalContext*);
+
typedef struct EnDekunuts {
/* 0x0000 */ Actor actor;
- /* 0x014C */ char unk_14C[0x1C8];
+ /* 0x014C */ SkelAnime skelAnime;
+ /* 0x0190 */ EnDekunutsActionFunc actionFunc;
+ /* 0x0194 */ u8 playWalkSound;
+ /* 0x0195 */ u8 runAwayCount;
+ /* 0x0196 */ s16 animFlagAndTimer;
+ /* 0x0198 */ s16 runDirection;
+ /* 0x019A */ s16 shotsPerRound;
+ /* 0x019C */ Vec3s jointTable[25];
+ /* 0x0232 */ Vec3s morphTable[25];
+ /* 0x02C8 */ ColliderCylinder collider;
} EnDekunuts; // size = 0x0314
extern const ActorInit En_Dekunuts_InitVars;