diff options
| author | petrie911 <69443847+petrie911@users.noreply.github.com> | 2021-03-29 14:35:46 -0500 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-03-29 15:35:46 -0400 |
| commit | 28cfd82a4f692cdeb1e66c2df980da07e6b41e2d (patch) | |
| tree | 94896568117a3864adf4a3c8f543c47bc5225b61 /src | |
| parent | 86f16cf662db0e4b8ba9973a6b055ab9cd395670 (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.c | 1469 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_Boss_Ganondrof/z_boss_ganondrof.h | 94 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c | 7 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.c | 722 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.h | 77 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_En_fHG/z_en_fhg.c | 708 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_En_fHG/z_en_fhg.h | 62 | ||||
| -rw-r--r-- | src/overlays/actors/ovl_Item_B_Heart/z_item_b_heart.c | 27 |
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); |
