From 81d701adc4102d8ee4bcf12dac7399d5c9f01727 Mon Sep 17 00:00:00 2001 From: Zixer1 <99333209+Zixer1@users.noreply.github.com> Date: Mon, 13 Jul 2026 14:07:22 -0400 Subject: [PATCH] feat(highlight): replace the small-player highlight toggle with a strength slider (#4588) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replaces the "Highlight small players" on/off toggle with a **0-500% Strength slider** controlling the glow's **width** (0 = off, 100% = the previous default). - `UserSettings`: `highlightSmallPlayers()`/toggle → `highlightGlowStrength()`/set, float-backed, clamped to [0, 5]. - `SmallPlayerGlowPass` takes the strength via a setter (pushed by `ClientGameRunner` on the settings-changed event), so it stays a pure consumer and the slider still updates live while the settings modal has the sim paused. Width = a non-linear blur-iteration count; intensity compensated so wider stays about as bright. - `MapRenderer` persists the strength across a WebGL context restore. - `SettingsModal`: the toggle row becomes a range input. Behavior note: with the toggle gone the glow **defaults ON at 100%** (old toggle defaulted OFF); can default to 0 (opt-in) if preferred. - [x] I have added screenshots for all UI updates - [x] I process any text displayed to the user through translateText() and I've added it to the en.json file - [x] I have added relevant tests to the test directory --- resources/lang/en.json | 2 +- src/client/ClientGameRunner.ts | 11 +++ src/client/WebGLFrameBuilder.ts | 5 +- src/client/hud/layers/SettingsModal.ts | 32 +++++---- src/client/render/gl/MapRenderer.ts | 12 ++++ src/client/render/gl/Renderer.ts | 4 ++ .../render/gl/passes/SmallPlayerGlowPass.ts | 68 +++++++++++++++---- src/core/game/UserSettings.ts | 14 ++-- tests/UserSettings.test.ts | 22 +++--- 9 files changed, 120 insertions(+), 50 deletions(-) diff --git a/resources/lang/en.json b/resources/lang/en.json index 9f5529854..3d8704cfe 100644 --- a/resources/lang/en.json +++ b/resources/lang/en.json @@ -1410,8 +1410,8 @@ "ground_attack_desc": "Send a ground attack to the tile under your cursor.", "help_messages_desc": "Show contextual tips and warnings during gameplay, such as army limit warnings and general gameplay advice.", "help_messages_label": "Help Messages", + "highlight_glow_strength_label": "Highlight strength", "highlight_small_players_desc": "Add a glow to small players so they're easy to find.", - "highlight_small_players_label": "Highlight small players", "keybind_conflict_error": "The key {key} is already bound to another action.", "keybinds_hint": "Click a key to rebind it. You can assign a single key or Shift + key combination.", "left_click_desc": "When ON, left-click opens menu and sword button attacks. When OFF, left-click attacks directly.", diff --git a/src/client/ClientGameRunner.ts b/src/client/ClientGameRunner.ts index fcb79f42f..76e3215ef 100644 --- a/src/client/ClientGameRunner.ts +++ b/src/client/ClientGameRunner.ts @@ -527,6 +527,17 @@ async function createClientGame( { signal: graphicsListenerAbort.signal }, ); + // Push the small-player glow Strength to the pass (which is a pure consumer) + // on the settings-changed event, so moving the slider updates the glow live + // even while the settings modal has the sim paused. + view.setSmallPlayerGlowStrength(userSettings.highlightGlowStrength()); + globalThis.addEventListener( + `${USER_SETTINGS_CHANGED_EVENT}:settings.highlightGlowStrength`, + () => + view.setSmallPlayerGlowStrength(userSettings.highlightGlowStrength()), + { signal: graphicsListenerAbort.signal }, + ); + // Re-resolve names drawn on the map when the anonymous-names setting toggles // so they switch live, like the leaderboard. globalThis.addEventListener( diff --git a/src/client/WebGLFrameBuilder.ts b/src/client/WebGLFrameBuilder.ts index 79194795d..359f8fffe 100644 --- a/src/client/WebGLFrameBuilder.ts +++ b/src/client/WebGLFrameBuilder.ts @@ -3,7 +3,6 @@ import { base64url } from "jose"; import { assetUrl } from "../core/AssetUrls"; import { decodePatternData } from "../core/PatternDecoder"; import { PlayerType } from "../core/game/Game"; -import { UserSettings } from "../core/game/UserSettings"; import { uploadFrameData } from "./render/frame/Upload"; // Type-only: a value import would pull GPURenderer and its `.glsl?raw` shader // imports into any non-Vite consumer (e.g. the Node perf harness). @@ -93,7 +92,6 @@ export class WebGLFrameBuilder { } private readonly highlightSetBuf = new Uint8Array(PALETTE_SIZE); - private readonly userSettings = new UserSettings(); private glowRescanTick = 0; update(gameView: GameView): void { @@ -209,8 +207,9 @@ export class WebGLFrameBuilder { * Client-only view — toggle it live in the settings. */ private syncSmallPlayerGlow(gameView: GameView): void { + // Strength (incl. off at 0) is read live in the glow pass; here we only + // decide who qualifies. Skip spawn + the first minute. if ( - !this.userSettings.highlightSmallPlayers() || gameView.inSpawnPhase() || gameView.elapsedGameSeconds() < SMALL_PLAYER_GLOW_GRACE_SECONDS ) { diff --git a/src/client/hud/layers/SettingsModal.ts b/src/client/hud/layers/SettingsModal.ts index 6b905f63a..8b9880a0c 100644 --- a/src/client/hud/layers/SettingsModal.ts +++ b/src/client/hud/layers/SettingsModal.ts @@ -135,11 +135,6 @@ export class SettingsModal extends LitElement implements Controller { this.requestUpdate(); } - private onToggleHighlightSmallPlayersButtonClick() { - this.userSettings.toggleHighlightSmallPlayers(); - this.requestUpdate(); - } - private onToggleAlertFrameButtonClick() { this.userSettings.toggleAlertFrame(); this.requestUpdate(); @@ -210,6 +205,12 @@ export class SettingsModal extends LitElement implements Controller { this.requestUpdate(); } + private onHighlightGlowStrengthChange(event: Event) { + const strength = parseFloat((event.target as HTMLInputElement).value) / 100; + this.userSettings.setHighlightGlowStrength(strength); + this.requestUpdate(); + } + render() { if (!this.isVisible) { return null; @@ -356,30 +357,35 @@ export class SettingsModal extends LitElement implements Controller { - +