summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorpetrie911 <69443847+petrie911@users.noreply.github.com>2021-03-29 14:35:46 -0500
committerGitHub <noreply@github.com>2021-03-29 15:35:46 -0400
commit28cfd82a4f692cdeb1e66c2df980da07e6b41e2d (patch)
tree94896568117a3864adf4a3c8f543c47bc5225b61 /src
parent86f16cf662db0e4b8ba9973a6b055ab9cd395670 (diff)
Phantom Ganon (ovl_Boss_Ganondrof) and related actors (#442)
* Darkmeiro decompilation Bg_Gnd_Darkmeiro decompiled, matched, and documented. * give this a shot * fix conflict * one more try * It's Phantom Ganon time * Fhg_Fire matched * small touch up * more documentation * starting naming fire * renaming * cleanup * hooray for new names * merge * first pass * camera status * bgcheck * object 1 * object 2 * .s * .s * fig's comments * implementing zel's suggestions and a few other things * the work begins * work continues * docs, shifts, cleanup * cleanup * texture names * addressing the rest of the notes Co-authored-by: petrie911 <pmontag@DESKTOP-LG8A167.localdomain>
Diffstat (limited to 'src')
-rw-r--r--src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c1469
-rw-r--r--src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h94
-rw-r--r--src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c7
-rw-r--r--src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.c722
-rw-r--r--src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.h77
-rw-r--r--src/overlays/actors/ovl_En_fHG/z_en_fhg.c708
-rw-r--r--src/overlays/actors/ovl_En_fHG/z_en_fhg.h62
-rw-r--r--src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c27
8 files changed, 2814 insertions, 352 deletions
diff --git a/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c b/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c
index d2e3fe6a5..1f3660651 100644
--- a/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c
+++ b/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.c
@@ -1,15 +1,75 @@
+/*
+ * File: z_boss_ganondrof.c
+ * Overlay: ovl_Boss_Ganondrof
+ * Description: Phantom Ganon
+ */
+
#include "z_boss_ganondrof.h"
+#include "objects/object_gnd/object_gnd.h"
+#include "overlays/actors/ovl_En_fHG/z_en_fhg.h"
+#include "overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.h"
+#include "overlays/effects/ovl_Effect_Ss_Fhg_Flash/z_eff_ss_fhg_flash.h"
+#include "overlays/effects/ovl_Effect_Ss_Hahen/z_eff_ss_hahen.h"
#define FLAGS 0x00000035
#define THIS ((BossGanondrof*)thisx)
+typedef enum {
+ /* 0 */ NOT_DEAD,
+ /* 1 */ DEATH_START,
+ /* 2 */ DEATH_THROES,
+ /* 3 */ DEATH_WARP,
+ /* 4 */ DEATH_SCREAM,
+ /* 5 */ DEATH_DISINTEGRATE,
+ /* 6 */ DEATH_FINISH
+} BossGanondrofDeathState;
+
+typedef enum {
+ /* 0 */ THROW_NORMAL,
+ /* 1 */ THROW_SLOW
+} BossGanondrofThrowAction;
+
+typedef enum {
+ /* 0 */ STUNNED_FALL,
+ /* 1 */ STUNNED_GROUND
+} BossGanondrofStunnedAction;
+
+typedef enum {
+ /* 0 */ CHARGE_WINDUP,
+ /* 1 */ CHARGE_START,
+ /* 2 */ CHARGE_ATTACK,
+ /* 3 */ CHARGE_FINISH
+} BossGanondrofChargeAction;
+
+typedef enum {
+ /* 0 */ DEATH_SPASM,
+ /* 1 */ DEATH_LIMP,
+ /* 2 */ DEATH_HUNCHED
+} BossGanondrofDeathAction;
+
void BossGanondrof_Init(Actor* thisx, GlobalContext* globalCtx);
void BossGanondrof_Destroy(Actor* thisx, GlobalContext* globalCtx);
void BossGanondrof_Update(Actor* thisx, GlobalContext* globalCtx);
void BossGanondrof_Draw(Actor* thisx, GlobalContext* globalCtx);
-/*
+void BossGanondrof_SetupIntro(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_Intro(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_SetupPaintings(BossGanondrof* this);
+void BossGanondrof_Paintings(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_SetupNeutral(BossGanondrof* this, f32 arg1);
+void BossGanondrof_Neutral(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_SetupThrow(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_Throw(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_SetupBlock(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_Block(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_SetupReturn(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_Return(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_SetupCharge(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_Charge(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_Stunned(BossGanondrof* this, GlobalContext* globalCtx);
+void BossGanondrof_Death(BossGanondrof* this, GlobalContext* globalCtx);
+
const ActorInit Boss_Ganondrof_InitVars = {
ACTOR_BOSS_GANONDROF,
ACTORCAT_BOSS,
@@ -22,7 +82,7 @@ const ActorInit Boss_Ganondrof_InitVars = {
(ActorFunc)BossGanondrof_Draw,
};
-static ColliderCylinderInit D_80914CD0 = {
+static ColliderCylinderInit sCylinderInitBody = {
{
COLTYPE_HIT3,
AT_ON | AT_TYPE_ENEMY,
@@ -42,7 +102,7 @@ static ColliderCylinderInit D_80914CD0 = {
{ 30, 90, -50, { 0, 0, 0 } },
};
-static ColliderCylinderInit D_80914CFC = {
+static ColliderCylinderInit sCylinderInitSpear = {
{
COLTYPE_HIT3,
AT_ON | AT_TYPE_ENEMY,
@@ -61,71 +121,1404 @@ static ColliderCylinderInit D_80914CFC = {
},
{ 20, 30, -20, { 0, 0, 0 } },
};
-*/
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80910640.s")
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80910680.s")
+// clang-format off
+static u8 sDecayMaskHigh[16 * 16] = {
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,
+ 1,0,1,1,0,0,0,0,1,1,1,1,1,1,0,1,
+ 1,0,1,1,1,0,0,0,0,1,1,1,1,1,0,1,
+ 1,0,0,1,1,1,1,0,0,0,1,1,1,0,0,1,
+ 1,0,0,1,1,1,1,1,0,0,0,1,1,0,0,1,
+ 1,0,1,1,1,1,0,0,0,0,0,1,0,0,0,1,
+ 1,1,1,1,1,1,1,1,0,0,0,0,1,1,0,1,
+ 1,0,1,1,1,1,1,0,0,0,0,1,1,1,0,1,
+ 1,0,0,1,1,1,0,0,0,1,1,1,1,1,0,1,
+ 1,0,0,0,0,0,0,0,0,0,1,1,1,1,0,1,
+ 1,0,0,0,1,1,0,0,0,1,1,1,1,1,1,1,
+ 1,0,0,1,1,1,1,0,1,1,1,1,1,1,1,1,
+ 1,0,1,1,1,1,1,0,0,1,1,1,1,1,0,1,
+ 1,1,1,1,1,1,1,0,0,1,1,1,0,0,0,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+};
+
+static u8 sDecayMaskLow[16 * 16] = {
+ 1,1,1,0,1,0,0,1,0,0,1,1,1,1,1,1,
+ 0,0,0,0,0,0,0,0,1,1,1,0,0,1,1,0,
+ 1,0,1,1,0,0,0,0,0,1,1,0,0,1,0,0,
+ 1,0,0,1,1,0,0,0,0,0,1,1,1,0,0,0,
+ 0,0,0,1,1,1,0,0,0,0,0,1,1,0,0,1,
+ 0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,1,
+ 1,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,
+ 1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,
+ 1,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,
+ 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,
+ 1,0,0,0,0,1,0,0,0,0,0,1,1,1,0,0,
+ 1,0,0,0,0,1,0,0,0,0,1,0,1,1,0,0,
+ 0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,
+ 1,0,0,0,1,0,1,0,0,0,1,1,0,0,0,1,
+ 1,0,0,1,1,1,0,0,0,1,1,1,0,0,0,1,
+};
+
+static u8 sDecayMaskTotal[16 * 16] = {
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+};
+// clang-format on
+
+// These are Phantom Ganon's body textures, but I don't know which is which.
+static u64* sLimbTex_rgb5a1_8x8[] = {
+ gPhantomGanonLimbTex_00A800, gPhantomGanonLimbTex_00AE80, gPhantomGanonLimbTex_00AF00,
+ gPhantomGanonLimbTex_00C180, gPhantomGanonLimbTex_00C400,
+};
+static u64* sLimbTex_rgb5a1_16x8[] = {
+ gPhantomGanonLimbTex_00B980, gPhantomGanonLimbTex_00C480, gPhantomGanonLimbTex_00BC80,
+ gPhantomGanonLimbTex_00BD80, gPhantomGanonLimbTex_00C080,
+};
+static u64* sLimbTex_rgb5a1_16x16[] = {
+ gPhantomGanonLimbTex_00C200, gPhantomGanonLimbTex_00A000, gPhantomGanonLimbTex_00A200,
+ gPhantomGanonLimbTex_00A400, gPhantomGanonLimbTex_00A600, gPhantomGanonLimbTex_00A880,
+ gPhantomGanonLimbTex_00B780, gPhantomGanonLimbTex_00BA80, gPhantomGanonLimbTex_00BE80,
+};
+static u64* sLimbTex_rgb5a1_16x32[] = { gPhantomGanonLimbTex_00AA80, gPhantomGanonLimbTex_00AF80 };
+
+static u64* sMouthTex_ci8_16x16[] = { gPhantomGanonMouthTex, gPhantomGanonSmileTex };
+
+static InitChainEntry sInitChain[] = {
+ ICHAIN_U8(targetMode, 5, ICHAIN_CONTINUE),
+ ICHAIN_S8(naviEnemyId, 43, ICHAIN_CONTINUE),
+ ICHAIN_F32_DIV1000(gravity, 0, ICHAIN_CONTINUE),
+ ICHAIN_F32(targetArrowOffset, 0, ICHAIN_STOP),
+};
+
+static Vec3f sAudioVec = { 0.0f, 0.0f, 50.0f };
+
+void BossGanondrof_ClearPixels8x8(s16* texture, u8* mask, s16 index) {
+ if (mask[index]) {
+ texture[index / 4] = 0;
+ }
+}
+
+void BossGanondrof_ClearPixels16x8(s16* texture, u8* mask, s16 index) {
+ if (mask[index]) {
+ texture[index / 2] = 0;
+ }
+}
+
+void BossGanondrof_ClearPixels16x16(s16* texture, u8* mask, s16 index) {
+ if (mask[index]) {
+ texture[index] = 0;
+ }
+}
+
+void BossGanondrof_ClearPixels32x16(s16* texture, u8* mask, s16 index) {
+ if (mask[index]) {
+ s16 i = (index & 0xF) + ((index & 0xF0) << 1);
+
+ texture[i + 0x10] = 0;
+ texture[i] = 0;
+ }
+}
+
+void BossGanondrof_ClearPixels16x32(s16* texture, u8* mask, s16 index) {
+ if (mask[index]) {
+ s16 i = ((index & 0xF) * 2) + ((index & 0xF0) * 2);
+
+ texture[i + 1] = 0;
+ texture[i] = 0;
+ }
+}
+
+void BossGanondrof_ClearPixels(u8* mask, s16 index) {
+ s16 i;
+
+ for (i = 0; i < 5; i++) {
+ // ARRAY_COUNT can't be used here because the arrays aren't guaranteed to be the same size.
+ BossGanondrof_ClearPixels8x8(SEGMENTED_TO_VIRTUAL(sLimbTex_rgb5a1_8x8[i]), mask, index);
+ BossGanondrof_ClearPixels16x8(SEGMENTED_TO_VIRTUAL(sLimbTex_rgb5a1_16x8[i]), mask, index);
+ }
+
+ for (i = 0; i < ARRAY_COUNT(sLimbTex_rgb5a1_16x16); i++) {
+ BossGanondrof_ClearPixels16x16(SEGMENTED_TO_VIRTUAL(sLimbTex_rgb5a1_16x16[i]), mask, index);
+ }
+
+ for (i = 0; i < ARRAY_COUNT(sLimbTex_rgb5a1_16x32); i++) {
+ BossGanondrof_ClearPixels16x32(SEGMENTED_TO_VIRTUAL(sLimbTex_rgb5a1_16x32[i]), mask, index);
+ }
+
+ BossGanondrof_ClearPixels32x16(SEGMENTED_TO_VIRTUAL(gPhantomGanonLimbTex_00B380), mask, index);
+ BossGanondrof_ClearPixels16x32(SEGMENTED_TO_VIRTUAL(gPhantomGanonEyeTex), mask, index);
+ for (i = 0; i < ARRAY_COUNT(sMouthTex_ci8_16x16); i++) {
+ BossGanondrof_ClearPixels16x16(SEGMENTED_TO_VIRTUAL(sMouthTex_ci8_16x16[i]), mask, index);
+ }
+}
+
+void BossGanondrof_SetColliderPos(Vec3f* pos, ColliderCylinder* collider) {
+ collider->dim.pos.x = pos->x;
+ collider->dim.pos.y = pos->y;
+ collider->dim.pos.z = pos->z;
+}
+
+void BossGanondrof_Init(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ BossGanondrof* this = THIS;
+
+ Actor_ProcessInitChain(&this->actor, sInitChain);
+ ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f);
+ Actor_SetScale(&this->actor, 0.01f);
+ SkelAnime_Init(globalCtx, &this->skelAnime, &gPhantomGanonSkel, &gPhantomGanonRideAnim, NULL, NULL, 0);
+ if (this->actor.params < GND_FAKE_BOSS) {
+ this->actor.params = GND_REAL_BOSS;
+ this->actor.colChkInfo.health = 30;
+ this->lightNode = LightContext_InsertLight(globalCtx, &globalCtx->lightCtx, &this->lightInfo);
+ Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y,
+ this->actor.world.pos.z, 255, 255, 255, 255);
+ BossGanondrof_SetupIntro(this, globalCtx);
+ } else {
+ BossGanondrof_SetupPaintings(this);
+ }
+
+ Collider_InitCylinder(globalCtx, &this->colliderBody);
+ Collider_InitCylinder(globalCtx, &this->colliderSpear);
+ Collider_SetCylinder(globalCtx, &this->colliderBody, &this->actor, &sCylinderInitBody);
+ Collider_SetCylinder(globalCtx, &this->colliderSpear, &this->actor, &sCylinderInitSpear);
+ this->actor.flags &= ~1;
+ if (Flags_GetClear(globalCtx, globalCtx->roomCtx.curRoom.num)) {
+ Actor_Kill(&this->actor);
+ Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_DOOR_WARP1, GND_BOSSROOM_CENTER_X, GND_BOSSROOM_CENTER_Y,
+ GND_BOSSROOM_CENTER_Z, 0, 0, 0, -1);
+ Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_ITEM_B_HEART, 200.0f + GND_BOSSROOM_CENTER_X,
+ GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, 0);
+ } else {
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG, this->actor.world.pos.x,
+ this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, this->actor.params);
+ }
+}
+
+void BossGanondrof_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ BossGanondrof* this = THIS;
+
+ osSyncPrintf("DT1\n");
+ SkelAnime_Free(&this->skelAnime, globalCtx);
+ Collider_DestroyCylinder(globalCtx, &this->colliderBody);
+ Collider_DestroyCylinder(globalCtx, &this->colliderSpear);
+ if (this->actor.params == GND_REAL_BOSS) {
+ LightContext_RemoveLight(globalCtx, &globalCtx->lightCtx, this->lightNode);
+ }
+
+ osSyncPrintf("DT2\n");
+}
+
+void BossGanondrof_SetupIntro(BossGanondrof* this, GlobalContext* globalCtx) {
+ Animation_PlayLoop(&this->skelAnime, &gPhantomGanonRidePoseAnim);
+ this->actionFunc = BossGanondrof_Intro;
+ this->work[GND_MASK_OFF] = true;
+}
+
+void BossGanondrof_Intro(BossGanondrof* this, GlobalContext* globalCtx) {
+ s16 i;
+ s32 pad;
+ EnfHG* horse = (EnfHG*)this->actor.child;
+
+ SkelAnime_Update(&this->skelAnime);
+ this->actor.world.pos = horse->actor.world.pos;
+ this->actor.shape.rot.y = this->actor.world.rot.y = horse->actor.world.rot.y;
+
+ osSyncPrintf("SW %d------------------------------------------------\n", horse->bossGndSignal);
+
+ if ((this->timers[1] != 0) && (this->timers[1] < 25)) {
+ Vec3f pos;
+ Vec3f vel = { 0.0f, 0.0f, 0.0f };
+ Vec3f accel = { 0.0f, 0.0f, 0.0f };
+
+ pos.x = this->bodyPartsPos[14].x + Rand_CenteredFloat(10.0f);
+ pos.y = this->bodyPartsPos[14].y + Rand_ZeroFloat(-5.0f);
+ pos.z = this->bodyPartsPos[14].z + Rand_CenteredFloat(10.0f) + 5.0f;
+ accel.y = 0.03f;
+ EffectSsKFire_Spawn(globalCtx, &pos, &vel, &accel, (s16)Rand_ZeroFloat(10.0f) + 5, 0);
+ }
+
+ if (this->timers[1] == 20) {
+ this->work[GND_MASK_OFF] = false;
+ }
+
+ if (this->timers[1] == 30) {
+ func_80078914(&sAudioVec, NA_SE_EN_FANTOM_TRANSFORM);
+ }
+
+ if (horse->bossGndSignal == FHG_LIGHTNING) {
+ Animation_Change(&this->skelAnime, &gPhantomGanonMaskOnAnim, 0.5f, 0.0f,
+ Animation_GetLastFrame(&gPhantomGanonMaskOnAnim), ANIMMODE_ONCE_INTERP, 0.0f);
+ this->timers[1] = 40;
+ }
+
+ if (horse->bossGndSignal == FHG_REAR) {
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonHorseRearingAnim, -3.0f);
+ }
+
+ if (horse->bossGndSignal == FHG_RIDE) {
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonRidePoseAnim, -13.0f);
+ }
+
+ if (horse->bossGndSignal == FHG_SPUR) {
+ EnfHG* horseTemp;
+
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonRideSpearRaiseAnim, -7.0f);
+ horseTemp = (EnfHG*)this->actor.child;
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE, this->spearTip.x,
+ this->spearTip.y, this->spearTip.z, 50, FHGFIRE_LIGHT_GREEN, 0, FHGFIRE_SPEAR_LIGHT);
+ this->actor.child = &horseTemp->actor;
+ }
+
+ if (horse->bossGndSignal == FHG_FINISH) {
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonRideSpearResetAnim, -5.0f);
+ }
+
+ switch (this->work[GND_EYE_STATE]) {
+ case GND_EYESTATE_FADE:
+ this->fwork[GND_EYE_ALPHA] += 40.0f;
+ if (this->fwork[GND_EYE_ALPHA] >= 255.0f) {
+ this->fwork[GND_EYE_ALPHA] = 255.0f;
+ }
+ break;
+
+ case GND_EYESTATE_BRIGHTEN:
+ this->fwork[GND_EYE_BRIGHTNESS] += 20.0f;
+ if (this->fwork[GND_EYE_BRIGHTNESS] > 255.0f) {
+ this->fwork[GND_EYE_BRIGHTNESS] = 255.0f;
+ }
+ break;
+ }
+
+ this->armRotY = Math_SinS(this->work[GND_VARIANCE_TIMER] * 0x6E8) * 0;
+ this->armRotZ = Math_CosS(this->work[GND_VARIANCE_TIMER] * 0x8DC) * 300.0f;
+ for (i = 0; i < 30; i++) {
+ this->rideRotY[i] = Math_SinS(this->work[GND_VARIANCE_TIMER] * ((i * 50) + 0x7B0)) * 100.0f;
+ this->rideRotZ[i] = Math_CosS(this->work[GND_VARIANCE_TIMER] * ((i * 50) + 0x8DC)) * 100.0f;
+ }
+
+ if (horse->bossGndSignal == FHG_START_FIGHT) {
+ BossGanondrof_SetupPaintings(this);
+ for (i = 0; i < 30; i++) {
+ this->rideRotY[i] = this->rideRotZ[i] = 0.0f;
+ }
+ }
+
+ horse->bossGndSignal = FHG_NO_SIGNAL;
+}
+
+void BossGanondrof_SetupPaintings(BossGanondrof* this) {
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonRideAnim, -5.0f);
+ this->actionFunc = BossGanondrof_Paintings;
+}
+
+void BossGanondrof_Paintings(BossGanondrof* this, GlobalContext* globalCtx) {
+ EnfHG* horse = (EnfHG*)this->actor.child;
+
+ osSyncPrintf("RUN 1\n");
+ SkelAnime_Update(&this->skelAnime);
+ osSyncPrintf("RUN 2\n");
+
+ if (horse->bossGndSignal == FHG_RAISE_SPEAR) {
+ EnfHG* horseTemp;
+
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonRideSpearRaiseAnim, -2.0f);
+ this->actor.flags |= 1;
+ horseTemp = (EnfHG*)this->actor.child;
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE, this->spearTip.x,
+ this->spearTip.y, this->spearTip.z, 30, FHGFIRE_LIGHT_GREEN, 0, FHGFIRE_SPEAR_LIGHT);
+ this->actor.child = &horseTemp->actor;
+ } else if (horse->bossGndSignal == FHG_LIGHTNING) {
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonRideSpearStrikeAnim, -2.0f);
+ } else if (horse->bossGndSignal == FHG_RESET) {
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonRideSpearResetAnim, -2.0f);
+ } else if (horse->bossGndSignal == FHG_RIDE) {
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonRideAnim, -2.0f);
+ this->actor.flags &= ~1;
+ }
+
+ osSyncPrintf("RUN 3\n");
+ this->actor.world.pos = horse->actor.world.pos;
+ this->actor.world.pos.y = horse->actor.world.pos.y;
+ this->actor.shape.rot.y = this->actor.world.rot.y = horse->actor.world.rot.y;
+ if (this->flyMode != GND_FLY_PAINTING) {
+ BossGanondrof_SetupNeutral(this, -20.0f);
+ this->timers[0] = 100;
+ this->colliderBody.dim.radius = 20;
+ this->colliderBody.dim.height = 60;
+ this->colliderBody.dim.yShift = -33;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_LAUGH);
+ this->actor.naviEnemyId = 0x1A;
+ } else {
+ horse->bossGndSignal = FHG_NO_SIGNAL;
+ this->actor.scale.x = horse->actor.scale.x / 1.15f;
+ this->actor.scale.y = horse->actor.scale.y / 1.15f;
+ this->actor.scale.z = horse->actor.scale.z / 1.15f;
+ osSyncPrintf("RUN 4\n");
+ }
+}
+
+void BossGanondrof_SetupNeutral(BossGanondrof* this, f32 arg1) {
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonNeutralAnim, arg1);
+ this->actionFunc = BossGanondrof_Neutral;
+ this->actor.flags |= 1;
+ this->fwork[GND_FLOAT_SPEED] = 0.0f;
+ this->timers[0] = (s16)(Rand_ZeroOne() * 64.0f) + 30;
+}
+
+void BossGanondrof_Neutral(BossGanondrof* this, GlobalContext* globalCtx) {
+ f32 targetX;
+ f32 targetY;
+ f32 targetZ;
+ Player* player = PLAYER;
+ Actor* playerx = &player->actor;
+ Actor* thisx = &this->actor;
+ f32 rand01;
+ s16 i;
+
+ SkelAnime_Update(&this->skelAnime);
+ switch (this->flyMode) {
+ case GND_FLY_NEUTRAL:
+ if (this->timers[0] == 0) {
+ this->timers[0] = (s16)(Rand_ZeroOne() * 64.0f) + 30;
+ rand01 = Rand_ZeroOne();
+ if (thisx->colChkInfo.health < 5) {
+ if (rand01 < 0.25f) {
+ BossGanondrof_SetupThrow(this, globalCtx);
+ } else if (rand01 >= 0.8f) {
+ this->flyMode = GND_FLY_CHARGE;
+ this->timers[0] = 60;
+ this->fwork[GND_FLOAT_SPEED] = 0.0f;
+ Audio_PlayActorSound2(thisx, NA_SE_EN_FANTOM_LAUGH);
+ } else {
+ this->flyMode = GND_FLY_VOLLEY;
+ this->timers[0] = 60;
+ this->fwork[GND_FLOAT_SPEED] = 0.0f;
+ Audio_PlayActorSound2(thisx, NA_SE_EN_FANTOM_LAUGH);
+ }
+ } else if ((rand01 < 0.5f) || (this->work[GND_THROW_COUNT] < 5)) {
+ BossGanondrof_SetupThrow(this, globalCtx);
+ } else {
+ this->flyMode = GND_FLY_VOLLEY;
+ this->timers[0] = 60;
+ this->fwork[GND_FLOAT_SPEED] = 0.0f;
+ Audio_PlayActorSound2(thisx, NA_SE_EN_FANTOM_LAUGH);
+ }
+ }
+
+ if (this->timers[1] != 0) {
+ targetX = GND_BOSSROOM_CENTER_X;
+ targetZ = GND_BOSSROOM_CENTER_Z;
+ } else {
+ targetX = playerx->world.pos.x + (180.0f * Math_SinS(playerx->shape.rot.y));
+ targetZ = playerx->world.pos.z + (180.0f * Math_CosS(playerx->shape.rot.y));
+ if (sqrtf(SQ(targetX - GND_BOSSROOM_CENTER_X) + SQ(targetZ - GND_BOSSROOM_CENTER_Z)) > 280.0f) {
+ this->timers[1] = 50;
+ this->fwork[GND_FLOAT_SPEED] = 0.0f;
+ }
+ }
+
+ targetY = playerx->world.pos.y + 100.0f + 0.0f;
+ targetX += Math_SinS(this->work[GND_VARIANCE_TIMER] * 0x500) * 100.0f;
+ targetZ += Math_CosS(this->work[GND_VARIANCE_TIMER] * 0x700) * 100.0f;
+ break;
+ case GND_FLY_VOLLEY:
+ targetX = GND_BOSSROOM_CENTER_X - 14.0f;
+ targetZ = GND_BOSSROOM_CENTER_Z + 265.0f;
+
+ targetY = playerx->world.pos.y + 100.0f + 100.0f;
+ targetX += Math_SinS(this->work[GND_VARIANCE_TIMER] * 0x500) * 100.0f;
+ targetZ += Math_CosS(this->work[GND_VARIANCE_TIMER] * 0x700) * 100.0f;
+ if (this->timers[0] == 0) {
+ this->flyMode = GND_FLY_RETURN;
+ this->returnSuccess = false;
+ BossGanondrof_SetupThrow(this, globalCtx);
+ this->timers[0] = 80;
+ }
+ break;
+ case GND_FLY_RETURN:
+ targetX = GND_BOSSROOM_CENTER_X - 14.0f;
+ targetZ = GND_BOSSROOM_CENTER_Z + 265.0f;
+
+ targetY = playerx->world.pos.y + 100.0f + 100.0f;
+ targetX += Math_SinS(this->work[GND_VARIANCE_TIMER] * 0x500) * 50.0f;
+ targetZ += Math_CosS(this->work[GND_VARIANCE_TIMER] * 0x700) * 50.0f;
+ if (this->returnSuccess) {
+ this->returnSuccess = false;
+ BossGanondrof_SetupReturn(this, globalCtx);
+ this->timers[0] = 80;
+ }
+
+ if (this->timers[0] == 0) {
+ this->flyMode = GND_FLY_NEUTRAL;
+ }
+ break;
+ case GND_FLY_CHARGE:
+ targetX = GND_BOSSROOM_CENTER_X - 14.0f;
+ targetZ = GND_BOSSROOM_CENTER_Z + 215.0f;
+
+ targetY = playerx->world.pos.y + 100.0f + 50.0f;
+ targetX += Math_SinS(this->work[GND_VARIANCE_TIMER] * 0x500) * 100.0f;
+ targetZ += Math_CosS(this->work[GND_VARIANCE_TIMER] * 0x700) * 100.0f;
+ if (this->timers[0] == 0) {
+ BossGanondrof_SetupCharge(this, globalCtx);
+ }
+ break;
+ }
+
+ Math_ApproachF(&thisx->world.pos.x, targetX, 0.05f, this->fwork[GND_FLOAT_SPEED]);
+ if (this->timers[2] != 0) {
+ Math_ApproachF(&thisx->world.pos.y, targetY + 100.0f, 0.1f, 50.0f);
+ } else {
+ Math_ApproachF(&thisx->world.pos.y, targetY, 0.05f, 10.0f);
+ }
+
+ Math_ApproachF(&thisx->world.pos.z, targetZ, 0.05f, this->fwork[GND_FLOAT_SPEED]);
+ Math_ApproachF(&this->fwork[GND_FLOAT_SPEED], 50.0f, 1.0f, 0.5f);
+ thisx->velocity.x = thisx->world.pos.x - thisx->prevPos.x;
+ thisx->velocity.z = thisx->world.pos.z - thisx->prevPos.z;
+ thisx->world.pos.y += 2.0f * Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
+ Math_ApproachS(&thisx->shape.rot.y, thisx->yawTowardsPlayer, 5, 0xBB8);
+ if ((this->work[GND_VARIANCE_TIMER] & 1) == 0) {
+ Vec3f pos;
+ Vec3f vel = { 0.0f, 0.0f, 0.0f };
+ Vec3f accel = { 0.0f, 0.0f, 0.0f };
+
+ for (i = 0; i < 3; i++) {
+ pos.x = Rand_CenteredFloat(20.0f) + this->spearTip.x;
+ pos.y = Rand_CenteredFloat(20.0f) + this->spearTip.y;
+ pos.z = Rand_CenteredFloat(20.0f) + this->spearTip.z;
+ accel.y = -0.08f;
+ EffectSsFhgFlash_SpawnLightBall(globalCtx, &pos, &vel, &accel, (s16)(Rand_ZeroOne() * 80.0f) + 150,
+ FHGFLASH_LIGHTBALL_GREEN);
+ }
+ }
+
+ if (player->unk_A73 != 0) {
+ BossGanondrof_SetupBlock(this, globalCtx);
+ }
+
+ Audio_PlayActorSound2(thisx, NA_SE_EN_FANTOM_FLOAT - SFX_FLAG);
+}
+
+void BossGanondrof_SetupThrow(BossGanondrof* this, GlobalContext* globalCtx) {
+ EnfHG* horseTemp;
+ s16 lightTime;
+
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonThrowAnim);
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonThrowAnim, -5.0f);
+ this->actionFunc = BossGanondrof_Throw;
+ if ((Rand_ZeroOne() <= 0.1f) && (this->work[GND_THROW_COUNT] >= 10) && (this->flyMode == GND_FLY_NEUTRAL)) {
+ this->work[GND_ACTION_STATE] = THROW_SLOW;
+ this->work[GND_THROW_FRAME] = 1000;
+ lightTime = 32;
+ } else {
+ this->work[GND_ACTION_STATE] = THROW_NORMAL;
+ this->work[GND_THROW_FRAME] = 25;
+ lightTime = 25;
+ }
+
+ horseTemp = (EnfHG*)this->actor.child;
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE, this->spearTip.x,
+ this->spearTip.y, this->spearTip.z, lightTime, FHGFIRE_LIGHT_GREEN, 0, FHGFIRE_SPEAR_LIGHT);
+ this->actor.child = &horseTemp->actor;
+ this->work[GND_THROW_COUNT]++;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_STICK);
+}
+
+void BossGanondrof_Throw(BossGanondrof* this, GlobalContext* globalCtx) {
+ SkelAnime_Update(&this->skelAnime);
+ osSyncPrintf("this->fwork[GND_END_FRAME] = %d\n", (s16)this->fwork[GND_END_FRAME]);
+ osSyncPrintf("this->work[GND_SHOT_FRAME] = %d\n", this->work[GND_THROW_FRAME]);
+ if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) {
+ BossGanondrof_SetupNeutral(this, -6.0f);
+ }
+
+ if ((this->work[GND_ACTION_STATE] != THROW_NORMAL) && Animation_OnFrame(&this->skelAnime, 21.0f)) {
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonThrowEndAnim);
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonThrowEndAnim, 0.0f);
+ this->work[GND_THROW_FRAME] = 10;
+ }
+
+ if (Animation_OnFrame(&this->skelAnime, this->work[GND_THROW_FRAME])) {
+ if (this->flyMode <= GND_FLY_NEUTRAL) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_MASIC2);
+ } else {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_MASIC1);
+ }
+
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_VOICE);
+ }
+
+ if (Animation_OnFrame(&this->skelAnime, this->work[GND_THROW_FRAME])) {
+ EnfHG* horseTemp = (EnfHG*)this->actor.child;
+
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE, this->spearTip.x,
+ this->spearTip.y, this->spearTip.z, this->work[GND_ACTION_STATE], 0, 0, FHGFIRE_ENERGY_BALL);
+ this->actor.child = &horseTemp->actor;
+ }
+
+ Math_ApproachS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 5, 0x7D0);
+ this->actor.world.pos.x += this->actor.velocity.x;
+ this->actor.world.pos.z += this->actor.velocity.z;
+ Math_ApproachZeroF(&this->actor.velocity.x, 1.0f, 0.5f);
+ Math_ApproachZeroF(&this->actor.velocity.z, 1.0f, 0.5f);
+ this->actor.world.pos.y += 2.0f * Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
+}
+
+void BossGanondrof_SetupReturn(BossGanondrof* this, GlobalContext* globalCtx) {
+ static AnimationHeader* returnAnim[] = { &gPhantomGanonReturn1Anim, &gPhantomGanonReturn2Anim };
+ s16 rand = Rand_ZeroOne() * 1.99f;
+
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(returnAnim[rand]);
+ Animation_MorphToPlayOnce(&this->skelAnime, returnAnim[rand], 0.0f);
+ this->actionFunc = BossGanondrof_Return;
+}
+
+void BossGanondrof_Return(BossGanondrof* this, GlobalContext* globalCtx) {
+ SkelAnime_Update(&this->skelAnime);
+ if (Animation_OnFrame(&this->skelAnime, 5.0f)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_VOICE);
+ osSyncPrintf("VOISE 2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+ osSyncPrintf("VOISE 2 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
+ }
+
+ if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) {
+ BossGanondrof_SetupNeutral(this, 0.0f);
+ }
+
+ this->actor.world.pos.x += this->actor.velocity.x;
+ this->actor.world.pos.z += this->actor.velocity.z;
+ Math_ApproachZeroF(&this->actor.velocity.x, 1.0f, 0.5f);
+ Math_ApproachZeroF(&this->actor.velocity.z, 1.0f, 0.5f);
+ this->actor.world.pos.y += 2.0f * Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
+ if (this->returnSuccess) {
+ this->returnSuccess = false;
+ BossGanondrof_SetupReturn(this, globalCtx);
+ this->timers[0] = 80;
+ }
+}
+
+void BossGanondrof_SetupStunned(BossGanondrof* this, GlobalContext* globalCtx) {
+ if (this->actionFunc != BossGanondrof_Stunned) {
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonAirDamageAnim);
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonAirDamageAnim, 0.0f);
+ this->timers[0] = 50;
+ this->shockTimer = 60;
+ } else {
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonGroundDamageAnim);
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonGroundDamageAnim, 0.0f);
+ }
+
+ this->actionFunc = BossGanondrof_Stunned;
+ this->work[GND_ACTION_STATE] = STUNNED_FALL;
+ this->actor.velocity.x = 0.0f;
+ this->actor.velocity.z = 0.0f;
+}
+
+void BossGanondrof_Stunned(BossGanondrof* this, GlobalContext* globalCtx) {
+ osSyncPrintf("DAMAGE .................................\n");
+ SkelAnime_Update(&this->skelAnime);
+ this->actor.gravity = -0.2f;
+ if (this->actor.world.pos.y <= 5.0f) {
+ if (this->work[GND_ACTION_STATE] == STUNNED_FALL) {
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonStunnedAnim);
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonStunnedAnim, -10.0f);
+ this->work[GND_ACTION_STATE] = STUNNED_GROUND;
+ }
+
+ this->actor.velocity.y = 0.0f;
+ this->actor.gravity = 0.0f;
+ if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_DAMAGE2);
+ }
+
+ this->actor.flags |= 0x400;
+ }
+
+ osSyncPrintf("TIME0 %d ********************************************\n", this->timers[0]);
+ if (this->timers[0] == 0) {
+ BossGanondrof_SetupNeutral(this, -5.0f);
+ this->timers[0] = 30;
+ this->timers[2] = 30;
+ this->flyMode = GND_FLY_NEUTRAL;
+ this->actor.velocity.y = 0.0f;
+ this->actor.gravity = 0.0f;
+ }
+
+ Actor_MoveForward(&this->actor);
+}
+
+void BossGanondrof_SetupBlock(BossGanondrof* this, GlobalContext* globalCtx) {
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonBlockAnim);
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonBlockAnim, -3.0f);
+ this->actionFunc = BossGanondrof_Block;
+ this->timers[0] = 10;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_STICK);
+}
+
+void BossGanondrof_Block(BossGanondrof* this, GlobalContext* globalCtx) {
+ this->colliderBody.base.colType = COLTYPE_METAL;
+ SkelAnime_Update(&this->skelAnime);
+ this->actor.world.pos.x += this->actor.velocity.x;
+ this->actor.world.pos.z += this->actor.velocity.z;
+ Math_ApproachZeroF(&this->actor.velocity.x, 1.0f, 0.5f);
+ Math_ApproachZeroF(&this->actor.velocity.z, 1.0f, 0.5f);
+ this->actor.world.pos.y += 2.0f * Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
+ if (this->timers[0] == 0) {
+ BossGanondrof_SetupNeutral(this, -5.0f);
+ this->timers[0] = 10;
+ this->flyMode = GND_FLY_NEUTRAL;
+ }
+}
+
+void BossGanondrof_SetupCharge(BossGanondrof* this, GlobalContext* globalCtx) {
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonChargeWindupAnim);
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonChargeWindupAnim, -3.0f);
+ this->actionFunc = BossGanondrof_Charge;
+ this->timers[0] = 20;
+ this->work[GND_ACTION_STATE] = CHARGE_WINDUP;
+}
+
+void BossGanondrof_Charge(BossGanondrof* this, GlobalContext* globalCtx) {
+ Player* player = PLAYER;
+ Actor* playerx = &player->actor;
+ Actor* thisx = &this->actor;
+ f32 dxCenter = thisx->world.pos.x - GND_BOSSROOM_CENTER_X;
+ f32 dzCenter = thisx->world.pos.z - GND_BOSSROOM_CENTER_Z;
+
+ this->colliderBody.base.colType = COLTYPE_METAL;
+ SkelAnime_Update(&this->skelAnime);
+ switch (this->work[GND_ACTION_STATE]) {
+ case CHARGE_WINDUP:
+ if (this->timers[0] == 218) {
+ Audio_PlayActorSound2(thisx, NA_SE_EN_FANTOM_STICK);
+ }
+
+ if (this->timers[0] == 19) {
+ Audio_PlayActorSound2(thisx, NA_SE_EN_FANTOM_ATTACK);
+ }
+
+ thisx->world.pos.x += thisx->velocity.x;
+ thisx->world.pos.z += thisx->velocity.z;
+ Math_ApproachZeroF(&thisx->velocity.x, 1.0f, 0.5f);
+ Math_ApproachZeroF(&thisx->velocity.z, 1.0f, 0.5f);
+ if (this->timers[0] == 0) {
+ this->work[GND_ACTION_STATE] = CHARGE_START;
+ this->timers[0] = 10;
+ thisx->speedXZ = 0.0f;
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonChargeStartAnim);
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonChargeStartAnim, 0.0f);
+ }
+
+ Math_ApproachS(&thisx->shape.rot.y, thisx->yawTowardsPlayer, 5, 0x7D0);
+ break;
+ case CHARGE_START:
+ if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) {
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonChargeAnim);
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonChargeAnim, 0.0f);
+ this->work[GND_ACTION_STATE] = CHARGE_ATTACK;
+ }
+ case CHARGE_ATTACK:
+ if (this->timers[0] != 0) {
+ Vec3f vecToLink;
+
+ Math_ApproachS(&thisx->shape.rot.y, thisx->yawTowardsPlayer, 5, 0x7D0);
+ vecToLink.x = playerx->world.pos.x - thisx->world.pos.x;
+ vecToLink.y = playerx->world.pos.y + 40.0f - thisx->world.pos.y;
+ vecToLink.z = playerx->world.pos.z - thisx->world.pos.z;
+ thisx->world.rot.y = thisx->shape.rot.y;
+ thisx->world.rot.x =
+ Math_FAtan2F(vecToLink.y, sqrtf(SQ(vecToLink.x) + SQ(vecToLink.z))) * (0x8000 / M_PI);
+ }
+
+ func_8002D908(thisx);
+ func_8002D7EC(thisx);
+ Math_ApproachF(&thisx->speedXZ, 10.0f, 1.0f, 0.5f);
+ if ((sqrtf(SQ(dxCenter) + SQ(dzCenter)) > 280.0f) || (thisx->xyzDistToPlayerSq < SQ(100.0f))) {
+ this->work[GND_ACTION_STATE] = CHARGE_FINISH;
+ this->timers[0] = 20;
+ }
+ break;
+ case CHARGE_FINISH:
+ thisx->gravity = 0.2f;
+ Actor_MoveForward(thisx);
+ osSyncPrintf("YP %f @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@\n", thisx->world.pos.y);
+ if (thisx->world.pos.y < 5.0f) {
+ thisx->world.pos.y = 5.0f;
+ thisx->velocity.y = 0.0f;
+ }
+
+ if (sqrtf(SQ(dxCenter) + SQ(dzCenter)) > 280.0f) {
+ Math_ApproachZeroF(&thisx->speedXZ, 1.0f, 2.0f);
+ this->timers[0] = 0;
+ }
+
+ if (this->timers[0] == 0) {
+ Math_ApproachZeroF(&thisx->speedXZ, 1.0f, 2.0f);
+ Math_ApproachZeroF(&thisx->velocity.y, 1.0f, 2.0f);
+ Math_ApproachS(&thisx->shape.rot.y, thisx->yawTowardsPlayer, 5, 0x7D0);
+ if ((thisx->speedXZ <= 0.5f) && (fabsf(thisx->velocity.y) <= 0.1f)) {
+ BossGanondrof_SetupNeutral(this, -10.0f);
+ this->timers[0] = 30;
+ this->flyMode = GND_FLY_NEUTRAL;
+ }
+ }
+ break;
+ }
+
+ if (thisx->world.pos.y > (GND_BOSSROOM_CENTER_Y + 83.0f)) {
+ thisx->world.pos.y += 2.0f * Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
+ }
+ {
+ s16 i;
+ Vec3f pos;
+ Vec3f vel = { 0.0f, 0.0f, 0.0f };
+ Vec3f accel = { 0.0f, 0.0f, 0.0f };
+ Vec3f baseOffset = { 0.0f, 50.0f, 0.0f };
+ Vec3f offset;
+
+ baseOffset.y = 10.0f;
+ for (i = 0; i < 10; i++) {
+ Matrix_Push();
+ Matrix_RotateY((thisx->shape.rot.y / (f32)0x8000) * M_PI, MTXMODE_NEW);
+ Matrix_RotateX((thisx->shape.rot.x / (f32)0x8000) * M_PI, MTXMODE_APPLY);
+ Matrix_RotateZ((this->work[GND_PARTICLE_ANGLE] / (f32)0x8000) * M_PI, MTXMODE_APPLY);
+ Matrix_MultVec3f(&baseOffset, &offset);
+ Matrix_Pop();
+ pos.x = this->spearTip.x + offset.x;
+ pos.y = this->spearTip.y + offset.y;
+ pos.z = this->spearTip.z + offset.z;
+ vel.x = (offset.x * 500.0f) / 1000.0f;
+ vel.y = (offset.y * 500.0f) / 1000.0f;
+ vel.z = (offset.z * 500.0f) / 1000.0f;
+ accel.x = (offset.x * -50.0f) / 1000.0f;
+ accel.y = (offset.y * -50.0f) / 1000.0f;
+ accel.z = (offset.z * -50.0f) / 1000.0f;
+ EffectSsFhgFlash_SpawnLightBall(globalCtx, &pos, &vel, &accel, 150, i % 7);
+ this->work[GND_PARTICLE_ANGLE] += 0x1A5C;
+ }
+ }
+
+ if (!(this->work[GND_VARIANCE_TIMER] & 7)) {
+ EnfHG* horse = (EnfHG*)thisx->child;
+
+ Actor_SpawnAsChild(&globalCtx->actorCtx, thisx, globalCtx, ACTOR_EN_FHG_FIRE, this->spearTip.x,
+ this->spearTip.y, this->spearTip.z, 8, FHGFIRE_LIGHT_BLUE, 0, FHGFIRE_SPEAR_LIGHT);
+ thisx->child = &horse->actor;
+ }
+}
+
+void BossGanondrof_SetupDeath(BossGanondrof* this, GlobalContext* globalCtx) {
+ Animation_PlayOnce(&this->skelAnime, &gPhantomGanonDeathBlowAnim);
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonDeathBlowAnim);
+ this->actionFunc = BossGanondrof_Death;
+ Audio_SetBGM(0x100100FF);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_DEAD);
+ this->deathState = DEATH_START;
+ this->actor.flags &= ~1;
+ this->work[GND_VARIANCE_TIMER] = 0;
+ this->shockTimer = 50;
+}
+
+void BossGanondrof_Death(BossGanondrof* this, GlobalContext* globalCtx) {
+ u8 holdCamera = false;
+ u8 bodyDecayLevel = 0;
+ f32 camX;
+ f32 camZ;
+ f32 pad;
+ Player* player = PLAYER;
+ Camera* camera = Gameplay_GetCamera(globalCtx, 0);
+
+ osSyncPrintf("PYP %f\n", player->actor.floorHeight);
+ SkelAnime_Update(&this->skelAnime);
+ this->work[GND_DEATH_SFX_TIMER]++;
+ if (((60 < this->work[GND_DEATH_SFX_TIMER]) && (this->work[GND_DEATH_SFX_TIMER] < 500)) ||
+ ((501 < this->work[GND_DEATH_SFX_TIMER]) && (this->work[GND_DEATH_SFX_TIMER] < 620))) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_GOMA_LAST - SFX_FLAG);
+ }
+
+ switch (this->deathState) {
+ case DEATH_START:
+ func_80064520(globalCtx, &globalCtx->csCtx);
+ func_8002DF54(globalCtx, &this->actor, 1);
+ this->deathCamera = Gameplay_CreateSubCamera(globalCtx);
+ Gameplay_ChangeCameraStatus(globalCtx, 0, 1);
+ osSyncPrintf("7\n");
+ Gameplay_ChangeCameraStatus(globalCtx, this->deathCamera, 7);
+ osSyncPrintf("8\n");
+ this->deathState = DEATH_THROES;
+ player->actor.speedXZ = 0.0f;
+ this->timers[0] = 50;
+ this->cameraEye = camera->eye;
+ this->cameraAt = camera->at;
+ this->cameraNextEye.x = this->targetPos.x;
+ this->cameraNextEye.y = GND_BOSSROOM_CENTER_Y + 83.0f;
+ this->cameraNextEye.z = (this->targetPos.z + 100.0f) + 50;
+ this->cameraNextAt.x = this->targetPos.x;
+ this->cameraNextAt.y = this->targetPos.y - 10.0f;
+ this->cameraNextAt.z = this->targetPos.z;
+ this->cameraEyeVel.x = fabsf(camera->eye.x - this->cameraNextEye.x);
+ this->cameraEyeVel.y = fabsf(camera->eye.y - this->cameraNextEye.y);
+ this->cameraEyeVel.z = fabsf(camera->eye.z - this->cameraNextEye.z);
+ this->cameraAtVel.x = fabsf(camera->at.x - this->cameraNextAt.x);
+ this->cameraAtVel.y = fabsf(camera->at.y - this->cameraNextAt.y);
+ this->cameraAtVel.z = fabsf(camera->at.z - this->cameraNextAt.z);
+ this->cameraAccel = 0.02f;
+ this->cameraEyeMaxVel.x = this->cameraEyeMaxVel.y = this->cameraEyeMaxVel.z = 0.05f;
+ this->work[GND_ACTION_STATE] = DEATH_SPASM;
+ this->timers[0] = 150;
+ this->cameraAtMaxVel.x = 0.2f;
+ this->cameraAtMaxVel.y = 0.2f;
+ this->cameraAtMaxVel.z = 0.2f;
+ case DEATH_THROES:
+ switch (this->work[GND_ACTION_STATE]) {
+ case DEATH_SPASM:
+ if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) {
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonAirDamageAnim);
+ Animation_Change(&this->skelAnime, &gPhantomGanonAirDamageAnim, 0.5f, 0.0f,
+ this->fwork[GND_END_FRAME], ANIMMODE_ONCE_INTERP, 0.0f);
+ this->work[GND_ACTION_STATE] = DEATH_LIMP;
+ }
+ break;
+ case DEATH_LIMP:
+ if (Animation_OnFrame(&this->skelAnime, this->fwork[GND_END_FRAME])) {
+ this->fwork[GND_END_FRAME] = Animation_GetLastFrame(&gPhantomGanonLimpAnim);
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonLimpAnim, -20.0f);
+ this->work[GND_ACTION_STATE] = DEATH_HUNCHED;
+ }
+ case DEATH_HUNCHED:
+ bodyDecayLevel = 1;
+ break;
+ }
+ Math_ApproachS(&this->actor.shape.rot.y, this->work[GND_VARIANCE_TIMER] * -100, 5, 0xBB8);
+ Math_ApproachF(&this->cameraNextEye.z, this->targetPos.z + 60.0f, 0.02f, 0.5f);
+ Math_ApproachF(&this->actor.world.pos.y, GND_BOSSROOM_CENTER_Y + 133.0f, 0.05f, 100.0f);
+ this->actor.world.pos.y += Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
+ this->cameraNextAt.x = this->targetPos.x;
+ this->cameraNextAt.y = this->targetPos.y - 10.0f;
+ this->cameraNextAt.z = this->targetPos.z;
+ if (this->timers[0] == 0) {
+ this->deathState = DEATH_WARP;
+ this->timers[0] = 350;
+ this->timers[1] = 50;
+ this->fwork[GND_CAMERA_ZOOM] = 300.0f;
+ this->cameraNextEye.y = GND_BOSSROOM_CENTER_Y + 233.0f;
+ player->actor.world.pos.x = GND_BOSSROOM_CENTER_X - 200.0f;
+ player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
+ holdCamera = true;
+ bodyDecayLevel = 1;
+ }
+ break;
+ case DEATH_WARP:
+ if (this->timers[1] == 1) {
+ EnfHG* horseTemp = (EnfHG*)this->actor.child;
+
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE,
+ GND_BOSSROOM_CENTER_X, GND_BOSSROOM_CENTER_Y + 3.0f, GND_BOSSROOM_CENTER_Z, 0x4000,
+ 0, 0, FHGFIRE_WARP_DEATH);
+ this->actor.child = &horseTemp->actor;
+ func_8010B680(globalCtx, 0x108E, NULL);
+ }
+
+ this->actor.shape.rot.y -= 0xC8;
+ this->actor.world.pos.y += Math_SinS(this->work[GND_VARIANCE_TIMER] * 1500);
+ this->fwork[GND_CAMERA_ANGLE] += 0x78;
+ camX = Math_SinS(this->fwork[GND_CAMERA_ANGLE]) * this->fwork[GND_CAMERA_ZOOM];
+ camZ = Math_CosS(this->fwork[GND_CAMERA_ANGLE]) * this->fwork[GND_CAMERA_ZOOM];
+ this->cameraEye.x = GND_BOSSROOM_CENTER_X + camX;
+ this->cameraEye.y = this->cameraNextEye.y;
+ this->cameraEye.z = GND_BOSSROOM_CENTER_Z + camZ;
+ this->cameraAt.x = GND_BOSSROOM_CENTER_X;
+ this->cameraAt.y = GND_BOSSROOM_CENTER_Y + 23.0f;
+ this->cameraAt.z = GND_BOSSROOM_CENTER_Z;
+ Math_ApproachF(&this->cameraNextEye.y, GND_BOSSROOM_CENTER_Y + 33.0f, 0.05f, 0.5f);
+ Math_ApproachF(&this->fwork[GND_CAMERA_ZOOM], 170.0f, 0.05f, 1.0f);
+ Math_ApproachF(&this->actor.world.pos.x, GND_BOSSROOM_CENTER_X, 0.05f, 1.5f);
+ Math_ApproachF(&this->actor.world.pos.y, GND_BOSSROOM_CENTER_Y + 83.0f, 0.05f, 1.0f);
+ Math_ApproachF(&this->actor.world.pos.z, GND_BOSSROOM_CENTER_Z, 0.05f, 1.5f);
+ if (this->timers[0] == 0) {
+ this->deathState = DEATH_SCREAM;
+ this->timers[0] = 50;
+ Animation_MorphToLoop(&this->skelAnime, &gPhantomGanonScreamAnim, -10.0f);
+ this->actor.world.pos.x = GND_BOSSROOM_CENTER_X;
+ this->actor.world.pos.y = GND_BOSSROOM_CENTER_Y + 83.0f;
+ this->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
+ this->actor.shape.rot.y = 0;
+ this->work[GND_BODY_DECAY_INDEX] = 0;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_LAST);
+ }
+
+ holdCamera = true;
+ bodyDecayLevel = 1;
+ break;
+ case DEATH_SCREAM:
+ holdCamera = true;
+ bodyDecayLevel = 2;
+ this->actor.world.pos.y = GND_BOSSROOM_CENTER_Y + 83.0f;
+ this->cameraEye.x = GND_BOSSROOM_CENTER_X;
+ this->cameraEye.y = GND_BOSSROOM_CENTER_Y + 83.0f;
+ this->cameraEye.z = GND_BOSSROOM_CENTER_Z + 50.0f;
+ this->cameraAt.x = GND_BOSSROOM_CENTER_X;
+ this->cameraAt.y = GND_BOSSROOM_CENTER_Y + 103.0f;
+ this->cameraAt.z = GND_BOSSROOM_CENTER_Z;
+ if (this->timers[0] == 0) {
+ this->deathState = DEATH_DISINTEGRATE;
+ Animation_MorphToPlayOnce(&this->skelAnime, &gPhantomGanonLastPoseAnim, -10.0f);
+ this->work[GND_BODY_DECAY_INDEX] = 0;
+ this->timers[0] = 40;
+ }
+ break;
+ case DEATH_DISINTEGRATE:
+ holdCamera = true;
+ bodyDecayLevel = 3;
+ Math_ApproachZeroF(&this->cameraEye.y, 0.05f, 1.0f); // approaches GND_BOSSROOM_CENTER_Y + 33.0f
+ Math_ApproachF(&this->cameraEye.z, GND_BOSSROOM_CENTER_Z + 170.0f, 0.05f, 2.0f);
+ Math_ApproachF(&this->cameraAt.y, GND_BOSSROOM_CENTER_Y + 53.0f, 0.05f, 1.0f);
+ if (this->timers[0] == 0) {
+ this->timers[0] = 250;
+ this->deathState = DEATH_FINISH;
+ }
+ break;
+ case DEATH_FINISH:
+ holdCamera = true;
+ bodyDecayLevel = 10;
+ if (this->timers[0] == 150) {
+ Audio_SetBGM(0x21);
+ Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_DOOR_WARP1, GND_BOSSROOM_CENTER_X,
+ GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z, 0, 0, 0, -1);
+ }
+
+ Math_ApproachZeroF(&this->cameraEye.y, 0.05f, 1.0f); // GND_BOSSROOM_CENTER_Y + 33.0f
+ Math_ApproachF(&this->cameraEye.z, GND_BOSSROOM_CENTER_Z + 170.0f, 0.05f, 2.0f);
+ Math_ApproachF(&this->cameraAt.y, GND_BOSSROOM_CENTER_Y + 53.0f, 0.05f, 1.0f);
+ if (this->timers[0] == 0) {
+ EnfHG* horse = (EnfHG*)this->actor.child;
+
+ camera->eye = this->cameraEye;
+ camera->eyeNext = this->cameraEye;
+ camera->at = this->cameraAt;
+ func_800C08AC(globalCtx, this->deathCamera, 0);
+ this->deathCamera = 0;
+ func_80064534(globalCtx, &globalCtx->csCtx);
+ func_8002DF54(globalCtx, &this->actor, 7);
+ Actor_Spawn(&globalCtx->actorCtx, globalCtx, ACTOR_ITEM_B_HEART, GND_BOSSROOM_CENTER_X,
+ GND_BOSSROOM_CENTER_Y, GND_BOSSROOM_CENTER_Z + 200.0f, 0, 0, 0, 0);
+ this->actor.child = &horse->actor;
+ this->killActor = true;
+ horse->killActor = true;
+ Flags_SetClear(globalCtx, globalCtx->roomCtx.curRoom.num);
+ Flags_SetSwitch(globalCtx, 0x22);
+ }
+ break;
+ }
+
+ if (bodyDecayLevel) {
+ Vec3f pos;
+ Vec3f vel = { 0.0f, 0.0f, 0.0f };
+ Vec3f accelKFire = { 0.0f, 0.0f, 0.0f };
+ Vec3f accelHahen = { 0.0f, -0.5f, 0.0f };
+ s16 limbDecayIndex;
+ s16 i;
+
+ vel.x = this->actor.world.pos.x - this->actor.prevPos.x;
+ vel.z = this->actor.world.pos.z - this->actor.prevPos.z;
+ if (bodyDecayLevel < 10) {
+ if (this->work[GND_DEATH_ENV_TIMER] == 0) {
+ if (globalCtx->envCtx.unk_BF == 0) {
+ globalCtx->envCtx.unk_BF = 3;
+ this->work[GND_DEATH_ENV_TIMER] = (s16)Rand_ZeroFloat(5.0f) + 4.0f;
+ globalCtx->envCtx.unk_D6 = 0x28;
+ } else {
+ globalCtx->envCtx.unk_BF = 0;
+ this->work[GND_DEATH_ENV_TIMER] = (s16)Rand_ZeroFloat(2.0f) + 2.0f;
+ globalCtx->envCtx.unk_D6 = 0x14;
+ }
+ } else {
+ this->work[GND_DEATH_ENV_TIMER]--;
+ }
+
+ for (i = 0; i <= 0; i++) {
+ limbDecayIndex = this->work[GND_LIMB_DECAY_INDEX];
+ this->work[GND_LIMB_DECAY_INDEX]++;
+ this->work[GND_LIMB_DECAY_INDEX] %= 25;
+ pos.x = this->bodyPartsPos[limbDecayIndex].x + Rand_CenteredFloat(5.0f);
+ pos.y = this->bodyPartsPos[limbDecayIndex].y + Rand_CenteredFloat(5.0f);
+ pos.z = this->bodyPartsPos[limbDecayIndex].z + Rand_CenteredFloat(5.0f);
+ accelKFire.y = 0.0f;
+
+ if (bodyDecayLevel == 3) {
+ accelKFire.y = -0.2f;
+ accelKFire.x = (GND_BOSSROOM_CENTER_X - pos.x) * 0.002f;
+ accelKFire.z = (GND_BOSSROOM_CENTER_Z - pos.z) * 0.002f;
+ accelHahen.x = (GND_BOSSROOM_CENTER_X - pos.x) * 0.001f;
+ accelHahen.y = -1.0f;
+ accelHahen.z = (GND_BOSSROOM_CENTER_Z - pos.z) * 0.001f;
+ }
+
+ EffectSsKFire_Spawn(globalCtx, &pos, &vel, &accelKFire, (s16)Rand_ZeroFloat(20.0f) + 15,
+ bodyDecayLevel);
+ if ((Rand_ZeroOne() < 0.5f) || (bodyDecayLevel == 3)) {
+ EffectSsHahen_Spawn(globalCtx, &pos, &vel, &accelHahen, 0, (s16)Rand_ZeroFloat(4.0f) + 7,
+ HAHEN_OBJECT_DEFAULT, 10, NULL);
+ }
+ }
+ } else {
+ globalCtx->envCtx.unk_BF = 0;
+ globalCtx->envCtx.unk_D6 = 0x14;
+ }
+
+ this->work[GND_BODY_DECAY_FLAG] = true;
+ for (i = 0; i < 5; i++) {
+ if (bodyDecayLevel == 1) {
+ BossGanondrof_ClearPixels(sDecayMaskLow, this->work[GND_BODY_DECAY_INDEX]);
+ } else if (bodyDecayLevel == 2) {
+ BossGanondrof_ClearPixels(sDecayMaskHigh, this->work[GND_BODY_DECAY_INDEX]);
+ } else {
+ BossGanondrof_ClearPixels(sDecayMaskTotal, this->work[GND_BODY_DECAY_INDEX]);
+ }
+
+ if (this->work[GND_BODY_DECAY_INDEX] < 0x100) {
+ this->work[GND_BODY_DECAY_INDEX]++;
+ }
+ }
+ }
+
+ if (this->deathCamera != 0) {
+ if (!holdCamera) {
+ Math_ApproachF(&this->cameraEye.x, this->cameraNextEye.x, this->cameraEyeMaxVel.x,
+ this->cameraEyeVel.x * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraEye.y, this->cameraNextEye.y, this->cameraEyeMaxVel.y,
+ this->cameraEyeVel.y * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraEye.z, this->cameraNextEye.z, this->cameraEyeMaxVel.z,
+ this->cameraEyeVel.z * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraAt.x, this->cameraNextAt.x, this->cameraAtMaxVel.x,
+ this->cameraAtVel.x * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraAt.y, this->cameraNextAt.y, this->cameraAtMaxVel.y,
+ this->cameraAtVel.y * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraAt.z, this->cameraNextAt.z, this->cameraAtMaxVel.z,
+ this->cameraAtVel.z * this->cameraSpeedMod);
+ Math_ApproachF(&this->cameraSpeedMod, 1.0f, 1.0f, this->cameraAccel);
+ }
+
+ Gameplay_CameraSetAtEye(globalCtx, this->deathCamera, &this->cameraAt, &this->cameraEye);
+ }
+}
+
+void BossGanondrof_CollisionCheck(BossGanondrof* this, GlobalContext* globalCtx) {
+ s32 acHit;
+ EnfHG* horse = (EnfHG*)this->actor.child;
+ ColliderInfo* hurtbox;
+
+ if (this->work[GND_INVINC_TIMER] != 0) {
+ this->work[GND_INVINC_TIMER]--;
+ this->returnCount = 0;
+ this->colliderBody.base.acFlags &= ~AC_HIT;
+ } else {
+ acHit = this->colliderBody.base.acFlags & AC_HIT;
+ if ((acHit && ((s8)this->actor.colChkInfo.health > 0)) || (this->returnCount != 0)) {
+ if (acHit) {
+ this->colliderBody.base.acFlags &= ~AC_HIT;
+ hurtbox = this->colliderBody.info.acHitInfo;
+ }
+ if (this->flyMode != GND_FLY_PAINTING) {
+ if (acHit && (this->actionFunc != BossGanondrof_Stunned) && (hurtbox->toucher.dmgFlags & 0x0001F8A4)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_PL_WALK_GROUND - SFX_FLAG);
+ osSyncPrintf("hit != 0 \n");
+ } else if (this->actionFunc != BossGanondrof_Charge) {
+ if (this->returnCount == 0) {
+ u8 dmg;
+ u8 canKill = false;
+ s32 dmgFlags = hurtbox->toucher.dmgFlags;
+
+ if (dmgFlags & 0x80) {
+ return;
+ }
+ dmg = CollisionCheck_GetSwordDamage(dmgFlags);
+ (dmg == 0) ? (dmg = 2) : (canKill = true);
+ if (((s8)this->actor.colChkInfo.health > 2) || canKill) {
+ this->actor.colChkInfo.health -= dmg;
+ }
+
+ if ((s8)this->actor.colChkInfo.health <= 0) {
+ BossGanondrof_SetupDeath(this, globalCtx);
+ func_80032C7C(globalCtx, &this->actor);
+ return;
+ }
+ }
+ BossGanondrof_SetupStunned(this, globalCtx);
+ if (this->returnCount >= 2) {
+ this->timers[0] = 120;
+ }
+ this->work[GND_INVINC_TIMER] = 10;
+ horse->hitTimer = 20;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_DAMAGE);
+ } else {
+ Audio_PlayActorSound2(&this->actor, NA_SE_PL_WALK_GROUND - SFX_FLAG);
+ }
+ } else if (acHit && (hurtbox->toucher.dmgFlags & 0x0001F8A4)) {
+ this->work[GND_INVINC_TIMER] = 10;
+ this->actor.colChkInfo.health -= 2;
+ horse->hitTimer = 20;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_DAMAGE);
+ }
+ this->returnCount = 0;
+ }
+ }
+}
+
+void BossGanondrof_Update(Actor* thisx, GlobalContext* globalCtx) {
+ f32 cs;
+ f32 sn;
+ f32 legRotTargetY;
+ f32 legRotTargetZ;
+ f32 legSplitTarget;
+ s32 pad2;
+ s16 i;
+ s32 pad;
+ BossGanondrof* this = THIS;
+ EnfHG* horse;
+
+ osSyncPrintf("MOVE START %d\n", this->actor.params);
+ this->actor.flags &= ~0x400;
+ this->colliderBody.base.colType = COLTYPE_HIT3;
+ if (this->killActor) {
+ Actor_Kill(&this->actor);
+ return;
+ }
+ this->work[GND_VARIANCE_TIMER]++;
+ horse = (EnfHG*)this->actor.child;
+ osSyncPrintf("MOVE START EEEEEEEEEEEEEEEEEEEEEE%d\n", this->actor.params);
+
+ this->actionFunc(this, globalCtx);
+
+ for (i = 0; i < ARRAY_COUNT(this->timers); i++) {
+ if (this->timers[i]) {
+ this->timers[i]--;
+ }
+ }
+ if (this->work[GND_UNKTIMER_1]) {
+ this->work[GND_UNKTIMER_1]--;
+ }
+ if (this->work[GND_UNKTIMER_2]) {
+ this->work[GND_UNKTIMER_2]--;
+ }
+
+ if (this->actionFunc != BossGanondrof_Death) {
+ BossGanondrof_CollisionCheck(this, globalCtx);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809106C0.s")
+ osSyncPrintf("MOVE END\n");
+ BossGanondrof_SetColliderPos(&this->targetPos, &this->colliderBody);
+ BossGanondrof_SetColliderPos(&this->spearTip, &this->colliderSpear);
+ if ((this->flyMode == GND_FLY_PAINTING) && !horse->bossGndInPainting) {
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderBody.base);
+ }
+ if ((this->actionFunc == BossGanondrof_Stunned) && (this->timers[0] > 1)) {
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderBody.base);
+ CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->colliderBody.base);
+ } else if (this->actionFunc == BossGanondrof_Block) {
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderBody.base);
+ } else if (this->actionFunc == BossGanondrof_Charge) {
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->colliderBody.base);
+ CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->colliderBody.base);
+ CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->colliderSpear.base);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809106F0.s")
+ this->actor.focus.pos = this->targetPos;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80910738.s")
+ sn = Math_SinS(-this->actor.shape.rot.y);
+ cs = Math_CosS(-this->actor.shape.rot.y);
+ legRotTargetY = ((sn * this->actor.velocity.z) + (cs * this->actor.velocity.x)) * 300.0f;
+ legRotTargetZ = ((-sn * this->actor.velocity.x) + (cs * this->actor.velocity.z)) * 300.0f;
+ Math_ApproachF(&this->legRotY, legRotTargetY, 1.0f, 600.0f);
+ Math_ApproachF(&this->legRotZ, legRotTargetZ, 1.0f, 600.0f);
+ if ((this->flyMode != GND_FLY_PAINTING) && (this->actionFunc != BossGanondrof_Stunned) &&
+ (this->deathState == NOT_DEAD)) {
+ legSplitTarget = (Math_SinS(this->work[GND_VARIANCE_TIMER] * 0x8DC) * -500.0f) - 500.0f;
+ } else {
+ legSplitTarget = 0.0f;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80910784.s")
+ Math_ApproachF(&this->legSplitY, legSplitTarget, 1.0f, 100.0f);
+ if (this->shockTimer != 0) {
+ s16 j;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80910A34.s")
+ this->shockTimer--;
+ osSyncPrintf("F 1\n");
+ for (j = 0; j < 7; j++) {
+ osSyncPrintf("F 15\n");
+ EffectSsFhgFlash_SpawnShock(globalCtx, &this->actor, &this->actor.world.pos, 45, FHGFLASH_SHOCK_PG);
+ }
+ osSyncPrintf("F 2\n");
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/BossGanondrof_Init.s")
+ if (this->actor.params == GND_REAL_BOSS) {
+ Lights_PointNoGlowSetInfo(&this->lightInfo, this->spearTip.x, this->spearTip.y, this->spearTip.z, 255, 255, 255,
+ 200);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/BossGanondrof_Destroy.s")
+s32 BossGanondrof_OverrideLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot,
+ void* thisx) {
+ BossGanondrof* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80910D80.s")
+ switch (limbIndex) {
+ case 15:
+ if ((this->actionFunc == BossGanondrof_Intro) && this->work[GND_MASK_OFF]) {
+ *dList = gPhantomGanonFaceDL;
+ }
+ rot->y += this->rideRotY[limbIndex];
+ rot->z += this->rideRotZ[limbIndex];
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80910DCC.s")
+ case 19:
+ rot->y += this->legRotY + this->legSplitY;
+ rot->z += this->legRotZ;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80911294.s")
+ case 20:
+ rot->y += this->legRotY + this->legSplitY;
+ rot->z += this->legRotZ;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809112D4.s")
+ case 21:
+ rot->y += this->legRotY + this->legSplitY;
+ rot->z += this->legRotZ;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809114E8.s")
+ case 23:
+ rot->y += this->legRotY - this->legSplitY;
+ rot->z += this->legRotZ;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_8091156C.s")
+ case 24:
+ rot->y += this->legRotY - this->legSplitY;
+ rot->z += this->legRotZ;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80911CB0.s")
+ case 25:
+ rot->y += this->legRotY - this->legSplitY;
+ rot->z += this->legRotZ;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80911DD8.s")
+ case 5:
+ case 6:
+ case 7:
+ rot->y += this->armRotY;
+ rot->z += this->armRotZ;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80912020.s")
+ case 8:
+ case 9:
+ case 10:
+ rot->y += this->armRotY;
+ rot->z += this->armRotZ;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809120BC.s")
+ case 13:
+ if (this->deathState != NOT_DEAD) {
+ *dList = NULL;
+ }
+ default:
+ rot->y += this->rideRotY[limbIndex];
+ rot->z += this->rideRotZ[limbIndex];
+ break;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809121E0.s")
+ return 0;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809122A4.s")
+void BossGanondrof_PostLimbDraw(GlobalContext* globalCtx, s32 limbIndex, Gfx** dList, Vec3s* rot, void* thisx) {
+ static Vec3f zeroVec = { 0.0f, 0.0f, 0.0f };
+ static Vec3f spearVec = { 0.0f, 0.0f, 6000.0f };
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809123D4.s")
+ BossGanondrof* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80912448.s")
+ if (limbIndex == 14) {
+ Matrix_MultVec3f(&zeroVec, &this->targetPos);
+ } else if (limbIndex == 13) {
+ Matrix_MultVec3f(&spearVec, &this->spearTip);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80912524.s")
+ if (((this->flyMode != GND_FLY_PAINTING) || (this->actionFunc == BossGanondrof_Intro)) && (limbIndex <= 25)) {
+ Matrix_MultVec3f(&zeroVec, &this->bodyPartsPos[limbIndex - 1]);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80912594.s")
+Gfx* BossGanondrof_GetClearPixelDList(GraphicsContext* gfxCtx) {
+ Gfx* dList = (Gfx*)Graph_Alloc(gfxCtx, sizeof(Gfx) * 4);
+ Gfx* dListHead = dList;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80912C94.s")
+ gDPPipeSync(dListHead++);
+ gDPSetRenderMode(dListHead++, G_RM_FOG_SHADE_A, G_RM_AA_ZB_TEX_EDGE2);
+ gSPClearGeometryMode(dListHead++, G_CULL_BACK);
+ gSPEndDisplayList(dListHead++);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80912D2C.s")
+ return dList;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80913C54.s")
+Gfx* BossGanondrof_GetNullDList(GraphicsContext* gfxCtx) {
+ Gfx* dList = (Gfx*)Graph_Alloc(gfxCtx, sizeof(Gfx) * 1);
+ Gfx* dListHead = dList;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/BossGanondrof_Update.s")
+ gSPEndDisplayList(dListHead++);
+ return dList;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809142E0.s")
+void BossGanondrof_Draw(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ BossGanondrof* this = THIS;
+ EnfHG* horse;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809146DC.s")
+ OPEN_DISPS(globalCtx->state.gfxCtx, "../z_boss_ganondrof.c", 3716);
+ osSyncPrintf("MOVE P = %x\n", this->actor.update);
+ osSyncPrintf("STOP TIMER = %d ==============\n", this->actor.freezeTimer);
+ horse = (EnfHG*)this->actor.child;
+ if (this->flyMode == GND_FLY_PAINTING) {
+ Matrix_RotateY((horse->turnRot * 3.1416f) / (f32)0x8000, 1);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_809147A0.s")
+ osSyncPrintf("YP %f\n", this->actor.world.pos.y);
+ func_80093D18(globalCtx->state.gfxCtx);
+ if (this->work[GND_INVINC_TIMER] & 4) {
+ POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, 255, 50, 0, 0, 900, 1099);
+ } else {
+ POLY_OPA_DISP = Gfx_SetFog(POLY_OPA_DISP, (u32)horse->warpColorFilterR, (u32)horse->warpColorFilterG,
+ (u32)horse->warpColorFilterB, 0, (s32)horse->warpColorFilterUnk1 + 995,
+ (s32)horse->warpColorFilterUnk2 + 1000);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/func_80914818.s")
+ osSyncPrintf("DRAW 11\n");
+ osSyncPrintf("EYE_COL %d\n", (s16)this->fwork[GND_EYE_BRIGHTNESS]);
+ gDPSetEnvColor(POLY_OPA_DISP++, (s16)this->fwork[GND_EYE_BRIGHTNESS], (s16)this->fwork[GND_EYE_BRIGHTNESS],
+ (s16)this->fwork[GND_EYE_BRIGHTNESS], (s16)this->fwork[GND_EYE_ALPHA]);
+ if (this->work[GND_BODY_DECAY_FLAG]) {
+ gSPSegment(POLY_OPA_DISP++, 0x08, BossGanondrof_GetClearPixelDList(globalCtx->state.gfxCtx));
+ } else {
+ gSPSegment(POLY_OPA_DISP++, 0x08, BossGanondrof_GetNullDList(globalCtx->state.gfxCtx));
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_Boss_Ganondrof/BossGanondrof_Draw.s")
+ SkelAnime_DrawOpa(globalCtx, this->skelAnime.skeleton, this->skelAnime.jointTable, BossGanondrof_OverrideLimbDraw,
+ BossGanondrof_PostLimbDraw, this);
+ osSyncPrintf("DRAW 22\n");
+ POLY_OPA_DISP = func_800BC8A0(globalCtx, POLY_OPA_DISP);
+ CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_boss_ganondrof.c", 3814);
+ osSyncPrintf("DRAW END %d\n", this->actor.params);
+}
diff --git a/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h b/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h
index 170111a4e..6846a4b11 100644
--- a/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h
+++ b/src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h
@@ -6,11 +6,99 @@
struct BossGanondrof;
+typedef void (*BossGanondrofActionFunc)(struct BossGanondrof*, GlobalContext*);
+
+#define GND_REAL_BOSS 1
+#define GND_FAKE_BOSS 10
+
+#define GND_BOSSROOM_CENTER_X 14.0f
+#define GND_BOSSROOM_CENTER_Y -33.0f
+#define GND_BOSSROOM_CENTER_Z -3315.0f
+
+typedef enum {
+ /* 0 */ GND_FLY_PAINTING,
+ /* 1 */ GND_FLY_NEUTRAL,
+ /* 2 */ GND_FLY_VOLLEY,
+ /* 3 */ GND_FLY_RETURN,
+ /* 4 */ GND_FLY_CHARGE
+} BossGanondrofFlyMode;
+
+typedef enum {
+ /* 0 */ GND_EYESTATE_NONE,
+ /* 1 */ GND_EYESTATE_FADE,
+ /* 2 */ GND_EYESTATE_BRIGHTEN
+} BossGanondrofEyeState;
+
+typedef enum {
+ /* 0 */ GND_VARIANCE_TIMER,
+ /* 1 */ GND_US_1,
+ /* 2 */ GND_US_2,
+ /* 3 */ GND_US_3,
+ /* 4 */ GND_UNKTIMER_1,
+ /* 5 */ GND_UNKTIMER_2,
+ /* 6 */ GND_INVINC_TIMER,
+ /* 7 */ GND_ACTION_STATE,
+ /* 8 */ GND_THROW_FRAME,
+ /* 9 */ GND_THROW_COUNT,
+ /* 10 */ GND_MASK_OFF,
+ /* 11 */ GND_EYE_STATE,
+ /* 12 */ GND_PARTICLE_ANGLE,
+ /* 13 */ GND_BODY_DECAY_INDEX,
+ /* 14 */ GND_BODY_DECAY_FLAG,
+ /* 15 */ GND_LIMB_DECAY_INDEX,
+ /* 16 */ GND_DEATH_ENV_TIMER,
+ /* 17 */ GND_DEATH_SFX_TIMER,
+ /* 20 */ GND_SHORT_COUNT = 20
+} BossGanondrofS16Var;
+
+typedef enum {
+ /* 0 */ GND_FLOAT_SPEED,
+ /* 1 */ GND_END_FRAME,
+ /* 2 */ GND_EYE_BRIGHTNESS,
+ /* 3 */ GND_CAMERA_ZOOM,
+ /* 4 */ GND_CAMERA_ANGLE,
+ /* 5 */ GND_EYE_ALPHA,
+ /* 13 */ GND_FLOAT_COUNT = 13
+} BossGanondrofF32Var;
+
typedef struct BossGanondrof {
/* 0x0000 */ Actor actor;
- /* 0x014C */ char unk_14C[0xCC];
- /* 0x0218 */ Vec3f bodyPartsPos[24];
- /* 0x03C8 */ char unk_3C8[0x1B0];
+ /* 0x014C */ SkelAnime skelAnime;
+ /* 0x0190 */ BossGanondrofActionFunc actionFunc;
+ /* 0x0194 */ s16 work[GND_SHORT_COUNT];
+ /* 0x01BC */ s16 timers[5];
+ /* 0x01C6 */ u8 killActor;
+ /* 0x01C7 */ u8 returnCount;
+ /* 0x01C8 */ u8 shockTimer;
+ /* 0x01C9 */ u8 flyMode;
+ /* 0x01CA */ u8 returnSuccess;
+ /* 0x01CC */ f32 fwork[GND_FLOAT_COUNT];
+ /* 0x0200 */ Vec3f spearTip;
+ /* 0x020C */ Vec3f targetPos;
+ /* 0x0218 */ Vec3f bodyPartsPos[27]; // only 25 used
+ /* 0x035C */ s16 deathCamera;
+ /* 0x035E */ s16 deathState;
+ /* 0x0360 */ Vec3f cameraEye;
+ /* 0x036C */ Vec3f cameraAt;
+ /* 0x0378 */ Vec3f cameraEyeVel;
+ /* 0x0384 */ Vec3f cameraAtVel;
+ /* 0x0390 */ Vec3f cameraNextEye;
+ /* 0x039C */ Vec3f cameraEyeMaxVel;
+ /* 0x03A8 */ Vec3f cameraNextAt;
+ /* 0x03B4 */ Vec3f cameraAtMaxVel;
+ /* 0x03C0 */ f32 cameraSpeedMod;
+ /* 0x03C4 */ f32 cameraAccel;
+ /* 0x03C8 */ f32 legRotY;
+ /* 0x03CC */ f32 legRotZ;
+ /* 0x03D0 */ f32 legSplitY;
+ /* 0x03D4 */ f32 armRotY;
+ /* 0x03D8 */ f32 armRotZ;
+ /* 0x03DC */ f32 rideRotZ[30]; // possibly only 25 used
+ /* 0x0454 */ f32 rideRotY[30]; // possibly only 25 used
+ /* 0x04CC */ LightNode* lightNode;
+ /* 0x04D0 */ LightInfo lightInfo;
+ /* 0x04E0 */ ColliderCylinder colliderBody;
+ /* 0x052C */ ColliderCylinder colliderSpear;
} BossGanondrof; // size = 0x0578
extern const ActorInit Boss_Ganondrof_InitVars;
diff --git a/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c
index e6bbcc4d4..56b710b0f 100644
--- a/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c
+++ b/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c
@@ -7,6 +7,7 @@
#include "z_door_shutter.h"
#include "objects/object_demo_kekkai/object_demo_kekkai.h"
#include "overlays/actors/ovl_Boss_Goma/z_boss_goma.h"
+#include "objects/object_gnd/object_gnd.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_hidan_objects/object_hidan_objects.h"
@@ -87,7 +88,7 @@ static ShutterInfo D_80998134[] = {
{ 0x06006910, gDungeonDoorDL, 130, 12, 20, 15 },
{ 0x060000C0, 0x060001F0, 240, 14, 70, 15 },
{ 0x06000590, 0x06006460, 0, 110, 50, 15 },
- { 0x06012AB0, NULL, 130, 12, 50, 15 },
+ { gPhantomGanonBarsDL, NULL, 130, 12, 50, 15 },
{ 0x0601EC20, NULL, 130, 12, 50, 15 },
{ 0x06000100, 0x060001F0, 240, 14, 50, 15 },
{ 0x060010C0, NULL, 130, 12, 50, 15 },
@@ -156,7 +157,6 @@ static UNK_PTR D_809982D4[] = {
};
extern CollisionHeader D_0601EDD0; // gohma block collision header
-extern CollisionHeader D_06012FD0; // phantom ganon bars collision header
void DoorShutter_SetupAction(DoorShutter* this, DoorShutterActionFunc actionFunc) {
this->actionFunc = actionFunc;
@@ -283,7 +283,8 @@ void DoorShutter_SetupType(DoorShutter* this, GlobalContext* globalCtx) {
Actor_SetObjectDependency(globalCtx, &this->dyna.actor);
this->unk_16C = D_809980F0[this->unk_16B].index1;
- CollisionHeader_GetVirtual((this->doorType == SHUTTER_GOHMA_BLOCK) ? &D_0601EDD0 : &D_06012FD0, &colHeader);
+ CollisionHeader_GetVirtual((this->doorType == SHUTTER_GOHMA_BLOCK) ? &D_0601EDD0 : &gPhantomGanonBarsCol,
+ &colHeader);
this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, &this->dyna.actor, colHeader);
if (this->doorType == SHUTTER_GOHMA_BLOCK) {
this->dyna.actor.velocity.y = 0.0f;
diff --git a/src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.c b/src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.c
index 0eb4519f7..04b411c06 100644
--- a/src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.c
+++ b/src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.c
@@ -5,6 +5,9 @@
*/
#include "z_en_fhg_fire.h"
+#include "objects/object_fhg/object_fhg.h"
+#include "objects/gameplay_keep/gameplay_keep.h"
+#include "overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h"
#include "overlays/actors/ovl_En_fHG/z_en_fhg.h"
#include "overlays/effects/ovl_Effect_Ss_Fhg_Flash/z_eff_ss_fhg_flash.h"
@@ -12,28 +15,36 @@
#define THIS ((EnFhgFire*)thisx)
+typedef enum {
+ /* 0 */ STRIKE_INIT,
+ /* 10 */ STRIKE_BURST = 10,
+ /* 11 */ STRIKE_TRAILS
+} StrikeMode;
+
+typedef enum {
+ /* 0 */ TRAIL_INIT,
+ /* 1 */ TRAIL_APPEAR,
+ /* 2 */ TRAIL_DISSIPATE
+} TrailMode;
+
+typedef enum {
+ /* 0 */ BALL_FIZZLE,
+ /* 1 */ BALL_BURST,
+ /* 2 */ BALL_IMPACT
+} BallKillMode;
+
void EnFhgFire_Init(Actor* thisx, GlobalContext* globalCtx);
void EnFhgFire_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnFhgFire_Update(Actor* thisx, GlobalContext* globalCtx);
void EnFhgFire_Draw(Actor* thisx, GlobalContext* globalCtx);
-void func_80A0F6F8(EnFhgFire* this, GlobalContext* globalCtx);
-void func_80A0FA90(EnFhgFire* this, GlobalContext* globalCtx);
-void func_80A0FC48(EnFhgFire* this, GlobalContext* globalCtx);
-void func_80A0FD8C(EnFhgFire* this, GlobalContext* globalCtx);
-void func_80A10008(EnFhgFire* this, GlobalContext* globalCtx);
-void func_80A10220(EnFhgFire* this, GlobalContext* globalCtx);
-void func_80A10F18(EnFhgFire* this, GlobalContext* globalCtx);
-
-extern ColliderCylinderInit D_80A11790;
-extern Vec3f D_80A117BC;
-extern Vec3f D_80A117C8;
-extern Vec3f D_80A117D4;
-
-extern Gfx D_0600FAA0[];
-extern Gfx D_0600FCF8[];
-extern Gfx D_060105E0[];
-extern Gfx D_06012160[];
+void EnFhgFire_LightningStrike(EnFhgFire* this, GlobalContext* globalCtx);
+void EnFhgFire_LightningTrail(EnFhgFire* this, GlobalContext* globalCtx);
+void EnFhgFire_LightningShock(EnFhgFire* this, GlobalContext* globalCtx);
+void EnFhgFire_LightningBurst(EnFhgFire* this, GlobalContext* globalCtx);
+void EnFhgFire_SpearLight(EnFhgFire* this, GlobalContext* globalCtx);
+void EnFhgFire_EnergyBall(EnFhgFire* this, GlobalContext* globalCtx);
+void EnFhgFire_PhantomWarp(EnFhgFire* this, GlobalContext* globalCtx);
const ActorInit En_Fhg_Fire_InitVars = {
0,
@@ -47,224 +58,224 @@ const ActorInit En_Fhg_Fire_InitVars = {
(ActorFunc)EnFhgFire_Draw,
};
-void EnFhgFire_SetupAction(EnFhgFire* this, EnFhgFireActionFunc actionFunc) {
- this->actionFunc = actionFunc;
+static ColliderCylinderInit sCylinderInit = {
+ {
+ COLTYPE_NONE,
+ AT_ON | AT_TYPE_ENEMY,
+ AC_ON | AC_TYPE_PLAYER,
+ OC1_ON | OC1_TYPE_ALL,
+ OC2_TYPE_1,
+ COLSHAPE_CYLINDER,
+ },
+ {
+ ELEMTYPE_UNK6,
+ { 0x00100700, 0x03, 0x20 },
+ { 0x0D900700, 0x00, 0x00 },
+ TOUCH_ON,
+ BUMP_ON,
+ OCELEM_ON,
+ },
+ { 20, 30, 10, { 0, 0, 0 } },
+};
+
+void EnFhgFire_SetUpdate(EnFhgFire* this, EnFhgFireUpdateFunc updateFunc) {
+ this->updateFunc = updateFunc;
}
void EnFhgFire_Init(Actor* thisx, GlobalContext* globalCtx) {
- f32 tempf0;
+ s32 pad;
EnFhgFire* this = THIS;
Player* player = PLAYER;
- f32 tempf1;
- f32 tempf2;
- f32 tempf3;
- ActorShape_Init(&thisx->shape, 0.0f, NULL, 0.0f);
- if ((thisx->params == 0x23) || (thisx->params == 0x24) || (thisx->params == 0x32)) {
+ ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f);
+ if ((this->actor.params == FHGFIRE_LIGHTNING_SHOCK) || (this->actor.params == FHGFIRE_LIGHTNING_BURST) ||
+ (this->actor.params == FHGFIRE_ENERGY_BALL)) {
Collider_InitCylinder(globalCtx, &this->collider);
- Collider_SetCylinder(globalCtx, &this->collider, thisx, &D_80A11790);
- }
- this->unk_160 = 200.0f;
- Actor_SetScale(thisx, 0.0f);
-
- if (thisx->params == 0x01) {
- EnFhgFire_SetupAction(this, func_80A0F6F8);
- Audio_PlayActorSound2(thisx, NA_SE_EN_FANTOM_THUNDER);
- } else if (thisx->params >= 0x64) {
- EnFhgFire_SetupAction(this, func_80A0FA90);
- thisx->shape.rot = thisx->world.rot;
+ Collider_SetCylinder(globalCtx, &this->collider, &this->actor, &sCylinderInit);
}
-
- if (thisx->params == 0x23) {
- thisx->draw = NULL;
- EnFhgFire_SetupAction(this, func_80A0FC48);
- thisx->speedXZ = 30.0f;
- Audio_PlayActorSound2(thisx, NA_SE_EN_FANTOM_SPARK);
- return;
+ this->fwork[FHGFIRE_ALPHA] = 200.0f;
+ Actor_SetScale(&this->actor, 0.0f);
+
+ if (this->actor.params == FHGFIRE_LIGHTNING_STRIKE) {
+ EnFhgFire_SetUpdate(this, EnFhgFire_LightningStrike);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_THUNDER);
+ } else if (this->actor.params >= FHGFIRE_LIGHTNING_TRAIL) {
+ EnFhgFire_SetUpdate(this, EnFhgFire_LightningTrail);
+ this->actor.shape.rot = this->actor.world.rot;
}
-
- if (thisx->params == 0x24) {
- EnFhgFire_SetupAction(this, func_80A0FD8C);
- this->unk_160 = 255.0f;
- this->unk_150.x = 0x20;
- this->unk_150.y = 0x32;
- this->unk_1FE = 0x0A;
-
- tempf2 = thisx->world.rot.x;
- this->unk_18C = tempf2 / 100.0f;
- tempf1 = tempf2 * 0.13f;
-
- this->collider.dim.radius = tempf1;
- this->collider.dim.height = tempf1;
+ if (this->actor.params == FHGFIRE_LIGHTNING_SHOCK) {
+ this->actor.draw = NULL;
+ EnFhgFire_SetUpdate(this, EnFhgFire_LightningShock);
+ this->actor.speedXZ = 30.0f;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_SPARK);
+ } else if (this->actor.params == FHGFIRE_LIGHTNING_BURST) {
+ EnFhgFire_SetUpdate(this, EnFhgFire_LightningBurst);
+ this->fwork[FHGFIRE_ALPHA] = 255.0f;
+ this->work[FHGFIRE_TIMER] = 32;
+ this->work[FHGFIRE_FX_TIMER] = 50;
+ this->lensFlareTimer = 10;
+
+ this->fwork[FHGFIRE_BURST_SCALE] = this->actor.world.rot.x / 100.0f;
+ this->collider.dim.radius = this->actor.world.rot.x * 0.13f;
+ this->collider.dim.height = this->actor.world.rot.x * 0.13f;
this->collider.dim.yShift = 0;
- return;
- }
-
- if (thisx->params == 0x26) {
+ } else if (this->actor.params == FHGFIRE_SPEAR_LIGHT) {
// "light spear"
osSyncPrintf("yari hikari ct 1\n");
- EnFhgFire_SetupAction(this, func_80A10008);
+ EnFhgFire_SetUpdate(this, EnFhgFire_SpearLight);
osSyncPrintf("yari hikari ct 2\n");
- this->unk_150.x = thisx->world.rot.x;
- this->fireMode = thisx->world.rot.y;
- return;
- }
-
- switch (thisx->params) {
- case 0x27:
- case 0x28:
- case 0x29:
- Actor_SetScale(thisx, 7.0f);
- EnFhgFire_SetupAction(this, func_80A10F18);
- if (thisx->params == 0x29) {
- this->unk_150.x = 0x01B8;
- thisx->scale.z = 1.0f;
- } else {
- this->unk_150.x = 0x4C;
- Audio_PlayActorSound2(thisx, NA_SE_EV_FANTOM_WARP_S);
- Audio_PlayActorSound2(thisx, NA_SE_EV_FANTOM_WARP_S2);
- }
- return;
- }
-
- if (thisx->params == 0x32) {
- thisx->speedXZ = (thisx->world.rot.x == 0) ? 8.0f : 3.0f;
- EnFhgFire_SetupAction(this, func_80A10220);
-
- this->unk_150.x = 0x46;
- this->unk_150.y = 0x02;
-
- tempf1 = player->actor.world.pos.x - thisx->world.pos.x;
- tempf2 = player->actor.world.pos.y + 30.0f - thisx->world.pos.y;
- tempf3 = player->actor.world.pos.z - thisx->world.pos.z;
- thisx->world.rot.y = Math_FAtan2F(tempf1, tempf3) * 10430.378f; // 65536/(2*M_PI)
- tempf0 = sqrtf(SQ(tempf1) + SQ(tempf3));
- thisx->world.rot.x = Math_FAtan2F(tempf2, tempf0) * 10430.378f; // 65536/(2*M_PI)
+ this->work[FHGFIRE_TIMER] = this->actor.world.rot.x;
+ this->work[FHGFIRE_FIRE_MODE] = this->actor.world.rot.y;
+ } else if ((this->actor.params == FHGFIRE_WARP_EMERGE) || (this->actor.params == FHGFIRE_WARP_RETREAT) ||
+ (this->actor.params == FHGFIRE_WARP_DEATH)) {
+ Actor_SetScale(&this->actor, 7.0f);
+ EnFhgFire_SetUpdate(this, EnFhgFire_PhantomWarp);
+ if (this->actor.params == FHGFIRE_WARP_DEATH) {
+ this->work[FHGFIRE_TIMER] = 440;
+ this->actor.scale.z = 1.0f;
+ } else {
+ this->work[FHGFIRE_TIMER] = 76;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_FANTOM_WARP_S);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_FANTOM_WARP_S2);
+ }
+ } else if (this->actor.params == FHGFIRE_ENERGY_BALL) {
+ f32 dxL;
+ f32 dyL;
+ f32 dzL;
+ f32 dxzL;
+
+ this->actor.speedXZ = (this->actor.world.rot.x == 0) ? 8.0f : 3.0f;
+ EnFhgFire_SetUpdate(this, EnFhgFire_EnergyBall);
+
+ this->work[FHGFIRE_TIMER] = 70;
+ this->work[FHGFIRE_FX_TIMER] = 2;
+
+ dxL = player->actor.world.pos.x - this->actor.world.pos.x;
+ dyL = player->actor.world.pos.y + 30.0f - this->actor.world.pos.y;
+ dzL = player->actor.world.pos.z - this->actor.world.pos.z;
+ this->actor.world.rot.y = Math_FAtan2F(dxL, dzL) * (0x8000 / M_PI);
+ dxzL = sqrtf(SQ(dxL) + SQ(dzL));
+ this->actor.world.rot.x = Math_FAtan2F(dyL, dxzL) * (0x8000 / M_PI);
this->collider.dim.radius = 40;
this->collider.dim.height = 50;
this->collider.dim.yShift = -25;
this->lightNode = LightContext_InsertLight(globalCtx, &globalCtx->lightCtx, &this->lightInfo);
- Lights_PointNoGlowSetInfo(&this->lightInfo, thisx->world.pos.x, thisx->world.pos.y, thisx->world.pos.z, 255,
- 255, 255, 0xFF);
+ Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y,
+ this->actor.world.pos.z, 255, 255, 255, 255);
}
}
void EnFhgFire_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
EnFhgFire* this = THIS;
- if ((thisx->params == 0x23) || (thisx->params == 0x24) || (thisx->params == 0x32)) {
+ if ((this->actor.params == FHGFIRE_LIGHTNING_SHOCK) || (this->actor.params == FHGFIRE_LIGHTNING_BURST) ||
+ (this->actor.params == FHGFIRE_ENERGY_BALL)) {
Collider_DestroyCylinder(globalCtx, &this->collider);
}
- if (thisx->params == 0x32) {
+ if (this->actor.params == FHGFIRE_ENERGY_BALL) {
LightContext_RemoveLight(globalCtx, &globalCtx->lightCtx, this->lightNode);
}
}
-void func_80A0F6F8(EnFhgFire* this, GlobalContext* globalCtx) {
- Camera* camera;
- s32 pad;
- Vec3f ballVelocity;
- Vec3f ballAccel;
+void EnFhgFire_LightningStrike(EnFhgFire* this, GlobalContext* globalCtx) {
+ Camera* camera = Gameplay_GetCamera(globalCtx, 0);
s16 i;
- s16 randY;
- s16* tmp;
- tmp = &this->unk_156;
- camera = Gameplay_GetCamera(globalCtx, 0);
-
- switch (this->fireMode) {
- case 0x00:
- this->fireMode = 0x0A;
- this->unk_150.x = 0x07;
+ switch (this->work[FHGFIRE_FIRE_MODE]) {
+ case STRIKE_INIT:
+ this->work[FHGFIRE_FIRE_MODE] = STRIKE_BURST;
+ this->work[FHGFIRE_TIMER] = 7;
break;
+ case STRIKE_BURST:
+ this->actor.shape.rot.y =
+ Camera_GetInputDirYaw(camera) + 0x8000 * (this->work[FHGFIRE_VARIANCE_TIMER] & 0xFF);
+ Math_ApproachF(&this->fwork[FHGFIRE_SCALE], 1.0f, 1.0f, 0.2f);
- case 0x0A:
- this->actor.shape.rot.y = Camera_GetInputDirYaw(camera) + ((*tmp & 0xFF) << 0x0F);
- Math_ApproachF(&this->scale, 1.0f, 1.0f, 0.2f);
-
- if (this->unk_150.x == 0) {
- this->fireMode = 0x0B;
+ if (this->work[FHGFIRE_TIMER] == 0) {
+ this->work[FHGFIRE_FIRE_MODE] = STRIKE_TRAILS;
this->actor.shape.rot.z += 0x8000;
- this->unk_150.x = 0x25;
+ this->work[FHGFIRE_TIMER] = 37;
this->actor.world.pos.y -= 200.0f;
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE,
this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 500, 0, 0,
- 0x24);
-
- ballAccel = D_80A117BC;
-
- for (i = 0; i < 35; i++) {
- ballVelocity.x = Rand_CenteredFloat(30.f);
- ballVelocity.y = Rand_ZeroFloat(5.0f) + 3.0f;
- ballVelocity.z = Rand_CenteredFloat(30.f);
- ballAccel.y = -0.2f;
- EffectSsFhgFlash_SpawnLightBall(globalCtx, &this->actor.world.pos, &ballVelocity, &ballAccel,
- (s16)(Rand_ZeroOne() * 100.0f) + 240, FHGFLASH_LIGHTBALL_GREEN);
+ FHGFIRE_LIGHTNING_BURST);
+ {
+ Vec3f sp7C;
+ Vec3f sp70 = { 0.0f, -1.0f, 0.0f };
+
+ for (i = 0; i < 35; i++) {
+ sp7C.x = Rand_CenteredFloat(30.f);
+ sp7C.y = Rand_ZeroFloat(5.0f) + 3.0f;
+ sp7C.z = Rand_CenteredFloat(30.f);
+ sp70.y = -0.2f;
+ EffectSsFhgFlash_SpawnLightBall(globalCtx, &this->actor.world.pos, &sp7C, &sp70,
+ (s16)(Rand_ZeroOne() * 100.0f) + 240, FHGFLASH_LIGHTBALL_GREEN);
+ }
}
-
func_80033E88(&this->actor, globalCtx, 4, 10);
}
break;
+ case STRIKE_TRAILS:
+ this->actor.shape.rot.y =
+ Camera_GetInputDirYaw(camera) + (this->work[FHGFIRE_VARIANCE_TIMER] & 0xFF) * 0x8000;
- case 0x0B:
- this->actor.shape.rot.y = Camera_GetInputDirYaw(camera) + ((*tmp & 0xFF) << 0x0F);
-
- Math_ApproachF(&this->scale, 0.0f, 1.0f, 0.2f);
- if (this->unk_150.x == 0x1E) {
- randY = (Rand_ZeroOne() < 0.5f) ? 0x1000 : 0;
+ Math_ApproachF(&this->fwork[FHGFIRE_SCALE], 0.0f, 1.0f, 0.2f);
+ if (this->work[FHGFIRE_TIMER] == 30) {
+ s16 randY = (Rand_ZeroOne() < 0.5f) ? 0x1000 : 0;
for (i = 0; i < 8; i++) {
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE,
this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0,
- (i * 8192) + randY, 0x4000, i + 0x64);
+ (i * 0x2000) + randY, 0x4000, FHGFIRE_LIGHTNING_TRAIL + i);
}
for (i = 0; i < 8; i++) {
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE,
this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0,
- (i * 8192) + randY, 0, 0x23);
+ (i * 0x2000) + randY, 0, FHGFIRE_LIGHTNING_SHOCK);
}
}
- if (this->unk_150.x == 0) {
+ if (this->work[FHGFIRE_TIMER] == 0) {
Actor_Kill(&this->actor);
}
}
- Actor_SetScale(&this->actor, this->scale);
+ Actor_SetScale(&this->actor, this->fwork[FHGFIRE_SCALE]);
}
-void func_80A0FA90(EnFhgFire* this, GlobalContext* globalCtx) {
+void EnFhgFire_LightningTrail(EnFhgFire* this, GlobalContext* globalCtx) {
osSyncPrintf("FF MOVE 1\n");
this->actor.shape.rot.x += (s16)(Rand_ZeroOne() * 4000.0f) + 0x4000;
- switch (this->fireMode) {
- case 0:
- this->fireMode = 1;
- this->unk_150.x = (s16)(Rand_ZeroOne() * 7.0f) + 0x07;
- case 1:
- Math_ApproachF(&this->scale, 1.7f, 1.0f, 0.34f);
-
- if (this->unk_150.x == 0) {
- this->fireMode = 0x02;
- this->unk_150.x = 0x0A;
- this->actor.world.pos.z += Math_SinS(this->actor.shape.rot.y) * -200.0f * this->scale;
- this->actor.world.pos.x += Math_CosS(this->actor.shape.rot.y) * 200.0f * this->scale;
+ switch (this->work[FHGFIRE_FIRE_MODE]) {
+ case TRAIL_INIT:
+ this->work[FHGFIRE_FIRE_MODE] = TRAIL_APPEAR;
+ this->work[FHGFIRE_TIMER] = (s16)(Rand_ZeroOne() * 7.0f) + 7;
+ case TRAIL_APPEAR:
+ Math_ApproachF(&this->fwork[FHGFIRE_SCALE], 1.7f, 1.0f, 0.34f);
+
+ if (this->work[FHGFIRE_TIMER] == 0) {
+ this->work[FHGFIRE_FIRE_MODE] = TRAIL_DISSIPATE;
+ this->work[FHGFIRE_TIMER] = 10;
+ this->actor.world.pos.z += Math_SinS(this->actor.shape.rot.y) * -200.0f * this->fwork[FHGFIRE_SCALE];
+ this->actor.world.pos.x += Math_CosS(this->actor.shape.rot.y) * 200.0f * this->fwork[FHGFIRE_SCALE];
this->actor.shape.rot.y += 0x8000;
}
break;
- case 2:
- Math_ApproachZeroF(&this->scale, 1.0f, 0.34f);
- if (this->unk_150.x == 0) {
+ case TRAIL_DISSIPATE:
+ Math_ApproachZeroF(&this->fwork[FHGFIRE_SCALE], 1.0f, 0.34f);
+ if (this->work[FHGFIRE_TIMER] == 0) {
Actor_Kill(&this->actor);
}
break;
}
- Actor_SetScale(&this->actor, this->scale);
+ Actor_SetScale(&this->actor, this->fwork[FHGFIRE_SCALE]);
if (this->actor.scale.x > 1.0f) {
this->actor.scale.x = 1.0f;
}
@@ -272,7 +283,7 @@ void func_80A0FA90(EnFhgFire* this, GlobalContext* globalCtx) {
osSyncPrintf("FF MOVE 2\n");
}
-void func_80A0FC48(EnFhgFire* this, GlobalContext* globalCtx) {
+void EnFhgFire_LightningShock(EnFhgFire* this, GlobalContext* globalCtx) {
Player* player = PLAYER;
Vec3f pos;
@@ -299,27 +310,27 @@ void func_80A0FC48(EnFhgFire* this, GlobalContext* globalCtx) {
}
}
-void func_80A0FD8C(EnFhgFire* this, GlobalContext* globalCtx) {
+void EnFhgFire_LightningBurst(EnFhgFire* this, GlobalContext* globalCtx) {
Player* player = PLAYER;
s32 pad;
globalCtx->envCtx.unk_E1 = 0x01;
this->actor.shape.rot.y += 0x1000;
- if (this->unk_150.y == 0x31) {
+ if (this->work[FHGFIRE_FX_TIMER] == 49) {
globalCtx->envCtx.unk_BF = 1;
globalCtx->envCtx.unk_D6 = 0xFF;
}
- if (this->unk_150.y == 0x1F) {
+ if (this->work[FHGFIRE_FX_TIMER] == 31) {
globalCtx->envCtx.unk_BF = 0x00;
globalCtx->envCtx.unk_D6 = 0x14;
}
- if (this->unk_150.y >= 0x30) {
+ if (this->work[FHGFIRE_FX_TIMER] >= 48) {
globalCtx->envCtx.unk_E2[2] = 0xFF;
globalCtx->envCtx.unk_E2[1] = 0xFF;
globalCtx->envCtx.unk_E2[0] = 0xFF;
- if (((this->unk_150.x & 0xFF) % 2) != 0) {
+ if (((this->work[FHGFIRE_TIMER] & 0xFF) % 2) != 0) {
globalCtx->envCtx.unk_E2[3] = 0x46;
} else {
globalCtx->envCtx.unk_E2[3] = 0x00;
@@ -328,65 +339,64 @@ void func_80A0FD8C(EnFhgFire* this, GlobalContext* globalCtx) {
globalCtx->envCtx.unk_E2[3] = 0x00;
}
- if (this->unk_150.x < 0x15) {
- Math_ApproachZeroF(&this->unk_160, 1.0f, 45.0f);
- Math_ApproachZeroF(&this->scale, 1.0f, 0.5f);
+ if (this->work[FHGFIRE_TIMER] <= 20) {
+ Math_ApproachZeroF(&this->fwork[FHGFIRE_ALPHA], 1.0f, 45.0f);
+ Math_ApproachZeroF(&this->fwork[FHGFIRE_SCALE], 1.0f, 0.5f);
} else {
- Math_ApproachF(&this->scale, this->unk_18C, 0.5f, 3.0f);
+ Math_ApproachF(&this->fwork[FHGFIRE_SCALE], this->fwork[FHGFIRE_BURST_SCALE], 0.5f, 3.0f);
}
- Actor_SetScale(&this->actor, this->scale);
- if (3.0f < this->unk_18C) {
+ Actor_SetScale(&this->actor, this->fwork[FHGFIRE_SCALE]);
+ if (this->fwork[FHGFIRE_BURST_SCALE] > 3.0f) {
Collider_UpdateCylinder(&this->actor, &this->collider);
if (player->invincibilityTimer == 0) {
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
}
- if (this->unk_150.x == 0) {
+ if (this->work[FHGFIRE_TIMER] == 0) {
Actor_Kill(&this->actor);
globalCtx->envCtx.unk_E1 = 0;
}
- if (this->unk_1FE != 0) {
- this->unk_1FE--;
- this->unk_1FC = 1;
- Math_ApproachF(&this->unk_200, 40.0f, 0.3f, 10.0f);
+
+ if (this->lensFlareTimer != 0) {
+ this->lensFlareTimer--;
+ this->lensFlareOn = true;
+ Math_ApproachF(&this->lensFlareScale, 40.0f, 0.3f, 10.0f);
} else {
- Math_ApproachZeroF(&this->unk_200, 1.0f, 5.0f);
- if (this->unk_200 == 0.0f) {
- this->unk_1FC = 0;
+ Math_ApproachZeroF(&this->lensFlareScale, 1.0f, 5.0f);
+ if (this->lensFlareScale == 0.0f) {
+ this->lensFlareOn = false;
}
}
- // Related to scene draw config 30, only used in BossGanon_Update and
- // loaded in z_kankyo
- D_8015FCF0 = this->unk_1FC;
+ D_8015FCF0 = this->lensFlareOn;
D_8015FCF8 = this->actor.world.pos;
- D_8015FD06 = this->unk_200;
+ D_8015FD06 = this->lensFlareScale;
D_8015FD08 = 10.0f;
D_8015FD0C = 0;
}
-void func_80A10008(EnFhgFire* this, GlobalContext* globalCtx) {
- EnfHG* horse;
+void EnFhgFire_SpearLight(EnFhgFire* this, GlobalContext* globalCtx) {
+ BossGanondrof* bossGnd;
s16 i;
osSyncPrintf("yari hikari 1\n");
- horse = (EnfHG*)this->actor.parent;
- if ((this->unk_156 % 2) != 0) {
+ bossGnd = (BossGanondrof*)this->actor.parent;
+ if ((this->work[FHGFIRE_VARIANCE_TIMER] % 2) != 0) {
Actor_SetScale(&this->actor, 6.0f);
} else {
Actor_SetScale(&this->actor, 5.25f);
}
- this->actor.world.pos = horse->unk_200;
- this->actor.shape.rot.z += (s16)(Rand_ZeroOne() * 20000.0f) + 0x4000;
+ this->actor.world.pos = bossGnd->spearTip;
+ this->actor.shape.rot.z += (s16)(Rand_ZeroOne() * 0x4E20) + 0x4000;
osSyncPrintf("yari hikari 2\n");
- if (this->fireMode == 0) {
+ if (this->work[FHGFIRE_FIRE_MODE] == FHGFIRE_LIGHT_GREEN) {
Vec3f ballPos;
- Vec3f ballVelocity = D_80A117C8;
- Vec3f ballAccel = D_80A117D4;
+ Vec3f ballVel = { 0.0f, 0.0f, 0.0f };
+ Vec3f ballAccel = { 0.0f, 0.0f, 0.0f };
osSyncPrintf("FLASH !!\n");
@@ -396,124 +406,354 @@ void func_80A10008(EnFhgFire* this, GlobalContext* globalCtx) {
ballPos.z = Rand_CenteredFloat(20.0f) + this->actor.world.pos.z;
ballAccel.y = -0.08f;
- EffectSsFhgFlash_SpawnLightBall(globalCtx, &ballPos, &ballVelocity, &ballAccel,
+ EffectSsFhgFlash_SpawnLightBall(globalCtx, &ballPos, &ballVel, &ballAccel,
(s16)(Rand_ZeroOne() * 80.0f) + 150, FHGFLASH_LIGHTBALL_GREEN);
}
}
- if (this->unk_150.x == 0) {
+ if (this->work[FHGFIRE_TIMER] == 0) {
Actor_Kill(&this->actor);
}
}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fhg_Fire/func_80A10220.s")
+void EnFhgFire_EnergyBall(EnFhgFire* this, GlobalContext* globalCtx) {
+ f32 dxL;
+ f32 dyL;
+ f32 dzL;
+ f32 dxzL;
+ f32 dxPG;
+ f32 dyPG;
+ f32 dzPG;
+ u8 killMode = BALL_FIZZLE;
+ u8 canBottleReflect1;
+ Player* player = PLAYER;
+
+ if (this->work[FHGFIRE_KILL_TIMER] != 0) {
+ this->work[FHGFIRE_KILL_TIMER]--;
+ if (this->work[FHGFIRE_KILL_TIMER] == 0) {
+ Actor_Kill(&this->actor);
+ return;
+ }
+ } else {
+ s32 canBottleReflect2;
+ BossGanondrof* bossGnd = (BossGanondrof*)this->actor.parent;
+
+ dxPG = bossGnd->targetPos.x - this->actor.world.pos.x;
+ dyPG = bossGnd->targetPos.y - this->actor.world.pos.y;
+ dzPG = bossGnd->targetPos.z - this->actor.world.pos.z;
+ dxL = player->actor.world.pos.x - this->actor.world.pos.x;
+ dyL = player->actor.world.pos.y + 40.0f - this->actor.world.pos.y;
+ dzL = player->actor.world.pos.z - this->actor.world.pos.z;
+ func_8002D908(&this->actor);
+ func_8002D7EC(&this->actor);
+ if (this->work[FHGFIRE_VARIANCE_TIMER] & 1) {
+ Actor_SetScale(&this->actor, 6.0f);
+ } else {
+ Actor_SetScale(&this->actor, 5.25f);
+ }
+ this->actor.shape.rot.z += (s16)(Rand_ZeroOne() * 0x4E20) + 0x4000;
+ {
+ u8 lightBallColor1 = FHGFLASH_LIGHTBALL_GREEN;
+ s16 i1;
+ Vec3f spD4;
+ Vec3f spC8 = { 0.0f, 0.0f, 0.0f };
+ Vec3f spBC = { 0.0f, 0.0f, 0.0f };
+
+ if (this->work[FHGFIRE_FIRE_MODE] >= FHGFIRE_LIGHT_BLUE) {
+ lightBallColor1 = FHGFLASH_LIGHTBALL_LIGHTBLUE;
+ }
+ for (i1 = 0; i1 < 3; i1++) {
+ spD4.x = Rand_CenteredFloat(20.0f) + this->actor.world.pos.x;
+ spD4.y = Rand_CenteredFloat(20.0f) + this->actor.world.pos.y;
+ spD4.z = Rand_CenteredFloat(20.0f) + this->actor.world.pos.z;
+ spBC.y = -0.08f;
+ EffectSsFhgFlash_SpawnLightBall(globalCtx, &spD4, &spC8, &spBC, (s16)(Rand_ZeroOne() * 80.0f) + 150,
+ lightBallColor1);
+ }
+ }
+ switch (this->work[FHGFIRE_FIRE_MODE]) {
+ case FHGFIRE_LIGHT_GREEN:
+ canBottleReflect1 =
+ ((player->stateFlags1 & 2) &&
+ (ABS((s16)(player->actor.shape.rot.y - (s16)(bossGnd->actor.yawTowardsPlayer + 0x8000))) <
+ 0x2000) &&
+ (sqrtf(SQ(dxL) + SQ(dyL) + SQ(dzL)) <= 25.0f))
+ ? true
+ : false;
+ if ((this->collider.base.acFlags & AC_HIT) || canBottleReflect1) {
+ ColliderInfo* hurtbox = this->collider.info.acHitInfo;
+ s16 i2;
+ Vec3f spA8;
+ Vec3f sp9C = { 0.0f, -0.5f, 0.0f };
+ s16 angleModX;
+ s16 angleModY;
+
+ for (i2 = 0; i2 < 30; i2++) {
+ spA8.x = Rand_CenteredFloat(20.0f);
+ spA8.y = Rand_CenteredFloat(20.0f);
+ spA8.z = Rand_CenteredFloat(20.0f);
+ EffectSsFhgFlash_SpawnLightBall(globalCtx, &this->actor.world.pos, &spA8, &sp9C,
+ (s16)(Rand_ZeroOne() * 25.0f) + 50, FHGFLASH_LIGHTBALL_GREEN);
+ }
+ canBottleReflect2 = canBottleReflect1;
+ if (!canBottleReflect2 && (hurtbox->toucher.dmgFlags & 0x00100000)) {
+ killMode = BALL_IMPACT;
+ Audio_PlaySoundGeneral(NA_SE_IT_SHIELD_REFLECT_MG, &player->actor.projectedPos, 4, &D_801333E0,
+ &D_801333E0, &D_801333E8);
+ func_800AA000(this->actor.xyzDistToPlayerSq, 0xFF, 0x14, 0x96);
+ } else {
+ if (bossGnd->flyMode == GND_FLY_NEUTRAL) {
+ angleModX = Rand_CenteredFloat(0x2000);
+ angleModY = Rand_CenteredFloat(0x2000);
+ this->actor.speedXZ = 15.0f;
+ } else {
+ angleModX = 0;
+ angleModY = 0;
+ this->work[FHGFIRE_RETURN_COUNT]++;
+ if ((this->work[FHGFIRE_RETURN_COUNT] > 3) && (Rand_ZeroOne() < 0.5f)) {
+ this->work[FHGFIRE_RETURN_COUNT] = 100;
+ }
+
+ if (!canBottleReflect2 && (player->swordAnimation >= 24)) {
+ this->actor.speedXZ = 20.0f;
+ this->work[FHGFIRE_RETURN_COUNT] = 4;
+ } else {
+ this->actor.speedXZ += 1.0f;
+ }
+ }
+ this->actor.world.rot.y = (s16)(Math_FAtan2F(dxPG, dzPG) * (0x8000 / M_PI)) + angleModY;
+ this->actor.world.rot.x =
+ (s16)(Math_FAtan2F(dyPG, sqrtf((dxPG * dxPG) + (dzPG * dzPG))) * (0x8000 / M_PI)) +
+ angleModX;
+ this->work[FHGFIRE_FIRE_MODE] = FHGFIRE_LIGHT_BLUE;
+ this->work[FHGFIRE_FX_TIMER] = 2;
+ Audio_PlaySoundGeneral(NA_SE_IT_SWORD_REFLECT_MG, &player->actor.projectedPos, 4, &D_801333E0,
+ &D_801333E0, &D_801333E8);
+ func_800AA000(this->actor.xyzDistToPlayerSq, 0xB4, 0x14, 0x64);
+ }
+ } else if (sqrtf(SQ(dxL) + SQ(dyL) + SQ(dzL)) <= 25.0f) {
+ killMode = BALL_BURST;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_HIT_THUNDER);
+ if ((bossGnd->flyMode >= GND_FLY_VOLLEY) && (this->work[FHGFIRE_RETURN_COUNT] >= 2)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_LAUGH);
+ }
+ func_8002F698(globalCtx, &this->actor, 3.0f, this->actor.world.rot.y, 0.0f, 3, 0x10);
+ }
+ break;
+ case FHGFIRE_LIGHT_BLUE:
+ if ((bossGnd->flyMode == GND_FLY_RETURN) && (this->work[FHGFIRE_RETURN_COUNT] < 100)) {
+ this->actor.world.rot.y = Math_FAtan2F(dxPG, dzPG) * (0x8000 / M_PI);
+ if ((sqrtf(SQ(dxPG) + SQ(dzPG)) < (150.0f + (this->actor.speedXZ * 8.0f)))) {
+ this->work[FHGFIRE_FIRE_MODE] = FHGFIRE_LIGHT_REFLECT;
+ bossGnd->returnSuccess = true;
+ this->work[FHGFIRE_TIMER] = 8;
+ }
+ } else {
+ if (this->work[FHGFIRE_RETURN_COUNT] >= 100) {
+ if ((sqrtf(SQ(dxPG) + SQ(dyPG) + SQ(dzPG)) < 100.0f)) {
+ bossGnd->returnSuccess = true;
+ }
+ this->actor.world.rot.y = Math_FAtan2F(dxPG, dzPG) * (0x8000 / M_PI);
+ this->actor.world.rot.x = Math_FAtan2F(dyPG, sqrtf(SQ(dxPG) + SQ(dzPG))) * (0x8000 / M_PI);
+ }
+ if ((fabsf(dxPG) < 30.0f) && (fabsf(dzPG) < 30.0f) && (fabsf(dyPG) < 45.0f)) {
+ killMode = BALL_IMPACT;
+ bossGnd->returnCount = this->work[FHGFIRE_RETURN_COUNT] + 1;
+ Audio_PlaySoundGeneral(NA_SE_EN_FANTOM_HIT_THUNDER, &bossGnd->actor.projectedPos, 4,
+ &D_801333E0, &D_801333E0, &D_801333E8);
+ Audio_PlaySoundGeneral(NA_SE_EN_FANTOM_DAMAGE, &bossGnd->actor.projectedPos, 4, &D_801333E0,
+ &D_801333E0, &D_801333E8);
+ }
+ }
+ break;
+ case FHGFIRE_LIGHT_REFLECT:
+ if (this->work[FHGFIRE_TIMER] == 0) {
+ s16 i3;
+ Vec3f sp88;
+ Vec3f sp7C = { 0.0f, -0.5f, 0.0f };
+
+ for (i3 = 0; i3 < 30; i3++) {
+ sp88.x = Rand_CenteredFloat(20.0f);
+ sp88.y = Rand_CenteredFloat(20.0f);
+ sp88.z = Rand_CenteredFloat(20.0f);
+ EffectSsFhgFlash_SpawnLightBall(globalCtx, &this->actor.world.pos, &sp88, &sp7C,
+ (s16)(Rand_ZeroOne() * 40.0f) + 80, FHGFLASH_LIGHTBALL_GREEN);
+ }
+ this->actor.world.rot.y = Math_FAtan2F(dxL, dzL) * (0x8000 / M_PI);
+ dxzL = sqrtf(SQ(dxL) + SQ(dzL));
+ this->actor.world.rot.x = Math_FAtan2F(dyL, dxzL) * (0x8000 / M_PI);
+ this->work[FHGFIRE_FIRE_MODE] = FHGFIRE_LIGHT_GREEN;
+ Audio_PlayActorSound2(&this->actor, NA_SE_IT_SWORD_REFLECT_MG);
+ this->actor.speedXZ += 2.0f;
+ }
+ break;
+ }
+
+ osSyncPrintf("F_FIRE_MODE %d\n", this->work[FHGFIRE_FIRE_MODE]);
+ osSyncPrintf("fly_mode %d\n", bossGnd->flyMode);
+ if (this->work[FHGFIRE_FX_TIMER] == 0) {
+ Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 50.0f, 50.0f, 100.0f, 7);
+ if ((this->actor.bgCheckFlags & 0x19) || killMode) {
+ u8 lightBallColor2 = FHGFLASH_LIGHTBALL_GREEN;
+ s16 i4;
+ Vec3f sp6C;
+ Vec3f sp60 = { 0.0f, -1.0f, 0.0f };
+
+ if (this->work[FHGFIRE_FIRE_MODE] > FHGFIRE_LIGHT_GREEN) {
+ lightBallColor2 = FHGFLASH_LIGHTBALL_LIGHTBLUE;
+ }
+ for (i4 = 0; i4 < 30; i4++) {
+ sp6C.x = Rand_CenteredFloat(20.0f);
+ sp6C.y = Rand_CenteredFloat(20.0f);
+ sp6C.z = Rand_CenteredFloat(20.0f);
+ sp60.y = -0.1f;
+ EffectSsFhgFlash_SpawnLightBall(globalCtx, &this->actor.world.pos, &sp6C, &sp60,
+ (s16)(Rand_ZeroOne() * 50.0f) + 100, lightBallColor2);
+ }
+ if (killMode == BALL_BURST) {
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE,
+ this->actor.world.pos.x, player->actor.world.pos.y + 20.0f,
+ this->actor.world.pos.z, 0xC8, 0, 0, FHGFIRE_LIGHTNING_BURST);
+ }
+ bossGnd->flyMode = GND_FLY_NEUTRAL;
+ this->work[FHGFIRE_KILL_TIMER] = 30;
+ this->actor.draw = NULL;
+ if (killMode == BALL_FIZZLE) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_THUNDER_GND);
+ }
+ return;
+ } else {
+ Collider_UpdateCylinder(&this->actor, &this->collider);
+ osSyncPrintf("BEFORE setAC %d\n", this->collider.base.shape);
+ CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
+ osSyncPrintf("AFTER setAC\n");
+ }
+ }
+ Lights_PointNoGlowSetInfo(&this->lightInfo, (s16)this->actor.world.pos.x, (s16)this->actor.world.pos.y,
+ (s16)this->actor.world.pos.z, 255, 255, 255, 200);
+ if (this->actor.speedXZ > 20.0f) {
+ this->actor.speedXZ = 20.0f;
+ }
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_FIRE - SFX_FLAG);
+ // Why ah ah ah ah
+ osSyncPrintf("なぜだああああああああ %d\n", this->work[FHGFIRE_VARIANCE_TIMER]);
+ }
+}
-void func_80A10F18(EnFhgFire* this, GlobalContext* globalCtx) {
+void EnFhgFire_PhantomWarp(EnFhgFire* this, GlobalContext* globalCtx) {
EnfHG* horse = (EnfHG*)this->actor.parent;
- f32 phi_f0;
- s32 tmp;
+ f32 scrollDirection;
- this->unk_174 = (this->unk_174 + (25.0f * this->unk_184));
- this->unk_178 = (this->unk_178 - (40.0f * this->unk_184));
- this->unk_17C = (this->unk_17C + (5.0f * this->unk_184));
- this->unk_180 = (this->unk_180 - (30.0f * this->unk_184));
+ this->fwork[FHGFIRE_WARP_TEX_1_X] += 25.0f * this->fwork[FHGFIRE_WARP_TEX_SPEED];
+ this->fwork[FHGFIRE_WARP_TEX_1_Y] -= 40.0f * this->fwork[FHGFIRE_WARP_TEX_SPEED];
+ this->fwork[FHGFIRE_WARP_TEX_2_X] += 5.0f * this->fwork[FHGFIRE_WARP_TEX_SPEED];
+ this->fwork[FHGFIRE_WARP_TEX_2_Y] -= 30.0f * this->fwork[FHGFIRE_WARP_TEX_SPEED];
- if (this->actor.params == 0x29) {
- if (this->unk_150.x >= 0x47) {
+ if (this->actor.params == FHGFIRE_WARP_DEATH) {
+ if (this->work[FHGFIRE_TIMER] > 70) {
Audio_PlayActorSound2(&this->actor, NA_SE_EV_FANTOM_WARP_L - SFX_FLAG);
Audio_PlayActorSound2(&this->actor, NA_SE_EV_FANTOM_WARP_L2 - SFX_FLAG);
}
- if (this->unk_150.x == 0x46) {
+ if (this->work[FHGFIRE_TIMER] == 70) {
Audio_PlayActorSound2(&this->actor, NA_SE_EV_FANTOM_WARP_S);
Audio_PlayActorSound2(&this->actor, NA_SE_EV_FANTOM_WARP_S2);
}
}
- if (this->unk_150.x >= 0x33) {
- phi_f0 = 1.0f;
- if (this->actor.params >= 0x28) {
- phi_f0 = -1.0f;
- }
-
- Math_ApproachF(&this->unk_184, phi_f0, 1.0f, 0.04f);
- Math_ApproachF(&this->unk_188, 255.0f, 1.0f, 10.2f);
- } else {
- if (this->unk_150.x < 0x1A) {
- Math_ApproachZeroF(&this->unk_184, 1.0f, 0.04f);
- Math_ApproachZeroF(&this->unk_188, 1.0f, 10.2f);
+ if (this->work[FHGFIRE_TIMER] > 50) {
+ scrollDirection = 1.0f;
+ if (this->actor.params > FHGFIRE_WARP_EMERGE) {
+ scrollDirection = -1.0f;
}
+ Math_ApproachF(&this->fwork[FHGFIRE_WARP_TEX_SPEED], scrollDirection, 1.0f, 0.04f);
+ Math_ApproachF(&this->fwork[FHGFIRE_WARP_ALPHA], 255.0f, 1.0f, 10.2f);
+ } else if (this->work[FHGFIRE_TIMER] <= 25) {
+ Math_ApproachZeroF(&this->fwork[FHGFIRE_WARP_TEX_SPEED], 1.0f, 0.04f);
+ Math_ApproachZeroF(&this->fwork[FHGFIRE_WARP_ALPHA], 1.0f, 10.2f);
}
osSyncPrintf("EFC 1\n");
- if ((this->unk_150.x == 0) || ((this->actor.params == 0x27) && (horse->unk_14F != 0))) {
+ if ((this->work[FHGFIRE_TIMER] == 0) || ((this->actor.params == FHGFIRE_WARP_EMERGE) && horse->fhgFireKillWarp)) {
Actor_Kill(&this->actor);
}
osSyncPrintf("EFC 2\n");
}
void EnFhgFire_Update(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
EnFhgFire* this = THIS;
- this->unk_156++;
+ this->work[FHGFIRE_VARIANCE_TIMER]++;
- DECR(this->unk_150.x);
- DECR(this->unk_150.y);
+ if (this->work[FHGFIRE_TIMER] != 0) {
+ this->work[FHGFIRE_TIMER]--;
+ }
+ if (this->work[FHGFIRE_FX_TIMER] != 0) {
+ this->work[FHGFIRE_FX_TIMER]--;
+ }
- this->actionFunc(this, globalCtx);
+ this->updateFunc(this, globalCtx);
}
+static u64* sDustTextures[] = {
+ gDust1Tex, gDust2Tex, gDust3Tex, gDust4Tex, gDust5Tex, gDust6Tex, gDust7Tex, gDust8Tex,
+};
+
void EnFhgFire_Draw(Actor* thisx, GlobalContext* globalCtx) {
- EnFhgFire* this = THIS;
s32 pad;
+ EnFhgFire* this = THIS;
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_fhg_fire.c", 1723);
- if (thisx->params == 0x24) {
+ if (this->actor.params == FHGFIRE_LIGHTNING_BURST) {
func_80093D84(globalCtx->state.gfxCtx);
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->unk_160);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->fwork[FHGFIRE_ALPHA]);
gDPSetEnvColor(POLY_XLU_DISP++, 165, 255, 75, 0);
gDPPipeSync(POLY_XLU_DISP++);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_fhg_fire.c", 1745),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(D_0600FCF8));
- } else if ((thisx->params == 0x26) || (thisx->params == 0x32)) {
+ gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(gPhantomLightningBlastDL));
+ } else if ((this->actor.params == FHGFIRE_SPEAR_LIGHT) || (this->actor.params == FHGFIRE_ENERGY_BALL)) {
osSyncPrintf("yari hikari draw 1\n");
func_800D1FD4(&globalCtx->mf_11DA0);
func_80093D84(globalCtx->state.gfxCtx);
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->unk_160);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->fwork[FHGFIRE_ALPHA]);
- if (this->fireMode > 0) {
+ if (this->work[FHGFIRE_FIRE_MODE] > FHGFIRE_LIGHT_GREEN) {
gDPSetEnvColor(POLY_XLU_DISP++, 0, 255, 255, 0);
} else {
gDPSetEnvColor(POLY_XLU_DISP++, 165, 255, 75, 0);
}
gDPPipeSync(POLY_XLU_DISP++);
- Matrix_RotateZ((thisx->shape.rot.z / 32768.0f) * 3.1416f, 1);
+ Matrix_RotateZ((this->actor.shape.rot.z / (f32)0x8000) * 3.1416f, 1);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_fhg_fire.c", 1801),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, D_06012160);
- } else if ((thisx->params == 0x27) || (thisx->params == 0x28) || (thisx->params == 0x29)) {
+ gSPDisplayList(POLY_XLU_DISP++, gPhantomEnergyBallDL);
+ } else if ((this->actor.params == FHGFIRE_WARP_EMERGE) || (this->actor.params == FHGFIRE_WARP_RETREAT) ||
+ (this->actor.params == FHGFIRE_WARP_DEATH)) {
func_80093D84(globalCtx->state.gfxCtx);
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 0, 0, (u8)this->unk_188);
- gDPSetEnvColor(POLY_XLU_DISP++, 90, 50, 95, (s8)(this->unk_188 * 0.5f));
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 0, 0, 0, (u8)this->fwork[FHGFIRE_WARP_ALPHA]);
+ gDPSetEnvColor(POLY_XLU_DISP++, 90, 50, 95, (s8)(this->fwork[FHGFIRE_WARP_ALPHA] * 0.5f));
gDPPipeSync(POLY_XLU_DISP++);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_fhg_fire.c", 1833),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_XLU_DISP++, 0x08,
- Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (s16)this->unk_174, (s16)this->unk_178, 0x40, 0x40, 1,
- (s16)this->unk_17C, (s16)this->unk_180, 0x40, 0x40));
- gSPDisplayList(POLY_XLU_DISP++, D_0600FAA0);
+ Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, (s16)this->fwork[FHGFIRE_WARP_TEX_1_X],
+ (s16)this->fwork[FHGFIRE_WARP_TEX_1_Y], 0x40, 0x40, 1,
+ (s16)this->fwork[FHGFIRE_WARP_TEX_2_X], (s16)this->fwork[FHGFIRE_WARP_TEX_2_Y],
+ 0x40, 0x40));
+ gSPDisplayList(POLY_XLU_DISP++, gPhantomWarpDL);
} else {
osSyncPrintf("FF DRAW 1\n");
Matrix_Translate(0.0f, -100.0f, 0.0f, 1);
func_80093D84(globalCtx->state.gfxCtx);
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->unk_160);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->fwork[FHGFIRE_ALPHA]);
gDPSetEnvColor(POLY_XLU_DISP++, 0, 255, 30, 0);
gDPPipeSync(POLY_XLU_DISP++);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_fhg_fire.c", 1892),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, D_060105E0);
+ gSPDisplayList(POLY_XLU_DISP++, gPhantomLightningDL);
osSyncPrintf("FF DRAW 2\n");
}
diff --git a/src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.h b/src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.h
index 883af9c30..b07363810 100644
--- a/src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.h
+++ b/src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.h
@@ -6,37 +6,64 @@
struct EnFhgFire;
-typedef void (*EnFhgFireActionFunc)(struct EnFhgFire*, GlobalContext *globalCtx);
+typedef void (*EnFhgFireUpdateFunc)(struct EnFhgFire*, GlobalContext*);
+
+typedef enum {
+ /* 1 */ FHGFIRE_LIGHTNING_STRIKE = 1,
+ /* 35 */ FHGFIRE_LIGHTNING_SHOCK = 35,
+ /* 36 */ FHGFIRE_LIGHTNING_BURST,
+ /* 38 */ FHGFIRE_SPEAR_LIGHT = 38,
+ /* 39 */ FHGFIRE_WARP_EMERGE,
+ /* 40 */ FHGFIRE_WARP_RETREAT,
+ /* 41 */ FHGFIRE_WARP_DEATH,
+ /* 50 */ FHGFIRE_ENERGY_BALL = 50,
+ /* 100 */ FHGFIRE_LIGHTNING_TRAIL = 100
+} FhgFireParam;
+
+typedef enum {
+ /* 0 */ FHGFIRE_LIGHT_GREEN,
+ /* 1 */ FHGFIRE_LIGHT_BLUE,
+ /* 2 */ FHGFIRE_LIGHT_REFLECT
+} FhgLightMode;
+
+typedef enum {
+ /* 0 */ FHGFIRE_TIMER,
+ /* 1 */ FHGFIRE_FX_TIMER,
+ /* 2 */ FHGFIRE_US_2,
+ /* 3 */ FHGFIRE_VARIANCE_TIMER,
+ /* 4 */ FHGFIRE_FIRE_MODE,
+ /* 5 */ FHGFIRE_RETURN_COUNT,
+ /* 6 */ FHGFIRE_KILL_TIMER,
+ /* 7 */ FHGFIRE_SHORT_COUNT
+} FhgFireS16Var;
+
+typedef enum {
+ /* 0 */ FHGFIRE_ALPHA,
+ /* 1 */ FHGFIRE_UF_1,
+ /* 2 */ FHGFIRE_UF_2,
+ /* 3 */ FHGFIRE_SCALE,
+ /* 4 */ FHGFIRE_UF_4,
+ /* 5 */ FHGFIRE_WARP_TEX_1_X,
+ /* 6 */ FHGFIRE_WARP_TEX_1_Y,
+ /* 7 */ FHGFIRE_WARP_TEX_2_X,
+ /* 8 */ FHGFIRE_WARP_TEX_2_Y,
+ /* 9 */ FHGFIRE_WARP_TEX_SPEED,
+ /* 10 */ FHGFIRE_WARP_ALPHA,
+ /* 11 */ FHGFIRE_BURST_SCALE,
+ /* 15 */ FHGFIRE_FLOAT_COUNT = 15
+} FhgFireF32Var;
typedef struct EnFhgFire {
/* 0x0000 */ Actor actor;
- /* 0x014C */ EnFhgFireActionFunc actionFunc;
- /* 0x0150 */ Vec3s unk_150; // rotation
- /* 0x0156 */ s16 unk_156;
- /* 0x0158 */ s16 fireMode;
- /* 0x015a */ s16 unk_15A;
- /* 0x015C */ s16 unk_15C;
- /* 0x015E */ char unk_15E[0x02];
- /* 0x0160 */ f32 unk_160;
- /* 0x0164 */ char unk_164[0x08];
- /* 0x016C */ f32 scale;
- /* 0x0170 */ char unk_170[0x04];
- /* 0x0174 */ f32 unk_174;
- /* 0x0178 */ f32 unk_178;
- /* 0x017C */ f32 unk_17C;
- /* 0x0180 */ f32 unk_180;
- /* 0x0184 */ f32 unk_184;
- /* 0x0188 */ f32 unk_188;
- /* 0x018C */ f32 unk_18C;
- /* 0x0190 */ char unk_190[0x0C];
+ /* 0x014C */ EnFhgFireUpdateFunc updateFunc;
+ /* 0x0150 */ s16 work[FHGFIRE_SHORT_COUNT];
+ /* 0x0160 */ f32 fwork[FHGFIRE_FLOAT_COUNT];
/* 0x019C */ LightNode* lightNode;
/* 0x01A0 */ LightInfo lightInfo;
- /* 0x01AE */ char unk_1AE[2];
/* 0x01B0 */ ColliderCylinder collider;
- /* 0x01FC */ u8 unk_1FC;
- /* 0x01FD */ char unk_1FD;
- /* 0x01FE */ s16 unk_1FE;
- /* 0x0200 */ f32 unk_200;
+ /* 0x01FC */ u8 lensFlareOn;
+ /* 0x01FE */ s16 lensFlareTimer;
+ /* 0x0200 */ f32 lensFlareScale;
} EnFhgFire; // size = 0x0204
extern const ActorInit En_Fhg_Fire_InitVars;
diff --git a/src/overlays/actors/ovl_En_fHG/z_en_fhg.c b/src/overlays/actors/ovl_En_fHG/z_en_fhg.c
index 207a55e92..5a30f52b4 100644
--- a/src/overlays/actors/ovl_En_fHG/z_en_fhg.c
+++ b/src/overlays/actors/ovl_En_fHG/z_en_fhg.c
@@ -5,17 +5,51 @@
*/
#include "z_en_fhg.h"
+#include "objects/object_fhg/object_fhg.h"
+#include "objects/object_fhg/object_fhg.h"
+#include "overlays/actors/ovl_Door_Shutter/z_door_shutter.h"
+#include "overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h"
+#include "overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.h"
#define FLAGS 0x00000010
#define THIS ((EnfHG*)thisx)
+typedef struct {
+ /* 0x00 */ Vec3f pos;
+ /* 0x0C */ s16 yRot;
+} EnfHGPainting; // size = 0x10;
+
+typedef enum {
+ /* 0 */ INTRO_WAIT,
+ /* 1 */ INTRO_START,
+ /* 2 */ INTRO_FENCE,
+ /* 3 */ INTRO_BACK,
+ /* 4 */ INTRO_REVEAL,
+ /* 5 */ INTRO_CUT,
+ /* 6 */ INTRO_LAUGH,
+ /* 7 */ INTRO_TITLE,
+ /* 8 */ INTRO_RETREAT,
+ /* 9 */ INTRO_FINISH,
+ /* 15 */ INTRO_READY = 15
+} EnfHGIntroState;
+
void EnfHG_Init(Actor* thisx, GlobalContext* globalCtx);
void EnfHG_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnfHG_Update(Actor* thisx, GlobalContext* globalCtx);
void EnfHG_Draw(Actor* thisx, GlobalContext* globalCtx);
-/*
+void EnfHG_SetupIntro(EnfHG* this, GlobalContext* globalCtx);
+void EnfHG_Intro(EnfHG* this, GlobalContext* globalCtx);
+void EnfHG_SetupApproach(EnfHG* this, GlobalContext* globalCtx, s16 paintingIndex);
+void EnfHG_Approach(EnfHG* this, GlobalContext* globalCtx);
+void EnfHG_Attack(EnfHG* this, GlobalContext* globalCtx);
+void EnfHG_Damage(EnfHG* this, GlobalContext* globalCtx);
+void EnfHG_Retreat(EnfHG* this, GlobalContext* globalCtx);
+void EnfHG_Done(EnfHG* this, GlobalContext* globalCtx);
+
+void EnfHG_Noop(Actor* thisx, GlobalContext* globalCtx, PSkinAwb* skin);
+
const ActorInit En_fHG_InitVars = {
ACTOR_EN_FHG,
ACTORCAT_BG,
@@ -27,29 +61,673 @@ const ActorInit En_fHG_InitVars = {
(ActorFunc)EnfHG_Update,
(ActorFunc)EnfHG_Draw,
};
-*/
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/EnfHG_Init.s")
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/EnfHG_Destroy.s")
+static EnfHGPainting sPaintings[] = {
+ { { 0.0f, 60.0f, -315.0f }, 0x0000 }, { { -260.0f, 60.0f, -145.0f }, 0x2AAA },
+ { { -260.0f, 60.0f, 165.0f }, 0x5554 }, { { 0.0f, 60.0f, 315.0f }, 0x7FFE },
+ { { 260.0f, 60.0f, 155.0f }, 0xAAA8 }, { { 260.0f, 60.0f, -155.0f }, 0xD552 },
+};
+
+static InitChainEntry sInitChain[] = {
+ ICHAIN_S8(naviEnemyId, 26, ICHAIN_CONTINUE),
+ ICHAIN_F32(uncullZoneScale, 1200, ICHAIN_STOP),
+};
+
+void EnfHG_Init(Actor* thisx, GlobalContext* globalCtx2) {
+ GlobalContext* globalCtx = globalCtx2;
+ EnfHG* this = THIS;
+
+ Actor_ProcessInitChain(&this->actor, sInitChain);
+ Flags_SetSwitch(globalCtx, 0x14);
+ Actor_SetScale(&this->actor, 0.011499999f);
+ this->actor.gravity = -3.5f;
+ ActorShape_Init(&this->actor.shape, -2600.0f, NULL, 20.0f);
+ this->actor.speedXZ = 0.0f;
+ this->actor.focus.pos = this->actor.world.pos;
+ this->actor.focus.pos.y += 70.0f;
+ func_800A663C(globalCtx, &this->skin, &gPhantomHorseSkel, &gPhantomHorseRunningAnim);
+
+ if (this->actor.params >= GND_FAKE_BOSS) {
+ EnfHG_SetupApproach(this, globalCtx, this->actor.params - GND_FAKE_BOSS);
+ } else {
+ EnfHG_SetupIntro(this, globalCtx);
+ }
+}
+
+void EnfHG_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ EnfHG* this = THIS;
+
+ osSyncPrintf("F DT1\n");
+ func_800A6888(globalCtx, &this->skin);
+ osSyncPrintf("F DT2\n");
+}
+
+void EnfHG_SetupIntro(EnfHG* this, GlobalContext* globalCtx) {
+ Animation_PlayLoop(&this->skin.skelAnime, &gPhantomHorseIdleAnim);
+ this->actionFunc = EnfHG_Intro;
+ this->actor.world.pos.x = GND_BOSSROOM_CENTER_X;
+ this->actor.world.pos.y = GND_BOSSROOM_CENTER_Y - 267.0f;
+ this->actor.world.pos.z = GND_BOSSROOM_CENTER_Z;
+}
+
+void EnfHG_Intro(EnfHG* this, GlobalContext* globalCtx) {
+ static Vec3f audioVec = { 0.0f, 0.0f, 50.0f };
+ s32 pad64;
+ Player* player = PLAYER;
+ BossGanondrof* bossGnd = (BossGanondrof*)this->actor.parent;
+ s32 pad58;
+ s32 pad54;
+
+ if (this->cutsceneState != INTRO_FINISH) {
+ SkelAnime_Update(&this->skin.skelAnime);
+ }
+ switch (this->cutsceneState) {
+ case INTRO_WAIT:
+ if ((fabsf(player->actor.world.pos.x - (GND_BOSSROOM_CENTER_X + 0.0f)) < 150.0f) &&
+ (fabsf(player->actor.world.pos.z - (GND_BOSSROOM_CENTER_Z + 0.0f)) < 150.0f)) {
+ this->cutsceneState = INTRO_READY;
+ }
+ break;
+ case INTRO_READY:
+ if ((fabsf(player->actor.world.pos.x - (GND_BOSSROOM_CENTER_X + 0.0f)) < 100.0f) &&
+ (fabsf(player->actor.world.pos.z - (GND_BOSSROOM_CENTER_Z + 315.0f)) < 100.0f)) {
+ this->cutsceneState = INTRO_START;
+ if (gSaveContext.eventChkInf[7] & 4) {
+ this->timers[0] = 57;
+ }
+ }
+ break;
+ case INTRO_START:
+ if (gSaveContext.eventChkInf[7] & 4) {
+ if (this->timers[0] == 55) {
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_DOOR_SHUTTER,
+ GND_BOSSROOM_CENTER_X + 0.0f, GND_BOSSROOM_CENTER_Y - 97.0f,
+ GND_BOSSROOM_CENTER_Z + 308.0f, 0, 0, 0, (SHUTTER_PG_BARS << 6));
+ }
+ if (this->timers[0] == 51) {
+ Audio_PlayActorSound2(this->actor.child, NA_SE_EV_SPEAR_FENCE);
+ Audio_SetBGM(0x1B);
+ }
+ if (this->timers[0] == 0) {
+ EnfHG_SetupApproach(this, globalCtx, Rand_ZeroOne() * 5.99f);
+ this->bossGndSignal = FHG_START_FIGHT;
+ }
+ break;
+ }
+ func_80064520(globalCtx, &globalCtx->csCtx);
+ func_8002DF54(globalCtx, &this->actor, 8);
+ this->cutsceneCamera = Gameplay_CreateSubCamera(globalCtx);
+ Gameplay_ChangeCameraStatus(globalCtx, 0, 1);
+ Gameplay_ChangeCameraStatus(globalCtx, this->cutsceneCamera, 7);
+ this->cutsceneState = INTRO_FENCE;
+ this->timers[0] = 60;
+ this->actor.world.pos.y = GND_BOSSROOM_CENTER_Y - 7.0f;
+ Audio_SetBGM(0x100100FF);
+ gSaveContext.eventChkInf[7] |= 4;
+ Flags_SetSwitch(globalCtx, 0x23);
+ case INTRO_FENCE:
+ player->actor.world.pos.x = GND_BOSSROOM_CENTER_X + 0.0f;
+ player->actor.world.pos.y = GND_BOSSROOM_CENTER_Y + 7.0f;
+ player->actor.world.pos.z = GND_BOSSROOM_CENTER_Z + 155.0f;
+ player->actor.world.rot.y = player->actor.shape.rot.y = 0;
+ player->actor.speedXZ = 0.0f;
+ this->cameraEye.x = GND_BOSSROOM_CENTER_X + 0.0f;
+ this->cameraEye.y = GND_BOSSROOM_CENTER_Y + 37.0f;
+ this->cameraEye.z = GND_BOSSROOM_CENTER_Z + 170.0f;
+ this->cameraAt.x = GND_BOSSROOM_CENTER_X + 0.0f;
+ this->cameraAt.y = GND_BOSSROOM_CENTER_Y + 47.0f;
+ this->cameraAt.z = GND_BOSSROOM_CENTER_Z + 315.0f;
+ if (this->timers[0] == 25) {
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_DOOR_SHUTTER,
+ GND_BOSSROOM_CENTER_X + 0.0f, GND_BOSSROOM_CENTER_Y - 97.0f,
+ GND_BOSSROOM_CENTER_Z + 308.0f, 0, 0, 0, (SHUTTER_PG_BARS << 6));
+ }
+ if (this->timers[0] == 21) {
+ Audio_PlayActorSound2(this->actor.child, NA_SE_EV_SPEAR_FENCE);
+ }
+ if (this->timers[0] == 0) {
+ this->cutsceneState = INTRO_BACK;
+ this->timers[0] = 80;
+ }
+ break;
+ case INTRO_BACK:
+ if (this->timers[0] == 25) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_HORSE_GROAN);
+ }
+ if (this->timers[0] == 20) {
+ func_8002DF54(globalCtx, &this->actor, 9);
+ }
+ if (this->timers[0] == 1) {
+ Audio_SetBGM(0x23);
+ }
+ Math_ApproachF(&this->cameraEye.x, GND_BOSSROOM_CENTER_X + 40.0f, 0.05f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraEye.y, GND_BOSSROOM_CENTER_Y + 37.0f, 0.05f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraEye.z, GND_BOSSROOM_CENTER_Z + 80.0f, 0.05f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraAt.x, GND_BOSSROOM_CENTER_X - 100.0f, 0.05f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraAt.y, GND_BOSSROOM_CENTER_Y + 47.0f, 0.05f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraAt.z, GND_BOSSROOM_CENTER_Z + 335.0f, 0.05f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraSpeedMod, 1.0f, 1.0f, 0.01f);
+ if (this->timers[0] == 0) {
+ this->cutsceneState = INTRO_REVEAL;
+ this->timers[0] = 50;
+ this->cameraSpeedMod = 0.0f;
+ }
+ break;
+ case INTRO_REVEAL:
+ Math_ApproachF(&this->cameraEye.x, GND_BOSSROOM_CENTER_X + 70.0f, 0.1f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraEye.y, GND_BOSSROOM_CENTER_Y + 7.0f, 0.1f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraEye.z, GND_BOSSROOM_CENTER_Z + 200.0f, 0.1f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraAt.x, GND_BOSSROOM_CENTER_X - 150.0f, 0.1f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraAt.y, GND_BOSSROOM_CENTER_Y + 107.0f, 0.1f, this->cameraSpeedMod * 20.0f);
+ Math_ApproachF(&this->cameraAt.z, GND_BOSSROOM_CENTER_Z - 65.0f, 0.1f, this->cameraSpeedMod * 40.0f);
+ Math_ApproachF(&this->cameraSpeedMod, 1.0f, 1.0f, 0.05f);
+ if (this->timers[0] == 5) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_HORSE_SANDDUST);
+ }
+ if (this->timers[0] == 0) {
+ this->cutsceneState = INTRO_CUT;
+ this->timers[0] = 50;
+ this->cameraSpeedMod = 0.0f;
+ }
+ break;
+ case INTRO_CUT:
+ this->cutsceneState = INTRO_LAUGH;
+ this->cameraEye.x = GND_BOSSROOM_CENTER_X + 50.0f;
+ this->cameraEye.y = GND_BOSSROOM_CENTER_Y + 17.0f;
+ this->cameraEye.z = GND_BOSSROOM_CENTER_Z + 110.0f;
+ this->cameraAt.x = GND_BOSSROOM_CENTER_X - 150.0f;
+ this->cameraAt.y = GND_BOSSROOM_CENTER_Y + 207.0f;
+ this->cameraAt.z = GND_BOSSROOM_CENTER_Z - 155.0f;
+ this->cameraEyeVel.x = fabsf(this->cameraEye.x - (GND_BOSSROOM_CENTER_X + 20.0f));
+ this->cameraEyeVel.y = fabsf(this->cameraEye.y - (GND_BOSSROOM_CENTER_Y + 102.0f));
+ this->cameraEyeVel.z = fabsf(this->cameraEye.z - (GND_BOSSROOM_CENTER_Z + 25.0f));
+ this->cameraAtVel.x = fabsf(this->cameraAt.x - (GND_BOSSROOM_CENTER_X - 150.0f));
+ this->cameraAtVel.y = fabsf(this->cameraAt.y - (GND_BOSSROOM_CENTER_Y + 197.0f));
+ this->cameraAtVel.z = fabsf(this->cameraAt.z - (GND_BOSSROOM_CENTER_Z - 65.0f));
+ this->timers[0] = 250;
+ case INTRO_LAUGH:
+ Math_ApproachF(&this->cameraEye.x, GND_BOSSROOM_CENTER_X + 20.0f, 0.05f,
+ this->cameraSpeedMod * this->cameraEyeVel.x);
+ Math_ApproachF(&this->cameraEye.y, GND_BOSSROOM_CENTER_Y + 102.0f, 0.05f,
+ this->cameraSpeedMod * this->cameraEyeVel.y);
+ Math_ApproachF(&this->cameraEye.z, GND_BOSSROOM_CENTER_Z + 25.0f, 0.05f,
+ this->cameraSpeedMod * this->cameraEyeVel.z);
+ Math_ApproachF(&this->cameraAt.x, GND_BOSSROOM_CENTER_X - 150.0f, 0.05f,
+ this->cameraSpeedMod * this->cameraAtVel.x);
+ Math_ApproachF(&this->cameraAt.y, GND_BOSSROOM_CENTER_Y + 197.0f, 0.05f,
+ this->cameraSpeedMod * this->cameraAtVel.y);
+ Math_ApproachF(&this->cameraAt.z, GND_BOSSROOM_CENTER_Z - 65.0f, 0.05f,
+ this->cameraSpeedMod * this->cameraAtVel.z);
+ Math_ApproachF(&this->cameraSpeedMod, 0.01f, 1.0f, 0.001f);
+ if ((this->timers[0] == 245) || (this->timers[0] == 3)) {
+ Animation_MorphToPlayOnce(&this->skin.skelAnime, &gPhantomHorseRearingAnim, -8.0f);
+ this->bossGndSignal = FHG_REAR;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_HORSE_NEIGH);
+ if (this->timers[0] == 3) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_VOICE);
+ }
+ }
+ if (this->timers[0] == 192) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_HORSE_SANDDUST);
+ }
+ if (this->timers[0] == 212) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_HORSE_LAND2);
+ Animation_Change(&this->skin.skelAnime, &gPhantomHorseIdleAnim, 0.3f, 0.0f, 5.0f, ANIMMODE_LOOP_INTERP,
+ -10.0f);
+ }
+ if (this->timers[0] == 90) {
+ globalCtx->envCtx.unk_BF = 2;
+ globalCtx->envCtx.unk_D6 = 0x14;
+ }
+ if (this->timers[0] == 100) {
+ this->bossGndSignal = FHG_LIGHTNING;
+ }
+ if (this->timers[0] == 60) {
+ this->bossGndSignal = FHG_RIDE;
+ }
+ if (this->timers[0] == 130) {
+ Audio_SetBGM(0x105000FF);
+ }
+ if (this->timers[0] == 30) {
+ bossGnd->work[GND_EYE_STATE] = GND_EYESTATE_BRIGHTEN;
+ }
+ if (this->timers[0] == 35) {
+ func_80078914(&audioVec, NA_SE_EN_FANTOM_EYE);
+ }
+ if (this->timers[0] == 130) {
+ bossGnd->work[GND_EYE_STATE] = GND_EYESTATE_FADE;
+ func_80078914(&audioVec, NA_SE_EN_FANTOM_ST_LAUGH);
+ }
+ if (this->timers[0] == 20) {
+ Audio_SetBGM(0x1B);
+ }
+ if (this->timers[0] == 2) {
+ this->cameraSpeedMod = 0.0f;
+ this->cutsceneState = INTRO_TITLE;
+ this->cameraEyeVel.x = fabsf(this->cameraEye.x - (GND_BOSSROOM_CENTER_X + 180.0f));
+ this->cameraEyeVel.y = fabsf(this->cameraEye.y - (GND_BOSSROOM_CENTER_Y + 7.0f));
+ this->cameraEyeVel.z = fabsf(this->cameraEye.z - (GND_BOSSROOM_CENTER_Z + 140.0f));
+ this->timers[0] = 100;
+ this->timers[1] = 34;
+ this->cameraAtVel.x = fabsf(this->cameraAt.x - this->actor.world.pos.x);
+ this->cameraAtVel.y = fabsf(this->cameraAt.y - ((this->actor.world.pos.y + 70.0f) - 20.0f));
+ this->cameraAtVel.z = fabsf(this->cameraAt.z - this->actor.world.pos.z);
+ }
+ break;
+ case INTRO_TITLE:
+ if (this->timers[1] == 1) {
+ Animation_Change(&this->skin.skelAnime, &gPhantomHorseIdleAnim, 0.5f, 0.0f,
+ Animation_GetLastFrame(&gPhantomHorseIdleAnim), ANIMMODE_LOOP_INTERP, -3.0f);
+ }
+ Math_ApproachF(&this->cameraEye.x, GND_BOSSROOM_CENTER_X + 180.0f, 0.1f,
+ this->cameraSpeedMod * this->cameraEyeVel.x);
+ Math_ApproachF(&this->cameraEye.y, GND_BOSSROOM_CENTER_Y + 7.0f, 0.1f,
+ this->cameraSpeedMod * this->cameraEyeVel.y);
+ Math_ApproachF(&this->cameraEye.z, this->cameraPanZ + (GND_BOSSROOM_CENTER_Z + 140.0f), 0.1f,
+ this->cameraSpeedMod * this->cameraEyeVel.z);
+ Math_ApproachF(&this->cameraPanZ, -100.0f, 0.1f, 1.0f);
+ Math_ApproachF(&this->cameraAt.x, this->actor.world.pos.x, 0.1f, this->cameraSpeedMod * 10.0f);
+ Math_ApproachF(&this->cameraAt.y, (this->actor.world.pos.y + 70.0f) - 20.0f, 0.1f,
+ this->cameraSpeedMod * 10.0f);
+ Math_ApproachF(&this->cameraAt.z, this->actor.world.pos.z, 0.1f, this->cameraSpeedMod * 10.0f);
+ Math_ApproachF(&this->actor.world.pos.y, 60.0f, 0.1f, 2.0f);
+ this->actor.world.pos.y += 2.0f * Math_SinS(this->gallopTimer * 0x5DC);
+ Math_ApproachF(&this->cameraSpeedMod, 1.0f, 1.0f, 0.05f);
+ if (this->timers[0] == 75) {
+ TitleCard_InitBossName(globalCtx, &globalCtx->actorCtx.titleCtx,
+ SEGMENTED_TO_VIRTUAL(&gPhantomGanonTitleCardTex), 0xA0, 0xB4, 0x80, 0x28);
+ }
+ if (this->timers[0] == 0) {
+ this->cutsceneState = INTRO_RETREAT;
+ this->timers[0] = 200;
+ this->timers[1] = 23;
+ this->cameraSpeedMod = 0.0f;
+ Animation_Change(&this->skin.skelAnime, &gPhantomHorseLeapAnim, 1.0f, 0.0f,
+ Animation_GetLastFrame(&gPhantomHorseLeapAnim), ANIMMODE_ONCE_INTERP, -4.0f);
+ this->bossGndSignal = FHG_SPUR;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_VOICE);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_HORSE_NEIGH);
+ }
+ break;
+ case INTRO_RETREAT:
+ if (this->timers[1] == 1) {
+ Animation_Change(&this->skin.skelAnime, &gPhantomHorseLandAnim, 0.5f, 0.0f,
+ Animation_GetLastFrame(&gPhantomHorseLandAnim), ANIMMODE_ONCE_INTERP, -3.0f);
+ this->bossGndSignal = FHG_FINISH;
+ }
+ if (this->timers[0] == 170) {
+ func_8002DF54(globalCtx, &this->actor, 8);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_MASIC2);
+ }
+ Math_ApproachF(&this->cameraEye.z, this->cameraPanZ + (GND_BOSSROOM_CENTER_Z + 100.0f), 0.1f,
+ this->cameraSpeedMod * 1.5f);
+ Math_ApproachF(&this->cameraPanZ, -100.0f, 0.1f, 1.0f);
+ Math_ApproachF(&this->actor.world.pos.z, GND_BOSSROOM_CENTER_Z + 400.0f - 0.5f, 1.0f,
+ this->cameraSpeedMod * 10.0f);
+ Math_ApproachF(&this->cameraSpeedMod, 1.0f, 1.0f, 0.05f);
+ if ((fabsf(this->actor.world.pos.z - (GND_BOSSROOM_CENTER_Z + 400.0f - 0.5f)) < 300.0f) &&
+ !this->spawnedWarp) {
+ this->spawnedWarp = true;
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE,
+ GND_BOSSROOM_CENTER_X + 0.0f, this->actor.world.pos.y + 50.0f,
+ GND_BOSSROOM_CENTER_Z + 400.0f - 0.5f, 0, this->actor.shape.rot.y, 0,
+ FHGFIRE_WARP_RETREAT);
+ this->fhgFireKillWarp = true;
+ }
+ Math_ApproachF(&this->cameraAt.x, this->actor.world.pos.x, 0.2f, 50.0f);
+ Math_ApproachF(&this->cameraAt.z, this->actor.world.pos.z, 0.2f, 50.0f);
+ osSyncPrintf("TIME %d-------------------------------------------------\n", this->timers[0]);
+ if (fabsf(this->actor.world.pos.z - (GND_BOSSROOM_CENTER_Z + 400.0f - 0.5f)) < 1.0f) {
+ globalCtx->envCtx.unk_BF = 0;
+ globalCtx->envCtx.unk_D6 = 0x14;
+ this->cutsceneState = INTRO_FINISH;
+ Animation_MorphToLoop(&this->skin.skelAnime, &gPhantomHorseRunningAnim, -3.0f);
+ this->bossGndSignal = FHG_START_FIGHT;
+ this->timers[1] = 75;
+ this->timers[0] = 140;
+ }
+ break;
+ case INTRO_FINISH:
+ EnfHG_Retreat(this, globalCtx);
+ Math_ApproachF(&this->cameraEye.z, this->cameraPanZ + (GND_BOSSROOM_CENTER_Z + 100.0f), 0.1f,
+ this->cameraSpeedMod * 1.5f);
+ Math_ApproachF(&this->cameraPanZ, -100.0f, 0.1f, 1.0f);
+ Math_ApproachF(&this->cameraAt.y, (this->actor.world.pos.y + 70.0f) - 20.0f, 0.1f,
+ this->cameraSpeedMod * 10.0f);
+ if (this->timers[1] == 0) {
+ Camera* camera = Gameplay_GetCamera(globalCtx, 0);
+
+ camera->eye = this->cameraEye;
+ camera->eyeNext = this->cameraEye;
+ camera->at = this->cameraAt;
+ func_800C08AC(globalCtx, this->cutsceneCamera, 0);
+ this->cutsceneCamera = 0;
+ func_80064534(globalCtx, &globalCtx->csCtx);
+ func_8002DF54(globalCtx, &this->actor, 7);
+ this->actionFunc = EnfHG_Retreat;
+ }
+ break;
+ }
+ if (this->cutsceneCamera != 0) {
+ Gameplay_CameraSetAtEye(globalCtx, this->cutsceneCamera, &this->cameraAt, &this->cameraEye);
+ }
+}
+
+void EnfHG_SetupApproach(EnfHG* this, GlobalContext* globalCtx, s16 paintingIndex) {
+ s16 oppositeIndex[6] = { 3, 4, 5, 0, 1, 2 };
+
+ Animation_MorphToLoop(&this->skin.skelAnime, &gPhantomHorseRunningAnim, 0.0f);
+ this->actionFunc = EnfHG_Approach;
+ this->curPainting = paintingIndex;
+ this->targetPainting = oppositeIndex[this->curPainting];
+
+ osSyncPrintf("KABE NO 1 = %d\n", this->curPainting);
+ osSyncPrintf("KABE NO 2 = %d\n", this->targetPainting);
+
+ this->actor.world.pos.x = (1.3f * sPaintings[this->curPainting].pos.x) + (GND_BOSSROOM_CENTER_X - 4.0f);
+ this->actor.world.pos.y = sPaintings[this->curPainting].pos.y + (GND_BOSSROOM_CENTER_Y + 153.0f);
+ this->actor.world.pos.z = (1.3f * sPaintings[this->curPainting].pos.z) - -(GND_BOSSROOM_CENTER_Z - 10.0f);
+ this->actor.world.rot.y = sPaintings[this->curPainting].yRot;
+
+ osSyncPrintf("XP1 = %f\n", this->actor.world.pos.x);
+ osSyncPrintf("ZP1 = %f\n", this->actor.world.pos.z);
+
+ this->inPaintingPos.x = (sPaintings[this->targetPainting].pos.x * 1.3f) + (GND_BOSSROOM_CENTER_X - 4.0f);
+ this->inPaintingPos.y = sPaintings[this->targetPainting].pos.y + (GND_BOSSROOM_CENTER_Y + 33.0f);
+ this->inPaintingPos.z = (sPaintings[this->targetPainting].pos.z * 1.3f) - -(GND_BOSSROOM_CENTER_Z - 10.0f);
+ this->inPaintingVelX = (fabsf(this->inPaintingPos.x - this->actor.world.pos.x) * 2) * 0.01f;
+
+ if (this->inPaintingVelX < 1.0f) {
+ this->inPaintingVelX = 1.0f;
+ }
+ this->inPaintingVelZ = (fabsf(this->inPaintingPos.z - this->actor.world.pos.z) * 2) * 0.01f;
+ if (this->inPaintingVelZ < 1.0f) {
+ this->inPaintingVelZ = 1.0f;
+ }
+
+ this->timers[0] = 100;
+ this->actor.scale.x = 0.002f;
+ this->actor.scale.y = 0.002f;
+ this->actor.scale.z = 0.001f;
+ this->approachRate = 0.0f;
+
+ this->warpColorFilterR = globalCtx->lightCtx.unk_07;
+ this->warpColorFilterG = globalCtx->lightCtx.unk_08;
+ this->warpColorFilterB = globalCtx->lightCtx.unk_09;
+ this->warpColorFilterUnk1 = 0.0f;
+ this->warpColorFilterUnk2 = 0.0f;
+ this->turnRot = 0;
+ this->turnTarget = 0;
+ this->spawnedWarp = false;
+}
+
+void EnfHG_Approach(EnfHG* this, GlobalContext* globalCtx) {
+ osSyncPrintf("STANDBY !!\n");
+ osSyncPrintf("XP2 = %f\n", this->actor.world.pos.x);
+ osSyncPrintf("ZP2 = %f\n", this->actor.world.pos.z);
+ if (this->actor.params == GND_REAL_BOSS) {
+ this->hoofSfxPos.x = this->actor.projectedPos.x / (this->actor.scale.x * 100.0f);
+ this->hoofSfxPos.y = this->actor.projectedPos.y / (this->actor.scale.x * 100.0f);
+ this->hoofSfxPos.z = this->actor.projectedPos.z / (this->actor.scale.x * 100.0f);
+ if ((this->gallopTimer % 8) == 0) {
+ func_80078914(&this->hoofSfxPos, NA_SE_EV_HORSE_RUN);
+ }
+ }
+ SkelAnime_Update(&this->skin.skelAnime);
+ Math_ApproachF(&this->actor.scale.x, 0.011499999f, 1.0f, this->approachRate);
+ Math_ApproachF(&this->approachRate, 0.0002f, 1.0f, 0.0000015f);
+ Math_ApproachF(&this->actor.world.pos.y, 60.0f, 0.1f, 1.0f);
+ this->actor.scale.y = this->actor.scale.x;
+ if (this->timers[0] == 0) {
+ osSyncPrintf("arg_data ------------------------------------>%d\n", this->actor.params);
+ if (this->actor.params != GND_REAL_BOSS) {
+ this->timers[0] = 140;
+ this->actionFunc = EnfHG_Retreat;
+ Animation_MorphToLoop(&this->skin.skelAnime, &gPhantomHorseRunningAnim, 0.0f);
+ this->turnTarget = -0x8000;
+ } else {
+ this->actionFunc = EnfHG_Attack;
+ Audio_PlayActorSound2(&this->actor, NA_SE_EV_GANON_HORSE_NEIGH);
+ this->timers[0] = 40;
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE,
+ this->actor.world.pos.x, this->actor.world.pos.y + 50.0f, this->actor.world.pos.z, 0,
+ this->actor.shape.rot.y + 0x8000, 0, FHGFIRE_WARP_EMERGE);
+ this->fhgFireKillWarp = false;
+ }
+ }
+}
+
+void EnfHG_Attack(EnfHG* this, GlobalContext* globalCtx) {
+ osSyncPrintf("KABE OUT !!\n");
+ this->bossGndInPainting = false;
+ SkelAnime_Update(&this->skin.skelAnime);
+ if (this->timers[0] != 0) {
+ Math_ApproachF(&this->actor.scale.z, 0.011499999f, 1.0f, 0.0002f);
+ if (this->timers[0] == 1) {
+ this->bossGndSignal = FHG_RAISE_SPEAR;
+ this->timers[1] = 50;
+ Animation_MorphToPlayOnce(&this->skin.skelAnime, &gPhantomHorseLeapAnim, 0.0f);
+ }
+ Math_ApproachF(&this->warpColorFilterR, 255.0f, 1.0f, 10.0f);
+ Math_ApproachF(&this->warpColorFilterG, 255.0f, 1.0f, 10.0f);
+ Math_ApproachF(&this->warpColorFilterB, 255.0f, 1.0f, 10.0f);
+ Math_ApproachF(&this->warpColorFilterUnk1, -60.0f, 1.0f, 5.0f);
+ } else {
+ Math_ApproachF(&this->warpColorFilterR, globalCtx->lightCtx.unk_07, 1.0f, 10.0f);
+ Math_ApproachF(&this->warpColorFilterG, globalCtx->lightCtx.unk_07, 1.0f, 10.0f);
+ Math_ApproachF(&this->warpColorFilterB, globalCtx->lightCtx.unk_07, 1.0f, 10.0f);
+ Math_ApproachF(&this->warpColorFilterUnk1, 0.0f, 1.0f, 5.0f);
+ if (this->timers[1] == 29) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_MASIC2);
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_VOICE);
+ }
+ if (this->hitTimer == 0) {
+ if (this->timers[1] == 24) {
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE,
+ this->actor.world.pos.x, (this->actor.world.pos.y + 100.0f) + 25.0f,
+ this->actor.world.pos.z, 0, 0, 0, FHGFIRE_LIGHTNING_STRIKE);
+ }
+ if (this->timers[1] == 45) {
+ Animation_MorphToLoop(&this->skin.skelAnime, &gPhantomHorseAirAnim, 0.0f);
+ }
+ if (this->timers[1] == 38) {
+ this->bossGndSignal = FHG_LIGHTNING;
+ }
+ if (this->timers[1] == 16) {
+ Animation_MorphToPlayOnce(&this->skin.skelAnime, &gPhantomHorseLandAnim, 0.0f);
+ this->bossGndSignal = FHG_RESET;
+ }
+ }
+ Math_ApproachF(&this->actor.scale.z, 0.011499999f, 1.0f, 0.002f);
+ Math_ApproachF(&this->actor.world.pos.x, this->inPaintingPos.x, 1.0f, this->inPaintingVelX);
+ Math_ApproachF(&this->actor.world.pos.y, 60.0f, 0.1f, 1.0f);
+ Math_ApproachF(&this->actor.world.pos.z, this->inPaintingPos.z, 1.0f, this->inPaintingVelZ);
+ }
+ if (this->hitTimer == 20) {
+ this->actionFunc = EnfHG_Damage;
+ this->spawnedWarp = false;
+ Animation_Change(&this->skin.skelAnime, &gPhantomHorseLandAnim, -1.0f, 0.0f,
+ Animation_GetLastFrame(&gPhantomHorseLandAnim), ANIMMODE_ONCE, -5.0f);
+ this->timers[0] = 10;
+ this->bossGndSignal = FHG_RESET;
+ this->damageSpeedMod = 1.0f;
+ } else {
+ f32 dx = this->actor.world.pos.x - this->inPaintingPos.x;
+ f32 dz = this->actor.world.pos.z - this->inPaintingPos.z;
+ f32 dxz = sqrtf(SQ(dx) + SQ(dz));
+
+ if (dxz < 350.0f) {
+ this->bossGndInPainting = true;
+ }
+ if ((dxz < 300.0f) && !this->spawnedWarp) {
+ this->spawnedWarp = true;
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE, this->inPaintingPos.x,
+ this->actor.world.pos.y + 50.0f, this->inPaintingPos.z, 0, this->actor.shape.rot.y, 0,
+ FHGFIRE_WARP_RETREAT);
+ this->fhgFireKillWarp = true;
+ }
+ osSyncPrintf("SPD X %f\n", this->inPaintingVelX);
+ osSyncPrintf("SPD Z %f\n", this->inPaintingVelZ);
+ osSyncPrintf("X=%f\n", dx);
+ osSyncPrintf("Z=%f\n", dz);
+ if (dxz == 0.0f) {
+ this->timers[0] = 140;
+ this->actionFunc = EnfHG_Retreat;
+ Animation_MorphToLoop(&this->skin.skelAnime, &gPhantomHorseRunningAnim, 0.0f);
+ this->bossGndSignal = FHG_RIDE;
+ }
+ }
+}
+
+void EnfHG_Damage(EnfHG* this, GlobalContext* globalCtx) {
+ f32 dx;
+ f32 dz;
+ f32 dxz2;
+
+ osSyncPrintf("REVISE !!\n");
+ SkelAnime_Update(&this->skin.skelAnime);
+ Math_ApproachF(&this->warpColorFilterR, globalCtx->lightCtx.unk_07, 1.0f, 10.0f);
+ Math_ApproachF(&this->warpColorFilterG, globalCtx->lightCtx.unk_07, 1.0f, 10.0f);
+ Math_ApproachF(&this->warpColorFilterB, globalCtx->lightCtx.unk_07, 1.0f, 10.0f);
+ Math_ApproachF(&this->warpColorFilterUnk1, 0.0f, 1.0f, 5.0f);
+ Math_ApproachF(&this->actor.scale.z, 0.011499999f, 1.0f, 0.002f);
+ if (this->timers[0] != 0) {
+ Math_ApproachZeroF(&this->damageSpeedMod, 1.0f, 0.1f);
+ if (this->timers[0] == 1) {
+ this->targetPainting = this->curPainting;
+ this->inPaintingPos.x = (sPaintings[this->targetPainting].pos.x * 1.3f) + (GND_BOSSROOM_CENTER_X - 4.0f);
+ this->inPaintingPos.y = sPaintings[this->targetPainting].pos.y;
+ this->inPaintingPos.z = (sPaintings[this->targetPainting].pos.z * 1.3f) - -(GND_BOSSROOM_CENTER_Z - 10.0f);
+ }
+ } else {
+ Math_ApproachF(&this->damageSpeedMod, 1.0f, 1.0f, 0.1f);
+ }
+ Math_ApproachF(&this->actor.world.pos.x, this->inPaintingPos.x, 1.0f, this->damageSpeedMod * this->inPaintingVelX);
+ Math_ApproachF(&this->actor.world.pos.y, 60.0f, 0.1f, 1.0f);
+ Math_ApproachF(&this->actor.world.pos.z, this->inPaintingPos.z, 1.0f, this->damageSpeedMod * this->inPaintingVelZ);
+ dx = this->actor.world.pos.x - this->inPaintingPos.x;
+ dz = this->actor.world.pos.z - this->inPaintingPos.z;
+ dxz2 = sqrtf(SQ(dx) + SQ(dz));
+ if ((dxz2 < 300.0f) && (!this->spawnedWarp)) {
+ this->spawnedWarp = true;
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_EN_FHG_FIRE, this->inPaintingPos.x,
+ this->actor.world.pos.y + 50.0f, this->inPaintingPos.z, 0, this->actor.shape.rot.y + 0x8000,
+ 0, FHGFIRE_WARP_RETREAT);
+ }
+ if (dxz2 == 0.0f) {
+ BossGanondrof* bossGnd = (BossGanondrof*)this->actor.parent;
+
+ this->timers[0] = 140;
+ this->actionFunc = EnfHG_Retreat;
+ Animation_MorphToLoop(&this->skin.skelAnime, &gPhantomHorseRunningAnim, 0.0f);
+ if (bossGnd->actor.colChkInfo.health > 24) {
+ this->bossGndSignal = FHG_RIDE;
+ } else {
+ bossGnd->flyMode = GND_FLY_NEUTRAL;
+ }
+ this->turnTarget = -0x8000;
+ }
+}
+
+void EnfHG_Retreat(EnfHG* this, GlobalContext* globalCtx) {
+ osSyncPrintf("KABE IN !!\n");
+ if (this->turnTarget != 0) {
+ Math_ApproachS(&this->turnRot, this->turnTarget, 5, 2000);
+ }
+ if (this->actor.params == GND_REAL_BOSS) {
+ this->hoofSfxPos.x = this->actor.projectedPos.x / (this->actor.scale.x * 100.0f);
+ this->hoofSfxPos.y = this->actor.projectedPos.y / (this->actor.scale.x * 100.0f);
+ this->hoofSfxPos.z = this->actor.projectedPos.z / (this->actor.scale.x * 100.0f);
+ if ((this->gallopTimer % 8) == 0) {
+ func_80078914(&this->hoofSfxPos, NA_SE_EV_HORSE_RUN);
+ }
+ }
+ SkelAnime_Update(&this->skin.skelAnime);
+ Math_ApproachF(&this->actor.scale.z, 0.001f, 1.0f, 0.001f);
+ Math_ApproachF(&this->actor.scale.x, 0.002f, 0.05f, 0.0001f);
+ Math_ApproachF(&this->actor.world.pos.y, 200.0f, 0.05f, 1.0f);
+ this->actor.scale.y = this->actor.scale.x;
+ if ((this->timers[0] == 80) && (this->actor.params == GND_REAL_BOSS)) {
+ Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_LAUGH);
+ }
+ if (this->timers[0] == 0) {
+ BossGanondrof* bossGnd = (BossGanondrof*)this->actor.parent;
+ s16 paintingIdxReal;
+ s16 paintingIdxFake;
+
+ if (this->actor.params != GND_REAL_BOSS) {
+ this->killActor = true;
+ bossGnd->killActor = true;
+ } else if (bossGnd->flyMode != GND_FLY_PAINTING) {
+ this->actionFunc = EnfHG_Done;
+ this->actor.draw = NULL;
+ } else {
+ paintingIdxReal = Rand_ZeroOne() * 5.99f;
+ EnfHG_SetupApproach(this, globalCtx, paintingIdxReal);
+ do {
+ paintingIdxFake = Rand_ZeroOne() * 5.99f;
+ } while (paintingIdxFake == paintingIdxReal);
+ osSyncPrintf("ac1 = %x `````````````````````````````````````````````````\n",
+ Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_BOSS_GANONDROF,
+ this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z,
+ 0, 0, 0, paintingIdxFake + GND_FAKE_BOSS));
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/func_80B62B04.s")
+void EnfHG_Done(EnfHG* this, GlobalContext* globalCtx) {
+ this->bossGndInPainting = false;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/func_80B62B6C.s")
+void EnfHG_Update(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ EnfHG* this = THIS;
+ u8 i;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/func_80B63D84.s")
+ if (this->killActor) {
+ Actor_Kill(&this->actor);
+ return;
+ }
+ this->gallopTimer++;
+ this->bossGndInPainting = true;
+ for (i = 0; i < 5; i++) {
+ if (this->timers[i] != 0) {
+ this->timers[i]--;
+ }
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/func_80B6404C.s")
+ this->actionFunc(this, globalCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/func_80B6424C.s")
+ if (this->hitTimer != 0) {
+ this->hitTimer--;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/func_80B6476C.s")
+ this->actor.focus.pos = this->actor.world.pos;
+ this->actor.focus.pos.y += 70.0f;
+ this->actor.shape.rot.y = this->actor.world.rot.y;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/func_80B64AA8.s")
+ this->actor.shape.yOffset = Math_SinS(this->hitTimer * 0x9000) * 700.0f * (this->hitTimer / 20.0f);
+ this->actor.shape.rot.z = (s16)(Math_SinS(this->hitTimer * 0x7000) * 1500.0f) * (this->hitTimer / 20.0f);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/func_80B64CF4.s")
+void EnfHG_Noop(Actor* thisx, GlobalContext* globalCtx, PSkinAwb* skin) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/EnfHG_Update.s")
+void EnfHG_Draw(Actor* thisx, GlobalContext* globalCtx) {
+ EnfHG* this = THIS;
+ BossGanondrof* bossGnd = (BossGanondrof*)this->actor.parent;
+ s32 pad;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/func_80B64E94.s")
+ OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_fhg.c", 2439);
+ func_80093D18(globalCtx->state.gfxCtx);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_fHG/EnfHG_Draw.s")
+ POLY_OPA_DISP = ((bossGnd->work[GND_INVINC_TIMER] & 4) && (bossGnd->flyMode == GND_FLY_PAINTING))
+ ? Gfx_SetFog(POLY_OPA_DISP, 255, 50, 0, 0, 900, 1099)
+ : Gfx_SetFog(POLY_OPA_DISP, (u32)this->warpColorFilterR, (u32)this->warpColorFilterG,
+ (u32)this->warpColorFilterB, 0, (s32)this->warpColorFilterUnk1 + 995,
+ (s32)this->warpColorFilterUnk2 + 1000);
+ func_800A6330(&this->actor, globalCtx, &this->skin, EnfHG_Noop, 0x23);
+ POLY_OPA_DISP = func_800BC8A0(globalCtx, POLY_OPA_DISP);
+ CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_fhg.c", 2480);
+}
diff --git a/src/overlays/actors/ovl_En_fHG/z_en_fhg.h b/src/overlays/actors/ovl_En_fHG/z_en_fhg.h
index d62f35bc3..36d4495b5 100644
--- a/src/overlays/actors/ovl_En_fHG/z_en_fhg.h
+++ b/src/overlays/actors/ovl_En_fHG/z_en_fhg.h
@@ -6,21 +6,59 @@
struct EnfHG;
+typedef void (*EnfHGActionFunc)(struct EnfHG*, GlobalContext*);
+
+typedef enum {
+ /* 0 */ FHG_NO_SIGNAL,
+ /* 1 */ FHG_RAISE_SPEAR,
+ /* 2 */ FHG_REAR,
+ /* 3 */ FHG_LIGHTNING,
+ /* 4 */ FHG_RESET,
+ /* 5 */ FHG_RIDE,
+ /* 10 */ FHG_SPUR = 10,
+ /* 11 */ FHG_FINISH,
+ /* -1 */ FHG_START_FIGHT = 255
+} EnfHGSignal;
+
typedef struct EnfHG {
/* 0x0000 */ Actor actor;
- /* 0x014C */ char unk_14C[0x3];
- /* 0x014F */ u8 unk_14F;
- /* 0x0150 */ char unk_150[0x77];
- /* 0x01C7 */ u8 unk_1C7;
- /* 0x01C8 */ char unk_1C8;
- /* 0x01C9 */ u8 flyMode;
- /* 0x01CA */ u8 unk_1CA;
- /* 0x01CB */ char unk_1CB[0x15];
+ /* 0x014C */ u8 bossGndSignal;
+ /* 0x014D */ u8 bossGndInPainting;
+ /* 0x014E */ u8 killActor;
+ /* 0x014F */ u8 fhgFireKillWarp;
+ /* 0x0150 */ Vec3f cameraEye;
+ /* 0x015C */ Vec3f cameraAt;
+ /* 0x0168 */ Vec3f cameraEyeVel;
+ /* 0x0174 */ Vec3f cameraAtVel;
+ /* 0x0180 */ Vec3f hoofSfxPos;
+ /* 0x018C */ Vec3f inPaintingPos;
+ /* 0x0198 */ f32 inPaintingVelX;
+ /* 0x019C */ f32 inPaintingVelZ;
+ /* 0x0198 */ f32 damageSpeedMod;
+ /* 0x01A4 */ f32 approachRate;
+ /* 0x01A8 */ f32 cameraSpeedMod;
+ /* 0x01AC */ f32 cameraPanZ;
+ /* 0x01B0 */ char unk_1B0[0x10];
+ /* 0x01C0 */ s16 gallopTimer;
+ /* 0x01C2 */ s16 curPainting;
+ /* 0x01C4 */ s16 targetPainting;
+ /* 0x01C6 */ s16 turnTarget;
+ /* 0x01C8 */ s16 spawnedWarp;
+ /* 0x01CA */ s16 cutsceneState;
+ /* 0x01CC */ s16 cutsceneCamera;
+ /* 0x01CE */ char unk_1CE[6];
+ /* 0x01D4 */ s16 timers[5];
+ /* 0x01DE */ s16 hitTimer;
/* 0x01E0 */ s16 turnRot;
- /* 0x01E2 */ char unk_1E2[0x1E];
- /* 0x0200 */ Vec3f unk_200;
- /* 0x020C */ Vec3f unk_20C;
- /* 0x0218 */ char unk_218[0x7C];
+ /* 0x01E2 */ char unk_1E2[6];
+ /* 0x01E8 */ f32 warpColorFilterR;
+ /* 0x01EC */ f32 warpColorFilterG;
+ /* 0x01F0 */ f32 warpColorFilterB;
+ /* 0x01F4 */ f32 warpColorFilterUnk1;
+ /* 0x01F8 */ f32 warpColorFilterUnk2;
+ /* 0x01FC */ EnfHGActionFunc actionFunc;
+ /* 0x0200 */ char unk_200[4];
+ /* 0x0204 */ PSkinAwb skin;
} EnfHG; // size = 0x0294
extern const ActorInit En_Fhg_InitVars;
diff --git a/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c b/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c
index 194163b52..531b1de8f 100644
--- a/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c
+++ b/src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c
@@ -5,6 +5,7 @@
*/
#include "z_item_b_heart.h"
+#include "objects/object_gi_hearts/object_gi_hearts.h"
#define FLAGS 0x00000000
@@ -17,9 +18,6 @@ void ItemBHeart_Draw(Actor* thisx, GlobalContext* globalCtx);
void func_80B85264(ItemBHeart* this, GlobalContext* globalCtx);
-extern Gfx D_06001290[];
-extern Gfx D_06001470[];
-
const ActorInit Item_B_Heart_InitVars = {
ACTOR_ITEM_B_HEART,
ACTORCAT_MISC,
@@ -67,11 +65,11 @@ void ItemBHeart_Update(Actor* thisx, GlobalContext* globalCtx) {
}
void func_80B85264(ItemBHeart* this, GlobalContext* globalCtx) {
- f32 temp;
+ f32 yOffset;
- this->unk_164 += 1;
- temp = ((Math_SinS(this->unk_164 * 1548) * 5.0f) + 20.0f);
- Math_ApproachF(&this->actor.world.pos.y, this->actor.home.pos.y + temp, 0.1f, this->unk_158);
+ this->unk_164++;
+ yOffset = (Math_SinS(this->unk_164 * 0x60C) * 5.0f) + 20.0f;
+ Math_ApproachF(&this->actor.world.pos.y, this->actor.home.pos.y + yOffset, 0.1f, this->unk_158);
Math_ApproachF(&this->unk_158, 2.0f, 1.0f, 0.1f);
this->actor.shape.rot.y += 0x400;
@@ -82,7 +80,7 @@ void func_80B85264(ItemBHeart* this, GlobalContext* globalCtx) {
void ItemBHeart_Draw(Actor* thisx, GlobalContext* globalCtx) {
ItemBHeart* this = THIS;
Actor* actorIt;
- u8 flag = 0;
+ u8 flag = false;
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 506);
@@ -90,25 +88,24 @@ void ItemBHeart_Draw(Actor* thisx, GlobalContext* globalCtx) {
while (actorIt != NULL) {
if ((actorIt->id == ACTOR_DOOR_WARP1) && (actorIt->projectedPos.z > this->actor.projectedPos.z)) {
- flag = 1;
+ flag = true;
break;
- } else {
- actorIt = actorIt->next;
}
+ actorIt = actorIt->next;
}
if (flag) {
func_80093D84(globalCtx->state.gfxCtx);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 551),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, D_06001290);
- gSPDisplayList(POLY_XLU_DISP++, D_06001470);
+ gSPDisplayList(POLY_XLU_DISP++, gGiHeartBorderDL);
+ gSPDisplayList(POLY_XLU_DISP++, gGiHeartContainerDL);
} else {
func_80093D18(globalCtx->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 557),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_OPA_DISP++, D_06001290);
- gSPDisplayList(POLY_OPA_DISP++, D_06001470);
+ gSPDisplayList(POLY_OPA_DISP++, gGiHeartBorderDL);
+ gSPDisplayList(POLY_OPA_DISP++, gGiHeartContainerDL);
}
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_item_b_heart.c", 561);