summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTharo <17233964+Thar0@users.noreply.github.com>2024-06-21 02:36:11 +0100
committerGitHub <noreply@github.com>2024-06-20 18:36:11 -0700
commit384115d2a07c8885a4702f3ec7fa7eac5a3879c1 (patch)
treeae17dc4c247c3948bf30e15ae4a47aa0124c93b1
parent2c680efa9169eaaddae97330fa3ea9586a273b57 (diff)
ovl_En_Death and ovl_En_Minideath (#1645)
* En_Death new build system edition * Fix merge * Matched * Fix merge * Some names * Suggested changes * Further suggested changes * Add value comments to MinideathAction
-rw-r--r--assets/xml/objects/object_death.xml102
-rw-r--r--linker_scripts/undefined_syms.ld21
-rw-r--r--spec7
-rw-r--r--src/overlays/actors/ovl_En_Death/z_en_death.c1923
-rw-r--r--src/overlays/actors/ovl_En_Death/z_en_death.h50
-rw-r--r--src/overlays/actors/ovl_En_Minideath/z_en_minideath.c1002
-rw-r--r--src/overlays/actors/ovl_En_Minideath/z_en_minideath.h39
-rw-r--r--tools/disasm/functions.txt72
8 files changed, 2739 insertions, 477 deletions
diff --git a/assets/xml/objects/object_death.xml b/assets/xml/objects/object_death.xml
index 7588c484a..08ebdc3f0 100644
--- a/assets/xml/objects/object_death.xml
+++ b/assets/xml/objects/object_death.xml
@@ -1,17 +1,17 @@
<Root>
<File Name="object_death" Segment="6">
- <Animation Name="object_death_Anim_000E64" Offset="0xE64" /> <!-- Original name is "d13_atack" -->
- <Animation Name="object_death_Anim_0015B4" Offset="0x15B4" /> <!-- Original name is "d13_callenemy" -->
- <Animation Name="object_death_Anim_001834" Offset="0x1834" /> <!-- Original name is "d13_callingenemy" -->
- <Animation Name="object_death_Anim_001F80" Offset="0x1F80" /> <!-- Original name is "d13_damage" -->
- <Animation Name="object_death_Anim_002DE8" Offset="0x2DE8" /> <!-- Original name is "d13_deadhit" -->
- <Animation Name="object_death_Anim_00352C" Offset="0x352C" /> <!-- Original name is "d13_deadwait" -->
- <Animation Name="object_death_Anim_003CAC" Offset="0x3CAC" /> <!-- Original name is "d13_fly" -->
+ <Animation Name="gGomessScytheSwingAnim" Offset="0xE64" /> <!-- Original name is "d13_atack" -->
+ <Animation Name="gGomessBatSwarmStartAnim" Offset="0x15B4" /> <!-- Original name is "d13_callenemy" -->
+ <Animation Name="gGomessBatSwarmAnim" Offset="0x1834" /> <!-- Original name is "d13_callingenemy" -->
+ <Animation Name="gGomessDamagedAnim" Offset="0x1F80" /> <!-- Original name is "d13_damage" -->
+ <Animation Name="gGomessBeginDeathAnim" Offset="0x2DE8" /> <!-- Original name is "d13_deadhit" -->
+ <Animation Name="gGomessDeathAnim" Offset="0x352C" /> <!-- Original name is "d13_deadwait" -->
+ <Animation Name="gGomessFloatAnim" Offset="0x3CAC" /> <!-- Original name is "d13_fly" -->
<DList Name="object_death_DL_006B80" Offset="0x6B80" />
<DList Name="object_death_DL_006D18" Offset="0x6D18" />
<DList Name="object_death_DL_006E08" Offset="0x6E08" />
- <DList Name="object_death_DL_006F88" Offset="0x6F88" /> <!-- Original name is "d13_kama_model" ("sickle​") -->
- <DList Name="object_death_DL_0073D0" Offset="0x73D0" /> <!-- Original name is "d13_kamahaA_model" -->
+ <DList Name="gGomessScytheHandleDL" Offset="0x6F88" /> <!-- Original name is "d13_kama_model" ("sickle​") -->
+ <DList Name="gGomessScytheBladeDL" Offset="0x73D0" /> <!-- Original name is "d13_kamahaA_model" -->
<DList Name="object_death_DL_0074B8" Offset="0x74B8" />
<DList Name="object_death_DL_007560" Offset="0x7560" />
<DList Name="object_death_DL_007638" Offset="0x7638" />
@@ -39,47 +39,47 @@
<Texture Name="object_death_Tex_0095C8" OutName="tex_0095C8" Format="rgba16" Width="16" Height="16" Offset="0x95C8" />
<Texture Name="object_death_Tex_0097C8" OutName="tex_0097C8" Format="rgba16" Width="4" Height="8" Offset="0x97C8" />
<Texture Name="object_death_Tex_009808" OutName="tex_009808" Format="i4" Width="16" Height="16" Offset="0x9808" />
- <DList Name="object_death_DL_009988" Offset="0x9988" />
- <Texture Name="object_death_Tex_009AA0" OutName="tex_009AA0" Format="i4" Width="16" Height="16" Offset="0x9AA0" />
- <DList Name="object_death_DL_009BA0" Offset="0x9BA0" /> <!-- Original name is "d13_cover_model" -->
- <Texture Name="object_death_Tex_009C40" OutName="tex_009C40" Format="rgba16" Width="16" Height="16" Offset="0x9C40" />
- <DList Name="object_death_DL_009F10" Offset="0x9F10" />
- <DList Name="object_death_DL_009F88" Offset="0x9F88" />
- <DList Name="object_death_DL_00A088" Offset="0xA088" />
- <DList Name="object_death_DL_00A188" Offset="0xA188" />
- <DList Name="object_death_DL_00A288" Offset="0xA288" />
- <DList Name="object_death_DL_00A388" Offset="0xA388" />
- <DList Name="object_death_DL_00A488" Offset="0xA488" />
- <DList Name="object_death_DL_00A588" Offset="0xA588" />
- <DList Name="object_death_DL_00A688" Offset="0xA688" />
- <DList Name="object_death_DL_00A788" Offset="0xA788" />
- <Texture Name="object_death_Tex_00A7B8" OutName="tex_00A7B8" Format="rgba16" Width="32" Height="16" Offset="0xA7B8" />
- <Limb Name="object_death_Standardlimb_00ABB8" Type="Standard" EnumName="OBJECT_DEATH_LIMB_01" Offset="0xABB8" />
- <Limb Name="object_death_Standardlimb_00ABC4" Type="Standard" EnumName="OBJECT_DEATH_LIMB_02" Offset="0xABC4" />
- <Limb Name="object_death_Standardlimb_00ABD0" Type="Standard" EnumName="OBJECT_DEATH_LIMB_03" Offset="0xABD0" />
- <Limb Name="object_death_Standardlimb_00ABDC" Type="Standard" EnumName="OBJECT_DEATH_LIMB_04" Offset="0xABDC" />
- <Limb Name="object_death_Standardlimb_00ABE8" Type="Standard" EnumName="OBJECT_DEATH_LIMB_05" Offset="0xABE8" />
- <Limb Name="object_death_Standardlimb_00ABF4" Type="Standard" EnumName="OBJECT_DEATH_LIMB_06" Offset="0xABF4" />
- <Limb Name="object_death_Standardlimb_00AC00" Type="Standard" EnumName="OBJECT_DEATH_LIMB_07" Offset="0xAC00" />
- <Limb Name="object_death_Standardlimb_00AC0C" Type="Standard" EnumName="OBJECT_DEATH_LIMB_08" Offset="0xAC0C" />
- <Limb Name="object_death_Standardlimb_00AC18" Type="Standard" EnumName="OBJECT_DEATH_LIMB_09" Offset="0xAC18" />
- <Limb Name="object_death_Standardlimb_00AC24" Type="Standard" EnumName="OBJECT_DEATH_LIMB_0A" Offset="0xAC24" />
- <Limb Name="object_death_Standardlimb_00AC30" Type="Standard" EnumName="OBJECT_DEATH_LIMB_0B" Offset="0xAC30" />
- <Limb Name="object_death_Standardlimb_00AC3C" Type="Standard" EnumName="OBJECT_DEATH_LIMB_0C" Offset="0xAC3C" />
- <Limb Name="object_death_Standardlimb_00AC48" Type="Standard" EnumName="OBJECT_DEATH_LIMB_0D" Offset="0xAC48" />
- <Limb Name="object_death_Standardlimb_00AC54" Type="Standard" EnumName="OBJECT_DEATH_LIMB_0E" Offset="0xAC54" />
- <Limb Name="object_death_Standardlimb_00AC60" Type="Standard" EnumName="OBJECT_DEATH_LIMB_0F" Offset="0xAC60" />
- <Limb Name="object_death_Standardlimb_00AC6C" Type="Standard" EnumName="OBJECT_DEATH_LIMB_10" Offset="0xAC6C" />
- <Limb Name="object_death_Standardlimb_00AC78" Type="Standard" EnumName="OBJECT_DEATH_LIMB_11" Offset="0xAC78" />
- <Limb Name="object_death_Standardlimb_00AC84" Type="Standard" EnumName="OBJECT_DEATH_LIMB_12" Offset="0xAC84" />
- <Limb Name="object_death_Standardlimb_00AC90" Type="Standard" EnumName="OBJECT_DEATH_LIMB_13" Offset="0xAC90" />
- <Limb Name="object_death_Standardlimb_00AC9C" Type="Standard" EnumName="OBJECT_DEATH_LIMB_14" Offset="0xAC9C" />
- <Limb Name="object_death_Standardlimb_00ACA8" Type="Standard" EnumName="OBJECT_DEATH_LIMB_15" Offset="0xACA8" />
- <Skeleton Name="object_death_Skel_00AD08" Type="Flex" LimbType="Standard" LimbNone="OBJECT_DEATH_LIMB_NONE" LimbMax="OBJECT_DEATH_LIMB_MAX" EnumName="ObjectDeathLimb" Offset="0xAD08" />
- <Animation Name="object_death_Anim_00B284" Offset="0xB284" /> <!-- Original name is "d13_gahaha" -->
- <Animation Name="object_death_Anim_00B508" Offset="0xB508" /> <!-- Original name is "d13_guard" -->
- <Animation Name="object_death_Anim_00CB2C" Offset="0xCB2C" /> <!-- Original name is "d13_jakin" -->
- <TextureAnimation Name="object_death_Matanimheader_00CB84" Offset="0xCB84" />
- <TextureAnimation Name="object_death_Matanimheader_00CBC0" Offset="0xCBC0" />
+ <DList Name="gGomessCoreDL" Offset="0x9988" />
+ <Texture Name="gGomessCoreTex" OutName="gomess_core" Format="i4" Width="16" Height="16" Offset="0x9AA0" />
+ <DList Name="gGomessBatsGuardingCoreDL" Offset="0x9BA0" /> <!-- Original name is "d13_cover_model" -->
+ <Texture Name="gGomessBatsGuardingCoreTex" OutName="gomess_bats_guarding_core" Format="rgba16" Width="16" Height="16" Offset="0x9C40" />
+ <DList Name="gGomessBatMaterialDL" Offset="0x9F10" />
+ <DList Name="gGomessBatFrame1DL" Offset="0x9F88" />
+ <DList Name="gGomessBatFrame2DL" Offset="0xA088" />
+ <DList Name="gGomessBatFrame3DL" Offset="0xA188" />
+ <DList Name="gGomessBatFrame4DL" Offset="0xA288" />
+ <DList Name="gGomessBatFrame5DL" Offset="0xA388" />
+ <DList Name="gGomessBatFrame6DL" Offset="0xA488" />
+ <DList Name="gGomessBatFrame7DL" Offset="0xA588" />
+ <DList Name="gGomessBatFrame8DL" Offset="0xA688" />
+ <DList Name="gGomessBatFrame9DL" Offset="0xA788" />
+ <Texture Name="gGomessBatTex" OutName="gomess_bat" Format="rgba16" Width="32" Height="16" Offset="0xA7B8" />
+ <Limb Name="object_death_Standardlimb_00ABB8" Type="Standard" EnumName="GOMESS_LIMB_1" Offset="0xABB8" />
+ <Limb Name="object_death_Standardlimb_00ABC4" Type="Standard" EnumName="GOMESS_LIMB_CORE_POS" Offset="0xABC4" />
+ <Limb Name="object_death_Standardlimb_00ABD0" Type="Standard" EnumName="GOMESS_LIMB_LOWER_BODY" Offset="0xABD0" />
+ <Limb Name="object_death_Standardlimb_00ABDC" Type="Standard" EnumName="GOMESS_LIMB_TORSO" Offset="0xABDC" />
+ <Limb Name="object_death_Standardlimb_00ABE8" Type="Standard" EnumName="GOMESS_LIMB_COLLAR" Offset="0xABE8" />
+ <Limb Name="object_death_Standardlimb_00ABF4" Type="Standard" EnumName="GOMESS_LIMB_HEAD_LOWER" Offset="0xABF4" />
+ <Limb Name="object_death_Standardlimb_00AC00" Type="Standard" EnumName="GOMESS_LIMB_HEAD_UPPER" Offset="0xAC00" />
+ <Limb Name="object_death_Standardlimb_00AC0C" Type="Standard" EnumName="GOMESS_LIMB_8" Offset="0xAC0C" />
+ <Limb Name="object_death_Standardlimb_00AC18" Type="Standard" EnumName="GOMESS_LIMB_9" Offset="0xAC18" />
+ <Limb Name="object_death_Standardlimb_00AC24" Type="Standard" EnumName="GOMESS_LIMB_10" Offset="0xAC24" />
+ <Limb Name="object_death_Standardlimb_00AC30" Type="Standard" EnumName="GOMESS_LIMB_11" Offset="0xAC30" />
+ <Limb Name="object_death_Standardlimb_00AC3C" Type="Standard" EnumName="GOMESS_LIMB_CLOAK_UPPER" Offset="0xAC3C" />
+ <Limb Name="object_death_Standardlimb_00AC48" Type="Standard" EnumName="GOMESS_LIMB_CLOAK_LOWER" Offset="0xAC48" />
+ <Limb Name="object_death_Standardlimb_00AC54" Type="Standard" EnumName="GOMESS_LIMB_UPPER_ARM_LEFT" Offset="0xAC54" />
+ <Limb Name="object_death_Standardlimb_00AC60" Type="Standard" EnumName="GOMESS_LIMB_FOREARM_LEFT" Offset="0xAC60" />
+ <Limb Name="object_death_Standardlimb_00AC6C" Type="Standard" EnumName="GOMESS_LIMB_HAND_LEFT" Offset="0xAC6C" />
+ <Limb Name="object_death_Standardlimb_00AC78" Type="Standard" EnumName="GOMESS_LIMB_UPPER_ARM_RIGHT" Offset="0xAC78" />
+ <Limb Name="object_death_Standardlimb_00AC84" Type="Standard" EnumName="GOMESS_LIMB_FOREARM_RIGHT" Offset="0xAC84" />
+ <Limb Name="object_death_Standardlimb_00AC90" Type="Standard" EnumName="GOMESS_LIMB_HAND_RIGHT" Offset="0xAC90" />
+ <Limb Name="object_death_Standardlimb_00AC9C" Type="Standard" EnumName="GOMESS_LIMB_SCYTHE_HANDLE" Offset="0xAC9C" />
+ <Limb Name="object_death_Standardlimb_00ACA8" Type="Standard" EnumName="GOMESS_LIMB_SCYTHE_BLADE" Offset="0xACA8" />
+ <Skeleton Name="gGomessSkel" Type="Flex" LimbType="Standard" LimbNone="GOMESS_LIMB_NONE" LimbMax="GOMESS_LIMB_MAX" EnumName="GomessSkelLimb" Offset="0xAD08" />
+ <Animation Name="object_death_Anim_00B284" Offset="0xB284" /> <!-- Original name is "d13_gahaha" --> <!-- Intro anim 1 -->
+ <Animation Name="gGomessScytheSpinAnim" Offset="0xB508" /> <!-- Original name is "d13_guard" -->
+ <Animation Name="object_death_Anim_00CB2C" Offset="0xCB2C" /> <!-- Original name is "d13_jakin" --> <!-- Intro anim 2 -->
+ <TextureAnimation Name="gGomessCoreMatAnim" Offset="0xCB84" />
+ <TextureAnimation Name="gGomessBodyMatAnim" Offset="0xCBC0" />
</File>
</Root>
diff --git a/linker_scripts/undefined_syms.ld b/linker_scripts/undefined_syms.ld
index 880773f84..d92b391d1 100644
--- a/linker_scripts/undefined_syms.ld
+++ b/linker_scripts/undefined_syms.ld
@@ -242,27 +242,6 @@ D_06004894 = 0x06004894;
D_060086BC = 0x060086BC;
D_0600C3E0 = 0x0600C3E0;
-// ovl_En_Death
-
-D_06000E64 = 0x06000E64;
-D_060015B4 = 0x060015B4;
-D_06001834 = 0x06001834;
-D_06001F80 = 0x06001F80;
-D_06002DE8 = 0x06002DE8;
-D_0600352C = 0x0600352C;
-D_06003CAC = 0x06003CAC;
-D_06006F88 = 0x06006F88;
-D_060073D0 = 0x060073D0;
-D_06009988 = 0x06009988;
-D_06009BA0 = 0x06009BA0;
-D_06009F10 = 0x06009F10;
-D_0600AD08 = 0x0600AD08;
-D_0600B284 = 0x0600B284;
-D_0600B508 = 0x0600B508;
-D_0600CB2C = 0x0600CB2C;
-D_0600CB84 = 0x0600CB84;
-D_0600CBC0 = 0x0600CBC0;
-
// ovl_En_Knight
D_060005A8 = 0x060005A8;
diff --git a/spec b/spec
index 2144cf439..c9df4a8e1 100644
--- a/spec
+++ b/spec
@@ -1046,17 +1046,14 @@ beginseg
name "ovl_En_Death"
compress
include "$(BUILD_DIR)/src/overlays/actors/ovl_En_Death/z_en_death.o"
- include "$(BUILD_DIR)/data/ovl_En_Death/ovl_En_Death.data.o"
- include "$(BUILD_DIR)/data/ovl_En_Death/ovl_En_Death.reloc.o"
+ include "$(BUILD_DIR)/src/overlays/actors/ovl_En_Death/ovl_En_Death_reloc.o"
endseg
beginseg
name "ovl_En_Minideath"
compress
include "$(BUILD_DIR)/src/overlays/actors/ovl_En_Minideath/z_en_minideath.o"
- include "$(BUILD_DIR)/data/ovl_En_Minideath/ovl_En_Minideath.data.o"
- include "$(BUILD_DIR)/data/ovl_En_Minideath/ovl_En_Minideath.bss.o"
- include "$(BUILD_DIR)/data/ovl_En_Minideath/ovl_En_Minideath.reloc.o"
+ include "$(BUILD_DIR)/src/overlays/actors/ovl_En_Minideath/ovl_En_Minideath_reloc.o"
endseg
beginseg
diff --git a/src/overlays/actors/ovl_En_Death/z_en_death.c b/src/overlays/actors/ovl_En_Death/z_en_death.c
index 0eb9268f7..2f501a35e 100644
--- a/src/overlays/actors/ovl_En_Death/z_en_death.c
+++ b/src/overlays/actors/ovl_En_Death/z_en_death.c
@@ -6,38 +6,57 @@
#include "z_en_death.h"
#include "z64rumble.h"
+#include "overlays/actors/ovl_Arrow_Light/z_arrow_light.h"
+#include "objects/gameplay_keep/gameplay_keep.h"
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_IGNORE_QUAKE)
#define THIS ((EnDeath*)thisx)
-void EnDeath_Init(Actor* thisx, PlayState* play);
+void EnDeath_Init(Actor* thisx, PlayState* play2);
void EnDeath_Destroy(Actor* thisx, PlayState* play);
void EnDeath_Update(Actor* thisx, PlayState* play);
void EnDeath_Draw(Actor* thisx, PlayState* play);
-void func_808C589C(EnDeath* this, PlayState* play);
-void func_808C5AB8(EnDeath* this, PlayState* play);
-void func_808C5CB4(EnDeath* this, PlayState* play);
-void func_808C5E90(EnDeath* this, PlayState* play);
-void func_808C6070(EnDeath* this, PlayState* play);
-void func_808C64DC(EnDeath* this, PlayState* play);
-void func_808C66A8(EnDeath* this, PlayState* play);
-void func_808C682C(EnDeath* this, PlayState* play);
-void func_808C692C(EnDeath* this, PlayState* play);
-void func_808C6AB0(EnDeath* this, PlayState* play);
-void func_808C6CDC(EnDeath* this, PlayState* play);
-void func_808C6F6C(EnDeath* this, PlayState* play);
-void func_808C72AC(EnDeath* this, PlayState* play);
-void func_808C74F8(EnDeath* this, PlayState* play);
-void func_808C7888(EnDeath* this, PlayState* play);
-void func_808C7AAC(EnDeath* this, PlayState* play);
-void func_808C7B88(EnDeath* this, PlayState* play);
-void func_808C7C88(EnDeath* this, PlayState* play);
-void func_808C7D34(EnDeath* this, PlayState* play);
-void func_808C7DCC(EnDeath* this, PlayState* play);
-
-#if 0
+void EnDeath_IntroCutscenePart1(EnDeath* this, PlayState* play);
+void EnDeath_IntroCutscenePart2(EnDeath* this, PlayState* play);
+void EnDeath_IntroCutscenePart3(EnDeath* this, PlayState* play);
+void EnDeath_IntroCutscenePart4(EnDeath* this, PlayState* play);
+void EnDeath_IntroCutscenePart5(EnDeath* this, PlayState* play);
+void EnDeath_ApproachPlayer(EnDeath* this, PlayState* play);
+void EnDeath_SwingAttack(EnDeath* this, PlayState* play);
+void EnDeath_EndSwingAttack(EnDeath* this, PlayState* play);
+void EnDeath_BlockProjectile(EnDeath* this, PlayState* play);
+void EnDeath_SpinAttack(EnDeath* this, PlayState* play);
+void EnDeath_Damaged(EnDeath* this, PlayState* play);
+void EnDeath_DeathCutscenePart1(EnDeath* this, PlayState* play);
+void EnDeath_DeathCutscenePart2(EnDeath* this, PlayState* play);
+void EnDeath_DeathCutscenePart3(EnDeath* this, PlayState* play);
+void EnDeath_DeathCutscenePart4(EnDeath* this, PlayState* play);
+void EnDeath_Dead(EnDeath* this, PlayState* play);
+void EnDeath_StartBatSwarm(EnDeath* this, PlayState* play);
+void EnDeath_BatSwarm(EnDeath* this, PlayState* play);
+void EnDeath_PlayCutscene(EnDeath* this, PlayState* play);
+void EnDeath_BeginWithoutCutscene(EnDeath* this, PlayState* play);
+
+void EnDeath_SetupIntroCutscenePart2(EnDeath* this, PlayState* play);
+void EnDeath_SetupIntroCutscenePart3(EnDeath* this);
+void EnDeath_SetupIntroCutscenePart4(EnDeath* this, PlayState* play);
+void EnDeath_SetupIntroCutscenePart5(EnDeath* this, PlayState* play);
+void EnDeath_SetupApproachPlayer(EnDeath* this);
+void EnDeath_SetupSwingAttack(EnDeath* this);
+void EnDeath_SetupEndSwingAttack(EnDeath* this);
+void EnDeath_SetupBlockProjectile(EnDeath* this);
+void EnDeath_SetupSpinAttack(EnDeath* this);
+void EnDeath_SetupDeathCutscenePart2(EnDeath* this, PlayState* play);
+void EnDeath_SetupDeathCutscenePart3(EnDeath* this);
+void EnDeath_SetupDead(EnDeath* this, PlayState* play);
+void EnDeath_SetupStartBatSwarm(EnDeath* this);
+void EnDeath_SetupBatSwarm(EnDeath* this);
+void EnDeath_SetupPlayCutscene(EnDeath* this);
+void EnDeath_SetupBeginWithoutCutscene(EnDeath* this);
+void EnDeath_SetupDeathCutscenePart4(EnDeath* this);
+
ActorInit En_Death_InitVars = {
/**/ ACTOR_EN_DEATH,
/**/ ACTORCAT_ENEMY,
@@ -50,230 +69,1690 @@ ActorInit En_Death_InitVars = {
/**/ EnDeath_Draw,
};
-// static ColliderSphereInit sSphereInit = {
-static ColliderSphereInit D_808C98E0 = {
- { COLTYPE_HIT3, AT_NONE, AC_NONE | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_SPHERE, },
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
+static ColliderSphereInit sSphereInit = {
+ {
+ COLTYPE_HIT3,
+ AT_NONE,
+ AC_NONE | AC_TYPE_PLAYER,
+ OC1_NONE,
+ OC2_TYPE_1,
+ COLSHAPE_SPHERE,
+ },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
{ 1, { { 0, 0, 0 }, 22 }, 100 },
};
-// static ColliderCylinderInit sCylinderInit = {
-static ColliderCylinderInit D_808C990C = {
- { COLTYPE_NONE, AT_NONE, AC_NONE, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, },
- { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_ON, },
+static ColliderCylinderInit sCylinderInit = {
+ {
+ COLTYPE_NONE,
+ AT_NONE,
+ AC_NONE,
+ OC1_ON | OC1_TYPE_ALL,
+ OC2_TYPE_1,
+ COLSHAPE_CYLINDER,
+ },
+ {
+ ELEMTYPE_UNK0,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00000000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_NONE,
+ OCELEM_ON,
+ },
{ 35, 90, 20, { 0, 0, 0 } },
};
-// static ColliderTrisElementInit sTrisElementsInit[2] = {
-static ColliderTrisElementInit D_808C9938[2] = {
+static ColliderTrisElementInit sTrisElementsInit[2] = {
{
- { ELEMTYPE_UNK2, { 0xF7CFFFFF, 0x04, 0x20 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
+ {
+ ELEMTYPE_UNK2,
+ { 0xF7CFFFFF, 0x04, 0x20 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
{ { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } },
},
{
- { ELEMTYPE_UNK2, { 0xF7CFFFFF, 0x04, 0x20 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
+ {
+ ELEMTYPE_UNK2,
+ { 0xF7CFFFFF, 0x04, 0x20 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
{ { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } },
},
};
-// static ColliderTrisInit sTrisInit = {
-static ColliderTrisInit D_808C99B0 = {
- { COLTYPE_METAL, AT_ON | AT_TYPE_ENEMY, AC_ON | AC_HARD | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_TRIS, },
- ARRAY_COUNT(sTrisElementsInit), D_808C9938, // sTrisElementsInit,
+static ColliderTrisInit sTrisInit = {
+ {
+ COLTYPE_METAL,
+ AT_ON | AT_TYPE_ENEMY,
+ AC_ON | AC_HARD | AC_TYPE_PLAYER,
+ OC1_NONE,
+ OC2_TYPE_1,
+ COLSHAPE_TRIS,
+ },
+ ARRAY_COUNT(sTrisElementsInit),
+ sTrisElementsInit,
};
-// static ColliderQuadInit sQuadInit = {
-static ColliderQuadInit D_808C99C0 = {
- { COLTYPE_NONE, AT_NONE | AT_TYPE_ENEMY, AC_NONE, OC1_NONE, OC2_TYPE_2, COLSHAPE_QUAD, },
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x04, 0x20 }, { 0x00000000, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NORMAL | TOUCH_UNK7, BUMP_NONE, OCELEM_NONE, },
+static ColliderQuadInit sQuadInit = {
+ {
+ COLTYPE_NONE,
+ AT_NONE | AT_TYPE_ENEMY,
+ AC_NONE,
+ OC1_NONE,
+ OC2_TYPE_2,
+ COLSHAPE_QUAD,
+ },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x04, 0x20 },
+ { 0x00000000, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NORMAL | TOUCH_UNK7,
+ BUMP_NONE,
+ OCELEM_NONE,
+ },
{ { { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f }, { 0.0f, 0.0f, 0.0f } } },
};
-// static DamageTable sDamageTable = {
-static DamageTable D_808C9A10 = {
- /* Deku Nut */ DMG_ENTRY(0, 0x0),
- /* Deku Stick */ DMG_ENTRY(1, 0x0),
- /* Horse trample */ DMG_ENTRY(0, 0x0),
- /* Explosives */ DMG_ENTRY(1, 0xF),
- /* Zora boomerang */ DMG_ENTRY(1, 0x0),
- /* Normal arrow */ DMG_ENTRY(1, 0x0),
- /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0),
- /* Hookshot */ DMG_ENTRY(1, 0x0),
- /* Goron punch */ DMG_ENTRY(1, 0x0),
- /* Sword */ DMG_ENTRY(1, 0x0),
- /* Goron pound */ DMG_ENTRY(0, 0x0),
- /* Fire arrow */ DMG_ENTRY(1, 0x2),
- /* Ice arrow */ DMG_ENTRY(1, 0x3),
- /* Light arrow */ DMG_ENTRY(2, 0x4),
- /* Goron spikes */ DMG_ENTRY(1, 0x0),
- /* Deku spin */ DMG_ENTRY(0, 0x0),
- /* Deku bubble */ DMG_ENTRY(1, 0x0),
- /* Deku launch */ DMG_ENTRY(2, 0x0),
- /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x0),
- /* Zora barrier */ DMG_ENTRY(0, 0x0),
- /* Normal shield */ DMG_ENTRY(0, 0x0),
- /* Light ray */ DMG_ENTRY(0, 0x0),
- /* Thrown object */ DMG_ENTRY(1, 0x0),
- /* Zora punch */ DMG_ENTRY(1, 0x0),
- /* Spin attack */ DMG_ENTRY(1, 0x0),
- /* Sword beam */ DMG_ENTRY(0, 0x0),
- /* Normal Roll */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0),
- /* Unblockable */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0),
- /* Powder Keg */ DMG_ENTRY(1, 0xF),
+typedef enum {
+ /* 0x0 */ DMGEFF_NONE = 0,
+ /* 0x2 */ DMGEFF_FIRE_ARROW = 2,
+ /* 0x3 */ DMGEFF_ICE_ARROW,
+ /* 0x4 */ DMGEFF_LIGHT_ARROW,
+ /* 0xF */ DMGEFF_EXPLOSIVES = 15
+} EnDeathDamageEffect;
+
+static DamageTable sDamageTable = {
+ /* Deku Nut */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Deku Stick */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Horse trample */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Explosives */ DMG_ENTRY(1, DMGEFF_EXPLOSIVES),
+ /* Zora boomerang */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Normal arrow */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* UNK_DMG_0x06 */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Hookshot */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Goron punch */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Sword */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Goron pound */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Fire arrow */ DMG_ENTRY(1, DMGEFF_FIRE_ARROW),
+ /* Ice arrow */ DMG_ENTRY(1, DMGEFF_ICE_ARROW),
+ /* Light arrow */ DMG_ENTRY(2, DMGEFF_LIGHT_ARROW),
+ /* Goron spikes */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Deku spin */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Deku bubble */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Deku launch */ DMG_ENTRY(2, DMGEFF_NONE),
+ /* UNK_DMG_0x12 */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Zora barrier */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Normal shield */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Light ray */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Thrown object */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Zora punch */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Spin attack */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Sword beam */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Normal Roll */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* UNK_DMG_0x1B */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* UNK_DMG_0x1C */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Unblockable */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* UNK_DMG_0x1E */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Powder Keg */ DMG_ENTRY(1, DMGEFF_EXPLOSIVES),
};
-// sColChkInfoInit
-static CollisionCheckInfoInit2 D_808C9A30 = { 20, 28, 90, 20, 100 };
+static CollisionCheckInfoInit2 sColChkInfoInit = { 20, 28, 90, 20, 100 };
-// static InitChainEntry sInitChain[] = {
-static InitChainEntry D_808C9A60[] = {
+static EffectBlureInit2 sBlureInit = {
+ 0, 8, 0, { 100, 50, 100, 200 }, { 100, 0, 0, 64 }, { 100, 0, 0, 20 }, { 50, 0, 0, 0 }, 8,
+ 0, 2, 0, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
+};
+
+static InitChainEntry sInitChain[] = {
ICHAIN_VEC3F(scale, 0, ICHAIN_CONTINUE),
ICHAIN_S8(hintId, TATL_HINT_ID_GOMESS, ICHAIN_CONTINUE),
ICHAIN_F32(targetArrowOffset, 6000, ICHAIN_CONTINUE),
ICHAIN_U8(targetMode, TARGET_MODE_5, ICHAIN_STOP),
};
-#endif
-
-extern ColliderSphereInit D_808C98E0;
-extern ColliderCylinderInit D_808C990C;
-extern ColliderTrisElementInit D_808C9938[2];
-extern ColliderTrisInit D_808C99B0;
-extern ColliderQuadInit D_808C99C0;
-extern DamageTable D_808C9A10;
-extern CollisionCheckInfoInit2 D_808C9A30;
-extern InitChainEntry D_808C9A60[];
-
-extern UNK_TYPE D_06000E64;
-extern UNK_TYPE D_060015B4;
-extern UNK_TYPE D_06001834;
-extern UNK_TYPE D_06001F80;
-extern UNK_TYPE D_06002DE8;
-extern UNK_TYPE D_0600352C;
-extern UNK_TYPE D_06003CAC;
-extern UNK_TYPE D_06006F88;
-extern UNK_TYPE D_060073D0;
-extern UNK_TYPE D_06009988;
-extern UNK_TYPE D_06009F10;
-extern UNK_TYPE D_0600B284;
-extern UNK_TYPE D_0600B508;
-extern UNK_TYPE D_0600CB2C;
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/EnDeath_Init.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/EnDeath_Destroy.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5310.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5394.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5428.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C54F0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C566C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C571C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C589C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C597C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5AB8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5C0C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5CB4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5D6C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5E90.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5F58.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6070.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C645C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C64DC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6620.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C66A8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C67C8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C682C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C68B8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C692C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6A08.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6AB0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6C5C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6CDC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6D40.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6F6C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C70D8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C72AC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C74A4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C74F8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7800.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7888.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7A30.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7AAC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7AEC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7B88.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7C04.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7C88.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7CFC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7D34.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7DB8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7DCC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7E24.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7EDC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/EnDeath_Update.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C84A4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C8690.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C882C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C8D18.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C9160.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C9220.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C9340.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/EnDeath_Draw.s")
+void EnDeath_Init(Actor* thisx, PlayState* play2) {
+ EnDeath* this = THIS;
+ PlayState* play = play2;
+ f32 yOffset = 15.0f;
+ s16 yRot = 0;
+ s32 i;
+
+ Actor_ProcessInitChain(&this->actor, sInitChain);
+ ActorShape_Init(&this->actor.shape, 5500.0f, ActorShadow_DrawCircle, 80.0f);
+
+ SkelAnime_InitFlex(play, &this->skelAnime, &gGomessSkel, &gGomessFloatAnim, this->jointTable, this->morphTable,
+ GOMESS_LIMB_MAX);
+
+ Collider_InitAndSetSphere(play, &this->coreCollider, &this->actor, &sSphereInit);
+ Collider_InitAndSetCylinder(play, &this->bodyCollider, &this->actor, &sCylinderInit);
+ Collider_InitAndSetQuad(play, &this->weaponCollider, &this->actor, &sQuadInit);
+ Collider_InitAndSetTris(play, &this->weaponSpinningCollider, &this->actor, &sTrisInit,
+ this->weaponSpinningColliderElements);
+
+ this->coreCollider.dim.worldSphere.radius = this->coreCollider.dim.modelSphere.radius;
+
+ CollisionCheck_SetInfo2(&this->actor.colChkInfo, &sDamageTable, &sColChkInfoInit);
+
+ Effect_Add(play, &this->effectIndex, EFFECT_BLURE2, 0, 0, &sBlureInit);
+
+ if (!CHECK_EVENTINF(EVENTINF_INTRO_CS_WATCHED_GOMESS)) {
+ this->actor.world.pos.y += 400.0f;
+ }
+
+ // Spawn each bat as a child
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i] = (EnMinideath*)Actor_SpawnAsChild(
+ &play->actorCtx, &this->actor, play, ACTOR_EN_MINIDEATH, this->actor.world.pos.x,
+ this->actor.world.pos.y + yOffset, this->actor.world.pos.z, 0, yRot, 0, i);
+ if (this->miniDeaths[i] == NULL) {
+ Actor_Kill(&this->actor);
+ }
+ yRot += 0x3A00;
+ yOffset += 4.0f;
+ }
+
+ // Make the ith bat a child of the (i+1)th bat
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths) - 1; i++) {
+ this->miniDeaths[i]->actor.child = &this->miniDeaths[i + 1]->actor;
+ }
+
+ this->bodyMatAnim = Lib_SegmentedToVirtual(&gGomessBodyMatAnim);
+ this->coreMatAnim = Lib_SegmentedToVirtual(&gGomessCoreMatAnim);
+
+ if (CHECK_EVENTINF(EVENTINF_INTRO_CS_WATCHED_GOMESS)) {
+ // Watched intro cutscene
+ this->holdsScythe = true;
+ Actor_SetScale(&this->actor, 0.01f);
+ this->matAnimStep = 23;
+ this->actor.params = 20;
+ this->scytheScale = 1.0f;
+ EnDeath_SetupBeginWithoutCutscene(this);
+ } else {
+ // Start intro cutscene
+ this->inEarlyIntro = true;
+ this->actor.flags &= ~ACTOR_FLAG_TARGETABLE;
+ EnDeath_SetupPlayCutscene(this);
+ }
+}
+
+void EnDeath_Destroy(Actor* thisx, PlayState* play) {
+ EnDeath* this = THIS;
+
+ Collider_DestroySphere(play, &this->coreCollider);
+ Collider_DestroyCylinder(play, &this->bodyCollider);
+ Collider_DestroyQuad(play, &this->weaponCollider);
+ Collider_DestroyTris(play, &this->weaponSpinningCollider);
+ AudioSfx_StopByPos(&this->scytheScreenPos);
+ Effect_Destroy(play, this->effectIndex);
+}
+
+void EnDeath_DimLights(PlayState* play) {
+ EnvLightSettings* lightSettings;
+ s32 i;
+
+ play->envCtx.lightSettingOverride = 20;
+ play->envCtx.lightSetting = 20;
+ play->envCtx.prevLightSetting = 20;
+ play->envCtx.lightBlend = 1.0f;
+ lightSettings = &play->envCtx.lightSettingsList[20];
+
+ for (i = 0; i < 3; i++) {
+ lightSettings->light1Dir[i] = play->envCtx.lightSettings.light1Dir[i];
+ lightSettings->light2Dir[i] = play->envCtx.lightSettings.light2Dir[i];
+ }
+}
+
+void EnDeath_Float(EnDeath* this) {
+ Actor_PlaySfx_Flagged(&this->actor, NA_SE_EN_SHARP_FLOAT - SFX_FLAG);
+
+ if (this->floatTimer == 0) {
+ this->floatTimer = 40;
+ }
+ this->floatTimer--;
+ this->actor.world.pos.y = this->actor.home.pos.y + (1.0f - Math_CosS(this->floatTimer * 0x666)) * 7.5f;
+}
+
+s32 EnDeath_ProjectileApproaching(EnDeath* this, PlayState* play) {
+ Actor* projectileActor =
+ func_800BC270(play, &this->actor, 80.0f, 0x10000 | 0x2000 | 0x1000 | 0x800 | 0x80 | 0x20 | 0x10);
+ s16 angle;
+
+ if (projectileActor != NULL) {
+ angle = Actor_WorldYawTowardActor(&this->actor, projectileActor) - this->actor.shape.rot.y;
+
+ if (ABS_ALT(angle) < 0x2000) {
+ angle = Actor_WorldPitchTowardPoint(projectileActor, &this->actor.focus.pos) - projectileActor->world.rot.x;
+
+ if (ABS_ALT(angle) < 0x3000) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+void EnDeath_UpdateSpinAttackTris(EnDeath* this) {
+ f32 sinRotY = Math_SinS(this->actor.shape.rot.y);
+ f32 cosRotY = Math_CosS(this->actor.shape.rot.y);
+ Vec3f p3;
+ Vec3f p2;
+ Vec3f p1;
+
+ p1.x = this->actor.world.pos.x - 70.0f * cosRotY + 75.0f * sinRotY;
+ p1.y = this->actor.world.pos.y + -10.0f;
+ p1.z = this->actor.world.pos.z + 70.0f * sinRotY + 75.0f * cosRotY;
+
+ p2.x = this->actor.world.pos.x + 70.0f * cosRotY + 65.0f * sinRotY;
+ p2.y = p1.y + 150.0f;
+ p2.z = this->actor.world.pos.z - 70.0f * sinRotY + 65.0f * cosRotY;
+
+ p3.x = p1.x;
+ p3.x += -10.0f * sinRotY;
+ p3.y = p2.y;
+ p3.z = p1.z;
+ p3.z += -10.0f * cosRotY;
+ Collider_SetTrisVertices(&this->weaponSpinningCollider, 0, &p1, &p2, &p3);
+
+ p3.x = p2.x;
+ p3.x += 10.0f * sinRotY;
+ p3.y = p1.y;
+ p3.z = p2.z;
+ p3.z += 10.0f * cosRotY;
+ Collider_SetTrisVertices(&this->weaponSpinningCollider, 1, &p1, &p3, &p2);
+}
+
+f32 EnDeath_UpdateCoreVelocityAndRotation(EnDeath* this) {
+ f32 tmp;
+
+ this->coreVelocity = this->actor.world.pos.y - this->actor.home.pos.y;
+ this->coreVelocity = CLAMP_MIN(this->coreVelocity, 0.0f);
+ this->coreVelocity *= 0.02f;
+ this->coreVelocity = SQ(this->coreVelocity) * 3.0f + 80.0f;
+
+ tmp = 22.5f / (this->coreVelocity * (2 * M_PIf));
+ this->coreRotation += TRUNCF_BINANG(0x10000 * tmp);
+}
+
+void EnDeath_SetupIntroCutscenePart1(EnDeath* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+ Vec3f eye;
+ Vec3f at;
+
+ this->actor.shape.rot.y = this->actor.shape.rot.y - 0x657A;
+ this->actionTimer = 60;
+
+ eye.x = (Math_SinS(this->actor.home.rot.y + 0x98) * 542.0f) + this->actor.world.pos.x;
+ eye.z = (Math_CosS(this->actor.home.rot.y + 0x98) * 542.0f) + this->actor.world.pos.z;
+ eye.y = this->actor.home.pos.y + 3.0f;
+
+ at.x = this->actor.world.pos.x;
+ at.z = this->actor.world.pos.z;
+ at.y = this->actor.world.pos.y - 116.0f;
+
+ player->actor.world.pos.x = Math_SinS(this->actor.home.rot.y - 0x370) * 463.0f + this->actor.world.pos.x;
+ player->actor.world.pos.z = Math_CosS(this->actor.home.rot.y - 0x370) * 463.0f + this->actor.world.pos.z;
+ player->actor.shape.rot.y = Actor_WorldYawTowardActor(&player->actor, &this->actor);
+
+ Play_SetCameraAtEye(play, this->camId, &at, &eye);
+ Play_SetCameraFov(play, this->camId, 77.0f);
+ Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_21);
+
+ this->actionFunc = EnDeath_IntroCutscenePart1;
+}
+
+void EnDeath_IntroCutscenePart1(EnDeath* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+
+ player->actor.world.pos.x = Math_SinS(this->actor.home.rot.y - 0x370) * 463.0f + this->actor.world.pos.x;
+ player->actor.world.pos.z = Math_CosS(this->actor.home.rot.y - 0x370) * 463.0f + this->actor.world.pos.z;
+ player->actor.shape.rot.y = Actor_WorldYawTowardActor(&player->actor, &this->actor);
+
+ if (this->actionTimer == 25) {
+ Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_81);
+ }
+ if (this->actionTimer > 0) {
+ this->actionTimer--;
+ } else {
+ EnDeath_SetupIntroCutscenePart2(this, play);
+ }
+ EnDeath_UpdateCoreVelocityAndRotation(this);
+}
+
+void EnDeath_SetupIntroCutscenePart2(EnDeath* this, PlayState* play) {
+ Camera* camera = Play_GetCamera(play, this->camId);
+ s32 i;
+
+ EnDeath_DimLights(play);
+
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_INTRO_1;
+ }
+
+ this->actionTimer = 50;
+ this->camEyeTarget.x = Math_SinS(this->actor.home.rot.y) * 140.0f + this->actor.world.pos.x;
+ this->camEyeTarget.z = Math_CosS(this->actor.home.rot.y) * 140.0f + this->actor.world.pos.z;
+ this->camEyeTarget.y = this->actor.home.pos.y + 20.0f;
+ this->camAtTarget.x = this->actor.world.pos.x;
+ this->camAtTarget.z = this->actor.world.pos.z;
+ this->camAtTarget.y = this->actor.home.pos.y + 50.0f;
+ this->camEyeSpeed = Math_Vec3f_DistXYZ(&camera->eye, &this->camEyeTarget) * 0.0225f;
+ this->camAtSpeed = Math_Vec3f_DistXYZ(&camera->at, &this->camAtTarget) * 0.0225f;
+ this->actionFunc = EnDeath_IntroCutscenePart2;
+}
+
+void EnDeath_IntroCutscenePart2(EnDeath* this, PlayState* play) {
+ Camera* camera = Play_GetCamera(play, this->camId);
+
+ if (this->actionTimer == 42) {
+ Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_4);
+ } else if (this->actionTimer == 27) {
+ Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_123);
+ }
+ if (this->actionTimer <= 0) {
+ if (this->actor.world.pos.y < (this->actor.home.pos.y + 400.0f) - 225.0f) {
+ play->envCtx.lightSettingOverride = 26;
+ }
+ Math_Vec3f_StepTo(&camera->eye, &this->camEyeTarget, this->camEyeSpeed);
+ Math_Vec3f_StepTo(&camera->at, &this->camAtTarget, this->camAtSpeed);
+ Play_SetCameraAtEye(play, this->camId, &camera->at, &camera->eye);
+ if (Math_StepToF(&this->actor.world.pos.y, this->actor.home.pos.y, 9.0f) != 0) {
+ this->actionTimer--;
+ if (this->actionTimer == -20) {
+ EnDeath_SetupIntroCutscenePart3(this);
+ }
+ }
+ } else {
+ this->actionTimer--;
+ }
+ EnDeath_UpdateCoreVelocityAndRotation(this);
+}
+
+void EnDeath_SetupIntroCutscenePart3(EnDeath* this) {
+ SET_EVENTINF(EVENTINF_INTRO_CS_WATCHED_GOMESS);
+ Animation_Change(&this->skelAnime, &object_death_Anim_00B284, 0.0f, 0.0f,
+ Animation_GetLastFrame(&object_death_Anim_00B284), ANIMMODE_ONCE, 0.0f);
+ this->actor.scale.y = 0.01f;
+ this->actor.shape.rot.y += 0x777F;
+ Actor_PlaySfx(&this->actor, NA_SE_EN_DEATH_APPEAR);
+ this->actionFunc = EnDeath_IntroCutscenePart3;
+}
+
+void EnDeath_IntroCutscenePart3(EnDeath* this, PlayState* play) {
+ s32 stepDone = Math_StepToF(&this->actor.scale.x, 0.01f, 0.0005f);
+ f32 temp;
+
+ this->actor.scale.z = this->actor.scale.x;
+ temp = 0.01f - this->actor.scale.x;
+ if (temp > 0.0025f) {
+ temp = 0.0025f;
+ }
+ this->actor.shape.rot.y += TRUNCF_BINANG(temp * 0x44C000);
+ if (stepDone) {
+ this->inEarlyIntro = false;
+ EnDeath_SetupIntroCutscenePart4(this, play);
+ }
+ EnDeath_UpdateCoreVelocityAndRotation(this);
+}
+
+void EnDeath_SetupIntroCutscenePart4(EnDeath* this, PlayState* play) {
+ Camera* camera = Play_GetCamera(play, this->camId);
+ f32 invAnimDuration = 1.0f / Animation_GetLastFrame(&object_death_Anim_00B284);
+
+ this->actionTimer = 10;
+ this->skelAnime.playSpeed = 1.0f;
+ this->actor.shape.rot.y = this->actor.home.rot.y;
+ this->camEyeTarget.x = Math_SinS(this->actor.home.rot.y) * 50.0f + this->actor.world.pos.x;
+ this->camEyeTarget.z = Math_CosS(this->actor.home.rot.y) * 50.0f + this->actor.world.pos.z;
+ this->camEyeTarget.y = this->actor.home.pos.y + 95.0f;
+ this->camAtTarget.x = this->actor.world.pos.x;
+ this->camAtTarget.z = this->actor.world.pos.z;
+ this->camAtTarget.y = this->actor.world.pos.y + 100.0f;
+ this->camEyeSpeed = Math_Vec3f_DistXYZ(&camera->eye, &this->camEyeTarget) * invAnimDuration;
+ this->camAtSpeed = Math_Vec3f_DistXYZ(&camera->at, &this->camAtTarget) * invAnimDuration;
+
+ this->actionFunc = EnDeath_IntroCutscenePart4;
+}
+
+void EnDeath_IntroCutscenePart4(EnDeath* this, PlayState* play) {
+ Camera* camera = Play_GetCamera(play, this->camId);
+
+ if (this->matAnimStep < 23) {
+ this->matAnimStep++;
+ }
+ Math_Vec3f_StepTo(&camera->eye, &this->camEyeTarget, this->camEyeSpeed);
+ Math_Vec3f_StepTo(&camera->at, &this->camAtTarget, this->camAtSpeed);
+ Play_SetCameraAtEye(play, this->camId, &camera->at, &camera->eye);
+ if (SkelAnime_Update(&this->skelAnime)) {
+ if (this->actionTimer > 0) {
+ this->actionTimer--;
+ } else {
+ EnDeath_SetupIntroCutscenePart5(this, play);
+ }
+ }
+ EnDeath_UpdateCoreVelocityAndRotation(this);
+}
+
+void EnDeath_SetupIntroCutscenePart5(EnDeath* this, PlayState* play) {
+ Camera* camera = Play_GetCamera(play, this->camId);
+
+ Animation_PlayOnce(&this->skelAnime, &object_death_Anim_00CB2C);
+ this->matAnimStep = 23;
+ Audio_PlayBgm_StorePrevBgm(NA_BGM_MINI_BOSS);
+ this->camEyeTarget.x = Math_SinS(this->actor.home.rot.y) * 230.0f + this->actor.world.pos.x;
+ this->camEyeTarget.z = Math_CosS(this->actor.home.rot.y) * 230.0f + this->actor.world.pos.z;
+ this->camEyeTarget.y = this->actor.home.pos.y + 40.0f;
+ this->camAtTarget.y = this->actor.world.pos.y + 85.0f;
+ this->camEyeSpeed = Math_Vec3f_DistXYZ(&camera->eye, &this->camEyeTarget) * (1.0f / 7.0f);
+ this->camAtSpeed = Math_Vec3f_DistXYZ(&camera->at, &this->camAtTarget) * (1.0f / 7.0f);
+ Audio_PlaySfx_AtPos(&this->scytheScreenPos, NA_SE_EN_DEATH_VOICE);
+ this->actionFunc = EnDeath_IntroCutscenePart5;
+}
+
+void EnDeath_IntroCutscenePart5(EnDeath* this, PlayState* play) {
+ Camera* camera = Play_GetCamera(play, this->camId);
+ f32 scale;
+
+ if (Animation_OnFrame(&this->skelAnime, 12.0f)) {
+ play->envCtx.lightSettingOverride = 27;
+ } else if (Animation_OnFrame(&this->skelAnime, 25.0f)) {
+ play->envCtx.lightSettingOverride = 26;
+ } else if (Animation_OnFrame(&this->skelAnime, 38.0f)) {
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_INTRO_3;
+ }
+ } else if (Animation_OnFrame(&this->skelAnime, 14.0f)) {
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_INTRO_2;
+ this->miniDeaths[i]->actor.world.pos.x =
+ (this->miniDeaths[i]->actor.world.pos.x - this->actor.world.pos.x) * 1.8f + this->actor.world.pos.x;
+ this->miniDeaths[i]->actor.world.pos.z =
+ (this->miniDeaths[i]->actor.world.pos.z - this->actor.world.pos.z) * 1.8f + this->actor.world.pos.z;
+ this->miniDeaths[i]->actor.world.pos.y =
+ (this->miniDeaths[i]->actor.world.pos.y - this->actor.world.pos.y) * 1.7f + this->actor.world.pos.y;
+ }
+ this->holdsScythe = true;
+ this->scytheScale = 1.0f;
+ }
+ Math_Vec3f_StepTo(&camera->eye, &this->camEyeTarget, this->camEyeSpeed);
+ Math_Vec3f_StepTo(&camera->at, &this->camAtTarget, this->camAtSpeed);
+ Math_StepToF(&camera->fov, 60.0f, 2.4285715f);
+ Play_SetCameraFov(play, this->camId, camera->fov);
+ Play_SetCameraAtEye(play, this->camId, &camera->at, &camera->eye);
+
+ scale = CLAMP(this->skelAnime.curFrame, 10.0f, 14.0f) - 10.0f;
+ this->scytheScale = scale * 0.25f;
+ if (scale < 14.0f) {
+ EnDeath_UpdateCoreVelocityAndRotation(this);
+ }
+ if (SkelAnime_Update(&this->skelAnime)) {
+ CutsceneManager_Stop(this->actor.csId);
+ Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_END);
+ this->actor.flags |= ACTOR_FLAG_TARGETABLE;
+ this->coreCollider.base.acFlags |= AC_ON;
+ EnDeath_SetupApproachPlayer(this);
+ }
+}
+
+void EnDeath_SetupApproachPlayer(EnDeath* this) {
+ Animation_MorphToLoop(&this->skelAnime, &gGomessFloatAnim, 10.0f);
+
+ this->actor.speed = 1.5f;
+ if (this->actionFunc == EnDeath_EndSwingAttack || this->actionFunc == EnDeath_SpinAttack) {
+ this->actionTimer = 140;
+ } else {
+ this->actionTimer = 100;
+ }
+ this->actionFunc = EnDeath_ApproachPlayer;
+}
+
+void EnDeath_ApproachPlayer(EnDeath* this, PlayState* play) {
+ if (play->envCtx.lightSettingOverride == 20) {
+ play->envCtx.lightSettingOverride = 26;
+ }
+ EnDeath_Float(this);
+ SkelAnime_Update(&this->skelAnime);
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 8, 0x1000, 0x100);
+
+ if (this->actionTimer > 0) {
+ this->actionTimer--;
+ }
+ if (this->actor.params < 5 && Rand_ZeroOne() < 0.4f && EnDeath_ProjectileApproaching(this, play)) {
+ EnDeath_SetupBlockProjectile(this);
+ } else if (this->actionTimer < 100 && this->actor.xzDistToPlayer < 200.0f) {
+ EnDeath_SetupSwingAttack(this);
+ } else if (this->actionTimer == 0) {
+ if (this->actor.params >= 5) {
+ EnDeath_SetupStartBatSwarm(this);
+ } else {
+ EnDeath_SetupSpinAttack(this);
+ }
+ }
+}
+
+void EnDeath_SetupSwingAttack(EnDeath* this) {
+ Animation_Change(&this->skelAnime, &gGomessScytheSwingAnim, 1.0f, 0.0f, 10.0f, ANIMMODE_ONCE, -3.0f);
+ this->actionTimer = 0;
+ this->floatTimer = 0;
+ this->actor.speed = 8.0f;
+ Actor_PlaySfx(&this->actor, NA_SE_EN_DEATH_ATTACK);
+ this->actionFunc = EnDeath_SwingAttack;
+}
+
+void EnDeath_SwingAttack(EnDeath* this, PlayState* play) {
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 4, 0x1000, 0x200);
+ Math_StepToF(&this->actor.world.pos.y, this->actor.home.pos.y, 3.0f);
+ this->actor.shape.rot.x = TRUNCF_BINANG((100.0f - this->actor.xzDistToPlayer) * 0.01f * 0x400);
+ this->actor.shape.rot.x = CLAMP_MIN(this->actor.shape.rot.x, 0);
+
+ if (this->actionTimer > 0) {
+ this->actionTimer++;
+ if (this->actionTimer == 3) {
+ EnDeath_SetupEndSwingAttack(this);
+ }
+ } else if (SkelAnime_Update(&this->skelAnime) && this->actor.xzDistToPlayer < 100.0f) {
+ Audio_PlaySfx_AtPos(&this->scytheScreenPos, NA_SE_EN_DEATH_SCYTHE);
+ this->actionTimer++;
+ this->actor.speed = 0.0f;
+ }
+}
+
+void EnDeath_SetupEndSwingAttack(EnDeath* this) {
+ this->skelAnime.endFrame = Animation_GetLastFrame(&gGomessScytheSwingAnim);
+ this->actionTimer = 0;
+ this->weaponColliderLastUpdateTime = -1;
+ this->unk_18C = true;
+ this->actionFunc = EnDeath_EndSwingAttack;
+ this->actor.speed = 0.0f;
+}
+
+void EnDeath_EndSwingAttack(EnDeath* this, PlayState* play) {
+ this->actionTimer++;
+ if (this->skelAnime.curFrame > 20.0f) {
+ this->unk_18C = false;
+ this->weaponCollider.base.atFlags &= ~AT_ON;
+ Math_ScaledStepToS(&this->actor.shape.rot.x, 0, 0x200);
+ }
+ if (SkelAnime_Update(&this->skelAnime)) {
+ this->actor.shape.rot.x = 0;
+ EnDeath_SetupApproachPlayer(this);
+ }
+}
+
+void EnDeath_SetupBlockProjectile(EnDeath* this) {
+ Animation_MorphToLoop(&this->skelAnime, &gGomessScytheSpinAnim, -3.0f);
+ this->weaponColliderLastUpdateTime = 31;
+ this->actionTimer = 30;
+ this->actor.speed = 0.0f;
+ EnDeath_UpdateSpinAttackTris(this);
+ this->unk_18C = true;
+ this->numScytheAfterImages = -3;
+ this->actionFunc = EnDeath_BlockProjectile;
+}
+
+void EnDeath_BlockProjectile(EnDeath* this, PlayState* play) {
+ EnDeath_Float(this);
+
+ this->actionTimer--;
+ if (this->numScytheAfterImages < 7) {
+ this->numScytheAfterImages++;
+ }
+ SkelAnime_Update(&this->skelAnime);
+ if (Animation_OnFrame(&this->skelAnime, 0.0f)) {
+ Audio_PlaySfx_AtPos(&this->scytheScreenPos, NA_SE_EN_DEATH_ROLL);
+ }
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 8, 0x1000, 0x100);
+ EnDeath_UpdateSpinAttackTris(this);
+ if (this->actionTimer == 0) {
+ if (this->actor.xzDistToPlayer > 200.0f) {
+ EnDeath_SetupSpinAttack(this);
+ } else {
+ EnDeath_SetupApproachPlayer(this);
+ }
+ }
+}
+
+void EnDeath_SetupSpinAttack(EnDeath* this) {
+ if (this->actionFunc != EnDeath_BlockProjectile) {
+ Animation_MorphToLoop(&this->skelAnime, &gGomessScytheSpinAnim, -3.0f);
+ this->numScytheAfterImages = -3;
+ this->actionTimer = 0;
+ this->weaponColliderLastUpdateTime = -1;
+ this->unk_18C = true;
+ this->actor.speed = 0.0f;
+ } else {
+ // Starting straight out of blocking a projectile, already spinning so start moving immediately
+ this->actionTimer = 10;
+ this->weaponColliderLastUpdateTime = 9;
+ this->actor.speed = 10.0f;
+ }
+ EnDeath_UpdateSpinAttackTris(this);
+ this->actionFunc = EnDeath_SpinAttack;
+}
+
+void EnDeath_SpinAttack(EnDeath* this, PlayState* play) {
+ EnDeath_Float(this);
+
+ SkelAnime_Update(&this->skelAnime);
+ if (Animation_OnFrame(&this->skelAnime, 0.0f)) {
+ Audio_PlaySfx_AtPos(&this->scytheScreenPos, NA_SE_EN_DEATH_ROLL);
+ }
+
+ if (this->numScytheAfterImages < 7) {
+ this->numScytheAfterImages++;
+ }
+
+ this->actionTimer++;
+ if (this->actionTimer < 10) {
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 8, 0x1000, 0x100);
+ } else if (this->actionTimer == 10) {
+ this->actor.speed = 10.0f;
+ }
+
+ EnDeath_UpdateSpinAttackTris(this);
+
+ Math_ScaledStepToS(&this->cloakUpperRotationModifier, (s32)(Math_SinS(this->actionTimer * 0x2000) * 0x800) + 0x3000,
+ 0x1000);
+ Math_ScaledStepToS(&this->cloakLowerRotationModifier, (s32)(Math_SinS(this->actionTimer * 0x2000 - 0x8000) * 0x800),
+ 0x1000);
+
+ if ((this->actor.bgCheckFlags & BGCHECKFLAG_WALL) || (this->weaponCollider.base.atFlags & AT_HIT) ||
+ (this->weaponSpinningCollider.base.atFlags & AT_HIT)) {
+ this->unk_18C = false;
+ this->weaponCollider.base.atFlags &= ~(AT_ON | AT_HIT);
+ this->weaponSpinningCollider.base.atFlags &= ~AT_HIT;
+ EnDeath_SetupApproachPlayer(this);
+ }
+}
+
+void EnDeath_SetupDamaged(EnDeath* this) {
+ Animation_PlayOnce(&this->skelAnime, &gGomessDamagedAnim);
+ this->actor.speed = 10.0f;
+ func_800BE568(&this->actor, &this->coreCollider);
+ Actor_SetColorFilter(&this->actor, COLORFILTER_COLORFLAG_RED, 255, COLORFILTER_BUFFLAG_OPA, 15);
+ Actor_PlaySfx(&this->actor, NA_SE_EN_DEATH_DAMAGE);
+ this->actionFunc = EnDeath_Damaged;
+}
+
+void EnDeath_Damaged(EnDeath* this, PlayState* play) {
+ EnDeath_Float(this);
+ Math_StepToF(&this->actor.speed, 0.0f, 0.5f);
+ if (SkelAnime_Update(&this->skelAnime)) {
+ this->coreCollider.base.acFlags |= AC_ON;
+ EnDeath_SetupSpinAttack(this);
+ }
+}
+
+void EnDeath_SetupDeathCutscenePart1(EnDeath* this, PlayState* play) {
+ Vec3f eye;
+ Vec3f at;
+ s32 i;
+
+ this->actor.flags &= ~(ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_IGNORE_QUAKE);
+ Animation_PlayOnce(&this->skelAnime, &gGomessBeginDeathAnim);
+
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_DEATH_1;
+ }
+
+ this->coreGuarded = false;
+ this->coreCollider.base.acFlags &= ~AC_ON;
+ Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 30);
+ this->actionTimer = 35;
+ this->actor.world.pos.y = this->actor.home.pos.y;
+ this->actor.speed = 0.0f;
+ this->camEyeTarget.x = Math_SinS(this->actor.shape.rot.y + 0x900) * 79.0f + this->actor.world.pos.x;
+ this->camEyeTarget.z = Math_CosS(this->actor.shape.rot.y + 0x900) * 79.0f + this->actor.world.pos.z;
+ this->camEyeTarget.y = this->actor.home.pos.y + 63.0f;
+ at.x = this->actor.world.pos.x;
+ at.y = this->actor.world.pos.y + 100.0f;
+ at.z = this->actor.world.pos.z;
+ eye.x = Math_SinS(this->actor.shape.rot.y + 0x900) * 179.0f + this->actor.world.pos.x;
+ eye.z = Math_CosS(this->actor.shape.rot.y + 0x900) * 179.0f + this->actor.world.pos.z;
+ eye.y = this->actor.home.pos.y + 30.0f;
+ Play_SetCameraAtEye(play, this->camId, &at, &eye);
+ this->camEyeSpeed = Math_Vec3f_DistXYZ(&eye, &this->camEyeTarget) * 0.05f;
+ this->actor.shape.rot.y += 0x2000;
+ Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_WAIT);
+ Actor_PlaySfx(&this->actor, NA_SE_EN_DEATH_DEAD);
+ this->actionFunc = EnDeath_DeathCutscenePart1;
+}
+
+void EnDeath_DeathCutscenePart1(EnDeath* this, PlayState* play) {
+ Camera* camera = Play_GetCamera(play, this->camId);
+ f32 distToTarget = Math_Vec3f_StepTo(&camera->eye, &this->camEyeTarget, this->camEyeSpeed);
+
+ Play_SetCameraAtEye(play, this->camId, &camera->at, &camera->eye);
+
+ if (SkelAnime_Update(&this->skelAnime)) {
+ this->actor.shape.rot.y += 0x2000;
+ Animation_PlayLoop(&this->skelAnime, &gGomessDeathAnim);
+ } else if (this->skelAnime.animation == &gGomessBeginDeathAnim) {
+ this->actor.shape.rot.y += 0x2000;
+ if (this->skelAnime.curFrame > 3.0f) {
+ Matrix_Put(&this->scytheMtxF);
+ Matrix_RotateXS(-0x1000, MTXMODE_APPLY);
+ Matrix_Get(&this->scytheMtxF);
+ this->holdsScythe = false;
+ this->scytheMtxF.yw += 18.0f;
+ Actor_PlaySfx(&this->actor, NA_SE_EN_DEATH_SCYTHE);
+ }
+ }
+
+ if (distToTarget < 0.1f) {
+ if (this->actionTimer == 35) {
+ Audio_PlaySfx_AtPosWithVolumeTransition(&this->scytheScreenPos, NA_SE_EN_DEATH_SCYTHE_LEV, 0x41);
+ }
+ if (this->actionTimer > 0) {
+ this->actionTimer--;
+ }
+ if (this->actionTimer == 0) {
+ EnDeath_SetupDeathCutscenePart2(this, play);
+ }
+ }
+}
+
+void EnDeath_SetupDeathCutscenePart2(EnDeath* this, PlayState* play) {
+ EnvLightSettings* lightSettings1;
+ EnvLightSettings* lightSettings2;
+ Player* player = GET_PLAYER(play);
+ Vec3f eye;
+ Vec3f at;
+ f32 sinRotY;
+ f32 cosRotY;
+ s32 i;
+
+ Animation_PlayLoop(&this->skelAnime, &gGomessDeathAnim);
+ this->actionTimer = 30;
+ player->actor.shape.rot.y = Actor_WorldYawTowardPoint(&player->actor, &this->actor.home.pos) + 0x1000;
+ this->actor.shape.rot.y = player->actor.shape.rot.y + 0x6000;
+ sinRotY = Math_SinS(player->actor.shape.rot.y);
+ cosRotY = Math_CosS(player->actor.shape.rot.y);
+ this->actor.world.pos.x = player->actor.world.pos.x + (260.0f * sinRotY);
+ this->actor.world.pos.z = player->actor.world.pos.z + (260.0f * cosRotY);
+ this->actor.world.pos.y = this->actor.home.pos.y + 15.0f;
+ eye.x = (Math_SinS((s16)(player->actor.shape.rot.y - 0x2500)) * 182.0f) + this->actor.world.pos.x;
+ eye.z = (Math_CosS((s16)(player->actor.shape.rot.y - 0x2500)) * 182.0f) + this->actor.world.pos.z;
+ eye.y = this->actor.world.pos.y - 13.0f;
+ at.x = player->actor.world.pos.x + (120.0f * sinRotY);
+ at.y = player->actor.world.pos.y + 90.0f;
+ at.z = player->actor.world.pos.z + (120.0f * cosRotY);
+ Play_SetCameraAtEye(play, this->camId, &at, &eye);
+
+ lightSettings1 = &play->envCtx.lightSettingsList[20];
+ lightSettings2 = &play->envCtx.lightSettingsList[21];
+
+ for (i = 0; i < 3; i++) {
+ lightSettings1->light1Dir[i] = lightSettings2->light1Dir[i];
+ lightSettings1->light2Dir[i] = lightSettings2->light2Dir[i];
+ }
+
+ this->actionFunc = EnDeath_DeathCutscenePart2;
+}
+
+void EnDeath_DeathCutscenePart2(EnDeath* this, PlayState* play) {
+ f32 sin;
+ f32 cos;
+ s16 camYaw;
+
+ SkelAnime_Update(&this->skelAnime);
+
+ this->actionTimer--;
+ if (this->actionTimer >= 0 && this->actionTimer < 3) {
+ camYaw = Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x8000;
+ sin = Math_SinS(camYaw);
+ cos = Math_CosS(camYaw);
+ Matrix_Translate(this->actor.world.pos.x + (83.0f * sin) + (-38.0f * cos),
+ this->actor.world.pos.y + 53.0f + 15.0f * this->actionTimer,
+ this->actor.world.pos.z + (83.0f * cos) - (-38.0f * sin), MTXMODE_NEW);
+ Matrix_RotateYS(camYaw - 0x3300, MTXMODE_APPLY);
+ Matrix_RotateXS(0x1100 - this->actionTimer * 0x1800, MTXMODE_APPLY);
+ Matrix_RotateZS(-0xA00, MTXMODE_APPLY);
+ Matrix_Scale(0.01f, 0.01f, 0.01f, MTXMODE_APPLY);
+ Matrix_Get(&this->scytheMtxF);
+ if (this->actionTimer == 0) {
+ Camera_AddQuake(GET_ACTIVE_CAM(play), 2, 4, 6);
+ Rumble_Request(this->actor.xyzDistToPlayerSq, 180, 20, 100);
+ AudioSfx_StopByPosAndId(&this->scytheScreenPos, NA_SE_EN_DEATH_SCYTHE_LEV);
+ Audio_PlaySfx_AtPos(&this->scytheScreenPos, NA_SE_EN_DEATH_SCYTHE_ONGND);
+ }
+ }
+ if (this->actionTimer < -25) {
+ play->envCtx.lightSettingOverride = 20;
+ EnDeath_SetupDeathCutscenePart3(this);
+ }
+}
+
+void EnDeath_SetupDeathCutscenePart3(EnDeath* this) {
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_DEATH_2;
+ }
+
+ this->actionTimer = 0;
+ this->actionFunc = EnDeath_DeathCutscenePart3;
+}
+
+void EnDeath_DeathCutscenePart3(EnDeath* this, PlayState* play) {
+ static Vec3f sSparkleVel = { 0.0f, -1.5f, 0.0f };
+ static Vec3f sSparkleAccel = { 0.0f, -0.2f, 0.0f };
+ static Color_RGBA8 sSparklePrimColor = { 0, 0, 0, 0 };
+ static Color_RGBA8 sSparkleEnvColor = { 40, 40, 40, 0 };
+ static s16 sDeleteLimbFrameNumbers[GOMESS_LIMB_MAX] = {
+ 30, 30, 10, 2, 12, 17, 17, 17, 17, 17, 17, 17, 14, 10, 12, 9, 9, 12, 9, 9, 30, 30,
+ };
+ s32 i;
+ s32 j;
+ u8* flameAlpha;
+ Vec3f* sparklePos;
+ s32 pad;
+ s32 pad1;
+ f32 sin;
+ f32 cos;
+ f32 x;
+ s32 alpha;
+
+ sparklePos = this->sparklePositions;
+ flameAlpha = this->flameAlphas;
+ for (i = 0; (i ^ 0) < ARRAY_COUNT(this->sparklePositions); i++) { //! FAKE
+ sparklePos->y += 1.7f;
+ alpha = *flameAlpha - 30;
+ *flameAlpha = CLAMP_MIN(alpha, 0);
+ sparklePos++;
+ flameAlpha++;
+ }
+
+ alpha = -this->actionTimer * 14 + 252;
+ this->actor.shape.shadowAlpha = CLAMP_MIN(alpha, 0);
+
+ if (this->actionTimer < 18) {
+ sparklePos = &this->sparklePositions[(this->actionTimer * 7) % ARRAY_COUNT(this->sparklePositions)];
+ flameAlpha = &this->flameAlphas[(this->actionTimer * 7) % ARRAY_COUNT(this->flameAlphas)];
+
+ sin = Math_SinS(Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x8000);
+ cos = Math_CosS(Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x8000);
+
+ for (j = 0; j < 7; j++) {
+ x = Rand_CenteredFloat(100.0f) - 20.0f;
+ sparklePos->x = this->actor.world.pos.x + 30.0f * sin + x * cos;
+ sparklePos->y = (Rand_ZeroFloat(20.0f) + this->actor.world.pos.y + 4.0f * this->actionTimer) - 30.0f;
+ sparklePos->z = this->actor.world.pos.z + 30.0f * cos - x * sin;
+ *flameAlpha = 255 - j * 4;
+ EffectSsKirakira_SpawnSmall(play, sparklePos, &sSparkleVel, &sSparkleAccel, &sSparklePrimColor,
+ &sSparkleEnvColor);
+ sparklePos++;
+ flameAlpha++;
+ }
+ Actor_PlaySfx_Flagged(&this->actor, NA_SE_EN_COMMON_EXTINCT_LEV - SFX_FLAG);
+ }
+
+ this->actionTimer++;
+
+ for (i = 0; i < ARRAY_COUNT(this->noDrawLimbs); i++) {
+ if (this->actionTimer == sDeleteLimbFrameNumbers[i]) {
+ this->noDrawLimbs[i] = true;
+ }
+ }
+
+ if (this->actionTimer == 26) {
+ EnDeath_SetupDeathCutscenePart4(this);
+ }
+}
+
+void EnDeath_SetupDeathCutscenePart4(EnDeath* this) {
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(this->flameAlphas); i++) {
+ this->flameAlphas[i] = 0;
+ }
+
+ Math_Vec3f_Copy(&this->actor.world.pos, &this->actor.focus.pos);
+ this->actor.bgCheckFlags &= ~BGCHECKFLAG_GROUND;
+ this->actionTimer = 0;
+ this->actionFunc = EnDeath_DeathCutscenePart4;
+ this->actor.gravity = -1.0f;
+ this->actor.shape.yOffset = 0.0f;
+}
+
+void EnDeath_DeathCutscenePart4(EnDeath* this, PlayState* play) {
+ static Vec3f sSparkleAccel = { 0.0f, -1.0f, 0.0f };
+ static Color_RGBA8 sSparklePrimColor = { 0, 200, 100, 0 };
+ static Color_RGBA8 sSparkleEnvColor = { 0, 100, 0, 0 };
+ Vec3f sparkleVel;
+ s32 i;
+
+ if (this->actionTimer == 0) {
+ if ((this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) || this->actor.floorHeight == BGCHECK_Y_MIN) {
+ Actor_SetScale(&this->actor, 0.0f);
+ this->actionTimer++;
+
+ for (i = 0; i < 40; i++) {
+ sSparkleAccel.y = -0.2f;
+ sparkleVel.x = Rand_CenteredFloat(4.0f);
+ sparkleVel.z = Rand_CenteredFloat(4.0f);
+ sparkleVel.y = Rand_ZeroFloat(2.0f) + 3.0f;
+ EffectSsKirakira_SpawnSmall(play, &this->actor.world.pos, &sparkleVel, &sSparkleAccel,
+ &sSparklePrimColor, &sSparkleEnvColor);
+ }
+ Actor_PlaySfx(&this->actor, NA_SE_EN_DEATH_HEARTBREAK);
+ }
+ } else {
+ this->actionTimer++;
+ if (this->actionTimer == 20) {
+ EnDeath_SetupDead(this, play);
+ }
+ }
+}
+
+void EnDeath_SetupDead(EnDeath* this, PlayState* play) {
+ CutsceneManager_Stop(this->actor.csId);
+ Player_SetCsAction(play, &this->actor, PLAYER_CSACTION_END);
+ Flags_SetClearTemp(play, play->roomCtx.curRoom.num);
+ this->actionTimer = 255;
+ play->envCtx.lightSettingOverride = 255;
+ this->actionFunc = EnDeath_Dead;
+}
+
+void EnDeath_Dead(EnDeath* this, PlayState* play) {
+ if (this->actionTimer > 0) {
+ this->actionTimer -= 5;
+ if (this->actionTimer <= 0) {
+ this->actionTimer = 0;
+ Actor_Kill(&this->actor);
+ }
+ }
+}
+
+void EnDeath_SetupStartBatSwarm(EnDeath* this) {
+ s32 i;
+
+ Actor_PlaySfx(&this->actor, NA_SE_EN_DEATH_VOICE);
+ Animation_MorphToPlayOnce(&this->skelAnime, &gGomessBatSwarmStartAnim, 5.0f);
+ this->actor.speed = 0.0f;
+
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_START_SWARM;
+ }
+
+ this->floatTimer = 0;
+ this->actionFunc = EnDeath_StartBatSwarm;
+}
+
+void EnDeath_StartBatSwarm(EnDeath* this, PlayState* play) {
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 8, 0x1000, 0x100);
+ Math_StepToF(&this->actor.world.pos.y, this->actor.home.pos.y, 5.0f);
+
+ if (SkelAnime_Update(&this->skelAnime)) {
+ play->envCtx.lightSettingOverride = 27;
+ EnDeath_SetupBatSwarm(this);
+ }
+}
+
+void EnDeath_SetupBatSwarm(EnDeath* this) {
+ s32 i;
+
+ Animation_PlayLoop(&this->skelAnime, &gGomessBatSwarmAnim);
+
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_SWARM;
+ }
+
+ this->actionFunc = EnDeath_BatSwarm;
+ this->actor.speed = 0.0f;
+}
+
+void EnDeath_BatSwarm(EnDeath* this, PlayState* play) {
+ Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 8, 0x1000, 0x100);
+ SkelAnime_Update(&this->skelAnime);
+
+ if (this->actor.params >= 5) {
+ play->envCtx.lightSettingOverride = 26;
+ EnDeath_SetupApproachPlayer(this);
+ }
+}
+
+void EnDeath_SetupPlayCutscene(EnDeath* this) {
+ CutsceneManager_Queue(this->actor.csId);
+ this->actionFunc = EnDeath_PlayCutscene;
+}
+
+void EnDeath_PlayCutscene(EnDeath* this, PlayState* play) {
+ // Wait for it's turn to play
+ if (CutsceneManager_IsNext(this->actor.csId)) {
+ // Start playing
+ CutsceneManager_Start(this->actor.csId, &this->actor);
+ this->camId = CutsceneManager_GetCurrentSubCamId(this->actor.csId);
+ if (this->actor.colChkInfo.health == 0) {
+ // Death cutscene
+ EnDeath_SetupDeathCutscenePart1(this, play);
+ } else {
+ // Intro cutscene
+ EnDeath_SetupIntroCutscenePart1(this, play);
+ }
+ } else {
+ CutsceneManager_Queue(this->actor.csId);
+ }
+}
+
+void EnDeath_SetupBeginWithoutCutscene(EnDeath* this) {
+ this->actionFunc = EnDeath_BeginWithoutCutscene;
+}
+
+void EnDeath_BeginWithoutCutscene(EnDeath* this, PlayState* play) {
+ if (!Play_InCsMode(play)) {
+ EnDeath_DimLights(play);
+ this->coreCollider.base.acFlags |= AC_ON;
+ Audio_PlayBgm_StorePrevBgm(NA_BGM_MINI_BOSS);
+ EnDeath_SetupApproachPlayer(this);
+ }
+}
+
+void EnDeath_UpdateCore(EnDeath* this, PlayState* play) {
+ if (this->coreGuarded) {
+ // Core falling to the ground
+ this->corePos.y += this->coreVelocity;
+ this->coreVelocity -= 1.0f;
+ this->coreRotation += 0x1800;
+ if (this->corePos.y < this->actor.floorHeight) {
+ // Hit the floor
+ this->corePos.y = this->actor.floorHeight;
+ func_800B3030(play, &this->corePos, &gZeroVec3f, &gZeroVec3f, 100, 0, 0);
+ SoundSource_PlaySfxAtFixedWorldPos(play, &this->corePos, 11, NA_SE_EN_EXTINCT);
+ this->coreGuarded = false;
+ }
+ }
+}
+
+void EnDeath_UpdateDamage(EnDeath* this, PlayState* play) {
+ s32 i;
+
+ if (this->explosiveDamageTimer > 0) {
+ this->explosiveDamageTimer--;
+ }
+ if (this->coreCollider.base.acFlags & AC_HIT) {
+ this->coreCollider.base.acFlags &= ~AC_HIT;
+
+ if (this->actor.params >= 5) {
+ this->coreGuarded = true;
+ this->coreVelocity = -1.0f;
+ this->coreRotation = this->actor.shape.rot.y;
+ Math_Vec3s_ToVec3f(&this->corePos, &this->coreCollider.dim.worldSphere.center);
+ SoundSource_PlaySfxAtFixedWorldPos(play, &this->corePos, 30, NA_SE_EN_FFLY_DEAD);
+
+ if (this->actor.colChkInfo.damageEffect == DMGEFF_LIGHT_ARROW &&
+ this->actionFunc != EnDeath_StartBatSwarm) {
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_SCATTER;
+ }
+ play->envCtx.lightSettingOverride = 28;
+
+ this->lightArrowDamageTimer = 20;
+ if (this->actionFunc == EnDeath_ApproachPlayer) {
+ this->actionTimer = 100;
+ }
+ } else if (this->actor.colChkInfo.damageEffect == DMGEFF_EXPLOSIVES) {
+ this->explosiveDamageTimer = 10;
+ }
+ } else if (this->actor.colChkInfo.damageEffect != DMGEFF_EXPLOSIVES || this->explosiveDamageTimer == 0) {
+ this->unk_18C = false;
+ this->weaponCollider.base.atFlags &= ~AT_ON;
+ this->coreCollider.base.acFlags &= ~AC_ON;
+
+ if (this->actor.colChkInfo.damageEffect == DMGEFF_LIGHT_ARROW) {
+ this->dmgEffectAlpha = 3.0f;
+ this->dmgEffectScale = 0.8f;
+ this->dmgEffect = ACTOR_DRAW_DMGEFF_LIGHT_ORBS;
+ Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->coreCollider.info.bumper.hitPos.x,
+ this->coreCollider.info.bumper.hitPos.y, this->coreCollider.info.bumper.hitPos.z, 0, 0, 0,
+ 4);
+ }
+ if (play->envCtx.lightSettingOverride == 27) {
+ play->envCtx.lightSettingOverride = 26;
+ }
+ this->actor.shape.rot.x = 0;
+
+ if (Actor_ApplyDamage(&this->actor) == 0) {
+ Enemy_StartFinishingBlow(play, &this->actor);
+ Audio_RestorePrevBgm(); // Stop miniboss BGM
+ EnDeath_SetupPlayCutscene(this);
+ } else {
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_RETURN;
+ }
+ EnDeath_SetupDamaged(this);
+ }
+ }
+ }
+}
+
+void EnDeath_Update(Actor* thisx, PlayState* play) {
+ EnDeath* this = THIS;
+ ArrowLight* lightArrow;
+ s32 pad;
+
+ if (this->lightArrowDamageTimer > 0) {
+ this->lightArrowDamageTimer--;
+
+ lightArrow = (ArrowLight*)SubS_FindActor(play, NULL, ACTORCAT_ITEMACTION, ACTOR_ARROW_LIGHT);
+ if (lightArrow != NULL) {
+ lightArrow->screenFillIntensity = -100.0f;
+ }
+
+ if (this->lightArrowDamageTimer == 0) {
+ play->envCtx.lightSettingOverride = 26;
+ }
+ }
+
+ EnDeath_UpdateDamage(this, play);
+ EnDeath_UpdateCore(this, play);
+ if (this->actionFunc != EnDeath_SpinAttack) {
+ Math_ScaledStepToS(&this->cloakUpperRotationModifier, 0, 0x800);
+ Math_ScaledStepToS(&this->cloakLowerRotationModifier, 0, 0x800);
+ }
+
+ this->actionFunc(this, play);
+
+ if (this->actionFunc != EnDeath_Damaged) {
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+ }
+ Actor_MoveWithGravity(&this->actor);
+
+ Actor_UpdateBgCheckInfo(play, &this->actor, 40.0f, (this->actionFunc == EnDeath_SpinAttack) ? 50.0f : 100.0f, 40.0f,
+ UPDBGCHECKINFO_FLAG_4 | UPDBGCHECKINFO_FLAG_2 | UPDBGCHECKINFO_FLAG_1);
+
+ this->bodyCollider.dim.pos.x = this->actor.world.pos.x + Math_SinS(this->actor.shape.rot.y) * 3.0f;
+ this->bodyCollider.dim.pos.z = this->actor.world.pos.z + Math_CosS(this->actor.shape.rot.y) * 3.0f;
+ this->bodyCollider.dim.pos.y = this->actor.world.pos.y;
+
+ if (this->actor.params < 5) {
+ this->coreCollider.dim.worldSphere.radius = this->coreCollider.dim.modelSphere.radius + 5;
+ } else {
+ this->coreCollider.dim.worldSphere.radius = this->coreCollider.dim.modelSphere.radius;
+ }
+
+ if (this->actionFunc != EnDeath_Dead) {
+ CollisionCheck_SetOC(play, &play->colChkCtx, &this->bodyCollider.base);
+ }
+ if (this->coreCollider.base.acFlags & AC_ON) {
+ CollisionCheck_SetAC(play, &play->colChkCtx, &this->coreCollider.base);
+ }
+ if (this->weaponCollider.base.atFlags & AT_ON) {
+ CollisionCheck_SetAT(play, &play->colChkCtx, &this->weaponCollider.base);
+ }
+ if (this->actionFunc == EnDeath_BlockProjectile || this->actionFunc == EnDeath_SpinAttack) {
+ CollisionCheck_SetAT(play, &play->colChkCtx, &this->weaponSpinningCollider.base);
+ CollisionCheck_SetAC(play, &play->colChkCtx, &this->weaponSpinningCollider.base);
+ }
+
+ if (this->dmgEffectAlpha > 0.0f) {
+ if (this->dmgEffect != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX) {
+ Math_StepToF(&this->dmgEffectAlpha, 0.0f, 0.05f);
+ this->dmgEffectScale = (this->dmgEffectAlpha + 1.0f) * 0.4f;
+
+ this->dmgEffectScale = CLAMP_MAX(this->dmgEffectScale, 0.8f);
+ } else if (Math_StepToF(&this->dmgEffectSteamScale, 0.8f, 0.02f) == 0) {
+ Actor_PlaySfx_Flagged(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG);
+ }
+ }
+}
+
+void EnDeath_DrawScytheSpinning(EnDeath* this, PlayState* play) {
+ s32 i;
+ Gfx* gfx;
+ s32 pad;
+
+ func_800B8118(&this->actor, play, 0);
+ Scene_SetRenderModeXlu(play, 1, 2);
+
+ OPEN_DISPS(play->state.gfxCtx);
+ gfx = POLY_XLU_DISP;
+
+ for (i = 1; i < this->numScytheAfterImages; i++) {
+ gDPPipeSync(gfx++);
+ gDPSetEnvColor(gfx++, 30, 30, 0, 255 - i * 35);
+
+ Matrix_Put(&this->scytheMtxF);
+ Matrix_RotateXS(i * 0x2100, MTXMODE_APPLY);
+
+ gSPMatrix(gfx++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gfx++, gGomessScytheHandleDL);
+
+ Matrix_Translate(0.0f, -1084.0f, 7012.0f, MTXMODE_APPLY);
+ Matrix_RotateZYX(-0x4000, 0, -0x4000, MTXMODE_APPLY);
+
+ gSPMatrix(gfx++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gfx++, gGomessScytheBladeDL);
+ }
+
+ POLY_XLU_DISP = gfx;
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+void EnDeath_DrawScythe(EnDeath* this, PlayState* play) {
+ Gfx* gfx;
+ s32 pad;
+
+ if (this->actionFunc == EnDeath_Dead) {
+ func_800B8118(&this->actor, play, 0);
+ Scene_SetRenderModeXlu(play, 1, 2);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ if (this->actionFunc == EnDeath_Dead) {
+ gfx = POLY_XLU_DISP;
+
+ gDPPipeSync(gfx++);
+ gDPSetEnvColor(gfx++, 30, 30, 0, this->actionTimer);
+ } else {
+ gfx = POLY_OPA_DISP;
+ }
+
+ Matrix_Put(&this->scytheMtxF);
+ Matrix_Scale(this->scytheScale, this->scytheScale, this->scytheScale, MTXMODE_APPLY);
+
+ gSPMatrix(&gfx[0], Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(&gfx[1], gGomessScytheHandleDL);
+
+ Matrix_Translate(0.0f, -1084.0f, 7012.0f, MTXMODE_APPLY);
+ Matrix_RotateZYX(-0x4000, 0, -0x4000, MTXMODE_APPLY);
+
+ gSPMatrix(&gfx[2], Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(&gfx[3], gGomessScytheBladeDL);
+
+ Matrix_MultZero(&this->scytheWorldPos);
+
+ if (this->actionFunc == EnDeath_Dead) {
+ POLY_XLU_DISP = &gfx[4];
+ } else {
+ POLY_OPA_DISP = &gfx[4];
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+void EnDeath_DrawBats(EnDeath* this, PlayState* play) {
+ // Each bat is animated by cycling through these display lists
+ static Gfx* sMinideathDLs[MINIDEATH_ANIM_LENGTH] = {
+ gGomessBatFrame1DL, gGomessBatFrame2DL, gGomessBatFrame3DL, gGomessBatFrame4DL, gGomessBatFrame5DL,
+ gGomessBatFrame6DL, gGomessBatFrame7DL, gGomessBatFrame8DL, gGomessBatFrame9DL,
+ };
+ EnMinideath* miniDeath;
+ MtxF* cmf;
+ f32 scale2;
+ MiniDeathEffect* effect;
+ s32 j;
+ f32 scale;
+ Gfx* gfx;
+ s32 i;
+ Vec3f quakeOffset;
+
+ OPEN_DISPS(play->state.gfxCtx);
+ gfx = POLY_OPA_DISP;
+
+ gSPDisplayList(gfx++, gSetupDLs[SETUPDL_25]);
+ gSPDisplayList(gfx++, gGomessBatMaterialDL);
+
+ cmf = Matrix_GetCurrent();
+
+ if (this->actionFunc == EnDeath_Dead) {
+ scale2 = this->actionTimer * 0.000035f;
+ scale = 0.007f;
+ if (scale2 > 0.007f) {
+ scale2 = 0.007f;
+ scale = 0.007f;
+ }
+ } else {
+ scale2 = 0.007f;
+ scale = 0.007f;
+ }
+
+ if (this->actor.flags & ACTOR_FLAG_IGNORE_QUAKE) {
+ Math_Vec3f_Copy(&quakeOffset, &play->mainCamera.quakeOffset);
+ } else {
+ Math_Vec3f_Copy(&quakeOffset, &gZeroVec3f);
+ }
+
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ if (this->actionFunc == EnDeath_BeginWithoutCutscene ||
+ CHECK_FLAG_ALL(this->miniDeaths[i]->actor.flags, ACTOR_FLAG_40)) {
+ miniDeath = this->miniDeaths[i];
+
+ Matrix_RotateZYX(miniDeath->actor.shape.rot.x, miniDeath->actor.shape.rot.y, 0, MTXMODE_NEW);
+ Matrix_Scale(scale2, scale2, scale2, MTXMODE_APPLY);
+
+ for (effect = miniDeath->effects, j = 0; j < MINIDEATH_NUM_EFFECTS; j++, effect++) {
+ if (effect->state == 0) {
+ cmf->mf[3][0] = effect->pos.x + quakeOffset.x;
+ cmf->mf[3][1] = effect->pos.y + quakeOffset.y;
+ cmf->mf[3][2] = effect->pos.z + quakeOffset.z;
+
+ gSPMatrix(gfx++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gfx++, sMinideathDLs[effect->animFrame]);
+ }
+ }
+
+ for (effect = miniDeath->effects, j = 0; j < MINIDEATH_NUM_EFFECTS; j++, effect++) {
+ if (effect->state == 1) {
+ Matrix_RotateZYX(0x4000, effect->angle.y, 0, MTXMODE_NEW);
+ Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
+ cmf->mf[3][0] = effect->pos.x + quakeOffset.x;
+ cmf->mf[3][1] = effect->pos.y + quakeOffset.y;
+ cmf->mf[3][2] = effect->pos.z + quakeOffset.z;
+
+ gSPMatrix(gfx++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gfx++, sMinideathDLs[effect->animFrame]);
+ }
+ }
+ }
+ }
+
+ if (this->inEarlyIntro) {
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ miniDeath = this->miniDeaths[i];
+
+ Matrix_RotateZYX(miniDeath->actor.shape.rot.x, miniDeath->actor.shape.rot.y, 0, MTXMODE_NEW);
+ Matrix_Scale(scale2, scale2, scale2, MTXMODE_APPLY);
+
+ for (effect = miniDeath->effects, j = 0; j < MINIDEATH_NUM_EFFECTS; j++, effect++) {
+ cmf->mf[3][0] = miniDeath->actor.world.pos.x - effect->vel.x;
+ cmf->mf[3][1] = miniDeath->actor.world.pos.y + (20.0f - effect->vel.y);
+ cmf->mf[3][2] = miniDeath->actor.world.pos.z - effect->vel.z;
+
+ gSPMatrix(gfx++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gfx++, sMinideathDLs[effect->animFrame]);
+ }
+ }
+ }
+
+ if (this->coreGuarded) {
+ Matrix_RotateZYX(0x4000, this->coreRotation, 0, MTXMODE_NEW);
+ Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
+ cmf->mf[3][0] = this->corePos.x + quakeOffset.x;
+ cmf->mf[3][1] = this->corePos.y + quakeOffset.y;
+ cmf->mf[3][2] = this->corePos.z + quakeOffset.z;
+
+ gSPMatrix(gfx++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(gfx++, sMinideathDLs[0]);
+ }
+
+ POLY_OPA_DISP = gfx;
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+void EnDeath_DrawFlames(EnDeath* this, PlayState* play2) {
+ PlayState* play = play2;
+ s32 i;
+ MtxF* cmf;
+ s32 numFlames;
+ u8* flameAlpha;
+ Vec3f* sparklePos;
+ MiniDeathEffect* effect;
+ u8 alpha;
+ s32 j;
+
+ numFlames = this->actionTimer * 7;
+ if (numFlames > ARRAY_COUNT(this->flameAlphas)) {
+ numFlames = ARRAY_COUNT(this->flameAlphas);
+ }
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ gDPSetEnvColor(POLY_XLU_DISP++, 230, 135, 25, 0);
+
+ Matrix_Put(&play->billboardMtxF);
+ Matrix_Scale(0.00405f, 0.003f, 0.00405f, MTXMODE_APPLY);
+
+ cmf = Matrix_GetCurrent();
+
+ sparklePos = this->sparklePositions;
+ flameAlpha = this->flameAlphas;
+ for (i = 0; i < numFlames; i++) {
+ if (*flameAlpha > 0) {
+
+ gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 165, 255, 215, *flameAlpha);
+ gSPSegment(POLY_XLU_DISP++, 0x08,
+ Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 32, 64, 1, 0,
+ ((play->gameplayFrames + i * 10) * -20) & 0x1FF, 32, 128));
+
+ cmf->mf[3][0] = sparklePos->x;
+ cmf->mf[3][1] = sparklePos->y;
+ cmf->mf[3][2] = sparklePos->z;
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, gEffFire1DL);
+ }
+ sparklePos++;
+ flameAlpha++;
+ }
+
+ Matrix_Put(&play->billboardMtxF);
+ Matrix_Scale(0.00405f, 0.003f, 0.00405f, MTXMODE_APPLY);
+
+ if (this->actionFunc == EnDeath_Dead) {
+ alpha = this->actionTimer;
+ } else {
+ alpha = 255;
+ }
+
+ for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) {
+ if (CHECK_FLAG_ALL(this->miniDeaths[i]->actor.flags, ACTOR_FLAG_40)) {
+ for (effect = this->miniDeaths[i]->effects, j = 0; j < MINIDEATH_NUM_EFFECTS; j++, effect++) {
+ cmf->mf[3][0] = effect->pos.x;
+ cmf->mf[3][1] = effect->pos.y - 12.0f;
+ cmf->mf[3][2] = effect->pos.z;
+
+ gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 165, 255, 215, alpha);
+ gSPSegment(POLY_XLU_DISP++, 0x08,
+ Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 32, 64, 1, 0,
+ ((play->gameplayFrames + ((i + j) * 10)) * -20) & 511, 32, 128));
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx),
+ G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, gEffFire1DL);
+ }
+ }
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+void EnDeath_DrawCore(EnDeath* this, PlayState* play) {
+ s32 pad;
+ Gfx* gfx;
+
+ OPEN_DISPS(play->state.gfxCtx);
+ gfx = POLY_OPA_DISP;
+
+ Matrix_ReplaceRotation(&play->billboardMtxF);
+
+ gSPMatrix(&gfx[0], Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(&gfx[1], gGomessCoreDL);
+
+ if (this->actor.params >= 5) {
+ // bats in front of the core
+ gSPDisplayList(&gfx[2], gGomessBatsGuardingCoreDL);
+ POLY_OPA_DISP = &gfx[3];
+ } else {
+ POLY_OPA_DISP = &gfx[2];
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+s32 EnDeath_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
+ EnDeath* this = THIS;
+
+ if (this->noDrawLimbs[limbIndex] == true) {
+ *dList = NULL;
+ } else if (limbIndex == GOMESS_LIMB_CLOAK_LOWER && this->actionFunc == EnDeath_DeathCutscenePart3) {
+ if (this->actionTimer - 5 > 0) {
+ f32 scale = 1.0f - 0.1f * (this->actionTimer - 5);
+
+ Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
+ }
+ }
+
+ if (limbIndex == GOMESS_LIMB_SCYTHE_HANDLE || limbIndex == GOMESS_LIMB_SCYTHE_BLADE) {
+ if (!this->holdsScythe) {
+ *dList = NULL;
+ }
+ } else if (limbIndex == GOMESS_LIMB_CLOAK_UPPER) {
+ rot->z += this->cloakUpperRotationModifier;
+ } else if (limbIndex == GOMESS_LIMB_CLOAK_LOWER) {
+ rot->z += this->cloakLowerRotationModifier;
+ }
+ return 0;
+}
+
+void EnDeath_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
+ static Vec3f sWeaponColliderOffsetEndSwing = { -1000.0f, 12000.0f, 0.0f };
+ static Vec3f sWeaponColliderOffsetOther = { -2000.0f, -2500.0f, 0.0f };
+ static Vec3f sDamageEffectOffsets[5] = {
+ { 1000.0f, 2000.0f, 0.0f }, { 1500.0f, 1000.0f, 4000.0f }, { 1500.0f, 1000.0f, -4000.0f },
+ { 4000.0f, 4000.0f, 2000.0f }, { 4000.0f, 4000.0f, -2000.0f },
+ };
+ static s8 sLimbToBodyParts[GOMESS_LIMB_MAX] = {
+ -1, -1, -1, 12, -1, 0, -1, -1, -1, -1, -1, -1, -1, 7, 1, 2, 3, 4, 5, 6, -1, -1,
+ };
+ EnDeath* this = THIS;
+ s8 index;
+
+ if (limbIndex == GOMESS_LIMB_SCYTHE_BLADE) {
+ Matrix_MultZero(&this->scytheWorldPos);
+
+ if ((this->weaponCollider.base.atFlags & AT_ON) && this->weaponColliderLastUpdateTime != this->actionTimer) {
+ Vec3f quad0;
+ Vec3f quad1;
+ Vec3f pos1;
+ Vec3f pos2;
+
+ Math_Vec3f_Copy(&quad0, &this->weaponCollider.dim.quad[0]);
+ Math_Vec3f_Copy(&quad1, &this->weaponCollider.dim.quad[1]);
+
+ if (this->actionFunc == EnDeath_EndSwingAttack) {
+ Matrix_MultVecX(6000.0f, &pos1);
+ Matrix_MultVec3f(&sWeaponColliderOffsetEndSwing, &pos2);
+ } else {
+ Matrix_MultVecY(5000.0f, &pos2);
+ Matrix_MultVec3f(&sWeaponColliderOffsetOther, &pos1);
+ }
+
+ Collider_SetQuadVertices(&this->weaponCollider, &pos2, &pos1, &quad0, &quad1);
+ EffectBlure_AddVertex(Effect_GetByIndex(this->effectIndex), &pos1, &pos2);
+
+ this->weaponColliderLastUpdateTime = this->actionTimer;
+ } else if (this->unk_18C) {
+ if (this->actionFunc == EnDeath_EndSwingAttack) {
+ Matrix_MultVecX(6000.0f, &this->weaponCollider.dim.quad[1]);
+ Matrix_MultVec3f(&sWeaponColliderOffsetEndSwing, &this->weaponCollider.dim.quad[0]);
+ } else {
+ Matrix_MultVecY(5000.0f, &this->weaponCollider.dim.quad[0]);
+ Matrix_MultVec3f(&sWeaponColliderOffsetOther, &this->weaponCollider.dim.quad[1]);
+ }
+ this->unk_18C = false;
+ this->weaponCollider.base.atFlags |= AT_ON;
+ this->weaponColliderLastUpdateTime = this->actionTimer;
+ }
+ } else if (limbIndex == GOMESS_LIMB_CORE_POS && this->actionFunc != EnDeath_Dead) {
+ Matrix_Push();
+ EnDeath_DrawCore(this, play);
+ Matrix_Pop();
+ Matrix_MultZero(&this->actor.focus.pos);
+
+ this->coreCollider.dim.worldSphere.center.x = this->actor.focus.pos.x;
+ this->coreCollider.dim.worldSphere.center.y = this->actor.focus.pos.y;
+ this->coreCollider.dim.worldSphere.center.z = this->actor.focus.pos.z;
+
+ if (this->actor.params < 5) {
+ this->coreCollider.dim.worldSphere.center.y = this->actor.focus.pos.y + 5.0f;
+ }
+ } else if (limbIndex == GOMESS_LIMB_SCYTHE_HANDLE) {
+ if (!(this->actionFunc != EnDeath_SpinAttack && this->actionFunc != EnDeath_BlockProjectile &&
+ this->actionFunc != EnDeath_IntroCutscenePart5) ||
+ (this->actionFunc == EnDeath_DeathCutscenePart1 && this->holdsScythe == true)) {
+ Matrix_Get(&this->scytheMtxF);
+ }
+ }
+
+ index = sLimbToBodyParts[limbIndex];
+ if (index != -1) {
+ if (index < 7) {
+ // get matrix translation as-is, occupies slots 0, 1, 2, 3, 4, 5, 6
+ Matrix_MultZero(&this->bodyPartsPos[index]);
+ } else if (index == 7) {
+ // 5 points using 5 offsets, occupies slots 7, 8, 9, 10, 11
+ s32 i;
+ Vec3f* offset;
+ Vec3f* effPos;
+
+ for (effPos = &this->bodyPartsPos[index], offset = &sDamageEffectOffsets[0], i = 0;
+ i != ARRAY_COUNT(sDamageEffectOffsets); i++, offset++, effPos++) {
+ Matrix_MultVec3f(offset, effPos);
+ }
+ } else if (index == 12) {
+ // get matrix translation as-is and a point offset by -2000 from it, occupies slots 12, 13
+ Matrix_MultZero(&this->bodyPartsPos[index]);
+ Matrix_MultVecY(-2000.0f, &this->bodyPartsPos[index + 1]);
+ }
+ }
+}
+
+void EnDeath_Draw(Actor* thisx, PlayState* play) {
+ EnDeath* this = THIS;
+ s32 pad;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL25_Opa(play->state.gfxCtx);
+ func_800B8050(&this->actor, play, 0);
+ AnimatedMat_DrawStepOpa(play, this->bodyMatAnim, this->matAnimStep);
+ AnimatedMat_DrawOpa(play, this->coreMatAnim);
+ Scene_SetRenderModeXlu(play, 0, 1);
+
+ gDPSetEnvColor(POLY_OPA_DISP++, 30, 30, 0, 255);
+
+ if (this->actionFunc != EnDeath_Dead && this->actionFunc != EnDeath_DeathCutscenePart4) {
+ SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
+ EnDeath_OverrideLimbDraw, EnDeath_PostLimbDraw, &this->actor);
+ }
+ if (this->actionFunc == EnDeath_DeathCutscenePart4) {
+ EnDeath_DrawCore(this, play);
+ }
+ if (!this->holdsScythe) {
+ EnDeath_DrawScythe(this, play);
+ }
+ if (this->actor.colorFilterTimer != 0) {
+ func_800AE5A0(play);
+ }
+ Actor_DrawDamageEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos),
+ this->dmgEffectScale, this->dmgEffectSteamScale, this->dmgEffectAlpha, this->dmgEffect);
+ if (this->actionFunc == EnDeath_SpinAttack || this->actionFunc == EnDeath_BlockProjectile) {
+ EnDeath_DrawScytheSpinning(this, play);
+ }
+ EnDeath_DrawBats(this, play);
+ if (this->actionFunc == EnDeath_Dead || this->actionFunc == EnDeath_DeathCutscenePart4 ||
+ (this->actionFunc == EnDeath_DeathCutscenePart3 && this->actionTimer > 0)) {
+ EnDeath_DrawFlames(this, play);
+ }
+ SkinMatrix_Vec3fMtxFMultXYZ(&play->viewProjectionMtxF, &this->scytheWorldPos, &this->scytheScreenPos);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
diff --git a/src/overlays/actors/ovl_En_Death/z_en_death.h b/src/overlays/actors/ovl_En_Death/z_en_death.h
index 16863cf83..ea33ea2ad 100644
--- a/src/overlays/actors/ovl_En_Death/z_en_death.h
+++ b/src/overlays/actors/ovl_En_Death/z_en_death.h
@@ -2,6 +2,8 @@
#define Z_EN_DEATH_H
#include "global.h"
+#include "overlays/actors/ovl_En_Minideath/z_en_minideath.h"
+#include "objects/object_death/object_death.h"
struct EnDeath;
@@ -9,9 +11,53 @@ typedef void (*EnDeathActionFunc)(struct EnDeath*, PlayState*);
typedef struct EnDeath {
/* 0x000 */ Actor actor;
- /* 0x144 */ char unk_144[0x44];
+ /* 0x144 */ SkelAnime skelAnime;
/* 0x188 */ EnDeathActionFunc actionFunc;
- /* 0x18C */ char unk_18C[0x7AC];
+ /* 0x18C */ u8 unk_18C;
+ /* 0x18D */ u8 coreGuarded;
+ /* 0x18E */ u8 holdsScythe;
+ /* 0x18F */ u8 dmgEffect;
+ /* 0x190 */ s8 numScytheAfterImages;
+ /* 0x191 */ u8 matAnimStep; // animated material color step?
+ /* 0x192 */ u8 inEarlyIntro;
+ /* 0x193 */ u8 noDrawLimbs[GOMESS_LIMB_MAX];
+ /* 0x1A9 */ u8 flameAlphas[56];
+ /* 0x1E2 */ Vec3s jointTable[GOMESS_LIMB_MAX];
+ /* 0x266 */ Vec3s morphTable[GOMESS_LIMB_MAX];
+ /* 0x2EA */ s16 floatTimer;
+ /* 0x2EC */ s16 weaponColliderLastUpdateTime;
+ /* 0x2EE */ s16 actionTimer;
+ /* 0x2F0 */ UNK_TYPE2 unk_2F0;
+ /* 0x2F2 */ s16 cloakUpperRotationModifier;
+ /* 0x2F4 */ s16 cloakLowerRotationModifier;
+ /* 0x2F6 */ s16 coreRotation;
+ /* 0x2F8 */ s16 explosiveDamageTimer;
+ /* 0x2FA */ s16 camId;
+ /* 0x2FC */ s16 lightArrowDamageTimer;
+ /* 0x300 */ s32 effectIndex;
+ /* 0x304 */ f32 scytheScale;
+ /* 0x308 */ f32 coreVelocity;
+ /* 0x30C */ f32 camEyeSpeed;
+ /* 0x310 */ f32 camAtSpeed;
+ /* 0x314 */ f32 dmgEffectScale;
+ /* 0x318 */ f32 dmgEffectSteamScale;
+ /* 0x31C */ f32 dmgEffectAlpha;
+ /* 0x320 */ Vec3f corePos;
+ /* 0x32C */ Vec3f scytheWorldPos;
+ /* 0x338 */ Vec3f scytheScreenPos;
+ /* 0x344 */ Vec3f camEyeTarget;
+ /* 0x350 */ Vec3f camAtTarget;
+ /* 0x35C */ Vec3f bodyPartsPos[14];
+ /* 0x404 */ Vec3f sparklePositions[56];
+ /* 0x6A4 */ MtxF scytheMtxF;
+ /* 0x6E4 */ EnMinideath* miniDeaths[20];
+ /* 0x734 */ AnimatedMaterial* bodyMatAnim;
+ /* 0x738 */ AnimatedMaterial* coreMatAnim;
+ /* 0x73C */ ColliderCylinder bodyCollider;
+ /* 0x788 */ ColliderQuad weaponCollider;
+ /* 0x808 */ ColliderSphere coreCollider;
+ /* 0x860 */ ColliderTris weaponSpinningCollider;
+ /* 0x880 */ ColliderTrisElement weaponSpinningColliderElements[2];
} EnDeath; // size = 0x938
#endif // Z_EN_DEATH_H
diff --git a/src/overlays/actors/ovl_En_Minideath/z_en_minideath.c b/src/overlays/actors/ovl_En_Minideath/z_en_minideath.c
index c8e0bdd42..2d4411e45 100644
--- a/src/overlays/actors/ovl_En_Minideath/z_en_minideath.c
+++ b/src/overlays/actors/ovl_En_Minideath/z_en_minideath.c
@@ -5,6 +5,8 @@
*/
#include "z_en_minideath.h"
+#include "overlays/actors/ovl_En_Death/z_en_death.h"
+#include "objects/object_death/object_death.h"
#define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10)
@@ -14,21 +16,29 @@ void EnMinideath_Init(Actor* thisx, PlayState* play);
void EnMinideath_Destroy(Actor* thisx, PlayState* play);
void EnMinideath_Update(Actor* thisx, PlayState* play);
-void func_808CA860(EnMinideath* this, PlayState* play);
-void func_808CA8F4(EnMinideath* this, PlayState* play);
-void func_808CAAEC(EnMinideath* this, PlayState* play);
-void func_808CABB0(EnMinideath* this, PlayState* play);
-void func_808CACD8(EnMinideath* this, PlayState* play);
-void func_808CAE18(EnMinideath* this, PlayState* play);
-void func_808CAF68(EnMinideath* this, PlayState* play);
-void func_808CB094(EnMinideath* this, PlayState* play);
-void func_808CB22C(EnMinideath* this, PlayState* play);
-void func_808CB454(EnMinideath* this, PlayState* play);
-void func_808CB59C(EnMinideath* this, PlayState* play);
-void func_808CB6D4(EnMinideath* this, PlayState* play);
-void func_808CB7CC(EnMinideath* this, PlayState* play);
-
-#if 0
+void EnMinideath_PreBattle(EnMinideath* this, PlayState* play);
+void EnMinideath_Intro1(EnMinideath* this, PlayState* play);
+void EnMinideath_Intro2(EnMinideath* this, PlayState* play);
+void EnMinideath_CrowdParent(EnMinideath* this, PlayState* play);
+void EnMinideath_Scatter(EnMinideath* this, PlayState* play);
+void EnMinideath_Return(EnMinideath* this, PlayState* play);
+void EnMinideath_Intro3(EnMinideath* this, PlayState* play);
+void EnMinideath_StartSwarm(EnMinideath* this, PlayState* play);
+void EnMinideath_SwarmFollower(EnMinideath* this, PlayState* play);
+void EnMinideath_SwarmLeader(EnMinideath* this, PlayState* play);
+void EnMinideath_Death1(EnMinideath* this, PlayState* play);
+void EnMinideath_Die(EnMinideath* this, PlayState* play);
+void EnMinideath_Dead(EnMinideath* this, PlayState* play);
+
+void EnMinideath_RandomizeEffects(EnMinideath* this);
+void EnMinideath_SetupPreBattle(EnMinideath* this);
+void EnMinideath_SetupIntro1(EnMinideath* this);
+void EnMinideath_SetupIntro2(EnMinideath* this);
+void EnMinideath_SetupCrowdParent(EnMinideath* this);
+void EnMinideath_SetupReturn(EnMinideath* this);
+void EnMinideath_SetupIntro3(EnMinideath* this);
+void EnMinideath_SetupDead(EnMinideath* this);
+
ActorInit En_Minideath_InitVars = {
/**/ ACTOR_EN_MINIDEATH,
/**/ ACTORCAT_ENEMY,
@@ -41,147 +51,861 @@ ActorInit En_Minideath_InitVars = {
/**/ NULL,
};
-// static ColliderJntSphElementInit sJntSphElementsInit[3] = {
-static ColliderJntSphElementInit D_808CBF50[3] = {
+static ColliderJntSphElementInit sJntSphElementsInit[3] = {
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x04 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_HARD, BUMP_ON, OCELEM_ON, },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x04 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_HARD,
+ BUMP_ON,
+ OCELEM_ON,
+ },
{ 1, { { 0, 0, 0 }, 15 }, 100 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x04 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_HARD, BUMP_ON, OCELEM_ON, },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x04 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_HARD,
+ BUMP_ON,
+ OCELEM_ON,
+ },
{ 1, { { 0, 0, 0 }, 15 }, 100 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x04 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_HARD, BUMP_ON, OCELEM_ON, },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x04 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_HARD,
+ BUMP_ON,
+ OCELEM_ON,
+ },
{ 1, { { 0, 0, 0 }, 15 }, 100 },
},
};
-// static ColliderJntSphInit sJntSphInit = {
-static ColliderJntSphInit D_808CBFBC = {
- { COLTYPE_NONE, AT_NONE | AT_TYPE_ENEMY, AC_ON | AC_TYPE_PLAYER, OC1_NONE | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_JNTSPH, },
- ARRAY_COUNT(sJntSphElementsInit), D_808CBF50, // sJntSphElementsInit,
+static ColliderJntSphInit sJntSphInit = {
+ {
+ COLTYPE_NONE,
+ AT_NONE | AT_TYPE_ENEMY,
+ AC_ON | AC_TYPE_PLAYER,
+ OC1_NONE | OC1_TYPE_ALL,
+ OC2_TYPE_1,
+ COLSHAPE_JNTSPH,
+ },
+ ARRAY_COUNT(sJntSphElementsInit),
+ sJntSphElementsInit,
};
-// static DamageTable sDamageTable = {
-static DamageTable D_808CBFCC = {
- /* Deku Nut */ DMG_ENTRY(0, 0x1),
- /* Deku Stick */ DMG_ENTRY(1, 0x0),
- /* Horse trample */ DMG_ENTRY(1, 0x0),
- /* Explosives */ DMG_ENTRY(1, 0x0),
- /* Zora boomerang */ DMG_ENTRY(1, 0x0),
- /* Normal arrow */ DMG_ENTRY(1, 0x0),
- /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0),
- /* Hookshot */ DMG_ENTRY(1, 0x0),
- /* Goron punch */ DMG_ENTRY(1, 0x0),
- /* Sword */ DMG_ENTRY(1, 0x0),
- /* Goron pound */ DMG_ENTRY(0, 0x0),
- /* Fire arrow */ DMG_ENTRY(1, 0x2),
- /* Ice arrow */ DMG_ENTRY(1, 0x3),
- /* Light arrow */ DMG_ENTRY(2, 0x4),
- /* Goron spikes */ DMG_ENTRY(1, 0x0),
- /* Deku spin */ DMG_ENTRY(1, 0x0),
- /* Deku bubble */ DMG_ENTRY(1, 0x0),
- /* Deku launch */ DMG_ENTRY(2, 0x0),
- /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x1),
- /* Zora barrier */ DMG_ENTRY(1, 0x5),
- /* Normal shield */ DMG_ENTRY(0, 0x0),
- /* Light ray */ DMG_ENTRY(0, 0x0),
- /* Thrown object */ DMG_ENTRY(1, 0x0),
- /* Zora punch */ DMG_ENTRY(1, 0x0),
- /* Spin attack */ DMG_ENTRY(1, 0x0),
- /* Sword beam */ DMG_ENTRY(0, 0x0),
- /* Normal Roll */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0),
- /* Unblockable */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0),
- /* Powder Keg */ DMG_ENTRY(1, 0x0),
+typedef enum {
+ /* 0 */ DMGEFF_NONE,
+ /* 1 */ DMGEFF_STUN,
+ /* 2 */ DMGEFF_FIRE_ARROW,
+ /* 3 */ DMGEFF_ICE_ARROW,
+ /* 4 */ DMGEFF_LIGHT_ARROW,
+ /* 5 */ DMGEFF_ZORA_BARRIER
+} EnMinideathDamageEffect;
+
+static DamageTable sDamageTable = {
+ /* Deku Nut */ DMG_ENTRY(0, DMGEFF_STUN),
+ /* Deku Stick */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Horse trample */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Explosives */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Zora boomerang */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Normal arrow */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* UNK_DMG_0x06 */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Hookshot */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Goron punch */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Sword */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Goron pound */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Fire arrow */ DMG_ENTRY(1, DMGEFF_FIRE_ARROW),
+ /* Ice arrow */ DMG_ENTRY(1, DMGEFF_ICE_ARROW),
+ /* Light arrow */ DMG_ENTRY(2, DMGEFF_LIGHT_ARROW),
+ /* Goron spikes */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Deku spin */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Deku bubble */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Deku launch */ DMG_ENTRY(2, DMGEFF_NONE),
+ /* UNK_DMG_0x12 */ DMG_ENTRY(0, DMGEFF_STUN),
+ /* Zora barrier */ DMG_ENTRY(1, DMGEFF_ZORA_BARRIER),
+ /* Normal shield */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Light ray */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Thrown object */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Zora punch */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Spin attack */ DMG_ENTRY(1, DMGEFF_NONE),
+ /* Sword beam */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Normal Roll */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* UNK_DMG_0x1B */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* UNK_DMG_0x1C */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Unblockable */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* UNK_DMG_0x1E */ DMG_ENTRY(0, DMGEFF_NONE),
+ /* Powder Keg */ DMG_ENTRY(1, DMGEFF_NONE),
};
-// sColChkInfoInit
-static CollisionCheckInfoInit D_808CBFEC = { 1, 15, 30, 10 };
+static CollisionCheckInfoInit sColChkInfoInit = { 1, 15, 30, 10 };
-// static InitChainEntry sInitChain[] = {
-static InitChainEntry D_808CBFF4[] = {
+static InitChainEntry sInitChain[] = {
ICHAIN_F32(uncullZoneScale, 100, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP),
};
-#endif
-
-extern ColliderJntSphElementInit D_808CBF50[3];
-extern ColliderJntSphInit D_808CBFBC;
-extern DamageTable D_808CBFCC;
-extern CollisionCheckInfoInit D_808CBFEC;
-extern InitChainEntry D_808CBFF4[];
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/EnMinideath_Init.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/EnMinideath_Destroy.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA268.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA308.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA34C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA458.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA7D4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA860.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA8E0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA8F4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAAC8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAAEC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAB90.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CABB0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAC54.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CACD8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAE00.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAE18.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAF08.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAF68.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB07C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB094.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB0C8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB22C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB418.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB454.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB524.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB59C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB6A8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB6D4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB7B8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB7CC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB810.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB8F4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/EnMinideath_Update.s")
+static s32 sItemDropTimer;
+static s32 sNumSwarmHits;
+static s32 sScatterTimer;
+static s32 sPlayedDeathSfx;
+
+void EnMinideath_Init(Actor* thisx, PlayState* play) {
+ EnMinideath* this = THIS;
+ s32 i;
+
+ Actor_ProcessInitChain(thisx, sInitChain);
+
+ this->initialHeightDiffFromParent = thisx->world.pos.y - thisx->parent->world.pos.y;
+ this->spawnShapeYaw = thisx->shape.rot.y;
+
+ thisx->shape.rot.y = thisx->parent->shape.rot.y;
+ thisx->world.rot.y = thisx->parent->shape.rot.y;
+ thisx->flags &= ~ACTOR_FLAG_TARGETABLE;
+
+ Collider_InitAndSetJntSph(play, &this->collider, thisx, &sJntSphInit, this->colliderElements);
+ CollisionCheck_SetInfo(&thisx->colChkInfo, &sDamageTable, &sColChkInfoInit);
+
+ for (i = 0; i < MINIDEATH_NUM_EFFECTS; i++) {
+ this->collider.elements[i].dim.worldSphere.radius = this->collider.elements[i].dim.modelSphere.radius;
+ }
+
+ EnMinideath_RandomizeEffects(this);
+
+ this->number = thisx->params;
+ thisx->params = MINIDEATH_ACTION_CONTINUE;
+ this->crowdState = false;
+
+ if (CHECK_EVENTINF(EVENTINF_INTRO_CS_WATCHED_GOMESS)) {
+ this->collider.base.atFlags |= AT_ON;
+ this->crowdState = true;
+
+ EnMinideath_CrowdParent(this, play);
+
+ for (i = 0; i < MINIDEATH_NUM_EFFECTS; i++) {
+ Math_Vec3f_Sum(&thisx->world.pos, &this->effects[i].vel, &this->effects[i].pos);
+ }
+
+ EnMinideath_SetupCrowdParent(this);
+ } else {
+ EnMinideath_SetupPreBattle(this);
+ }
+}
+
+void EnMinideath_Destroy(Actor* thisx, PlayState* play) {
+ EnMinideath* this = THIS;
+
+ Collider_DestroyJntSph(play, &this->collider);
+}
+
+void EnMinideath_DropCollectible(Vec3f* spawnPos, PlayState* play) {
+ if (sItemDropTimer == 0 && Rand_ZeroOne() < 0.3f) {
+ if (Rand_ZeroOne() < 0.5f) {
+ Item_DropCollectible(play, spawnPos, ITEM00_ARROWS_10);
+ } else {
+ Item_DropCollectible(play, spawnPos, ITEM00_MAGIC_JAR_BIG);
+ }
+ sItemDropTimer = 800; // wait 40 seconds before next drop
+ }
+}
+
+void EnMinideath_UpdateCrowdState(EnMinideath* this, s32 crowdParent) {
+ // If the state is changed to the same as before, don't update the count
+ if (this->crowdState != crowdParent) {
+ this->crowdState = crowdParent;
+
+ // Gomess params stores the number of crowding bats
+ if (crowdParent == true) {
+ this->actor.parent->params++;
+ } else {
+ this->actor.parent->params--;
+ }
+ }
+}
+
+void EnMinideath_RandomizeEffects(EnMinideath* this) {
+ MiniDeathEffect* effect;
+ s32 i;
+
+ for (effect = this->effects, i = 0; i < MINIDEATH_NUM_EFFECTS; i++, effect++) {
+ effect->vel.x = Rand_CenteredFloat(80.0f);
+ effect->vel.y = Rand_ZeroFloat(40.0f);
+ effect->vel.z = Rand_CenteredFloat(80.0f);
+ effect->animFrame = (s32)Rand_ZeroFloat(9.0f) % MINIDEATH_ANIM_LENGTH;
+ effect->angle.x = (s32)Rand_Next() >> 17;
+ effect->angle.y = (s32)Rand_Next() >> 16;
+ effect->state = 0;
+ effect->timer = 0;
+ }
+}
+
+void EnMinideath_UpdateEffects(EnMinideath* this, PlayState* play) {
+ s16 angle;
+ MiniDeathEffect* effect;
+ f32 phi_fv0;
+ f32 phi_fa0;
+ s32 i;
+ s32 phi_s7;
+ s32 phi_s3;
+
+ phi_s3 = 0;
+ phi_s7 = 0;
+
+ effect = this->effects;
+ for (i = 0; i < MINIDEATH_NUM_EFFECTS; i++, effect++) {
+ if (effect->state == 0) {
+ effect->vel.x += 3.0f * Math_CosS(effect->angle.x) * Math_SinS(effect->angle.y);
+ effect->vel.y += 3.0f * Math_SinS(effect->angle.x);
+ effect->vel.z += 3.0f * Math_CosS(effect->angle.x) * Math_CosS(effect->angle.y);
+
+ if (this->actionFunc == EnMinideath_PreBattle) {
+ phi_fv0 = 100.0f;
+ phi_fa0 = SQ(phi_fv0);
+ } else if (this->actionFunc == EnMinideath_StartSwarm || this->actionFunc == EnMinideath_SwarmLeader) {
+ phi_fv0 = 20.0f;
+ phi_fa0 = SQ(20.0f);
+ } else {
+ phi_fv0 = 40.0f;
+ phi_fa0 = SQ(40.0f);
+ }
+
+ if (effect->vel.y < 0.0f || phi_fv0 < effect->vel.y || phi_fa0 < SQ(effect->vel.x) + SQ(effect->vel.z)) {
+ angle = Math_Atan2S_XY(sqrtf(SQ(effect->vel.x) + SQ(effect->vel.z)), effect->vel.y);
+ effect->angle.x = -1 * angle + ((s32)Rand_Next() >> 19);
+ angle = Math_Atan2S_XY(effect->vel.z, effect->vel.x);
+ effect->angle.y = 0x8000 + angle + ((s32)Rand_Next() >> 19);
+ }
+
+ phi_s3++;
+ } else if (effect->state == 1) {
+ effect->pos.y += effect->vel.y;
+ effect->angle.y += 0x1800;
+ effect->vel.y -= 1.0f;
+
+ if (effect->pos.y < this->actor.parent->home.pos.y) {
+ effect->pos.y = this->actor.parent->home.pos.y;
+ func_800B3030(play, &effect->pos, &gZeroVec3f, &gZeroVec3f, 100, 0, 0);
+ SoundSource_PlaySfxAtFixedWorldPos(play, &effect->pos, 11, NA_SE_EN_EXTINCT);
+ EnMinideath_DropCollectible(&effect->pos, play);
+ effect->state = 2;
+ }
+ } else if (effect->state == 2) {
+ if (effect->timer > 0) {
+ effect->timer--;
+ } else if (this->actionFunc == EnMinideath_CrowdParent) {
+ Math_Vec3f_Diff(&this->actor.parent->focus.pos, &this->actor.world.pos, &effect->vel);
+ effect->state = 0;
+ this->collider.elements[i].info.bumperFlags |= BUMP_ON;
+ this->collider.elements[i].info.toucherFlags |= TOUCH_ON;
+ phi_s7 = 1;
+ phi_s3++;
+ }
+ }
+ }
+
+ if (phi_s7 && phi_s3 > 1) {
+ EnMinideath_UpdateCrowdState(this, true);
+ }
+}
+
+void EnMinideath_SetupPreBattle(EnMinideath* this) {
+ this->actor.speed = 6.0f;
+ this->actor.world.pos.x = Rand_CenteredFloat(600.0f) + this->actor.parent->world.pos.x;
+ this->actor.world.pos.z = Rand_CenteredFloat(600.0f) + this->actor.parent->world.pos.z;
+ this->actor.shape.rot.y = (s32)Rand_Next() >> 16;
+ this->actor.shape.rot.x = 0;
+ this->moveDirection.y = this->actor.shape.rot.y;
+ this->actionFunc = EnMinideath_PreBattle;
+}
+
+void EnMinideath_PreBattle(EnMinideath* this, PlayState* play) {
+ if (Math_ScaledStepToS(&this->actor.shape.rot.y, this->moveDirection.y, 0x480) &&
+ (this->actor.bgCheckFlags & BGCHECKFLAG_WALL)) {
+ // Fly away from walls
+ this->moveDirection.y = ((s32)Rand_Next() >> 18) + this->actor.wallYaw;
+ }
+ if (this->actor.params == MINIDEATH_ACTION_INTRO_1) {
+ EnMinideath_SetupIntro1(this);
+ }
+}
+
+void EnMinideath_SetupIntro1(EnMinideath* this) {
+ this->actionFunc = EnMinideath_Intro1;
+}
+
+void EnMinideath_Intro1(EnMinideath* this, PlayState* play) {
+ EnDeath* parent;
+ Vec3f sp38;
+ s32 phi_v0;
+ s16 angle;
+
+ Math_StepToF(&this->actor.speed, 15.0f, 0.5f);
+
+ if (this->actor.child == NULL) {
+ phi_v0 = 0;
+ angle = 0;
+ } else if (this->number == 6) {
+ phi_v0 = 1;
+ angle = 0x5555;
+ } else if (this->number == 12) {
+ phi_v0 = 2;
+ angle = -0x5556;
+ } else {
+ phi_v0 = -1;
+ Math_Vec3f_Copy(&sp38, &this->actor.child->world.pos);
+ angle = 0;
+ }
+
+ if (phi_v0 != -1) {
+ parent = (EnDeath*)this->actor.parent;
+
+ angle += parent->coreRotation;
+ sp38.x = this->actor.parent->world.pos.x + Math_SinS(angle) * parent->coreVelocity;
+ sp38.z = this->actor.parent->world.pos.z + Math_CosS(angle) * parent->coreVelocity;
+ sp38.y = this->actor.parent->world.pos.y + phi_v0 * 20;
+ }
+ Math_SmoothStepToS(&this->actor.shape.rot.y, Actor_WorldYawTowardPoint(&this->actor, &sp38), 2, 0x1000, 0x100);
+ if (this->actor.parent->scale.z > 0.0f) {
+ sp38.y = this->actor.parent->world.pos.y + this->initialHeightDiffFromParent;
+ }
+ Math_SmoothStepToS(&this->actor.shape.rot.x, Actor_WorldPitchTowardPoint(&this->actor, &sp38), 2, 0x1000, 0x100);
+ if (this->actor.params == MINIDEATH_ACTION_INTRO_2) {
+ EnMinideath_SetupIntro2(this);
+ }
+}
+
+void EnMinideath_SetupIntro2(EnMinideath* this) {
+ this->actor.params = MINIDEATH_ACTION_CONTINUE;
+ this->actionFunc = EnMinideath_Intro2;
+ this->actor.speed = 5.0f;
+}
+
+void EnMinideath_Intro2(EnMinideath* this, PlayState* play) {
+ Actor_WorldDistXYZToPoint(&this->actor, &this->actor.parent->focus.pos);
+ Math_ScaledStepToS(&this->actor.shape.rot.y,
+ Actor_WorldYawTowardPoint(&this->actor, &this->actor.parent->focus.pos), 0x800);
+ Math_ScaledStepToS(&this->actor.shape.rot.x,
+ Actor_WorldPitchTowardPoint(&this->actor, &this->actor.parent->focus.pos), 0x800);
+ if (this->actor.params == MINIDEATH_ACTION_INTRO_3) {
+ this->collider.base.atFlags |= AT_ON;
+ EnMinideath_SetupIntro3(this);
+ }
+}
+
+void EnMinideath_SetupCrowdParent(EnMinideath* this) {
+ this->actor.shape.rot.x = 0;
+ this->actionFunc = EnMinideath_CrowdParent;
+ this->actor.speed = 0.0f;
+}
+
+void EnMinideath_CrowdParent(EnMinideath* this, PlayState* play) {
+ s16 yaw = this->spawnShapeYaw + this->actor.parent->shape.rot.y;
+
+ this->actor.world.pos.x = this->actor.parent->world.pos.x + Math_SinS(yaw) * 60.0f;
+ this->actor.world.pos.z = this->actor.parent->world.pos.z + Math_CosS(yaw) * 60.0f;
+ this->actor.world.pos.y = this->actor.parent->world.pos.y + this->initialHeightDiffFromParent;
+ this->actor.shape.rot.y = this->actor.parent->shape.rot.y;
+}
+
+void EnMinideath_SetupScatter(EnMinideath* this) {
+ this->actor.params = MINIDEATH_ACTION_CONTINUE;
+ this->actor.speed = 8.0f;
+ func_800BE33C(&this->actor.parent->world.pos, &this->actor.world.pos, &this->moveDirection, false);
+ if (sScatterTimer != 0) {
+ this->timer = sScatterTimer;
+ } else {
+ this->timer = 200;
+ }
+ EnMinideath_UpdateCrowdState(this, false);
+ this->actionFunc = EnMinideath_Scatter;
+}
+
+void EnMinideath_Scatter(EnMinideath* this, PlayState* play) {
+ f32 y;
+ f32 parentY;
+
+ Math_StepToF(&this->actor.speed, 6.0f, 0.5f);
+
+ if (Math_ScaledStepToS(&this->actor.shape.rot.y, this->moveDirection.y, 0x480) &&
+ (this->actor.bgCheckFlags & BGCHECKFLAG_WALL)) {
+ // Fly away from walls
+ this->moveDirection.y = ((s32)Rand_Next() >> 18) + this->actor.wallYaw;
+ }
+
+ if (Math_ScaledStepToS(&this->actor.shape.rot.x, this->moveDirection.x, 0x480)) {
+ y = this->actor.world.pos.y;
+ parentY = this->actor.parent->home.pos.y;
+
+ if (y < parentY + 50.0f) {
+ this->moveDirection.x = -0x800 - (Rand_Next() >> 20);
+ } else if (y > parentY + 200.0f) {
+ this->moveDirection.x = 0x800 + (Rand_Next() >> 20);
+ }
+ }
+
+ if (this->timer == 0) {
+ EnMinideath_SetupReturn(this);
+ } else {
+ this->timer--;
+ }
+}
+
+void EnMinideath_SetupReturn(EnMinideath* this) {
+ this->actor.params = MINIDEATH_ACTION_CONTINUE;
+ this->actionFunc = EnMinideath_Return;
+}
+
+void EnMinideath_Return(EnMinideath* this, PlayState* play) {
+ s32 pad;
+ f32 distToParent = Actor_WorldDistXYZToPoint(&this->actor, &this->actor.parent->focus.pos);
+ f32 velocityFactor = distToParent * (1.0f / 60.0f);
+
+ if (velocityFactor > 1.0f) {
+ velocityFactor = 1.0f;
+ }
+ Math_StepToF(&this->actor.speed, 6.0f * velocityFactor, 0.5f);
+ Math_ScaledStepToS(&this->actor.shape.rot.y,
+ Actor_WorldYawTowardPoint(&this->actor, &this->actor.parent->focus.pos), 0x800);
+ Math_ScaledStepToS(&this->actor.shape.rot.x,
+ Actor_WorldPitchTowardPoint(&this->actor, &this->actor.parent->focus.pos), 0x800);
+ if (distToParent < 30.0f) {
+ EnMinideath_SetupIntro3(this);
+ }
+}
+
+void EnMinideath_SetupIntro3(EnMinideath* this) {
+ s32 i;
+
+ this->actor.speed = 0.0f;
+ EnMinideath_UpdateCrowdState(this, true);
+
+ for (i = 0; i < MINIDEATH_NUM_EFFECTS; i++) {
+ this->effects[i].timer = 0;
+ }
+ this->actionFunc = EnMinideath_Intro3;
+}
+
+void EnMinideath_Intro3(EnMinideath* this, PlayState* play) {
+ Vec3f target;
+ f32 dist;
+ s16 sp26;
+ s32 stepDone;
+
+ stepDone =
+ Math_ScaledStepToS(&this->actor.shape.rot.y, this->spawnShapeYaw + this->actor.parent->shape.rot.y, 0x800);
+ Math_ScaledStepToS(&this->actor.shape.rot.x, 0, 0x800);
+ sp26 = this->spawnShapeYaw + this->actor.parent->shape.rot.y;
+ target.x = this->actor.parent->world.pos.x + Math_SinS(sp26) * 60.0f;
+ target.z = this->actor.parent->world.pos.z + Math_CosS(sp26) * 60.0f;
+ target.y = this->actor.parent->world.pos.y + this->initialHeightDiffFromParent;
+
+ dist = Math_Vec3f_StepTo(&this->actor.world.pos, &target, 10.0f);
+ if (stepDone && dist < 20.0f) {
+ EnMinideath_SetupCrowdParent(this);
+ }
+}
+
+void EnMinideath_SetupStartSwarm(EnMinideath* this) {
+ this->actor.params = MINIDEATH_ACTION_CONTINUE;
+ this->actionFunc = EnMinideath_StartSwarm;
+}
+
+void EnMinideath_StartSwarm(EnMinideath* this, PlayState* play) {
+ Math_Vec3f_StepTo(&this->actor.world.pos, &this->actor.parent->focus.pos, 5.0f);
+}
+
+void EnMinideath_SetupSwarmFollower(EnMinideath* this, PlayState* play) {
+ s32 phi_a2;
+ s32 phi_v1;
+ s32 phi_a1;
+
+ this->actor.params = MINIDEATH_ACTION_CONTINUE;
+ this->actor.speed = 8.0f;
+
+ if (this->number >= 10) {
+ phi_v1 = 19 - this->number;
+ phi_a1 = 1;
+ phi_a2 = 0;
+ } else {
+ phi_v1 = 9 - this->number;
+ phi_a1 = -1;
+ phi_a2 = 0x200;
+ }
+ this->actor.shape.rot.y = this->actor.parent->shape.rot.y + 0x4000 * phi_a1 + 0x2000 * phi_v1 * phi_a1;
+ this->actor.shape.rot.x = 0xC00 + phi_a2 - 0x400 * phi_v1;
+
+ this->actor.world.pos.x = this->actor.parent->focus.pos.x + Math_SinS(this->actor.shape.rot.y) * 60.0f;
+ this->actor.world.pos.z = this->actor.parent->focus.pos.z + Math_CosS(this->actor.shape.rot.y) * 60.0f;
+ this->actor.world.pos.y = this->actor.parent->focus.pos.y - Math_SinS(this->actor.shape.rot.x) * 60.0f;
+
+ EnMinideath_RandomizeEffects(this);
+ this->timer = 100;
+ EnMinideath_UpdateCrowdState(this, false);
+
+ sNumSwarmHits = 0;
+
+ if (this->actor.child == NULL || this->number == 9) {
+ this->targetActor = &GET_PLAYER(play)->actor;
+ } else {
+ this->targetActor = this->actor.child;
+ }
+ this->actionFunc = EnMinideath_SwarmFollower;
+}
+
+void EnMinideath_SwarmFollower(EnMinideath* this, PlayState* play) {
+ Vec3f targetFocus;
+ s16 yawOffset = 0;
+
+ Math_StepToF(&this->actor.speed, 6.0f, 0.2f);
+ if (this->timer > 0) {
+ this->timer--;
+ }
+
+ if (this->targetActor->id != ACTOR_EN_MINIDEATH) {
+ if (this->timer == 0) {
+ this->targetActor = this->actor.parent;
+ }
+ Math_Vec3f_Copy(&targetFocus, &this->targetActor->focus.pos);
+ if (Actor_WorldDistXYZToPoint(&this->actor, &targetFocus) > 200.0f) {
+ if (this->number < 10) {
+ yawOffset = -0x1C00;
+ } else {
+ yawOffset = 0x1C00;
+ }
+ targetFocus.y += 50.0f;
+ }
+ } else {
+ if (((EnMinideath*)this->targetActor)->actionFunc != EnMinideath_SwarmFollower) {
+ Math_Vec3f_Copy(&targetFocus, &this->actor.parent->focus.pos);
+ } else {
+ Math_Vec3f_Copy(&targetFocus, &this->targetActor->focus.pos);
+ }
+ }
+ Math_SmoothStepToS(&this->actor.shape.rot.y, Actor_WorldYawTowardPoint(&this->actor, &targetFocus) + yawOffset, 5,
+ 0xC00, 0x80);
+ Math_SmoothStepToS(&this->actor.shape.rot.x, Actor_WorldPitchTowardPoint(&this->actor, &targetFocus), 5, 0xC00,
+ 0x80);
+ if ((this->collider.base.atFlags & AT_HIT) && this->timer > 0) {
+ sNumSwarmHits++;
+ }
+ if (this->timer == 0 && Actor_WorldDistXYZToPoint(&this->actor, &this->actor.parent->focus.pos) < 50.0f) {
+ EnMinideath_SetupIntro3(this);
+ }
+}
+
+void EnMinideath_SetupSwarmLeader(EnMinideath* this) {
+ this->actor.params = MINIDEATH_ACTION_CONTINUE;
+ this->timer = 10;
+ EnMinideath_RandomizeEffects(this);
+ this->actionFunc = EnMinideath_SwarmLeader;
+}
+
+void EnMinideath_SwarmLeader(EnMinideath* this, PlayState* play) {
+ Vec3f target;
+
+ if (this->timer > 0) {
+ this->timer--;
+ }
+ target.x = (Math_SinS(this->actor.parent->shape.rot.y) * 20.0f) + this->actor.parent->focus.pos.x;
+ target.z = (Math_CosS(this->actor.parent->shape.rot.y) * 20.0f) + this->actor.parent->focus.pos.z;
+ target.y = this->actor.parent->focus.pos.y;
+ Math_Vec3f_StepTo(&this->actor.world.pos, &target, 5.0f);
+ if (this->timer == 0 && ((EnMinideath*)this->actor.child)->actionFunc != EnMinideath_SwarmFollower) {
+ EnMinideath_SetupCrowdParent(this);
+ }
+}
+
+void EnMinideath_SetupDeath1(EnMinideath* this) {
+ s32 i;
+
+ this->actor.params = MINIDEATH_ACTION_CONTINUE;
+ EnMinideath_UpdateCrowdState(this, false);
+ this->collider.base.atFlags &= ~AT_ON;
+
+ for (i = 0; i < MINIDEATH_NUM_EFFECTS; i++) {
+ this->effects[i].state = 0;
+ }
+
+ this->moveDirection.y = this->actor.shape.rot.y;
+ this->moveDirection.x = this->actor.shape.rot.x;
+ this->actionFunc = EnMinideath_Death1;
+}
+
+void EnMinideath_Death1(EnMinideath* this, PlayState* play) {
+ f32 y;
+ f32 parentY;
+
+ Math_StepToF(&this->actor.speed, 5.0f, 0.2f);
+ if (Math_ScaledStepToS(&this->actor.shape.rot.y, this->moveDirection.y, 0x480) &&
+ (this->actor.bgCheckFlags & BGCHECKFLAG_WALL)) {
+ // Fly away from walls
+ this->moveDirection.y = ((s32)Rand_Next() >> 18) + this->actor.wallYaw;
+ }
+
+ if (Math_ScaledStepToS(&this->actor.shape.rot.x, this->moveDirection.x, 0x480)) {
+ y = this->actor.world.pos.y;
+ parentY = this->actor.parent->home.pos.y;
+ if (y < parentY + 50.0f) {
+ this->moveDirection.x = -0x800 - (Rand_Next() >> 20);
+ } else if (y > parentY + 200.0f) {
+ this->moveDirection.x = 0x800 + (Rand_Next() >> 20);
+ }
+ }
+}
+
+void EnMinideath_SetupDie(EnMinideath* this) {
+ this->actor.params = MINIDEATH_ACTION_CONTINUE;
+ this->moveDirection.x = 0x4000;
+ this->actionFunc = EnMinideath_Die;
+ this->actor.gravity = -0.5f;
+}
+
+void EnMinideath_Die(EnMinideath* this, PlayState* play) {
+ MiniDeathEffect* effect;
+ s32 i;
+ s32 stepsComplete = 0;
+
+ Math_StepToF(&this->actor.speed, 0.0f, 0.2f);
+ Math_ScaledStepToS(&this->actor.shape.rot.x, this->moveDirection.x, 0x480);
+ Actor_PlaySfx_Flagged(&this->actor, NA_SE_EN_COMMON_EXTINCT_LEV - SFX_FLAG);
+
+ if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND) {
+ this->actor.speed = 0.0f;
+
+ for (effect = this->effects, i = 0; i < MINIDEATH_NUM_EFFECTS; i++, effect++) {
+ if (Math_StepToF(&effect->vel.y, 0.0f, 7.0f)) {
+ stepsComplete++;
+ }
+ }
+ if (stepsComplete == MINIDEATH_NUM_EFFECTS) {
+ EnMinideath_SetupDead(this);
+ }
+ }
+}
+
+void EnMinideath_SetupDead(EnMinideath* this) {
+ this->actionFunc = EnMinideath_Dead;
+}
+
+void EnMinideath_Dead(EnMinideath* this, PlayState* play) {
+ if (this->actor.parent->update == NULL) {
+ Actor_Kill(&this->actor);
+ } else {
+ Actor_PlaySfx_Flagged(&this->actor, NA_SE_EN_COMMON_EXTINCT_LEV - SFX_FLAG);
+ }
+}
+
+void EnMinideath_SetNextAction(EnMinideath* this, PlayState* play) {
+ s16 action = this->actor.params;
+
+ if (action == MINIDEATH_ACTION_DEATH_1) {
+ EnMinideath_SetupDeath1(this);
+ } else if (action == MINIDEATH_ACTION_RETURN) {
+ EnMinideath_SetupReturn(this);
+ } else if (action == MINIDEATH_ACTION_START_SWARM) {
+ EnMinideath_SetupStartSwarm(this);
+ } else if (action == MINIDEATH_ACTION_SWARM) {
+ if (this->number == 0 || this->number == 10) {
+ // Bats 0 and 10 set the general motion trajectory
+ EnMinideath_SetupSwarmLeader(this);
+ } else {
+ // These ones follow around 0 and 10
+ EnMinideath_SetupSwarmFollower(this, play);
+ }
+ } else if (action == MINIDEATH_ACTION_SCATTER) {
+ EnMinideath_SetupScatter(this);
+ } else if (action == MINIDEATH_ACTION_DEATH_2) {
+ EnMinideath_SetupDie(this);
+ }
+}
+
+void EnMinideath_UpdateDamage(EnMinideath* this, PlayState* play) {
+ if (this->collider.base.acFlags & AC_HIT) {
+ this->collider.base.acFlags &= ~AC_HIT;
+
+ if (this->actor.colChkInfo.damageEffect == DMGEFF_STUN) {
+ if (this->actionFunc == EnMinideath_CrowdParent || this->actionFunc == EnMinideath_Intro3) {
+ sScatterTimer = 5;
+ } else if (this->actionFunc == EnMinideath_SwarmFollower) {
+ EnMinideath** miniDeaths = ((EnDeath*)this->actor.parent)->miniDeaths;
+ s32 i;
+
+ for (i = this->number - 1; i >= 0; i--) {
+ EnMinideath* other = miniDeaths[i];
+
+ if (other->targetActor == &this->actor) {
+ other->targetActor = this->targetActor;
+ break;
+ }
+ }
+
+ this->timer = 0;
+ this->targetActor = &GET_PLAYER(play)->actor;
+ }
+ } else {
+ s32 i;
+ s32 j;
+ s32 phi_a0;
+
+ for (i = 0; i < MINIDEATH_NUM_EFFECTS; i++) {
+ if (this->collider.elements[i].info.bumperFlags & BUMP_HIT) {
+ this->collider.elements[i].info.bumperFlags &= ~(BUMP_ON | BUMP_HIT);
+ this->collider.elements[i].info.toucherFlags &= ~(TOUCH_ON | TOUCH_HIT);
+ this->effects[i].vel.y = -1.0f;
+ this->effects[i].state = 1;
+ this->effects[i].angle.y = this->actor.shape.rot.y;
+ this->effects[i].timer = 60;
+
+ if ((this->actionFunc == EnMinideath_CrowdParent || this->actionFunc == EnMinideath_Intro3) &&
+ this->actor.colChkInfo.damageEffect == DMGEFF_LIGHT_ARROW) {
+ sScatterTimer = 200;
+ }
+ }
+ }
+
+ phi_a0 = 0;
+ for (j = 0; j < MINIDEATH_NUM_EFFECTS; j++) {
+ if (this->effects[j].state != 0) {
+ phi_a0++;
+ }
+ }
+
+ if (phi_a0 > 1) {
+ EnMinideath_UpdateCrowdState(this, false);
+ }
+
+ if (!sPlayedDeathSfx) {
+ Actor_PlaySfx(&this->actor, NA_SE_EN_FFLY_DEAD);
+ sPlayedDeathSfx = true;
+ }
+ }
+ }
+}
+
+void EnMinideath_Update(Actor* thisx, PlayState* play) {
+ EnMinideath* this = THIS;
+ s32 pad;
+ ColliderJntSphElement* elem;
+ s32 temp;
+ s32 i;
+ MiniDeathEffect* effect;
+
+ if (sItemDropTimer > 0) {
+ sItemDropTimer--;
+ }
+
+ if (this->actionFunc != EnMinideath_Dead) {
+ for (i = 0; i < MINIDEATH_NUM_EFFECTS; i++) {
+ if (this->effects[i].state == 0) {
+ Actor_PlaySfx_Flagged(&this->actor, NA_SE_EV_BAT_FLY - SFX_FLAG);
+ break;
+ }
+ }
+ }
+
+ EnMinideath_UpdateDamage(this, play);
+
+ EnMinideath_SetNextAction(this, play);
+ this->actionFunc(this, play);
+
+ if (this->actionFunc != EnMinideath_Dead) {
+ this->actor.world.rot.y = this->actor.shape.rot.y;
+ this->actor.world.rot.x = -this->actor.shape.rot.x;
+
+ if (this->actionFunc == EnMinideath_Die) {
+ Actor_MoveWithGravity(&this->actor);
+ } else {
+ Actor_MoveWithoutGravity(&this->actor);
+ }
+
+ if (this->actionFunc != EnMinideath_CrowdParent && this->actionFunc != EnMinideath_Intro3) {
+ Actor_UpdateBgCheckInfo(play, &this->actor, 30.0f, 50.0f, 80.0f, 7);
+ }
+
+ if (this->actionFunc != EnMinideath_Die) {
+ EnMinideath_UpdateEffects(this, play);
+ }
+
+ Actor_SetFocus(&this->actor, 0.0f);
+
+ effect = this->effects;
+ elem = this->collider.elements;
+ for (i = 0; i != MINIDEATH_NUM_EFFECTS; i++) {
+ if (effect->state == 0) {
+ Math_Vec3f_Sum(&this->actor.world.pos, &effect->vel, &effect->pos);
+
+ if (this->actionFunc != EnMinideath_Die) {
+ effect->animFrame++;
+ if (effect->animFrame == MINIDEATH_ANIM_LENGTH) {
+ effect->animFrame = 0;
+ }
+ }
+
+ elem->dim.worldSphere.center.x = effect->pos.x;
+ elem->dim.worldSphere.center.y = effect->pos.y;
+ elem->dim.worldSphere.center.z = effect->pos.z;
+ }
+ effect++;
+ elem++;
+ }
+
+ if (this->collider.base.atFlags & AT_HIT) {
+ this->collider.base.atFlags &= ~AT_HIT;
+ this->attackTimer = 40;
+ Actor_PlaySfx(&this->actor, NA_SE_EN_FFLY_ATTACK);
+ }
+ if (this->collider.base.atFlags & AT_ON) {
+ temp = (this->actionFunc == EnMinideath_CrowdParent) ? (play->gameplayFrames % 4) : 4;
+
+ if (temp == 4 || temp == (this->number & 3)) {
+ if (this->attackTimer == 0 && this->actor.parent->shape.rot.x == 0) {
+ CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base);
+ }
+ if (this->actionFunc != EnMinideath_StartSwarm) {
+ CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base);
+ }
+ }
+ }
+ if (this->attackTimer > 0) {
+ this->attackTimer--;
+ }
+ if (this->number == 19) {
+ EnMinideath* other = NULL;
+ sPlayedDeathSfx = false;
+
+ if (sScatterTimer != 0) {
+ do {
+ other = (EnMinideath*)SubS_FindActor(play, &other->actor, ACTORCAT_ENEMY, ACTOR_EN_MINIDEATH);
+ if (other != NULL) {
+ EnMinideath_SetupScatter(other);
+ other = (EnMinideath*)other->actor.next;
+ }
+ } while (other != NULL);
+
+ play->envCtx.lightSettingOverride = 28;
+
+ if (sScatterTimer == 5) {
+ ((EnDeath*)this->actor.parent)->lightArrowDamageTimer = 5;
+ } else {
+ ((EnDeath*)this->actor.parent)->lightArrowDamageTimer = 20;
+ }
+ sScatterTimer = 0;
+ } else if (sNumSwarmHits >= 5) {
+ do {
+ other = (EnMinideath*)SubS_FindActor(play, &other->actor, ACTORCAT_ENEMY, ACTOR_EN_MINIDEATH);
+ if (other != NULL) {
+ other->timer = 0;
+ other = (EnMinideath*)other->actor.next;
+ }
+ } while (other != NULL);
+ sNumSwarmHits = 0;
+ }
+ }
+ }
+}
diff --git a/src/overlays/actors/ovl_En_Minideath/z_en_minideath.h b/src/overlays/actors/ovl_En_Minideath/z_en_minideath.h
index 0a08318ab..0e42ce7f0 100644
--- a/src/overlays/actors/ovl_En_Minideath/z_en_minideath.h
+++ b/src/overlays/actors/ovl_En_Minideath/z_en_minideath.h
@@ -7,10 +7,47 @@ struct EnMinideath;
typedef void (*EnMinideathActionFunc)(struct EnMinideath*, PlayState*);
+#define MINIDEATH_NUM_EFFECTS 3
+
+// "animation" length
+#define MINIDEATH_ANIM_LENGTH 9
+
+typedef enum {
+ /* 0 */ MINIDEATH_ACTION_CONTINUE, // continue with current action until it is changed
+ /* 1 */ MINIDEATH_ACTION_SCATTER, // scatter after light arrows?
+ /* 2 */ MINIDEATH_ACTION_RETURN, // gomess damaged
+ /* 3 */ MINIDEATH_ACTION_START_SWARM,
+ /* 4 */ MINIDEATH_ACTION_SWARM, // chase player?
+ /* 5 */ MINIDEATH_ACTION_DEATH_2, // death cs part 3
+ /* 6 */ MINIDEATH_ACTION_DEATH_1, // death cs part 1
+ /* 7 */ MINIDEATH_ACTION_INTRO_1, // intro cs part 2
+ /* 8 */ MINIDEATH_ACTION_INTRO_2, // intro cs part 5 (1)
+ /* 9 */ MINIDEATH_ACTION_INTRO_3 // intro cs part 5 (2)
+} MinideathAction;
+
+typedef struct {
+ /* 0x00 */ u8 animFrame;
+ /* 0x01 */ u8 state;
+ /* 0x04 */ Vec3f pos;
+ /* 0x10 */ Vec3f vel;
+ /* 0x1C */ Vec3s angle;
+ /* 0x22 */ s16 timer;
+} MiniDeathEffect; // size = 0x24
+
typedef struct EnMinideath {
/* 0x000 */ Actor actor;
/* 0x144 */ EnMinideathActionFunc actionFunc;
- /* 0x148 */ char unk_148[0x164];
+ /* 0x148 */ u8 number;
+ /* 0x149 */ u8 crowdState;
+ /* 0x14A */ s16 timer;
+ /* 0x14C */ s16 spawnShapeYaw;
+ /* 0x14E */ s16 attackTimer;
+ /* 0x150 */ Vec3s moveDirection;
+ /* 0x158 */ f32 initialHeightDiffFromParent;
+ /* 0x15C */ Actor* targetActor;
+ /* 0x160 */ MiniDeathEffect effects[MINIDEATH_NUM_EFFECTS];
+ /* 0x1CC */ ColliderJntSph collider;
+ /* 0x1EC */ ColliderJntSphElement colliderElements[MINIDEATH_NUM_EFFECTS];
} EnMinideath; // size = 0x2AC
#endif // Z_EN_MINIDEATH_H
diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt
index 5ad93e571..3b259bea7 100644
--- a/tools/disasm/functions.txt
+++ b/tools/disasm/functions.txt
@@ -6188,10 +6188,10 @@
0x808C7888:("func_808C7888",),
0x808C7A30:("func_808C7A30",),
0x808C7AAC:("func_808C7AAC",),
- 0x808C7AEC:("func_808C7AEC",),
- 0x808C7B88:("func_808C7B88",),
- 0x808C7C04:("func_808C7C04",),
- 0x808C7C88:("func_808C7C88",),
+ 0x808C7AEC:("EnDeath_SetupStartBatSwarm",),
+ 0x808C7B88:("EnDeath_StartBatSwarm",),
+ 0x808C7C04:("EnDeath_SetupBatSwarm",),
+ 0x808C7C88:("EnDeath_BatSwarm",),
0x808C7CFC:("func_808C7CFC",),
0x808C7D34:("func_808C7D34",),
0x808C7DB8:("func_808C7DB8",),
@@ -6209,38 +6209,38 @@
0x808C96C8:("EnDeath_Draw",),
0x808CA0B0:("EnMinideath_Init",),
0x808CA23C:("EnMinideath_Destroy",),
- 0x808CA268:("func_808CA268",),
- 0x808CA308:("func_808CA308",),
- 0x808CA34C:("func_808CA34C",),
- 0x808CA458:("func_808CA458",),
- 0x808CA7D4:("func_808CA7D4",),
- 0x808CA860:("func_808CA860",),
- 0x808CA8E0:("func_808CA8E0",),
- 0x808CA8F4:("func_808CA8F4",),
- 0x808CAAC8:("func_808CAAC8",),
- 0x808CAAEC:("func_808CAAEC",),
- 0x808CAB90:("func_808CAB90",),
- 0x808CABB0:("func_808CABB0",),
- 0x808CAC54:("func_808CAC54",),
- 0x808CACD8:("func_808CACD8",),
- 0x808CAE00:("func_808CAE00",),
- 0x808CAE18:("func_808CAE18",),
- 0x808CAF08:("func_808CAF08",),
- 0x808CAF68:("func_808CAF68",),
- 0x808CB07C:("func_808CB07C",),
- 0x808CB094:("func_808CB094",),
- 0x808CB0C8:("func_808CB0C8",),
- 0x808CB22C:("func_808CB22C",),
- 0x808CB418:("func_808CB418",),
- 0x808CB454:("func_808CB454",),
- 0x808CB524:("func_808CB524",),
- 0x808CB59C:("func_808CB59C",),
- 0x808CB6A8:("func_808CB6A8",),
- 0x808CB6D4:("func_808CB6D4",),
- 0x808CB7B8:("func_808CB7B8",),
- 0x808CB7CC:("func_808CB7CC",),
- 0x808CB810:("func_808CB810",),
- 0x808CB8F4:("func_808CB8F4",),
+ 0x808CA268:("EnMinideath_DropCollectible",),
+ 0x808CA308:("EnMinideath_UpdateCrowdState",),
+ 0x808CA34C:("EnMinideath_RandomizeEffects",),
+ 0x808CA458:("EnMinideath_UpdateEffects",),
+ 0x808CA7D4:("EnMinideath_SetupPreBattle",),
+ 0x808CA860:("EnMinideath_PreBattle",),
+ 0x808CA8E0:("EnMinideath_SetupIntro1",),
+ 0x808CA8F4:("EnMinideath_Intro1",),
+ 0x808CAAC8:("EnMinideath_SetupIntro2",),
+ 0x808CAAEC:("EnMinideath_Intro2",),
+ 0x808CAB90:("EnMinideath_SetupCrowdParent",),
+ 0x808CABB0:("EnMinideath_CrowdParent",),
+ 0x808CAC54:("EnMinideath_SetupScatter",),
+ 0x808CACD8:("EnMinideath_Scatter",),
+ 0x808CAE00:("EnMinideath_SetupReturn",),
+ 0x808CAE18:("EnMinideath_Return",),
+ 0x808CAF08:("EnMinideath_SetupIntro3",),
+ 0x808CAF68:("EnMinideath_Intro3",),
+ 0x808CB07C:("EnMinideath_SetupStartSwarm",),
+ 0x808CB094:("EnMinideath_StartSwarm",),
+ 0x808CB0C8:("EnMinideath_SetupSwarmFollower",),
+ 0x808CB22C:("EnMinideath_SwarmFollower",),
+ 0x808CB418:("EnMinideath_SetupSwarmLeader",),
+ 0x808CB454:("EnMinideath_SwarmLeader",),
+ 0x808CB524:("EnMinideath_SetupDeath1",),
+ 0x808CB59C:("EnMinideath_Death1",),
+ 0x808CB6A8:("EnMinideath_SetupDie",),
+ 0x808CB6D4:("EnMinideath_Die",),
+ 0x808CB7B8:("EnMinideath_SetupDead",),
+ 0x808CB7CC:("EnMinideath_Dead",),
+ 0x808CB810:("EnMinideath_SetNextAction",),
+ 0x808CB8F4:("EnMinideath_UpdateDamage",),
0x808CBB18:("EnMinideath_Update",),
0x808CC260:("EnVm_Init",),
0x808CC3E0:("EnVm_Destroy",),