mirror of
https://github.com/openfrontio/OpenFrontIO.git
synced 2026-07-23 21:16:21 +00:00
## Summary Moves the small-player glow strength from a standalone UserSettings key (`settings.highlightGlowStrength`) into the graphics overrides blob (`smallPlayerGlow.strength`), and moves its slider from the basic settings modal into the **Effects** section of the graphics settings modal. The pass now reads strength from its live `RenderSettings` slice like every other graphics knob, flowing through `applyGraphicsOverrides`. This removes the dedicated push chain (ClientGameRunner listener → MapRenderer → Renderer → pass setter) and MapRenderer's context-restore reapply — strength survives WebGL context restores automatically now, participates in the graphics modal's "Reset to defaults", and shows up in the render debug GUI. ## Bug fix The old slider had no visible effect below ~115%: strength only drove the blur-iteration count (`round(strength ** 2.74)`, floored at 1 pass), and the composite intensity (`alpha * pulse * sqrt(passes)`) never factored strength directly — so 10% rendered identical to 100%. Strength is now a linear opacity fade on a fixed-width aura: - 100% = the aura's full brightness, 10% = barely visible, 0% = off - Slider capped at 100% (the >100% aura-widening mechanism became unreachable and is removed: `passesFor`, `lastPasses`, and the blur-iteration loop) - Default is 25% - The pass clamps persisted values above 1 so stale settings from the old 500% range can't over-brighten ## Notes - Reuses the existing `user_setting.highlight_glow_strength_label` / `highlight_small_players_desc` translation keys — no en.json change - The legacy `settings.highlightGlowStrength` localStorage key is not migrated (the slider only shipped in #4588 a few days ago); users reset to the 25% default ## Test plan - [x] `tests/GraphicsOverrides.test.ts` — schema validation + apply coverage for the new override group - [x] Full suite (171 tests), tsc, eslint all pass 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
61 lines
2.3 KiB
TypeScript
61 lines
2.3 KiB
TypeScript
import { EFFECTS_KEY, UserSettings } from "../src/core/game/UserSettings";
|
|
|
|
describe("UserSettings effect selection", () => {
|
|
beforeEach(() => {
|
|
localStorage.clear();
|
|
// UserSettings keeps a static in-memory cache; reset it too so each test
|
|
// reads fresh from the (cleared) localStorage.
|
|
(
|
|
UserSettings as unknown as { cache: Map<string, string | null> }
|
|
).cache.clear();
|
|
});
|
|
|
|
it("sets and reads a per-effectType selection", () => {
|
|
const s = new UserSettings();
|
|
s.setSelectedEffectName("transportShipTrail", "spectrum");
|
|
expect(s.getSelectedEffectName("transportShipTrail")).toBe("spectrum");
|
|
});
|
|
|
|
it("returns null when nothing is selected", () => {
|
|
expect(
|
|
new UserSettings().getSelectedEffectName("transportShipTrail"),
|
|
).toBeNull();
|
|
});
|
|
|
|
it("clearing the last selection removes the storage key", () => {
|
|
const s = new UserSettings();
|
|
s.setSelectedEffectName("transportShipTrail", "spectrum");
|
|
s.setSelectedEffectName("transportShipTrail", undefined);
|
|
expect(s.getSelectedEffectName("transportShipTrail")).toBeNull();
|
|
expect(localStorage.getItem(EFFECTS_KEY)).toBeNull();
|
|
});
|
|
|
|
it("clearing one effectType leaves other types intact", () => {
|
|
const s = new UserSettings();
|
|
// Seed two types directly (only one real effectType exists today).
|
|
localStorage.setItem(
|
|
EFFECTS_KEY,
|
|
JSON.stringify({ transportShipTrail: "spectrum", future: "x" }),
|
|
);
|
|
s.setSelectedEffectName("transportShipTrail", undefined);
|
|
expect(s.getSelectedEffects()).toEqual({ future: "x" });
|
|
});
|
|
|
|
it("returns an empty map for a corrupt blob", () => {
|
|
localStorage.setItem(EFFECTS_KEY, "not json");
|
|
expect(new UserSettings().getSelectedEffects()).toEqual({});
|
|
});
|
|
|
|
it("keeps per-nukeType nuke-explosion slots independent", () => {
|
|
const s = new UserSettings();
|
|
s.setSelectedEffectName("atom", "atom_boom");
|
|
s.setSelectedEffectName("hydro", "hydro_boom");
|
|
expect(s.getSelectedEffectName("atom")).toBe("atom_boom");
|
|
expect(s.getSelectedEffectName("hydro")).toBe("hydro_boom");
|
|
// Clearing one bomb's slot leaves the others intact.
|
|
s.setSelectedEffectName("atom", undefined);
|
|
expect(s.getSelectedEffectName("atom")).toBeNull();
|
|
expect(s.getSelectedEffectName("hydro")).toBe("hydro_boom");
|
|
});
|
|
});
|