ReadonlyunitsReadonlyweaponsReadonlyweaponReadonlyfactionsReadonlyabilitiesReadonlyunitReadonlytargetReadonlydetachmentsReadonlyalliedReadonlyenhancementsReadonlystratagemsReadonlywargearReadonlywargearReadonlymissionsReadonlymissionReadonlymissionReadonlydeploymentReadonlyforceReadonlyterrainReadonlyterrainReadonlyhullReadonlyresourceReadonlyleaderReadonlyunitReadonlygameReadonlyinteractionReadonlyphaseStaticembeddedThe dataset built from the package's embedded data.
Phases a source acts in, unioned across its phase-mappings.
Resolve a terrain layout to absolute board-space vertices using this
dataset's embedded terrain-template catalog — the layout-id →
renderable-geometry hop. Mirror of Rust Dataset::resolve_terrain; the
geometry is pinned by the terrain-resolver conformance corpus.
The terrain layouts a deployment pattern recommends, in declared order, skipping any ids absent from the dataset.
Every ability carrying a reactive AbilityTrigger, sorted by ability id. Each entry names the units that list the ability (sorted; empty for faction/detachment-rule abilities no unit references directly).
Dispatch index for event-driven consumers: GameEvent → the reactive triggers firing on it. Keys are iterated in event order and each bucket is sorted by ability id, so the structure is deterministic across runs.
Weapons whose profiles reference the given weapon-keyword id.
Units carrying the given keyword, matched case-insensitively against the
union of each unit's keywords and faction_keywords. Powers a list
builder's keyword search bar (type "Khorne" to find every Khorne unit),
across the whole dataset — so it also surfaces cross-faction ally pools.
Returns each faction's copy of a shared unit id separately.
The allied-rules offered for an army of factionId running the given
detachments. A rule applies when both its gates pass: the army gate
(army_keywords_any empty, or intersecting the faction's keywords) and the
detachment gate (detachment_ids empty, or any listed id among detachmentIds). Order
follows the allied-rules data file. The strict "every model carries an
army keyword" check (for soup lists) is a builder/validation concern — this
offers the candidate rules a faction qualifies for. Mirror of Rust
Dataset::allies_for; pinned by the allies_for conformance query.
The unit pool an allied-rule grants, sorted by name. Starts from the rule's
source_faction_id (if set, to keep that faction's copy of shared ids) or
the whole dataset, then ANDs every filter the rule sets: source_datasheet_ids
(an explicit id allowlist — the primary selector for generated pools), any
source_keywords, required_keywords (all present), excluded_keywords
(none present), and roles. Empty for an unknown rule id or a pool that
resolves to nothing. Mirror of Rust Dataset::ally_units_for; pinned by the
ally_units_for conformance query.
Wargear options authored for the given unit, in declared order. Scoped to
the unit's own faction: a chassis shared across factions (e.g.
chaos-terminators in World Eaters and Emperors Children) reuses the same
option ids for different swaps, so the lookup keys on (faction_id, unit_id)
— never the union across factions. Mirror of Rust Dataset::wargear_options_of.
Empty for a unit with no options.
The unit-composition authored for the given unit, faction-scoped exactly
like wargearOptionsOf: shared chassis carry a distinct composition
per faction under one unit_id, so the lookup keys on (faction_id, unit_id) rather than the faction-blind unitCompositions.find(...).
undefined when the unit has no composition.
Leaders whose leader-attachment data lists bodyguardUnitId among its
eligible body units, sorted by name. The attachment is stored on the
leader pointing down to its bodyguards, so answering "which leaders can
attach to this unit?" means scanning the attachment list. Returns an empty
array for a unit that no leader can attach to (including leader units).
The inverse of leadersAttachableTo: the body units the given
leader can attach to, sorted by name. Scans the same leader-attachment
data from the leader's side (leader_id matches; resolve each
eligible_bodyguard_ids entry), deduped by id. Empty for a non-leader
unit. Together the two queries give the bidirectional attachment graph the
SPA needs to offer a partner dropdown from either end.
Enumerate every ability that could apply to the given unit in phase,
grouped by source. The SPA uses this to render the abilities pane.
Attacker-perspective Buff stack for a (unit, phase) combination: intrinsic weapon-profile keywords plus every eligible ability whose DSL effect translates to an attacker-side buff (army, detachment, unit, attached members, support, plus any stratagems the caller has opted into).
The result includes only buffs the buff layer can express today — the
unsupported half of the DSL→Buff translation is dropped here so callers
who just want the stack don't need to thread diagnostics through. Use
AbilityView.describeBuffs when you need the diagnostics for an
individual ability. Symmetric to defensiveBuffsFor, which walks
the same eligibility set under target perspective.
OptionalweaponProfiles?: { weaponId: string; profileIndex: number }[]OptionaloptedInStratagemIds?: string[]Stratagem ids the caller has opted into spending CP on.
Defender-perspective buff stack for the chosen unit: walks the same
eligible-abilities set as buffsFor but translates each ability's
DSL effect as defensive (FNP, save mods from stat-modifier Sv,
toughness mods from stat-modifier T, save rerolls, incoming hit
penalties from bs-modifier). Use this when the chosen unit is being
crunched as the target — the engine reads feelNoPain/saveMod/
toughnessMod out of resolveBuffs so wiring the result into crunch
just means concatenating onto the existing buffs array.
weaponProfiles are ignored under target perspective — weapon-keyword
effects ride with the firing weapon, not the receiving unit.
Enumerate every attacker-side buff a unit could stack in context as a
list of toggleable levers, plus the activation groups that limit them.
Unlike buffsFor — which returns only the buffs that auto-apply —
this surfaces the player decisions too: stratagems, and the activatable
gates the DSL models as dice-pool options, choice branches, or
timing-gated activations (e.g. Blessings of Khorne's three keyword grants).
Each lever carries enabled (its default state) and, where it's part of a
limited pool, a group id whose StackableBuffGroup caps how many
can fire at once. The intended loop:
const { buffs } = ds.stackableBuffsFor(input, ctx);
const chosen = buffs.filter(b => b.enabled).flatMap(b => b.buffs);
crunch({ ...profiles, buffs: chosen, context: ctx }, ds);
Target/phase conditions a lever still carries (e.g. "vs Infantry") ride on
each buff's applicableWhen, so toggling it on is always safe — the
resolver gates it per-target.
The whole dataset, with linked accessors over every entity collection.