Runtime Data Types
Authored assets describe what can exist; runtime types store what is happening in one battle
Battle state and controller
| Type | Responsibility | Use from project code |
|---|---|---|
IBattleState | Read-only view of phase, turn, units, energy, piles, counters, encounter, waits, and variables | Read through GCSApi.Battle or higher-level GCSApi helpers |
IBattleController | Supported gateway for changing HP, armor, energy, statuses, cards, variables, delayed triggers, and units | Custom FlowGraph nodes receive it as ctx.Controller; external code normally uses GCSApi |
BattleStateView | Internal concrete object that implements the state and controller contracts | Do not make integration code depend on its private implementation surface |
The split is deliberate; reads can be broad; writes must pass through a controller path so Hooks, events, phase checks, Monitor capture, and presentation remain synchronized
Unit state
| Type | Live data |
|---|---|
UnitState | Definition reference, current/max HP, armor, team, alive state, statuses, skip-turn flags, and active Hooks |
EnemyUnitState | Everything in UnitState, plus the current Intent and enemy-pattern execution state |
A GamePlayerUnit or GameEnemyUnit is the authored definition; its runtime state is created once for the current battle; enemy HP is rolled from the definition's inclusive HP range at battle start; later definition edits do not rewrite the existing unit
Status instances are stored as stack counts on the unit, keyed by GameStatus; the GameStatus still defines stack and decay rules, while UnitState answers how many stacks this unit has now
Card definitions and instances
| Concept | Runtime representation | Meaning |
|---|---|---|
| Card definition | GameCard | Authored name, text, base cost, classification, Target, art, and Behavior |
| Battle copy | CardInstance | One copy with an instance id, upgrade state, and instance-specific cost changes |
| Active definition | CardInstance.GetActiveCard() | Upgraded card when the instance is upgraded; otherwise the base card |
Use definitions while browsing databases and building decks; use instances for battle operations; two copies of Strike share one GameCard definition but remain two different CardInstance objects in the piles
Card piles and master deck
| Type or surface | Lifetime |
|---|---|
| Hand, draw, discard, and exhaust piles | One active battle |
CardPile contents | Ordered CardInstance lists |
| Run master deck | Persists across battles in the current run and seeds later battle piles |
CardCostRule | One card instance; expires by its configured duration or battle end |
Card Zones and Piles documents movement, reshuffling, hand limits, card play, generated cards, and the distinction between the run deck and battle piles
Definition versus instance
| You are changing | Correct object |
|---|---|
| The cost printed on every future Strike | GameCard definition |
| The cost of one Strike in the current battle | that CardInstance through a supported cost rule |
| An enemy's authored HP range | GameEnemyUnit definition |
| This enemy's current HP | its EnemyUnitState through a controller call |
| A status's stack policy | GameStatus definition |
| Current Poison on one unit | that unit's status stacks through a controller call |
| A starting deck recipe | GameDeck definition |
| Cards currently available in battle | the live piles |
Editing a definition in Play Mode does not reliably migrate state that was already instantiated; inspect live values in Game Card Monitor rather than assuming the Inspector still represents the running battle
Safe mutation paths
Use exactly one of these supported entry points:
- Built-in FlowGraph Action nodes for authored behavior
ctx.Controllerinside a custom FlowGraph nodeGCSApifrom external project code
Directly assigning HP, changing a pile list, or editing a status dictionary bypasses one or more of these behaviors:
- Hook resolution
- phase and target checks
- built-in event dispatch
- Monitor evidence
- UI and presentation refresh
- battle-outcome checks
If a public GCSApi mutation does not exist for a project requirement, implement a focused custom node or integration through the documented controller contract; do not treat an accessible internal field as a supported API
Public boundary
Treat these as supported integration surfaces:
GCSApiIBattleStateand documented read modelsIBattleControllerthrough documented extension contexts- public FlowGraph node bases, ports, and execution contexts
GCSEventNamesand event argument types- the four extension registries
Types not exposed through those surfaces are implementation details even when C# visibility makes them reachable; start with Runtime Architecture for the layer map and GCSApi Guide for project-code workflows