import { CutsceneRunner, tileToWorld, worldToScreen } from '@rpg/engine';
import { Game } from '../../Game';
import { FLAGS, type FlagId } from '../../data/ids';
import { QUEST_TONE_TILES } from '../../data/quests';
/**
* Квест «Голос для резонатора» (docs/world.md, акт 2): звон у деревьев-
* механизмов рощи (интерактивы, тон — варом через реакции) и кат-сцена
* настройки — резонатор ловит собранные тоны, роща отвечает.
*/
export class ResonatorQuest {
constructor(
private game: Game,
/** Экранный центр ромба тайла (с Origin карты). */
private tileCenter: (tx: number, ty: number) => { x: number; y: number },
/** Всплеск пеплинок в точке (CombatViews.hitBurst). */
private burst: (s: { x: number; y: number }) => void,
private showToast: (text: string) => void,
private cutscene: CutsceneRunner
) {}
/** Кат-сцена настройки: камера к резонатору Клинта, звон, ответ рощи. */
startTuneCutscene(): void {
// Резонатор у поляны Клинта (интерактив clint_resonator).
const at = tileToWorld(12, 8);
const s = worldToScreen(at.x, at.y);
this.cutscene.play([
// Камера подходит и наезжает: настройка — крупный план.
{ kind: 'cameraMove', x: at.x, y: at.y, seconds: 1, camera: this.game.camera },
{ kind: 'cameraZoom', camera: this.game.camera, z: 2, seconds: 0.8 },
// Резонатор ловит тон: звон, тряска, всплеск.
{
kind: 'burst',
fn: () => {
void this.game.audio.play('sfx/bell_low', 1);
this.game.camera.addShake(2, 0.4);
this.burst(s);
},
seconds: 1
},
// Роща отвечает: прозвеневшие деревья вспыхивают в такт.
{
kind: 'burst',
fn: () => {
QUEST_TONE_TILES.forEach(([tx, ty], i) => {
if (!this.game.state.hasFlag(FLAGS[`tone_tree_${i + 1}` as FlagId])) return;
this.burst(this.tileCenter(tx, ty));
});
},
seconds: 1.2
},
// Отъезд и тост-финал квеста.
{ kind: 'cameraZoom', camera: this.game.camera, z: 1, seconds: 0.6 },
{ kind: 'call', fn: () => this.showToast('Резонатор держит тон. Роща слышит.') }
]);
}
}