// SWDBGData.js — data layer for Star Wars Deckbuilder. // All card content lives in /data/swdbg-cards.json (user-editable); this module // indexes the parsed JSON and exposes lookups. loadCardData() must be called // before the engine is used: the Phaser scene feeds it the preloaded JSON and // tools/verifySWDBG.js reads the file from disk. export const FACTIONS = ['empire', 'rebel']; export const FACTION_INFO = { empire: { label: 'Galactic Empire', color: 0x4d7fd6, colorHex: '#4d7fd6', dark: 0x16233d, symbol: '◉' }, rebel: { label: 'Rebel Alliance', color: 0xd6604d, colorHex: '#d6604d', dark: 0x3d1a16, symbol: '✴' }, neutral: { label: 'Neutral', color: 0xc9a54a, colorHex: '#c9a54a', dark: 0x332a14, symbol: '◈' }, }; // Every op the engine understands. verifySWDBG.js checks each card in the JSON // against this list so a data edit can't silently no-op. export const OPS = [ 'draw', 'gainResources', 'gainForce', 'gainAttack', 'damageBase', 'dealDamage', 'repairBase', 'oppDiscard', 'oppChoice', 'discardRow', 'destroyCapital', 'exileCards', 'freePurchase', 'buyGalaxyDiscard', 'topdeckNextPurchase', 'recoverDiscard', 'lookTop', 'lookTopSwap', 'lookOppHand', 'takeRowTemp', 'revealTop', 'choose', 'multi', 'purchaseToHand', 'traitBoost', 'typeBoost', 'rowBonus', 'selfBoostWhileForce', 'selfBoostWithTrait', 'selfBoostPerBaseLost', 'capitalDiscount', 'onPlayTraitAttack', ]; export const TIMINGS = ['action', 'constant', 'onPlay', 'onBounty', 'onPurchase', 'onReveal']; // Ops that are passive modifiers — never activated as an action. export const CONSTANT_OPS = ['traitBoost', 'typeBoost', 'rowBonus', 'selfBoostWhileForce', 'selfBoostWithTrait', 'selfBoostPerBaseLost', 'capitalDiscount', 'onPlayTraitAttack']; let DATA = null; export function loadCardData(json) { if (!json || !json.cards) throw new Error('swdbg-cards.json missing or malformed'); const byId = new Map(); const add = (def) => { if (byId.has(def.id)) throw new Error(`duplicate card id ${def.id}`); byId.set(def.id, def); }; for (const def of json.starterCards) add(def); add(json.outerRimPilot); for (const def of json.cards) add(def); const bases = { rebel: new Map(), empire: new Map() }; for (const f of FACTIONS) for (const b of json.bases[f]) bases[f].set(b.id, b); DATA = { json, byId, bases, meta: json.meta }; return DATA; } export function getData() { if (!DATA) throw new Error('loadCardData() must be called before using the engine'); return DATA; } export function cardDef(idOrInst) { const id = typeof idOrInst === 'string' ? idOrInst : idOrInst?.id; const def = getData().byId.get(id); if (!def) throw new Error(`unknown card id ${id}`); return def; } export function baseDef(faction, id) { const def = getData().bases[faction].get(id); if (!def) throw new Error(`unknown ${faction} base ${id}`); return def; } export function basesFor(faction) { return getData().json.bases[faction]; } let uidCounter = 0; export function makeInstance(id) { return { uid: ++uidCounter, id }; } export function resetUids() { uidCounter = 0; } // Deck construction ---------------------------------------------------------- export function buildGalaxyDeck() { const out = []; for (const def of getData().json.cards) { for (let i = 0; i < def.count; i++) out.push(makeInstance(def.id)); } return out; } export function buildStarterDeck(faction) { const out = []; for (const entry of getData().json.starters[faction]) { for (let i = 0; i < entry.count; i++) out.push(makeInstance(entry.id)); } return out; } export function buildOuterRim() { const def = getData().json.outerRimPilot; return Array.from({ length: def.count }, () => makeInstance(def.id)); }