import type { Spell } from '../game' export function cooldownNow() { return Date.now() } export function cooldownRemaining( cooldowns: Record, spellId: string, now = cooldownNow(), ) { return Math.max(0, ((cooldowns[spellId] ?? 0) - now) / 1000) } export function hasActiveCooldowns( cooldowns: Record, now = cooldownNow(), ) { return Object.values(cooldowns).some((readyAtMs) => readyAtMs > now) } export function pruneExpiredCooldowns( cooldowns: Record, now = cooldownNow(), ) { let changed = false const nextCooldowns: Record = {} for (const id in cooldowns) { if (cooldowns[id] <= now) { changed = true continue } nextCooldowns[id] = cooldowns[id] } return changed ? nextCooldowns : cooldowns } export function reduceCooldown( cooldowns: Record, spellId: string, seconds: number, now = cooldownNow(), ) { const readyAtMs = cooldowns[spellId] if (!readyAtMs || readyAtMs <= now) return cooldowns const nextReadyAtMs = readyAtMs - seconds * 1000 const nextCooldowns = { ...cooldowns } if (nextReadyAtMs <= now) delete nextCooldowns[spellId] else nextCooldowns[spellId] = nextReadyAtMs return nextCooldowns } export function canCastSpell( spell: Spell, resource: number, cooldowns: Record, resourceCost: number, now = cooldownNow(), ) { return resource >= resourceCost && cooldownRemaining(cooldowns, spell.id, now) <= 0 } export function putSpellOnCooldown( cooldowns: Record, spell: Spell, cooldownMultiplier = 1, now = cooldownNow(), ) { const cooldownMs = spell.cooldown * cooldownMultiplier * 1000 if (cooldownMs <= 0) { const nextCooldowns = { ...cooldowns } delete nextCooldowns[spell.id] return nextCooldowns } return { ...cooldowns, [spell.id]: now + cooldownMs, } }