En_Stream (unused water vortex from OoT) OK (#480)

* En_Stream (unused water vortex from OoT) OK

* Better names in EnStream_PlayerIsInRange

* Enum for whether the player is in range
This commit is contained in:
Tom Overton 2021-12-06 15:52:18 -08:00 committed by GitHub
parent 64ecb146ae
commit d218c9be23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 134 additions and 24 deletions

3
spec
View File

@ -1723,8 +1723,7 @@ beginseg
name "ovl_En_Stream"
compress
include "build/src/overlays/actors/ovl_En_Stream/z_en_stream.o"
include "build/data/ovl_En_Stream/ovl_En_Stream.data.o"
include "build/data/ovl_En_Stream/ovl_En_Stream.reloc.o"
include "build/src/overlays/actors/ovl_En_Stream/ovl_En_Stream_reloc.o"
endseg
beginseg

View File

@ -1,7 +1,7 @@
/*
* File: z_en_stream.c
* Overlay: ovl_En_Stream
* Description:
* Description: Unused water vortex from OoT
*/
#include "z_en_stream.h"
@ -15,9 +15,8 @@ void EnStream_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnStream_Update(Actor* thisx, GlobalContext* globalCtx);
void EnStream_Draw(Actor* thisx, GlobalContext* globalCtx);
void EnStream_SetupAction(EnStream* this, EnStreamActionFunc actionFunc);
void EnStream_WaitForPlayer(EnStream* this, GlobalContext* globalCtx);
#if 0
const ActorInit En_Stream_InitVars = {
ACTOR_EN_STREAM,
ACTORCAT_BG,
@ -30,29 +29,122 @@ const ActorInit En_Stream_InitVars = {
(ActorFunc)EnStream_Draw,
};
// static InitChainEntry sInitChain[] = {
static InitChainEntry D_80965B20[] = {
static InitChainEntry sInitChain[] = {
ICHAIN_VEC3F_DIV1000(scale, 20, ICHAIN_STOP),
};
#endif
extern Gfx D_06000950[];
extern InitChainEntry D_80965B20[];
void EnStream_SetupAction(EnStream* this, EnStreamActionFunc actionFunc) {
this->actionFunc = actionFunc;
}
extern UNK_TYPE D_06000950;
void EnStream_Init(Actor* thisx, GlobalContext* globalCtx) {
EnStream* this = THIS;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Stream/EnStream_SetupAction.s")
this->size = EN_STREAM_SIZE(&this->actor);
Actor_ProcessInitChain(&this->actor, sInitChain);
if (this->size != EN_STREAM_SIZE_NORMAL && this->size == EN_STREAM_SIZE_SMALL) {
this->actor.scale.y = 0.01f;
}
EnStream_SetupAction(this, EnStream_WaitForPlayer);
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Stream/EnStream_Init.s")
void EnStream_Destroy(Actor* thisx, GlobalContext* globalCtx) {
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Stream/EnStream_Destroy.s")
s32 EnStream_PlayerIsInRange(Vec3f* vortexWorldPos, Vec3f* playerWorldPos, Vec3f* posDifference, f32 vortexYScale) {
s32 ret = EN_STREAM_PLAYER_OUTSIDE_RANGE;
f32 smallConstant = 28.0f;
f32 upperBounds = 160 * vortexYScale * 50.0f;
f32 lowerBounds = 0 * vortexYScale * 50.0f;
f32 xzDist;
f32 range;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Stream/func_809656D4.s")
posDifference->x = playerWorldPos->x - vortexWorldPos->x;
posDifference->y = playerWorldPos->y - vortexWorldPos->y;
posDifference->z = playerWorldPos->z - vortexWorldPos->z;
xzDist = sqrtf(SQ(posDifference->x) + SQ(posDifference->z));
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Stream/func_809657F4.s")
if (lowerBounds <= posDifference->y && posDifference->y <= upperBounds) {
posDifference->y -= lowerBounds;
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Stream/func_8096597C.s")
range = ((75.0f - smallConstant) * (posDifference->y / (upperBounds - lowerBounds))) + 28.0f;
if (xzDist <= range) {
ret = EN_STREAM_PLAYER_WITHIN_RANGE_INSIDE_VORTEX;
}
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Stream/EnStream_Update.s")
if (posDifference->y <= lowerBounds && xzDist <= 28.0f) {
ret = EN_STREAM_PLAYER_WITHIN_RANGE_BELOW_VORTEX;
}
#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Stream/EnStream_Draw.s")
return ret;
}
void EnStream_SuckPlayer(EnStream* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
s32 pad48;
Vec3f posDifference;
f32 xzDist;
f32 yDistWithOffset;
s32 pad30[2];
if (EnStream_PlayerIsInRange(&this->actor.world.pos, &player->actor.world.pos, &posDifference,
this->actor.scale.y) != EN_STREAM_PLAYER_OUTSIDE_RANGE) {
xzDist = sqrtf(SQ(posDifference.x) + SQ(posDifference.z));
yDistWithOffset = player->actor.world.pos.y - (this->actor.world.pos.y - 90.0f);
player->unk_B84 = Math_Atan2S(-posDifference.x, -posDifference.z);
if (xzDist > 3.0f) {
Math_SmoothStepToF(&player->unk_B80, 3.0f, 0.5f, xzDist, 0.0f);
} else {
player->unk_B80 = 0.0f;
Math_SmoothStepToF(&player->actor.world.pos.x, this->actor.world.pos.x, 0.5f, 3.0f, 0.0f);
Math_SmoothStepToF(&player->actor.world.pos.z, this->actor.world.pos.z, 0.5f, 3.0f, 0.0f);
}
if (yDistWithOffset > 0.0f) {
Math_SmoothStepToF(&player->actor.velocity.y, -3.0f, 0.7f, yDistWithOffset, 0.0f);
if (posDifference.y < -70.0f) {
player->stateFlags2 |= 0x80000000;
}
}
} else {
EnStream_SetupAction(this, EnStream_WaitForPlayer);
}
}
void EnStream_WaitForPlayer(EnStream* this, GlobalContext* globalCtx) {
Player* player = GET_PLAYER(globalCtx);
s32 pad;
Vec3f temp;
if (EnStream_PlayerIsInRange(&this->actor.world.pos, &player->actor.world.pos, &temp, this->actor.scale.y) !=
EN_STREAM_PLAYER_OUTSIDE_RANGE) {
EnStream_SetupAction(this, EnStream_SuckPlayer);
}
}
void EnStream_Update(Actor* thisx, GlobalContext* globalCtx) {
EnStream* this = THIS;
this->actionFunc(this, globalCtx);
func_800B8FE8(&this->actor, NA_SE_EV_WHIRLPOOL - SFX_FLAG);
}
void EnStream_Draw(Actor* thisx, GlobalContext* globalCtx) {
u32 multipliedFrames;
u32 frames = globalCtx->gameplayFrames;
Gfx* gfx;
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C2DC(globalCtx->state.gfxCtx);
gfx = POLY_XLU_DISP;
gSPMatrix(&gfx[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
multipliedFrames = frames * 20;
gSPSegment(&gfx[1], 0x08,
Gfx_TwoTexScroll(globalCtx->state.gfxCtx, 0, frames * 30, -multipliedFrames, 64, 64, 1, multipliedFrames,
-multipliedFrames, 64, 64));
gSPDisplayList(&gfx[2], D_06000950);
POLY_XLU_DISP = &gfx[3];
CLOSE_DISPS(globalCtx->state.gfxCtx);
}

View File

@ -3,14 +3,33 @@
#include "global.h"
/**
* Even in OoT, where this actor was used, every single instance of it had
* a params of 0x0000, so it's hard to know how they intended to use this.
* In the final game, only an EN_STREAM_SIZE of 1 does anything different.
*/
#define EN_STREAM_SIZE(thisx) ((thisx)->params & 0xFF)
typedef enum {
/* 0 */ EN_STREAM_SIZE_NORMAL,
/* 1 */ EN_STREAM_SIZE_SMALL,
} EnStreamSize;
typedef enum {
/* 0 */ EN_STREAM_PLAYER_OUTSIDE_RANGE,
/* 1 */ EN_STREAM_PLAYER_WITHIN_RANGE_INSIDE_VORTEX,
/* 2 */ EN_STREAM_PLAYER_WITHIN_RANGE_BELOW_VORTEX,
} EnStreamPlayerLocation;
struct EnStream;
typedef void (*EnStreamActionFunc)(struct EnStream*, GlobalContext*);
typedef struct EnStream {
/* 0x0000 */ Actor actor;
/* 0x0144 */ EnStreamActionFunc actionFunc;
/* 0x0148 */ char unk_144[0x8];
/* 0x000 */ Actor actor;
/* 0x144 */ EnStreamActionFunc actionFunc;
/* 0x148 */ s32 size;
/* 0x14C */ UNK_TYPE1 unk_14C[0x4];
} EnStream; // size = 0x150
extern const ActorInit En_Stream_InitVars;

View File

@ -7888,9 +7888,9 @@
0x80965650:("EnStream_SetupAction",),
0x8096565C:("EnStream_Init",),
0x809656C4:("EnStream_Destroy",),
0x809656D4:("func_809656D4",),
0x809657F4:("func_809657F4",),
0x8096597C:("func_8096597C",),
0x809656D4:("EnStream_PlayerIsInRange",),
0x809657F4:("EnStream_SuckPlayer",),
0x8096597C:("EnStream_WaitForPlayer",),
0x809659D0:("EnStream_Update",),
0x80965A04:("EnStream_Draw",),
0x80965BB0:("EnMm_SetupAction",),