mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-08-13 17:03:47 -04:00
a5df9dddf0
* First batch some overlay
* Almost all overlay
* effect & gamestate
* kaleido stuffs
* more overlay
* more left over from code folder
* remaining hardcoded line and file
* Open & Close _DISP __FILE__ & __LINE__ clean up
* Some if (1) {} remove
* LOG_xxxx __FILE__ , __LINE__ cleaned
* ASSERT macro __FILE__ __LINE__
* mtx without line/file in functions
* " if (1) {} " & "if (0) {}" and tab/white place
* LogUtils as macro
* GameState_, GameAlloc_, SystemArena_ & ZeldaArena_
* Revert "GameState_, GameAlloc_, SystemArena_ & ZeldaArena_"
This reverts commit 0d85caaf7e
.
* Like last commit but as macro
* Fix matrix not using macros
* use function not macro
* DebugArena_* functions
GameAlloc_MallocDebug
BgCheck_PosErrorCheck as macros
removed issues with ; in macro file
758 lines
32 KiB
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);
|
|
}
|