diff --git a/assets/xml/objects/object_death.xml b/assets/xml/objects/object_death.xml index 7588c484a..6c75cc824 100644 --- a/assets/xml/objects/object_death.xml +++ b/assets/xml/objects/object_death.xml @@ -1,12 +1,12 @@  - - - - - - - + + + + + + + @@ -39,47 +39,47 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spec b/spec index f44741aea..6067fba85 100644 --- a/spec +++ b/spec @@ -1029,17 +1029,14 @@ beginseg name "ovl_En_Death" compress include "build/src/overlays/actors/ovl_En_Death/z_en_death.o" - include "build/data/ovl_En_Death/ovl_En_Death.data.o" - include "build/data/ovl_En_Death/ovl_En_Death.reloc.o" + include "build/src/overlays/actors/ovl_En_Death/ovl_En_Death_reloc.o" endseg beginseg name "ovl_En_Minideath" compress include "build/src/overlays/actors/ovl_En_Minideath/z_en_minideath.o" - include "build/data/ovl_En_Minideath/ovl_En_Minideath.data.o" - include "build/data/ovl_En_Minideath/ovl_En_Minideath.bss.o" - include "build/data/ovl_En_Minideath/ovl_En_Minideath.reloc.o" + include "build/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..80b294063 100644 --- a/src/overlays/actors/ovl_En_Death/z_en_death.c +++ b/src/overlays/actors/ovl_En_Death/z_en_death.c @@ -6,6 +6,9 @@ #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" +#include "prevent_bss_reordering2.h" #define FLAGS (ACTOR_FLAG_TARGETABLE | ACTOR_FLAG_UNFRIENDLY | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_IGNORE_QUAKE) @@ -15,119 +18,212 @@ void EnDeath_Init(Actor* thisx, PlayState* play); 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 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 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); +void EnDeath_PlayCutscene(EnDeath* this, PlayState* play); +void EnDeath_BeginWithoutCutscene(EnDeath* this, PlayState* play); -#if 0 -ActorInit En_Death_InitVars = { - /**/ ACTOR_EN_DEATH, - /**/ ACTORCAT_ENEMY, - /**/ FLAGS, - /**/ OBJECT_DEATH, - /**/ sizeof(EnDeath), - /**/ EnDeath_Init, - /**/ EnDeath_Destroy, - /**/ EnDeath_Update, - /**/ EnDeath_Draw, +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 func_808C7AEC(EnDeath* this); +void func_808C7C04(EnDeath* this); +void EnDeath_SetupPlayCutscene(EnDeath* this); +void EnDeath_SetupBeginWithoutCutscene(EnDeath* this); +void EnDeath_SetupDeathCutscenePart4(EnDeath* this); + +const ActorInit En_Death_InitVars = { + ACTOR_EN_DEATH, + ACTORCAT_ENEMY, + FLAGS, + OBJECT_DEATH, + sizeof(EnDeath), + (ActorFunc)EnDeath_Init, + (ActorFunc)EnDeath_Destroy, + (ActorFunc)EnDeath_Update, + (ActorFunc)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, }, + { + 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, }, + { + 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] = { { - { 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, + { + COLTYPE_METAL, + AT_ON | AT_TYPE_ENEMY, + AC_ON | AC_HARD | AC_TYPE_PLAYER, + OC1_NONE, + OC2_TYPE_1, + COLSHAPE_TRIS, + }, + 2, + D_808C9938, // 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, }, + { + 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 } } }, }; +typedef enum { + DMGEFF_NONE = 0, + DMGEFF_FIRE_ARROW = 2, + DMGEFF_ICE_ARROW = 3, + DMGEFF_LIGHT_ARROW = 4, + DMGEFF_EXPLOSIVES = 15 +} EnDeathDamageEffect; + // 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), + /* 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 EffectBlureInit2 D_808C9A3C = { + 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[] = { static InitChainEntry D_808C9A60[] = { ICHAIN_VEC3F(scale, 0, ICHAIN_CONTINUE), @@ -136,144 +232,1531 @@ static InitChainEntry D_808C9A60[] = { ICHAIN_U8(targetMode, TARGET_MODE_5, ICHAIN_STOP), }; -#endif +void EnDeath_Init(Actor* thisx, PlayState* play) { + EnDeath* this = THIS; + PlayState* play2 = play; + f32 yOffset = 15.0f; + s16 yRot = 0; + s32 i; -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[]; + Actor_ProcessInitChain(&this->actor, D_808C9A60); + ActorShape_Init(&this->actor.shape, 5500.0f, ActorShadow_DrawCircle, 80.0f); -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; + SkelAnime_InitFlex(play2, &this->skelAnime, &gGomessSkel, &gGomessFloatAnim, this->jointTable, + this->morphTable, GOMESS_LIMB_MAX); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/EnDeath_Init.s") + Collider_InitAndSetSphere(play2, &this->coreCollider, &this->actor, &D_808C98E0); + Collider_InitAndSetCylinder(play2, &this->bodyCollider, &this->actor, &D_808C990C); + Collider_InitAndSetQuad(play2, &this->unk_788, &this->actor, &D_808C99C0); + Collider_InitAndSetTris(play2, &this->unk_860, &this->actor, &D_808C99B0, this->unk_880); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/EnDeath_Destroy.s") + this->coreCollider.dim.worldSphere.radius = this->coreCollider.dim.modelSphere.radius; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5310.s") + CollisionCheck_SetInfo2(&this->actor.colChkInfo, &D_808C9A10, &D_808C9A30); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5394.s") + Effect_Add(play2, &this->effectIndex, EFFECT_BLURE2, 0, 0, &D_808C9A3C); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5428.s") + if (!(gSaveContext.eventInf[6] & 8)) { + this->actor.world.pos.y += 400.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C54F0.s") + for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) { + this->miniDeaths[i] = (EnMinideath*)Actor_SpawnAsChild( + &play2->actorCtx, &this->actor, play2, 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; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C566C.s") + for (i = 0; i < ARRAY_COUNT(this->miniDeaths) - 1; i++) { + this->miniDeaths[i]->actor.child = &this->miniDeaths[i + 1]->actor; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C571C.s") + this->bodyMatAnim = Lib_SegmentedToVirtual(&gGomessBodyMatAnim); + this->coreMatAnim = Lib_SegmentedToVirtual(&gGomessCoreMatAnim); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C589C.s") + if (gSaveContext.eventInf[6] & 8) { + // Watched intro cutscene + this->unk_18E = true; + Actor_SetScale(&this->actor, 0.01f); + this->unk_191 = 0x17; + this->actor.params = 20; + this->scytheScale = 1.0f; + EnDeath_SetupBeginWithoutCutscene(this); + } else { + // Start intro cutscene + this->unk_192 = true; + this->actor.flags &= ~ACTOR_FLAG_TARGETABLE; + EnDeath_SetupPlayCutscene(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C597C.s") +void EnDeath_Destroy(Actor* thisx, PlayState* play) { + EnDeath* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5AB8.s") + Collider_DestroySphere(play, &this->coreCollider); + Collider_DestroyCylinder(play, &this->bodyCollider); + Collider_DestroyQuad(play, &this->unk_788); + Collider_DestroyTris(play, &this->unk_860); + AudioSfx_StopByPos(&this->scytheScreenPos); + Effect_Destroy(play, this->effectIndex); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5C0C.s") +void EnDeath_DimLights(PlayState* play) { + EnvLightSettings* lightSettings; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5CB4.s") + play->envCtx.lightSettingOverride = 20; + play->envCtx.lightSetting = 20; + play->envCtx.prevLightSetting = 20; + play->envCtx.lightBlend = 1.0f; + lightSettings = &play->envCtx.lightSettingsList[20]; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5D6C.s") + for (i = 0; i != 3; i++) { + lightSettings->light1Dir[i] = play->envCtx.lightSettings.light1Dir[i]; + lightSettings->light2Dir[i] = play->envCtx.lightSettings.light2Dir[i]; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5E90.s") +void EnDeath_Float(EnDeath* this) { + Actor_PlaySfx_Flagged(&this->actor, NA_SE_EN_SHARP_FLOAT - SFX_FLAG); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C5F58.s") + 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; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6070.s") +s32 EnDeath_ProjectileApproaching(EnDeath* this, PlayState* play) { + Actor* projectileActor = + func_800BC270(play, &this->actor, 80.0f, 0x10000 | 0x2000 | 0x1000 | 0x800 | 0x80 | 0x20 | 0x10); + s16 ret; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C645C.s") + if (projectileActor != NULL && + (ret = Actor_WorldYawTowardActor(&this->actor, projectileActor) - this->actor.shape.rot.y, + ABS_ALT(ret) < 0x2000) && + (ret = Actor_WorldPitchTowardPoint(projectileActor, &this->actor.focus.pos) - projectileActor->world.rot.x, + ABS_ALT(ret) < 0x3000)) { + return true; + } + return false; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C64DC.s") +void EnDeath_UpdateSpinAttackTris(EnDeath* this) { + f32 sinRotY = Math_SinS(this->actor.shape.rot.y); + f32 cosRotY = Math_CosS(this->actor.shape.rot.y); + Vec3f sp54; + Vec3f sp48; + Vec3f sp3C; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6620.s") + sp3C.x = this->actor.world.pos.x - 70.0f * cosRotY + 75.0f * sinRotY; + sp3C.y = this->actor.world.pos.y + -10.0f; + sp3C.z = this->actor.world.pos.z + 70.0f * sinRotY + 75.0f * cosRotY; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C66A8.s") + sp48.x = this->actor.world.pos.x + 70.0f * cosRotY + 65.0f * sinRotY; + sp48.y = sp3C.y + 150.0f; + sp48.z = this->actor.world.pos.z - 70.0f * sinRotY + 65.0f * cosRotY; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C67C8.s") + sp54.x = sp3C.x; + sp54.x += -10.0f * sinRotY; + sp54.y = sp48.y; + sp54.z = sp3C.z; + sp54.z += -10.0f * cosRotY; + Collider_SetTrisVertices(&this->unk_860, 0, &sp3C, &sp48, &sp54); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C682C.s") + sp54.x = sp48.x; + sp54.x += 10.0f * sinRotY; + sp54.y = sp3C.y; + sp54.z = sp48.z; + sp54.z += 10.0f * cosRotY; + Collider_SetTrisVertices(&this->unk_860, 1, &sp3C, &sp54, &sp48); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C68B8.s") +f32 EnDeath_UpdateCoreVelocityAndRotation(EnDeath* this) { + f32 tmp; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C692C.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6A08.s") + tmp = 22.5f / (this->coreVelocity * (2 * M_PI)); + this->coreRotation += (s16)(65536.0f * tmp); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6AB0.s") +void EnDeath_SetupIntroCutscenePart1(EnDeath* this, PlayState* play) { + Player* player = GET_PLAYER(play); + Vec3f eye; + Vec3f at; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6C5C.s") + this->actor.shape.rot.y = this->actor.shape.rot.y - 0x657A; + this->actionTimer = 60; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6CDC.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6D40.s") + at.x = this->actor.world.pos.x; + at.z = this->actor.world.pos.z; + at.y = this->actor.world.pos.y - 116.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C6F6C.s") + 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); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C70D8.s") + Play_SetCameraAtEye(play, this->camId, &at, &eye); + Play_SetCameraFov(play, this->camId, 77.0f); + func_800B724C(play, &this->actor, 0x15); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C72AC.s") + this->actionFunc = EnDeath_IntroCutscenePart1; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C74A4.s") +void EnDeath_IntroCutscenePart1(EnDeath* this, PlayState* play) { + Player* player = GET_PLAYER(play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C74F8.s") + 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); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7800.s") + if (this->actionTimer == 25) { + func_800B724C(play, &this->actor, 0x51); + } + if (this->actionTimer > 0) { + this->actionTimer--; + } else { + EnDeath_SetupIntroCutscenePart2(this, play); + } + EnDeath_UpdateCoreVelocityAndRotation(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7888.s") +void EnDeath_SetupIntroCutscenePart2(EnDeath* this, PlayState* play) { + Camera* camera = Play_GetCamera(play, this->camId); + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7A30.s") + EnDeath_DimLights(play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7AAC.s") + for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) { + this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_7; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7AEC.s") + 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; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7B88.s") +void EnDeath_IntroCutscenePart2(EnDeath* this, PlayState* play) { + Camera* camera = Play_GetCamera(play, this->camId); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7C04.s") + if (this->actionTimer == 42) { + func_800B724C(play, &this->actor, 4); + } else if (this->actionTimer == 27) { + func_800B724C(play, &this->actor, 0x7B); + } + 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); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7C88.s") +void EnDeath_SetupIntroCutscenePart3(EnDeath* this) { + gSaveContext.eventInf[6] |= 8; + 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; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7CFC.s") +void EnDeath_IntroCutscenePart3(EnDeath* this, PlayState* play) { + s32 stepDone = Math_StepToF(&this->actor.scale.x, 0.01f, 0.0005f); + f32 temp; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7D34.s") + 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 += (s16)(temp * 4505600.0f); + if (stepDone) { + this->unk_192 = false; + EnDeath_SetupIntroCutscenePart4(this, play); + } + EnDeath_UpdateCoreVelocityAndRotation(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7DB8.s") +void EnDeath_SetupIntroCutscenePart4(EnDeath* this, PlayState* play) { + Camera* camera = Play_GetCamera(play, this->camId); + f32 invAnimDuration = 1.0f / Animation_GetLastFrame(&object_death_Anim_00B284); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7DCC.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7E24.s") + this->actionFunc = EnDeath_IntroCutscenePart4; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C7EDC.s") +void EnDeath_IntroCutscenePart4(EnDeath* this, PlayState* play) { + Camera* camera = Play_GetCamera(play, this->camId); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/EnDeath_Update.s") + if (this->unk_191 < 23) { + this->unk_191++; + } + 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); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C84A4.s") +void EnDeath_SetupIntroCutscenePart5(EnDeath* this, PlayState* play) { + Camera* camera = Play_GetCamera(play, this->camId); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C8690.s") + Animation_PlayOnce(&this->skelAnime, &object_death_Anim_00CB2C); + this->unk_191 = 0x17; + 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) * 0.14285715f; + this->camAtSpeed = Math_Vec3f_DistXYZ(&camera->at, &this->camAtTarget) * 0.14285715f; + Audio_PlaySfx_AtPos(&this->scytheScreenPos, NA_SE_EN_DEATH_VOICE); + this->actionFunc = EnDeath_IntroCutscenePart5; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C882C.s") +void EnDeath_IntroCutscenePart5(EnDeath* this, PlayState* play) { + Camera* camera = Play_GetCamera(play, this->camId); + f32 scale; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C8D18.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C9160.s") + for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) { + this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_9; + } + } else if (Animation_OnFrame(&this->skelAnime, 14.0f)) { + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C9220.s") + for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) { + this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_8; + 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->unk_18E = 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); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/func_808C9340.s") + 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); + func_800B724C(play, &this->actor, 6); + this->actor.flags |= ACTOR_FLAG_TARGETABLE; + this->coreCollider.base.acFlags |= AC_ON; + EnDeath_SetupApproachPlayer(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Death/EnDeath_Draw.s") +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) { + func_808C7AEC(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 = (s16)((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->unk_2EC = -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->unk_788.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->unk_2EC = 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->unk_2EC = -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->unk_2EC = 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->unk_2F2, (s32)(Math_SinS(this->actionTimer * 0x2000) * 0x800) + 0x3000, 0x1000); + Math_ScaledStepToS(&this->unk_2F4, (s32)(Math_SinS(this->actionTimer * 0x2000 - 0x8000) * 0x800), 0x1000); + + if ((this->actor.bgCheckFlags & 8) || (this->unk_788.base.atFlags & AT_HIT) || + (this->unk_860.base.atFlags & AT_HIT)) { + this->unk_18C = false; + this->unk_788.base.atFlags &= ~(AT_ON | AT_HIT); + this->unk_860.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, 0x4000, 255, 0, 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_6; + } + + this->unk_18D = 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; + func_800B724C(play, &this->actor, 7); + 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->unk_6A4); + Matrix_RotateXS(-0x1000, MTXMODE_APPLY); + Matrix_Get(&this->unk_6A4); + this->unk_18E = false; + this->unk_6A4.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->unk_6A4); + 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_DIE; + } + + this->actionTimer = 0; + this->actionFunc = EnDeath_DeathCutscenePart3; +} + +void EnDeath_DeathCutscenePart3(EnDeath* this, PlayState* play) { + static Vec3f sparkleVel = { 0.0f, -1.5f, 0.0f }; + static Vec3f sparkleAccel = { 0.0f, -0.2f, 0.0f }; + static Color_RGBA8 sparklePrimColor = { 0, 0, 0, 0 }; + static Color_RGBA8 sparkleEnvColor = { 40, 40, 40, 0 }; + static s16 D_808C9A90[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 phi_v0; + s32 phi_s0; + u8* temp1A9; + Vec3f* sparklePos; + s32 pad; + s32 pad1; + f32 sin; + f32 cos; + f32 temp_fs0; + s32 temp_v1; + + sparklePos = this->unk_404; + temp1A9 = this->unk_1A9; + for (phi_v0 = 0; (phi_v0 ^ 0) < ARRAY_COUNT(this->unk_404); phi_v0++) { + sparklePos->y += 1.7f; + temp_v1 = *temp1A9 - 30; + *temp1A9 = CLAMP_MIN(temp_v1, 0); + sparklePos++; + temp1A9++; + } + + temp_v1 = (-this->actionTimer * 14) + 252; + this->actor.shape.shadowAlpha = CLAMP_MIN(temp_v1, 0); + + if (this->actionTimer < 18) { + sparklePos = &this->unk_404[(this->actionTimer * 7) % ARRAY_COUNT(this->unk_404)]; + temp1A9 = &this->unk_1A9[(this->actionTimer * 7) % ARRAY_COUNT(this->unk_1A9)]; + + sin = Math_SinS(Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x8000); + cos = Math_CosS(Camera_GetCamDirYaw(GET_ACTIVE_CAM(play)) + 0x8000); + + for (phi_s0 = 0; phi_s0 < 7; phi_s0++) { + temp_fs0 = Rand_CenteredFloat(100.0f) - 20.0f; + sparklePos->x = this->actor.world.pos.x + (30.0f * sin) + (temp_fs0 * 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) - (temp_fs0 * sin); + *temp1A9 = 255 - phi_s0 * 4; + EffectSsKirakira_SpawnSmall(play, sparklePos, &sparkleVel, &sparkleAccel, &sparklePrimColor, + &sparkleEnvColor); + sparklePos++; + temp1A9++; + } + Actor_PlaySfx_Flagged(&this->actor, NA_SE_EN_COMMON_EXTINCT_LEV - SFX_FLAG); + } + + this->actionTimer++; + + for (phi_v0 = 0; phi_v0 < ARRAY_COUNT(this->unk_193); phi_v0++) { + if (this->actionTimer == D_808C9A90[phi_v0]) { + this->unk_193[phi_v0] = 1; + } + } + + if (this->actionTimer == 26) { + EnDeath_SetupDeathCutscenePart4(this); + } +} + +void EnDeath_SetupDeathCutscenePart4(EnDeath* this) { + s32 i; + + for (i = 0; i < ARRAY_COUNT(this->unk_1A9); i++) { + this->unk_1A9[i] = 0; + } + + Math_Vec3f_Copy(&this->actor.world.pos, &this->actor.focus.pos); + this->actor.bgCheckFlags &= ~1; + 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 sparkleAccel = { 0.0f, -1.0f, 0.0f }; + static Color_RGBA8 sparklePrimColor = { 0, 200, 100, 0 }; + static Color_RGBA8 sparkleEnvColor = { 0, 100, 0, 0 }; + Vec3f sparkleVel; + s32 i; + + if (this->actionTimer == 0) { + if ((this->actor.bgCheckFlags & 1) || this->actor.floorHeight == -32000.0f) { + Actor_SetScale(&this->actor, 0.0f); + this->actionTimer++; + + for (i = 0; i < 40; i++) { + sparkleAccel.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, &sparkleAccel, + &sparklePrimColor, &sparkleEnvColor); + } + 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); + func_800B724C(play, &this->actor, 6); + 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 func_808C7AEC(EnDeath* this) { + s32 i; + + Actor_PlaySfx(&this->actor, NA_SE_EN_DEATH_VOICE); + Animation_MorphToPlayOnce(&this->skelAnime, &object_death_Anim_0015B4, 5.0f); + this->actor.speed = 0.0f; + + for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) { + this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_3; + } + + this->floatTimer = 0; + this->actionFunc = func_808C7B88; +} + +void func_808C7B88(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; + func_808C7C04(this); + } +} + +void func_808C7C04(EnDeath* this) { + s32 i; + + Animation_PlayLoop(&this->skelAnime, &object_death_Anim_001834); + + for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) { + this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_4; + } + + this->actionFunc = func_808C7C88; + this->actor.speed = 0.0f; +} + +void func_808C7C88(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->unk_18D) { + // 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->unk_18D = false; + } + } +} + +void EnDeath_UpdateDamage(EnDeath* this, PlayState* play) { + s32 i; + + if (this->unk_2F8 > 0) { + this->unk_2F8--; + } + if (this->coreCollider.base.acFlags & AC_HIT) { + this->coreCollider.base.acFlags &= ~AC_HIT; + + if (this->actor.params >= 5) { + this->unk_18D = 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 != func_808C7B88) { + for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) { + this->miniDeaths[i]->actor.params = MINIDEATH_ACTION_1; + } + play->envCtx.lightSettingOverride = 28; + + this->unk_2FC = 20; + if (this->actionFunc == EnDeath_ApproachPlayer) { + this->actionTimer = 100; + } + } else if (this->actor.colChkInfo.damageEffect == DMGEFF_EXPLOSIVES) { + this->unk_2F8 = 0xA; + } + } else if (this->actor.colChkInfo.damageEffect != DMGEFF_EXPLOSIVES || this->unk_2F8 == 0) { + this->unk_18C = false; + this->unk_788.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_2; + } + EnDeath_SetupDamaged(this); + } + } + } +} + +void EnDeath_Update(Actor* thisx, PlayState* play) { + EnDeath* this = THIS; + ArrowLight* lightArrow; + s32 pad; + + if (this->unk_2FC > 0) { + this->unk_2FC--; + + lightArrow = (ArrowLight*)SubS_FindActor(play, NULL, ACTORCAT_ITEMACTION, ACTOR_ARROW_LIGHT); + if (lightArrow != NULL) { + lightArrow->screenFillIntensity = -100.0f; + } + + if (this->unk_2FC == 0) { + play->envCtx.lightSettingOverride = 26; + } + } + + EnDeath_UpdateDamage(this, play); + EnDeath_UpdateCore(this, play); + if (this->actionFunc != EnDeath_SpinAttack) { + Math_ScaledStepToS(&this->unk_2F2, 0, 0x800); + Math_ScaledStepToS(&this->unk_2F4, 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, 4 | 2 | 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->unk_788.base.atFlags & AT_ON) { + CollisionCheck_SetAT(play, &play->colChkCtx, &this->unk_788.base); + } + if (this->actionFunc == EnDeath_BlockProjectile || this->actionFunc == EnDeath_SpinAttack) { + CollisionCheck_SetAT(play, &play->colChkCtx, &this->unk_860.base); + CollisionCheck_SetAC(play, &play->colChkCtx, &this->unk_860.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* dl; + s32 pad; + + func_800B8118(&this->actor, play, 0); + Scene_SetRenderModeXlu(play, 1, 2); + + OPEN_DISPS(play->state.gfxCtx); + dl = POLY_XLU_DISP; + + for (i = 1; i < this->numScytheAfterImages; i++) { + gDPPipeSync(dl++); + gDPSetEnvColor(dl++, 30, 30, 0, 255 - i * 35); + + Matrix_Put(&this->unk_6A4); + Matrix_RotateXS(i * 0x2100, MTXMODE_APPLY); + + gSPMatrix(dl++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(dl++, object_death_DL_006F88); // scythe handle + + Matrix_Translate(0.0f, -1084.0f, 7012.0f, MTXMODE_APPLY); + Matrix_RotateZYX(-0x4000, 0, -0x4000, MTXMODE_APPLY); + + gSPMatrix(dl++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(dl++, object_death_DL_0073D0); // scythe blade + } + + POLY_XLU_DISP = dl; + CLOSE_DISPS(play->state.gfxCtx); +} + +void EnDeath_DrawScythe(EnDeath* this, PlayState* play) { + Gfx* dl; + 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) { + dl = POLY_XLU_DISP; + + gDPPipeSync(dl++); + gDPSetEnvColor(dl++, 30, 30, 0, this->actionTimer); + } else { + dl = POLY_OPA_DISP; + } + + Matrix_Put(&this->unk_6A4); + Matrix_Scale(this->scytheScale, this->scytheScale, this->scytheScale, MTXMODE_APPLY); + + gSPMatrix(&dl[0], Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(&dl[1], object_death_DL_006F88); // scythe handle + + Matrix_Translate(0.0f, -1084.0f, 7012.0f, MTXMODE_APPLY); + Matrix_RotateZYX(-0x4000, 0, -0x4000, MTXMODE_APPLY); + + gSPMatrix(&dl[2], Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(&dl[3], object_death_DL_0073D0); // scythe blade + + Matrix_MultZero(&this->scytheWorldPos); + + if (this->actionFunc == EnDeath_Dead) { + POLY_XLU_DISP = &dl[4]; + } else { + POLY_OPA_DISP = &dl[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 phi_fs2; + MiniDeathStruct* phi_s0; + s32 j; + f32 scale; + Gfx* dl; + s32 i; + Vec3f sp9C; + + OPEN_DISPS(play->state.gfxCtx); + dl = POLY_OPA_DISP; + + gSPDisplayList(dl++, &gSetupDLs[0x19]); // incementing by 0x30 it seems. this is odd. The increment size may be wrong? TODO + gSPDisplayList(dl++, gGomessBatMaterialDL); + + cmf = Matrix_GetCurrent(); + + if (this->actionFunc == EnDeath_Dead) { + phi_fs2 = this->actionTimer * 0.000035f; + scale = 0.007f; + if (phi_fs2 > 0.007f) { + phi_fs2 = 0.007f; + scale = 0.007f; + } + } else { + phi_fs2 = 0.007f; + scale = 0.007f; + } + + if (this->actor.flags & ACTOR_FLAG_IGNORE_QUAKE) { + Math_Vec3f_Copy(&sp9C, &play->mainCamera.quakeOffset); + } else { + Math_Vec3f_Copy(&sp9C, &gZeroVec3f); + } + + for (i = 0; i < ARRAY_COUNT(this->miniDeaths); i++) { + if (this->actionFunc == EnDeath_BeginWithoutCutscene || + (this->miniDeaths[i]->actor.flags & ACTOR_FLAG_40) == ACTOR_FLAG_40) { + miniDeath = this->miniDeaths[i]; + + Matrix_RotateZYX(miniDeath->actor.shape.rot.x, miniDeath->actor.shape.rot.y, 0, MTXMODE_NEW); + Matrix_Scale(phi_fs2, phi_fs2, phi_fs2, MTXMODE_APPLY); + + for (phi_s0 = miniDeath->unk_160, j = 0; j < ARRAY_COUNT(miniDeath->unk_160); j++, phi_s0++) { + if (phi_s0->unk_1 == 0) { + cmf->mf[3][0] = phi_s0->unk_4.x + sp9C.x; + cmf->mf[3][1] = phi_s0->unk_4.y + sp9C.y; + cmf->mf[3][2] = phi_s0->unk_4.z + sp9C.z; + + gSPMatrix(dl++, Matrix_NewMtx(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(dl++, sMinideathDLs[phi_s0->animFrame]); + } + } + + for (phi_s0 = miniDeath->unk_160, j = 0; j < ARRAY_COUNT(miniDeath->unk_160); j++, phi_s0++) { + if (phi_s0->unk_1 == 1) { + Matrix_RotateZYX(0x4000, phi_s0->unk_1E, 0, MTXMODE_NEW); + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); + cmf->mf[3][0] = phi_s0->unk_4.x + sp9C.x; + cmf->mf[3][1] = phi_s0->unk_4.y + sp9C.y; + cmf->mf[3][2] = phi_s0->unk_4.z + sp9C.z; + + gSPMatrix(dl++, Matrix_NewMtx(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(dl++, sMinideathDLs[phi_s0->animFrame]); + } + } + } + } + + if (this->unk_192) { + 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(phi_fs2, phi_fs2, phi_fs2, MTXMODE_APPLY); + + for (phi_s0 = miniDeath->unk_160, j = 0; j < ARRAY_COUNT(miniDeath->unk_160); j++, phi_s0++) { + cmf->mf[3][0] = miniDeath->actor.world.pos.x - phi_s0->unk_10.x; + cmf->mf[3][1] = miniDeath->actor.world.pos.y + (20.0f - phi_s0->unk_10.y); + cmf->mf[3][2] = miniDeath->actor.world.pos.z - phi_s0->unk_10.z; + + gSPMatrix(dl++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(dl++, sMinideathDLs[phi_s0->animFrame]); + } + } + } + + if (this->unk_18D) { + Matrix_RotateZYX(0x4000, this->coreRotation, 0, MTXMODE_NEW); + Matrix_Scale(scale, scale, scale, MTXMODE_APPLY); + cmf->mf[3][0] = this->corePos.x + sp9C.x; + cmf->mf[3][1] = this->corePos.y + sp9C.y; + cmf->mf[3][2] = this->corePos.z + sp9C.z; + + gSPMatrix(dl++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(dl++, sMinideathDLs[0]); + } + + POLY_OPA_DISP = dl; + CLOSE_DISPS(play->state.gfxCtx); +} + +void EnDeath_DrawFlames(EnDeath* this, PlayState* play2) { + PlayState* play = play2; + s32 phi_t1; + MtxF* cmf; + s32 phi_s7; + u8* phi_s3; + Vec3f* phi_s1; + MiniDeathStruct* phi_s1_2; + u8 alpha; + s32 phi_s3_2; + + phi_s7 = this->actionTimer * 7; + if (phi_s7 > ARRAY_COUNT(this->unk_1A9)) { + phi_s7 = ARRAY_COUNT(this->unk_1A9); + } + + 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(); + + phi_s1 = this->unk_404; + phi_s3 = this->unk_1A9; + for (phi_t1 = 0; phi_t1 < phi_s7; phi_t1++) { + if (*phi_s3 > 0) { + + gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 165, 255, 215, *phi_s3); + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 32, 64, 1, 0, + ((play->gameplayFrames + (phi_t1 * 10)) * -20) & 0x1FF, 32, 128)); + + cmf->mf[3][0] = phi_s1->x; + cmf->mf[3][1] = phi_s1->y; + cmf->mf[3][2] = phi_s1->z; + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, gEffFire1DL); + } + phi_s1++; + phi_s3++; + } + + 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 (phi_t1 = 0; phi_t1 < ARRAY_COUNT(this->miniDeaths); phi_t1++) { + if ((this->miniDeaths[phi_t1]->actor.flags & ACTOR_FLAG_40) == ACTOR_FLAG_40) { + phi_s1_2 = this->miniDeaths[phi_t1]->unk_160; + + for (phi_s3_2 = 0; phi_s3_2 < ARRAY_COUNT(this->miniDeaths[phi_t1]->unk_160); phi_s3_2++, phi_s1_2++) { + cmf->mf[3][0] = phi_s1_2->unk_4.x; + cmf->mf[3][1] = phi_s1_2->unk_4.y - 12.0f; + cmf->mf[3][2] = phi_s1_2->unk_4.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 + ((phi_s3_2 + phi_t1) * 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* dl; + + OPEN_DISPS(play->state.gfxCtx); + dl = POLY_OPA_DISP; + + Matrix_ReplaceRotation(&play->billboardMtxF); + + gSPMatrix(&dl[0], Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(&dl[1], gGomessCoreDL); + + if (this->actor.params >= 5) { + // bats in front of the core + gSPDisplayList(&dl[2], gGomessBatsGuardingCoreDL); + POLY_OPA_DISP = &dl[3]; + } else { + POLY_OPA_DISP = &dl[2]; + } + + CLOSE_DISPS(play->state.gfxCtx); +} + +s32 EnDeath_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, + Actor* thisx) { + EnDeath* this = THIS; + f32 temp_f12; + s32 temp_v0; + + if (this->unk_193[limbIndex] == 1) { + *dList = NULL; + } else if (limbIndex == GOMESS_LIMB_CLOAK_LOWER && this->actionFunc == EnDeath_DeathCutscenePart3) { + temp_v0 = this->actionTimer - 5; + if (temp_v0 > 0) { + temp_f12 = 1.0f - (temp_v0 * 0.1f); + Matrix_Scale(temp_f12, temp_f12, temp_f12, MTXMODE_APPLY); + } + } + if (limbIndex == GOMESS_LIMB_SCYTHE_HANDLE || limbIndex == GOMESS_LIMB_SCYTHE_BLADE) { + if (!this->unk_18E) { + *dList = NULL; + } + } else if (limbIndex == GOMESS_LIMB_CLOAK_UPPER) { + rot->z = rot->z + this->unk_2F2; + } else if (limbIndex == GOMESS_LIMB_CLOAK_LOWER) { + rot->z = rot->z + this->unk_2F4; + } + return 0; +} + +void EnDeath_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { + static Vec3f D_808C9AF4 = { -1000.0f, 12000.0f, 0.0f }; + static Vec3f D_808C9B00 = { -2000.0f, -2500.0f, 0.0f }; + static Vec3f D_808C9B0C[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 D_808C9B48[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->unk_788.base.atFlags & AT_ON) && this->unk_2EC != this->actionTimer) { + Vec3f quad0; + Vec3f quad1; + Vec3f pos1; + Vec3f pos2; + + Math_Vec3f_Copy(&quad0, &this->unk_788.dim.quad[0]); + Math_Vec3f_Copy(&quad1, &this->unk_788.dim.quad[1]); + + if (this->actionFunc == EnDeath_EndSwingAttack) { + Matrix_MultVecX(6000.0f, &pos1); + Matrix_MultVec3f(&D_808C9AF4, &pos2); + } else { + Matrix_MultVecY(5000.0f, &pos2); + Matrix_MultVec3f(&D_808C9B00, &pos1); + } + + Collider_SetQuadVertices(&this->unk_788, &pos2, &pos1, &quad0, &quad1); + EffectBlure_AddVertex(Effect_GetByIndex(this->effectIndex), &pos1, &pos2); + + this->unk_2EC = this->actionTimer; + } else if (this->unk_18C) { + if (this->actionFunc == EnDeath_EndSwingAttack) { + Matrix_MultVecX(6000.0f, &this->unk_788.dim.quad[1]); + Matrix_MultVec3f(&D_808C9AF4, &this->unk_788.dim.quad[0]); + } else { + Matrix_MultVecY(5000.0f, &this->unk_788.dim.quad[0]); + Matrix_MultVec3f(&D_808C9B00, &this->unk_788.dim.quad[1]); + } + this->unk_18C = false; + this->unk_788.base.atFlags |= AT_ON; + this->unk_2EC = 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->unk_18E == true)) { + Matrix_Get(&this->unk_6A4); + } + } + + index = D_808C9B48[limbIndex]; + if (index != -1) { + if (index < 7) { + // get matrix translation as-is, occupies slots 0, 1, 2, 3, 4, 5, 6 + Matrix_MultZero(&this->dmgEffectPositions[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->dmgEffectPositions[index], offset = &D_808C9B0C[0], i = 0; + i != ARRAY_COUNT(D_808C9B0C); 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->dmgEffectPositions[index]); + Matrix_MultVecY(-2000.0f, &this->dmgEffectPositions[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->unk_191); + 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->unk_18E) { + EnDeath_DrawScythe(this, play); + } + if (this->actor.colorFilterTimer != 0) { + func_800AE5A0(play); + } + Actor_DrawDamageEffects(play, &this->actor, this->dmgEffectPositions, ARRAY_COUNT(this->dmgEffectPositions), + 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..6aa3f696e 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 unk_18D; + /* 0x18E */ u8 unk_18E; + /* 0x18F */ u8 dmgEffect; + /* 0x190 */ s8 numScytheAfterImages; + /* 0x191 */ u8 unk_191; // animated material color step? + /* 0x192 */ u8 unk_192; + /* 0x193 */ u8 unk_193[GOMESS_LIMB_MAX]; + /* 0x1A9 */ u8 unk_1A9[56]; + /* 0x1E2 */ Vec3s jointTable[GOMESS_LIMB_MAX]; + /* 0x266 */ Vec3s morphTable[GOMESS_LIMB_MAX]; + /* 0x2EA */ s16 floatTimer; + /* 0x2EC */ s16 unk_2EC; + /* 0x2EE */ s16 actionTimer; + /* 0x2F0 */ char unk_2F0[0x2]; + /* 0x2F2 */ s16 unk_2F2; + /* 0x2F4 */ s16 unk_2F4; + /* 0x2F6 */ s16 coreRotation; + /* 0x2F8 */ s16 unk_2F8; + /* 0x2FA */ s16 camId; + /* 0x2FC */ s16 unk_2FC; + /* 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 dmgEffectPositions[14]; + /* 0x404 */ Vec3f unk_404[56]; + /* 0x6A4 */ MtxF unk_6A4; + /* 0x6E4 */ EnMinideath* miniDeaths[20]; + /* 0x734 */ AnimatedMaterial* bodyMatAnim; + /* 0x738 */ AnimatedMaterial* coreMatAnim; + /* 0x73C */ ColliderCylinder bodyCollider; + /* 0x788 */ ColliderQuad unk_788; // weapon? + /* 0x808 */ ColliderSphere coreCollider; + /* 0x860 */ ColliderTris unk_860; + /* 0x880 */ ColliderTrisElement unk_880[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..8f539118a 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) @@ -25,78 +27,124 @@ 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); +void EnMinideath_Die(EnMinideath* this, PlayState* play); +void EnMinideath_Dead(EnMinideath* this, PlayState* play); -#if 0 -ActorInit En_Minideath_InitVars = { - /**/ ACTOR_EN_MINIDEATH, - /**/ ACTORCAT_ENEMY, - /**/ FLAGS, - /**/ OBJECT_DEATH, - /**/ sizeof(EnMinideath), - /**/ EnMinideath_Init, - /**/ EnMinideath_Destroy, - /**/ EnMinideath_Update, - /**/ NULL, +void func_808CA34C(EnMinideath* this); +void func_808CA7D4(EnMinideath* this); +void func_808CA8E0(EnMinideath* this); +void func_808CAAC8(EnMinideath* this); +void func_808CAB90(EnMinideath* this); +void func_808CAE00(EnMinideath* this); +void func_808CAF08(EnMinideath* this); +void EnMinideath_SetupDead(EnMinideath* this); + +const ActorInit En_Minideath_InitVars = { + ACTOR_EN_MINIDEATH, + ACTORCAT_ENEMY, + FLAGS, + OBJECT_DEATH, + sizeof(EnMinideath), + (ActorFunc)EnMinideath_Init, + (ActorFunc)EnMinideath_Destroy, + (ActorFunc)EnMinideath_Update, + (ActorFunc)NULL, }; // static ColliderJntSphElementInit sJntSphElementsInit[3] = { static ColliderJntSphElementInit D_808CBF50[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, + { + COLTYPE_NONE, + AT_NONE | AT_TYPE_ENEMY, + AC_ON | AC_TYPE_PLAYER, + OC1_NONE | OC1_TYPE_ALL, + OC2_TYPE_1, + COLSHAPE_JNTSPH, + }, + ARRAY_COUNT(D_808CBF50), + D_808CBF50, // sJntSphElementsInit, }; +typedef enum { + DMGEFF_NONE = 0, + DMGEFF_STUN = 1, + DMGEFF_FIRE_ARROW = 2, + DMGEFF_ICE_ARROW = 3, + DMGEFF_LIGHT_ARROW = 4, + DMGEFF_ZORA_BARRIER = 5 +} EnMinideathDamageEffect; + // 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), + /* 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 @@ -108,80 +156,754 @@ static InitChainEntry D_808CBFF4[] = { ICHAIN_F32(uncullZoneDownward, 100, ICHAIN_STOP), }; -#endif +static s32 sItemDropTimer; +s32 D_808CC254; +s32 D_808CC258; +s32 D_808CC25C; -extern ColliderJntSphElementInit D_808CBF50[3]; -extern ColliderJntSphInit D_808CBFBC; -extern DamageTable D_808CBFCC; -extern CollisionCheckInfoInit D_808CBFEC; -extern InitChainEntry D_808CBFF4[]; +void EnMinideath_Init(Actor* thisx, PlayState* play) { + EnMinideath* this = THIS; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/EnMinideath_Init.s") + Actor_ProcessInitChain(thisx, D_808CBFF4); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/EnMinideath_Destroy.s") + this->unk_158 = thisx->world.pos.y - thisx->parent->world.pos.y; + this->spawnShapeRot = thisx->shape.rot.y; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA268.s") + thisx->shape.rot.y = thisx->parent->shape.rot.y; + thisx->world.rot.y = thisx->parent->shape.rot.y; + thisx->flags &= ~ACTOR_FLAG_TARGETABLE; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA308.s") + Collider_InitAndSetJntSph(play, &this->collider, thisx, &D_808CBFBC, this->colliderElements); + CollisionCheck_SetInfo(&thisx->colChkInfo, &D_808CBFCC, &D_808CBFEC); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA34C.s") + for (i = 0; i < ARRAY_COUNT(this->colliderElements); i++) { + this->collider.elements[i].dim.worldSphere.radius = this->collider.elements[i].dim.modelSphere.radius; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA458.s") + func_808CA34C(this); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA7D4.s") + this->number = thisx->params; + thisx->params = 0; + this->unk_149 = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA860.s") + if (gSaveContext.eventInf[6] & 8) { + this->collider.base.atFlags |= AT_ON; + this->unk_149 = true; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA8E0.s") + func_808CABB0(this, play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CA8F4.s") + for (i = 0; i < ARRAY_COUNT(this->unk_160); i++) { + Math_Vec3f_Sum(&thisx->world.pos, &this->unk_160[i].unk_10, &this->unk_160[i].unk_4); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAAC8.s") + func_808CAB90(this); + } else { + func_808CA7D4(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAAEC.s") +void EnMinideath_Destroy(Actor* thisx, PlayState* play) { + EnMinideath* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAB90.s") + Collider_DestroyJntSph(play, &this->collider); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CABB0.s") +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 + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAC54.s") +void func_808CA308(EnMinideath* this, s32 arg1) { + if (this->unk_149 != arg1) { + this->unk_149 = arg1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CACD8.s") + if (arg1 == true) { + this->actor.parent->params++; + } else { + this->actor.parent->params--; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAE00.s") +void func_808CA34C(EnMinideath* this) { + MiniDeathStruct* phi_s0; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAE18.s") + for (phi_s0 = this->unk_160, i = 0; i < ARRAY_COUNT(this->unk_160); i++, phi_s0++) { + phi_s0->unk_10.x = Rand_CenteredFloat(80.0f); + phi_s0->unk_10.y = Rand_ZeroFloat(40.0f); + phi_s0->unk_10.z = Rand_CenteredFloat(80.0f); + phi_s0->animFrame = (s32)Rand_ZeroFloat(9.0f) % MINIDEATH_ANIM_LENGTH; + phi_s0->unk_1C = ((s32)Rand_Next() >> 17); + phi_s0->unk_1E = ((s32)Rand_Next() >> 16); + phi_s0->unk_1 = 0; + phi_s0->unk_22 = 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAF08.s") +void func_808CA458(EnMinideath* this, PlayState* play) { + s16 temp_s1; + MiniDeathStruct* phi_s0; + f32 phi_fv0; + f32 phi_fa0; + s32 i; + s32 phi_s7; + s32 phi_s3; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CAF68.s") + phi_s3 = 0; + phi_s7 = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB07C.s") + phi_s0 = this->unk_160; + for (i = 0; i < ARRAY_COUNT(this->unk_160); i++, phi_s0++) { + if (phi_s0->unk_1 == 0) { + phi_s0->unk_10.x += 3.0f * Math_CosS(phi_s0->unk_1C) * Math_SinS(phi_s0->unk_1E); + phi_s0->unk_10.y += 3.0f * Math_SinS(phi_s0->unk_1C); + phi_s0->unk_10.z += 3.0f * Math_CosS(phi_s0->unk_1C) * Math_CosS(phi_s0->unk_1E); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB094.s") + if (this->actionFunc == func_808CA860) { + phi_fv0 = 100.0f; + phi_fa0 = SQ(phi_fv0); + } else if (this->actionFunc == func_808CB094 || this->actionFunc == func_808CB454) { + phi_fv0 = 20.0f; + phi_fa0 = SQ(20.0f); + } else { + phi_fv0 = 40.0f; + phi_fa0 = SQ(40.0f); + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB0C8.s") + if (phi_s0->unk_10.y < 0.0f || phi_fv0 < phi_s0->unk_10.y || + phi_fa0 < SQ(phi_s0->unk_10.x) + SQ(phi_s0->unk_10.z)) { + temp_s1 = Math_Atan2S_XY(sqrtf(SQ(phi_s0->unk_10.x) + SQ(phi_s0->unk_10.z)), phi_s0->unk_10.y); + phi_s0->unk_1C = -1 * temp_s1 + ((s32)Rand_Next() >> 19); + temp_s1 = Math_Atan2S_XY(phi_s0->unk_10.z, phi_s0->unk_10.x); + phi_s0->unk_1E = temp_s1 + ((s32)Rand_Next() >> 19) + 0x8000; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB22C.s") + phi_s3++; + } else if (phi_s0->unk_1 == 1) { + phi_s0->unk_4.y += phi_s0->unk_10.y; + phi_s0->unk_1E += 0x1800; + phi_s0->unk_10.y -= 1.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB418.s") + if (phi_s0->unk_4.y < this->actor.parent->home.pos.y) { + phi_s0->unk_4.y = this->actor.parent->home.pos.y; + func_800B3030(play, &phi_s0->unk_4, &gZeroVec3f, &gZeroVec3f, 100, 0, 0); + SoundSource_PlaySfxAtFixedWorldPos(play, &phi_s0->unk_4, 11, NA_SE_EN_EXTINCT); + EnMinideath_DropCollectible(&phi_s0->unk_4, play); + phi_s0->unk_1 = 2; + } + } else if (phi_s0->unk_1 == 2) { + if (phi_s0->unk_22 > 0) { + phi_s0->unk_22--; + } else if (this->actionFunc == func_808CABB0) { + Math_Vec3f_Diff(&this->actor.parent->focus.pos, &this->actor.world.pos, &phi_s0->unk_10); + phi_s0->unk_1 = 0; + this->collider.elements[i].info.bumperFlags |= BUMP_ON; + this->collider.elements[i].info.toucherFlags |= TOUCH_ON; + phi_s7 = 1; + phi_s3++; + } + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB454.s") + if (phi_s7 && phi_s3 > 1) { + func_808CA308(this, true); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB524.s") +void func_808CA7D4(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->unk_150.y = this->actor.shape.rot.y; + this->actionFunc = func_808CA860; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB59C.s") +void func_808CA860(EnMinideath* this, PlayState* play) { + if (Math_ScaledStepToS(&this->actor.shape.rot.y, this->unk_150.y, 0x480) && (this->actor.bgCheckFlags & 8)) { + // Fly away from walls + this->unk_150.y = ((s32)Rand_Next() >> 18) + this->actor.wallYaw; + } + if (this->actor.params == MINIDEATH_ACTION_7) { + func_808CA8E0(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB6A8.s") +void func_808CA8E0(EnMinideath* this) { + this->actionFunc = func_808CA8F4; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB6D4.s") +void func_808CA8F4(EnMinideath* this, PlayState* play) { + EnDeath* parent; + Vec3f sp38; + s32 phi_v0; + s16 angle; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB7B8.s") + Math_StepToF(&this->actor.speed, 15.0f, 0.5f); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB7CC.s") + if (this->actor.child == NULL) { + phi_v0 = 0; + angle = 0; + } else { + angle = 0x5555; + if (this->number == 6) { + phi_v0 = 1; + } 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; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB810.s") + if (phi_v0 != -1) { + parent = (EnDeath*)this->actor.parent; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/func_808CB8F4.s") + 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->unk_158; + } + Math_SmoothStepToS(&this->actor.shape.rot.x, Actor_WorldPitchTowardPoint(&this->actor, &sp38), 2, 0x1000, 0x100); + if (this->actor.params == MINIDEATH_ACTION_8) { + func_808CAAC8(this); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Minideath/EnMinideath_Update.s") +void func_808CAAC8(EnMinideath* this) { + this->actor.params = MINIDEATH_ACTION_CONTINUE; + this->actionFunc = func_808CAAEC; + this->actor.speed = 5.0f; +} + +void func_808CAAEC(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_9) { + this->collider.base.atFlags |= AT_ON; + func_808CAF08(this); + } +} + +void func_808CAB90(EnMinideath* this) { + this->actor.shape.rot.x = 0; + this->actionFunc = func_808CABB0; + this->actor.speed = 0.0f; +} + +void func_808CABB0(EnMinideath* this, PlayState* play) { + s16 sp1E = this->spawnShapeRot + this->actor.parent->shape.rot.y; + + this->actor.world.pos.x = this->actor.parent->world.pos.x + Math_SinS(sp1E) * 60.0f; + this->actor.world.pos.z = this->actor.parent->world.pos.z + Math_CosS(sp1E) * 60.0f; + this->actor.world.pos.y = this->actor.parent->world.pos.y + this->unk_158; + this->actor.shape.rot.y = this->actor.parent->shape.rot.y; +} + +void func_808CAC54(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->unk_150, false); + if (D_808CC258 != 0) { + this->timer = D_808CC258; + } else { + this->timer = 200; + } + func_808CA308(this, false); + this->actionFunc = func_808CACD8; +} + +void func_808CACD8(EnMinideath* this, PlayState* play) { + f32 temp_fv0; + f32 temp_fv1; + + Math_StepToF(&this->actor.speed, 6.0f, 0.5f); + + if (Math_ScaledStepToS(&this->actor.shape.rot.y, this->unk_150.y, 0x480) && (this->actor.bgCheckFlags & 8)) { + // Fly away from walls + this->unk_150.y = ((s32)Rand_Next() >> 18) + this->actor.wallYaw; + } + + if (Math_ScaledStepToS(&this->actor.shape.rot.x, this->unk_150.x, 0x480)) { + temp_fv0 = this->actor.world.pos.y; + temp_fv1 = this->actor.parent->home.pos.y; + + if (temp_fv0 < temp_fv1 + 50.0f) { + this->unk_150.x = -0x800 - ((u32)Rand_Next() >> 20); + } else if (temp_fv0 > temp_fv1 + 200.0f) { + this->unk_150.x = ((u32)Rand_Next() >> 20) + 0x800; + } + } + + if (this->timer == 0) { + func_808CAE00(this); + } else { + this->timer--; + } +} + +void func_808CAE00(EnMinideath* this) { + this->actor.params = MINIDEATH_ACTION_CONTINUE; + this->actionFunc = func_808CAE18; +} + +void func_808CAE18(EnMinideath* this, PlayState* play) { + s32 pad; + f32 temp_fv0 = Actor_WorldDistXYZToPoint(&this->actor, &this->actor.parent->focus.pos); + f32 phi_fa0 = temp_fv0 * 0.016666668f; + + if (phi_fa0 > 1.0f) { + phi_fa0 = 1.0f; + } + Math_StepToF(&this->actor.speed, 6.0f * phi_fa0, 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 (temp_fv0 < 30.0f) { + func_808CAF08(this); + } +} + +void func_808CAF08(EnMinideath* this) { + s32 phi_v0; + + this->actor.speed = 0.0f; + func_808CA308(this, true); + + for (phi_v0 = 0; phi_v0 < ARRAY_COUNT(this->unk_160); phi_v0++) { + this->unk_160[phi_v0].unk_22 = 0; + } + this->actionFunc = func_808CAF68; +} + +void func_808CAF68(EnMinideath* this, PlayState* play) { + Vec3f target; + f32 dist; + s16 sp26; + s32 done; + + done = Math_ScaledStepToS(&this->actor.shape.rot.y, this->spawnShapeRot + this->actor.parent->shape.rot.y, 0x800); + Math_ScaledStepToS(&this->actor.shape.rot.x, 0, 0x800); + sp26 = this->spawnShapeRot + 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->unk_158; + + dist = Math_Vec3f_StepTo(&this->actor.world.pos, &target, 10.0f); + if (done && dist < 20.0f) { + func_808CAB90(this); + } +} + +void func_808CB07C(EnMinideath* this) { + this->actor.params = MINIDEATH_ACTION_CONTINUE; + this->actionFunc = func_808CB094; +} + +void func_808CB094(EnMinideath* this, PlayState* play) { + Math_Vec3f_StepTo(&this->actor.world.pos, &this->actor.parent->focus.pos, 5.0f); +} + +void func_808CB0C8(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 + (phi_a1 * 0x4000) + ((phi_v1 * 0x2000) * phi_a1); + this->actor.shape.rot.x = (phi_a2 - phi_v1 * 0x400) + 0xC00; + + 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; + + func_808CA34C(this); + this->timer = 100; + func_808CA308(this, false); + + D_808CC254 = 0; + + if (this->actor.child == NULL || this->number == 9) { + this->unk_15C = &GET_PLAYER(play)->actor; + } else { + this->unk_15C = this->actor.child; + } + this->actionFunc = func_808CB22C; +} + +void func_808CB22C(EnMinideath* this, PlayState* play) { + Vec3f sp34; + s16 sp32 = 0; + + Math_StepToF(&this->actor.speed, 6.0f, 0.2f); + if (this->timer > 0) { + this->timer--; + } + + if (this->unk_15C->id != ACTOR_EN_MINIDEATH) { + if (this->timer == 0) { + this->unk_15C = this->actor.parent; + } + Math_Vec3f_Copy(&sp34, &this->unk_15C->focus.pos); + if (Actor_WorldDistXYZToPoint(&this->actor, &sp34) > 200.0f) { + if (this->number < 10) { + sp32 = -0x1C00; + } else { + sp32 = 0x1C00; + } + sp34.y += 50.0f; + } + } else if (((EnMinideath*)this->unk_15C)->actionFunc != func_808CB22C) { + Math_Vec3f_Copy(&sp34, &this->actor.parent->focus.pos); + } else { + Math_Vec3f_Copy(&sp34, &this->unk_15C->focus.pos); + } + Math_SmoothStepToS(&this->actor.shape.rot.y, Actor_WorldYawTowardPoint(&this->actor, &sp34) + sp32, 5, 0xC00, 0x80); + Math_SmoothStepToS(&this->actor.shape.rot.x, Actor_WorldPitchTowardPoint(&this->actor, &sp34), 5, 0xC00, 0x80); + if ((this->collider.base.atFlags & AT_HIT) && this->timer > 0) { + D_808CC254 += 1; + } + if (this->timer == 0 && Actor_WorldDistXYZToPoint(&this->actor, &this->actor.parent->focus.pos) < 50.0f) { + func_808CAF08(this); + } +} + +void func_808CB418(EnMinideath* this) { + this->actor.params = MINIDEATH_ACTION_CONTINUE; + this->timer = 10; + func_808CA34C(this); + this->actionFunc = func_808CB454; +} + +void func_808CB454(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 != func_808CB22C) { + func_808CAB90(this); + } +} + +void func_808CB524(EnMinideath* this) { + s32 i; + + this->actor.params = MINIDEATH_ACTION_CONTINUE; + func_808CA308(this, false); + this->collider.base.atFlags &= ~AT_ON; + + for (i = 0; i < ARRAY_COUNT(this->unk_160); i++) { + this->unk_160[i].unk_1 = 0; + } + + this->unk_150.y = this->actor.shape.rot.y; + this->unk_150.x = this->actor.shape.rot.x; + this->actionFunc = func_808CB59C; +} + +void func_808CB59C(EnMinideath* this, PlayState* play) { + f32 temp_fv0; + f32 temp_fv1; + + Math_StepToF(&this->actor.speed, 5.0f, 0.2f); + if (Math_ScaledStepToS(&this->actor.shape.rot.y, this->unk_150.y, 0x480) && (this->actor.bgCheckFlags & 8)) { + // Fly away from walls + this->unk_150.y = ((s32)Rand_Next() >> 0x12) + this->actor.wallYaw; + } + if (Math_ScaledStepToS(&this->actor.shape.rot.x, this->unk_150.x, 0x480)) { + temp_fv0 = this->actor.world.pos.y; + temp_fv1 = this->actor.parent->home.pos.y; + if (temp_fv0 < (temp_fv1 + 50.0f)) { + this->unk_150.x = -0x800 - ((u32)Rand_Next() >> 20); + } else if (temp_fv0 > (temp_fv1 + 200.0f)) { + this->unk_150.x = ((u32)Rand_Next() >> 20) + 0x800; + } + } +} + +void EnMinideath_SetupDie(EnMinideath* this) { + this->actor.params = MINIDEATH_ACTION_CONTINUE; + this->unk_150.x = 0x4000; + this->actionFunc = EnMinideath_Die; + this->actor.gravity = -0.5f; +} + +void EnMinideath_Die(EnMinideath* this, PlayState* play) { + MiniDeathStruct* phi_s0; + s32 i; + s32 phi_s2 = 0; + + Math_StepToF(&this->actor.speed, 0.0f, 0.2f); + Math_ScaledStepToS(&this->actor.shape.rot.x, this->unk_150.x, 0x480); + Actor_PlaySfx_Flagged(&this->actor, NA_SE_EN_COMMON_EXTINCT_LEV - SFX_FLAG); + + if (this->actor.bgCheckFlags & 1) { + this->actor.speed = 0.0f; + + for (phi_s0 = this->unk_160, i = 0; i < ARRAY_COUNT(this->unk_160); i++, phi_s0++) { + if (Math_StepToF(&phi_s0->unk_10.y, 0.0f, 7.0f)) { + phi_s2++; + } + } + + if (phi_s2 == ARRAY_COUNT(this->unk_160)) { + 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_6) { + func_808CB524(this); + } else if (action == MINIDEATH_ACTION_2) { + func_808CAE00(this); + } else if (action == MINIDEATH_ACTION_3) { + func_808CB07C(this); + } else if (action == MINIDEATH_ACTION_4) { + if (this->number == 0 || this->number == 10) { + func_808CB418(this); + } else { + func_808CB0C8(this, play); + } + } else if (action == MINIDEATH_ACTION_1) { + func_808CAC54(this); + } else if (action == MINIDEATH_ACTION_DIE) { + EnMinideath_SetupDie(this); + } +} + +void func_808CB8F4(EnMinideath* this, PlayState* play) { + s32 temp_a0_2; + EnMinideath* temp_a0_3; + s32 phi_a2; + s32 phi_v0_2; + s32 phi_a0; + + if (this->collider.base.acFlags & AC_HIT) { + this->collider.base.acFlags &= ~AC_HIT; + + if (this->actor.colChkInfo.damageEffect == DMGEFF_STUN) { + if (this->actionFunc == func_808CABB0 || this->actionFunc == func_808CAF68) { + D_808CC258 = 5; + } else if (this->actionFunc == func_808CB22C) { + EnMinideath** miniDeaths = (EnMinideath**)((EnDeath*)this->actor.parent)->miniDeaths; + + for (temp_a0_2 = this->number - 1; temp_a0_2 >= 0; temp_a0_2--) { + temp_a0_3 = miniDeaths[temp_a0_2]; + + if (temp_a0_3->unk_15C == &this->actor) { + temp_a0_3->unk_15C = this->unk_15C; + break; + } + } + + this->timer = 0; + this->unk_15C = &GET_PLAYER(play)->actor; + } + } else { + for (phi_a2 = 0; phi_a2 < ARRAY_COUNT(this->colliderElements); phi_a2++) { + if (this->collider.elements[phi_a2].info.bumperFlags & BUMP_HIT) { + this->collider.elements[phi_a2].info.bumperFlags &= ~(BUMP_ON | BUMP_HIT); + this->collider.elements[phi_a2].info.toucherFlags &= ~(TOUCH_ON | TOUCH_HIT); + this->unk_160[phi_a2].unk_10.y = -1.0f; + this->unk_160[phi_a2].unk_1 = 1; + this->unk_160[phi_a2].unk_1E = this->actor.shape.rot.y; + this->unk_160[phi_a2].unk_22 = 60; + + if ((this->actionFunc == func_808CABB0 || this->actionFunc == func_808CAF68) && + this->actor.colChkInfo.damageEffect == DMGEFF_LIGHT_ARROW) { + D_808CC258 = 200; + } + } + } + + phi_a0 = 0; + for (phi_v0_2 = 0; phi_v0_2 < ARRAY_COUNT(this->unk_160); phi_v0_2++) { + if (this->unk_160[phi_v0_2].unk_1 != 0) { + phi_a0++; + } + } + + if (phi_a0 > 1) { + func_808CA308(this, false); + } + + if (D_808CC25C == 0) { + Actor_PlaySfx(&this->actor, NA_SE_EN_FFLY_DEAD); + D_808CC25C = 1; + } + } + } +} + +void EnMinideath_Update(Actor* thisx, PlayState* play) { + EnMinideath* this = THIS; + s32 pad; + ColliderJntSphElement* elem; + s32 temp; + s32 i; + MiniDeathStruct* phi_s0; + EnMinideath* phi_s0_3; + + if (sItemDropTimer > 0) { + sItemDropTimer--; + } + + if (this->actionFunc != EnMinideath_Dead) { + for (i = 0; i < ARRAY_COUNT(this->unk_160); i++) { + if (this->unk_160[i].unk_1 == 0) { + Actor_PlaySfx_Flagged(&this->actor, NA_SE_EV_BAT_FLY - SFX_FLAG); + break; + } + } + } + + func_808CB8F4(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 != func_808CABB0 && this->actionFunc != func_808CAF68) { + Actor_UpdateBgCheckInfo(play, &this->actor, 30.0f, 50.0f, 80.0f, 7); + } + + if (this->actionFunc != EnMinideath_Die) { + func_808CA458(this, play); + } + + Actor_SetFocus(&this->actor, 0.0f); + + phi_s0 = this->unk_160; + elem = this->collider.elements; + for (i = 0; i != ARRAY_COUNT(this->colliderElements); i++) { + if (phi_s0->unk_1 == 0) { + Math_Vec3f_Sum(&this->actor.world.pos, &phi_s0->unk_10, &phi_s0->unk_4); + + if (this->actionFunc != EnMinideath_Die) { + phi_s0->animFrame++; + if (phi_s0->animFrame == MINIDEATH_ANIM_LENGTH) { + phi_s0->animFrame = 0; + } + } + + elem->dim.worldSphere.center.x = phi_s0->unk_4.x; + elem->dim.worldSphere.center.y = phi_s0->unk_4.y; + elem->dim.worldSphere.center.z = phi_s0->unk_4.z; + } + phi_s0++; + 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 == func_808CABB0) ? (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 != func_808CB094) { + CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base); + } + } + } + if (this->attackTimer > 0) { + this->attackTimer--; + } + if (this->number == 19) { + phi_s0_3 = NULL; + D_808CC25C = 0; + + if (D_808CC258 != 0) { + do { + phi_s0_3 = + (EnMinideath*)SubS_FindActor(play, &phi_s0_3->actor, ACTORCAT_ENEMY, ACTOR_EN_MINIDEATH); + if (phi_s0_3 != NULL) { + func_808CAC54(phi_s0_3); + phi_s0_3 = (EnMinideath*)phi_s0_3->actor.next; + } + } while (phi_s0_3 != NULL); + + play->envCtx.lightSettingOverride = 28; + + if (D_808CC258 == 5) { + ((EnDeath*)this->actor.parent)->unk_2FC = 5; + } else { + ((EnDeath*)this->actor.parent)->unk_2FC = 20; + } + D_808CC258 = 0; + } else if (D_808CC254 >= 5) { + do { + phi_s0_3 = + (EnMinideath*)SubS_FindActor(play, &phi_s0_3->actor, ACTORCAT_ENEMY, ACTOR_EN_MINIDEATH); + if (phi_s0_3 != NULL) { + phi_s0_3->timer = 0; + phi_s0_3 = (EnMinideath*)phi_s0_3->actor.next; + } + } while (phi_s0_3 != NULL); + D_808CC254 = 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..2c1c35869 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*); +// "animation" length +#define MINIDEATH_ANIM_LENGTH 9 + +typedef enum { + MINIDEATH_ACTION_CONTINUE, // continue with current action until it is changed + MINIDEATH_ACTION_1, // scatter after light arrows? + MINIDEATH_ACTION_2, // gomess damaged + MINIDEATH_ACTION_3, + MINIDEATH_ACTION_4, // chase player? + MINIDEATH_ACTION_DIE, // dead? + MINIDEATH_ACTION_6, + MINIDEATH_ACTION_7, + MINIDEATH_ACTION_8, + MINIDEATH_ACTION_9 +} MinideathAction; + +typedef struct { + /* 0x00 */ u8 animFrame; + /* 0x01 */ u8 unk_1; + /* 0x04 */ Vec3f unk_4; + /* 0x10 */ Vec3f unk_10; + /* 0x1C */ s16 unk_1C; + /* 0x1E */ s16 unk_1E; + /* 0x20 */ char unk_20[0x2]; + /* 0x22 */ s16 unk_22; +} MiniDeathStruct; // size = 0x24 + typedef struct EnMinideath { - /* 0x000 */ Actor actor; - /* 0x144 */ EnMinideathActionFunc actionFunc; - /* 0x148 */ char unk_148[0x164]; + /* 0x0000 */ Actor actor; + /* 0x0144 */ EnMinideathActionFunc actionFunc; + /* 0x0148 */ u8 number; + /* 0x0149 */ u8 unk_149; + /* 0x014A */ s16 timer; + /* 0x014C */ s16 spawnShapeRot; + /* 0x014E */ s16 attackTimer; + /* 0x0150 */ Vec3s unk_150; // move direction? + /* 0x0158 */ f32 unk_158; + /* 0x015C */ Actor* unk_15C; + /* 0x0160 */ MiniDeathStruct unk_160[3]; + /* 0x01CC */ ColliderJntSph collider; + /* 0x01EC */ ColliderJntSphElement colliderElements[3]; } EnMinideath; // size = 0x2AC #endif // Z_EN_MINIDEATH_H diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index fa541ead0..be573d38c 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -6209,7 +6209,7 @@ 0x808C96C8:("EnDeath_Draw",), 0x808CA0B0:("EnMinideath_Init",), 0x808CA23C:("EnMinideath_Destroy",), - 0x808CA268:("func_808CA268",), + 0x808CA268:("EnMinideath_DropCollectible",), 0x808CA308:("func_808CA308",), 0x808CA34C:("func_808CA34C",), 0x808CA458:("func_808CA458",), @@ -6239,7 +6239,7 @@ 0x808CB6D4:("func_808CB6D4",), 0x808CB7B8:("func_808CB7B8",), 0x808CB7CC:("func_808CB7CC",), - 0x808CB810:("func_808CB810",), + 0x808CB810:("EnMinideath_SetNextAction",), 0x808CB8F4:("func_808CB8F4",), 0x808CBB18:("EnMinideath_Update",), 0x808CC260:("EnVm_Init",),