# Dialog Engine — окно диалога и язык сценариев Dialog Engine — это то, что игрок читает и по чему щёлкает: окно диалога с репликами, портретами и вариантами ответа. За ним стоит **язык сценариев** — небольшие текстовые файлы `.scenario`, в которых история записана строка за строкой: кто что говорит, какие есть варианты ответа, куда ведёт каждый из них и что при этом происходит в игре (новый фон, музыка, предмет, шаг задания, другая сцена). С его помощью рассказывает свою история каждая игра коллекции — от шаблона новеллы до RPG Plus. ## Что видит игрок Сценарий сцены запускается сам, как только игрок входит в неё. Реплики появляются в окне внизу экрана; щелчок показывает следующую: ![Город из My Novel: вечерняя улица, в окне диалога — реплика «Вечерний город. Фонари уже горят, по мостовой тянет прохладой».](assets/town-text.jpg) Когда история о чём-то спрашивает, справа появляются варианты ответа — и она ждёт, пока игрок выберет один из них: ![Вопрос «Куда пойти?» в окне диалога и два варианта справа: «Зайти в бар» и «Вернуться домой».](assets/town-choice.jpg) Вариант «Зайти в бар» переносит игрока в сцену бара, где запускается уже его собственный сценарий: ![Бар из My Novel и его первая реплика в окне диалога.](assets/bar-text.jpg) ## Сценарий этих кадров Вот весь сценарий города из шаблона новеллы (`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 "" -> :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 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.