docs(A): README·framework 문서를 실제 구현에 맞게 정정
미존재 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>
This commit is contained in:
78
README.md
78
README.md
@@ -43,14 +43,15 @@ git pull
|
||||
```
|
||||
slaymaple/
|
||||
├── Global/ # 월드 전역 설정 · 공용 모델 · 게임로직
|
||||
│ ├── common.gamelogic # SlayCardCatalog / SlayRunState / SlayCombatManager 부착 지점
|
||||
│ ├── common.gamelogic # SlayDeckController 부착 지점 (카드 UI 전투)
|
||||
│ ├── Player.model # 플레이어 모델
|
||||
│ ├── *.model # 몬스터 등 공용 모델
|
||||
│ ├── WorldConfig.config # 월드 설정
|
||||
│ └── ...
|
||||
├── RootDesk/
|
||||
│ └── MyDesk/ # 작업용 책상 — codeblock(스크립트)·모델·타일셋
|
||||
│ ├── Monster.codeblock
|
||||
│ ├── SlayDeckController.codeblock # 카드 UI 전투 컨트롤러 (생성물)
|
||||
│ ├── Monster.codeblock # 필드 액션 몬스터 (HP·피격·리스폰, 카드 전투와 별개)
|
||||
│ ├── MonsterAttack.codeblock
|
||||
│ ├── PlayerAttack.codeblock
|
||||
│ ├── PlayerHit.codeblock
|
||||
@@ -58,7 +59,11 @@ slaymaple/
|
||||
│ ├── UIToast.codeblock
|
||||
│ └── RectTileData_Henesys.tileset
|
||||
├── map/
|
||||
│ └── map01.map # 메인 맵
|
||||
│ ├── map01.map ~ map11.map # 맵 11종 (공식 배경 + STS풍 우측 배치)
|
||||
├── tools/ # 결정적 생성기 (단일 소스)
|
||||
│ ├── gen-slaydeck.mjs # 카드/덱 UI · SlayDeckController · common 생성
|
||||
│ ├── gen-cardhand.mjs # 손패 카드 엔티티 생성
|
||||
│ └── gen-maps.mjs # 맵 생성
|
||||
├── ui/ # UI 그룹 (Default / Popup / Toast)
|
||||
├── docs/
|
||||
│ └── slaymaple_basic_framework.md # 전투 프레임워크 설계 문서
|
||||
@@ -71,42 +76,61 @@ slaymaple/
|
||||
|
||||
## 게임 프레임워크 현황
|
||||
|
||||
`Global/common.gamelogic`의 `/common` 엔티티에 부착된 세 컴포넌트가 전투의 핵심입니다.
|
||||
현재 전투는 `Global/common.gamelogic`의 `/common` 엔티티에 부착된 **`SlayDeckController` 단일 컴포넌트**로 동작합니다. 모든 카드/덱/전투 관련 산출물(`ui/DefaultGroup.ui` · `RootDesk/MyDesk/SlayDeckController.codeblock` · `common.gamelogic`)은 **`tools/gen-slaydeck.mjs` 단일 소스에서 생성**됩니다(직접 편집 금지, 결정적 출력).
|
||||
|
||||
| 컴포넌트 | 역할 |
|
||||
|---|---|
|
||||
| `SlayCardCatalog` | 카드 데이터, 시작 덱 구성, 보상 풀, 카드 복제 정의 |
|
||||
| `SlayRunState` | HP·골드·층수·덱·유물·카드 보상 등 런(run) 영속 데이터 관리 |
|
||||
| `SlayCombatManager` | 턴 진행, 드로우/버림/소멸 더미, 에너지, 적 의도, 방어도, 데미지, 승패 처리 |
|
||||
| 컴포넌트 | 상태 | 역할 |
|
||||
|---|---|---|
|
||||
| `SlayDeckController` | ✅ 구현됨 | 카드 손패 UI 전투 — 드로우/버림/재셔플, 에너지, 카드 효과(데미지/방어), 적 HP·방어·의도, 턴 진행, 승패 |
|
||||
| `Monster.codeblock` | ✅ 구현됨 | 필드 액션 몬스터(HP·피격·리스폰) — 카드 전투와는 **별개** 시스템 |
|
||||
|
||||
### 프로토타입 흐름
|
||||
1. `SlayRunState`가 HP 80 · 10장 시작 덱으로 새 런 시작
|
||||
2. `SlayCombatManager`가 데모 전투 자동 시작
|
||||
3. 매 플레이어 턴: 에너지 3 회복, 방어도 초기화, 적 의도 갱신, 5장 드로우
|
||||
4. 카드 사용 시 에너지 소모 → 데미지/방어/드로우/에너지/상태이상 적용 → 버림 또는 소멸
|
||||
5. 턴 종료 시 손패 버림, 적 의도 실행, 상태이상 처리, 다음 턴 시작
|
||||
6. 전투 승리 시 잔여 HP 저장, 골드 15 지급, 카드 보상 3종 생성
|
||||
### 구현된 카드 전투 (단일 전투 루프)
|
||||
- **카드 손패 UI**: 에너지 3, 매 턴 5장 드로우, 버림 더미·재셔플, 카드 클릭 사용, 종류별 색상.
|
||||
- **카드 3종**: 타격(피해 6) · 방어(방어도 5) · 강타(피해 10). 각 카드에 `damage`/`block` 수치 필드. 시작 덱 10장.
|
||||
- **전투 상태**: 플레이어 `HP`/`Block`, 적 `HP`/`Block`/`Intent(의도)`. 적 의도는 **결정적 사이클**(공격10 → 공격6 → 방어8)로 다음 행동을 미리 표시.
|
||||
- **규칙**: 데미지는 방어도 먼저 차감 후 잔여만 HP에 적용. 플레이어 Block은 턴 시작 시 리셋.
|
||||
- **턴 흐름**: 카드 사용(`Attack`→적 HP↓, `Skill`→플레이어 Block↑) → 턴 종료 → 적 턴(의도 실행) → 다음 플레이어 턴.
|
||||
- **승패**: 적 HP 0 → 승리, 플레이어 HP 0 → 패배. 승패 시 입력 잠금 + 결과 표시(전투 보상 훅 자리 = E 예정).
|
||||
- **UI(CombatHud)**: 적 패널(이름·HP·방어·의도)·플레이어 패널(HP·방어)·승패 결과 텍스트.
|
||||
|
||||
> ⚠️ 플레이어 HP(80)·적 HP(45)·의도 수치(10·6·8)는 **루프 검증용 임시 placeholder**입니다.
|
||||
> 향후 캐릭터 특성별/몬스터별 데이터로 분리할 예정입니다(아래 D 참조).
|
||||
|
||||
### 유용한 스크립트 호출
|
||||
`/common` 엔티티에 붙은 스크립트에서:
|
||||
`/common` 엔티티(또는 Play Test 컨텍스트)에서:
|
||||
```lua
|
||||
self.Entity.SlayCombatManager:PlayCard(1, 1)
|
||||
self.Entity.SlayCombatManager:EndPlayerTurn()
|
||||
self.Entity.SlayCombatManager:DebugPlayFirstPlayable()
|
||||
self.Entity.SlayRunState:PickReward(1)
|
||||
self.Entity.SlayCombatManager:StartCombat("elite")
|
||||
local c = _EntityService:GetEntityByPath("/common").SlayDeckController
|
||||
c:PlayCard(1) -- 손패 slot 카드 사용
|
||||
c:EndPlayerTurn() -- 턴 종료 → 적 턴 → 다음 턴
|
||||
c:StartCombat() -- 전투 재시작(상태 초기화)
|
||||
```
|
||||
|
||||
상세 설계는 [`docs/slaymaple_basic_framework.md`](docs/slaymaple_basic_framework.md) 참조.
|
||||
|
||||
---
|
||||
|
||||
## 향후 설계 (미구현 — 목표 아키텍처)
|
||||
|
||||
아래는 로그라이크 메타까지 확장했을 때의 **목표 컴포넌트 구조**로, 현재는 미구현입니다. (현재는 `SlayDeckController` 하나가 카드 전투만 담당)
|
||||
|
||||
| 컴포넌트 (계획) | 역할 |
|
||||
|---|---|
|
||||
| `SlayCardCatalog` | 카드 데이터, 시작 덱 구성, 보상 풀, 카드 복제 정의 |
|
||||
| `SlayRunState` | HP·골드·층수·덱·유물·카드 보상 등 런(run) 영속 데이터 관리 |
|
||||
| `SlayCombatManager` | 턴 진행, 드로우/버림/소멸 더미, 에너지, 적 의도, 방어도, 데미지, 승패 처리 |
|
||||
|
||||
> 위 구조로 가더라도 카드/적 데이터는 `tools/`의 결정적 생성기를 단일 소스로 유지하는 방향을 권장합니다.
|
||||
|
||||
---
|
||||
|
||||
## 다음 구현 단계
|
||||
- [ ] HP·방어도·에너지·적 의도·손패 5버튼을 렌더링하는 전투 UI
|
||||
- [ ] 전투/엘리트/상점/휴식/이벤트/보스 노드를 가진 맵 노드 UI
|
||||
- [ ] `OnCombatStart` / `OnCardPlayed` / `OnTurnStart` / `OnCombatReward` 훅을 가진 유물 시스템
|
||||
- [ ] 적 행동 패턴을 데이터로 정의 (현재 단순 의도 패턴 → 무브셋)
|
||||
- [ ] 런 루프 완성 후 저장/불러오기
|
||||
- [x] HP·방어도·에너지·적 의도·손패 카드를 렌더링하는 전투 UI **(완료 — `SlayDeckController` + CombatHud)**
|
||||
- [x] 카드 사용이 실제 데미지/방어/적 의도/승패에 반영되는 단일 전투 루프 **(완료)**
|
||||
- [ ] 카드/적 데이터를 `data/cards.json` · `data/enemies.json`로 외부화 (D)
|
||||
- [ ] 전투를 N회 자동 시뮬레이션하는 밸런스 검증 도구 `tools/sim-balance.mjs` (F, D 선행)
|
||||
- [ ] 전투/엘리트/상점/휴식/이벤트/보스 노드를 가진 맵 노드 UI (E)
|
||||
- [ ] `OnCombatStart` / `OnCardPlayed` / `OnTurnStart` / `OnCombatReward` 훅을 가진 유물 시스템 (E)
|
||||
- [ ] 적 행동 패턴을 데이터로 정의 (현재 단순 결정적 의도 사이클 → 무브셋)
|
||||
- [ ] 런 영속(HP/골드/층/덱/유물) + 저장/불러오기 (E, 루프 end-to-end 후)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,42 +1,84 @@
|
||||
# SlayMaple Basic Framework
|
||||
|
||||
This project now has a small deckbuilder roguelike foundation inspired by turn-based card combat games.
|
||||
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).
|
||||
|
||||
## Components
|
||||
## Current Components (implemented)
|
||||
|
||||
- `SlayCardCatalog`: Defines card data, starter deck composition, reward pool, and card cloning.
|
||||
- `SlayRunState`: Owns persistent run data such as HP, gold, floor, deck, relics, and card rewards.
|
||||
- `SlayCombatManager`: Runs combat turns, draw/discard/exhaust piles, energy, enemy intents, block, damage, victory, and defeat.
|
||||
- `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 three components are attached to the `/common` entity in `Global/common.gamelogic`.
|
||||
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 were added, reopen or reload the local workspace so the new codeblock files are imported into the editor state.
|
||||
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.
|
||||
|
||||
## Prototype Flow
|
||||
## Implemented Combat Loop
|
||||
|
||||
1. `SlayRunState` starts a new run with 80 HP and a 10-card starter deck.
|
||||
2. `SlayCombatManager` starts a demo combat automatically.
|
||||
3. Each player turn refreshes energy to 3, clears block, rolls enemy intent, and draws 5 cards.
|
||||
4. Playing a card spends energy, applies damage/block/draw/energy/status effects, then sends the card to discard or exhaust.
|
||||
5. Ending the turn discards the hand, resolves enemy intent, ticks statuses, and starts the next turn.
|
||||
6. Winning combat stores the remaining HP back into the run, grants 15 gold, and generates 3 card reward options.
|
||||
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 a script attached to the same `/common` entity:
|
||||
From the `/common` entity (or a Play Test context):
|
||||
|
||||
```lua
|
||||
self.Entity.SlayCombatManager:PlayCard(1, 1)
|
||||
self.Entity.SlayCombatManager:EndPlayerTurn()
|
||||
self.Entity.SlayCombatManager:DebugPlayFirstPlayable()
|
||||
self.Entity.SlayRunState:PickReward(1)
|
||||
self.Entity.SlayCombatManager:StartCombat("elite")
|
||||
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
|
||||
|
||||
- Add a combat UI that renders HP, block, energy, enemy intent, and 5 hand-card buttons.
|
||||
- Add a map node UI with combat, elite, shop, rest, event, and boss node types.
|
||||
- Add relic definitions and hooks such as `OnCombatStart`, `OnCardPlayed`, `OnTurnStart`, and `OnCombatReward`.
|
||||
- Add enemy move sets as data instead of the current simple intent pattern.
|
||||
- Add save/load once the run loop is playable end to end.
|
||||
- [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.
|
||||
|
||||
Reference in New Issue
Block a user