import {createMiddlewareChain} from "../utils/middleware"; import {CombatGameContext} from "./types"; import {getAliveEnemies} from "@/samples/slay-the-spire-like/system/combat/utils"; import { onEntityEffectUpkeep, onPlayerItemEffectUpkeep } from "@/samples/slay-the-spire-like/system/combat/effects"; import {promptMainAction} from "@/samples/slay-the-spire-like/system/combat/prompts"; type TriggerTypes = { onCombatStart: {}, onTurnStart: { entityKey: "player" | string, }, onTurnEnd: { entityKey: "player" | string, }, onShuffle: { entityKey: "player" | string, }, onCardPlayed: { cardId: string, }, onCardDiscarded: { cardId: string, }, onCardDrawn: { cardId: string, }, onEffectApplied: { effectId: string, entityKey: "player" | string, stacks: number, }, } function createTriggers(){ return { onCombatStart: createTrigger("onCombatStart"), onTurnStart: createTrigger("onTurnStart"), onTurnEnd: createTrigger("onTurnEnd"), onShuffle: createTrigger("onShuffle"), onCardPlayed: createTrigger("onCardPlayed"), onCardDiscarded: createTrigger("onCardDiscarded"), onCardDrawn: createTrigger("onCardDrawn"), onEffectApplied: createTrigger("onEffectApplied"), } } export type Triggers = ReturnType export function createStartWith(build: (triggers: Triggers) => void){ const triggers = createTriggers(); build(triggers); return async function(game: CombatGameContext){ await triggers.onCombatStart.execute(game,{}); while(true){ await triggers.onTurnStart.execute(game,{entityKey: "player"}); await game.produceAsync(draft => { onEntityEffectUpkeep(draft.player); onPlayerItemEffectUpkeep(draft.player); }); while(true){ const action = await promptMainAction(game); if(action.action === "end-turn") break; //TODO resolve action here } // TODO discard cards here await triggers.onTurnEnd.execute(game,{entityKey: "player"}); // TODO recover energy, draw new cards here for(const enemy of getAliveEnemies(game.value)){ await triggers.onTurnStart.execute(game,{entityKey: enemy.id}); } await game.produceAsync(draft => { for(const enemy of getAliveEnemies(game.value)){ onEntityEffectUpkeep(enemy); } }); // TODO execute enemy intent, then update with new one here for(const enemy of getAliveEnemies(game.value)){ await triggers.onTurnEnd.execute(game,{entityKey: enemy.id}); } } } } function createTrigger(event: TKey) { type Ctx = TriggerTypes[TKey] & { event: TKey, game: CombatGameContext }; const {use, execute} = createMiddlewareChain(); return { use, execute: (game: CombatGameContext, ctx: TriggerTypes[TKey]) => execute({...ctx, event, game}), } }