Deal area names; fix the scene-control hook for Foundry v13+

Two bugs the first real button-press exposed.

The ⛏ never appeared. getSceneControlButtons was written for the old array
shape, but v13+ passes a record keyed by name and the token group is `tokens`,
plural — so the hook silently added nothing. Every earlier test had gone through
the API, which masked it completely. It now handles both shapes.

Area names were picked per-area from a small per-role list, so two areas sharing
a role could collide: a generated dungeon shipped with two scenes both called
"The Lesser Vault". Names are now dealt globally without replacement, falling
back to other roles' lists before ever repeating. This is the same bug already
fixed for features, decisions, temptations and situations — missed for names
because names were assigned in beat.mjs rather than dealt in delve.mjs.

A test now generates 180 delves at 6, 9 and 12 areas and asserts no two areas
in one delve share a name. Tests 38 -> 39.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-05 09:44:53 +01:00
co-authored by Claude Opus 5
parent 47778fdbf6
commit ded836d4c8
4 changed files with 47 additions and 21 deletions
+20 -17
View File
@@ -173,21 +173,24 @@ Hooks.once('ready', async () => {
Hooks.on('getSceneControlButtons', controls => {
if (!game.user.isGM) return;
const group = Array.isArray(controls) ? controls.find(c => c.name === 'token') : controls.token;
if (!group) return;
const tools = Array.isArray(group.tools) ? group.tools : Object.values(group.tools ?? {});
const open = () => new DelveForgeApp().render(true);
tools.push({
name: 'delve-forge', title: 'DELVE — raise a dungeon', icon: 'fas fa-mountain', button: true,
onClick: open, onChange: open,
});
tools.push({
name: 'delve-remove', title: 'DELVE — remove a generated dungeon', icon: 'fas fa-trash', button: true,
onClick: () => removeDungeonDialog(), onChange: () => removeDungeonDialog(),
});
tools.push({
name: 'delve-next', title: 'DELVE — stage the next area (pre-authored delve)', icon: 'fas fa-forward', button: true,
onClick: () => (getState() ? enter() : ui.notifications.info('DELVE: no staged delve — use the ⛏ button to raise one.')),
onChange: () => (getState() ? enter() : ui.notifications.info('DELVE: no staged delve — use the ⛏ button to raise one.')),
});
// Foundry v13+ passes controls as a record keyed by name — the token group is `tokens`, plural —
// and each group's `tools` is a record too, not an array. Written for the old array shape, this
// hook silently added nothing and the button never appeared.
const group = controls.tokens ?? controls.token;
if (!group?.tools) return;
const tool = (name, title, icon, order, onClick) => {
const entry = { name, title, icon, order, button: true,
onChange: (event, active) => { if (active !== false) onClick(); },
onClick };
if (Array.isArray(group.tools)) group.tools.push(entry);
else group.tools[name] = entry;
};
tool('delve-forge', 'DELVE — raise a dungeon', 'fas fa-mountain', 90,
() => new DelveForgeApp().render(true));
tool('delve-remove', 'DELVE — remove a generated dungeon', 'fas fa-trash-can', 91,
() => removeDungeonDialog());
tool('delve-next', 'DELVE — stage the next area of a pre-authored delve', 'fas fa-forward', 92,
() => (getState() ? enter() : ui.notifications.info('DELVE: no staged delve — use ⛏ to raise one.')));
});