Kaysser Kayyali 8b18714d70 v0.3.0: rewrite Playwright test for the v0.3.0 surface
- Drop HUD-related assertions (2d-2g now check the HUD exports are
  GONE rather than present).
- Add v0.3.0 hub integration assertions:
  - 2h-2i: registerHubSection + pushToHubFeed exist.
  - 4a: pinned-achievements section is registered on combat-hud-hub.
  - 5a-5b: pushToHubFeed delivers entries to chh.getFeed.
  - 6a-6b: registerHubSection idempotent.
- Add awardAchievement + idempotency assertions (7a-7c).
- 8a: pageerror check (no thrown errors).
- Smoke test (verify-achievable-v1.mjs) unchanged; 57/57 still pass.
2026-06-22 16:12:08 -04:00

It's Achievable (its-achievable)

Foundry VTT module: achievements engine, custom rules, rewards, achievement wall, and combat HUD. Consumes the generic Foundry hook facade from foundry-hooks-lib and the encounter state from battle-focus.

Status

v0.1.0 — first release as a standalone repo. Sourced from battle-focus/scripts/{achievements.js, achievement-wall.js, custom-achievements-app.js, hud.js, achievement-rules.js} at battle-focus v0.5.0-alpha.12 (99cf757 on Gitea).

Stage 2 of the Foundry module split. The achievement code is now an independent module with its own:

  • Settings namespace (its-achievable.*)
  • Module id (its-achievable, lowercase kebab)
  • Achievements catalog and rule engine
  • HUD subscription to hooks-lib's v0.2.0 envelope stream
  • Chat-bar popover and form application

battle-focus retains its own copies of these files until Stage 3 of the split ships (which will delete the copies and add its-achievable as a soft dependency of battle-focus).

Dependencies

  • foundry-hooks-lib (≥0.2.0) — provides the Foundry event stream via the generic {ts, hook, args} envelope facade. See hooks-lib/docs/HOOK_CONTRACT.md.
  • battle-focus (soft) — provides the encounter singleton via game.modules.get("battle-focus").api.getActiveEncounter().

If either is missing, its-achievable logs a warning and degrades gracefully (achievements inactive).

Public API (on game.modules.get("its-achievable").api)

const api = game.modules.get("its-achievable").api;

// Catalog
api.getAchievementCatalog();
api.getActorAchievements(actorKey);

// Rule engine
api.evaluateRulesForEvent(event, encounter, actor, targetActor);
api.evaluateRulesForEncounterEnd(encounter);
api.evaluateRulesForCareerUpdate(career);

// Awarding
api.processEventForAchievements(event, encounter);
api.evaluateCombatAchievements(stats);
api.evaluateCareerAchievements(pcName, career, encounterId);
api.awardAchievement(actorKey, achievementId, encounterId);

// Wall + HUD
api.renderAchievementWall(actorId, actorName, opts);
api.getAchievementWallProgress(actorId, actorName);
api.renderAchievementPopover(unlocks, viewerName);
api.buildHudUpdatePayload(encounter, event);
api.openCustomAchievementsApp();

Settings namespace

Old (battle-focus.*) New (its-achievable.*)
achievementsByActor achievementsByActor
customAchievementRules customAchievementRules
enableRewards enableRewards

No automatic migration. Per the Stage 2 decision, users with existing worlds will need to re-create their custom rules and re-trigger any past achievement awards. Documented in CHANGELOG.

Tests

npm test    # smoke test, no Foundry needed

tests/PLAN.md describes what we test and what we don't. Real-Foundry integration testing happens when battle-focus migrates in Stage 3 and the existing E2E suite exercises the moved code.

Architecture notes

  • Hooks-lib first. its-achievable subscribes to foundry-hooks-lib's envelope stream. Combat lifecycle, document CRUD, dnd5e rolls — all via hooksLib.api.subscribeMany({...}). No direct Hooks.on(...) calls.
  • Encounter via battle-focus's API. its-achievable does not import battle-focus's encounter.js directly; it calls battle-focus.api.getActiveEncounter() to resolve the singleton.
  • HUD derives its payload locally. buildHudUpdatePayload lives in its-achievable (moved from battle-focus). It derives the HUD state from hooks-lib envelopes, not from a battle-focus broadcast.

Maintained by Kaysser Taylor + Hermes

Description
Hax's Tools � achievements + rewards + wall + HUD (battle-focus slice 2)
Readme 229 KiB
Languages
JavaScript 93.3%
HTML 6.7%