From 85a4d23fc66a040d26d1befced6e99b384246bb0 Mon Sep 17 00:00:00 2001 From: Parker Burnett Date: Thu, 8 Dec 2022 10:57:17 -0800 Subject: [PATCH] Documentation For En_Ik (#1190) * pushing up to save changes * syncing up some more docs * finishing what I can * PR feedback * fixing typo * Addressing comments * master merge * naming object * ummm committing this for now before catching up * other review + my review * more review * review2 Co-authored-by: fig02 --- assets/xml/objects/object_ik.xml | 79 +- src/overlays/actors/ovl_Demo_Ik/z_demo_ik.c | 4 +- src/overlays/actors/ovl_En_Ik/z_en_ik.c | 1164 ++++++++++--------- src/overlays/actors/ovl_En_Ik/z_en_ik.h | 103 +- 4 files changed, 767 insertions(+), 583 deletions(-) diff --git a/assets/xml/objects/object_ik.xml b/assets/xml/objects/object_ik.xml index 95606e6df7..5d86e1075a 100644 --- a/assets/xml/objects/object_ik.xml +++ b/assets/xml/objects/object_ik.xml @@ -1,7 +1,5 @@  - - @@ -10,62 +8,62 @@ - - + + - - - - - - - - - - - - + + + + + + + + + + + + - + - + - - - - + + + + - - - - + + + + - + - - - + + + - - - + + + @@ -75,14 +73,14 @@ - + - - - - + + + + @@ -97,8 +95,7 @@ - - - + + diff --git a/src/overlays/actors/ovl_Demo_Ik/z_demo_ik.c b/src/overlays/actors/ovl_Demo_Ik/z_demo_ik.c index 9277af4282..65371f306b 100644 --- a/src/overlays/actors/ovl_Demo_Ik/z_demo_ik.c +++ b/src/overlays/actors/ovl_Demo_Ik/z_demo_ik.c @@ -265,7 +265,7 @@ void DemoIk_Type1PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s case 0: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_demo_ik_inArmer.c", 390), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016BE0); + gSPDisplayList(POLY_XLU_DISP++, gIronKnuckleArmorRivetAndSymbolDL); break; case 2: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_demo_ik_inArmer.c", 396), @@ -432,7 +432,7 @@ void DemoIk_Type2PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s case 5: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_demo_ik_inFace.c", 286), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016BE0); + gSPDisplayList(POLY_XLU_DISP++, gIronKnuckleArmorRivetAndSymbolDL); break; default: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_demo_ik_inFace.c", 292), diff --git a/src/overlays/actors/ovl_En_Ik/z_en_ik.c b/src/overlays/actors/ovl_En_Ik/z_en_ik.c index 36bf288296..0b7863806c 100644 --- a/src/overlays/actors/ovl_En_Ik/z_en_ik.c +++ b/src/overlays/actors/ovl_En_Ik/z_en_ik.c @@ -13,44 +13,57 @@ typedef void (*EnIkDrawFunc)(struct EnIk*, PlayState*); -void EnIk_Init(Actor* thisx, PlayState* play); -void EnIk_Destroy(Actor* thisx, PlayState* play); -void EnIk_Update(Actor* thisx, PlayState* play); -void EnIk_Draw(Actor* thisx, PlayState* play); +#define ARMOR_BROKEN (1 << 0) -void func_80A74714(EnIk* this); -void func_80A747C0(EnIk* this, PlayState* play); -void func_80A7492C(EnIk* this, PlayState* play); -void func_80A74AAC(EnIk* this); -void func_80A74BA4(EnIk* this, PlayState* play); -void func_80A74E2C(EnIk* this); -void func_80A74EBC(EnIk* this, PlayState* play); -void func_80A7506C(EnIk* this); -void func_80A7510C(EnIk* this, PlayState* play); -void func_80A751C8(EnIk* this); -void func_80A75260(EnIk* this, PlayState* play); -void func_80A753D0(EnIk* this); -void func_80A7545C(EnIk* this, PlayState* play); -void func_80A754A0(EnIk* this); -void func_80A75530(EnIk* this, PlayState* play); -void func_80A755F0(EnIk* this); -void func_80A7567C(EnIk* this, PlayState* play); -void func_80A758B0(EnIk* this, PlayState* play); -void func_80A75A38(EnIk* this, PlayState* play); -void func_80A75FA0(Actor* thisx, PlayState* play); -void func_80A76798(Actor* thisx, PlayState* play); -void func_80A7748C(EnIk* this, PlayState* play); -void func_80A774BC(EnIk* this, PlayState* play); -void func_80A774F8(EnIk* this, PlayState* play); -void func_80A77844(EnIk* this, PlayState* play); -void func_80A779DC(EnIk* this, PlayState* play); -void func_80A77AEC(EnIk* this, PlayState* play); -void func_80A77B0C(EnIk* this, PlayState* play); -void func_80A77B3C(EnIk* this, PlayState* play); -void func_80A77ED0(EnIk* this, PlayState* play); -void func_80A77EDC(EnIk* this, PlayState* play); -void func_80A78160(EnIk* this, PlayState* play); -void func_80A781CC(Actor* thisx, PlayState* play); +typedef enum { + /* 0x00 */ IK_CS_ACTION_0, + /* 0x01 */ IK_CS_ACTION_1, + /* 0x02 */ IK_CS_ACTION_2, + /* 0x03 */ IK_CS_ACTION_3, + /* 0x04 */ IK_CS_ACTION_4, + /* 0x05 */ IK_CS_ACTION_5 +} EnIkCsAction; + +typedef enum { + /* 0x00 */ IK_CS_DRAW_NOTHING, + /* 0x01 */ IK_CS_DRAW_INTRO, + /* 0x02 */ IK_CS_DRAW_DEFEAT +} EnIkCsDrawMode; + +typedef enum { + /* 0x0 */ EN_IK_DMGEFF_NONE, + /* 0x6 */ EN_IK_DMGEFF_ELEMENTAL_MAGIC = 0x6, + /* 0xD */ EN_IK_DMGEFF_SPARKS_NO_DMG = 0xD, + /* 0xE */ EN_IK_DMGEFF_PROJECTILE, + /* 0xF */ EN_IK_DMGEFF_DAMAGE +} EnIkDamageEffect; + +void EnIk_UpdateEnemy(Actor* thisx, PlayState* play); +void EnIk_DrawEnemy(Actor* thisx, PlayState* play); + +void EnIk_SetupStandUp(EnIk* this); +void EnIk_StandUp(EnIk* this, PlayState* play); +void EnIk_Idle(EnIk* this, PlayState* play); +void EnIk_SetupWalkOrRun(EnIk* this); +void EnIk_WalkOrRun(EnIk* this, PlayState* play); +void EnIk_SetupVerticalAttack(EnIk* this); +void EnIk_VerticalAttack(EnIk* this, PlayState* play); +void EnIk_SetupPullOutAxe(EnIk* this); +void EnIk_PullOutAxe(EnIk* this, PlayState* play); +void EnIk_SetupDoubleHorizontalAttack(EnIk* this); +void EnIk_DoubleHorizontalAttack(EnIk* this, PlayState* play); +void EnIk_SetupRecoverFromHorizontalAttack(EnIk* this); +void EnIk_RecoverFromHorizontalAttack(EnIk* this, PlayState* play); +void EnIk_SetupSingleHorizontalAttack(EnIk* this); +void EnIk_SingleHorizontalAttack(EnIk* this, PlayState* play); +void EnIk_SetupStopAndBlock(EnIk* this); +void EnIk_StopAndBlock(EnIk* this, PlayState* play); +void EnIk_ReactToAttack(EnIk* this, PlayState* play); +void EnIk_Die(EnIk* this, PlayState* play); + +void EnIk_HandleCsCues(EnIk* this, PlayState* play); +void EnIk_ChangeToEnemy(EnIk* this, PlayState* play); +void EnIk_StartDefeatCutscene(Actor* thisx, PlayState* play); static ColliderCylinderInit sCylinderInit = { { @@ -131,38 +144,38 @@ static ColliderQuadInit sQuadInit = { }; static DamageTable sDamageTable = { - /* Deku nut */ DMG_ENTRY(0, 0xD), - /* Deku stick */ DMG_ENTRY(2, 0xF), - /* Slingshot */ DMG_ENTRY(1, 0xE), - /* Explosive */ DMG_ENTRY(2, 0xF), - /* Boomerang */ DMG_ENTRY(0, 0xD), - /* Normal arrow */ DMG_ENTRY(2, 0xE), - /* Hammer swing */ DMG_ENTRY(2, 0xF), - /* Hookshot */ DMG_ENTRY(0, 0xD), - /* Kokiri sword */ DMG_ENTRY(1, 0xF), - /* Master sword */ DMG_ENTRY(2, 0xF), - /* Giant's Knife */ DMG_ENTRY(4, 0xF), - /* Fire arrow */ DMG_ENTRY(2, 0xE), - /* Ice arrow */ DMG_ENTRY(2, 0xE), - /* Light arrow */ DMG_ENTRY(2, 0xE), - /* Unk arrow 1 */ DMG_ENTRY(2, 0xE), - /* Unk arrow 2 */ DMG_ENTRY(2, 0xE), - /* Unk arrow 3 */ DMG_ENTRY(15, 0xE), - /* Fire magic */ DMG_ENTRY(0, 0x6), - /* Ice magic */ DMG_ENTRY(0, 0x6), - /* Light magic */ DMG_ENTRY(0, 0x6), - /* Shield */ DMG_ENTRY(0, 0x0), - /* Mirror Ray */ DMG_ENTRY(0, 0x0), - /* Kokiri spin */ DMG_ENTRY(1, 0xF), - /* Giant spin */ DMG_ENTRY(4, 0xF), - /* Master spin */ DMG_ENTRY(2, 0xF), - /* Kokiri jump */ DMG_ENTRY(2, 0xF), - /* Giant jump */ DMG_ENTRY(8, 0xF), - /* Master jump */ DMG_ENTRY(4, 0xF), - /* Unknown 1 */ DMG_ENTRY(10, 0xF), - /* Unblockable */ DMG_ENTRY(0, 0x0), - /* Hammer jump */ DMG_ENTRY(4, 0xF), - /* Unknown 2 */ DMG_ENTRY(0, 0x0), + /* Deku nut */ DMG_ENTRY(0, EN_IK_DMGEFF_SPARKS_NO_DMG), + /* Deku stick */ DMG_ENTRY(2, EN_IK_DMGEFF_DAMAGE), + /* Slingshot */ DMG_ENTRY(1, EN_IK_DMGEFF_PROJECTILE), + /* Explosive */ DMG_ENTRY(2, EN_IK_DMGEFF_DAMAGE), + /* Boomerang */ DMG_ENTRY(0, EN_IK_DMGEFF_SPARKS_NO_DMG), + /* Normal arrow */ DMG_ENTRY(2, EN_IK_DMGEFF_PROJECTILE), + /* Hammer swing */ DMG_ENTRY(2, EN_IK_DMGEFF_DAMAGE), + /* Hookshot */ DMG_ENTRY(0, EN_IK_DMGEFF_SPARKS_NO_DMG), + /* Kokiri sword */ DMG_ENTRY(1, EN_IK_DMGEFF_DAMAGE), + /* Master sword */ DMG_ENTRY(2, EN_IK_DMGEFF_DAMAGE), + /* Giant's Knife */ DMG_ENTRY(4, EN_IK_DMGEFF_DAMAGE), + /* Fire arrow */ DMG_ENTRY(2, EN_IK_DMGEFF_PROJECTILE), + /* Ice arrow */ DMG_ENTRY(2, EN_IK_DMGEFF_PROJECTILE), + /* Light arrow */ DMG_ENTRY(2, EN_IK_DMGEFF_PROJECTILE), + /* Unk arrow 1 */ DMG_ENTRY(2, EN_IK_DMGEFF_PROJECTILE), + /* Unk arrow 2 */ DMG_ENTRY(2, EN_IK_DMGEFF_PROJECTILE), + /* Unk arrow 3 */ DMG_ENTRY(15, EN_IK_DMGEFF_PROJECTILE), + /* Fire magic */ DMG_ENTRY(0, EN_IK_DMGEFF_ELEMENTAL_MAGIC), + /* Ice magic */ DMG_ENTRY(0, EN_IK_DMGEFF_ELEMENTAL_MAGIC), + /* Light magic */ DMG_ENTRY(0, EN_IK_DMGEFF_ELEMENTAL_MAGIC), + /* Shield */ DMG_ENTRY(0, EN_IK_DMGEFF_NONE), + /* Mirror Ray */ DMG_ENTRY(0, EN_IK_DMGEFF_NONE), + /* Kokiri spin */ DMG_ENTRY(1, EN_IK_DMGEFF_DAMAGE), + /* Giant spin */ DMG_ENTRY(4, EN_IK_DMGEFF_DAMAGE), + /* Master spin */ DMG_ENTRY(2, EN_IK_DMGEFF_DAMAGE), + /* Kokiri jump */ DMG_ENTRY(2, EN_IK_DMGEFF_DAMAGE), + /* Giant jump */ DMG_ENTRY(8, EN_IK_DMGEFF_DAMAGE), + /* Master jump */ DMG_ENTRY(4, EN_IK_DMGEFF_DAMAGE), + /* Unknown 1 */ DMG_ENTRY(10, EN_IK_DMGEFF_DAMAGE), + /* Unblockable */ DMG_ENTRY(0, EN_IK_DMGEFF_NONE), + /* Hammer jump */ DMG_ENTRY(4, EN_IK_DMGEFF_DAMAGE), + /* Unknown 2 */ DMG_ENTRY(0, EN_IK_DMGEFF_NONE), }; void EnIk_Destroy(Actor* thisx, PlayState* play) { @@ -181,13 +194,13 @@ void EnIk_SetupAction(EnIk* this, EnIkActionFunc actionFunc) { this->actionFunc = actionFunc; } -void func_80A74398(Actor* thisx, PlayState* play) { +void EnIk_InitImpl(Actor* thisx, PlayState* play) { EnIk* this = (EnIk*)thisx; s32 pad; EffectBlureInit1 blureInit; - thisx->update = func_80A75FA0; - thisx->draw = func_80A76798; + thisx->update = EnIk_UpdateEnemy; + thisx->draw = EnIk_DrawEnemy; thisx->flags |= ACTOR_FLAG_10; Collider_InitCylinder(play, &this->bodyCollider); @@ -199,13 +212,13 @@ void func_80A74398(Actor* thisx, PlayState* play) { thisx->colChkInfo.damageTable = &sDamageTable; thisx->colChkInfo.mass = MASS_HEAVY; - this->unk_2FC = 0; + this->isBreakingProp = false; thisx->colChkInfo.health = 30; thisx->gravity = -1.0f; - this->switchFlags = (thisx->params >> 8) & 0xFF; - thisx->params &= 0xFF; + this->switchFlag = IK_GET_SWITCH_FLAG(thisx); + thisx->params = IK_GET_ARMOR_TYPE(thisx); - if (thisx->params == 0) { + if (thisx->params == IK_TYPE_NABOORU) { thisx->colChkInfo.health += 20; thisx->naviEnemyId = NAVI_ENEMY_IRON_KNUCKLE_NABOORU; } else { @@ -228,10 +241,10 @@ void func_80A74398(Actor* thisx, PlayState* play) { blureInit.calcMode = 2; Effect_Add(play, &this->blureIdx, EFFECT_BLURE1, 0, 0, &blureInit); - func_80A74714(this); + EnIk_SetupStandUp(this); - if (this->switchFlags != 0xFF) { - if (Flags_GetSwitch(play, this->switchFlags)) { + if (this->switchFlag != 0xFF) { + if (Flags_GetSwitch(play, this->switchFlag)) { Actor_Kill(thisx); } } else if (thisx->params != 0 && Flags_GetClear(play, play->roomCtx.curRoom.num)) { @@ -239,18 +252,18 @@ void func_80A74398(Actor* thisx, PlayState* play) { } } -s32 func_80A745E4(EnIk* this, PlayState* play) { - if (((this->unk_2FB != 0) || (this->actor.params == 0)) && +s32 EnIk_HandleBlocking(EnIk* this, PlayState* play) { + if (((this->armorStatusFlag != 0) || (this->actor.params == IK_TYPE_NABOORU)) && (func_800354B4(play, &this->actor, 100.0f, 0x2710, 0x4000, this->actor.shape.rot.y) != 0) && (play->gameplayFrames & 1)) { - func_80A755F0(this); + EnIk_SetupStopAndBlock(this); return true; } else { return false; } } -Actor* func_80A74674(PlayState* play, Actor* actor) { +Actor* EnIk_FindBreakableProp(PlayState* play, Actor* actor) { Actor* prop = play->actorCtx.actorLists[ACTORCAT_PROP].head; while (prop != NULL) { @@ -267,175 +280,190 @@ Actor* func_80A74674(PlayState* play, Actor* actor) { return NULL; } -void func_80A74714(EnIk* this) { - f32 frames = Animation_GetLastFrame(&object_ik_Anim_00CD70); - f32 frame; +void EnIk_SetupStandUp(EnIk* this) { + f32 endFrame = Animation_GetLastFrame(&gIronKnuckleStandUpAnim); + f32 startFrame; - if (this->actor.params >= 2) { - frame = frames - 1.0f; + if (this->actor.params >= IK_TYPE_BLACK) { + startFrame = endFrame - 1.0f; } else { - frame = 0.0f; + startFrame = 0.0f; } - Animation_Change(&this->skelAnime, &object_ik_Anim_00CD70, 0.0f, frame, frames, ANIMMODE_ONCE, 0.0f); + Animation_Change(&this->skelAnime, &gIronKnuckleStandUpAnim, 0.0f, startFrame, endFrame, ANIMMODE_ONCE, 0.0f); this->unk_2F8 = 3; this->actor.speedXZ = 0.0f; - EnIk_SetupAction(this, func_80A747C0); + EnIk_SetupAction(this, EnIk_StandUp); } -void func_80A747C0(EnIk* this, PlayState* play) { - Vec3f sp24; +void EnIk_StandUp(EnIk* this, PlayState* play) { + Vec3f sparksPos; if (this->bodyCollider.base.acFlags & AC_HIT) { - sp24 = this->actor.world.pos; + sparksPos = this->actor.world.pos; Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_ARMOR_HIT); - sp24.y += 30.0f; - func_8003424C(play, &sp24); + sparksPos.y += 30.0f; + func_8003424C(play, &sparksPos); this->skelAnime.playSpeed = 1.0f; func_800F5ACC(NA_BGM_MINI_BOSS); } + if (this->skelAnime.curFrame == 5.0f) { Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_WAKEUP); } + if (SkelAnime_Update(&this->skelAnime)) { this->actor.flags |= ACTOR_FLAG_0 | ACTOR_FLAG_2; - func_80A74AAC(this); + EnIk_SetupWalkOrRun(this); } } -void func_80A7489C(EnIk* this) { - f32 frames = Animation_GetLastFrame(&object_ik_Anim_00DD50); +void EnIk_SetupIdle(EnIk* this) { + f32 endFrame = Animation_GetLastFrame(&object_ik_Anim_00DD50); this->actor.flags |= ACTOR_FLAG_0 | ACTOR_FLAG_2; this->unk_2F8 = 4; this->actor.speedXZ = 0.0f; - Animation_Change(&this->skelAnime, &object_ik_Anim_00DD50, 0.0f, 0.0f, frames, ANIMMODE_LOOP, 4.0f); - EnIk_SetupAction(this, func_80A7492C); + Animation_Change(&this->skelAnime, &object_ik_Anim_00DD50, 0.0f, 0.0f, endFrame, ANIMMODE_LOOP, 4.0f); + EnIk_SetupAction(this, EnIk_Idle); } -void func_80A7492C(EnIk* this, PlayState* play) { - s32 phi_a0 = (this->unk_2FB == 0) ? 0xAAA : 0x3FFC; +void EnIk_Idle(EnIk* this, PlayState* play) { + s32 detectionThreshold = (this->armorStatusFlag == 0) ? 0xAAA : 0x3FFC; s16 yawDiff = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; - if ((ABS(yawDiff) <= phi_a0) && (this->actor.xzDistToPlayer < 100.0f) && + if ((ABS(yawDiff) <= detectionThreshold) && (this->actor.xzDistToPlayer < 100.0f) && (ABS(this->actor.yDistToPlayer) < 150.0f)) { if ((play->gameplayFrames & 1)) { - func_80A74E2C(this); + EnIk_SetupVerticalAttack(this); } else { - func_80A751C8(this); + EnIk_SetupDoubleHorizontalAttack(this); } } else if ((ABS(yawDiff) <= 0x4000) && (ABS(this->actor.yDistToPlayer) < 150.0f)) { - func_80A74AAC(this); + EnIk_SetupWalkOrRun(this); } else { - func_80A74AAC(this); + EnIk_SetupWalkOrRun(this); } - func_80A745E4(this, play); + + EnIk_HandleBlocking(this, play); SkelAnime_Update(&this->skelAnime); } -void func_80A74AAC(EnIk* this) { +void EnIk_SetupWalkOrRun(EnIk* this) { this->unk_2F8 = 5; - if (this->unk_2FB == 0) { - Animation_Change(&this->skelAnime, &object_ik_Anim_00ED24, 1.0f, 0.0f, - Animation_GetLastFrame(&object_ik_Anim_00ED24), ANIMMODE_LOOP, -4.0f); + + if (this->armorStatusFlag == 0) { + Animation_Change(&this->skelAnime, &gIronKnuckleWalkAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gIronKnuckleWalkAnim), ANIMMODE_LOOP, -4.0f); this->actor.speedXZ = 0.9f; } else { - Animation_Change(&this->skelAnime, &object_ik_Anim_006734, 1.0f, 0.0f, - Animation_GetLastFrame(&object_ik_Anim_006734), ANIMMODE_LOOP, -4.0f); + Animation_Change(&this->skelAnime, &gIronKnuckleRunAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gIronKnuckleRunAnim), ANIMMODE_LOOP, -4.0f); Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_DASH); this->actor.speedXZ = 2.5f; } + this->actor.world.rot.y = this->actor.shape.rot.y; - EnIk_SetupAction(this, func_80A74BA4); + EnIk_SetupAction(this, EnIk_WalkOrRun); } -void func_80A74BA4(EnIk* this, PlayState* play) { +void EnIk_WalkOrRun(EnIk* this, PlayState* play) { s16 temp_t0; - s16 temp_a1; + s16 targetYaw; s16 yawDiff; - s16 sp30; - s16 sp2E; - s16 phi_a3; + s16 footstepFrame1; + s16 footstepFrame2; + s16 stepVal; - if (this->unk_2FB == 0) { + if (this->armorStatusFlag == 0) { temp_t0 = 0xAAA; - phi_a3 = 0x320; - sp30 = 0; - sp2E = 0x10; + stepVal = 0x320; + footstepFrame1 = 0; + footstepFrame2 = 16; } else { temp_t0 = 0x3FFC; - phi_a3 = 0x4B0; - sp30 = 2; - sp2E = 9; + stepVal = 0x4B0; + footstepFrame1 = 2; + footstepFrame2 = 9; } - temp_a1 = this->actor.wallYaw - this->actor.shape.rot.y; - if ((this->actor.bgCheckFlags & BGCHECKFLAG_WALL) && (ABS(temp_a1) >= 0x4000)) { - temp_a1 = (this->actor.yawTowardsPlayer > 0) ? this->actor.wallYaw - 0x4000 : this->actor.wallYaw + 0x4000; - Math_SmoothStepToS(&this->actor.world.rot.y, temp_a1, 1, phi_a3, 0); + + targetYaw = this->actor.wallYaw - this->actor.shape.rot.y; + + if ((this->actor.bgCheckFlags & BGCHECKFLAG_WALL) && (ABS(targetYaw) >= 0x4000)) { + targetYaw = (this->actor.yawTowardsPlayer > 0) ? this->actor.wallYaw - 0x4000 : this->actor.wallYaw + 0x4000; + Math_SmoothStepToS(&this->actor.world.rot.y, targetYaw, 1, stepVal, 0); } else { - Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 1, phi_a3, 0); + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 1, stepVal, 0); } + this->actor.shape.rot.y = this->actor.world.rot.y; yawDiff = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; + if ((ABS(yawDiff) <= temp_t0) && (this->actor.xzDistToPlayer < 100.0f)) { if (ABS(this->actor.yDistToPlayer) < 150.0f) { - if ((play->gameplayFrames & 1)) { - func_80A74E2C(this); + if (play->gameplayFrames & 1) { + EnIk_SetupVerticalAttack(this); } else { - func_80A751C8(this); + EnIk_SetupDoubleHorizontalAttack(this); } } } - if (func_80A74674(play, &this->actor) != NULL) { - func_80A751C8(this); - this->unk_2FC = 1; + + if (EnIk_FindBreakableProp(play, &this->actor) != NULL) { + EnIk_SetupDoubleHorizontalAttack(this); + this->isBreakingProp = true; } else { temp_t0 = this->actor.yawTowardsPlayer - this->actor.shape.rot.y; + if (ABS(temp_t0) > 0x4000) { this->unk_300--; + if (this->unk_300 == 0) { - func_80A754A0(this); + EnIk_SetupSingleHorizontalAttack(this); } } else { - this->unk_300 = 0x28; + this->unk_300 = 40; } } - func_80A745E4(this, play); + + EnIk_HandleBlocking(this, play); SkelAnime_Update(&this->skelAnime); - if ((sp30 == (s16)this->skelAnime.curFrame) || (sp2E == (s16)this->skelAnime.curFrame)) { + + if (((s16)this->skelAnime.curFrame == footstepFrame1) || ((s16)this->skelAnime.curFrame == footstepFrame2)) { Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_WALK); } } -void func_80A74E2C(EnIk* this) { - f32 frames = Animation_GetLastFrame(&object_ik_Anim_001C28); +void EnIk_SetupVerticalAttack(EnIk* this) { + f32 endFrame = Animation_GetLastFrame(&gIronKnuckleVerticalAttackAnim); this->unk_2FF = 1; this->unk_2F8 = 6; this->actor.speedXZ = 0.0f; - Animation_Change(&this->skelAnime, &object_ik_Anim_001C28, 1.5f, 0.0f, frames, ANIMMODE_ONCE, -4.0f); - EnIk_SetupAction(this, func_80A74EBC); + Animation_Change(&this->skelAnime, &gIronKnuckleVerticalAttackAnim, 1.5f, 0.0f, endFrame, ANIMMODE_ONCE, -4.0f); + EnIk_SetupAction(this, EnIk_VerticalAttack); } -void func_80A74EBC(EnIk* this, PlayState* play) { - Vec3f sp2C; +void EnIk_VerticalAttack(EnIk* this, PlayState* play) { + Vec3f sparksPos; if (this->skelAnime.curFrame == 15.0f) { Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_SWING_AXE); } else if (this->skelAnime.curFrame == 21.0f) { - sp2C.x = this->actor.world.pos.x + Math_SinS(this->actor.shape.rot.y + 0x6A4) * 70.0f; - sp2C.z = this->actor.world.pos.z + Math_CosS(this->actor.shape.rot.y + 0x6A4) * 70.0f; - sp2C.y = this->actor.world.pos.y; + sparksPos.x = this->actor.world.pos.x + Math_SinS(this->actor.shape.rot.y + 0x6A4) * 70.0f; + sparksPos.z = this->actor.world.pos.z + Math_CosS(this->actor.shape.rot.y + 0x6A4) * 70.0f; + sparksPos.y = this->actor.world.pos.y; + Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_HIT_GND); Camera_RequestQuake(&play->mainCamera, 2, 25, 5); Rumble_Request(this->actor.xzDistToPlayer, 255, 20, 150); - CollisionCheck_SpawnShieldParticles(play, &sp2C); + CollisionCheck_SpawnShieldParticles(play, &sparksPos); } if ((this->skelAnime.curFrame > 17.0f) && (this->skelAnime.curFrame < 23.0f)) { this->unk_2FE = 1; } else { - if ((this->unk_2FB != 0) && (this->skelAnime.curFrame < 10.0f)) { + if ((this->armorStatusFlag != 0) && (this->skelAnime.curFrame < 10.0f)) { Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 1, 0x5DC, 0); this->actor.shape.rot.y = this->actor.world.rot.y; } @@ -443,105 +471,116 @@ void func_80A74EBC(EnIk* this, PlayState* play) { } if (SkelAnime_Update(&this->skelAnime)) { - func_80A7506C(this); + EnIk_SetupPullOutAxe(this); } } -void func_80A7506C(EnIk* this) { - f32 frames = Animation_GetLastFrame(&object_ik_Anim_0029FC); +void EnIk_SetupPullOutAxe(EnIk* this) { + f32 endFrame = Animation_GetLastFrame(&gIronKnuckleAxeStuckAnim); this->unk_2FE = 0; - this->unk_2F9 = (s8)frames; + this->animationTimer = (s8)endFrame; this->unk_2F8 = 7; this->unk_2FF = this->unk_2FE; - Animation_Change(&this->skelAnime, &object_ik_Anim_0029FC, 1.0f, 0.0f, frames, ANIMMODE_LOOP, -4.0f); + Animation_Change(&this->skelAnime, &gIronKnuckleAxeStuckAnim, 1.0f, 0.0f, endFrame, ANIMMODE_LOOP, -4.0f); Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_PULLOUT); - EnIk_SetupAction(this, func_80A7510C); + EnIk_SetupAction(this, EnIk_PullOutAxe); } -void func_80A7510C(EnIk* this, PlayState* play) { - f32 frames; +void EnIk_PullOutAxe(EnIk* this, PlayState* play) { + f32 endFrame; - if (SkelAnime_Update(&this->skelAnime) || (--this->unk_2F9 == 0)) { + if (SkelAnime_Update(&this->skelAnime) || (--this->animationTimer == 0)) { if (this->unk_2F8 == 8) { - func_80A7489C(this); + EnIk_SetupIdle(this); } else { - frames = Animation_GetLastFrame(&object_ik_Anim_002538); + endFrame = Animation_GetLastFrame(&gIronKnuckleRecoverFromVerticalAttackAnim); this->unk_2F8 = 8; - Animation_Change(&this->skelAnime, &object_ik_Anim_002538, 1.5f, 0.0f, frames, ANIMMODE_ONCE_INTERP, -4.0f); + Animation_Change(&this->skelAnime, &gIronKnuckleRecoverFromVerticalAttackAnim, 1.5f, 0.0f, endFrame, + ANIMMODE_ONCE_INTERP, -4.0f); } } } -void func_80A751C8(EnIk* this) { - f32 frames = Animation_GetLastFrame(&object_ik_Anim_0033C4); +// Happens when Player is in front of Iron Knuckle or when Iron Knuckle encounters ACTOR_BG_JYA_IRONOBJ +void EnIk_SetupDoubleHorizontalAttack(EnIk* this) { + f32 endFrame = Animation_GetLastFrame(&gIronKnuckleHorizontalAttackAnim); this->unk_2FF = 2; this->unk_300 = 0; this->unk_2F8 = 6; this->actor.speedXZ = 0.0f; - Animation_Change(&this->skelAnime, &object_ik_Anim_0033C4, 0.0f, 0.0f, frames, ANIMMODE_ONCE_INTERP, -6.0f); - this->unk_2FC = 0; - EnIk_SetupAction(this, func_80A75260); + Animation_Change(&this->skelAnime, &gIronKnuckleHorizontalAttackAnim, 0.0f, 0.0f, endFrame, ANIMMODE_ONCE_INTERP, + -6.0f); + this->isBreakingProp = false; + EnIk_SetupAction(this, EnIk_DoubleHorizontalAttack); } -void func_80A75260(EnIk* this, PlayState* play) { - f32 temp_f0; +void EnIk_DoubleHorizontalAttack(EnIk* this, PlayState* play) { + f32 playSpeed; this->unk_300 += 0x1C2; - temp_f0 = Math_SinS(this->unk_300); - this->skelAnime.playSpeed = ABS(temp_f0); + playSpeed = Math_SinS(this->unk_300); + this->skelAnime.playSpeed = ABS(playSpeed); if (this->skelAnime.curFrame > 11.0f) { this->unk_2FF = 3; } + if (((this->skelAnime.curFrame > 1.0f) && (this->skelAnime.curFrame < 9.0f)) || ((this->skelAnime.curFrame > 13.0f) && (this->skelAnime.curFrame < 18.0f))) { - if ((this->unk_2FC == 0) && (this->unk_2FB != 0) && (this->skelAnime.curFrame < 10.0f)) { + if (!this->isBreakingProp && (this->armorStatusFlag != 0) && (this->skelAnime.curFrame < 10.0f)) { Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 1, 0x5DC, 0); this->actor.shape.rot.y = this->actor.world.rot.y; } + if (this->unk_2FE < 0) { Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_SWING_AXE); } + this->unk_2FE = 1; } else { this->unk_2FE = 0; } + if (SkelAnime_Update(&this->skelAnime)) { - func_80A753D0(this); + EnIk_SetupRecoverFromHorizontalAttack(this); } } -void func_80A753D0(EnIk* this) { - f32 frames = Animation_GetLastFrame(&object_ik_Anim_003DBC); +void EnIk_SetupRecoverFromHorizontalAttack(EnIk* this) { + f32 endFrame = Animation_GetLastFrame(&gIronKnuckleRecoverFromHorizontalAttackAnim); this->unk_2FF = this->unk_2FE = 0; this->unk_2F8 = 8; - Animation_Change(&this->skelAnime, &object_ik_Anim_003DBC, 1.5f, 0.0f, frames, ANIMMODE_ONCE_INTERP, -4.0f); - EnIk_SetupAction(this, func_80A7545C); + Animation_Change(&this->skelAnime, &gIronKnuckleRecoverFromHorizontalAttackAnim, 1.5f, 0.0f, endFrame, + ANIMMODE_ONCE_INTERP, -4.0f); + EnIk_SetupAction(this, EnIk_RecoverFromHorizontalAttack); } -void func_80A7545C(EnIk* this, PlayState* play) { +void EnIk_RecoverFromHorizontalAttack(EnIk* this, PlayState* play) { if (SkelAnime_Update(&this->skelAnime)) { - func_80A7489C(this); - func_80A745E4(this, play); + EnIk_SetupIdle(this); + EnIk_HandleBlocking(this, play); } } -void func_80A754A0(EnIk* this) { - f32 frames = Animation_GetLastFrame(&object_ik_Anim_0033C4); +// Attack pattern when player is behind Iron Knuckle or attacks Iron Knuckle from behind +void EnIk_SetupSingleHorizontalAttack(EnIk* this) { + f32 endFrame = Animation_GetLastFrame(&gIronKnuckleHorizontalAttackAnim); this->unk_2F8 = 1; this->unk_2FF = 3; this->actor.speedXZ = 0.0f; - Animation_Change(&this->skelAnime, &object_ik_Anim_0033C4, 0.5f, 13.0f, frames, ANIMMODE_ONCE_INTERP, -4.0f); - EnIk_SetupAction(this, func_80A75530); + Animation_Change(&this->skelAnime, &gIronKnuckleHorizontalAttackAnim, 0.5f, 13.0f, endFrame, ANIMMODE_ONCE_INTERP, + -4.0f); + EnIk_SetupAction(this, EnIk_SingleHorizontalAttack); } -void func_80A75530(EnIk* this, PlayState* play) { +void EnIk_SingleHorizontalAttack(EnIk* this, PlayState* play) { Math_StepUntilS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 0x7D0); this->actor.shape.rot.y = this->actor.world.rot.y; + if ((this->skelAnime.curFrame > 13.0f) && (this->skelAnime.curFrame < 18.0f)) { if (this->unk_2FE < 0) { Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_SWING_AXE); @@ -550,106 +589,116 @@ void func_80A75530(EnIk* this, PlayState* play) { } else { this->unk_2FE = 0; } + if (SkelAnime_Update(&this->skelAnime)) { - func_80A753D0(this); - func_80A745E4(this, play); + EnIk_SetupRecoverFromHorizontalAttack(this); + EnIk_HandleBlocking(this, play); } } -void func_80A755F0(EnIk* this) { - f32 frames = Animation_GetLastFrame(&object_ik_Anim_00485C); +void EnIk_SetupStopAndBlock(EnIk* this) { + f32 endFrame = Animation_GetLastFrame(&gIronKnuckleBlockAnim); this->unk_2FE = 0; this->unk_2F8 = 9; this->actor.speedXZ = 0.0f; - Animation_Change(&this->skelAnime, &object_ik_Anim_00485C, 1.0f, 0.0f, frames, ANIMMODE_ONCE_INTERP, -4.0f); - EnIk_SetupAction(this, func_80A7567C); + Animation_Change(&this->skelAnime, &gIronKnuckleBlockAnim, 1.0f, 0.0f, endFrame, ANIMMODE_ONCE_INTERP, -4.0f); + EnIk_SetupAction(this, EnIk_StopAndBlock); } -void func_80A7567C(EnIk* this, PlayState* play) { +void EnIk_StopAndBlock(EnIk* this, PlayState* play) { CollisionCheck_SetAC(play, &play->colChkCtx, &this->shieldCollider.base); + if (SkelAnime_Update(&this->skelAnime)) { if ((ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) <= 0x4000) && (this->actor.xzDistToPlayer < 100.0f) && (ABS(this->actor.yDistToPlayer) < 150.0f)) { if ((play->gameplayFrames & 1)) { - func_80A74E2C(this); + EnIk_SetupVerticalAttack(this); } else { - func_80A751C8(this); + EnIk_SetupDoubleHorizontalAttack(this); } } else { - func_80A7489C(this); + EnIk_SetupIdle(this); } } } -void func_80A75790(EnIk* this) { +void EnIk_SetupReactToAttack(EnIk* this) { s16 yaw; s16 yawDiff; yaw = Math_Vec3f_Yaw(&this->actor.world.pos, &this->bodyCollider.base.ac->world.pos); this->unk_2F8 = 0; yawDiff = yaw - this->actor.shape.rot.y; + if (ABS(yawDiff) <= 0x4000) { - Animation_Change(&this->skelAnime, &object_ik_Anim_006194, 1.0f, 0.0f, - Animation_GetLastFrame(&object_ik_Anim_006194), ANIMMODE_ONCE, -4.0f); + Animation_Change(&this->skelAnime, &gIronKnuckleFrontHitAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gIronKnuckleFrontHitAnim), ANIMMODE_ONCE, -4.0f); this->actor.speedXZ = -6.0f; } else { - Animation_Change(&this->skelAnime, &object_ik_Anim_0045BC, 1.0f, 0.0f, - Animation_GetLastFrame(&object_ik_Anim_0045BC), ANIMMODE_ONCE, -4.0f); + Animation_Change(&this->skelAnime, &gIronKnuckleBackHitAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gIronKnuckleBackHitAnim), ANIMMODE_ONCE, -4.0f); this->actor.speedXZ = 6.0f; } + this->unk_2FE = 0; - EnIk_SetupAction(this, func_80A758B0); + EnIk_SetupAction(this, EnIk_ReactToAttack); } -void func_80A758B0(EnIk* this, PlayState* play) { +void EnIk_ReactToAttack(EnIk* this, PlayState* play) { Math_SmoothStepToF(&this->actor.speedXZ, 0.0f, 1.0f, 1.0f, 0.0f); + if (BodyBreak_SpawnParts(&this->actor, &this->bodyBreak, play, this->actor.params + 4)) { this->bodyBreak.val = BODYBREAK_STATUS_FINISHED; } + if (SkelAnime_Update(&this->skelAnime)) { if (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) <= 0x4000) { - func_80A7489C(this); - func_80A745E4(this, play); + EnIk_SetupIdle(this); + EnIk_HandleBlocking(this, play); } else { - func_80A754A0(this); + EnIk_SetupSingleHorizontalAttack(this); } } } -void func_80A7598C(EnIk* this) { - f32 frames = Animation_GetLastFrame(&object_ik_Anim_005944); +void EnIk_SetupDie(EnIk* this) { + f32 endFrame = Animation_GetLastFrame(&gIronKnuckleDeathAnim); this->unk_2FE = 0; this->unk_2F8 = 2; this->actor.speedXZ = 0.0f; - Animation_Change(&this->skelAnime, &object_ik_Anim_005944, 1.0f, 0.0f, frames, ANIMMODE_ONCE, -4.0f); - this->unk_2F9 = 0x18; + Animation_Change(&this->skelAnime, &gIronKnuckleDeathAnim, 1.0f, 0.0f, endFrame, ANIMMODE_ONCE, -4.0f); + this->animationTimer = 24; Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_DEAD); Audio_PlayActorSfx2(&this->actor, NA_SE_EN_NUTS_CUTBODY); - EnIk_SetupAction(this, func_80A75A38); + EnIk_SetupAction(this, EnIk_Die); } -void func_80A75A38(EnIk* this, PlayState* play) { +void EnIk_Die(EnIk* this, PlayState* play) { if (SkelAnime_Update(&this->skelAnime)) { - if ((this->actor.colChkInfo.health == 0) && (this->unk_2F9 != 0)) { + if ((this->actor.colChkInfo.health == 0) && (this->animationTimer != 0)) { s32 i; Vec3f pos; Vec3f sp7C = { 0.0f, 0.5f, 0.0f }; - this->unk_2F9--; + this->animationTimer--; - for (i = 0xC - (this->unk_2F9 >> 1); i >= 0; i--) { + for (i = 0xC - (this->animationTimer >> 1); i >= 0; i--) { pos.x = this->actor.world.pos.x + Rand_CenteredFloat(120.0f); pos.z = this->actor.world.pos.z + Rand_CenteredFloat(120.0f); pos.y = this->actor.world.pos.y + 20.0f + Rand_CenteredFloat(50.0f); + EffectSsDeadDb_Spawn(play, &pos, &sp7C, &sp7C, 100, 0, 255, 255, 255, 255, 0, 0, 255, 1, 9, true); } - if (this->unk_2F9 == 0) { + + if (this->animationTimer == 0) { Item_DropCollectibleRandom(play, &this->actor, &this->actor.world.pos, 0xB0); - if (this->switchFlags != 0xFF) { - Flags_SetSwitch(play, this->switchFlags); + + if (this->switchFlag != 0xFF) { + Flags_SetSwitch(play, this->switchFlag); } + Actor_Kill(&this->actor); } } @@ -658,136 +707,157 @@ void func_80A75A38(EnIk* this, PlayState* play) { } } -void func_80A75C38(EnIk* this, PlayState* play) { - f32 temp_f0; - u8 pad; - u8 pad2; +void EnIk_UpdateDamage(EnIk* this, PlayState* play) { + f32 frames; + s16 pad; u8 prevHealth; - s32 pad3; - Vec3f sp38; + s32 damageEffect; + Vec3f sparksPos; if ((this->unk_2F8 == 3) || (this->unk_2F8 == 2)) { return; } + if (this->shieldCollider.base.acFlags & AC_BOUNCED) { - temp_f0 = Animation_GetLastFrame(&object_ik_Anim_00485C) - 2.0f; - if (this->skelAnime.curFrame < temp_f0) { - this->skelAnime.curFrame = temp_f0; + frames = Animation_GetLastFrame(&gIronKnuckleBlockAnim) - 2.0f; + + if (this->skelAnime.curFrame < frames) { + this->skelAnime.curFrame = frames; } + this->shieldCollider.base.acFlags &= ~AC_BOUNCED; this->bodyCollider.base.acFlags &= ~AC_HIT; - return; - } - if (!(this->bodyCollider.base.acFlags & AC_HIT)) { - return; - } - sp38 = this->actor.world.pos; - sp38.y += 50.0f; - Actor_SetDropFlag(&this->actor, &this->bodyCollider.info, true); - this->unk_2FD = this->actor.colChkInfo.damageEffect; - this->bodyCollider.base.acFlags &= ~AC_HIT; + } else if (this->bodyCollider.base.acFlags & AC_HIT) { + sparksPos = this->actor.world.pos; + sparksPos.y += 50.0f; - if ((this->unk_2FD == 0) || (this->unk_2FD == 0xD) || ((this->unk_2FB == 0) && (this->unk_2FD == 0xE))) { - if (this->unk_2FD != 0) { - CollisionCheck_SpawnShieldParticlesMetal(play, &sp38); - } - return; - } - Actor_SetColorFilter(&this->actor, 0x4000, 0xFF, 0, 0xC); - prevHealth = this->actor.colChkInfo.health; - Actor_ApplyDamage(&this->actor); - if (this->actor.params != 0) { - if ((prevHealth > 10) && (this->actor.colChkInfo.health <= 10)) { - this->unk_2FB = 1; - BodyBreak_Alloc(&this->bodyBreak, 3, play); - } - } else if (this->actor.colChkInfo.health <= 10) { - Actor_ChangeCategory(play, &play->actorCtx, &this->actor, ACTORCAT_BOSS); - SfxSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_EN_LAST_DAMAGE); - if (this->switchFlags != 0xFF) { - Flags_SetSwitch(play, this->switchFlags); - } - return; - } else if (prevHealth == 50) { - Actor_ChangeCategory(play, &play->actorCtx, &this->actor, ACTORCAT_ENEMY); - } + Actor_SetDropFlag(&this->actor, &this->bodyCollider.info, true); - if (this->actor.colChkInfo.health == 0) { - func_80A7598C(this); - Enemy_StartFinishingBlow(play, &this->actor); - return; - } - Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 1, 0x7D0, 0); - if ((this->actor.params == 0) && (Rand_ZeroOne() < 0.5f)) { - if (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) > 0x4000) { - func_80A754A0(this); + this->damageEffect = this->actor.colChkInfo.damageEffect; + this->bodyCollider.base.acFlags &= ~AC_HIT; + + if ((this->damageEffect == EN_IK_DMGEFF_NONE) || (this->damageEffect == EN_IK_DMGEFF_SPARKS_NO_DMG) || + ((this->armorStatusFlag == 0) && (this->damageEffect == EN_IK_DMGEFF_PROJECTILE))) { + if (this->damageEffect != EN_IK_DMGEFF_NONE) { + // spawn sparks and don't damage + CollisionCheck_SpawnShieldParticlesMetal(play, &sparksPos); + } + return; } - } - if ((this->actor.params != 0) && (this->unk_2FB != 0)) { - if ((prevHealth > 10) && (this->actor.colChkInfo.health <= 10)) { - Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_ARMOR_OFF_DEMO); + + Actor_SetColorFilter(&this->actor, 0x4000, 0xFF, 0, 0xC); + + prevHealth = this->actor.colChkInfo.health; + Actor_ApplyDamage(&this->actor); + + if (this->actor.params != IK_TYPE_NABOORU) { + if ((prevHealth > 10) && (this->actor.colChkInfo.health <= 10)) { + this->armorStatusFlag = ARMOR_BROKEN; + BodyBreak_Alloc(&this->bodyBreak, 3, play); + } + } else if (this->actor.colChkInfo.health <= 10) { + Actor_ChangeCategory(play, &play->actorCtx, &this->actor, ACTORCAT_BOSS); + SfxSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 20, NA_SE_EN_LAST_DAMAGE); + if (this->switchFlag != 0xFF) { + Flags_SetSwitch(play, this->switchFlag); + } + return; + } else if (prevHealth == 50) { + Actor_ChangeCategory(play, &play->actorCtx, &this->actor, ACTORCAT_ENEMY); + } + + if (this->actor.colChkInfo.health == 0) { + EnIk_SetupDie(this); + Enemy_StartFinishingBlow(play, &this->actor); + return; + } + + Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 1, 0x7D0, 0); + + if ((this->actor.params == IK_TYPE_NABOORU) && (Rand_ZeroOne() < 0.5f)) { + if (ABS((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y)) > 0x4000) { + EnIk_SetupSingleHorizontalAttack(this); + } + } + + if ((this->actor.params != IK_TYPE_NABOORU) && (this->armorStatusFlag != 0)) { + if ((prevHealth > 10) && (this->actor.colChkInfo.health <= 10)) { + Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_ARMOR_OFF_DEMO); + } else { + Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_DAMAGE); + Audio_PlayActorSfx2(&this->actor, NA_SE_EN_NUTS_CUTBODY); + } + + EnIk_SetupReactToAttack(this); } else { + Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_ARMOR_HIT); Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_DAMAGE); - Audio_PlayActorSfx2(&this->actor, NA_SE_EN_NUTS_CUTBODY); + CollisionCheck_SpawnShieldParticles(play, &sparksPos); } - func_80A75790(this); - return; } - Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_ARMOR_HIT); - Audio_PlayActorSfx2(&this->actor, NA_SE_EN_IRONNACK_DAMAGE); - CollisionCheck_SpawnShieldParticles(play, &sp38); } -void func_80A75FA0(Actor* thisx, PlayState* play) { +void EnIk_UpdateEnemy(Actor* thisx, PlayState* play) { EnIk* this = (EnIk*)thisx; s32 pad; Player* player = GET_PLAYER(play); u8 prevInvincibilityTimer; - this->unk_2FA = this->unk_2FB; - func_80A75C38(this, play); - if ((this->actor.params == 0) && (this->actor.colChkInfo.health <= 10)) { - func_80A781CC(&this->actor, play); - return; - } - this->actionFunc(this, play); - if (this->axeCollider.base.atFlags & AT_HIT) { - this->axeCollider.base.atFlags &= ~AT_HIT; - if (&player->actor == this->axeCollider.base.at) { - prevInvincibilityTimer = player->invincibilityTimer; - if (player->invincibilityTimer <= 0) { - if (player->invincibilityTimer < -39) { - player->invincibilityTimer = 0; - } else { - player->invincibilityTimer = 0; - play->damagePlayer(play, -64); - this->unk_2FE = 0; + this->drawArmorFlag = this->armorStatusFlag; + EnIk_UpdateDamage(this, play); + + if ((this->actor.params == IK_TYPE_NABOORU) && (this->actor.colChkInfo.health <= 10)) { + EnIk_StartDefeatCutscene(&this->actor, play); + } else { + this->actionFunc(this, play); + + if (this->axeCollider.base.atFlags & AT_HIT) { + this->axeCollider.base.atFlags &= ~AT_HIT; + + if (this->axeCollider.base.at == &player->actor) { + prevInvincibilityTimer = player->invincibilityTimer; + + if (player->invincibilityTimer <= 0) { + if (player->invincibilityTimer < -39) { + player->invincibilityTimer = 0; + } else { + player->invincibilityTimer = 0; + play->damagePlayer(play, -64); + this->unk_2FE = 0; + } } + + func_8002F71C(play, &this->actor, 8.0f, this->actor.yawTowardsPlayer, 8.0f); + player->invincibilityTimer = prevInvincibilityTimer; } - func_8002F71C(play, &this->actor, 8.0f, this->actor.yawTowardsPlayer, 8.0f); - player->invincibilityTimer = prevInvincibilityTimer; } - } - Actor_MoveForward(&this->actor); - Actor_UpdateBgCheckInfo(play, &this->actor, 75.0f, 30.0f, 30.0f, - UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2 | UPDBGCHECKINFO_FLAG_3 | - UPDBGCHECKINFO_FLAG_4); - this->actor.focus.pos = this->actor.world.pos; - this->actor.focus.pos.y += 45.0f; - Collider_UpdateCylinder(&this->actor, &this->bodyCollider); - CollisionCheck_SetOC(play, &play->colChkCtx, &this->bodyCollider.base); - if ((this->actor.colChkInfo.health > 0) && (this->actor.colorFilterTimer == 0) && (this->unk_2F8 >= 2)) { - CollisionCheck_SetAC(play, &play->colChkCtx, &this->bodyCollider.base); - } - if (this->unk_2FE > 0) { - CollisionCheck_SetAT(play, &play->colChkCtx, &this->axeCollider.base); - } - if (this->unk_2F8 == 9) { - CollisionCheck_SetAC(play, &play->colChkCtx, &this->shieldCollider.base); + + Actor_MoveForward(&this->actor); + Actor_UpdateBgCheckInfo(play, &this->actor, 75.0f, 30.0f, 30.0f, + UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2 | UPDBGCHECKINFO_FLAG_3 | + UPDBGCHECKINFO_FLAG_4); + + this->actor.focus.pos = this->actor.world.pos; + this->actor.focus.pos.y += 45.0f; + + Collider_UpdateCylinder(&this->actor, &this->bodyCollider); + CollisionCheck_SetOC(play, &play->colChkCtx, &this->bodyCollider.base); + + if ((this->actor.colChkInfo.health > 0) && (this->actor.colorFilterTimer == 0) && (this->unk_2F8 >= 2)) { + CollisionCheck_SetAC(play, &play->colChkCtx, &this->bodyCollider.base); + } + + if (this->unk_2FE > 0) { + CollisionCheck_SetAT(play, &play->colChkCtx, &this->axeCollider.base); + } + + if (this->unk_2F8 == 9) { + CollisionCheck_SetAC(play, &play->colChkCtx, &this->shieldCollider.base); + } } } -Gfx* func_80A761B0(GraphicsContext* gfxCtx, u8 primR, u8 primG, u8 primB, u8 envR, u8 envG, u8 envB) { +Gfx* EnIk_SetPrimEnvColors(GraphicsContext* gfxCtx, u8 primR, u8 primG, u8 primB, u8 envR, u8 envG, u8 envB) { Gfx* displayList; Gfx* displayListHead; @@ -802,26 +872,28 @@ Gfx* func_80A761B0(GraphicsContext* gfxCtx, u8 primR, u8 primG, u8 primB, u8 env return displayList; } -s32 EnIk_OverrideLimbDraw3(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { +s32 EnIk_OverrideLimbDrawEnemy(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { EnIk* this = (EnIk*)thisx; - if (limbIndex == 12) { - if (this->actor.params != 0) { - *dList = object_ik_DL_018E78; + if (limbIndex == IRON_KNUCKLE_LIMB_HELMET_ARMOR) { + if (this->actor.params != IK_TYPE_NABOORU) { + *dList = gIronKnuckleHelmetDL; } - } else if (limbIndex == 13) { - if (this->actor.params != 0) { - *dList = object_ik_DL_019100; + } else if (limbIndex == IRON_KNUCKLE_LIMB_HEAD) { + if (this->actor.params != IK_TYPE_NABOORU) { + *dList = gIronKnuckleGerudoHeadDL; } - } else if ((limbIndex == 26) || (limbIndex == 27)) { - if ((this->unk_2FA & 1)) { + } else if ((limbIndex == IRON_KNUCKLE_LIMB_CHEST_ARMOR_FRONT) || + (limbIndex == IRON_KNUCKLE_LIMB_CHEST_ARMOR_BACK)) { + if (this->drawArmorFlag & ARMOR_BROKEN) { *dList = NULL; } - } else if ((limbIndex == 28) || (limbIndex == 29)) { - if (!(this->unk_2FA & 1)) { + } else if ((limbIndex == IRON_KNUCKLE_LIMB_TORSO) || (limbIndex == IRON_KNUCKLE_LIMB_WAIST)) { + if (!(this->drawArmorFlag & ARMOR_BROKEN)) { *dList = NULL; } } + return false; } @@ -847,25 +919,26 @@ static Vec3f D_80A784D0[] = { { -3000.0, -700.0, -5000.0 }, }; -void EnIk_PostLimbDraw3(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { +void EnIk_PostLimbDrawEnemy(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { Vec3f spF4; Vec3f spE8; EnIk* this = (EnIk*)thisx; OPEN_DISPS(play->state.gfxCtx, "../z_en_ik_inFight.c", 1201); - if (this->unk_2FB & 1) { - BodyBreak_SetInfo(&this->bodyBreak, limbIndex, 26, 27, 28, dList, BODYBREAK_OBJECT_DEFAULT); + if (this->armorStatusFlag & ARMOR_BROKEN) { + BodyBreak_SetInfo(&this->bodyBreak, limbIndex, IRON_KNUCKLE_LIMB_CHEST_ARMOR_FRONT, + IRON_KNUCKLE_LIMB_CHEST_ARMOR_BACK, IRON_KNUCKLE_LIMB_TORSO, dList, BODYBREAK_OBJECT_DEFAULT); } - if (limbIndex == 12) { + if (limbIndex == IRON_KNUCKLE_LIMB_HELMET_ARMOR) { gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, "../z_en_ik_inFight.c", 1217), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - if (this->actor.params != 0) { - gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_019E08); + if (this->actor.params != IK_TYPE_NABOORU) { + gSPDisplayList(POLY_XLU_DISP++, gIronKnuckleHelmetMarkingDL); } else { gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016D88); } - } else if (limbIndex == 17) { + } else if (limbIndex == IRON_KNUCKLE_LIMB_AXE) { s32 i; Vec3f sp9C[3]; Vec3f sp78[3]; @@ -896,25 +969,28 @@ void EnIk_PostLimbDraw3(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, } switch (limbIndex) { - case 22: + case IRON_KNUCKLE_LIMB_UPPER_LEFT_PAULDRON: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, "../z_en_ik_inFight.c", 1270), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016F88); break; - case 24: + + case IRON_KNUCKLE_LIMB_UPPER_RIGHT_PAULDRON: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, "../z_en_ik_inFight.c", 1275), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016EE8); break; - case 26: - if (!(this->unk_2FA & 1)) { + + case IRON_KNUCKLE_LIMB_CHEST_ARMOR_FRONT: + if (!(this->drawArmorFlag & ARMOR_BROKEN)) { gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, "../z_en_ik_inFight.c", 1281), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016BE0); + gSPDisplayList(POLY_XLU_DISP++, gIronKnuckleArmorRivetAndSymbolDL); } break; - case 27: - if (!(this->unk_2FA & 1)) { + + case IRON_KNUCKLE_LIMB_CHEST_ARMOR_BACK: + if (!(this->drawArmorFlag & ARMOR_BROKEN)) { gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, "../z_en_ik_inFight.c", 1288), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016CD8); @@ -925,7 +1001,7 @@ void EnIk_PostLimbDraw3(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, CLOSE_DISPS(play->state.gfxCtx, "../z_en_ik_inFight.c", 1294); } -void func_80A76798(Actor* thisx, PlayState* play) { +void EnIk_DrawEnemy(Actor* thisx, PlayState* play) { EnIk* this = (EnIk*)thisx; OPEN_DISPS(play->state.gfxCtx, "../z_en_ik_inFight.c", 1309); @@ -933,34 +1009,36 @@ void func_80A76798(Actor* thisx, PlayState* play) { Gfx_SetupDL_25Opa(play->state.gfxCtx); Gfx_SetupDL_25Xlu(play->state.gfxCtx); - if (this->actor.params == 0) { - gSPSegment(POLY_OPA_DISP++, 0x08, func_80A761B0(play->state.gfxCtx, 245, 225, 155, 30, 30, 0)); - gSPSegment(POLY_OPA_DISP++, 0x09, func_80A761B0(play->state.gfxCtx, 255, 40, 0, 40, 0, 0)); - gSPSegment(POLY_OPA_DISP++, 0x0A, func_80A761B0(play->state.gfxCtx, 255, 255, 255, 20, 40, 30)); - } else if (this->actor.params == 1) { - gSPSegment(POLY_OPA_DISP++, 0x08, func_80A761B0(play->state.gfxCtx, 245, 255, 205, 30, 35, 0)); - gSPSegment(POLY_OPA_DISP++, 0x09, func_80A761B0(play->state.gfxCtx, 185, 135, 25, 20, 20, 0)); - gSPSegment(POLY_OPA_DISP++, 0x0A, func_80A761B0(play->state.gfxCtx, 255, 255, 255, 30, 40, 20)); - } else if (this->actor.params == 2) { - gSPSegment(POLY_OPA_DISP++, 0x08, func_80A761B0(play->state.gfxCtx, 55, 65, 55, 0, 0, 0)); - gSPSegment(POLY_OPA_DISP++, 0x09, func_80A761B0(play->state.gfxCtx, 205, 165, 75, 25, 20, 0)); - gSPSegment(POLY_OPA_DISP++, 0x0A, func_80A761B0(play->state.gfxCtx, 205, 165, 75, 25, 20, 0)); + if (this->actor.params == IK_TYPE_NABOORU) { + gSPSegment(POLY_OPA_DISP++, 0x08, EnIk_SetPrimEnvColors(play->state.gfxCtx, 245, 225, 155, 30, 30, 0)); + gSPSegment(POLY_OPA_DISP++, 0x09, EnIk_SetPrimEnvColors(play->state.gfxCtx, 255, 40, 0, 40, 0, 0)); + gSPSegment(POLY_OPA_DISP++, 0x0A, EnIk_SetPrimEnvColors(play->state.gfxCtx, 255, 255, 255, 20, 40, 30)); + } else if (this->actor.params == IK_TYPE_SILVER) { + gSPSegment(POLY_OPA_DISP++, 0x08, EnIk_SetPrimEnvColors(play->state.gfxCtx, 245, 255, 205, 30, 35, 0)); + gSPSegment(POLY_OPA_DISP++, 0x09, EnIk_SetPrimEnvColors(play->state.gfxCtx, 185, 135, 25, 20, 20, 0)); + gSPSegment(POLY_OPA_DISP++, 0x0A, EnIk_SetPrimEnvColors(play->state.gfxCtx, 255, 255, 255, 30, 40, 20)); + } else if (this->actor.params == IK_TYPE_BLACK) { + gSPSegment(POLY_OPA_DISP++, 0x08, EnIk_SetPrimEnvColors(play->state.gfxCtx, 55, 65, 55, 0, 0, 0)); + gSPSegment(POLY_OPA_DISP++, 0x09, EnIk_SetPrimEnvColors(play->state.gfxCtx, 205, 165, 75, 25, 20, 0)); + gSPSegment(POLY_OPA_DISP++, 0x0A, EnIk_SetPrimEnvColors(play->state.gfxCtx, 205, 165, 75, 25, 20, 0)); } else { - gSPSegment(POLY_OPA_DISP++, 0x08, func_80A761B0(play->state.gfxCtx, 255, 255, 255, 180, 180, 180)); - gSPSegment(POLY_OPA_DISP++, 0x09, func_80A761B0(play->state.gfxCtx, 225, 205, 115, 25, 20, 0)); - gSPSegment(POLY_OPA_DISP++, 0x0A, func_80A761B0(play->state.gfxCtx, 225, 205, 115, 25, 20, 0)); + gSPSegment(POLY_OPA_DISP++, 0x08, EnIk_SetPrimEnvColors(play->state.gfxCtx, 255, 255, 255, 180, 180, 180)); + gSPSegment(POLY_OPA_DISP++, 0x09, EnIk_SetPrimEnvColors(play->state.gfxCtx, 225, 205, 115, 25, 20, 0)); + gSPSegment(POLY_OPA_DISP++, 0x0A, EnIk_SetPrimEnvColors(play->state.gfxCtx, 225, 205, 115, 25, 20, 0)); } + SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount, - EnIk_OverrideLimbDraw3, EnIk_PostLimbDraw3, this); + EnIk_OverrideLimbDrawEnemy, EnIk_PostLimbDrawEnemy, this); CLOSE_DISPS(play->state.gfxCtx, "../z_en_ik_inFight.c", 1351); } -void EnIk_StartMusic(void) { +void EnIk_StartMinibossBgm(void) { func_800F5ACC(NA_BGM_MINI_BOSS); } -void func_80A76C14(EnIk* this) { +// Cutscene: Nabooru Knuckle Wakes up +void EnIk_UpdateAction2Sfx(EnIk* this) { if (Animation_OnFrame(&this->skelAnime, 1.0f)) { Audio_PlaySfxGeneral(NA_SE_EN_IRONNACK_WAKEUP, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); @@ -982,13 +1060,14 @@ void func_80A76C14(EnIk* this) { } } -void func_80A76DDC(EnIk* this, PlayState* play, Vec3f* pos) { +// Cutscene: Summons Axe for Nabooru Knuckle +void EnIk_PlayAxeSpawnSfx(EnIk* this, PlayState* play, Vec3f* pos) { Audio_PlaySfxGeneral(NA_SE_EN_TWINROBA_TRANSFORM, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } -void func_80A76E2C(EnIk* this, PlayState* play, Vec3f* pos) { - static Vec3f D_80A78514[] = { +void EnIk_SpawnAxeSmoke(EnIk* this, PlayState* play, Vec3f* pos) { + static Vec3f sAxeSmokeEffectData[] = { { 1000.0, -1000.0, 1000.0 }, { 0.0, -1000.0, 0.0 }, { -1000.0, -5000.0, -4000.0 }, { 1000.0, -5000.0, -3000.0 }, { -1000.0, 1000.0, -6000.0 }, { -1000.0, 3000.0, -5000.0 }, { -800.0, 1000.0, -3000.0 }, { 0.0, -4000.0, -2000.0 }, { -1000.0, -2000.0, -6000.0 }, @@ -998,40 +1077,43 @@ void func_80A76E2C(EnIk* this, PlayState* play, Vec3f* pos) { { 900.0, -800.0, 2700.0 }, { 720.0f, 900.0f, 2500.0f }, }; - if (this->unk_4D4 == 0) { + if (!this->isAxeSummoned) { s32 pad; Vec3f effectVelocity = { 0.0f, 0.0f, 0.0f }; Vec3f effectAccel = { 0.0f, 0.3f, 0.0f }; s32 i; - for (i = ARRAY_COUNT(D_80A78514) - 1; i >= 0; i--) { + for (i = ARRAY_COUNT(sAxeSmokeEffectData) - 1; i >= 0; i--) { Color_RGBA8 primColor = { 200, 200, 200, 255 }; Color_RGBA8 envColor = { 150, 150, 150, 0 }; - s32 temp_v0; + s32 randColorOffset; Vec3f effectPos; - Matrix_MultVec3f(&D_80A78514[i], &effectPos); - temp_v0 = (Rand_ZeroOne() * 20.0f) - 10.0f; - primColor.r += temp_v0; - primColor.g += temp_v0; - primColor.b += temp_v0; - envColor.r += temp_v0; - envColor.g += temp_v0; - envColor.b += temp_v0; + Matrix_MultVec3f(&sAxeSmokeEffectData[i], &effectPos); + randColorOffset = (Rand_ZeroOne() * 20.0f) - 10.0f; + + primColor.r += randColorOffset; + primColor.g += randColorOffset; + primColor.b += randColorOffset; + + envColor.r += randColorOffset; + envColor.g += randColorOffset; + envColor.b += randColorOffset; + func_8002829C(play, &effectPos, &effectVelocity, &effectAccel, &primColor, &envColor, (Rand_ZeroOne() * 60.0f) + 300.0f, 0); } - this->unk_4D4 = 1; - func_80A76DDC(this, play, pos); + this->isAxeSummoned = true; + EnIk_PlayAxeSpawnSfx(this, play, pos); } } -void func_80A77034(EnIk* this, PlayState* play) { +void EnIk_UpdateBgCheckInfo(EnIk* this, PlayState* play) { Actor_UpdateBgCheckInfo(play, &this->actor, 75.0f, 30.0f, 30.0f, UPDBGCHECKINFO_FLAG_0 | UPDBGCHECKINFO_FLAG_2); } -s32 func_80A7707C(EnIk* this) { +s32 EnIk_UpdateSkelAnime(EnIk* this) { return SkelAnime_Update(&this->skelAnime); } @@ -1043,7 +1125,7 @@ CsCmdActorAction* EnIk_GetNpcAction(PlayState* play, s32 actionIdx) { } } -void func_80A770C0(EnIk* this, PlayState* play, s32 actionIdx) { +void EnIk_MoveNpcToPos(EnIk* this, PlayState* play, s32 actionIdx) { CsCmdActorAction* npcAction = EnIk_GetNpcAction(play, actionIdx); if (npcAction != NULL) { @@ -1054,48 +1136,51 @@ void func_80A770C0(EnIk* this, PlayState* play, s32 actionIdx) { } } -f32 EnIk_curFrame(Actor* thisx) { +f32 EnIk_GetAnimCurFrame(Actor* thisx) { EnIk* this = (EnIk*)thisx; return this->skelAnime.curFrame; } -void func_80A77148(EnIk* this) { - this->action = 0; - this->drawMode = 0; +// unused +void EnIk_SetupCsAction0(EnIk* this) { + this->csAction = IK_CS_ACTION_0; + this->csDrawMode = IK_CS_DRAW_NOTHING; this->actor.shape.shadowAlpha = 0; } -void func_80A77158(EnIk* this, PlayState* play) { - Animation_Change(&this->skelAnime, &object_ik_Anim_00C114, 1.0f, 0.0f, - Animation_GetLastFrame(&object_ik_Anim_00C114), ANIMMODE_ONCE, 0.0f); - func_80A770C0(this, play, 4); - this->action = 1; - this->drawMode = 1; - this->actor.shape.shadowAlpha = 0xFF; +// Cutscene: Nabooru sitting and Kotake and Koume looking at her +void EnIk_SetupCsAction1(EnIk* this, PlayState* play) { + Animation_Change(&this->skelAnime, &gIronKnuckleNabooruSummonAxeAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gIronKnuckleNabooruSummonAxeAnim), ANIMMODE_ONCE, 0.0f); + EnIk_MoveNpcToPos(this, play, 4); + this->csAction = IK_CS_ACTION_1; + this->csDrawMode = IK_CS_DRAW_INTRO; + this->actor.shape.shadowAlpha = 255; } -void func_80A771E4(EnIk* this) { - Animation_Change(&this->skelAnime, &object_ik_Anim_00C114, 1.0f, 0.0f, - Animation_GetLastFrame(&object_ik_Anim_00C114), ANIMMODE_ONCE, 0.0f); - this->action = 2; - this->drawMode = 1; - this->unk_4D4 = 0; - this->actor.shape.shadowAlpha = 0xFF; +// Cutscene: Nabooru Knuckle starts to stand up +void EnIk_SetupCsAction2(EnIk* this) { + Animation_Change(&this->skelAnime, &gIronKnuckleNabooruSummonAxeAnim, 1.0f, 0.0f, + Animation_GetLastFrame(&gIronKnuckleNabooruSummonAxeAnim), ANIMMODE_ONCE, 0.0f); + this->csAction = IK_CS_ACTION_2; + this->csDrawMode = IK_CS_DRAW_INTRO; + this->isAxeSummoned = false; + this->actor.shape.shadowAlpha = 255; } -void func_80A77264(EnIk* this, PlayState* play, s32 arg2) { - if ((arg2 != 0) && (EnIk_GetNpcAction(play, 4) != NULL)) { - func_80A78160(this, play); +void EnIk_HandleEnemyChange(EnIk* this, PlayState* play, s32 animFinished) { + if (animFinished && (EnIk_GetNpcAction(play, 4) != NULL)) { + EnIk_ChangeToEnemy(this, play); } } -void func_80A772A4(EnIk* this) { +void EnIk_PlayArmorFallSfx(EnIk* this) { Audio_PlaySfxGeneral(NA_SE_EN_IRONNACK_STAGGER_DEMO, &this->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } -void func_80A772EC(EnIk* this, PlayState* play) { +void EnIk_PlayDeathSfx(EnIk* this, PlayState* play) { static Vec3f D_80A78FA0; s32 pad[2]; f32 wDest; @@ -1105,109 +1190,117 @@ void func_80A772EC(EnIk* this, PlayState* play) { &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } -void func_80A7735C(EnIk* this, PlayState* play) { +// Cutscene: starts after final hit to Nabooru +void EnIk_SetupCsAction3(EnIk* this, PlayState* play) { s32 pad[3]; - f32 frames = Animation_GetLastFrame(&object_ik_Anim_0203D8); + f32 endFrame = Animation_GetLastFrame(&gIronKnuckleNabooruDeathAnim); - SkelAnime_InitFlex(play, &this->skelAnime, &object_ik_Skel_0205C0, NULL, this->jointTable, this->morphTable, 30); - Animation_Change(&this->skelAnime, &object_ik_Anim_0203D8, 1.0f, 0.0f, frames, ANIMMODE_ONCE, 0.0f); - this->action = 3; - this->drawMode = 2; - func_80A770C0(this, play, 4); - func_80A772EC(this, play); - this->actor.shape.shadowAlpha = 0xFF; + SkelAnime_InitFlex(play, &this->skelAnime, &gIronKnuckleDefeatSkel, NULL, this->jointTable, this->morphTable, + IRON_KNUCKLE_LIMB_MAX); + Animation_Change(&this->skelAnime, &gIronKnuckleNabooruDeathAnim, 1.0f, 0.0f, endFrame, ANIMMODE_ONCE, 0.0f); + this->csAction = IK_CS_ACTION_3; + this->csDrawMode = IK_CS_DRAW_DEFEAT; + EnIk_MoveNpcToPos(this, play, 4); + EnIk_PlayDeathSfx(this, play); + this->actor.shape.shadowAlpha = 255; } -void func_80A77434(EnIk* this, PlayState* play) { - this->action = 4; - this->drawMode = 2; - func_80A772A4(this); - this->actor.shape.shadowAlpha = 0xFF; +// Cutscene: Armor falling off revealing Nabooru underneath +void EnIk_SetupCsAction4(EnIk* this, PlayState* play) { + this->csAction = IK_CS_ACTION_4; + this->csDrawMode = IK_CS_DRAW_DEFEAT; + EnIk_PlayArmorFallSfx(this); + this->actor.shape.shadowAlpha = 255; } -void func_80A77474(EnIk* this, PlayState* play) { - this->action = 5; - this->drawMode = 0; +// Cutscene: all the armor has fallen off +void EnIk_SetupCsAction5(EnIk* this, PlayState* play) { + this->csAction = IK_CS_ACTION_5; + this->csDrawMode = IK_CS_DRAW_NOTHING; this->actor.shape.shadowAlpha = 0; } -void func_80A7748C(EnIk* this, PlayState* play) { - func_80A77034(this, play); - func_80A779DC(this, play); +void EnIk_CsAction3(EnIk* this, PlayState* play) { + EnIk_UpdateBgCheckInfo(this, play); + EnIk_HandleCsCues(this, play); } -void func_80A774BC(EnIk* this, PlayState* play) { - func_80A7707C(this); - func_80A77034(this, play); - func_80A779DC(this, play); +void EnIk_CsAction4(EnIk* this, PlayState* play) { + EnIk_UpdateSkelAnime(this); + EnIk_UpdateBgCheckInfo(this, play); + EnIk_HandleCsCues(this, play); } -void func_80A774F8(EnIk* this, PlayState* play) { +void EnIk_CsAction5(EnIk* this, PlayState* play) { if (EnIk_GetNpcAction(play, 4) == NULL) { Actor_Kill(&this->actor); } } -s32 EnIk_OverrideLimbDraw2(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { - EnIk* this = (EnIk*)thisx; - - if ((limbIndex == 13) || (limbIndex == 26) || (limbIndex == 27)) { - if (EnIk_curFrame(&this->actor) >= 30.0f) { +s32 EnIk_OverrideLimbDrawDefeat(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { + if ((limbIndex == IRON_KNUCKLE_DEFEAT_LIMB_HELMET_ARMOR) || (limbIndex == IRON_KNUCKLE_DEFEAT_LIMB_CHEST_ARMOR_FRONT) || + (limbIndex == IRON_KNUCKLE_DEFEAT_LIMB_CHEST_ARMOR_BACK)) { + if (EnIk_GetAnimCurFrame(thisx) >= 30.0f) { *dList = NULL; } } - return 0; + return false; } -void EnIk_PostLimbDraw2(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { +void EnIk_PostLimbDrawDefeat(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { GraphicsContext* gfxCtx = play->state.gfxCtx; OPEN_DISPS(gfxCtx, "../z_en_ik_inAwake.c", 207); switch (limbIndex) { - case 13: { + case IRON_KNUCKLE_DEFEAT_LIMB_HELMET_ARMOR: { EnIk* this = (EnIk*)thisx; - if (EnIk_curFrame(&this->actor) < 30.0f) { + if (EnIk_GetAnimCurFrame(&this->actor) < 30.0f) { gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inAwake.c", 267), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016D88); } } break; - case 22: + + case IRON_KNUCKLE_DEFEAT_LIMB_UPPER_LEFT_PAULDRON: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inAwake.c", 274), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016F88); break; - case 24: + + case IRON_KNUCKLE_DEFEAT_LIMB_UPPER_RIGHT_PAULDRON: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inAwake.c", 280), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016EE8); break; - case 26: { + + case IRON_KNUCKLE_DEFEAT_LIMB_CHEST_ARMOR_FRONT: { EnIk* this = (EnIk*)thisx; - if (EnIk_curFrame(&this->actor) < 30.0f) { + if (EnIk_GetAnimCurFrame(&this->actor) < 30.0f) { gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inAwake.c", 288), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016BE0); + gSPDisplayList(POLY_XLU_DISP++, gIronKnuckleArmorRivetAndSymbolDL); } } break; - case 27: { + + case IRON_KNUCKLE_DEFEAT_LIMB_CHEST_ARMOR_BACK: { EnIk* this = (EnIk*)thisx; - if (EnIk_curFrame(&this->actor) < 30.0f) { + if (EnIk_GetAnimCurFrame(&this->actor) < 30.0f) { gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inAwake.c", 297), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016CD8); } } break; } + CLOSE_DISPS(gfxCtx, "../z_en_ik_inAwake.c", 304); } -void func_80A77844(EnIk* this, PlayState* play) { +void EnIk_CsDrawDefeat(EnIk* this, PlayState* play) { GraphicsContext* gfxCtx = play->state.gfxCtx; SkelAnime* skelAnime = &this->skelAnime; s32 pad[2]; @@ -1217,46 +1310,52 @@ void func_80A77844(EnIk* this, PlayState* play) { func_8002EBCC(&this->actor, play, 0); Gfx_SetupDL_25Opa(gfxCtx); Gfx_SetupDL_25Xlu(gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x08, func_80A761B0(gfxCtx, 245, 225, 155, 30, 30, 0)); - gSPSegment(POLY_OPA_DISP++, 0x09, func_80A761B0(gfxCtx, 255, 40, 0, 40, 0, 0)); - gSPSegment(POLY_OPA_DISP++, 0x0A, func_80A761B0(gfxCtx, 255, 255, 255, 20, 40, 30)); + gSPSegment(POLY_OPA_DISP++, 0x08, EnIk_SetPrimEnvColors(gfxCtx, 245, 225, 155, 30, 30, 0)); + gSPSegment(POLY_OPA_DISP++, 0x09, EnIk_SetPrimEnvColors(gfxCtx, 255, 40, 0, 40, 0, 0)); + gSPSegment(POLY_OPA_DISP++, 0x0A, EnIk_SetPrimEnvColors(gfxCtx, 255, 255, 255, 20, 40, 30)); SkelAnime_DrawFlexOpa(play, skelAnime->skeleton, skelAnime->jointTable, skelAnime->dListCount, - EnIk_OverrideLimbDraw2, EnIk_PostLimbDraw2, this); + EnIk_OverrideLimbDrawDefeat, EnIk_PostLimbDrawDefeat, this); CLOSE_DISPS(gfxCtx, "../z_en_ik_inAwake.c", 345); } -void func_80A779DC(EnIk* this, PlayState* play) { +void EnIk_HandleCsCues(EnIk* this, PlayState* play) { CsCmdActorAction* npcAction = EnIk_GetNpcAction(play, 4); - u32 action; - u32 currentNpcAction; if (npcAction != NULL) { - action = npcAction->action; - currentNpcAction = this->npcAction; + s32 action = npcAction->action; + s32 currentNpcAction = this->npcAction; + if (action != currentNpcAction) { switch (action) { case 1: - func_80A77148(this); + EnIk_SetupCsAction0(this); break; + case 2: - func_80A77158(this, play); + EnIk_SetupCsAction1(this, play); break; + case 3: - func_80A771E4(this); + EnIk_SetupCsAction2(this); break; + case 4: - func_80A78160(this, play); + EnIk_ChangeToEnemy(this, play); break; + case 5: - func_80A7735C(this, play); + EnIk_SetupCsAction3(this, play); break; + case 6: - func_80A77434(this, play); + EnIk_SetupCsAction4(this, play); break; + case 7: - func_80A77474(this, play); + EnIk_SetupCsAction5(this, play); break; + default: osSyncPrintf("En_Ik_inConfrontion_Check_DemoMode:そんな動作は無い!!!!!!!!\n"); } @@ -1266,89 +1365,94 @@ void func_80A779DC(EnIk* this, PlayState* play) { } } -void func_80A77AEC(EnIk* this, PlayState* play) { - func_80A779DC(this, play); +void EnIk_CsAction0(EnIk* this, PlayState* play) { + EnIk_HandleCsCues(this, play); } -void func_80A77B0C(EnIk* this, PlayState* play) { - func_80A77034(this, play); - func_80A779DC(this, play); +void EnIk_CsAction1(EnIk* this, PlayState* play) { + EnIk_UpdateBgCheckInfo(this, play); + EnIk_HandleCsCues(this, play); } -void func_80A77B3C(EnIk* this, PlayState* play) { - s32 sp24; +void EnIk_CsAction2(EnIk* this, PlayState* play) { + s32 animFinished; - sp24 = func_80A7707C(this); - func_80A76C14(this); - func_80A77034(this, play); - func_80A779DC(this, play); - func_80A77264(this, play, sp24); + animFinished = EnIk_UpdateSkelAnime(this); + EnIk_UpdateAction2Sfx(this); + EnIk_UpdateBgCheckInfo(this, play); + EnIk_HandleCsCues(this, play); + EnIk_HandleEnemyChange(this, play, animFinished); } -static EnIkActionFunc sActionFuncs[] = { - func_80A77AEC, func_80A77B0C, func_80A77B3C, func_80A7748C, func_80A774BC, func_80A774F8, +static EnIkActionFunc sCsActionFuncs[] = { + EnIk_CsAction0, EnIk_CsAction1, EnIk_CsAction2, EnIk_CsAction3, EnIk_CsAction4, EnIk_CsAction5, }; -void EnIk_Update(Actor* thisx, PlayState* play) { +void EnIk_UpdateCutscene(Actor* thisx, PlayState* play) { EnIk* this = (EnIk*)thisx; - if (this->action < 0 || this->action >= ARRAY_COUNT(sActionFuncs) || sActionFuncs[this->action] == NULL) { + if (this->csAction < 0 || this->csAction >= ARRAY_COUNT(sCsActionFuncs) || sCsActionFuncs[this->csAction] == NULL) { osSyncPrintf(VT_FGCOL(RED) "メインモードがおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST); return; } - sActionFuncs[this->action](this, play); + sCsActionFuncs[this->csAction](this, play); } -s32 EnIk_OverrideLimbDraw1(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { +s32 EnIk_OverrideLimbDrawIntro(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, void* thisx) { EnIk* this = (EnIk*)thisx; f32 curFrame; switch (limbIndex) { - case 17: + case IRON_KNUCKLE_LIMB_AXE: curFrame = this->skelAnime.curFrame; if (curFrame < 120.0f) { *dList = NULL; } else { - func_80A76E2C(this, play, pos); + EnIk_SpawnAxeSmoke(this, play, pos); } break; - case 29: - case 30: + + case IRON_KNUCKLE_LIMB_WAIST: + case IRON_KNUCKLE_LIMB_MAX: *dList = NULL; break; } - return 0; + return false; } -void EnIk_PostLimbDraw1(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { +void EnIk_PostLimbDrawIntro(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) { GraphicsContext* gfxCtx = play->state.gfxCtx; OPEN_DISPS(gfxCtx, "../z_en_ik_inConfrontion.c", 571); switch (limbIndex) { - case 12: + case IRON_KNUCKLE_LIMB_HELMET_ARMOR: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inConfrontion.c", 575), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016D88); break; - case 22: + + case IRON_KNUCKLE_LIMB_UPPER_LEFT_PAULDRON: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inConfrontion.c", 581), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016F88); break; - case 24: + + case IRON_KNUCKLE_LIMB_UPPER_RIGHT_PAULDRON: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inConfrontion.c", 587), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016EE8); break; - case 26: + + case IRON_KNUCKLE_LIMB_CHEST_ARMOR_FRONT: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inConfrontion.c", 593), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016BE0); + gSPDisplayList(POLY_XLU_DISP++, gIronKnuckleArmorRivetAndSymbolDL); break; - case 27: + + case IRON_KNUCKLE_LIMB_CHEST_ARMOR_BACK: gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_ik_inConfrontion.c", 599), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); gSPDisplayList(POLY_XLU_DISP++, object_ik_DL_016CD8); @@ -1358,10 +1462,10 @@ void EnIk_PostLimbDraw1(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, CLOSE_DISPS(gfxCtx, "../z_en_ik_inConfrontion.c", 604); } -void func_80A77ED0(EnIk* this, PlayState* play) { +void EnIk_CsDrawNothing(EnIk* this, PlayState* play) { } -void func_80A77EDC(EnIk* this, PlayState* play) { +void EnIk_CsDrawIntro(EnIk* this, PlayState* play) { GraphicsContext* gfxCtx = play->state.gfxCtx; SkelAnime* skelAnime = &this->skelAnime; s32 pad[2]; @@ -1371,78 +1475,80 @@ void func_80A77EDC(EnIk* this, PlayState* play) { func_8002EBCC(&this->actor, play, 0); Gfx_SetupDL_25Opa(gfxCtx); Gfx_SetupDL_25Xlu(gfxCtx); - gSPSegment(POLY_OPA_DISP++, 0x08, func_80A761B0(gfxCtx, 245, 225, 155, 30, 30, 0)); - gSPSegment(POLY_OPA_DISP++, 0x09, func_80A761B0(gfxCtx, 255, 40, 0, 40, 0, 0)); - gSPSegment(POLY_OPA_DISP++, 0x0A, func_80A761B0(gfxCtx, 255, 255, 255, 20, 40, 30)); + gSPSegment(POLY_OPA_DISP++, 0x08, EnIk_SetPrimEnvColors(gfxCtx, 245, 225, 155, 30, 30, 0)); + gSPSegment(POLY_OPA_DISP++, 0x09, EnIk_SetPrimEnvColors(gfxCtx, 255, 40, 0, 40, 0, 0)); + gSPSegment(POLY_OPA_DISP++, 0x0A, EnIk_SetPrimEnvColors(gfxCtx, 255, 255, 255, 20, 40, 30)); SkelAnime_DrawFlexOpa(play, skelAnime->skeleton, skelAnime->jointTable, skelAnime->dListCount, - EnIk_OverrideLimbDraw1, EnIk_PostLimbDraw1, this); + EnIk_OverrideLimbDrawIntro, EnIk_PostLimbDrawIntro, this); CLOSE_DISPS(gfxCtx, "../z_en_ik_inConfrontion.c", 653); } -static EnIkDrawFunc sDrawFuncs[] = { func_80A77ED0, func_80A77EDC, func_80A77844 }; +static EnIkDrawFunc sCsDrawFuncs[] = { EnIk_CsDrawNothing, EnIk_CsDrawIntro, EnIk_CsDrawDefeat }; -void EnIk_Draw(Actor* thisx, PlayState* play) { +void EnIk_DrawCutscene(Actor* thisx, PlayState* play) { EnIk* this = (EnIk*)thisx; - if (this->drawMode < 0 || this->drawMode >= ARRAY_COUNT(sDrawFuncs) || sDrawFuncs[this->drawMode] == NULL) { + if (this->csDrawMode < 0 || this->csDrawMode >= ARRAY_COUNT(sCsDrawFuncs) || + sCsDrawFuncs[this->csDrawMode] == NULL) { osSyncPrintf(VT_FGCOL(RED) "描画モードがおかしい!!!!!!!!!!!!!!!!!!!!!!!!!\n" VT_RST); return; } - sDrawFuncs[this->drawMode](this, play); + sCsDrawFuncs[this->csDrawMode](this, play); } -void func_80A780D0(EnIk* this, PlayState* play) { - if (this->actor.params == 0) { +void EnIk_CsInit(EnIk* this, PlayState* play) { + if (this->actor.params == IK_TYPE_NABOORU) { if (!GET_EVENTCHKINF(EVENTCHKINF_3B)) { - this->actor.update = EnIk_Update; - this->actor.draw = EnIk_Draw; + this->actor.update = EnIk_UpdateCutscene; + this->actor.draw = EnIk_DrawCutscene; Actor_SetScale(&this->actor, 0.01f); } else { - func_80A78160(this, play); - EnIk_StartMusic(); + EnIk_ChangeToEnemy(this, play); + EnIk_StartMinibossBgm(); } } + osSyncPrintf("En_Ik_inConfrontion_Init : %d !!!!!!!!!!!!!!!!\n", this->actor.params); } -void func_80A78160(EnIk* this, PlayState* play) { - this->actor.update = func_80A75FA0; - this->actor.draw = func_80A76798; +void EnIk_ChangeToEnemy(EnIk* this, PlayState* play) { + this->actor.update = EnIk_UpdateEnemy; + this->actor.draw = EnIk_DrawEnemy; this->actor.flags |= ACTOR_FLAG_0 | ACTOR_FLAG_2; SET_EVENTCHKINF(EVENTCHKINF_3B); Actor_SetScale(&this->actor, 0.012f); - func_80A7489C(this); + EnIk_SetupIdle(this); } -void func_80A781CC(Actor* thisx, PlayState* play) { +void EnIk_StartDefeatCutscene(Actor* thisx, PlayState* play) { EnIk* this = (EnIk*)thisx; if (!Play_InCsMode(play)) { - this->actor.update = EnIk_Update; - this->actor.draw = EnIk_Draw; + this->actor.update = EnIk_UpdateCutscene; + this->actor.draw = EnIk_DrawCutscene; Cutscene_SetSegment(play, gSpiritBossNabooruKnuckleDefeatCs); gSaveContext.cutsceneTrigger = 1; Actor_SetScale(&this->actor, 0.01f); SET_EVENTCHKINF(EVENTCHKINF_3C); - func_80A7735C(this, play); + EnIk_SetupCsAction3(this, play); } } void EnIk_Init(Actor* thisx, PlayState* play) { EnIk* this = (EnIk*)thisx; - s32 flag = this->actor.params & 0xFF00; + s32 upperParams = IK_GET_UPPER_PARAMS(&this->actor); - if (((this->actor.params & 0xFF) == 0 && GET_EVENTCHKINF(EVENTCHKINF_3C)) || - (flag != 0 && Flags_GetSwitch(play, flag >> 8))) { + if (((IK_GET_ARMOR_TYPE(&this->actor) == IK_TYPE_NABOORU) && GET_EVENTCHKINF(EVENTCHKINF_3C)) || + (upperParams != 0 && Flags_GetSwitch(play, upperParams >> 8))) { Actor_Kill(&this->actor); } else { ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 30.0f); - SkelAnime_InitFlex(play, &this->skelAnime, &object_ik_Skel_01E178, &object_ik_Anim_00C114, this->jointTable, - this->morphTable, 30); - func_80A74398(&this->actor, play); - func_80A780D0(this, play); + SkelAnime_InitFlex(play, &this->skelAnime, &gIronKnuckleSkel, &gIronKnuckleNabooruSummonAxeAnim, + this->jointTable, this->morphTable, IRON_KNUCKLE_LIMB_MAX); + EnIk_InitImpl(&this->actor, play); + EnIk_CsInit(this, play); } } @@ -1454,6 +1560,6 @@ ActorInit En_Ik_InitVars = { sizeof(EnIk), (ActorFunc)EnIk_Init, (ActorFunc)EnIk_Destroy, - (ActorFunc)EnIk_Update, - (ActorFunc)EnIk_Draw, + (ActorFunc)EnIk_UpdateCutscene, + (ActorFunc)EnIk_DrawCutscene, }; diff --git a/src/overlays/actors/ovl_En_Ik/z_en_ik.h b/src/overlays/actors/ovl_En_Ik/z_en_ik.h index 418318e602..c7642f7733 100644 --- a/src/overlays/actors/ovl_En_Ik/z_en_ik.h +++ b/src/overlays/actors/ovl_En_Ik/z_en_ik.h @@ -8,21 +8,102 @@ struct EnIk; typedef void (*EnIkActionFunc)(struct EnIk*, PlayState*); +#define IK_GET_UPPER_PARAMS(thisx) ((thisx)->params & 0xFF00) +#define IK_GET_ARMOR_TYPE(thisx) ((thisx)->params & 0xFF) +#define IK_GET_SWITCH_FLAG(thisx) (((thisx)->params >> 8) & 0xFF) + +typedef enum { + /* 0 */ IK_TYPE_NABOORU, + /* 1 */ IK_TYPE_SILVER, + /* 2 */ IK_TYPE_BLACK, + /* 3 */ IK_TYPE_WHITE +} EnIkType; + +typedef enum { + /* 0x00 */ IRON_KNUCKLE_LIMB_NONE, + /* 0x01 */ IRON_KNUCKLE_LIMB_ROOT, + /* 0x02 */ IRON_KNUCKLE_LIMB_LOWER_BODY, + /* 0x03 */ IRON_KNUCKLE_LIMB_RIGHT_THIGH, + /* 0x04 */ IRON_KNUCKLE_LIMB_RIGHT_SHIN, + /* 0x05 */ IRON_KNUCKLE_LIMB_RIGHT_FOOT, + /* 0x06 */ IRON_KNUCKLE_LIMB_LEFT_THIGH, + /* 0x07 */ IRON_KNUCKLE_LIMB_LEFT_SHIN, + /* 0x08 */ IRON_KNUCKLE_LIMB_LEFT_FOOT, + /* 0x09 */ IRON_KNUCKLE_LIMB_UPPER_BODY_ROOT, + /* 0x0A */ IRON_KNUCKLE_LIMB_UPPER_BODY, + /* 0x0B */ IRON_KNUCKLE_LIMB_HEAD_ROOT, + /* 0x0C */ IRON_KNUCKLE_LIMB_HELMET_ARMOR, + /* 0x0D */ IRON_KNUCKLE_LIMB_HEAD, + /* 0x0E */ IRON_KNUCKLE_LIMB_RIGHT_UPPER_ARM, + /* 0x0F */ IRON_KNUCKLE_LIMB_RIGHT_FOREARM, + /* 0x10 */ IRON_KNUCKLE_LIMB_RIGHT_HAND_ROOT, + /* 0x11 */ IRON_KNUCKLE_LIMB_AXE, + /* 0x12 */ IRON_KNUCKLE_LIMB_RIGHT_HAND, + /* 0x13 */ IRON_KNUCKLE_LIMB_LEFT_UPPER_ARM, + /* 0x14 */ IRON_KNUCKLE_LIMB_LEFT_FOREARM, + /* 0x15 */ IRON_KNUCKLE_LIMB_LEFT_HAND, + /* 0x16 */ IRON_KNUCKLE_LIMB_UPPER_LEFT_PAULDRON, + /* 0x17 */ IRON_KNUCKLE_LIMB_LOWER_LEFT_PAULDRON, + /* 0x18 */ IRON_KNUCKLE_LIMB_UPPER_RIGHT_PAULDRON, + /* 0x19 */ IRON_KNUCKLE_LIMB_LOWER_RIGHT_PAULDRON, + /* 0x1A */ IRON_KNUCKLE_LIMB_CHEST_ARMOR_FRONT, + /* 0x1B */ IRON_KNUCKLE_LIMB_CHEST_ARMOR_BACK, + /* 0x1C */ IRON_KNUCKLE_LIMB_TORSO, + /* 0x1D */ IRON_KNUCKLE_LIMB_WAIST, + /* 0x1E */ IRON_KNUCKLE_LIMB_MAX +} IronKnuckleLimb; + +// This skeleton is only used in the defeat cutscene that reveals Nabooru under the armor. +// The only difference between this skeleton and the main one is that the head and helmet armor limbs are swapped. +typedef enum { + /* 0x00 */ IRON_KNUCKLE_DEFEAT_LIMB_NONE, + /* 0x01 */ IRON_KNUCKLE_DEFEAT_LIMB_ROOT, + /* 0x02 */ IRON_KNUCKLE_DEFEAT_LIMB_LOWER_BODY, + /* 0x03 */ IRON_KNUCKLE_DEFEAT_LIMB_RIGHT_THIGH, + /* 0x04 */ IRON_KNUCKLE_DEFEAT_LIMB_RIGHT_SHIN, + /* 0x05 */ IRON_KNUCKLE_DEFEAT_LIMB_RIGHT_FOOT, + /* 0x06 */ IRON_KNUCKLE_DEFEAT_LIMB_LEFT_THIGH, + /* 0x07 */ IRON_KNUCKLE_DEFEAT_LIMB_LEFT_SHIN, + /* 0x08 */ IRON_KNUCKLE_DEFEAT_LIMB_LEFT_FOOT, + /* 0x09 */ IRON_KNUCKLE_DEFEAT_LIMB_UPPER_BODY_ROOT, + /* 0x0A */ IRON_KNUCKLE_DEFEAT_LIMB_UPPER_BODY, + /* 0x0B */ IRON_KNUCKLE_DEFEAT_LIMB_HEAD_ROOT, + /* 0x0C */ IRON_KNUCKLE_DEFEAT_LIMB_HEAD, + /* 0x0D */ IRON_KNUCKLE_DEFEAT_LIMB_HELMET_ARMOR, + /* 0x0E */ IRON_KNUCKLE_DEFEAT_LIMB_RIGHT_UPPER_ARM, + /* 0x0F */ IRON_KNUCKLE_DEFEAT_LIMB_RIGHT_FOREARM, + /* 0x10 */ IRON_KNUCKLE_DEFEAT_LIMB_RIGHT_HAND_ROOT, + /* 0x11 */ IRON_KNUCKLE_DEFEAT_LIMB_AXE, + /* 0x12 */ IRON_KNUCKLE_DEFEAT_LIMB_RIGHT_HAND, + /* 0x13 */ IRON_KNUCKLE_DEFEAT_LIMB_LEFT_UPPER_ARM, + /* 0x14 */ IRON_KNUCKLE_DEFEAT_LIMB_LEFT_FOREARM, + /* 0x15 */ IRON_KNUCKLE_DEFEAT_LIMB_LEFT_HAND, + /* 0x16 */ IRON_KNUCKLE_DEFEAT_LIMB_UPPER_LEFT_PAULDRON, + /* 0x17 */ IRON_KNUCKLE_DEFEAT_LIMB_LOWER_LEFT_PAULDRON, + /* 0x18 */ IRON_KNUCKLE_DEFEAT_LIMB_UPPER_RIGHT_PAULDRON, + /* 0x19 */ IRON_KNUCKLE_DEFEAT_LIMB_LOWER_RIGHT_PAULDRON, + /* 0x1A */ IRON_KNUCKLE_DEFEAT_LIMB_CHEST_ARMOR_FRONT, + /* 0x1B */ IRON_KNUCKLE_DEFEAT_LIMB_CHEST_ARMOR_BACK, + /* 0x1C */ IRON_KNUCKLE_DEFEAT_LIMB_TORSO, + /* 0x1D */ IRON_KNUCKLE_DEFEAT_LIMB_WAIST, + /* 0x1E */ IRON_KNUCKLE_DEFEAT_LIMB_MAX +} IronKnuckleDefeatLimb; + typedef struct EnIk { /* 0x0000 */ Actor actor; /* 0x014C */ SkelAnime skelAnime; - /* 0x0190 */ Vec3s jointTable[30]; - /* 0x0244 */ Vec3s morphTable[30]; + /* 0x0190 */ Vec3s jointTable[IRON_KNUCKLE_LIMB_MAX]; + /* 0x0244 */ Vec3s morphTable[IRON_KNUCKLE_LIMB_MAX]; /* 0x02F8 */ u8 unk_2F8; - /* 0x02F9 */ u8 unk_2F9; - /* 0x02FA */ u8 unk_2FA; - /* 0x02FB */ u8 unk_2FB; - /* 0x02FC */ u8 unk_2FC; - /* 0x02FD */ u8 unk_2FD; + /* 0x02F9 */ u8 animationTimer; + /* 0x02FA */ u8 drawArmorFlag; + /* 0x02FB */ u8 armorStatusFlag; + /* 0x02FC */ u8 isBreakingProp; + /* 0x02FD */ u8 damageEffect; /* 0x02FE */ s8 unk_2FE; /* 0x02FF */ s8 unk_2FF; /* 0x0300 */ s16 unk_300; - /* 0x0302 */ s16 switchFlags; + /* 0x0302 */ s16 switchFlag; /* 0x0304 */ EnIkActionFunc actionFunc; /* 0x0308 */ BodyBreak bodyBreak; /* 0x0320 */ ColliderCylinder bodyCollider; @@ -30,10 +111,10 @@ typedef struct EnIk { /* 0x03EC */ ColliderTris shieldCollider; /* 0x040C */ ColliderTrisElement shieldColliderItems[2]; /* 0x04C4 */ s32 blureIdx; - /* 0x04C8 */ s32 action; - /* 0x04CC */ s32 drawMode; + /* 0x04C8 */ s32 csAction; + /* 0x04CC */ s32 csDrawMode; /* 0x04D0 */ u32 npcAction; - /* 0x04D4 */ s32 unk_4D4; + /* 0x04D4 */ s32 isAxeSummoned; /* 0x04D8 */ char unk_4D8[0x04]; } EnIk; // size = 0x04DC