diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b88d6d..c92b0b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,15 @@ All notable changes to Grim Arithmetic are documented here. +## v0.7.2-rc1 - Player-safe options and calmer tooltips + +Release candidate. Three usability fixes on top of v0.7.1; no changes to the underlying mortality math. + +### Usability +- The Grim Arithmetic settings section is now GM-only — regular players no longer see any module options (KHT-118). The GM-facing options carry clearer descriptions of what each one does. +- Hover help across all three windows now waits a beat (750ms) before appearing, so tooltips no longer flicker continuously while scanning down a list of values (KHT-120). +- The risk-rating tooltip now spells out the full ladder — Low, Guarded, Dangerous, Severe, Grim, with the chance-of-being-downed band for each — instead of just "Low → Grim" (KHT-121). + ## v0.7.1 - Localization, tooltips, and tactics clarity Builds on v0.7.0's ApplicationV2 migration with internationalization groundwork, on-hover help across every window, clearer tactics options, and a real CI/release pipeline. No changes to the underlying mortality math. diff --git a/lang/en.json b/lang/en.json index ea28ed3..f002c07 100644 --- a/lang/en.json +++ b/lang/en.json @@ -3,7 +3,7 @@ "Settings": { "DefaultStrikes": { "Name": "Default enemy Strike count", - "Hint": "Default number of Strikes used for immediate-threat estimates.", + "Hint": "How many Strikes each enemy is assumed to make per round when estimating immediate knock-out threat on the Encounter Danger Board.", "Choices": { "1": "1 Strike", "2": "2 Strikes", @@ -12,11 +12,11 @@ }, "DebugLogging": { "Name": "Debug logging", - "Hint": "Log Grim Arithmetic debug information to the browser console." + "Hint": "Write Grim Arithmetic diagnostic messages to the browser console (F12). Leave off unless troubleshooting." }, "EnableMonteCarlo": { "Name": "Enable Monte Carlo encounter simulation", - "Hint": "Disable on low-end machines if simulation runs are too slow. The Encounter Danger Board still works either way." + "Hint": "Turn on the Encounter Forecast's full-fight simulation. Disable on low-end machines if runs are too slow — the Encounter Danger Board still works either way." } }, "Window": { @@ -28,7 +28,8 @@ "Detail": "Detail", "Vs": "vs", "DownTooltip": "Chance this PC is knocked out in one round by this attack.", - "RiskPillTooltip": "Risk rating from chance of being downed: Low → Grim.", + "RiskPillTooltip": "Risk of being downed this round, lowest to highest: Low, Guarded, Dangerous, Severe, Grim.", + "RiskPillTooltipHtml": "Risk of being downed this round:
Low — below 5%
Guarded — 5–15%
Dangerous — 15–35%
Severe — 35–60%
Grim — 60% or more", "CiTooltip": "95% confidence interval — the range the true value likely falls in given sampling variance." }, "DangerBoard": { diff --git a/module.json b/module.json index 3a2e5b9..73c5d4a 100644 --- a/module.json +++ b/module.json @@ -2,7 +2,7 @@ "id": "grim-arithmetic", "title": "Grim Arithmetic", "description": "GM-facing PF2e mortality and encounter-risk analysis for Foundry VTT.", - "version": "0.7.1", + "version": "0.7.2-rc1", "authors": [ { "name": "Kyle Travis", @@ -36,5 +36,5 @@ ], "url": "https://github.com/kyletravis/grim-arithmetic", "manifest": "https://github.com/kyletravis/grim-arithmetic/releases/latest/download/module.json", - "download": "https://github.com/kyletravis/grim-arithmetic/releases/download/v0.7.1/grim-arithmetic-v0.7.1.zip" + "download": "https://github.com/kyletravis/grim-arithmetic/releases/download/v0.7.2-rc1/grim-arithmetic-v0.7.2-rc1.zip" } diff --git a/package.json b/package.json index 796d8e1..b78ec9c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "grim-arithmetic", - "version": "0.7.1", + "version": "0.7.2-rc1", "description": "Foundry VTT module for GM-facing PF2e mortality and encounter-risk analysis.", "type": "module", "private": true, diff --git a/src/main.ts b/src/main.ts index 8a05ca0..29c777f 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,9 +1,10 @@ import { MODULE_ID, MODULE_TITLE } from './constants'; import { logDebugCapture } from './debug-capture'; -import { registerSettings } from './settings'; +import { registerSettings, applyPlayerSettingsVisibility, type SettingsRegistry } from './settings'; import { DangerBoardPanel } from './ui/danger-board-panel'; import { ForecastPanel } from './ui/forecast-panel'; import { PairDetailPanel } from './ui/pair-detail-panel'; +import { applyTooltipDelay } from './ui/tooltip-delay'; import { registerTokenControls } from './ui/token-controls'; Hooks.once('init', () => { @@ -22,6 +23,13 @@ function registerHandlebarsHelpers(): void { } Hooks.once('ready', () => { + applyTooltipDelay(750); + // Runs before the GM guard below: players must reach this to have their settings hidden. + applyPlayerSettingsVisibility( + (game.settings as { settings?: SettingsRegistry } | undefined)?.settings, + game.user?.isGM === true + ); + if (!game.user?.isGM) return; const grimArithmeticModule = game.modules.get(MODULE_ID); diff --git a/src/settings.ts b/src/settings.ts index 5ab258e..74629a0 100644 --- a/src/settings.ts +++ b/src/settings.ts @@ -36,6 +36,34 @@ export function registerSettings(): void { }); } +const GRIM_SETTING_KEYS = ['defaultStrikes', 'debugLogging', ENABLE_MONTE_CARLO_SETTING] as const; + +export interface SettingsRegistry { + get(key: string): { config?: boolean } | undefined; +} + +/** + * Hide every Grim Arithmetic setting from non-GM players (KHT-118). + * + * Settings must be registered during `init`, but `game.user` is not populated + * until later — so registration can't know who the GM is. We register with + * `config: true` and, once `game.user.isGM` is known (the `ready` hook), flip + * the `config` flag to false for non-GMs. Foundry's settings menu reads each + * registration's `config` flag at render time and omits a module's heading + * when it has no visible settings, so this removes the entire Grim Arithmetic + * section for players — heading included. No-op for the GM. + */ +export function applyPlayerSettingsVisibility( + registry: SettingsRegistry | undefined | null, + isGM: boolean +): void { + if (isGM || !registry) return; + for (const key of GRIM_SETTING_KEYS) { + const registration = registry.get(`${MODULE_ID}.${key}`); + if (registration) registration.config = false; + } +} + /** * True when the Monte Carlo simulation feature is enabled for this client. * diff --git a/src/ui/tooltip-delay.ts b/src/ui/tooltip-delay.ts new file mode 100644 index 0000000..4b88cc9 --- /dev/null +++ b/src/ui/tooltip-delay.ts @@ -0,0 +1,20 @@ +/** + * Lengthen the delay before Foundry's native `data-tooltip` help appears, + * so tooltips don't fire continuously while scanning down a list of values + * (KHT-120). Foundry reads `TOOLTIP_ACTIVATION_MS` off the tooltip manager + * class at hover time, so overriding it affects all subsequent hovers. + * + * `game.tooltip.constructor` is the live class regardless of v13+ namespace + * relocation. No-ops safely when the manager is unavailable (pre-ready, or + * the test environment where `game` is undefined). + */ +export function applyTooltipDelay(ms: number): void { + if (typeof game === 'undefined') return; + try { + const manager = (game as { tooltip?: { constructor?: { TOOLTIP_ACTIVATION_MS?: number } } }).tooltip; + const managerClass = manager?.constructor; + if (managerClass) managerClass.TOOLTIP_ACTIVATION_MS = ms; + } catch { + /* tooltip manager unavailable; leave the default delay in place */ + } +} diff --git a/templates/danger-board-panel.hbs b/templates/danger-board-panel.hbs index 319f66e..3dc09cb 100644 --- a/templates/danger-board-panel.hbs +++ b/templates/danger-board-panel.hbs @@ -35,7 +35,7 @@ {{enemyName}} {{attackName}} {{downPercent}}% - {{riskLabel}} + {{riskLabel}}