미존재 3컴포넌트(SlayCardCatalog/SlayRunState/SlayCombatManager)를 구현된 것처럼 서술하던 부분을 정정. - '게임 프레임워크 현황'을 실제 구현(SlayDeckController 기반 카드 전투 + B 결과)으로 재작성 - 3대 컴포넌트는 '향후 설계(미구현 — 목표 아키텍처)' 섹션으로 분리 보존 - 디렉토리 트리·codeblock 목록·생성기(tools/) 반영, SlayDeckController 추가 - 스크립트 호출 예시를 실제 메서드(PlayCard/EndPlayerTurn/StartCombat)로 교체 - '다음 구현 단계'에서 전투 UI·전투 루프 완료 표시, D/F/E 반영 - 수치는 임시 placeholder임을 명시 - framework 문서도 동일 기조로 재작성 + Planned 섹션에 3컴포넌트 보존 검증: 문서에 적힌 컴포넌트명을 코드와 grep 교차확인 (SlayDeckController 실재, 3컴포넌트 코드 0건). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
85 lines
4.0 KiB
Markdown
85 lines
4.0 KiB
Markdown
# 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.
|