/** * Abklingzeiten für Fähigkeiten (Ausweichrolle, Orbital-Befehle) ohne Phaser. * Arbeitet mit der Spielzeit des GameScene, die während der Pause stillsteht – * Abklingzeiten laufen in der Pause also nicht heimlich weiter. * @module logic/cooldowns */ import { clamp } from './math.js'; export class CooldownTracker { constructor() { /** @type {Map} */ this.readyAt = new Map(); /** @type {Map} */ this.durations = new Map(); } /** * Startet die Abklingzeit von `id`. * @param {string} id * @param {number} durationMs * @param {number} now Spielzeit in ms. */ trigger(id, durationMs, now) { this.readyAt.set(id, now + durationMs); this.durations.set(id, durationMs); } /** * @param {string} id * @param {number} now * @returns {boolean} true, wenn die Fähigkeit benutzt werden kann (auch wenn nie ausgelöst). */ isReady(id, now) { return (this.readyAt.get(id) ?? -Infinity) <= now; } /** * @param {string} id * @param {number} now * @returns {number} Restzeit in ms (0 wenn bereit). */ remaining(id, now) { return Math.max(0, (this.readyAt.get(id) ?? now) - now); } /** * Fortschritt für Ladebalken im HUD. * @param {string} id * @param {number} now * @returns {number} 0 = gerade ausgelöst, 1 = bereit. */ progress(id, now) { const duration = this.durations.get(id); if (!duration) return 1; return clamp(1 - this.remaining(id, now) / duration, 0, 1); } /** * Setzt eine oder alle Abklingzeiten zurück. * @param {string} [id] */ reset(id) { if (id === undefined) { this.readyAt.clear(); this.durations.clear(); } else { this.readyAt.delete(id); this.durations.delete(id); } } }