2022-03-21 21:51:23 -04:00
|
|
|
/*
|
|
|
|
* File: z_en_siofuki.c
|
|
|
|
* Overlay: ovl_En_Siofuki
|
|
|
|
* Description: Water Spout
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "z_en_siofuki.h"
|
|
|
|
#include "objects/object_siofuki/object_siofuki.h"
|
|
|
|
|
|
|
|
#define FLAGS (ACTOR_FLAG_4 | ACTOR_FLAG_5)
|
|
|
|
|
|
|
|
void EnSiofuki_Init(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void EnSiofuki_Destroy(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void EnSiofuki_Update(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
void EnSiofuki_Draw(Actor* thisx, GlobalContext* globalCtx);
|
|
|
|
|
|
|
|
void func_80AFC34C(EnSiofuki* this, GlobalContext* globalCtx);
|
|
|
|
void func_80AFC544(EnSiofuki* this, GlobalContext* globalCtx);
|
|
|
|
void func_80AFC478(EnSiofuki* this, GlobalContext* globalCtx);
|
|
|
|
|
|
|
|
const ActorInit En_Siofuki_InitVars = {
|
|
|
|
ACTOR_EN_SIOFUKI,
|
|
|
|
ACTORCAT_BG,
|
|
|
|
FLAGS,
|
|
|
|
OBJECT_SIOFUKI,
|
|
|
|
sizeof(EnSiofuki),
|
|
|
|
(ActorFunc)EnSiofuki_Init,
|
|
|
|
(ActorFunc)EnSiofuki_Destroy,
|
|
|
|
(ActorFunc)EnSiofuki_Update,
|
|
|
|
(ActorFunc)EnSiofuki_Draw,
|
|
|
|
NULL,
|
|
|
|
};
|
|
|
|
|
|
|
|
static InitChainEntry sInitChain[] = {
|
|
|
|
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP),
|
|
|
|
};
|
|
|
|
|
|
|
|
void EnSiofuki_Init(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
EnSiofuki* this = (EnSiofuki*)thisx;
|
|
|
|
s32 type;
|
|
|
|
CollisionHeader* colHeader = NULL;
|
|
|
|
s32 pad;
|
|
|
|
|
|
|
|
if ((thisx->room == 10) && Flags_GetSwitch(globalCtx, 0x1E)) {
|
|
|
|
Actor_Kill(thisx);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
Actor_ProcessInitChain(thisx, sInitChain);
|
|
|
|
DynaPolyActor_Init(&this->dyna, DPM_PLAYER);
|
|
|
|
CollisionHeader_GetVirtual(&object_siofuki_Col_000D78, &colHeader);
|
|
|
|
this->dyna.bgId = DynaPoly_SetBgActor(globalCtx, &globalCtx->colCtx.dyna, thisx, colHeader);
|
|
|
|
this->sfxFlags |= 1;
|
|
|
|
|
|
|
|
type = ((u16)thisx->params >> 0xC) & 0xF;
|
|
|
|
if (!((type == 0) || (type == 1))) {
|
|
|
|
Actor_Kill(thisx);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->initPosY = thisx->world.pos.y;
|
|
|
|
this->unk_174 = 35.0f;
|
|
|
|
this->unk_170 = -6058.0f + this->unk_174;
|
|
|
|
|
|
|
|
if (thisx->shape.rot.x != 0) {
|
|
|
|
this->maxHeight = thisx->shape.rot.x * 40.0f;
|
|
|
|
this->currentHeight = this->maxHeight;
|
|
|
|
}
|
|
|
|
this->activeTime = 0;
|
|
|
|
if (thisx->shape.rot.y != 0) {
|
|
|
|
this->activeTime = thisx->shape.rot.y;
|
|
|
|
}
|
|
|
|
if (thisx->shape.rot.z != 0) {
|
|
|
|
thisx->scale.x = thisx->shape.rot.z * (1.0f / 1.73f) * 0.1f;
|
|
|
|
thisx->scale.z = thisx->shape.rot.z * 0.5f * 0.1f;
|
|
|
|
}
|
|
|
|
|
|
|
|
thisx->world.rot.x = 0;
|
|
|
|
thisx->world.rot.y = 0;
|
|
|
|
thisx->world.rot.z = 0;
|
|
|
|
thisx->shape.rot.x = 0;
|
|
|
|
thisx->shape.rot.y = 0;
|
|
|
|
thisx->shape.rot.z = 0;
|
|
|
|
|
|
|
|
type = ((u16)thisx->params >> 0xC) & 0xF;
|
|
|
|
if (type == EN_SIOFUKI_RAISING) {
|
|
|
|
this->currentHeight = 10.0f;
|
|
|
|
this->targetHeight = 10.0f;
|
|
|
|
this->actionFunc = func_80AFC34C;
|
|
|
|
} else if (type == EN_SIOFUKI_LOWERING) {
|
|
|
|
if (Flags_GetTreasure(globalCtx, (u16)thisx->params & 0x3F)) {
|
|
|
|
this->currentHeight = -45.0f;
|
|
|
|
this->targetHeight = -45.0f;
|
|
|
|
this->actionFunc = func_80AFC544;
|
|
|
|
} else {
|
|
|
|
this->targetHeight = this->currentHeight;
|
|
|
|
this->actionFunc = func_80AFC478;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnSiofuki_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
EnSiofuki* this = (EnSiofuki*)thisx;
|
|
|
|
|
|
|
|
DynaPoly_DeleteBgActor(globalCtx, &globalCtx->colCtx.dyna, this->dyna.bgId);
|
|
|
|
}
|
|
|
|
|
|
|
|
void func_80AFBDC8(EnSiofuki* this, GlobalContext* globalCtx) {
|
|
|
|
this->oscillation = sinf((globalCtx->gameplayFrames & 0x1F) / 32.0f * M_PI * 2.0f) * 4.0f;
|
|
|
|
this->unk_170 = this->unk_174 * 10.0f + -6058.0f - this->oscillation * 10.0f;
|
|
|
|
this->unk_174 = 35.0f;
|
|
|
|
this->dyna.actor.world.pos.y = this->initPosY + this->currentHeight + this->oscillation;
|
|
|
|
}
|
|
|
|
|
|
|
|
void func_80AFBE8C(EnSiofuki* this, GlobalContext* globalCtx) {
|
|
|
|
Player* player = GET_PLAYER(globalCtx);
|
|
|
|
f32 dX;
|
|
|
|
f32 dY;
|
|
|
|
f32 dZ;
|
|
|
|
s16 angle;
|
|
|
|
s16 dAngle;
|
|
|
|
f32 dist2d;
|
|
|
|
f32 speedScale;
|
|
|
|
|
|
|
|
dX = player->actor.world.pos.x - this->dyna.actor.world.pos.x;
|
|
|
|
dY = player->actor.world.pos.y - this->dyna.actor.world.pos.y;
|
|
|
|
dZ = player->actor.world.pos.z - this->dyna.actor.world.pos.z;
|
|
|
|
|
|
|
|
if ((dX > (this->dyna.actor.scale.x * -346.0f)) && (dX < (this->dyna.actor.scale.x * 346.0f)) &&
|
|
|
|
(dZ > (this->dyna.actor.scale.z * -400.0f)) && (dZ < (this->dyna.actor.scale.z * 400.0f)) && (dY < 0.0f)) {
|
|
|
|
if (func_8004356C(&this->dyna)) {
|
|
|
|
if (this->splashTimer <= 0) {
|
|
|
|
EffectSsGSplash_Spawn(globalCtx, &player->actor.world.pos, NULL, NULL, 1, 1);
|
|
|
|
this->splashTimer = 10;
|
|
|
|
} else {
|
|
|
|
this->splashTimer--;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->applySpeed = false;
|
|
|
|
this->appliedSpeed = 0.0f;
|
|
|
|
this->targetAppliedSpeed = 0.0f;
|
|
|
|
} else {
|
|
|
|
dist2d = sqrtf(SQ(dX) + SQ(dZ));
|
|
|
|
this->applySpeed = true;
|
|
|
|
this->splashTimer = 0;
|
|
|
|
angle = Math_FAtan2F(dX, dZ) * (0x8000 / M_PI);
|
|
|
|
dAngle = (player->actor.world.rot.y ^ 0x8000) - angle;
|
|
|
|
player->actor.gravity = 0.0f;
|
|
|
|
player->actor.velocity.y = 0.0f;
|
|
|
|
Math_SmoothStepToF(&player->actor.world.pos.y, this->dyna.actor.world.pos.y, 0.5f, 4.0f, 1.0f);
|
|
|
|
|
|
|
|
if ((dAngle < 0x4000) && (dAngle > -0x4000)) {
|
|
|
|
this->appliedYaw = player->actor.world.rot.y ^ 0x8000;
|
|
|
|
speedScale = dist2d / (this->dyna.actor.scale.x * 40.0f * 10.0f);
|
|
|
|
speedScale = CLAMP_MIN(speedScale, 0.0f);
|
|
|
|
speedScale = CLAMP_MAX(speedScale, 1.0f);
|
|
|
|
player->linearVelocity *= speedScale;
|
|
|
|
Math_ApproachF(&this->targetAppliedSpeed, 3.0f, 1.0f, 1.0f);
|
|
|
|
Math_ApproachF(&this->appliedSpeed, this->targetAppliedSpeed, 1.0f, 0.3f * speedScale);
|
|
|
|
} else {
|
|
|
|
this->appliedYaw = player->actor.world.rot.y;
|
|
|
|
player->linearVelocity /= 2.0f;
|
|
|
|
Math_ApproachF(&this->targetAppliedSpeed, 3.0f, 1.0f, 1.0f);
|
|
|
|
Math_ApproachF(&this->appliedSpeed, this->targetAppliedSpeed, 1.0f, 0.1f);
|
|
|
|
}
|
|
|
|
|
|
|
|
player->windDirection = this->appliedYaw;
|
|
|
|
player->windSpeed = this->appliedSpeed;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (this->applySpeed) {
|
|
|
|
player->linearVelocity = this->appliedSpeed + player->linearVelocity;
|
|
|
|
player->currentYaw = this->appliedYaw;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->targetAppliedSpeed = 0.0f;
|
|
|
|
this->appliedSpeed = 0.0f;
|
|
|
|
this->applySpeed = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void func_80AFC1D0(EnSiofuki* this, GlobalContext* globalCtx) {
|
|
|
|
Math_SmoothStepToF(&this->currentHeight, this->targetHeight, 0.8f, 3.0f, 0.01f);
|
|
|
|
}
|
|
|
|
|
|
|
|
void func_80AFC218(EnSiofuki* this, GlobalContext* globalCtx) {
|
|
|
|
func_80AFBDC8(this, globalCtx);
|
|
|
|
func_80AFBE8C(this, globalCtx);
|
|
|
|
func_80AFC1D0(this, globalCtx);
|
|
|
|
|
|
|
|
this->timer--;
|
|
|
|
if (this->timer < 0) {
|
|
|
|
Flags_UnsetSwitch(globalCtx, ((u16)this->dyna.actor.params >> 6) & 0x3F);
|
|
|
|
switch (((u16)this->dyna.actor.params >> 0xC) & 0xF) {
|
|
|
|
case EN_SIOFUKI_RAISING:
|
|
|
|
this->targetHeight = 10.0f;
|
|
|
|
this->actionFunc = func_80AFC34C;
|
|
|
|
break;
|
|
|
|
case EN_SIOFUKI_LOWERING:
|
|
|
|
this->targetHeight = this->maxHeight;
|
|
|
|
this->actionFunc = func_80AFC478;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
func_8002F994(&this->dyna.actor, this->timer);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (((((u16)this->dyna.actor.params >> 0xC) & 0xF) == EN_SIOFUKI_LOWERING) &&
|
|
|
|
Flags_GetTreasure(globalCtx, (u16)this->dyna.actor.params & 0x3F)) {
|
|
|
|
this->currentHeight = -45.0f;
|
|
|
|
this->targetHeight = -45.0f;
|
|
|
|
Flags_UnsetSwitch(globalCtx, ((u16)this->dyna.actor.params >> 6) & 0x3F);
|
|
|
|
this->actionFunc = func_80AFC544;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void func_80AFC34C(EnSiofuki* this, GlobalContext* globalCtx) {
|
|
|
|
func_80AFBDC8(this, globalCtx);
|
|
|
|
func_80AFBE8C(this, globalCtx);
|
|
|
|
func_80AFC1D0(this, globalCtx);
|
|
|
|
|
|
|
|
if (Flags_GetSwitch(globalCtx, ((u16)this->dyna.actor.params >> 6) & 0x3F)) {
|
|
|
|
this->targetHeight = 400.0f;
|
|
|
|
this->timer = 300;
|
|
|
|
this->actionFunc = func_80AFC218;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void func_80AFC3C8(EnSiofuki* this, GlobalContext* globalCtx) {
|
|
|
|
func_80AFBDC8(this, globalCtx);
|
|
|
|
func_80AFBE8C(this, globalCtx);
|
|
|
|
func_80AFC1D0(this, globalCtx);
|
|
|
|
|
|
|
|
this->timer--;
|
|
|
|
if (this->timer < 0) {
|
|
|
|
this->timer = this->activeTime * 20;
|
|
|
|
this->targetHeight = -45.0f;
|
|
|
|
this->actionFunc = func_80AFC218;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Flags_GetTreasure(globalCtx, (u16)this->dyna.actor.params & 0x3F)) {
|
|
|
|
this->currentHeight = -45.0f;
|
|
|
|
this->targetHeight = -45.0f;
|
|
|
|
this->actionFunc = func_80AFC544;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void func_80AFC478(EnSiofuki* this, GlobalContext* globalCtx) {
|
|
|
|
func_80AFBDC8(this, globalCtx);
|
|
|
|
func_80AFBE8C(this, globalCtx);
|
|
|
|
func_80AFC1D0(this, globalCtx);
|
|
|
|
|
|
|
|
if (((u16)this->dyna.actor.params >> 0xC & 0xF) == EN_SIOFUKI_LOWERING) {
|
|
|
|
if (Flags_GetSwitch(globalCtx, ((u16)this->dyna.actor.params >> 6) & 0x3F)) {
|
|
|
|
this->timer = 20;
|
|
|
|
this->actionFunc = func_80AFC3C8;
|
|
|
|
OnePointCutscene_Init(globalCtx, 5010, 40, &this->dyna.actor, MAIN_CAM);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Flags_GetTreasure(globalCtx, (u16)this->dyna.actor.params & 0x3F)) {
|
|
|
|
this->currentHeight = -45.0f;
|
|
|
|
this->targetHeight = -45.0f;
|
|
|
|
this->actionFunc = func_80AFC544;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void func_80AFC544(EnSiofuki* this, GlobalContext* globalCtx) {
|
|
|
|
func_80AFBDC8(this, globalCtx);
|
|
|
|
func_80AFC1D0(this, globalCtx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnSiofuki_Update(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
EnSiofuki* this = (EnSiofuki*)thisx;
|
|
|
|
|
|
|
|
this->actionFunc(this, globalCtx);
|
|
|
|
}
|
|
|
|
|
|
|
|
void EnSiofuki_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
|
|
|
EnSiofuki* this = (EnSiofuki*)thisx;
|
|
|
|
u32 x;
|
|
|
|
u32 y;
|
|
|
|
u32 gameplayFrames = globalCtx->gameplayFrames;
|
|
|
|
|
2022-07-05 19:29:34 -04:00
|
|
|
OPEN_DISPS(globalCtx->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
func_80093D84(globalCtx->state.gfxCtx);
|
|
|
|
Matrix_Translate(0.0f, this->unk_170, 0.0f, MTXMODE_APPLY);
|
|
|
|
Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
|
2022-07-05 19:29:34 -04:00
|
|
|
gSPMatrix(POLY_XLU_DISP++, MATRIX_NEWMTX(globalCtx->state.gfxCtx),
|
2022-03-21 21:51:23 -04:00
|
|
|
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
|
|
|
|
x = gameplayFrames * 15;
|
|
|
|
y = gameplayFrames * -15;
|
|
|
|
gSPSegment(POLY_XLU_DISP++, 0x08, Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, x, y, 64, 64, 1, x, y, 64, 64));
|
|
|
|
gSPDisplayList(POLY_XLU_DISP++, object_siofuki_DL_000B70);
|
2022-07-05 19:29:34 -04:00
|
|
|
CLOSE_DISPS(globalCtx->state.gfxCtx);
|
2022-03-21 21:51:23 -04:00
|
|
|
|
|
|
|
if (this->sfxFlags & 1) {
|
|
|
|
f32 heightRatio;
|
|
|
|
switch (((u16)thisx->params >> 0xC) & 0xF) {
|
|
|
|
case EN_SIOFUKI_RAISING:
|
|
|
|
heightRatio = (this->currentHeight - 10.0f) / (400.0f - 10.0f);
|
|
|
|
func_800F436C(&thisx->projectedPos, NA_SE_EV_FOUNTAIN - SFX_FLAG, 1.0f + heightRatio);
|
|
|
|
break;
|
|
|
|
case EN_SIOFUKI_LOWERING:
|
|
|
|
if (this->currentHeight > -35.0f) {
|
|
|
|
heightRatio = (this->currentHeight - -35.0f) / (this->maxHeight - -35.0f);
|
|
|
|
func_800F436C(&thisx->projectedPos, NA_SE_EV_FOUNTAIN - SFX_FLAG, 1.0f + heightRatio);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|