5 Commits

Author SHA1 Message Date
2f6acc0da1 v0.3.0: strip combat HUD; integrate with combat-hud-hub
- Deleted scripts/hud.js, scripts/event-translation.js, styles/hud.css,
  templates/hud.html.
- Removed mod.api.getHud/openHud/closeHud/buildHudUpdatePayload exports.
- Removed hudPosition setting (moved to combat-hud-hub).
- Added hub integration: at ready, if combat-hud-hub is installed,
  register a 'pinned-achievements' section. The chatBubble listener
  now also pushes entries into that section via hub.api.pushFeedEntry.
- Soft-dep on combat-hud-hub (optional); popover still works without
  the hub.
- Tests: 57/57 passing covering sections A-G (rule engine, catalog,
  awarding, hooks wiring, hub integration, graceful degradation).
2026-06-22 12:46:57 -04:00
3bc1053a30 v0.2.0: strap HUD to foundry-hooks-lib envelope stream
- New: scripts/event-translation.js — thin translation layer
  that takes hooks-lib envelope args and produces a HUD event
  shape. Handlers for combatStart, combatEnd, combatRound,
  combatTurn, createCombatant, deleteCombatant,
  dnd5e.rollAttackV2, dnd5e.rollDamageV2. Includes an
  extractD20 helper for Foundry v14 D20Roll terms.
- Rewire: scripts/hud.js — wireHooks(hooksLib) / unwireHooks()
  replace the v0.1.x Hooks.on('battle-focus:hud-update', ...)
  dead broadcast. The HUD now subscribes to the foundry-hooks-lib
  envelope stream via subscribeMany, runs each envelope through
  the translation layer, and dispatches to _onHudUpdate. Active
  encounter still comes from
  game.modules.get('battle-focus').api.getActiveEncounter()
  (the public seam, soft dependency).
- Auto-open: scripts/hud.js — _handleHudEvent now auto-opens
  the HUD on combatStart (resets dice streak + pinned queue)
  and auto-closes on combatEnd. Manual openHud / closeHud
  still work.
- Fix: scripts/hud.js — PARTS.body.template was still pointing
  to modules/battle-focus/templates/hud.html (a latent v0.1.x
  bug from before the module split). Now correctly points to
  modules/its-achievable/templates/hud.html.
- Lifecycle: scripts/main.js — at ready, looks up
  game.modules.get('foundry-hooks-lib').api and calls
  hud.wireHooks(hooksLibApi). At unregisterModule, calls
  hud.unwireHooks(). MODULE_VERSION bumped to 0.2.0.
- Manifest: module.json — version 0.2.0, compatibility.minimum
  13 → 14, download URL updated.
- package.json — version 0.2.0, devDep playwright-core, scripts
  test:foundry + test:all, foundry-hooks-lib dep ^0.4.0.
- Tests: tests/verify-achievable-foundry.mjs (new, 285 lines)
  — 20 assertions, 20 passed in ~10s against a live Foundry
  v14. Verifies mod.api surface, HUD singleton + wiring, the
  openHud path, and live event flow (combatStart + dnd5e.rollAttackV2
  populate the combatants list + dice streak + d20 value).
- Tests: tests/verify-achievable-v1.mjs — D.2 version assertion
  bumped to 0.2.0. 75/75 still green.

Pitfalls hit:
- HUD template was still pointing at battle-focus's path (latent
  v0.1.x bug; smoke test never rendered the HUD live so it
  wasn't caught). Fixed.
