summaryrefslogtreecommitdiff
path: root/soh
diff options
context:
space:
mode:
authordjevangelia <263709373+djevangelia@users.noreply.github.com>2026-07-19 19:04:32 +0200
committerGitHub <noreply@github.com>2026-07-19 17:04:32 +0000
commite579e7b9a463af78ec0ea0ea6cc67db309a4ca43 (patch)
treefb03f13854999a56d92b1c88f73f6d9561618f24 /soh
parent8cb0c745920989d31322ceeba2edb2bbf48ea402 (diff)
Polishing, climb everything door opening + sloped ledge climb up (#6936)
Allow player to try opening doors while climbing. Player can't open anything if a door doesn't offer it, so it's ok to try. Handle doors don't change player y position (player walks in the air), so manually lower it. Increase y height limit for doors to offer open from 15.0f/20.0f to 50.0f (normal door height). (For shutter doors height could be individualized depending on shutter door type in the future.) Make climbing up animation play even for sloped ledges. The animation/action breaks because game thinks player is not on ground. So, at the end of Player_ProcessSceneCollision, if player is in climbing up action, manually set BGCHECKFLAG_GROUND.
Diffstat (limited to 'soh')
-rw-r--r--soh/include/functions.h2
-rw-r--r--soh/soh/Enhancements/Cheats/ClimbEverything.cpp51
-rw-r--r--soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp2
-rw-r--r--soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h18
-rw-r--r--soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c4
-rw-r--r--soh/src/overlays/actors/ovl_En_Door/z_en_door.c6
-rw-r--r--soh/src/overlays/actors/ovl_player_actor/z_player.c2
7 files changed, 82 insertions, 3 deletions
diff --git a/soh/include/functions.h b/soh/include/functions.h
index 942f83a3b..af88ca2d9 100644
--- a/soh/include/functions.h
+++ b/soh/include/functions.h
@@ -1102,6 +1102,8 @@ void Path_CopyLastPoint(Path* path, Vec3f* dest);
void FrameAdvance_Init(FrameAdvanceContext* frameAdvCtx);
s32 FrameAdvance_Update(FrameAdvanceContext* frameAdvCtx, Input* input);
u8 PlayerGrounded(Player* player);
+s32 Player_ActionHandler_1(Player* player, PlayState* play);
+void Player_Action_8084BDFC(Player* player, PlayState* play);
void Player_SetBootData(PlayState* play, Player* player);
void Player_StartAnimMovement(PlayState* play, Player* player, s32 flags);
s32 Player_InBlockingCsMode(PlayState* play, Player* player);
diff --git a/soh/soh/Enhancements/Cheats/ClimbEverything.cpp b/soh/soh/Enhancements/Cheats/ClimbEverything.cpp
index 5c027c706..c3b2c808c 100644
--- a/soh/soh/Enhancements/Cheats/ClimbEverything.cpp
+++ b/soh/soh/Enhancements/Cheats/ClimbEverything.cpp
@@ -2,10 +2,61 @@
#include "soh/ShipInit.hpp"
#include "soh/cvar_prefixes.h"
+extern "C" {
+#include "functions.h"
+#include "macros.h"
+#include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h"
+extern PlayState* gPlayState;
+}
+
static void RegisterClimbEverything() {
COND_VB_SHOULD(VB_SURFACE_IS_CLIMBABLE, CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0), { *should = true; });
COND_VB_SHOULD(VB_SURFACE_ANGLE_IS_CLIMBABLE, CVarGetInteger(CVAR_CHEAT("ClimbEverything"), 0),
{ *should = true; });
+
+ COND_VB_SHOULD(VB_CLIMB, CVarGetInteger(CVAR_CHEAT("ClimbEverything"), false), {
+ Player* player = GET_PLAYER(gPlayState);
+
+ // Allow try opening door while climbing
+ if (Player_ActionHandler_1(player, gPlayState)) {
+ *should = false;
+ if (player->doorType == PLAYER_DOORTYPE_HANDLE) {
+ player->actor.world.pos.y = player->doorActor->world.pos.y;
+ }
+ }
+ });
+
+ COND_VB_SHOULD(VB_AFTER_PROCESS_SCENE_COLLISION, CVarGetInteger(CVAR_CHEAT("ClimbEverything"), false), {
+ Player* player = GET_PLAYER(gPlayState);
+
+ // Keep climb up animation on sloping ledges
+ if (player->actionFunc == Player_Action_8084BDFC) {
+ player->actor.bgCheckFlags |= BGCHECKFLAG_GROUND;
+ }
+ });
+
+ COND_VB_SHOULD(VB_EN_DOOR_OFFER_OPEN, CVarGetInteger(CVAR_CHEAT("ClimbEverything"), false), {
+ Vec3f playerPosRelToDoor = *va_arg(args, Vec3f*);
+ Player* player = GET_PLAYER(gPlayState);
+
+ // Set higher y distance limit to offer open door
+ if (fabsf(playerPosRelToDoor.y) < 50.0f && fabsf(playerPosRelToDoor.x) < 20.0f &&
+ fabsf(playerPosRelToDoor.z) < 50.0f) {
+ *should = true;
+ }
+ });
+
+ COND_VB_SHOULD(VB_BE_NEAR_DOOR_SHUTTER, CVarGetInteger(CVAR_CHEAT("ClimbEverything"), false), {
+ DoorShutter* doorShutter = va_arg(args, DoorShutter*);
+ Vec3f relPlayerPos = *va_arg(args, Vec3f*);
+ f32* maxDistSides = va_arg(args, f32*);
+
+ // Set higher y distance limit to offer open door
+ // Todo: Individualize this y depending on shutter door type.
+ if (fabsf(relPlayerPos.x) < *maxDistSides && fabsf(relPlayerPos.y) < 50.0f) {
+ *should = false;
+ }
+ });
}
static RegisterShipInitFunc initFunc(RegisterClimbEverything, { CVAR_CHEAT("ClimbEverything") });
diff --git a/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp b/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp
index 7b55b3c81..ce9b7e7a1 100644
--- a/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp
+++ b/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp
@@ -19,6 +19,8 @@ void RegisterWideShutterDoorRange() {
COND_VB_SHOULD(VB_BE_NEAR_DOOR_SHUTTER, CVAR_WIDE_SHUTTER_DOOR_RANGE_VALUE, {
DoorShutter* doorShutter = va_arg(args, DoorShutter*);
Vec3f relPlayerPos = *va_arg(args, Vec3f*);
+ f32* maxDistSides = va_arg(args, f32*);
+
if (doorShutter->gfxType == SHUTTER_BACK_LOCKED || doorShutter->gfxType == SHUTTER_PG_BARS ||
doorShutter->gfxType == SHUTTER_BOSS || doorShutter->gfxType == SHUTTER_GOHMA_BLOCK) {
*should = (SHUTTER_DOOR_RANGE_X < fabsf(relPlayerPos.x) || SHUTTER_DOOR_RANGE_Y < fabsf(relPlayerPos.y));
diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
index c550186bc..f8196a1a1 100644
--- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
+++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h
@@ -369,6 +369,14 @@ typedef enum {
// #### `result`
// ```c
+ // true
+ // ```
+ // #### `args`
+ // - None
+ VB_AFTER_PROCESS_SCENE_COLLISION,
+
+ // #### `result`
+ // ```c
// CHECK_BTN_ALL(input->press.button, BTN_START)
// ```
// #### `args`
@@ -2945,10 +2953,20 @@ typedef enum {
// ```
// #### `args`
// - `*DoorShutter`
+ // - `*Vec3f` (relPlayerPos)
+ // - `*f32` (maxDistSides)
VB_BE_NEAR_DOOR_SHUTTER,
// #### `result`
// ```c
+ // arg3 < fabsf(sp1C.x) || arg4 < fabsf(sp1C.y)
+ // ```
+ // #### `args`
+ // - `*Vec3f` (playerPosRelToDoor)
+ VB_EN_DOOR_OFFER_OPEN,
+
+ // #### `result`
+ // ```c
// CVarGetInteger(CVAR_ENHANCEMENT("3DSceneRender"), 0)
// ```
// #### `args`
diff --git a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c
index c402fe9a7..cefffeea8 100644
--- a/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c
+++ b/soh/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c
@@ -335,7 +335,9 @@ f32 DoorShutter_GetPlayerDistance(PlayState* play, DoorShutter* this, f32 arg2,
sp28.y = player->actor.world.pos.y + arg2;
sp28.z = player->actor.world.pos.z;
Actor_WorldToActorCoords(&this->dyna.actor, &sp1C, &sp28);
- if (GameInteractor_Should(VB_BE_NEAR_DOOR_SHUTTER, arg3 < fabsf(sp1C.x) || arg4 < fabsf(sp1C.y), this, &sp1C)) {
+
+ if (GameInteractor_Should(VB_BE_NEAR_DOOR_SHUTTER, (arg3 < fabsf(sp1C.x) || arg4 < fabsf(sp1C.y)), this, &sp1C,
+ &arg3)) {
return FLT_MAX;
} else {
return sp1C.z;
diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c
index 4ed0b710e..60a08afbc 100644
--- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c
+++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c
@@ -212,8 +212,10 @@ void EnDoor_Idle(EnDoor* this, PlayState* play) {
GameInteractor_ExecuteOnDungeonKeyUsedHooks(gSaveContext.mapIndex);
}
} else if (!Player_InCsMode(play)) {
- if (fabsf(playerPosRelToDoor.y) < 20.0f && fabsf(playerPosRelToDoor.x) < 20.0f &&
- fabsf(playerPosRelToDoor.z) < 50.0f) {
+ if (GameInteractor_Should(VB_EN_DOOR_OFFER_OPEN,
+ (fabsf(playerPosRelToDoor.y) < 20.0f && fabsf(playerPosRelToDoor.x) < 20.0f &&
+ fabsf(playerPosRelToDoor.z) < 50.0f),
+ &playerPosRelToDoor)) {
phi_v0 = player->actor.shape.rot.y - this->actor.shape.rot.y;
if (playerPosRelToDoor.z > 0.0f) {
phi_v0 = 0x8000 - phi_v0;
diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c
index 8b164513d..62f2d09f5 100644
--- a/soh/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c
@@ -11437,6 +11437,8 @@ void Player_ProcessSceneCollision(PlayState* play, Player* this) {
this->prevFloorType = sFloorType;
this->floorTypeTimer = 0;
}
+
+ GameInteractor_Should(VB_AFTER_PROCESS_SCENE_COLLISION, true);
}
void Player_UpdateCamAndSeqModes(PlayState* play, Player* this) {