Skip to main content

Data Model Reference

GCS ยท Reference

The six authorable asset families, the runtime battle types created from them, and the rule for who may mutate battle state.

For anyone deciding which type to reference, read, or leave alone when writing integration code.

The GCS data model splits into two halves. Assets are what you author in the Game Card Editor and store in databases. Runtime models are what a battle builds from those assets the moment it starts. Keeping the two apart answers most "where does this value live" questions before they become bugs.

Authorable assetsโ€‹

Six content families cover everything you can author:

TypeUser-facing responsibility
GameCardA playable card definition: cost, type, target mode, keywords, tags, artwork, and behavior.
GameStatusA buff, debuff, or reactive rule: stack policy, decay, icon, tags, behavior.
GameEnemyUnitAn enemy definition: HP range, tier, tags, prefab, intent behavior.
GamePlayerUnitA player definition: HP, energy, class identity, prefab, starting deck.
GameEncounterA battle setup: player, enemies, reward deck, battle rules, display data.
GameDeckA list of card entries (card plus copy count) used as starting or reward content.

The two unit families share one base, GameUnit, so a player unit and an enemy carry the same identity fields: Name, Description, Icon, Template prefab, and Tags. What differs is the stat block. A GamePlayerUnit has a fixed Base HP and Base Energy; a GameEnemyUnit has an HP Min / HP Max range and a Tier.

Each family has a matching database asset: GameCardDatabase, GameStatusDatabase, GameEnemyUnitDatabase, GamePlayerUnitDatabase, GameEncounterDatabase, and GameDeckDatabase. A database is a container of definitions. Registering it on the scene GameCardManager is what makes its content reachable at runtime.


Where behavior livesโ€‹

GameCard, GameStatus, and GameEnemyUnit each embed a flow graph directly in a field named Behavior. There is no separate behavior asset to create, link, or lose. The other three families carry no graph: an encounter describes the setup, a player unit acts through its cards, and a deck is just a card list.

One graph owner per effect

If you are looking for "the encounter's graph", it does not exist. Effects always belong to a card, a status, or an enemy. Encounter-wide rules are plain fields on BattleRules, not nodes.


Runtime modelsโ€‹

When GCSApi.StartBattle runs, GCS builds this runtime layer from the authored definitions:

TypeRuntime meaning
IBattleStateRead-only battle view: phase, units, piles, energy, turn, active encounter.
IBattleControllerThe supported mutation gateway for battle state.
UnitStateLive state for one unit: current HP, armor, statuses, flags.
EnemyUnitStateEnemy-specific UnitState with intent and behavior context.
CardInstanceOne card copy inside a battle pile, with its own instance id and upgrade flag.
CardPileA runtime pile: hand, draw, discard, or exhaust.
CardCostRuleA cost change applied to one card instance, either permanent or expiring after a set number of turns.
GCSApiThe public entry point for battle control, events, and the content registries.

The Monitor window shows this layer live. If a value appears there (current HP, armor, stacks, pile contents), it is runtime state, not something you edit on the asset.

Monitor Units tab showing live UnitState values for every unit in the battle


Definitions vs instancesโ€‹

Definitions are authored content. Instances are the copies a battle makes from them.

ConceptExampleDo not confuse with
Card definitionA GameCard named StrikeThe CardInstance currently in hand.
Unit definitionA GameEnemyUnit named StrawmanThat enemy's current HP and armor in battle.
Status definitionA GameStatus named BurnA unit's current Burn stack count.
Deck definitionA GameDeckThe runtime draw, discard, and exhaust piles.

Instance state is created once, at battle start. An enemy rolls its HP from the definition's range (both ends inclusive) and keeps that roll; a deck's entries become CardInstance copies in the draw pile, one per copy count. Editing a definition during Play Mode does not rewrite state that was already created from it.


The mutation ruleโ€‹

Never mutate runtime objects directly from your own code. Three supported paths exist:

  1. GCSApi for external C# integration.
  2. ctx.Controller inside custom FlowGraph nodes.
  3. Built-in FlowGraph nodes for authored effects.
Why direct writes bite back

Setting UnitState HP by hand, or inserting into a CardPile yourself, skips hooks, events, presentation updates, and Monitor output. The battle keeps running, but statuses stop reacting and the UI stops matching the state. Route every change through a controller method instead.


Internal-only typesโ€‹

Some runtime and editor classes are implementation details. If a type is not exposed through the authoring UI, GCSApi, the public node bases, event args, or a documented registry, treat it as internal even when C# lets you reach it. Internal types can change shape between versions; the documented entry points will not.