Skip to main content

Runtime Data Types

Guide

Authored assets describe what can exist; runtime types store what is happening in one battle

Battle state and controller

TypeResponsibilityUse from project code
IBattleStateRead-only view of phase, turn, units, energy, piles, counters, encounter, waits, and variablesRead through GCSApi.Battle or higher-level GCSApi helpers
IBattleControllerSupported gateway for changing HP, armor, energy, statuses, cards, variables, delayed triggers, and unitsCustom FlowGraph nodes receive it as ctx.Controller; external code normally uses GCSApi
BattleStateViewInternal concrete object that implements the state and controller contractsDo 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

TypeLive data
UnitStateDefinition reference, current/max HP, armor, team, alive state, statuses, skip-turn flags, and active Hooks
EnemyUnitStateEverything 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

ConceptRuntime representationMeaning
Card definitionGameCardAuthored name, text, base cost, classification, Target, art, and Behavior
Battle copyCardInstanceOne copy with an instance id, upgrade state, and instance-specific cost changes
Active definitionCardInstance.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 surfaceLifetime
Hand, draw, discard, and exhaust pilesOne active battle
CardPile contentsOrdered CardInstance lists
Run master deckPersists across battles in the current run and seeds later battle piles
CardCostRuleOne 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 changingCorrect object
The cost printed on every future StrikeGameCard definition
The cost of one Strike in the current battlethat CardInstance through a supported cost rule
An enemy's authored HP rangeGameEnemyUnit definition
This enemy's current HPits EnemyUnitState through a controller call
A status's stack policyGameStatus definition
Current Poison on one unitthat unit's status stacks through a controller call
A starting deck recipeGameDeck definition
Cards currently available in battlethe 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:

  1. Built-in FlowGraph Action nodes for authored behavior
  2. ctx.Controller inside a custom FlowGraph node
  3. GCSApi from 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:

  • GCSApi
  • IBattleState and documented read models
  • IBattleController through documented extension contexts
  • public FlowGraph node bases, ports, and execution contexts
  • GCSEventNames and 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