From 098cb7046059445c3dcfb2ff9e568a858f3384a1 Mon Sep 17 00:00:00 2001 From: nclok1405 <155463060+nclok1405@users.noreply.github.com> Date: Thu, 4 Dec 2025 11:15:49 +0900 Subject: [PATCH] Disable Screen Flash for Finishing Blow option (#5988) --- .../A11yNoScreenFlashForFinishingBlow.cpp | 25 +++++++++++++++++++ .../vanilla-behavior/GIVanillaBehavior.h | 8 ++++++ soh/soh/SohGui/SohMenuSettings.cpp | 4 +++ soh/src/code/z_play.c | 18 +++++++------ 4 files changed, 47 insertions(+), 8 deletions(-) create mode 100644 soh/soh/Enhancements/cosmetics/A11yNoScreenFlashForFinishingBlow.cpp diff --git a/soh/soh/Enhancements/cosmetics/A11yNoScreenFlashForFinishingBlow.cpp b/soh/soh/Enhancements/cosmetics/A11yNoScreenFlashForFinishingBlow.cpp new file mode 100644 index 000000000..c093594ef --- /dev/null +++ b/soh/soh/Enhancements/cosmetics/A11yNoScreenFlashForFinishingBlow.cpp @@ -0,0 +1,25 @@ +#include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "functions.h" +#include "macros.h" + +extern PlayState* gPlayState; +} + +static constexpr int32_t CVAR_A11YNOSCREENFLASHFORFINISHINGBLOW_DEFAULT = 0; +#define CVAR_A11YNOSCREENFLASHFORFINISHINGBLOW_NAME CVAR_SETTING("A11yNoScreenFlashForFinishingBlow") +#define CVAR_A11YNOSCREENFLASHFORFINISHINGBLOW_VALUE \ + CVarGetInteger(CVAR_A11YNOSCREENFLASHFORFINISHINGBLOW_NAME, CVAR_A11YNOSCREENFLASHFORFINISHINGBLOW_DEFAULT) + +static void RegisterA11yNoScreenFlashForFinishingBlow() { + COND_VB_SHOULD(VB_FLASH_SCREEN_FOR_FINISHING_BLOW, CVAR_A11YNOSCREENFLASHFORFINISHINGBLOW_VALUE, { + *should = false; + gPlayState->envCtx.fillScreen = false; // Force screen fill disabled + }); +} + +static RegisterShipInitFunc initFunc(RegisterA11yNoScreenFlashForFinishingBlow, + { CVAR_A11YNOSCREENFLASHFORFINISHINGBLOW_NAME }); diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index d0b017d96..62da37bcb 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -535,6 +535,14 @@ typedef enum { // - None VB_FIX_SAW_SOFTLOCK, + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - None + VB_FLASH_SCREEN_FOR_FINISHING_BLOW, + // #### `result` // ```c // true diff --git a/soh/soh/SohGui/SohMenuSettings.cpp b/soh/soh/SohGui/SohMenuSettings.cpp index 35abc38a3..3ea0d8d34 100644 --- a/soh/soh/SohGui/SohMenuSettings.cpp +++ b/soh/soh/SohGui/SohMenuSettings.cpp @@ -231,6 +231,10 @@ void SohMenu::AddMenuSettings() { .CVar(CVAR_SETTING("A11yDisableIdleCam")) .RaceDisable(false) .Options(CheckboxOptions().Tooltip("Disables the automatic re-centering of the camera when idle.")); + AddWidget(path, "Disable Screen Flash for Finishing Blow", WIDGET_CVAR_CHECKBOX) + .CVar(CVAR_SETTING("A11yNoScreenFlashForFinishingBlow")) + .RaceDisable(false) + .Options(CheckboxOptions().Tooltip("Disables the white screen flash on enemy kill.")); AddWidget(path, "EXPERIMENTAL", WIDGET_SEPARATOR_TEXT).Options(TextOptions().Color(Colors::Orange)); AddWidget(path, "ImGui Menu Scaling", WIDGET_CVAR_COMBOBOX) .CVar(CVAR_SETTING("ImGuiScale")) diff --git a/soh/src/code/z_play.c b/soh/src/code/z_play.c index b1a714dcb..89583e598 100644 --- a/soh/src/code/z_play.c +++ b/soh/src/code/z_play.c @@ -1180,15 +1180,17 @@ void Play_Update(PlayState* play) { } if (play->actorCtx.freezeFlashTimer && (play->actorCtx.freezeFlashTimer-- < 5)) { - osSyncPrintf("FINISH=%d\n", play->actorCtx.freezeFlashTimer); + if (GameInteractor_Should(VB_FLASH_SCREEN_FOR_FINISHING_BLOW, true)) { + osSyncPrintf("FINISH=%d\n", play->actorCtx.freezeFlashTimer); - if ((play->actorCtx.freezeFlashTimer > 0) && ((play->actorCtx.freezeFlashTimer % 2) != 0)) { - play->envCtx.fillScreen = true; - play->envCtx.screenFillColor[0] = play->envCtx.screenFillColor[1] = - play->envCtx.screenFillColor[2] = 150; - play->envCtx.screenFillColor[3] = 80; - } else { - play->envCtx.fillScreen = false; + if ((play->actorCtx.freezeFlashTimer > 0) && ((play->actorCtx.freezeFlashTimer % 2) != 0)) { + play->envCtx.fillScreen = true; + play->envCtx.screenFillColor[0] = play->envCtx.screenFillColor[1] = + play->envCtx.screenFillColor[2] = 150; + play->envCtx.screenFillColor[3] = 80; + } else { + play->envCtx.fillScreen = false; + } } } else { PLAY_LOG(3606);