把规则、架构与实现路线写成仓库文档。
后续改内容或结算顺序时有冻结依据,不必再翻原始稿才能对齐。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
# CONTENT_SCHEMA
|
||||
|
||||
Draft formats. Change this file together with JSON Schema and any validator.
|
||||
|
||||
Ordinary cards are data + standard effects. `customEffect` is an escape hatch.
|
||||
|
||||
## Identity
|
||||
|
||||
- `id`: stable string, unique in its catalog
|
||||
- `name`: display name
|
||||
- `tags`: string array, `kebab-case`
|
||||
|
||||
## Cards (`content/cards/*.json`)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "card.example.spark",
|
||||
"name": "Spark",
|
||||
"type": "Spell",
|
||||
"cost": 1,
|
||||
"tags": ["damage"],
|
||||
"effects": [
|
||||
{ "op": "Damage", "amount": 1, "target": "ChosenEnemy" }
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`type`: `Creature` | `Spell` | `Field`.
|
||||
|
||||
Creatures/fields may add `attack`, `health`, `countdown`, `triggers`, `activate`.
|
||||
|
||||
### Activate
|
||||
|
||||
```json
|
||||
"activate": [{ "op": "TransferStatsThenDie" }],
|
||||
"activateNeedsFriendly": true
|
||||
```
|
||||
|
||||
`activateNeedsEnemy` for targeted enemy activates. Default: once per own turn; usable the turn the creature enters.
|
||||
|
||||
### Play targeting flags
|
||||
|
||||
`playNeedsFriendly`, `playNeedsEnemy` (e.g. Vile Fire needs both).
|
||||
|
||||
### Tags (v1, partial)
|
||||
|
||||
Only these are recognized by rules/content checks. Extra kebab-case tags may exist as data and are ignored by the engine.
|
||||
|
||||
`damage`, `heal`, `creature`, `field`, `supply`, `countdown`
|
||||
|
||||
Do not grow this list unless a rule actually reads the new tag.
|
||||
|
||||
### Triggers
|
||||
|
||||
`when`: `TurnStart` | `OnDestroyed`. Effects use the same `op` list as play effects.
|
||||
|
||||
`effects` on a card are on-play / on-cast. Do not duplicate them as `OnEnter` yet.
|
||||
|
||||
## Standard `op` values
|
||||
|
||||
`Damage`, `Heal`, `Draw`, `Discard`, `Destroy`, `Summon`, `MoveCard`, `ModifyStat`, `ModifyCountdown`, `AddKeyword`, `RemoveKeyword`, `GenerateEnergy`, `AddStatus`, `RemoveStatus`.
|
||||
|
||||
Unknown `op` is a content error unless `customEffect` names a registered C# handler.
|
||||
|
||||
## Characters (`content/characters/*.json`)
|
||||
|
||||
Each character is **starting deck + skill** (see `docs/DESIGN.md`). `coreActions` / `bridge` are design metadata.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "char.example.ash",
|
||||
"name": "Ash",
|
||||
"coreActions": ["Damage", "Heal"],
|
||||
"bridge": "Damage+Heal",
|
||||
"skill": { "id": "skill.ash.ember", "summary": "..." },
|
||||
"startingDeck": ["card.example.spark"]
|
||||
}
|
||||
```
|
||||
|
||||
## Packs (`content/packs/*.json`)
|
||||
|
||||
In-run reward pools. `base: true` is always available this run. Other packs unlock when **all** `allOf` conditions are true. Evaluation is live against current run stats and current owned cards (not sticky, not meta).
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "pack.example.vitality",
|
||||
"name": "Vitality",
|
||||
"base": false,
|
||||
"coreActions": ["Heal"],
|
||||
"cards": ["card.example.salve"],
|
||||
"allOf": [{ "kind": "HealReceivedAtLeast", "amount": 2 }]
|
||||
}
|
||||
```
|
||||
|
||||
`kind`: `HealReceivedAtLeast`, `AttacksAtLeast`, `FriendlyDestroyedAtLeast`, `FatigueAtLeast`, `DeckTagAtLeast` (+ `tag`), `KillTagAtLeast` (+ `tag`).
|
||||
|
||||
World tags such as `cult` may appear in `KillTagAtLeast` without being v1 rules tags.
|
||||
|
||||
## Enemies / encounters
|
||||
|
||||
Same effect language as cards where possible. AI weights live in enemy data (`docs/AI.md`), not in the engine.
|
||||
|
||||
## Validation (Phase G)
|
||||
|
||||
Unique ids, existing references, required fields, numeric ranges, tag shape, effect arguments. PT report is optional and must not block load of contextual cards.
|
||||
Reference in New Issue
Block a user