Files
card_game/docs/CONTENT_SCHEMA.md
chenmoranzhiandCursor 06eb360fbf 把规则、架构与实现路线写成仓库文档。
后续改内容或结算顺序时有冻结依据,不必再翻原始稿才能对齐。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-09 02:04:20 +08:00

3.1 KiB

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)

{
  "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

"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.

{
  "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).

{
  "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.