67 lines
1.9 KiB
TypeScript
67 lines
1.9 KiB
TypeScript
// Card definitions as the engine sees them. The definitions themselves live in `content`.
|
|
|
|
import type { Action, Ctx } from "./queue";
|
|
|
|
/**
|
|
* A card's behaviour: given where and for whom it runs, the actions to perform.
|
|
* Module 2 writes these as functions in `content`; Module 5 turns them into data.
|
|
*/
|
|
export type EffectFn = (ctx: Ctx) => Action[];
|
|
|
|
/** What a triggered ability listens for. */
|
|
export type TriggerOn =
|
|
| "selfDamaged" // this minion takes damage
|
|
| "friendlyMinionDamaged" // a minion with the same owner (this one included) takes damage
|
|
| "anyMinionDamaged" // any minion takes damage
|
|
| "heroDamaged"; // either hero takes damage
|
|
|
|
/** The trigger's family name, as reported in `Triggered` events. */
|
|
export function triggerLabel(on: TriggerOn): string {
|
|
switch (on) {
|
|
case "selfDamaged":
|
|
case "friendlyMinionDamaged":
|
|
case "anyMinionDamaged":
|
|
case "heroDamaged":
|
|
return "damaged";
|
|
}
|
|
}
|
|
|
|
export interface Trigger {
|
|
on: TriggerOn;
|
|
effect: EffectFn;
|
|
}
|
|
|
|
/** What the engine needs to know about a card. */
|
|
export interface CardDef {
|
|
name: string;
|
|
attack: number;
|
|
health: number;
|
|
/** Triggered abilities, in printed order. */
|
|
triggers: Trigger[];
|
|
/** A spell's effect when cast; absent for minions. */
|
|
onCast?: EffectFn;
|
|
}
|
|
|
|
export function minion(name: string, attack: number, health: number, triggers: Trigger[] = []): CardDef {
|
|
return { name, attack, health, triggers };
|
|
}
|
|
|
|
export function spell(name: string, onCast: EffectFn): CardDef {
|
|
return { name, attack: 0, health: 0, triggers: [], onCast };
|
|
}
|
|
|
|
/** Every card the game can create, looked up by name. */
|
|
export class CardLibrary {
|
|
private readonly cards = new Map<string, CardDef>();
|
|
|
|
constructor(defs: CardDef[]) {
|
|
for (const def of defs) this.cards.set(def.name, def);
|
|
}
|
|
|
|
get(name: string): CardDef {
|
|
const def = this.cards.get(name);
|
|
if (!def) throw new Error(`unknown card "${name}": define it in src/content`);
|
|
return def;
|
|
}
|
|
}
|