# SlayMaple Basic Framework This project has a working single-combat deckbuilder loop inspired by turn-based card combat games. Card play is wired to real combat state (enemy/player HP, block, enemy intent, win/lose). ## Current Components (implemented) - `SlayDeckController`: The single combat component, attached to the `/common` entity in `Global/common.gamelogic`. Handles the card-hand UI (draw/discard/ reshuffle, energy, card-click play), card effects (damage/block), enemy HP/block/intent, turn flow, and victory/defeat. - `Monster.codeblock`: A separate field-action monster system (HP, hit event, respawn). **Not** part of the card combat. All card/deck/combat artifacts (`ui/DefaultGroup.ui`, `RootDesk/MyDesk/SlayDeckController.codeblock`, `Global/common.gamelogic`) are **generated from a single source, `tools/gen-slaydeck.mjs`** (deterministic output — do not hand-edit; change the generator and re-run `node tools/gen-slaydeck.mjs`). If the Maker session was already open before these files changed, reload the local workspace so the regenerated codeblock/UI files are imported into the editor state. ## Implemented Combat Loop 1. `StartCombat` initializes player (HP 80, Block 0) and a single enemy (HP 45, Block 0) with a deterministic 3-step intent cycle (Attack 10 → Attack 6 → Defend 8), then starts the first player turn. 2. Each player turn refreshes energy to 3, resets player block, and draws 5 cards. The enemy's upcoming intent is shown in advance. 3. Cards: Strike (damage 6), Defend (block 5), Bash (damage 10). Each card has numeric `damage`/`block` fields; starter deck is 10 cards. 4. Playing a card spends energy: `Attack` reduces enemy HP (block absorbs first); `Skill` adds player block. The card moves to the discard pile. 5. Ending the turn discards the hand, runs the enemy turn (executes the current intent — attack the player or gain block), advances the intent index, then starts the next player turn. 6. Enemy HP 0 → victory; player HP 0 → defeat. On combat end, input is locked and a result text is shown (combat-reward hook reserved for the roguelike meta — see Planned below). > Player HP (80), enemy HP (45), and intent values (10/6/8) are temporary > placeholders for loop verification. They will move to per-character / > per-enemy data (see "Data externalization" under Planned). ## Useful Script Calls From the `/common` entity (or a Play Test context): ```lua local c = _EntityService:GetEntityByPath("/common").SlayDeckController c:PlayCard(1) -- play the hand card in the given slot c:EndPlayerTurn() -- end turn → enemy turn → next turn c:StartCombat() -- restart combat (reset state) ``` ## Planned (not yet implemented) — Target Architecture The originally envisioned component split for the full roguelike. Currently **none of these exist**; `SlayDeckController` covers only the card combat above. - `SlayCardCatalog`: Card data, starter deck composition, reward pool, card cloning. - `SlayRunState`: Persistent run data — HP, gold, floor, deck, relics, card rewards. - `SlayCombatManager`: Turn flow, draw/discard/exhaust piles, energy, enemy intents, block, damage, victory, and defeat (the role currently played by `SlayDeckController`). ## Next Implementation Steps - [x] Combat UI rendering HP, block, energy, enemy intent, and hand cards (done — `SlayDeckController` + CombatHud). - [x] Card play wired to real damage/block/intent/win-lose (done). - [ ] Externalize card/enemy data to `data/cards.json` / `data/enemies.json`, injected by the generator. - [ ] Monte-Carlo balance simulator `tools/sim-balance.mjs` (requires the data externalization above). - [ ] Map node UI with combat, elite, shop, rest, event, and boss node types. - [ ] Relic definitions and hooks (`OnCombatStart`, `OnCardPlayed`, `OnTurnStart`, `OnCombatReward`). - [ ] Enemy move sets as data instead of the current deterministic intent cycle. - [ ] Run persistence (HP/gold/floor/deck/relics) + save/load once the loop is playable end to end.