mirror of
https://github.com/zeldaret/oot.git
synced 2024-11-25 09:45:02 +00:00
EnHoll
docs (door-less transition between rooms) (#1419)
* some EnHoll cleanup * some more EnHoll cleanup * even more EnHoll cleanup * EnHoll docs * `enHollFillAlpha` -> `bgCoverAlpha` * Dl -> DL * one temp: action -> type * Move static data out of `EnHoll_HorizontalVisibleNarrow` * "fade" -> "bgcover" * spread sentence over several lines * tweak comments formatting Co-authored-by: fig02 <fig02srl@gmail.com>
This commit is contained in:
parent
5f7e376112
commit
985dd7f520
5 changed files with 308 additions and 188 deletions
|
@ -858,7 +858,7 @@ typedef struct PlayState {
|
|||
/* 0x11E14 */ u8 skyboxId;
|
||||
/* 0x11E15 */ s8 transitionTrigger; // "fade_direction"
|
||||
/* 0x11E16 */ s16 unk_11E16;
|
||||
/* 0x11E18 */ s16 unk_11E18;
|
||||
/* 0x11E18 */ s16 bgCoverAlpha;
|
||||
/* 0x11E1A */ s16 nextEntranceIndex;
|
||||
/* 0x11E1C */ char unk_11E1C[0x40];
|
||||
/* 0x11E5C */ s8 shootingGalleryStatus;
|
||||
|
|
|
@ -370,7 +370,7 @@ void Play_Init(GameState* thisx) {
|
|||
this->state.destroy = Play_Destroy;
|
||||
this->transitionTrigger = TRANS_TRIGGER_END;
|
||||
this->unk_11E16 = 0xFF;
|
||||
this->unk_11E18 = 0;
|
||||
this->bgCoverAlpha = 0;
|
||||
this->haltAllActors = false;
|
||||
|
||||
if (gSaveContext.gameMode != GAMEMODE_TITLE_SCREEN) {
|
||||
|
@ -1207,7 +1207,7 @@ void Play_Draw(PlayState* this) {
|
|||
}
|
||||
|
||||
if ((R_HREG_MODE != HREG_MODE_PLAY) || (R_PLAY_DRAW_ROOM_FLAGS != 0)) {
|
||||
Environment_FillScreen(gfxCtx, 0, 0, 0, this->unk_11E18, FILL_SCREEN_OPA);
|
||||
Environment_FillScreen(gfxCtx, 0, 0, 0, this->bgCoverAlpha, FILL_SCREEN_OPA);
|
||||
}
|
||||
|
||||
if ((R_HREG_MODE != HREG_MODE_PLAY) || R_PLAY_DRAW_ACTORS) {
|
||||
|
|
|
@ -607,10 +607,10 @@ s32 func_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum) {
|
|||
&roomCtx->loadQueue, NULL, "../z_room.c", 1036);
|
||||
roomCtx->unk_30 ^= 1;
|
||||
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
s32 func_800973FC(PlayState* play, RoomContext* roomCtx) {
|
||||
|
|
|
@ -2,26 +2,79 @@
|
|||
|
||||
#define FLAGS ACTOR_FLAG_4
|
||||
|
||||
// Horizontal Plane parameters
|
||||
/*
|
||||
* Horizontal holls parameters (`ENHOLL_H_*`)
|
||||
* All horizontal holls are cuboids which react to how far (depth) and in which direction (side) the player is from the
|
||||
* actor, in the actor's local z direction.
|
||||
*/
|
||||
|
||||
#define PLANE_Y_MIN -50.0f
|
||||
#define PLANE_Y_MAX 200.0f
|
||||
// Defines the height of horizontal holls (all kinds) with a Y range relative to the actor position.
|
||||
#define ENHOLL_H_Y_MIN -50.0f
|
||||
#define ENHOLL_H_Y_MAX 200.0f
|
||||
|
||||
#define PLANE_HALFWIDTH 100.0f
|
||||
#define PLANE_HALFWIDTH_2 200.0f
|
||||
// Defines the width of horizontal holls (all kinds),
|
||||
// with a half-width extending on both lateral sides (towards local +x and -x).
|
||||
#define ENHOLL_H_HALFWIDTH_NARROW 100.0f
|
||||
#define ENHOLL_H_HALFWIDTH 200.0f
|
||||
|
||||
// Defines the depth range from horizontal invisible holls (`ENHOLL_H_INVISIBLE`, `ENHOLL_H_INVISIBLE_NARROW`),
|
||||
// at which rooms get loaded.
|
||||
// i.e. when the player's distance from the actor (along local z) is within this range, the corresponding room is loaded
|
||||
// Note: This means there is a depth range in the middle of `2 * ENHOLL_H_INVISIBLE_LOAD_DEPTH_MIN` where nothing
|
||||
// happens. That range where nothing happens is useful to avoid quickly repeated room swaps.
|
||||
// Note: This means the player is expected to be inside the depth range at some point.
|
||||
// i.e. this range needs to be deep enough so that the player cannot move past it in a single frame.
|
||||
#define ENHOLL_H_INVISIBLE_LOAD_DEPTH_MAX 100.0f
|
||||
#define ENHOLL_H_INVISIBLE_LOAD_DEPTH_MIN 50.0f
|
||||
|
||||
// Defines the depth from horizontal switch flag holls (`ENHOLL_H_BGCOVER_SWITCHFLAG`),
|
||||
// - at which the background geometry starts fading black;
|
||||
#define ENHOLL_H_SWITCHFLAG_BGCOVER_DEPTH 100.0f
|
||||
// - at which the background geometry is fully faded black,
|
||||
// and rooms are loaded if needed according to the side the player is on (along local z).
|
||||
#define ENHOLL_H_SWITCHFLAG_LOAD_DEPTH 50.0f
|
||||
|
||||
/*
|
||||
* Vertical holls parameters (`ENHOLL_V_*`)
|
||||
* All vertical holls are cylinders which react to how far (y dist) and in which direction (side) the player is from the
|
||||
* actor, along the vertical y axis.
|
||||
*/
|
||||
|
||||
// Vertical down holls parameters (`ENHOLL_V_DOWN_BGCOVER_LARGE`)
|
||||
#define ENHOLL_V_DOWN_RADIUS 500.0f
|
||||
// Y dist at which the background geometry starts fading black.
|
||||
#define ENHOLL_V_DOWN_BGCOVER_YDIST 605.0f
|
||||
// Y dist at which the background geometry is fully faded black, and the room down is loaded.
|
||||
#define ENHOLL_V_DOWN_LOAD_YDIST 95.0f
|
||||
|
||||
// Radius for other vertical holls (`ENHOLL_V_BGCOVER`, `ENHOLL_V_INVISIBLE`)
|
||||
#define ENHOLL_V_RADIUS 120.0f
|
||||
|
||||
// Vertical bg cover holls parameters (`ENHOLL_V_BGCOVER`)
|
||||
// Y dist at which the background geometry starts fading black.
|
||||
#define ENHOLL_V_BGCOVER_BGCOVER_YDIST 200.0f
|
||||
// Y dist at which the background geometry is fully faded black,
|
||||
// and rooms are loaded if needed according to the side the player is on (along y).
|
||||
#define ENHOLL_V_BGCOVER_LOAD_YDIST 50.0f
|
||||
|
||||
// Vertical invisible holls parameters (`ENHOLL_V_INVISIBLE`)
|
||||
// Similar to the range defined by `ENHOLL_H_INVISIBLE_LOAD_DEPTH_MAX` and min above for horizontal planes,
|
||||
// but vertically (along y).
|
||||
#define ENHOLL_V_INVISIBLE_LOAD_YDIST_MAX 200.0f
|
||||
#define ENHOLL_V_INVISIBLE_LOAD_YDIST_MIN 50.0f
|
||||
|
||||
void EnHoll_Init(Actor* thisx, PlayState* play);
|
||||
void EnHoll_Destroy(Actor* thisx, PlayState* play);
|
||||
void EnHoll_Update(Actor* thisx, PlayState* play);
|
||||
void EnHoll_Draw(Actor* thisx, PlayState* play);
|
||||
|
||||
void EnHoll_NextAction(EnHoll* this, PlayState* play);
|
||||
void func_80A58DD4(EnHoll* this, PlayState* play);
|
||||
void func_80A59014(EnHoll* this, PlayState* play);
|
||||
void func_80A591C0(EnHoll* this, PlayState* play);
|
||||
void func_80A593A4(EnHoll* this, PlayState* play);
|
||||
void func_80A59520(EnHoll* this, PlayState* play);
|
||||
void func_80A59618(EnHoll* this, PlayState* play);
|
||||
void EnHoll_WaitRoomLoaded(EnHoll* this, PlayState* play);
|
||||
void EnHoll_HorizontalVisibleNarrow(EnHoll* this, PlayState* play);
|
||||
void EnHoll_HorizontalInvisible(EnHoll* this, PlayState* play);
|
||||
void EnHoll_VerticalDownBgCoverLarge(EnHoll* this, PlayState* play);
|
||||
void EnHoll_VerticalBgCover(EnHoll* this, PlayState* play);
|
||||
void EnHoll_VerticalInvisible(EnHoll* this, PlayState* play);
|
||||
void EnHoll_HorizontalBgCoverSwitchFlag(EnHoll* this, PlayState* play);
|
||||
|
||||
ActorInit En_Holl_InitVars = {
|
||||
ACTOR_EN_HOLL,
|
||||
|
@ -36,7 +89,13 @@ ActorInit En_Holl_InitVars = {
|
|||
};
|
||||
|
||||
static EnHollActionFunc sActionFuncs[] = {
|
||||
func_80A58DD4, func_80A591C0, func_80A59520, func_80A59618, func_80A59014, func_80A593A4, func_80A59014,
|
||||
EnHoll_HorizontalVisibleNarrow, // ENHOLL_H_VISIBLE_NARROW
|
||||
EnHoll_VerticalDownBgCoverLarge, // ENHOLL_V_DOWN_BGCOVER_LARGE
|
||||
EnHoll_VerticalInvisible, // ENHOLL_V_INVISIBLE
|
||||
EnHoll_HorizontalBgCoverSwitchFlag, // ENHOLL_H_BGCOVER_SWITCHFLAG
|
||||
EnHoll_HorizontalInvisible, // ENHOLL_H_INVISIBLE
|
||||
EnHoll_VerticalBgCover, // ENHOLL_V_BGCOVER
|
||||
EnHoll_HorizontalInvisible, // ENHOLL_H_INVISIBLE_NARROW
|
||||
};
|
||||
|
||||
static InitChainEntry sInitChain[] = {
|
||||
|
@ -45,32 +104,6 @@ static InitChainEntry sInitChain[] = {
|
|||
ICHAIN_F32(uncullZoneDownward, 400, ICHAIN_STOP),
|
||||
};
|
||||
|
||||
/**
|
||||
* These are all absolute distances in the relative z direction. That is, moving
|
||||
* towards or away from the "face" of the loading plane regardless of orientation.
|
||||
* Moving within these distances of the load plane have the following effects:
|
||||
* [0] : Load the room on this side of the loading plane if not already loaded
|
||||
* [1] : Load the room on the other side of the loading plane
|
||||
* [2] : Fade Region (opaque -> transparent if approaching, transparent -> opaque if receding)
|
||||
* [3] : Transparent Region
|
||||
*
|
||||
* When traversing a loading plane of this kind, it attempts to:
|
||||
* Load Current Room (fails as it is already loaded)
|
||||
* Load Next Room
|
||||
* Load Previous Room
|
||||
* Load Next Room
|
||||
*
|
||||
* @bug The striped nature of loading planes can cause some actors to unload due to
|
||||
* conflicting Object Lists between the two rooms
|
||||
*
|
||||
* @bug If you can get around to the other side of the loading plane without triggering it,
|
||||
* you can load the room on the other side multiple times
|
||||
*/
|
||||
static f32 sHorizTriggerDists[2][4] = {
|
||||
{ 200.0f, 150.0f, 100.0f, 50.0f },
|
||||
{ 100.0f, 75.0f, 50.0f, 25.0f },
|
||||
};
|
||||
|
||||
void EnHoll_SetupAction(EnHoll* this, EnHollActionFunc func) {
|
||||
this->actionFunc = func;
|
||||
}
|
||||
|
@ -80,11 +113,10 @@ s32 EnHoll_IsKokiriLayer8(void) {
|
|||
}
|
||||
|
||||
void EnHoll_ChooseAction(EnHoll* this) {
|
||||
s32 action;
|
||||
s32 type = ENHOLL_GET_TYPE(&this->actor);
|
||||
|
||||
action = (this->actor.params >> 6) & 7;
|
||||
EnHoll_SetupAction(this, sActionFuncs[action]);
|
||||
if (action != 0) {
|
||||
EnHoll_SetupAction(this, sActionFuncs[type]);
|
||||
if (type != ENHOLL_H_VISIBLE_NARROW) {
|
||||
this->actor.draw = NULL;
|
||||
} else {
|
||||
this->planeAlpha = 255;
|
||||
|
@ -96,12 +128,12 @@ void EnHoll_Init(Actor* thisx, PlayState* play) {
|
|||
|
||||
Actor_ProcessInitChain(&this->actor, sInitChain);
|
||||
EnHoll_ChooseAction(this);
|
||||
this->unk_14F = 0;
|
||||
this->resetBgCoverAlpha = false;
|
||||
}
|
||||
|
||||
void EnHoll_Destroy(Actor* thisx, PlayState* play) {
|
||||
s32 transitionActorIdx = GET_TRANSITION_ACTOR_INDEX(thisx);
|
||||
TransitionActorEntry* transitionEntry = &play->transiActorCtx.list[transitionActorIdx];
|
||||
s32 transitionActorIndex = GET_TRANSITION_ACTOR_INDEX(thisx);
|
||||
TransitionActorEntry* transitionEntry = &play->transiActorCtx.list[transitionActorIndex];
|
||||
|
||||
transitionEntry->id = -transitionEntry->id;
|
||||
}
|
||||
|
@ -116,34 +148,69 @@ void EnHoll_SwapRooms(PlayState* play) {
|
|||
play->roomCtx.unk_30 ^= 1;
|
||||
}
|
||||
|
||||
// Horizontal Planes
|
||||
void func_80A58DD4(EnHoll* this, PlayState* play) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
s32 phi_t0 = ((play->sceneId == SCENE_SPIRIT_TEMPLE) ? 1 : 0) & 0xFFFFFFFF;
|
||||
Vec3f vec;
|
||||
f32 absZ;
|
||||
s32 transitionActorIdx;
|
||||
/**
|
||||
* These are all absolute distances in the relative z direction. That is, moving
|
||||
* towards or away from the "face" of the holl regardless of orientation.
|
||||
* Moving within these distances of the holl have the following effects:
|
||||
* [0] : Load the room on this side of the holl if not already loaded
|
||||
* [1] : Load the room on the other side of the holl
|
||||
* [2] : Start of fade region, where the plane is fully opaque
|
||||
* [3] : End of fade region region, where the plane is fully transparent
|
||||
*
|
||||
* Within the fade region, the plane goes:
|
||||
* opaque -> transparent if approaching,
|
||||
* transparent -> opaque if receding
|
||||
*/
|
||||
static f32 sHorizontalVisibleNarrowTriggerDists[2][4] = {
|
||||
{ 200.0f, 150.0f, 100.0f, 50.0f }, // default
|
||||
{ 100.0f, 75.0f, 50.0f, 25.0f }, // SCENE_SPIRIT_TEMPLE
|
||||
};
|
||||
|
||||
func_8002DBD0(&this->actor, &vec, &player->actor.world.pos);
|
||||
this->side = (vec.z < 0.0f) ? 0 : 1;
|
||||
absZ = fabsf(vec.z);
|
||||
if (vec.y > PLANE_Y_MIN && vec.y < PLANE_Y_MAX && fabsf(vec.x) < PLANE_HALFWIDTH &&
|
||||
absZ < sHorizTriggerDists[phi_t0][0]) {
|
||||
transitionActorIdx = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
if (absZ > sHorizTriggerDists[phi_t0][1]) {
|
||||
/**
|
||||
* When traversing a holl of this kind, it attempts to:
|
||||
* Load Current Room (fails as it is already loaded)
|
||||
* Load Next Room
|
||||
* Load Previous Room
|
||||
* Load Next Room
|
||||
*
|
||||
* @bug The striped nature of holls can cause some actors to unload due to
|
||||
* conflicting Object Lists between the two rooms
|
||||
*
|
||||
* @bug If you can get around to the other side of the holl without triggering it,
|
||||
* you can load the room on the other side multiple times
|
||||
*/
|
||||
void EnHoll_HorizontalVisibleNarrow(EnHoll* this, PlayState* play) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
s32 triggerDistsIndex = (u32)((play->sceneId == SCENE_SPIRIT_TEMPLE) ? 1 : 0);
|
||||
Vec3f relPlayerPos;
|
||||
f32 orthogonalDistToPlayer;
|
||||
s32 transitionActorIndex;
|
||||
|
||||
func_8002DBD0(&this->actor, &relPlayerPos, &player->actor.world.pos);
|
||||
this->side = (relPlayerPos.z < 0.0f) ? 0 : 1;
|
||||
orthogonalDistToPlayer = fabsf(relPlayerPos.z);
|
||||
if (relPlayerPos.y > ENHOLL_H_Y_MIN && relPlayerPos.y < ENHOLL_H_Y_MAX &&
|
||||
fabsf(relPlayerPos.x) < ENHOLL_H_HALFWIDTH_NARROW &&
|
||||
orthogonalDistToPlayer < sHorizontalVisibleNarrowTriggerDists[triggerDistsIndex][0]) {
|
||||
|
||||
transitionActorIndex = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
if (orthogonalDistToPlayer > sHorizontalVisibleNarrowTriggerDists[triggerDistsIndex][1]) {
|
||||
if (play->roomCtx.prevRoom.num >= 0 && play->roomCtx.status == 0) {
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIdx].sides[this->side].room;
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIndex].sides[this->side].room;
|
||||
EnHoll_SwapRooms(play);
|
||||
func_80097534(play, &play->roomCtx);
|
||||
}
|
||||
} else {
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIdx].sides[this->side ^ 1].room;
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIndex].sides[this->side ^ 1].room;
|
||||
if (play->roomCtx.prevRoom.num < 0) {
|
||||
func_8009728C(play, &play->roomCtx, this->actor.room);
|
||||
} else {
|
||||
this->planeAlpha = (255.0f / (sHorizTriggerDists[phi_t0][2] - sHorizTriggerDists[phi_t0][3])) *
|
||||
(absZ - sHorizTriggerDists[phi_t0][3]);
|
||||
this->planeAlpha =
|
||||
(255.0f / (sHorizontalVisibleNarrowTriggerDists[triggerDistsIndex][2] -
|
||||
sHorizontalVisibleNarrowTriggerDists[triggerDistsIndex][3])) *
|
||||
(orthogonalDistToPlayer - sHorizontalVisibleNarrowTriggerDists[triggerDistsIndex][3]);
|
||||
this->planeAlpha = CLAMP(this->planeAlpha, 0, 255);
|
||||
|
||||
if (play->roomCtx.curRoom.num != this->actor.room) {
|
||||
EnHoll_SwapRooms(play);
|
||||
}
|
||||
|
@ -152,162 +219,186 @@ void func_80A58DD4(EnHoll* this, PlayState* play) {
|
|||
}
|
||||
}
|
||||
|
||||
// Horizontal Planes
|
||||
void func_80A59014(EnHoll* this, PlayState* play) {
|
||||
void EnHoll_HorizontalInvisible(EnHoll* this, PlayState* play) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
s32 useViewEye = gDebugCamEnabled || play->csCtx.state != CS_STATE_IDLE;
|
||||
Vec3f vec;
|
||||
s32 temp;
|
||||
f32 planeHalfWidth;
|
||||
f32 absZ;
|
||||
Vec3f relSubjectPos;
|
||||
s32 isKokiriLayer8;
|
||||
f32 hollHalfWidth;
|
||||
f32 orthogonalDistToSubject;
|
||||
|
||||
func_8002DBD0(&this->actor, &vec, (useViewEye) ? &play->view.eye : &player->actor.world.pos);
|
||||
planeHalfWidth = (((this->actor.params >> 6) & 7) == 6) ? PLANE_HALFWIDTH : PLANE_HALFWIDTH_2;
|
||||
func_8002DBD0(&this->actor, &relSubjectPos, useViewEye ? &play->view.eye : &player->actor.world.pos);
|
||||
hollHalfWidth =
|
||||
(ENHOLL_GET_TYPE(&this->actor) == ENHOLL_H_INVISIBLE_NARROW) ? ENHOLL_H_HALFWIDTH_NARROW : ENHOLL_H_HALFWIDTH;
|
||||
|
||||
temp = EnHoll_IsKokiriLayer8();
|
||||
if (temp || (PLANE_Y_MIN < vec.y && vec.y < PLANE_Y_MAX && fabsf(vec.x) < planeHalfWidth &&
|
||||
(absZ = fabsf(vec.z), 100.0f > absZ && absZ > 50.0f))) {
|
||||
s32 transitionActorIdx = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
s32 side = (vec.z < 0.0f) ? 0 : 1;
|
||||
TransitionActorEntry* transitionEntry = &play->transiActorCtx.list[transitionActorIdx];
|
||||
isKokiriLayer8 = EnHoll_IsKokiriLayer8();
|
||||
if (isKokiriLayer8 || (relSubjectPos.y > ENHOLL_H_Y_MIN && relSubjectPos.y < ENHOLL_H_Y_MAX &&
|
||||
fabsf(relSubjectPos.x) < hollHalfWidth &&
|
||||
(orthogonalDistToSubject = fabsf(relSubjectPos.z),
|
||||
orthogonalDistToSubject < ENHOLL_H_INVISIBLE_LOAD_DEPTH_MAX &&
|
||||
orthogonalDistToSubject > ENHOLL_H_INVISIBLE_LOAD_DEPTH_MIN))) {
|
||||
s32 transitionActorIndex = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
s32 side = (relSubjectPos.z < 0.0f) ? 0 : 1;
|
||||
TransitionActorEntry* transitionEntry = &play->transiActorCtx.list[transitionActorIndex];
|
||||
s32 room = transitionEntry->sides[side].room;
|
||||
|
||||
this->actor.room = room;
|
||||
if (temp) {}
|
||||
if (isKokiriLayer8) {}
|
||||
if (this->actor.room != play->roomCtx.curRoom.num) {
|
||||
if (room) {}
|
||||
if (func_8009728C(play, &play->roomCtx, this->actor.room)) {
|
||||
EnHoll_SetupAction(this, EnHoll_NextAction);
|
||||
EnHoll_SetupAction(this, EnHoll_WaitRoomLoaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical Planes
|
||||
void func_80A591C0(EnHoll* this, PlayState* play) {
|
||||
void EnHoll_VerticalDownBgCoverLarge(EnHoll* this, PlayState* play) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
f32 absY = fabsf(this->actor.yDistToPlayer);
|
||||
s32 transitionActorIdx;
|
||||
f32 absYDistToPlayer = fabsf(this->actor.yDistToPlayer);
|
||||
s32 transitionActorIndex;
|
||||
|
||||
if (this->actor.xzDistToPlayer < 500.0f && absY < 700.0f) {
|
||||
transitionActorIdx = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
if (absY < 95.0f) {
|
||||
play->unk_11E18 = 0xFF;
|
||||
} else if (absY > 605.0f) {
|
||||
play->unk_11E18 = 0;
|
||||
if (this->actor.xzDistToPlayer < ENHOLL_V_DOWN_RADIUS &&
|
||||
// Nothing happens if `absYDistToPlayer > ENHOLL_V_DOWN_BGCOVER_YDIST`,
|
||||
// so this check may as well compare to ENHOLL_V_DOWN_BGCOVER_YDIST
|
||||
absYDistToPlayer < (ENHOLL_V_DOWN_BGCOVER_YDIST + 95.0f)) {
|
||||
|
||||
transitionActorIndex = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
|
||||
if (absYDistToPlayer < ENHOLL_V_DOWN_LOAD_YDIST) {
|
||||
play->bgCoverAlpha = 255;
|
||||
} else if (absYDistToPlayer > ENHOLL_V_DOWN_BGCOVER_YDIST) {
|
||||
play->bgCoverAlpha = 0;
|
||||
} else {
|
||||
play->unk_11E18 = (s16)(605.0f - absY) * 0.5f;
|
||||
play->bgCoverAlpha = (s16)(ENHOLL_V_DOWN_BGCOVER_YDIST - absYDistToPlayer) *
|
||||
(255 / (ENHOLL_V_DOWN_BGCOVER_YDIST - ENHOLL_V_DOWN_LOAD_YDIST));
|
||||
}
|
||||
if (absY < 95.0f) {
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIdx].sides[1].room;
|
||||
|
||||
if (absYDistToPlayer < ENHOLL_V_DOWN_LOAD_YDIST) {
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIndex].sides[1].room;
|
||||
Math_SmoothStepToF(&player->actor.world.pos.x, this->actor.world.pos.x, 1.0f, 50.0f, 10.0f);
|
||||
Math_SmoothStepToF(&player->actor.world.pos.z, this->actor.world.pos.z, 1.0f, 50.0f, 10.0f);
|
||||
if (this->actor.room != play->roomCtx.curRoom.num &&
|
||||
func_8009728C(play, &play->roomCtx, this->actor.room) != 0) {
|
||||
EnHoll_SetupAction(this, EnHoll_NextAction);
|
||||
this->unk_14F = 1;
|
||||
func_8009728C(play, &play->roomCtx, this->actor.room)) {
|
||||
EnHoll_SetupAction(this, EnHoll_WaitRoomLoaded);
|
||||
this->resetBgCoverAlpha = true;
|
||||
player->actor.speed = 0.0f;
|
||||
}
|
||||
}
|
||||
} else if (this->unk_14F != 0) {
|
||||
play->unk_11E18 = 0;
|
||||
this->unk_14F = 0;
|
||||
} else {
|
||||
if (this->resetBgCoverAlpha) {
|
||||
play->bgCoverAlpha = 0;
|
||||
this->resetBgCoverAlpha = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical Planes
|
||||
void func_80A593A4(EnHoll* this, PlayState* play) {
|
||||
f32 absY;
|
||||
void EnHoll_VerticalBgCover(EnHoll* this, PlayState* play) {
|
||||
f32 absYDistToPlayer;
|
||||
s32 side;
|
||||
s32 transitionActorIdx;
|
||||
s32 transitionActorIndex;
|
||||
|
||||
if ((this->actor.xzDistToPlayer < 120.0f) && (absY = fabsf(this->actor.yDistToPlayer), absY < 200.0f)) {
|
||||
if (absY < 50.0f) {
|
||||
play->unk_11E18 = 0xFF;
|
||||
if ((this->actor.xzDistToPlayer < ENHOLL_V_RADIUS) &&
|
||||
(absYDistToPlayer = fabsf(this->actor.yDistToPlayer), absYDistToPlayer < ENHOLL_V_BGCOVER_BGCOVER_YDIST)) {
|
||||
|
||||
if (absYDistToPlayer < ENHOLL_V_BGCOVER_LOAD_YDIST) {
|
||||
play->bgCoverAlpha = 255;
|
||||
} else {
|
||||
play->unk_11E18 = (200.0f - absY) * 1.7f;
|
||||
play->bgCoverAlpha = (ENHOLL_V_BGCOVER_BGCOVER_YDIST - absYDistToPlayer) *
|
||||
(255 / (ENHOLL_V_BGCOVER_BGCOVER_YDIST - ENHOLL_V_BGCOVER_LOAD_YDIST));
|
||||
}
|
||||
if (absY > 50.0f) {
|
||||
transitionActorIdx = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
side = (0.0f < this->actor.yDistToPlayer) ? 0 : 1;
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIdx].sides[side].room;
|
||||
|
||||
if (absYDistToPlayer > ENHOLL_V_BGCOVER_LOAD_YDIST) {
|
||||
transitionActorIndex = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
side = (this->actor.yDistToPlayer > 0.0f) ? 0 : 1;
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIndex].sides[side].room;
|
||||
if (this->actor.room != play->roomCtx.curRoom.num &&
|
||||
func_8009728C(play, &play->roomCtx, this->actor.room) != 0) {
|
||||
EnHoll_SetupAction(this, EnHoll_NextAction);
|
||||
this->unk_14F = 1;
|
||||
func_8009728C(play, &play->roomCtx, this->actor.room)) {
|
||||
EnHoll_SetupAction(this, EnHoll_WaitRoomLoaded);
|
||||
this->resetBgCoverAlpha = true;
|
||||
}
|
||||
}
|
||||
} else if (this->unk_14F != 0) {
|
||||
this->unk_14F = 0;
|
||||
play->unk_11E18 = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Vertical Planes
|
||||
void func_80A59520(EnHoll* this, PlayState* play) {
|
||||
f32 absY;
|
||||
s8 side;
|
||||
s32 transitionActorIdx;
|
||||
|
||||
if (this->actor.xzDistToPlayer < 120.0f) {
|
||||
absY = fabsf(this->actor.yDistToPlayer);
|
||||
if (absY < 200.0f && absY > 50.0f) {
|
||||
transitionActorIdx = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
side = (0.0f < this->actor.yDistToPlayer) ? 0 : 1;
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIdx].sides[side].room;
|
||||
if (this->actor.room != play->roomCtx.curRoom.num &&
|
||||
func_8009728C(play, &play->roomCtx, this->actor.room) != 0) {
|
||||
EnHoll_SetupAction(this, EnHoll_NextAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Horizontal Planes
|
||||
void func_80A59618(EnHoll* this, PlayState* play) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
Vec3f vec;
|
||||
f32 absZ;
|
||||
s32 side;
|
||||
s32 transitionActorIdx;
|
||||
|
||||
if (!Flags_GetSwitch(play, this->actor.params & 0x3F)) {
|
||||
if (this->unk_14F != 0) {
|
||||
play->unk_11E18 = 0;
|
||||
this->unk_14F = 0;
|
||||
}
|
||||
} else {
|
||||
func_8002DBD0(&this->actor, &vec, &player->actor.world.pos);
|
||||
absZ = fabsf(vec.z);
|
||||
if (PLANE_Y_MIN < vec.y && vec.y < PLANE_Y_MAX && fabsf(vec.x) < PLANE_HALFWIDTH_2 && absZ < 100.0f) {
|
||||
this->unk_14F = 1;
|
||||
transitionActorIdx = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
play->unk_11E18 = 0xFF - (s32)((absZ - 50.0f) * 5.9f);
|
||||
if (play->unk_11E18 >= 0x100) {
|
||||
play->unk_11E18 = 0xFF;
|
||||
} else if (play->unk_11E18 < 0) {
|
||||
play->unk_11E18 = 0;
|
||||
}
|
||||
if (absZ < 50.0f) {
|
||||
side = (vec.z < 0.0f) ? 0 : 1;
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIdx].sides[side].room;
|
||||
if (this->actor.room != play->roomCtx.curRoom.num &&
|
||||
func_8009728C(play, &play->roomCtx, this->actor.room) != 0) {
|
||||
EnHoll_SetupAction(this, EnHoll_NextAction);
|
||||
}
|
||||
}
|
||||
} else if (this->unk_14F != 0) {
|
||||
play->unk_11E18 = 0;
|
||||
this->unk_14F = 0;
|
||||
if (this->resetBgCoverAlpha) {
|
||||
this->resetBgCoverAlpha = false;
|
||||
play->bgCoverAlpha = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnHoll_NextAction(EnHoll* this, PlayState* play) {
|
||||
void EnHoll_VerticalInvisible(EnHoll* this, PlayState* play) {
|
||||
f32 absYDistToPlayer;
|
||||
s8 side;
|
||||
s32 transitionActorIndex;
|
||||
|
||||
if (this->actor.xzDistToPlayer < ENHOLL_V_RADIUS) {
|
||||
absYDistToPlayer = fabsf(this->actor.yDistToPlayer);
|
||||
if (absYDistToPlayer < ENHOLL_V_INVISIBLE_LOAD_YDIST_MAX &&
|
||||
absYDistToPlayer > ENHOLL_V_INVISIBLE_LOAD_YDIST_MIN) {
|
||||
transitionActorIndex = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
side = (this->actor.yDistToPlayer > 0.0f) ? 0 : 1;
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIndex].sides[side].room;
|
||||
if (this->actor.room != play->roomCtx.curRoom.num &&
|
||||
func_8009728C(play, &play->roomCtx, this->actor.room)) {
|
||||
EnHoll_SetupAction(this, EnHoll_WaitRoomLoaded);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnHoll_HorizontalBgCoverSwitchFlag(EnHoll* this, PlayState* play) {
|
||||
Player* player = GET_PLAYER(play);
|
||||
Vec3f relPlayerPos;
|
||||
f32 orthogonalDistToPlayer;
|
||||
s32 side;
|
||||
s32 transitionActorIndex;
|
||||
|
||||
if (!Flags_GetSwitch(play, ENHOLL_GET_SWITCH_FLAG(&this->actor))) {
|
||||
if (this->resetBgCoverAlpha) {
|
||||
play->bgCoverAlpha = 0;
|
||||
this->resetBgCoverAlpha = false;
|
||||
}
|
||||
} else {
|
||||
func_8002DBD0(&this->actor, &relPlayerPos, &player->actor.world.pos);
|
||||
orthogonalDistToPlayer = fabsf(relPlayerPos.z);
|
||||
|
||||
if (ENHOLL_H_Y_MIN < relPlayerPos.y && relPlayerPos.y < ENHOLL_H_Y_MAX &&
|
||||
fabsf(relPlayerPos.x) < ENHOLL_H_HALFWIDTH && orthogonalDistToPlayer < ENHOLL_H_SWITCHFLAG_BGCOVER_DEPTH) {
|
||||
|
||||
this->resetBgCoverAlpha = true;
|
||||
transitionActorIndex = GET_TRANSITION_ACTOR_INDEX(&this->actor);
|
||||
|
||||
play->bgCoverAlpha =
|
||||
255 - (s32)((orthogonalDistToPlayer - ENHOLL_H_SWITCHFLAG_LOAD_DEPTH) *
|
||||
(255 / (ENHOLL_H_SWITCHFLAG_BGCOVER_DEPTH - ENHOLL_H_SWITCHFLAG_LOAD_DEPTH) + 0.8f));
|
||||
if (play->bgCoverAlpha > 255) {
|
||||
play->bgCoverAlpha = 255;
|
||||
} else if (play->bgCoverAlpha < 0) {
|
||||
play->bgCoverAlpha = 0;
|
||||
}
|
||||
|
||||
if (orthogonalDistToPlayer < ENHOLL_H_SWITCHFLAG_LOAD_DEPTH) {
|
||||
side = (relPlayerPos.z < 0.0f) ? 0 : 1;
|
||||
this->actor.room = play->transiActorCtx.list[transitionActorIndex].sides[side].room;
|
||||
if (this->actor.room != play->roomCtx.curRoom.num &&
|
||||
func_8009728C(play, &play->roomCtx, this->actor.room)) {
|
||||
EnHoll_SetupAction(this, EnHoll_WaitRoomLoaded);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this->resetBgCoverAlpha) {
|
||||
play->bgCoverAlpha = 0;
|
||||
this->resetBgCoverAlpha = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EnHoll_WaitRoomLoaded(EnHoll* this, PlayState* play) {
|
||||
if (!EnHoll_IsKokiriLayer8() && play->roomCtx.status == 0) {
|
||||
func_80097534(play, &play->roomCtx);
|
||||
if (play->unk_11E18 == 0) {
|
||||
this->unk_14F = 0;
|
||||
if (play->bgCoverAlpha == 0) {
|
||||
this->resetBgCoverAlpha = false;
|
||||
}
|
||||
EnHoll_ChooseAction(this);
|
||||
}
|
||||
|
@ -324,7 +415,7 @@ void EnHoll_Update(Actor* thisx, PlayState* play) {
|
|||
void EnHoll_Draw(Actor* thisx, PlayState* play) {
|
||||
EnHoll* this = (EnHoll*)thisx;
|
||||
Gfx* gfxP;
|
||||
u32 setupDlIdx;
|
||||
u32 setupDLIndex;
|
||||
|
||||
// Only draw the plane if not invisible
|
||||
if (this->planeAlpha != 0) {
|
||||
|
@ -332,12 +423,12 @@ void EnHoll_Draw(Actor* thisx, PlayState* play) {
|
|||
|
||||
if (this->planeAlpha == 255) {
|
||||
gfxP = POLY_OPA_DISP;
|
||||
setupDlIdx = SETUPDL_37;
|
||||
setupDLIndex = SETUPDL_37;
|
||||
} else {
|
||||
gfxP = POLY_XLU_DISP;
|
||||
setupDlIdx = SETUPDL_0;
|
||||
setupDLIndex = SETUPDL_0;
|
||||
}
|
||||
gfxP = Gfx_SetupDL(gfxP, setupDlIdx);
|
||||
gfxP = Gfx_SetupDL(gfxP, setupDLIndex);
|
||||
if (this->side == 0) {
|
||||
Matrix_RotateY(M_PI, MTXMODE_APPLY);
|
||||
}
|
||||
|
|
|
@ -4,6 +4,35 @@
|
|||
#include "ultra64.h"
|
||||
#include "global.h"
|
||||
|
||||
#define ENHOLL_GET_TYPE(thisx) (((thisx)->params >> 6) & 7)
|
||||
#define ENHOLL_GET_SWITCH_FLAG(thisx) ((thisx)->params & 0x3F)
|
||||
|
||||
/**
|
||||
* Two kinds of holls:
|
||||
* Horizontal (H):
|
||||
* For the player to move horizontally between rooms.
|
||||
* Cuboid-shaped:
|
||||
* - height: 200 units high plus 50 units into the ground
|
||||
* - width: 400 units wide or, if narrow, 200 units wide
|
||||
* Vertical (V):
|
||||
* For the player to move vertically between rooms.
|
||||
* Cylinder-shaped, radius of 120 units.
|
||||
*
|
||||
* Three kinds of visual effects:
|
||||
* Visible: A plane is drawn at the holl location, and fades away as the player approaches.
|
||||
* Bg Cover: The background geometry (e.g. room geometry but not actors) fades black as the player approaches.
|
||||
* Invisible: Approaching the holl does not cause any particular visual effect.
|
||||
*/
|
||||
typedef enum {
|
||||
/* 0 */ ENHOLL_H_VISIBLE_NARROW,
|
||||
/* 1 */ ENHOLL_V_DOWN_BGCOVER_LARGE, // Only allows downwards transitions. 500 units radius. Used in fire temple drops.
|
||||
/* 2 */ ENHOLL_V_INVISIBLE,
|
||||
/* 3 */ ENHOLL_H_BGCOVER_SWITCHFLAG, // Enabled if a switch flag is set. Used in Dampe's race.
|
||||
/* 4 */ ENHOLL_H_INVISIBLE,
|
||||
/* 5 */ ENHOLL_V_BGCOVER,
|
||||
/* 6 */ ENHOLL_H_INVISIBLE_NARROW
|
||||
} EnHollType;
|
||||
|
||||
struct EnHoll;
|
||||
|
||||
typedef void (*EnHollActionFunc)(struct EnHoll*, PlayState*);
|
||||
|
@ -12,7 +41,7 @@ typedef struct EnHoll {
|
|||
/* 0x0000 */ Actor actor;
|
||||
/* 0x014C */ s16 planeAlpha;
|
||||
/* 0x014E */ u8 side;
|
||||
/* 0x014F */ u8 unk_14F;
|
||||
/* 0x014F */ u8 resetBgCoverAlpha;
|
||||
/* 0x0150 */ EnHollActionFunc actionFunc;
|
||||
} EnHoll; // size = 0x0154
|
||||
|
||||
|
|
Loading…
Reference in a new issue