import {CombatEntity, CombatState, EffectTable, PlayerEntity} from "./types"; import {CardData, EffectData} from "@/samples/slay-the-spire-like/system/types"; import {GameItemMeta} from "@/samples/slay-the-spire-like/system/progress/types"; import {GridInventory} from "@/samples/slay-the-spire-like/system/grid-inventory/types"; export function addEffect(effects: EffectTable, effect: EffectData, stacks: number){ let current = effects[effect.id]; if(!current) current = {data: effect, stacks}; else current.stacks += stacks; if(current.stacks === 0 && effects[effect.id]) delete effects[effect.id]; else if(current.stacks !== 0 && !effects[effect.id]) effects[effect.id] = current; } export function addEntityEffect(entity: CombatEntity, effect: EffectData, stacks: number){ addEffect(entity.effects, effect, stacks); } export function addItemEffect(entity: PlayerEntity, itemKey: string, effect: EffectData, stacks: number){ entity.itemEffects[itemKey] = entity.itemEffects[itemKey] || {}; addEffect(entity.itemEffects[itemKey], effect, stacks); } export function onEntityEffectUpkeep(entity: CombatEntity){ for(const effect of Object.values(entity.effects)){ const lifecycle = effect.data.lifecycle; if(lifecycle === 'temporary') addEntityEffect(entity, effect.data, -effect.stacks); else if(lifecycle === 'lingering') addEntityEffect(entity, effect.data, effect.stacks >= 0 ? -1 : 1); } } export function onEntityPostureDamage(entity: CombatEntity, damage: number){ for(const effect of Object.values(entity.effects)){ const lifecycle = effect.data.lifecycle; if(lifecycle === 'posture') addEntityEffect(entity, effect.data, -Math.min(damage, effect.stacks)); } } export function onPlayerItemEffectUpkeep(entity: PlayerEntity){ for(const [itemKey, itemEffects] of Object.entries(entity.itemEffects)){ for(const effect of Object.values(itemEffects)){ const lifecycle = effect.data.lifecycle; if(lifecycle === 'itemTemporary') addItemEffect(entity, itemKey, effect.data, -effect.stacks); } } } export function onItemPlay(entity: PlayerEntity, itemKey: string){ const effects = entity.itemEffects[itemKey]; if(!effects)return; for(const effect of Object.values(effects)){ if(effect.data.lifecycle === 'itemUntilPlay'){ addItemEffect(entity, itemKey, effect.data, -effect.stacks); } } } export function onItemDiscard(entity: PlayerEntity, itemKey: string){ const effects = entity.itemEffects[itemKey]; if(!effects)return; for(const effect of Object.values(effects)){ if(effect.data.lifecycle === 'itemUntilDiscard'){ addItemEffect(entity, itemKey, effect.data, -effect.stacks); } } } export function* getAliveEnemies(state: CombatState) { for (let enemy of state.enemies) { if (enemy.isAlive) { yield enemy; } } } export function getCombatEntity(state: CombatState, entityKey: string){ return entityKey === 'player' ? state.player : state.enemies.find(e => e.id === entityKey); } export function canPlayCard(player: PlayerEntity, costType: CardData['costType'], costCount: number, itemId: string, inventory: GridInventory): boolean { if (costType === 'energy') { return player.energy >= costCount; } if (costType === 'uses') { const item = inventory.items.get(itemId); if (!item || !item.meta) return false; const depletion = item.meta.depletion ?? 0; return depletion < costCount; } return true; } export function payCardCost(player: PlayerEntity, costType: CardData['costType'], costCount: number, itemId: string, inventory: GridInventory): void { if (costType === 'energy') { player.energy -= costCount; } else if (costType === 'uses') { const item = inventory.items.get(itemId); if (item && item.meta) { item.meta.depletion = (item.meta.depletion ?? 0) + costCount; } } }