Shipwright/soh/src/overlays/actors/ovl_En_Fhg_Fire/z_en_fhg_fire.c

758 lines
32 KiB
C

/*
* File: z_en_fhg_fire.c
* Overlay: ovl_En_Fhg_Fire
* Description: Phantom Ganon's Lighting Attack
*/
#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"
#define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_5)
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 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,
ACTORCAT_BOSS,
FLAGS,
OBJECT_FHG,
sizeof(EnFhgFire),
(ActorFunc)EnFhgFire_Init,
(ActorFunc)EnFhgFire_Destroy,
(ActorFunc)EnFhgFire_Update,
(ActorFunc)EnFhgFire_Draw,
NULL,
};
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) {
s32 pad;
EnFhgFire* this = (EnFhgFire*)thisx;
Player* player = GET_PLAYER(globalCtx);
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, &this->actor, &sCylinderInit);
}
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 (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;
} else if (this->actor.params == FHGFIRE_SPEAR_LIGHT) {
osSyncPrintf("yari hikari ct 1\n"); // "light spear"
EnFhgFire_SetUpdate(this, EnFhgFire_SpearLight);
osSyncPrintf("yari hikari ct 2\n");
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, 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 = (EnFhgFire*)thisx;
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 (this->actor.params == FHGFIRE_ENERGY_BALL) {
LightContext_RemoveLight(globalCtx, &globalCtx->lightCtx, this->lightNode);
}
}
void EnFhgFire_LightningStrike(EnFhgFire* this, GlobalContext* globalCtx) {
Camera* camera = Gameplay_GetCamera(globalCtx, 0);
s16 i;
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);
if (this->work[FHGFIRE_TIMER] == 0) {
this->work[FHGFIRE_FIRE_MODE] = STRIKE_TRAILS;
this->actor.shape.rot.z += 0x8000;
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,
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;
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 * 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 * 0x2000) + randY, 0, FHGFIRE_LIGHTNING_SHOCK);
}
}
if (this->work[FHGFIRE_TIMER] == 0) {
Actor_Kill(&this->actor);
}
}
Actor_SetScale(&this->actor, this->fwork[FHGFIRE_SCALE]);
}
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->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 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->fwork[FHGFIRE_SCALE]);
if (this->actor.scale.x > 1.0f) {
this->actor.scale.x = 1.0f;
}
osSyncPrintf("FF MOVE 2\n");
}
void EnFhgFire_LightningShock(EnFhgFire* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
Vec3f pos;
if (this->collider.base.atFlags & AT_HIT) {
this->collider.base.atFlags &= ~AT_HIT;
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_HIT_THUNDER);
}
if (Rand_ZeroOne() < 0.5f) {
pos = this->actor.world.pos;
pos.y -= 20.0f;
EffectSsFhgFlash_SpawnShock(globalCtx, &this->actor, &pos, 200, FHGFLASH_SHOCK_NO_ACTOR);
}
Actor_MoveForward(&this->actor);
Collider_UpdateCylinder(&this->actor, &this->collider);
if (player->invincibilityTimer == 0) {
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider.base);
}
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 50.0f, 50.0f, 100.0f, 1);
if (this->actor.bgCheckFlags & 8) {
Actor_Kill(&this->actor);
}
}
void EnFhgFire_LightningBurst(EnFhgFire* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
globalCtx->envCtx.fillScreen = true;
this->actor.shape.rot.y += 0x1000;
if (this->work[FHGFIRE_FX_TIMER] == 49) {
globalCtx->envCtx.unk_BF = 1;
globalCtx->envCtx.unk_D6 = 0xFF;
}
if (this->work[FHGFIRE_FX_TIMER] == 31) {
globalCtx->envCtx.unk_BF = 0x00;
globalCtx->envCtx.unk_D6 = 0x14;
}
if (this->work[FHGFIRE_FX_TIMER] >= 48) {
globalCtx->envCtx.screenFillColor[0] = globalCtx->envCtx.screenFillColor[1] =
globalCtx->envCtx.screenFillColor[2] = 255;
if ((this->work[FHGFIRE_TIMER] % 2) != 0) {
globalCtx->envCtx.screenFillColor[3] = 70;
} else {
globalCtx->envCtx.screenFillColor[3] = 0;
}
} else {
globalCtx->envCtx.screenFillColor[3] = 0;
}
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->fwork[FHGFIRE_SCALE], this->fwork[FHGFIRE_BURST_SCALE], 0.5f, 3.0f);
}
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->work[FHGFIRE_TIMER] == 0) {
Actor_Kill(&this->actor);
globalCtx->envCtx.fillScreen = false;
}
if (this->lensFlareTimer != 0) {
this->lensFlareTimer--;
this->lensFlareOn = true;
Math_ApproachF(&this->lensFlareScale, 40.0f, 0.3f, 10.0f);
} else {
Math_ApproachZeroF(&this->lensFlareScale, 1.0f, 5.0f);
if (this->lensFlareScale == 0.0f) {
this->lensFlareOn = false;
}
}
gCustomLensFlareOn = this->lensFlareOn;
gCustomLensFlarePos = this->actor.world.pos;
gLensFlareScale = this->lensFlareScale;
gLensFlareColorIntensity = 10.0f;
gLensFlareScreenFillAlpha = 0;
}
void EnFhgFire_SpearLight(EnFhgFire* this, GlobalContext* globalCtx) {
BossGanondrof* bossGnd;
s16 i;
osSyncPrintf("yari hikari 1\n");
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 = bossGnd->spearTip;
this->actor.shape.rot.z += (s16)(Rand_ZeroOne() * 0x4E20) + 0x4000;
osSyncPrintf("yari hikari 2\n");
if (this->work[FHGFIRE_FIRE_MODE] == FHGFIRE_LIGHT_GREEN) {
Vec3f ballPos;
Vec3f ballVel = { 0.0f, 0.0f, 0.0f };
Vec3f ballAccel = { 0.0f, 0.0f, 0.0f };
osSyncPrintf("FLASH !!\n");
for (i = 0; i < 2; i++) {
ballPos.x = Rand_CenteredFloat(20.0f) + this->actor.world.pos.x;
ballPos.y = Rand_CenteredFloat(20.0f) + this->actor.world.pos.y;
ballPos.z = Rand_CenteredFloat(20.0f) + this->actor.world.pos.z;
ballAccel.y = -0.08f;
EffectSsFhgFlash_SpawnLightBall(globalCtx, &ballPos, &ballVel, &ballAccel,
(s16)(Rand_ZeroOne() * 80.0f) + 150, FHGFLASH_LIGHTBALL_GREEN);
}
}
if (this->work[FHGFIRE_TIMER] == 0) {
Actor_Kill(&this->actor);
}
}
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 = GET_PLAYER(globalCtx);
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 EnFhgFire_PhantomWarp(EnFhgFire* this, GlobalContext* globalCtx) {
EnfHG* horse = (EnfHG*)this->actor.parent;
f32 scrollDirection;
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 == 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->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->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->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 = (EnFhgFire*)thisx;
this->work[FHGFIRE_VARIANCE_TIMER]++;
if (this->work[FHGFIRE_TIMER] != 0) {
this->work[FHGFIRE_TIMER]--;
}
if (this->work[FHGFIRE_FX_TIMER] != 0) {
this->work[FHGFIRE_FX_TIMER]--;
}
this->updateFunc(this, globalCtx);
}
static void* sDustTextures[] = {
gDust1Tex, gDust2Tex, gDust3Tex, gDust4Tex, gDust5Tex, gDust6Tex, gDust7Tex, gDust8Tex,
};
void EnFhgFire_Draw(Actor* thisx, GlobalContext* globalCtx) {
s32 pad;
EnFhgFire* this = (EnFhgFire*)thisx;
OPEN_DISPS(globalCtx->state.gfxCtx);
if (this->actor.params == FHGFIRE_LIGHTNING_BURST) {
func_80093D84(globalCtx->state.gfxCtx);
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),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
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");
Matrix_ReplaceRotation(&globalCtx->billboardMtxF);
func_80093D84(globalCtx->state.gfxCtx);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->fwork[FHGFIRE_ALPHA]);
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((this->actor.shape.rot.z / (f32)0x8000) * 3.1416f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
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->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),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPSegment(POLY_XLU_DISP++, 0x08,
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, MTXMODE_APPLY);
func_80093D84(globalCtx->state.gfxCtx);
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),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gSPDisplayList(POLY_XLU_DISP++, gPhantomLightningDL);
osSyncPrintf("FF DRAW 2\n");
}
CLOSE_DISPS(globalCtx->state.gfxCtx);
}