- createCombatant fires before combatStart during
  c.createEmbeddedDocuments + c.startCombat, so battle-focus's
  onCreateCombatant bails (encounter doesn't exist yet). This
  is a pre-existing battle-focus quirk, not a v0.2.0 regression.
  Documented in the test.
2026-06-20 19:42:31 -04:00
1d1c042a80 deps: require foundry-hooks-lib >=0.4.0
The v0.4.0 release of foundry-hooks-lib dropped v13 support
(per the hooks-lib v0.4.0 plan). its-achievable is v14-only
and already on v14 Foundry, so this is a no-op in practice.

Bump: minimum 0.3.0 -> 0.4.0. its-achievable itself is not
version-bumped since this is a relationship constraint
tightening, not a code change. Tests still 75/75.
2026-06-20 17:43:04 -04:00
888790e5ff v0.1.1: track the hax-hooks-lib -> foundry-hooks-lib rename
User callout: 'Hax' is Kaysser's nickname, drop it from module
names. hooks-lib v0.3.0 renamed its module id; this commit
follows:

- relationships.modules[0].id: hax-hooks-lib -> foundry-hooks-lib
- relationships.modules[0].compatibility.minimum: 0.2.0 -> 0.3.0
  (we now require the renamed version)
- module.json: version 0.1.0 -> 0.1.1, download URL updated
- README.md, scripts/main.js, tests/PLAN.md, tests/test-helpers.mjs:
  branding text updates
- .gitignore: un-ignore the new 0.1.1 zip

Verification: 75/75 smoke assertions pass, no logic change.

Module title is now 'It's Achievable' (dropped the
'Hax's Tools' umbrella prefix per the same callout). 2 module
text changes are non-functional; pure branding.
2026-06-20 16:55:29 -04:00
f2ef1ef4f3 v0.1.0 — initial extraction from battle-focus v0.5.0-alpha.12
Stage 2 of the Hax's Tools split. its-achievable ships as a
standalone module that subscribes to hax-hooks-lib's envelope
stream and provides achievements + custom rules + rewards +
achievement wall + combat HUD.

## What's new

scripts/ — moved from battle-focus/scripts/, MODULE_ID retagged
battle-focus → its-achievable:
- achievement-rules.js (323 lines) — rule engine: OPERATORS,
  TRIGGER_TYPES, evaluateCondition(s), testRule, evaluateRulesFor*
- achievements.js (1150 lines) — 24-entry catalog + award path,
  per-event evaluators, encounter-end + career-update evaluation
- achievement-wall.js (333 lines) — renderAchievementWall,
  getAchievementWallProgress, renderAchievementPopover
- custom-achievements-app.js (270 lines) — GM FormApplication
  for editing custom rules
- hud.js (624 lines) — combat HUD (ApplicationV2 +
  HandlebarsApplicationMixin); removed dead import of
  battle-focus's encounter.js (it was unused even in the
  original)

scripts/main.js — Foundry entry point. Registers settings at
its-achievable.* namespace; exposes the public API on mod.api;
registers chatBubble popover listener + HUD singleton on ready.

templates/ + styles/ — moved verbatim.

tests/PLAN.md — per-project test plan (sections A-F).
tests/test-helpers.mjs — Foundry stub.
tests/verify-achievable-v1.mjs — smoke test, 75 assertions
covering rule engine, catalog, awards, hooks-lib wiring, HUD
payload derivation, and wall/popover rendering. Runs in <2s.

## Architecture

- **Settings namespace**: its-achievable.* (was battle-focus.*).
  No migration (per Kaysser's decision); users with existing
  worlds re-create their custom rules. Documented in README.
- **HUD derives its own state from hooks-lib envelopes.** Stage 2
  keeps the legacy battle-focus:hud-update broadcast subscription
  for now (battle-focus still emits it); Stage 3 will switch the
  HUD to subscribe to hooks-lib directly and remove the
  battle-focus broadcasts.
- **Encounter singleton**: accessed via battle-focus's public
  api.getActiveEncounter() — no direct import of battle-focus's
  encounter.js.

## Dependencies

- hax-hooks-lib ^0.2.0 (declared in module.json relationships).
- battle-focus (soft, runtime) — provides the encounter singleton.

## Tests

- 75/75 smoke assertions pass in 0.07s.
- Module manifest validates: 0 errors, 1 warning (no icon —
  Stage 2+ work).

Push: Gitea only.
2026-06-20 14:04:56 -04:00