100 lines
9.2 KiB
Markdown
100 lines
9.2 KiB
Markdown
# Dialog Engine — окно диалога и язык сценариев
|
||
|
||
Dialog Engine — это то, что игрок читает и по чему щёлкает: окно диалога с репликами, портретами и вариантами ответа. За ним стоит **язык сценариев** — небольшие текстовые файлы `.scenario`, в которых история записана строка за строкой: кто что говорит, какие есть варианты ответа, куда ведёт каждый из них и что при этом происходит в игре (новый фон, музыка, предмет, шаг задания, другая сцена). С его помощью рассказывает свою история каждая игра коллекции — от шаблона новеллы до RPG Plus.
|
||
|
||
## Что видит игрок
|
||
|
||
Сценарий сцены запускается сам, как только игрок входит в неё. Реплики появляются в окне внизу экрана; щелчок показывает следующую:
|
||
|
||

|
||
|
||
Когда история о чём-то спрашивает, справа появляются варианты ответа — и она ждёт, пока игрок выберет один из них:
|
||
|
||

|
||
|
||
Вариант «Зайти в бар» переносит игрока в сцену бара, где запускается уже его собственный сценарий:
|
||
|
||

|
||
|
||
## Сценарий этих кадров
|
||
|
||
Вот весь сценарий города из шаблона новеллы (`my_novel_game/scenarios/my_novel_town.scenario`):
|
||
|
||
```scenario
|
||
scene: my_novel_town
|
||
priority: 10
|
||
---
|
||
# Город — хаб: при каждом визите игрок видит один и тот же выбор.
|
||
text "Вечерний город. Фонари уже горят, по мостовой тянет прохладой." key=my_novel/town/intro
|
||
select "Куда пойти?" key=my_novel/town/prompt
|
||
option "Зайти в бар" key=my_novel/town/opt_bar -> :bar
|
||
option "Вернуться домой" key=my_novel/town/opt_home -> :home
|
||
|
||
:bar
|
||
switch_scene my_novel_bar
|
||
end
|
||
|
||
:home
|
||
switch_scene my_novel_home
|
||
end
|
||
```
|
||
|
||
- **Заголовок** над `---` говорит, когда сценарий играет: `scene:` называет сцену, `priority:` упорядочивает несколько сценариев одной сцены (с меньшим числом играет первым). Ниже встречаются и другие строки заголовка.
|
||
- `text "…"` показывает реплику и ждёт щелчка. `key=` — ключ перевода реплики; текст в кавычках показывается, если перевода не нашлось.
|
||
- `select` задаёт вопрос, и каждый `option` — вариант ответа, который ведёт к **метке** (`-> :bar`).
|
||
- `:bar` — метка; `switch_scene` уходит в другую сцену; `end` завершает сценарий.
|
||
- Строка, начинающаяся с `#`, — заметка для автора.
|
||
|
||
Чтобы добавить историю в сцену, положите файл `.scenario` в любое место папки `scenarios/` своего мода и назовите сцену в заголовке.
|
||
|
||
## Как писать историю
|
||
|
||
**Реплики и портреты.** `text "…" first=marao/sad` показывает портрет на первом месте, `second=…` — на втором (см. Characters Engine). `ptext` делает то же, что `text`, и вдобавок подставляет вместо `${name}` значение переменной. `title "…"` показывает заголовок главы.
|
||
|
||
**Выбор и переходы.** Вариант ответа можно показывать только при выполнении условия: `option "Pay" "if=item('money/coin') >= 5" -> :pay` (условие с пробелами берётся в кавычки вместе с `if=`). `goto -> :label` перескакивает без вопросов. `when "<condition>" -> :label` выполняет переход, если условие выполнено в этот момент:
|
||
|
||
```scenario
|
||
when "rpg_wolf_dead == 1" -> :lantern
|
||
```
|
||
|
||
**Запоминание.** `flag rpg_quest_taken 1` ставит сюжетный флаг, который сохраняется вместе с игрой; условия читают его как `rpg_quest_taken == 1`. `set name value` задаёт переменную текущего диалога: `ptext` покажет её как `${name}`, а действия смогут её прочитать.
|
||
|
||
**Условия** — один общий язык: флаги, `item('id')` из Items Base, проверки заданий из Quests Engine, характеристики и экипировка из своих модов, соединённые через `&&`, `||` и `!`.
|
||
|
||
**Сцена.** `background`, `foreground`, `background_color`, `music`, `sound`, `effect`, `delay`, `light_set`, `hide_dialog`/`show_dialog`, `interactive_add`/`interactive_remove`, `notify`.
|
||
|
||
**Игровые действия.** `action <name> key=value …` запускает действие другого мода, например `action item.add id=money/coin count=3` или `action quest.set_status quest_id=woodland_ward status=Progress`. Все действия перечислены в schema-файлах модов, а Editor Tools предлагает их в редакторе сценариев и палитре команд.
|
||
|
||
## Когда сценарий запускается
|
||
|
||
Решает заголовок:
|
||
|
||
```scenario
|
||
scene: prolog_alley
|
||
priority: 15
|
||
condition: AwakeningQuest.notHasTag("cloak_taken")
|
||
is_one_run: true
|
||
save_allowed: true
|
||
---
|
||
```
|
||
|
||
- `scene:` — сцена, в которой сценарий играет, когда игрок приходит.
|
||
- `priority:` — порядок среди сценариев одной сцены; первым играет тот, у кого наименьшее допустимое число, а следующий стартует, когда диалог закончится.
|
||
- `condition:` — сценарий играет, только пока условие выполнено; когда флаг или задание меняется, сцена проверяет снова.
|
||
- `is_one_run: true` — играется один раз за игру.
|
||
- `after:` — ждёт, пока названный сценарий не будет пройден.
|
||
- `save_allowed: true` — в этой сцене можно сохраняться.
|
||
|
||
Сценарий без строки `scene:` не запускается сценой — его запускает что-то другое: например, щелчок по интерактивному объекту или событие на карте.
|
||
|
||
## Чужие моды добавляют и заменяют сценарии
|
||
|
||
Сценарии всех модов собираются в общий набор. Добавить историю в чужую сцену просто: назовите эту сцену в заголовке. А мод, который зависит от владельца и кладёт в себя сценарий с тем же именем файла, заменяет его.
|
||
|
||
## Если что-то пошло не так
|
||
|
||
1. **Сценарий никогда не играет.** Ошибочное имя в `scene:`, ложное условие в `condition` — или у сценария есть `is_one_run`, и он уже играл.
|
||
2. **Реплика показывается не на том языке.** Ключа `key=` нет в файлах `locale` мода для этого языка, и вместо перевода показывается текст в кавычках.
|
||
3. **Ответ ведёт в никуда.** Метка после `->` должна существовать в том же файле и записываться с двоеточием (`:bar`).
|
||
4. **`action` ничего не делает.** Мод — владелец действия не входит в игру (в логе написано, что действие "is not registered"), или имя параметра неверное — сверьте его с действием в редакторе сценариев Editor Tools.
|