Newer
Older
rpg / apps / game / src / systems / DialogueEffects.ts
import type { DialogueEffectOp } from '@rpg/engine';
import type { ItemId } from '../data/items';
import type { DialogueCustomId } from '../data/effects';

/**
 * Приёмник диалоговых эффектов: игра реализует его (сцена/системы),
 * движок только эмитит операции из do[]. Сюда стекается giveItem/takeItem,
 * звук, всплывашка и сюжетные custom-эффекты.
 */
export interface DialogueEffectSink {
    giveItem(id: ItemId, count: number): void;
    takeItem(id: ItemId, count: number): void;
    playSound(key: string): void;
    showToast(text: string): void;
    custom(name: DialogueCustomId, payload: Record<string, number | string | boolean> | undefined): void;
}

/**
 * Применить одну операцию эффекта к приёмнику. Неизвестный kind — ошибка
 * валидатора контента, рантайм его молча игнорирует.
 */
export function applyDialogueEffect(op: DialogueEffectOp, sink: DialogueEffectSink): void {
    switch (op.kind) {
        case 'giveItem':
            if (op.id) sink.giveItem(op.id as ItemId, op.count ?? 1);
            return;
        case 'takeItem':
            if (op.id) sink.takeItem(op.id as ItemId, op.count ?? 1);
            return;
        case 'sound':
            if (op.id) sink.playSound(op.id);
            return;
        case 'toast':
            if (op.text) sink.showToast(op.text);
            return;
        case 'custom':
            sink.custom((op.id ?? '') as DialogueCustomId, op.payload);
            return;
        default:
            return;
    }
}