import type { NpcDef } from './npcs';
import type { EnemyKindId } from './enemies';
import { NPCS } from './npcs';
import type { ItemId } from './items';
/**
* Области демо-среза (улица и интерьер — общий контекст). Карты хранятся
* файлами assets/maps/<id>.map (формат rpg-map, RLE) и загружаются через
* parseMap в BootScene.
*/
export type AreaId = 'meadows' | 'ponds' | 'zvenets';
/** Куда ведёт переход: в другую область (с точкой входа) или назад, откуда вошли. */
export type TransitionTarget =
| { kind: 'area'; area: AreaId; entry: { x: number; y: number } }
| { kind: 'return' };
/**
* Единый механизм переходов: выходы между локациями (step), двери/порталы/
* колодцы (click). Первая подходящая по тайлу и триггеру — срабатывает.
*/
export interface TransitionDef {
/** Тайл-триггер. */
tile: { x: number; y: number };
/** Подпись для подсказки при близости (позже) и снапшота. */
label?: string;
target: TransitionTarget;
/** step — наступил (по умолчанию), click — клик по тайлу (двери, порталы). */
trigger?: 'step' | 'click';
/** Условия: не выполнены — переход не срабатывает, герой получает lockedText. */
requiresFlag?: string;
requiresItem?: ItemId;
lockedText?: string;
/** Длительность fade (сек), по умолчанию 0.4. */
duration?: number;
}
/** Зона опасности (накат): герой без нужного предмета еле идёт и рискует голосом. */
export interface HazardDef {
name: string;
/** Тайлы низины (свежий пласт пепла). */
tiles: { x: number; y: number }[];
/** Без чего нельзя дышать здесь (по умолчанию — полотно-маска). */
requiresItem?: ItemId;
}
export interface AreaDef {
id: AreaId;
name: string;
/** Музыка области (кроссфейд при переходе). */
music: string;
/** Стартовый тайл (новая игра / респаун / фолбэк return). */
spawn: { x: number; y: number };
npcs: NpcDef[];
enemies: { kind: EnemyKindId; tile: { x: number; y: number } }[];
transitions: TransitionDef[];
/** Атмосферные частицы: 'ash' — пепел, 'fog' — туман прудов, 'none' — интерьер. */
ambience: 'ash' | 'fog' | 'none';
/** Зоны наката (необязательно). */
hazards?: HazardDef[];
/** Спавны пейзажных оленей (тайлы). */
fauna?: { x: number; y: number }[];
}
export const AREAS: Record<AreaId, AreaDef> = {
meadows: {
id: 'meadows',
name: 'Выжженные луга',
music: 'music/meadows',
spawn: { x: 14, y: 14 },
npcs: [],
enemies: [
{ kind: 'crawler', tile: { x: 8, y: 9 } },
{ kind: 'crawler', tile: { x: 10, y: 7 } },
{ kind: 'spitter', tile: { x: 19, y: 6 } },
{ kind: 'crawler', tile: { x: 22, y: 21 } },
{ kind: 'heavy', tile: { x: 6, y: 22 } }
],
transitions: [
// Северо-западный угол: тропа на Серые пруды.
{ tile: { x: 2, y: 2 }, target: { kind: 'area', area: 'ponds', entry: { x: 3, y: 3 } } },
// Тропа в Звенец (деревня-мастерская).
{ tile: { x: 26, y: 14 }, target: { kind: 'area', area: 'zvenets', entry: { x: 3, y: 10 } } },
// Встречный колодец: звон в Звенец (клик по тайлу колодца).
{
tile: { x: 22, y: 20 },
label: 'Старый колодец',
target: { kind: 'area', area: 'zvenets', entry: { x: 9, y: 7 } },
trigger: 'click',
duration: 0.2
}
],
ambience: 'ash',
// Безгласные олени у берегов прудов — подходят к звону.
fauna: [
{ x: 9, y: 18 },
{ x: 12, y: 20 }
]
},
ponds: {
id: 'ponds',
name: 'Серые пруды',
music: 'music/ponds',
spawn: { x: 3, y: 3 },
npcs: [],
enemies: [
{ kind: 'crawler', tile: { x: 4, y: 11 } },
{ kind: 'crawler', tile: { x: 9, y: 18 } },
{ kind: 'spitter', tile: { x: 18, y: 10 } },
{ kind: 'spitter', tile: { x: 18, y: 18 } },
{ kind: 'heavy', tile: { x: 13, y: 17 } }
],
transitions: [
// Обратно на луга.
{ tile: { x: 2, y: 2 }, target: { kind: 'area', area: 'meadows', entry: { x: 3, y: 3 } } }
],
ambience: 'fog',
// Свежий накат — низины у берегов: без вощёного полотна здесь не дышать.
hazards: [
{
name: 'Свежий накат',
requiresItem: 'cloth',
tiles: [
{ x: 5, y: 16 },
{ x: 6, y: 17 },
{ x: 7, y: 17 },
{ x: 8, y: 18 },
{ x: 9, y: 18 },
{ x: 10, y: 18 },
{ x: 11, y: 19 },
{ x: 12, y: 19 },
{ x: 13, y: 18 },
{ x: 14, y: 18 },
{ x: 15, y: 17 },
{ x: 4, y: 9 },
{ x: 3, y: 8 },
{ x: 15, y: 6 },
{ x: 16, y: 4 }
]
}
],
// Один олень на северо-западном берегу.
fauna: [{ x: 4, y: 6 }]
},
zvenets: {
id: 'zvenets',
name: 'Звенец',
music: 'music/zvenets',
spawn: { x: 14, y: 10 },
npcs: NPCS,
enemies: [],
transitions: [
// Тропа обратно на луга.
{ tile: { x: 2, y: 10 }, target: { kind: 'area', area: 'meadows', entry: { x: 25, y: 14 } } },
// Колодец у дома Ирвина: телепорт на луга (клик; встречный лугам).
{
tile: { x: 9, y: 6 },
label: 'Старый колодец',
target: { kind: 'area', area: 'meadows', entry: { x: 22, y: 21 } },
trigger: 'click',
duration: 0.2
}
],
ambience: 'ash'
}
};
/** Область по id (фолбэк 'meadows' — для старых сейвов и пустых id). */
export function areaOf(id: string | null | undefined): AreaDef {
return AREAS[(id ?? 'meadows') as AreaId] ?? AREAS.meadows;
}