mirror of
https://github.com/zeldaret/oot.git
synced 2025-08-06 06:10:21 +00:00
En_Fz Freezard (#519)
* En_Fr 47 of 48 func decomped * En_Fz Frezzard 26/36 func decompiled * En_Fz Freezard fully decomped * revert EnFr to independently submit EnFz * EnFz fully decompiled * more cleanup * pr feedback * pr feedback * petries review * asm * review Co-authored-by: Fig02 <fig02srl@gmail.com>
This commit is contained in:
parent
c2b5ae3ed2
commit
9f3e8cbf97
42 changed files with 836 additions and 2226 deletions
|
@ -9,12 +9,47 @@ void EnFz_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|||
void EnFz_Update(Actor* thisx, GlobalContext* globalCtx);
|
||||
void EnFz_Draw(Actor* thisx, GlobalContext* globalCtx);
|
||||
|
||||
extern UNK_TYPE D_060030A0;
|
||||
extern UNK_TYPE D_060030A8;
|
||||
extern UNK_TYPE D_06003158;
|
||||
extern UNK_TYPE D_06003160;
|
||||
void EnFz_UpdateTargetPos(EnFz* this, GlobalContext* globalCtx);
|
||||
|
||||
// Stationary Freezard
|
||||
void EnFz_SetupBlowSmokeStationary(EnFz* this);
|
||||
void EnFz_BlowSmokeStationary(EnFz* this, GlobalContext* globalCtx);
|
||||
|
||||
// Moving Freezard that can vanish and reappear
|
||||
void EnFz_Wait(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_SetupAppear(EnFz* this);
|
||||
void EnFz_Appear(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_SetupAimForMove(EnFz* this);
|
||||
void EnFz_AimForMove(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_SetupMoveTowardsPlayer(EnFz* this);
|
||||
void EnFz_MoveTowardsPlayer(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_SetupAimForFreeze(EnFz* this);
|
||||
void EnFz_AimForFreeze(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_SetupBlowSmoke(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_BlowSmoke(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_SetupDisappear(EnFz* this);
|
||||
void EnFz_Disappear(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_SetupWait(EnFz* this);
|
||||
|
||||
// Killed with fire source
|
||||
void EnFz_SetupMelt(EnFz* this);
|
||||
void EnFz_Melt(EnFz* this, GlobalContext* globalCtx);
|
||||
|
||||
// Death
|
||||
void EnFz_SetupDespawn(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_Despawn(EnFz* this, GlobalContext* globalCtx);
|
||||
|
||||
// Ice Smoke Effects
|
||||
void EnFz_SpawnIceSmokeNoFreeze(EnFz* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, f32 xyScale);
|
||||
void EnFz_SpawnIceSmokeFreeze(EnFz* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, f32 xyScale, f32 xyScaleTarget,
|
||||
s16 primAlpha, u8 isTimerMod8);
|
||||
void EnFz_UpdateIceSmoke(EnFz* this, GlobalContext* globalCtx);
|
||||
void EnFz_DrawIceSmoke(EnFz* this, GlobalContext* globalCtx);
|
||||
|
||||
// Same effects as "z_eff_ss_ice_smoke.h"
|
||||
extern Gfx* D_060030A0[];
|
||||
extern Gfx* D_06003158[];
|
||||
|
||||
/*
|
||||
const ActorInit En_Fz_InitVars = {
|
||||
ACTOR_EN_FZ,
|
||||
ACTORCAT_ENEMY,
|
||||
|
@ -27,7 +62,7 @@ const ActorInit En_Fz_InitVars = {
|
|||
(ActorFunc)EnFz_Draw,
|
||||
};
|
||||
|
||||
static ColliderCylinderInitType1 sCylinderInit = {
|
||||
static ColliderCylinderInitType1 sCylinderInit1 = {
|
||||
{
|
||||
COLTYPE_NONE,
|
||||
AT_ON | AT_TYPE_ENEMY,
|
||||
|
@ -46,7 +81,7 @@ static ColliderCylinderInitType1 sCylinderInit = {
|
|||
{ 30, 80, 0, { 0, 0, 0 } },
|
||||
};
|
||||
|
||||
static ColliderCylinderInitType1 sCylinderInit = {
|
||||
static ColliderCylinderInitType1 sCylinderInit2 = {
|
||||
{
|
||||
COLTYPE_METAL,
|
||||
AT_NONE,
|
||||
|
@ -65,7 +100,7 @@ static ColliderCylinderInitType1 sCylinderInit = {
|
|||
{ 35, 80, 0, { 0, 0, 0 } },
|
||||
};
|
||||
|
||||
static ColliderCylinderInitType1 sCylinderInit = {
|
||||
static ColliderCylinderInitType1 sCylinderInit3 = {
|
||||
{
|
||||
COLTYPE_NONE,
|
||||
AT_ON | AT_TYPE_ENEMY,
|
||||
|
@ -83,73 +118,779 @@ static ColliderCylinderInitType1 sCylinderInit = {
|
|||
},
|
||||
{ 20, 30, -15, { 0, 0, 0 } },
|
||||
};
|
||||
*/
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/EnFz_Init.s")
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/EnFz_Destroy.s")
|
||||
DamageTable sDamageTable = {
|
||||
/* Deku nut */ DMG_ENTRY(0, 0x0),
|
||||
/* Deku stick */ DMG_ENTRY(0, 0xF),
|
||||
/* Slingshot */ DMG_ENTRY(0, 0xF),
|
||||
/* Explosive */ DMG_ENTRY(2, 0xF),
|
||||
/* Boomerang */ DMG_ENTRY(0, 0xF),
|
||||
/* Normal arrow */ DMG_ENTRY(0, 0xF),
|
||||
/* Hammer swing */ DMG_ENTRY(2, 0xF),
|
||||
/* Hookshot */ DMG_ENTRY(2, 0xF),
|
||||
/* Kokiri sword */ DMG_ENTRY(0, 0xF),
|
||||
/* Master sword */ DMG_ENTRY(2, 0xF),
|
||||
/* Giant's Knife */ DMG_ENTRY(4, 0xF),
|
||||
/* Fire arrow */ DMG_ENTRY(4, 0x2),
|
||||
/* Ice arrow */ DMG_ENTRY(0, 0xF),
|
||||
/* Light arrow */ DMG_ENTRY(0, 0xF),
|
||||
/* Unk arrow 1 */ DMG_ENTRY(0, 0xF),
|
||||
/* Unk arrow 2 */ DMG_ENTRY(0, 0xF),
|
||||
/* Unk arrow 3 */ DMG_ENTRY(0, 0xF),
|
||||
/* Fire magic */ DMG_ENTRY(4, 0x2),
|
||||
/* Ice magic */ DMG_ENTRY(0, 0x0),
|
||||
/* Light magic */ DMG_ENTRY(0, 0x0),
|
||||
/* Shield */ DMG_ENTRY(0, 0x0),
|
||||
/* Mirror Ray */ DMG_ENTRY(0, 0x0),
|
||||
/* Kokiri spin */ DMG_ENTRY(0, 0xF),
|
||||
/* Giant spin */ DMG_ENTRY(4, 0xF),
|
||||
/* Master spin */ DMG_ENTRY(2, 0xF),
|
||||
/* Kokiri jump */ DMG_ENTRY(0, 0xF),
|
||||
/* Giant jump */ DMG_ENTRY(8, 0xF),
|
||||
/* Master jump */ DMG_ENTRY(4, 0xF),
|
||||
/* Unknown 1 */ DMG_ENTRY(0, 0x0),
|
||||
/* Unblockable */ DMG_ENTRY(0, 0x0),
|
||||
/* Hammer jump */ DMG_ENTRY(0, 0x0),
|
||||
/* Unknown 2 */ DMG_ENTRY(0, 0x0),
|
||||
};
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A1FF8C.s")
|
||||
static InitChainEntry sInitChain[] = {
|
||||
ICHAIN_S8(naviEnemyId, 59, ICHAIN_CONTINUE),
|
||||
ICHAIN_U8(targetMode, 2, ICHAIN_CONTINUE),
|
||||
ICHAIN_F32(targetArrowOffset, 30, ICHAIN_STOP),
|
||||
};
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A200B0.s")
|
||||
void EnFz_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnFz* this = THIS;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20100.s")
|
||||
Actor_ProcessInitChain(&this->actor, sInitChain);
|
||||
this->actor.colChkInfo.damageTable = &sDamageTable;
|
||||
this->actor.colChkInfo.health = 6;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A202FC.s")
|
||||
Collider_InitCylinder(globalCtx, &this->collider1);
|
||||
Collider_SetCylinderType1(globalCtx, &this->collider1, &this->actor, &sCylinderInit1);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A203DC.s")
|
||||
Collider_InitCylinder(globalCtx, &this->collider2);
|
||||
Collider_SetCylinderType1(globalCtx, &this->collider2, &this->actor, &sCylinderInit2);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A204A0.s")
|
||||
Collider_InitCylinder(globalCtx, &this->collider3);
|
||||
Collider_SetCylinderType1(globalCtx, &this->collider3, &this->actor, &sCylinderInit3);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20704.s")
|
||||
Actor_SetScale(&this->actor, 0.008f);
|
||||
this->actor.colChkInfo.mass = MASS_IMMOVABLE;
|
||||
this->actor.flags &= ~1;
|
||||
this->unusedTimer1 = 0;
|
||||
this->unusedCounter = 0;
|
||||
this->updateBgInfo = true;
|
||||
this->isMoving = false;
|
||||
this->isFreezing = false;
|
||||
this->isActive = true;
|
||||
this->isDespawning = false;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
this->actor.gravity = 0.0f;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->posOrigin.y = this->actor.world.pos.y;
|
||||
this->iceSmokeFreezingSpawnHeight = this->actor.world.pos.y;
|
||||
this->posOrigin.x = this->actor.world.pos.x;
|
||||
this->posOrigin.z = this->actor.world.pos.z;
|
||||
this->unusedFloat = 135.0f;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20748.s")
|
||||
if (this->actor.params < 0) {
|
||||
this->envAlpha = 0;
|
||||
this->actor.scale.y = 0.0f;
|
||||
EnFz_SetupWait(this);
|
||||
} else {
|
||||
this->envAlpha = 255;
|
||||
EnFz_SetupBlowSmokeStationary(this);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20774.s")
|
||||
EnFz_UpdateTargetPos(this, globalCtx);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A207F4.s")
|
||||
void EnFz_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnFz* this = THIS;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20830.s")
|
||||
Collider_DestroyCylinder(globalCtx, &this->collider1);
|
||||
Collider_DestroyCylinder(globalCtx, &this->collider2);
|
||||
Collider_DestroyCylinder(globalCtx, &this->collider3);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20880.s")
|
||||
void EnFz_UpdateTargetPos(EnFz* this, GlobalContext* globalCtx) {
|
||||
Vec3f pos;
|
||||
Vec3f hitPos;
|
||||
Vec3f vec1;
|
||||
s32 bgId;
|
||||
CollisionPoly* hitPoly;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A208A8.s")
|
||||
pos.x = this->actor.world.pos.x;
|
||||
pos.y = this->actor.world.pos.y + 20.0f;
|
||||
pos.z = this->actor.world.pos.z;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20938.s")
|
||||
Matrix_Translate(pos.x, pos.y, pos.z, MTXMODE_NEW);
|
||||
Matrix_RotateRPY(this->actor.shape.rot.x, this->actor.shape.rot.y, this->actor.shape.rot.z, MTXMODE_APPLY);
|
||||
vec1.x = vec1.y = 0.0f;
|
||||
vec1.z = 220.0f;
|
||||
Matrix_MultVec3f(&vec1, &this->wallHitPos);
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20978.s")
|
||||
if (BgCheck_EntityLineTest1(&globalCtx->colCtx, &pos, &this->wallHitPos, &hitPos, &hitPoly, true, false, false,
|
||||
true, &bgId)) {
|
||||
Math_Vec3f_Copy(&this->wallHitPos, &hitPos);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A209B4.s")
|
||||
pos.x = this->actor.world.pos.x - this->wallHitPos.x;
|
||||
pos.z = this->actor.world.pos.z - this->wallHitPos.z;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A209E4.s")
|
||||
this->distToTargetSq = SQ(pos.x) + SQ(pos.z);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20A20.s")
|
||||
s32 EnFz_ReachedTarget(EnFz* this, Vec3f* vec) {
|
||||
if (this->distToTargetSq <= (SQ(this->actor.world.pos.x - vec->x) + SQ(this->actor.world.pos.z - vec->z))) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20A4C.s")
|
||||
void EnFz_Damaged(EnFz* this, GlobalContext* globalCtx, Vec3f* vec, s32 numEffects, f32 unkFloat) {
|
||||
s32 i;
|
||||
Vec3f pos;
|
||||
Vec3f vel;
|
||||
Vec3f accel;
|
||||
Color_RGBA8 primColor;
|
||||
Color_RGBA8 envColor;
|
||||
f32 scale;
|
||||
s32 life;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20A88.s")
|
||||
primColor.r = 155;
|
||||
primColor.g = 255;
|
||||
primColor.b = 255;
|
||||
primColor.a = 255;
|
||||
envColor.r = 200;
|
||||
envColor.g = 200;
|
||||
envColor.b = 200;
|
||||
accel.x = accel.z = 0.0f;
|
||||
accel.y = -1.0f;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20AC0.s")
|
||||
for (i = 0; i < numEffects; i++) {
|
||||
scale = Rand_CenteredFloat(0.3f) + 0.6f;
|
||||
life = (s32)Rand_CenteredFloat(5.0f) + 12;
|
||||
pos.x = Rand_CenteredFloat(unkFloat) + vec->x;
|
||||
pos.y = Rand_ZeroFloat(unkFloat) + vec->y;
|
||||
pos.z = Rand_CenteredFloat(unkFloat) + vec->z;
|
||||
vel.x = Rand_CenteredFloat(10.0f);
|
||||
vel.y = Rand_ZeroFloat(10.0f) + 2.0f;
|
||||
vel.z = Rand_CenteredFloat(10.0f);
|
||||
EffectSsEnIce_Spawn(globalCtx, &pos, scale, &vel, &accel, &primColor, &envColor, life);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20CAC.s")
|
||||
CollisionCheck_SpawnShieldParticles(globalCtx, vec);
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20D4C.s")
|
||||
void EnFz_SpawnIceSmokeHiddenState(EnFz* this) {
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20D7C.s")
|
||||
// Fully grown
|
||||
void EnFz_SpawnIceSmokeGrowingState(EnFz* this) {
|
||||
Vec3f pos;
|
||||
Vec3f velocity;
|
||||
Vec3f accel;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20DBC.s")
|
||||
if ((this->counter % 16) == 0) {
|
||||
pos.x = Rand_CenteredFloat(40.0f) + this->actor.world.pos.x;
|
||||
pos.y = Rand_CenteredFloat(40.0f) + this->actor.world.pos.y + 30.0f;
|
||||
pos.z = Rand_CenteredFloat(40.0f) + this->actor.world.pos.z;
|
||||
accel.x = accel.z = 0.0f;
|
||||
accel.y = 0.1f;
|
||||
velocity.x = velocity.y = velocity.z = 0.0f;
|
||||
EnFz_SpawnIceSmokeNoFreeze(this, &pos, &velocity, &accel, Rand_ZeroFloat(7.5f) + 15.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20E84.s")
|
||||
// (2) Growing or Shrinking to/from hiding or (3) melting from fire
|
||||
void EnFz_SpawnIceSmokeActiveState(EnFz* this) {
|
||||
Vec3f pos;
|
||||
Vec3f velocity;
|
||||
Vec3f accel;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A20EC4.s")
|
||||
if ((this->counter % 4) == 0) {
|
||||
pos.x = Rand_CenteredFloat(40.0f) + this->actor.world.pos.x;
|
||||
pos.y = this->iceSmokeFreezingSpawnHeight;
|
||||
pos.z = Rand_CenteredFloat(40.0f) + this->actor.world.pos.z;
|
||||
accel.x = accel.z = 0.0f;
|
||||
accel.y = 0.1f;
|
||||
velocity.x = velocity.y = velocity.z = 0.0f;
|
||||
EnFz_SpawnIceSmokeNoFreeze(this, &pos, &velocity, &accel, Rand_ZeroFloat(7.5f) + 15.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/EnFz_Update.s")
|
||||
void EnFz_ApplyDamage(EnFz* this, GlobalContext* globalCtx) {
|
||||
Vec3f vec;
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/EnFz_Draw.s")
|
||||
if (this->isMoving && ((this->actor.bgCheckFlags & 8) ||
|
||||
(func_800339B8(&this->actor, globalCtx, 60.0f, this->actor.world.rot.y) == 0))) {
|
||||
this->actor.bgCheckFlags &= ~8;
|
||||
this->isMoving = false;
|
||||
this->speedXZ = 0.0f;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A2145C.s")
|
||||
if (this->isFreezing) {
|
||||
if ((this->actor.params < 0) && (this->collider1.base.atFlags & 2)) {
|
||||
this->isMoving = false;
|
||||
this->collider1.base.acFlags &= ~2;
|
||||
this->actor.speedXZ = this->speedXZ = 0.0f;
|
||||
this->timer = 10;
|
||||
EnFz_SetupDisappear(this);
|
||||
} else if (this->collider2.base.acFlags & 0x80) {
|
||||
this->collider2.base.acFlags &= ~0x80;
|
||||
this->collider1.base.acFlags &= ~2;
|
||||
} else if (this->collider1.base.acFlags & 2) {
|
||||
this->collider1.base.acFlags &= ~2;
|
||||
if (this->actor.colChkInfo.damageEffect != 2) {
|
||||
if (this->actor.colChkInfo.damageEffect == 0xF) {
|
||||
Actor_ApplyDamage(&this->actor);
|
||||
func_8003426C(&this->actor, 0x4000, 0xFF, 0x2000, 8);
|
||||
if (this->actor.colChkInfo.health) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FREEZAD_DAMAGE);
|
||||
vec.x = this->actor.world.pos.x;
|
||||
vec.y = this->actor.world.pos.y;
|
||||
vec.z = this->actor.world.pos.z;
|
||||
EnFz_Damaged(this, globalCtx, &vec, 10, 0.0f);
|
||||
this->unusedCounter++;
|
||||
} else {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FREEZAD_DEAD);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EV_ICE_BROKEN);
|
||||
vec.x = this->actor.world.pos.x;
|
||||
vec.y = this->actor.world.pos.y;
|
||||
vec.z = this->actor.world.pos.z;
|
||||
EnFz_Damaged(this, globalCtx, &vec, 30, 10.0f);
|
||||
EnFz_SetupDespawn(this, globalCtx);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Actor_ApplyDamage(&this->actor);
|
||||
func_8003426C(&this->actor, 0x4000, 0xFF, 0x2000, 8);
|
||||
if (this->actor.colChkInfo.health == 0) {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FREEZAD_DEAD);
|
||||
EnFz_SetupMelt(this);
|
||||
} else {
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FREEZAD_DAMAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A21500.s")
|
||||
void EnFz_SetYawTowardsPlayer(EnFz* this) {
|
||||
Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 10, 2000, 0);
|
||||
this->actor.world.rot.y = this->actor.shape.rot.y;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A215BC.s")
|
||||
void EnFz_SetupDisappear(EnFz* this) {
|
||||
this->state = 2;
|
||||
this->isFreezing = false;
|
||||
this->actor.flags &= ~1;
|
||||
this->actionFunc = EnFz_Disappear;
|
||||
}
|
||||
|
||||
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Fz/func_80A218A8.s")
|
||||
void EnFz_Disappear(EnFz* this, GlobalContext* globalCtx) {
|
||||
this->envAlpha -= 16;
|
||||
|
||||
if (this->envAlpha > 255) {
|
||||
this->envAlpha = 0;
|
||||
}
|
||||
|
||||
if (Math_SmoothStepToF(&this->actor.scale.y, 0.0f, 1.0f, 0.0005f, 0) == 0.0f) {
|
||||
EnFz_SetupWait(this);
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SetupWait(EnFz* this) {
|
||||
this->state = 0;
|
||||
this->unusedNum2 = 0;
|
||||
this->unusedNum1 = 0;
|
||||
this->timer = 100;
|
||||
this->actionFunc = EnFz_Wait;
|
||||
this->actor.world.pos.x = this->posOrigin.x;
|
||||
this->actor.world.pos.y = this->posOrigin.y;
|
||||
this->actor.world.pos.z = this->posOrigin.z;
|
||||
}
|
||||
|
||||
void EnFz_Wait(EnFz* this, GlobalContext* globalCtx) {
|
||||
if ((this->timer == 0) && (this->actor.xzDistToPlayer < 400.0f)) {
|
||||
EnFz_SetupAppear(this);
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SetupAppear(EnFz* this) {
|
||||
this->state = 2;
|
||||
this->timer = 20;
|
||||
this->unusedNum2 = 4000;
|
||||
this->actionFunc = EnFz_Appear;
|
||||
}
|
||||
|
||||
void EnFz_Appear(EnFz* this, GlobalContext* globalCtx) {
|
||||
if (this->timer == 0) {
|
||||
this->envAlpha += 8;
|
||||
if (this->envAlpha > 255) {
|
||||
this->envAlpha = 255;
|
||||
}
|
||||
|
||||
if (Math_SmoothStepToF(&this->actor.scale.y, 0.008f, 1.0f, 0.0005f, 0.0f) == 0.0f) {
|
||||
EnFz_SetupAimForMove(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SetupAimForMove(EnFz* this) {
|
||||
this->state = 1;
|
||||
this->timer = 40;
|
||||
this->updateBgInfo = true;
|
||||
this->isFreezing = true;
|
||||
this->actor.flags |= 1;
|
||||
this->actionFunc = EnFz_AimForMove;
|
||||
this->actor.gravity = -1.0f;
|
||||
}
|
||||
|
||||
void EnFz_AimForMove(EnFz* this, GlobalContext* globalCtx) {
|
||||
EnFz_SetYawTowardsPlayer(this);
|
||||
|
||||
if (this->timer == 0) {
|
||||
EnFz_SetupMoveTowardsPlayer(this);
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SetupMoveTowardsPlayer(EnFz* this) {
|
||||
this->state = 1;
|
||||
this->isMoving = true;
|
||||
this->timer = 100;
|
||||
this->actionFunc = EnFz_MoveTowardsPlayer;
|
||||
this->speedXZ = 4.0f;
|
||||
}
|
||||
|
||||
void EnFz_MoveTowardsPlayer(EnFz* this, GlobalContext* globalCtx) {
|
||||
if ((this->timer == 0) || !this->isMoving) {
|
||||
EnFz_SetupAimForFreeze(this);
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SetupAimForFreeze(EnFz* this) {
|
||||
this->state = 1;
|
||||
this->timer = 40;
|
||||
this->actionFunc = EnFz_AimForFreeze;
|
||||
this->speedXZ = 0.0f;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
}
|
||||
|
||||
void EnFz_AimForFreeze(EnFz* this, GlobalContext* globalCtx) {
|
||||
EnFz_SetYawTowardsPlayer(this);
|
||||
|
||||
if (this->timer == 0) {
|
||||
EnFz_SetupBlowSmoke(this, globalCtx);
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SetupBlowSmoke(EnFz* this, GlobalContext* globalCtx) {
|
||||
this->state = 1;
|
||||
this->timer = 80;
|
||||
this->actionFunc = EnFz_BlowSmoke;
|
||||
EnFz_UpdateTargetPos(this, globalCtx);
|
||||
}
|
||||
|
||||
void EnFz_BlowSmoke(EnFz* this, GlobalContext* globalCtx) {
|
||||
Vec3f vec1;
|
||||
Vec3f pos;
|
||||
Vec3f velocity;
|
||||
Vec3f accel;
|
||||
u8 isTimerMod8;
|
||||
s16 primAlpha;
|
||||
|
||||
if (this->timer == 0) {
|
||||
EnFz_SetupDisappear(this);
|
||||
} else if (this->timer >= 11) {
|
||||
isTimerMod8 = false;
|
||||
primAlpha = 150;
|
||||
func_8002F974(&this->actor, NA_SE_EN_FREEZAD_BREATH - SFX_FLAG);
|
||||
|
||||
if ((this->timer - 10) < 16) { // t < 26
|
||||
primAlpha = (this->timer * 10) - 100;
|
||||
}
|
||||
|
||||
accel.x = accel.z = 0.0f;
|
||||
accel.y = 0.6f;
|
||||
|
||||
pos.x = this->actor.world.pos.x;
|
||||
pos.y = this->actor.world.pos.y + 20.0f;
|
||||
pos.z = this->actor.world.pos.z;
|
||||
|
||||
Matrix_RotateY((this->actor.shape.rot.y / (f32)0x8000) * M_PI, MTXMODE_NEW);
|
||||
|
||||
vec1.x = 0.0f;
|
||||
vec1.y = -2.0f;
|
||||
vec1.z = 20.0f; // xz velocity
|
||||
|
||||
Matrix_MultVec3f(&vec1, &velocity);
|
||||
|
||||
if ((this->timer % 8) == 0) {
|
||||
isTimerMod8 = true;
|
||||
}
|
||||
|
||||
EnFz_SpawnIceSmokeFreeze(this, &pos, &velocity, &accel, 2.0f, 25.0f, primAlpha, isTimerMod8);
|
||||
|
||||
pos.x += (velocity.x * 0.5f);
|
||||
pos.y += (velocity.y * 0.5f);
|
||||
pos.z += (velocity.z * 0.5f);
|
||||
|
||||
EnFz_SpawnIceSmokeFreeze(this, &pos, &velocity, &accel, 2.0f, 25.0f, primAlpha, false);
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SetupDespawn(EnFz* this, GlobalContext* globalCtx) {
|
||||
this->state = 0;
|
||||
this->updateBgInfo = true;
|
||||
this->isFreezing = false;
|
||||
this->isDespawning = true;
|
||||
this->actor.flags &= ~1;
|
||||
this->isActive = false;
|
||||
this->timer = 60;
|
||||
this->speedXZ = 0.0f;
|
||||
this->actor.gravity = 0.0f;
|
||||
this->actor.velocity.y = 0.0f;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
Actor_ChangeCategory(globalCtx, &globalCtx->actorCtx, &this->actor, ACTORCAT_PROP);
|
||||
Item_DropCollectibleRandom(globalCtx, &this->actor, &this->actor.world.pos, 0x60);
|
||||
this->actionFunc = EnFz_Despawn;
|
||||
}
|
||||
|
||||
void EnFz_Despawn(EnFz* this, GlobalContext* globalCtx) {
|
||||
if (this->timer == 0) {
|
||||
Actor_Kill(&this->actor);
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SetupMelt(EnFz* this) {
|
||||
this->state = 3;
|
||||
this->isFreezing = false;
|
||||
this->isDespawning = true;
|
||||
this->actor.flags &= ~1;
|
||||
this->actionFunc = EnFz_Melt;
|
||||
this->actor.speedXZ = 0.0f;
|
||||
this->speedXZ = 0.0f;
|
||||
}
|
||||
|
||||
void EnFz_Melt(EnFz* this, GlobalContext* globalCtx) {
|
||||
Math_StepToF(&this->actor.scale.y, 0.0006f, 0.0002f);
|
||||
|
||||
if (this->actor.scale.y < 0.006f) {
|
||||
this->actor.scale.x += 0.0004f;
|
||||
this->actor.scale.z += 0.0004f;
|
||||
}
|
||||
|
||||
if (this->actor.scale.y < 0.004f) {
|
||||
this->envAlpha -= 8;
|
||||
if (this->envAlpha > 255) {
|
||||
this->envAlpha = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (this->envAlpha == 0) {
|
||||
EnFz_SetupDespawn(this, globalCtx);
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SetupBlowSmokeStationary(EnFz* this) {
|
||||
this->state = 1;
|
||||
this->timer = 40;
|
||||
this->updateBgInfo = true;
|
||||
this->isFreezing = true;
|
||||
this->actor.flags |= 1;
|
||||
this->actionFunc = EnFz_BlowSmokeStationary;
|
||||
this->actor.gravity = -1.0f;
|
||||
}
|
||||
|
||||
void EnFz_BlowSmokeStationary(EnFz* this, GlobalContext* globalCtx) {
|
||||
Vec3f vec1;
|
||||
Vec3f pos;
|
||||
Vec3f velocity;
|
||||
Vec3f accel;
|
||||
u8 isTimerMod8;
|
||||
s16 primAlpha;
|
||||
|
||||
if (this->counter & 0xC0) {
|
||||
EnFz_SetYawTowardsPlayer(this);
|
||||
EnFz_UpdateTargetPos(this, globalCtx);
|
||||
} else {
|
||||
isTimerMod8 = false;
|
||||
primAlpha = 150;
|
||||
func_8002F974(&this->actor, NA_SE_EN_FREEZAD_BREATH - SFX_FLAG);
|
||||
|
||||
if ((this->counter & 0x3F) >= 48) {
|
||||
primAlpha = 630 - ((this->counter & 0x3F) * 10);
|
||||
}
|
||||
|
||||
accel.x = accel.z = 0.0f;
|
||||
accel.y = 0.6f;
|
||||
|
||||
pos.x = this->actor.world.pos.x;
|
||||
pos.y = this->actor.world.pos.y + 20.0f;
|
||||
pos.z = this->actor.world.pos.z;
|
||||
|
||||
Matrix_RotateY((this->actor.shape.rot.y / (f32)0x8000) * M_PI, MTXMODE_NEW);
|
||||
|
||||
vec1.x = 0.0f;
|
||||
vec1.y = -2.0f;
|
||||
vec1.z = 20.0f;
|
||||
|
||||
Matrix_MultVec3f(&vec1, &velocity);
|
||||
|
||||
if ((this->counter % 8) == 0) {
|
||||
isTimerMod8 = true;
|
||||
}
|
||||
|
||||
EnFz_SpawnIceSmokeFreeze(this, &pos, &velocity, &accel, 2.0f, 25.0f, primAlpha, isTimerMod8);
|
||||
|
||||
pos.x += (velocity.x * 0.5f);
|
||||
pos.y += (velocity.y * 0.5f);
|
||||
pos.z += (velocity.z * 0.5f);
|
||||
|
||||
EnFz_SpawnIceSmokeFreeze(this, &pos, &velocity, &accel, 2.0f, 25.0f, primAlpha, false);
|
||||
}
|
||||
}
|
||||
|
||||
static EnFzSpawnIceSmokeFunc iceSmokeSpawnFuncs[] = {
|
||||
EnFz_SpawnIceSmokeHiddenState,
|
||||
EnFz_SpawnIceSmokeGrowingState,
|
||||
EnFz_SpawnIceSmokeActiveState,
|
||||
EnFz_SpawnIceSmokeActiveState,
|
||||
};
|
||||
|
||||
void EnFz_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||
EnFz* this = THIS;
|
||||
s32 pad;
|
||||
|
||||
this->counter++;
|
||||
|
||||
if (this->unusedTimer1 != 0) {
|
||||
this->unusedTimer1--;
|
||||
}
|
||||
|
||||
if (this->timer != 0) {
|
||||
this->timer--;
|
||||
}
|
||||
|
||||
if (this->unusedTimer2 != 0) {
|
||||
this->unusedTimer2--;
|
||||
}
|
||||
|
||||
Actor_SetFocus(&this->actor, 50.0f);
|
||||
EnFz_ApplyDamage(this, globalCtx);
|
||||
this->actionFunc(this, globalCtx);
|
||||
if (this->isDespawning == false) {
|
||||
Collider_UpdateCylinder(&this->actor, &this->collider1);
|
||||
Collider_UpdateCylinder(&this->actor, &this->collider2);
|
||||
if (this->isFreezing) {
|
||||
if (this->actor.colorFilterTimer == 0) {
|
||||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider1.base);
|
||||
CollisionCheck_SetAC(globalCtx, &globalCtx->colChkCtx, &this->collider2.base);
|
||||
}
|
||||
CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collider1.base);
|
||||
}
|
||||
}
|
||||
|
||||
Math_StepToF(&this->actor.speedXZ, this->speedXZ, 0.2f);
|
||||
Actor_MoveForward(&this->actor);
|
||||
|
||||
if (this->updateBgInfo) {
|
||||
Actor_UpdateBgCheckInfo(globalCtx, &this->actor, 20.0f, 20.0f, 20.0f, 5);
|
||||
}
|
||||
|
||||
iceSmokeSpawnFuncs[this->state](this);
|
||||
EnFz_UpdateIceSmoke(this, globalCtx);
|
||||
}
|
||||
|
||||
void EnFz_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||
static Gfx* displayLists[] = {
|
||||
0x06001130, // Body fully intact (5 or 6 health)
|
||||
0x060021A0, // Top right horn chipped off (from Freezards perspective) (3 or 4 health)
|
||||
0x06002CA0, // Entire head chipped off (1 or 2 health)
|
||||
};
|
||||
EnFz* this = THIS;
|
||||
s32 pad;
|
||||
s32 index;
|
||||
|
||||
index = (6 - this->actor.colChkInfo.health) >> 1;
|
||||
|
||||
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_fz.c", 1167);
|
||||
|
||||
if (1) {}
|
||||
|
||||
if (this->actor.colChkInfo.health == 0) {
|
||||
index = 2;
|
||||
}
|
||||
|
||||
if (this->isActive) {
|
||||
func_8002ED80(&this->actor, globalCtx, 0);
|
||||
func_80093D84(globalCtx->state.gfxCtx);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08,
|
||||
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 0, globalCtx->state.frames & 0x7F, 32, 32, 1, 0,
|
||||
(2 * globalCtx->state.frames) & 0x7F, 32, 32));
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_fz.c", 1183),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gDPSetCombineLERP(POLY_XLU_DISP++, TEXEL1, PRIMITIVE, PRIM_LOD_FRAC, TEXEL0, TEXEL1, TEXEL0, PRIMITIVE, TEXEL0,
|
||||
PRIMITIVE, ENVIRONMENT, COMBINED, ENVIRONMENT, COMBINED, 0, ENVIRONMENT, 0);
|
||||
gDPSetPrimColor(POLY_XLU_DISP++, 0, 128, 155, 255, 255, 255);
|
||||
gDPSetEnvColor(POLY_XLU_DISP++, 200, 200, 200, this->envAlpha);
|
||||
gSPDisplayList(POLY_XLU_DISP++, displayLists[index]);
|
||||
}
|
||||
|
||||
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_fz.c", 1200);
|
||||
EnFz_DrawIceSmoke(this, globalCtx);
|
||||
}
|
||||
|
||||
void EnFz_SpawnIceSmokeNoFreeze(EnFz* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, f32 xyScale) {
|
||||
EnFzEffectSsIceSmoke* iceSmoke = this->iceSmoke;
|
||||
s16 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(this->iceSmoke); i++) {
|
||||
if (iceSmoke->type == 0) {
|
||||
iceSmoke->type = 1;
|
||||
iceSmoke->pos = *pos;
|
||||
iceSmoke->velocity = *velocity;
|
||||
iceSmoke->accel = *accel;
|
||||
iceSmoke->primAlphaState = 0;
|
||||
iceSmoke->xyScale = xyScale / 1000.0f;
|
||||
iceSmoke->primAlpha = 0;
|
||||
iceSmoke->timer = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
iceSmoke++;
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_SpawnIceSmokeFreeze(EnFz* this, Vec3f* pos, Vec3f* velocity, Vec3f* accel, f32 xyScale, f32 xyScaleTarget,
|
||||
s16 primAlpha, u8 isTimerMod8) {
|
||||
EnFzEffectSsIceSmoke* iceSmoke = this->iceSmoke;
|
||||
s16 i;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(this->iceSmoke); i++) {
|
||||
if (iceSmoke->type == 0) {
|
||||
iceSmoke->type = 2;
|
||||
iceSmoke->pos = *pos;
|
||||
iceSmoke->velocity = *velocity;
|
||||
iceSmoke->accel = *accel;
|
||||
iceSmoke->primAlphaState = 0;
|
||||
iceSmoke->xyScale = xyScale / 1000.0f;
|
||||
iceSmoke->xyScaleTarget = xyScaleTarget / 1000.0f;
|
||||
iceSmoke->primAlpha = primAlpha;
|
||||
iceSmoke->timer = 0;
|
||||
iceSmoke->isTimerMod8 = isTimerMod8;
|
||||
break;
|
||||
}
|
||||
|
||||
iceSmoke++;
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_UpdateIceSmoke(EnFz* this, GlobalContext* globalCtx) {
|
||||
EnFzEffectSsIceSmoke* iceSmoke = this->iceSmoke;
|
||||
s16 i;
|
||||
Vec3f pos;
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(this->iceSmoke); i++) {
|
||||
if (iceSmoke->type) {
|
||||
iceSmoke->pos.x += iceSmoke->velocity.x;
|
||||
iceSmoke->pos.y += iceSmoke->velocity.y;
|
||||
iceSmoke->pos.z += iceSmoke->velocity.z;
|
||||
iceSmoke->timer++;
|
||||
iceSmoke->velocity.x += iceSmoke->accel.x;
|
||||
iceSmoke->velocity.y += iceSmoke->accel.y;
|
||||
iceSmoke->velocity.z += iceSmoke->accel.z;
|
||||
if (iceSmoke->type == 1) {
|
||||
if (iceSmoke->primAlphaState == 0) { // Becoming more opaque
|
||||
iceSmoke->primAlpha += 10;
|
||||
if (iceSmoke->primAlpha >= 100) {
|
||||
iceSmoke->primAlphaState++;
|
||||
}
|
||||
} else { // Becoming more transparent
|
||||
iceSmoke->primAlpha -= 3;
|
||||
if (iceSmoke->primAlpha <= 0) {
|
||||
iceSmoke->primAlpha = 0;
|
||||
iceSmoke->type = 0;
|
||||
}
|
||||
}
|
||||
} else if (iceSmoke->type == 2) { // Freezing
|
||||
Math_ApproachF(&iceSmoke->xyScale, iceSmoke->xyScaleTarget, 0.1f, iceSmoke->xyScaleTarget / 10.0f);
|
||||
if (iceSmoke->primAlphaState == 0) { // Becoming more opaque
|
||||
if (iceSmoke->timer >= 7) {
|
||||
iceSmoke->primAlphaState++;
|
||||
}
|
||||
} else { // Becoming more transparent, slows down
|
||||
iceSmoke->accel.y = 2.0f;
|
||||
iceSmoke->primAlpha -= 17;
|
||||
iceSmoke->velocity.x *= 0.75f;
|
||||
iceSmoke->velocity.z *= 0.75f;
|
||||
if (iceSmoke->primAlpha <= 0) {
|
||||
iceSmoke->primAlpha = 0;
|
||||
iceSmoke->type = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if ((this->unusedTimer2 == 0) && (iceSmoke->primAlpha >= 101) && iceSmoke->isTimerMod8) {
|
||||
this->collider3.dim.pos.x = (s16)iceSmoke->pos.x;
|
||||
this->collider3.dim.pos.y = (s16)iceSmoke->pos.y;
|
||||
this->collider3.dim.pos.z = (s16)iceSmoke->pos.z;
|
||||
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider3.base);
|
||||
}
|
||||
|
||||
pos.x = iceSmoke->pos.x;
|
||||
pos.y = iceSmoke->pos.y + 10.0f;
|
||||
pos.z = iceSmoke->pos.z;
|
||||
|
||||
if ((iceSmoke->primAlphaState != 2) && EnFz_ReachedTarget(this, &pos)) {
|
||||
iceSmoke->primAlphaState = 2;
|
||||
iceSmoke->velocity.x = 0.0f;
|
||||
iceSmoke->velocity.z = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
iceSmoke++;
|
||||
}
|
||||
}
|
||||
|
||||
void EnFz_DrawIceSmoke(EnFz* this, GlobalContext* globalCtx) {
|
||||
EnFzEffectSsIceSmoke* iceSmoke = this->iceSmoke;
|
||||
s16 i;
|
||||
GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
|
||||
u8 texLoaded = false;
|
||||
|
||||
OPEN_DISPS(gfxCtx, "../z_en_fz.c", 1384);
|
||||
|
||||
func_80093D84(globalCtx->state.gfxCtx);
|
||||
|
||||
for (i = 0; i < ARRAY_COUNT(this->iceSmoke); i++) {
|
||||
if (iceSmoke->type > 0) {
|
||||
gDPPipeSync(POLY_XLU_DISP++);
|
||||
|
||||
if (!texLoaded) {
|
||||
gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(&D_060030A0));
|
||||
texLoaded++;
|
||||
}
|
||||
|
||||
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, iceSmoke->primAlpha);
|
||||
gSPSegment(POLY_XLU_DISP++, 0x08,
|
||||
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, 3 * (iceSmoke->timer + (3 * i)),
|
||||
15 * (iceSmoke->timer + (3 * i)), 32, 64, 1, 0, 0, 32, 32));
|
||||
Matrix_Translate(iceSmoke->pos.x, iceSmoke->pos.y, iceSmoke->pos.z, MTXMODE_NEW);
|
||||
func_800D1FD4(&globalCtx->mf_11DA0);
|
||||
Matrix_Scale(iceSmoke->xyScale, iceSmoke->xyScale, 1.0f, MTXMODE_APPLY);
|
||||
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx, "../z_en_fz.c", 1424),
|
||||
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
||||
gSPDisplayList(POLY_XLU_DISP++, SEGMENTED_TO_VIRTUAL(&D_06003158));
|
||||
}
|
||||
|
||||
iceSmoke++;
|
||||
}
|
||||
|
||||
CLOSE_DISPS(gfxCtx, "../z_en_fz.c", 1430);
|
||||
}
|
||||
|
|
|
@ -6,9 +6,50 @@
|
|||
|
||||
struct EnFz;
|
||||
|
||||
typedef void (*EnFzActionFunc)(struct EnFz*, GlobalContext*);
|
||||
typedef void (*EnFzSpawnIceSmokeFunc)(struct EnFz*);
|
||||
|
||||
typedef struct {
|
||||
/* 0x0000 */ u8 type; // 0,1,2: State of freezard (1 not freezing, 2 freezing)
|
||||
/* 0x0001 */ u8 timer; // increments primAlphaState after reaching 7 (freezing), used in Gfx_TwoTexScroll
|
||||
/* 0x0004 */ Vec3f pos; // Random position within 20.0f of actor
|
||||
/* 0x0010 */ Vec3f velocity;
|
||||
/* 0x001C */ Vec3f accel;
|
||||
/* 0x0028 */ char unk_28[0x4];
|
||||
/* 0x002C */ s16 primAlpha; // transparency in RGBA colour system
|
||||
/* 0x002E */ s16 primAlphaState; // 0: increasing (more opaque) 1: decreasing (more transparent) 2: collision
|
||||
/* 0x0030 */ f32 xyScale; //
|
||||
/* 0x0034 */ f32 xyScaleTarget;
|
||||
/* 0x0038 */ u8 isTimerMod8; // conditional, used to run CollisionCheck_SetAT
|
||||
} EnFzEffectSsIceSmoke; // size = 0x3C
|
||||
|
||||
typedef struct EnFz {
|
||||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ char unk_14C[0xA88];
|
||||
/* 0x014C */ EnFzActionFunc actionFunc;
|
||||
/* 0x0150 */ ColliderCylinder collider1;
|
||||
/* 0x019C */ ColliderCylinder collider2;
|
||||
/* 0x01E8 */ ColliderCylinder collider3;
|
||||
/* 0x0234 */ Vec3f posOrigin; // Spawn position for moving freezard
|
||||
/* 0x0240 */ s16 counter; // A perpetual counter
|
||||
/* 0x0242 */ s16 unusedTimer1;
|
||||
/* 0x0244 */ s16 timer; // Used to time transition into next action. Can be 10, 20, 40, 60, 80, 100
|
||||
/* 0x0246 */ u8 updateBgInfo; // Always true in every instance
|
||||
/* 0x0247 */ u8 isMoving; // Freezard is moving in xz plane
|
||||
/* 0x0248 */ u8 isFreezing; // Freezard shooting ice projectiles that can freeze Link
|
||||
/* 0x0249 */ u8 unusedCounter; // Incremented when Freezard takes damage
|
||||
/* 0x024C */ f32 iceSmokeFreezingSpawnHeight; // Height for Ice Smoke Spawn, only when freezing
|
||||
/* 0x0250 */ f32 unusedFloat; // Set to 135.0f
|
||||
/* 0x0254 */ f32 speedXZ; // Set to 4.0f when moving
|
||||
/* 0x0258 */ u32 envAlpha; // transparency in RGBA colour system
|
||||
/* 0x025C */ u16 unusedNum1; // Only set to 0
|
||||
/* 0x025E */ u16 unusedNum2; // Set to either 0 when hidden or 4000 when growing
|
||||
/* 0x0260 */ u8 state; // 0 (hidden) 1 (growning/shrinking) 2 (full size) 3 (melting from fire)
|
||||
/* 0x0261 */ u8 isActive; // Default true. Set to false after beginning to despawn
|
||||
/* 0x0262 */ u8 isDespawning; // Default false. Set to false after beginning to despawn or melting
|
||||
/* 0x0263 */ u8 unusedTimer2; // Timer
|
||||
/* 0x0264 */ Vec3f wallHitPos; // Position contact was made with a wall
|
||||
/* 0x0270 */ f32 distToTargetSq;
|
||||
/* 0x0274 */ EnFzEffectSsIceSmoke iceSmoke[40];
|
||||
} EnFz; // size = 0x0BD4
|
||||
|
||||
extern const ActorInit En_Fz_InitVars;
|
||||
|
|
|
@ -10,10 +10,10 @@
|
|||
#define FLAGS 0x00000010
|
||||
|
||||
#define THIS ((EnHorseGameCheckBase*)thisx)
|
||||
#define AT_FINISH_LINE(actor) \
|
||||
#define AT_FINISH_LINE(actor) \
|
||||
(Math3D_PointInSquare2D(sFinishLine[0], sFinishLine[1], sFinishLine[2], sFinishLine[3], (actor)->world.pos.x, \
|
||||
(actor)->world.pos.z))
|
||||
#define AT_RANCH_EXIT(actor) \
|
||||
#define AT_RANCH_EXIT(actor) \
|
||||
(Math3D_PointInSquare2D(sRanchExit[0], sRanchExit[1], sRanchExit[2], sRanchExit[3], (actor)->world.pos.x, \
|
||||
(actor)->world.pos.z))
|
||||
|
||||
|
@ -321,7 +321,8 @@ s32 EnHorseGameCheck_UpdateMalonRace(EnHorseGameCheckBase* base, GlobalContext*
|
|||
|
||||
if (!(this->raceFlags & MALONRACE_PLAYER_ON_MARK) && AT_FINISH_LINE(player->rideActor)) {
|
||||
this->raceFlags |= MALONRACE_PLAYER_ON_MARK;
|
||||
} else if ((this->raceFlags & MALONRACE_PLAYER_ON_MARK) && !(this->raceFlags & MALONRACE_PLAYER_START) && !AT_FINISH_LINE(player->rideActor)) {
|
||||
} else if ((this->raceFlags & MALONRACE_PLAYER_ON_MARK) && !(this->raceFlags & MALONRACE_PLAYER_START) &&
|
||||
!AT_FINISH_LINE(player->rideActor)) {
|
||||
this->raceFlags |= MALONRACE_PLAYER_START;
|
||||
}
|
||||
if ((this->startTimer > 50) && !(this->raceFlags & MALONRACE_SET_TIMER)) {
|
||||
|
@ -366,7 +367,8 @@ s32 EnHorseGameCheck_UpdateMalonRace(EnHorseGameCheckBase* base, GlobalContext*
|
|||
}
|
||||
}
|
||||
}
|
||||
if ((player2->rideActor != NULL) && (this->raceFlags & MALONRACE_PLAYER_START) && AT_FINISH_LINE(player2->rideActor)) {
|
||||
if ((player2->rideActor != NULL) && (this->raceFlags & MALONRACE_PLAYER_START) &&
|
||||
AT_FINISH_LINE(player2->rideActor)) {
|
||||
if ((this->lapCount == 1) && (this->fenceCheck[15] == 0) && (player2->rideActor->prevPos.x < -200.0f)) {
|
||||
this->raceFlags |= MALONRACE_BROKE_RULE;
|
||||
func_8010B680(globalCtx, 0x208C, NULL);
|
||||
|
|
|
@ -169,8 +169,8 @@ void EnTr_ChooseAction2(EnTr* this, GlobalContext* globalCtx) {
|
|||
this->animation = D_80B24378[this->actor.params];
|
||||
this->timer = 39;
|
||||
Actor_SpawnAsChild(&globalCtx->actorCtx, &this->actor, globalCtx, ACTOR_DEMO_6K,
|
||||
this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0,
|
||||
0, 0, this->actor.params + 9);
|
||||
this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0,
|
||||
0, this->actor.params + 9);
|
||||
Audio_PlayActorSound2(&this->actor, NA_SE_EN_FANTOM_MASIC1);
|
||||
break;
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue