1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-08-06 06:10:21 +00:00

ovl_En_Siofuki (#456)

* ovl_En_Siofuki

* PR review

* Rebase

* PR review
This commit is contained in:
maekclena 2020-11-21 22:03:20 +01:00 committed by GitHub
parent 84a0acc9cf
commit 0453c7d3cf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
17 changed files with 307 additions and 961 deletions

View file

@ -1,3 +1,9 @@
/*
* File: z_en_siofuki.c
* Overlay: ovl_En_Siofuki
* Description: Water Spout
*/
#include "z_en_siofuki.h"
#define FLAGS 0x00000030
@ -9,7 +15,10 @@ 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,
ACTORTYPE_BG,
@ -21,27 +30,286 @@ const ActorInit En_Siofuki_InitVars = {
(ActorFunc)EnSiofuki_Update,
(ActorFunc)EnSiofuki_Draw,
};
*/
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/EnSiofuki_Init.s")
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/EnSiofuki_Destroy.s")
static InitChainEntry sInitChain[] = {
ICHAIN_VEC3F_DIV1000(scale, 100, ICHAIN_STOP),
};
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/func_80AFBDC8.s")
extern Gfx D_06000B70[];
extern UNK_TYPE D_06000D78;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/func_80AFBE8C.s")
void EnSiofuki_Init(Actor* thisx, GlobalContext* globalCtx) {
EnSiofuki* this = THIS;
s32 type;
ColHeader* colHeader = NULL;
s32 pad;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/func_80AFC1D0.s")
if ((thisx->room == 10) && Flags_GetSwitch(globalCtx, 0x1E)) {
Actor_Kill(thisx);
return;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/func_80AFC218.s")
Actor_ProcessInitChain(thisx, sInitChain);
DynaPolyInfo_SetActorMove(&this->dyna, DPM_PLAYER);
DynaPolyInfo_Alloc(&D_06000D78, &colHeader);
this->dyna.dynaPolyId = DynaPolyInfo_RegisterActor(globalCtx, &globalCtx->colCtx.dyna, thisx, colHeader);
this->sfxFlags |= 1;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/func_80AFC34C.s")
type = ((u16)thisx->params >> 0xC) & 0xF;
if (!((type == 0) || (type == 1))) {
Actor_Kill(thisx);
return;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/func_80AFC3C8.s")
this->initPosY = thisx->posRot.pos.y;
this->unk_174 = 35.0f;
this->unk_170 = -6058.0f + this->unk_174;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/func_80AFC478.s")
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;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/func_80AFC544.s")
thisx->posRot.rot.x = 0;
thisx->posRot.rot.y = 0;
thisx->posRot.rot.z = 0;
thisx->shape.rot.x = 0;
thisx->shape.rot.y = 0;
thisx->shape.rot.z = 0;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/EnSiofuki_Update.s")
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;
}
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/actors/ovl_En_Siofuki/EnSiofuki_Draw.s")
void EnSiofuki_Destroy(Actor* thisx, GlobalContext* globalCtx) {
EnSiofuki* this = THIS;
DynaPolyInfo_Free(globalCtx, &globalCtx->colCtx.dyna, this->dyna.dynaPolyId);
}
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.posRot.pos.y = this->initPosY + this->currentHeight + this->oscillation;
}
void func_80AFBE8C(EnSiofuki* this, GlobalContext* globalCtx) {
Player* player = PLAYER;
f32 dX;
f32 dY;
f32 dZ;
s16 angle;
s16 dAngle;
f32 dist2d;
f32 speedScale;
dX = player->actor.posRot.pos.x - this->dyna.actor.posRot.pos.x;
dY = player->actor.posRot.pos.y - this->dyna.actor.posRot.pos.y;
dZ = player->actor.posRot.pos.z - this->dyna.actor.posRot.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.posRot.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_atan2f(dX, dZ) * (0x8000 / M_PI);
dAngle = (player->actor.posRot.rot.y ^ 0x8000) - angle;
player->actor.gravity = 0.0f;
player->actor.velocity.y = 0.0f;
Math_SmoothScaleMaxMinF(&player->actor.posRot.pos.y, this->dyna.actor.posRot.pos.y, 0.5f, 4.0f, 1.0f);
if ((dAngle < 0x4000) && (dAngle > -0x4000)) {
this->appliedYaw = player->actor.posRot.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_SmoothScaleMaxF(&this->targetAppliedSpeed, 3.0f, 1.0f, 1.0f);
Math_SmoothScaleMaxF(&this->appliedSpeed, this->targetAppliedSpeed, 1.0f, 0.3f * speedScale);
} else {
this->appliedYaw = player->actor.posRot.rot.y;
player->linearVelocity /= 2.0f;
Math_SmoothScaleMaxF(&this->targetAppliedSpeed, 3.0f, 1.0f, 1.0f);
Math_SmoothScaleMaxF(&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_SmoothScaleMaxMinF(&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;
func_800800F8(globalCtx, 0x1392, 0x28, &this->dyna.actor, 0);
}
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 = THIS;
this->actionFunc(this, globalCtx);
}
void EnSiofuki_Draw(Actor* thisx, GlobalContext* globalCtx) {
EnSiofuki* this = THIS;
u32 x;
u32 y;
u32 gameplayFrames = globalCtx->gameplayFrames;
OPEN_DISPS(globalCtx->state.gfxCtx, "../z_en_siofuki.c", 654);
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);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx, "../z_en_siofuki.c", 662),
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++, D_06000B70);
CLOSE_DISPS(globalCtx->state.gfxCtx, "../z_en_siofuki.c", 674);
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;
}
}
}

View file

@ -4,11 +4,33 @@
#include "ultra64.h"
#include "global.h"
typedef enum {
/* 0x00 */ EN_SIOFUKI_RAISING,
/* 0x01 */ EN_SIOFUKI_LOWERING
} EnSiofukiType;
struct EnSiofuki;
typedef void (*EnSiofukiActionFunc)(struct EnSiofuki*, GlobalContext*);
typedef struct EnSiofuki {
/* 0x0000 */ Actor actor;
/* 0x014C */ char unk_14C[0x54];
/* 0x0000 */ DynaPolyActor dyna;
/* 0x0164 */ EnSiofukiActionFunc actionFunc;
/* 0x0168 */ s32 timer;
/* 0x016C */ f32 initPosY;
/* 0x0170 */ f32 unk_170;
/* 0x0174 */ f32 unk_174;
/* 0x0178 */ f32 oscillation;
/* 0x017C */ f32 targetHeight;
/* 0x0180 */ f32 currentHeight;
/* 0x0184 */ s32 splashTimer;
/* 0x0188 */ s32 applySpeed;
/* 0x018C */ f32 appliedSpeed;
/* 0x0190 */ f32 targetAppliedSpeed;
/* 0x0194 */ s16 appliedYaw;
/* 0x0196 */ s16 activeTime;
/* 0x0198 */ f32 maxHeight;
/* 0x019C */ u8 sfxFlags;
} EnSiofuki; // size = 0x01A0
extern const ActorInit En_Siofuki_InitVars;