Skip to content

task 2 report

Xopher edited this page Oct 22, 2026 · 1 revision

Task 2 report: the Temple Creator's Drops picker (board #1455)

Status: DONE_WITH_CONCERNS (concerns are design notes, nothing blocks the merge). Branch: worktree-agent-a60baf7b9f8792e7e (worktree .claude/worktrees/agent-a60baf7b9f8792e7e), base 62e9e5fb (origin/master). Commit: 153a921e feat(temple-creator): fight rooms pick what their beast drops

What I built

  • components/RoomDropsConfig.vue (new, <script setup lang="ts">, 260 lines): a "Drops" section styled like RoomLootConfig.vue.
    • Props { drops: RoomDrops | null }, emits update:drops with RoomDrops | null. No state of its own.
    • Dungeon item row: None first, then DUNGEON_ITEMS (Small Key, Boss Key, Map, Compass). A tile lights through dungeonItemId, so a stored dungeon: 'key' (how the temples spell it) lights Small Key, as 'small-key' does.
    • Items row: CONSUMABLE_ITEMS with the Bomb; any number can be ticked (a chest keeps at least one, a drop may keep none).
    • Gold field: a native number input (0 to 500, whole GP; fractions and negatives are cut, 500 matches the loot chest's slider); on leaving the field it shows the gold actually held, so a cut value never lingers on screen.
    • The emitted shape is a chest's: chest names the main thing (dungeon, else consumable, else gold); a field with nothing is left out; nothing at all is null. Fields the picker does not touch survive (a relic in dungeon, key rows in items).
  • components/index.ts: exports RoomDropsConfig.
  • XpRoomEditorPage.vue (+20 lines, 458 total): mounts <RoomDropsConfig v-if="hasDrops" v-model:drops="drops" /> between the monster/quest config chain and the loot config, so it shows for classic and quest fight rooms. hasDrops reads FIGHT_ROOM_TYPES (single source of truth, not the hook's duplicate list); drops is a writable computed over roomData.content.drops that deletes the key on null, so no drops: null is ever saved.
  • hooks/useTempleRoomEditor.ts (+2 lines): CONSUMABLE_ITEMS gains { id: BOMB_ITEM, icon: 'fa-bomb', label: 'Bomb' } (id 'Bomb', the name the solver, isBombSource and the bag know).
  • components/__tests__/RoomDropsConfig.spec.ts (new, 14 tests).

TDD evidence

RED (before the component existed):

chemx test src/app/Admin/XpCompendium/views/XpTemples/components/XpTempleCreator/components/__tests__/RoomDropsConfig.spec.ts
  ✖ Test Failures (1 failed out of 1)
    ✖ Test suite failed to run
      Cannot find module '../RoomDropsConfig.vue' from 'src/app/Admin/.../components/__tests__/RoomDropsConfig.spec.ts'

GREEN (committed tree, same command):

  ✔ All tests passed (14 passed in 41897ms)

The four brief tests use the brief's values verbatim: Small Key -> { chest: 'dungeon', dungeon: 'small-key' }; None with no gold or items -> null; gold 30 on a key drop -> { chest: 'dungeon', dungeon: 'small-key', gold: 30 }; ticking Bomb -> items: ['Bomb'] (as { chest: 'consumable', items: ['Bomb'] }). Extra tests: untick Bomb (null / keeps the other row), Bomb beside a key, None keeps gold and items, clearing gold, gold cut (-5, 12.7, 9000), the field resyncs on change, tiles marked (aria-pressed) for what the drop holds, 'key' lights Small Key, empty lights None, tile order.

Page check: I could not run the page in a browser (no dev server, no build, per the constraints). As a stand-in I ran a throwaway spec (tests/unit/ScratchRoomEditorPageCompile.spec.ts, deleted, not committed) that imports XpRoomEditorPage.vue through the repo's vue transform: it compiled, registered RoomDropsConfig and the compiled render contained RoomDropsConfig and onUpdate:drops. 1 passed. No typecheck or lint was run (the lead's wave gate does that).

Files changed (all under src/app/Admin/XpCompendium/views/XpTemples/components/XpTempleCreator/)

  • components/RoomDropsConfig.vue (new, 260)
  • components/__tests__/RoomDropsConfig.spec.ts (new, 123)
  • components/index.ts (+1)
  • XpRoomEditorPage.vue (+20, now 458, under 500)
  • hooks/useTempleRoomEditor.ts (+2, now 1002; it was already over budget at 1000, so the LINE_BUDGET_FILE count does not change)

Self-review

  • Conditions in ifs are named (isDungeonItemDrop, hasDungeonItem, holdsNothing, isTicked, isNumber); the one object-literal parameter has a named interface (HeldDrop). The two page lines if (!content) return; if (next) ...; else delete ... are simple tests, no compound booleans.
  • Mounted only for FIGHT_ROOM_TYPES; a drop written under another type is never shown or handed out (engine rule), and contentAfterTypeChange already drops drops when a room changes type (see concern 1).
  • No Ionic overlay, no alerts, no new text in the in-world copy catalogue (this is Game Master console text, like RoomLootConfig's).

Concerns

  1. contentAfterTypeChange (hooks/grid/roomContent.ts) does not carry drops between fight types, so retyping a monster to a mini-boss clears its drop (the GM re-picks). That is the safe side of its "a Boss Key cannot ride along into a miniboss" rule; I left it alone (not in the brief). Adding "drops" to the COMBAT_ROOM_TYPES keys in CARRIED_WITHIN_FAMILY would carry it, if the owner wants that.
  2. Adding the Bomb to the shared CONSUMABLE_ITEMS also makes it a tick in the loot chest's Consumable picker. I think that is wanted (the Task 7 "Bomb chest" is a loot room holding items: ['Bomb'], and a GM opening it should see the Bomb ticked), but it is a visible change beyond the Drops section.
  3. chestLoot's KNOWN table has no bomb entry, so a Bomb row shows as a generic "Bomb / Goes in your bag." gift in the reveal. That is Task 3's reveal path, not this task.
  4. The picker is unverified in a real browser (see Page check); the wiring is covered by the compile spec only, and the lead's typecheck/lint gate has not seen it.

(Concerns 1 and 3 are resolved in Fix round 1 below.)

Fix round 1 (commit 3415dd48)

Review finding (Important): a retype or a quest swap silently cleared the drop. applyQuestPick calls retypeRoom(room, tier), so swapping a quest room to a quest of another Fibonacci tier wiped drops, while every other fight-owned field survived within the combat family. Plus the lead's ruling: give the Bomb its own loot face.

What changed:

  • hooks/grid/roomContent.ts: "drops" added to the combat keys of CARRIED_WITHIN_FAMILY; the doc comment of contentAfterTypeChange now says the drop stays with the fight between combat rooms. It still never rides into a room that does not fight (a loot room, an empty room).
  • src/lib/services/temples/ChestLoot.ts: KNOWN.bomb = { name: 'Bomb', icon: 'bomb', blurb: 'Blows open a cracked wall. Goes in your bag.', tier: 'supply' } (a supply like the potions, so the chest's glow reads it as one), so lootFace('Bomb') shows the Font Awesome bomb instead of the gift.
  • tests/unit/TempleCreatorRoomContent.spec.ts: new test "keeps what a beast drops between combat rooms..." (monster -> miniboss, miniboss -> monster, monster -> boss, boss -> monster keep the drop; monster -> loot does not).
  • tests/unit/ChestLoot.spec.ts: new test "knows the Bomb: a supply with the bomb icon, not the plain gift".

RED (new tests written first):

chemx test tests/unit/TempleCreatorRoomContent.spec.ts
  ✖ Test Failures (1 failed out of 60)
    ✖ contentAfterTypeChange › keeps what a beast drops between combat rooms, so a retype or a quest swap to another tier does not wipe it
      Expected: {"chest": "dungeon", "dungeon": "master-key", "gold": 30, "items": ["Bomb"]}
      Received: undefined
chemx test tests/unit/ChestLoot.spec.ts
  ✖ Test Failures (1 failed out of 29)
    ✖ lootFace › knows the Bomb: a supply with the bomb icon, not the plain gift

GREEN (after the fix):

chemx test tests/unit/TempleCreatorRoomContent.spec.ts   ->  ✔ All tests passed (60 passed in 18279ms)
chemx test tests/unit/ChestLoot.spec.ts                  ->  ✔ All tests passed (29 passed in 21549ms)
chemx test src/app/Admin/XpCompendium/views/XpTemples/components/XpTempleCreator/components/__tests__/RoomDropsConfig.spec.ts
                                                         ->  ✔ All tests passed (14 passed in 22987ms)

Only those three specs were run (no typecheck/lint). Committed only the four paths above.

Table of Contents


Home - See Pages

Developer Docs

Start Screen

User Management

My Portal

My Home

The City (Hometown)

The World Map

The Dungeon

Game Master

Settings

Support & Glossary

About XP

Clone this wiki locally