QoL: Game.NoHitFlash toggle (D232) (#58)

* QoL: Game.NoHitFlash toggle (D232, route-(b) in currentPlayerSetFadeColour)

The community 'no damage flash' option. Every fade routes through
currentPlayerSetFadeColour; the only non-black ones are the two damage
paths (white g_DamageTypes envelope + red 150,0,0 death overlay), so
zeroing the RGB there kills exactly the hit flash and leaves blackouts,
the colour screen and the death fade untouched. Default 0 = original.

Frame A/B verification in progress; finding entry to follow.

* D232: add GE_NOHITFLASH_TRACE diagnostic to currentPlayerSetFadeColour

Env-gated osSyncPrintf (pattern per GE_D160) logging r/g/b/frac/caller
whenever a non-black fade reaches the gate. Used to resolve the frame-A/B
anomaly from the previous session: zero trace fires during a headless
no-input BUNKER1 run confirms the gate is inert absent real damage, and a
controlled ini-toggled A/B (framediff.py, exact + tolerant modes) shows
the gate's visual effect (99/100 frames match) is far smaller than the
port's own run-to-run noise floor (0/100 match between two runs of the
identical build) — the anomaly was D117 nondeterminism, not a real bug.
Full writeup in docs/HANDOFF.md (local, gitignored).

Claude-Session: https://claude.ai/code/session_016TaKy6AAsVUTfjkhrX6CjG

* D232 fix: zero frac too, not just RGB, in the NoHitFlash gate

User playtest found the white hit-flash was gone but a black fade-to-black
still played on every hit -- the gate zeroed r/g/b but left frac (the
overlay's alpha/opacity) untouched, so a fully-opaque BLACK rectangle drew
at the same envelope the white one would have. Same visual intrusion,
different colour, not what the toggle promises.

Fix: zero frac too when the gate fires, so the overlay doesn't draw at
all. This also drops the GE_NOHITFLASH_TRACE diagnostic added earlier
this session to hunt the original (unrelated, since-resolved) headless
frame-diff anomaly -- no longer needed now that the real bug is fixed and
user-verified in a live playtest.

User-verified: hit flash fully gone, no residual black flash, blackouts/
colour-screen/death-fade untouched.
This commit is contained in:
James Dansereau authored and GitHub committed 2026-09-12 09:20:13 -04:00
1 parent a24495672e
commit 8f0abae18f
2 files changed
+30

No files matched your search

+6
View File
@@ -86,6 +86,11 @@ f32 portScreenShakeScale = 1.0f;
* 0 (default) = the legal screen + logo attract sequence plays as normal. */
s32 portSkipIntro = 0;
/* D232: Game.NoHitFlash — the community "no damage flash" toggle (route-(b)
* hook in src/game/bondview2.c currentPlayerSetFadeColour). 0 (default) =
* original damage flash. */
s32 portNoHitFlash = 0;
/* D211: Video.FovScale as a multiplier on the render FOV. Applied game-side
* at the guPerspectiveF chokepoint (src/fr.c) so it lands BEFORE the CPU
* pre-multiplies projection x view into the combined world matrix — the
@@ -97,6 +102,7 @@ PD_CONSTRUCTOR static void videoConfigInit(void)
{
configRegisterFloat("Game.ScreenShakeIntensity", &portScreenShakeScale, 0.0f, 10.0f);
configRegisterInt("Game.SkipIntro", &portSkipIntro, 0, 1);
configRegisterInt("Game.NoHitFlash", &portNoHitFlash, 0, 1);
configRegisterInt("Video.VSync", &cfgVSync, 0, 1);
configRegisterInt("Video.FpsCap", &cfgFpsCap, 0, 1000);
configRegisterInt("Video.MSAA", &cfgMSAA, 1, 8);
+24
View File
@@ -4234,6 +4234,30 @@ Gfx *currentPlayerDrawFade(Gfx *gdl)
}
void currentPlayerSetFadeColour(s32 r, s32 g, s32 b, f32 frac) {
#if defined(PORT)
/* D232: Game.NoHitFlash — the community "no damage flash" toggle.
* Every fade in the game routes through this function, and the ONLY
* non-black ones are the two damage paths (the per-frame g_DamageTypes
* envelope in bondviewPlayerTickDamageAndHealth above — white 0xFF
* with an alpha envelope scaled by remaining health — and the red
* 150,0,0 overlay once the death blood finishes) — every other caller
* passes (0,0,0). User playtest (M-105 cont.) caught that zeroing just
* the RGB isn't enough: `frac` is the overlay's alpha/opacity, so a
* zeroed-RGB-but-nonzero-frac call still draws a fully opaque BLACK
* flash at the same envelope as the original white one -- same visual
* intrusion, different colour. Zero frac too so the overlay doesn't
* draw at all. Leaves all blackouts, the colour screen and the death
* fade's *own* frac-driven timing untouched (their frac is unaffected
* since they only ever pass (0,0,0) here). Default 0 = original
* behaviour. */
extern s32 portNoHitFlash;
if (portNoHitFlash && (r != 0 || g != 0 || b != 0)) {
r = 0;
g = 0;
b = 0;
frac = 0.0f;
}
#endif
g_CurrentPlayer->colourscreenred = r;
g_CurrentPlayer->colourscreengreen = g;
g_CurrentPlayer->colourscreenblue = b;