From 06f1e8b01e509ae4d627ae4b0dab5baae0f91f53 Mon Sep 17 00:00:00 2001 From: Eblo <7004497+Eblo@users.noreply.github.com> Date: Mon, 18 Aug 2025 22:23:52 -0400 Subject: [PATCH] Add restoration for NTSC 1.0 shutter door range --- .../Restorations/WideShutterDoorRanges.cpp | 31 +++++++++++++++++++ .../vanilla-behavior/GIVanillaBehavior.h | 8 +++++ soh/soh/SohGui/SohMenuEnhancements.cpp | 4 +++ .../actors/ovl_Door_Shutter/z_door_shutter.c | 2 +- 4 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp diff --git a/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp b/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp new file mode 100644 index 000000000..8f5fc4f30 --- /dev/null +++ b/soh/soh/Enhancements/Restorations/WideShutterDoorRanges.cpp @@ -0,0 +1,31 @@ +#include "public/bridge/consolevariablebridge.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "src/overlays/actors/ovl_Door_Shutter/z_door_shutter.h" +} + +#define CVAR_WIDE_SHUTTER_DOOR_RANGE CVAR_ENHANCEMENT("WideShutterDoorRange") +#define WIDE_SHUTTER_DOOR_RANGE_DEFAULT 0 +#define CVAR_WIDE_SHUTTER_DOOR_RANGE_VALUE CVarGetInteger(CVAR_WIDE_SHUTTER_DOOR_RANGE, WIDE_SHUTTER_DOOR_RANGE_DEFAULT) + +// The X range is 70 on NTSC 1.0 and 50 in later versions. The Y range is 15 in any version. +// https://github.com/zeldaret/oot/blob/6ecb84097c1a9a8426f3815c84aa6a5d49ad5804/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c#L248-L259 +#define SHUTTER_DOOR_RANGE_X 70 +#define SHUTTER_DOOR_RANGE_Y 15 + +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*); + // Jabu-Jabu door, Phantom Ganon bars, Gohma door, or boss door + if (doorShutter->unk_16C == 3 || doorShutter->unk_16C == 4 || doorShutter->unk_16C == 5 || + doorShutter->unk_16C == 7) { + *should = (SHUTTER_DOOR_RANGE_X < fabsf(relPlayerPos.x) || SHUTTER_DOOR_RANGE_Y < fabsf(relPlayerPos.y)); + } + }); +} + +static RegisterShipInitFunc initFunc_WideShutterDoorRange(RegisterWideShutterDoorRange, + { CVAR_WIDE_SHUTTER_DOOR_RANGE }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 09defd088..7e517155b 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2245,6 +2245,14 @@ typedef enum { // #### `args` // - `*EnBox` VB_CHEST_USE_ICE_EFFECT, + + // #### `result` + // ```c + // arg3 < fabsf(sp1C.x) || arg4 < fabsf(sp1C.y) + // ``` + // #### `args` + // - `*DoorShutter` + VB_BE_NEAR_DOOR_SHUTTER, } GIVanillaBehavior; #endif diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 488aeb720..74062164c 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1161,6 +1161,10 @@ void SohMenu::AddMenuEnhancements() { .CVar(CVAR_ENHANCEMENT("NGCKaleidoSwitcher")) .Options(CheckboxOptions().Tooltip( "Makes L and R switch pages like on the GameCube. Z opens the Debug Menu instead.")); + AddWidget(path, "Wide Door Ranges", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_ENHANCEMENT("WideShutterDoorRange")) + .Options(CheckboxOptions().Tooltip("Restores the wider range of certain shutter doors from NTSC 1.0.\n" + "Notably affects Jabu-Jabu and boss doors.")); // Difficulty Options path.sidebarName = "Difficulty"; 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 1a491064a..ea983771f 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,7 @@ f32 func_80996840(PlayState* play, DoorShutter* this, f32 arg2, f32 arg3, f32 ar sp28.y = player->actor.world.pos.y + arg2; sp28.z = player->actor.world.pos.z; Actor_WorldToActorCoords(&this->dyna.actor, &sp1C, &sp28); - if (arg3 < fabsf(sp1C.x) || arg4 < fabsf(sp1C.y)) { + if (GameInteractor_Should(VB_BE_NEAR_DOOR_SHUTTER, arg3 < fabsf(sp1C.x) || arg4 < fabsf(sp1C.y), this, &sp1C)) { return FLT_MAX; } else { return sp1C.z;