Создание диалогов (полный обзор)

Материал из Mod Wiki.

(Различия между версиями)
Перейти к: навигация, поиск
Версия 09:54, 5 июля 2008 (править)
BAC9-FLCL (Обсуждение | вклад)
(Текстовые (строковые) массивы)
← К предыдущему изменению
Версия 09:54, 5 июля 2008 (править) (отменить)
BAC9-FLCL (Обсуждение | вклад)
(Текстовые (строковые) массивы)
К следующему изменению →
Строка 179: Строка 179:
</source> </source>
-Во-первых, мы записываем текст фразы в <'''text>...</text>'''. Это, безусловно, удобно, но на самом деле - может привести к проблемам. Дело в том, что таким образом можно использовать только короткие фразы. Стоит ввести в тег длинный текст, и игра... так сказать, не переварит наш диалог.+Мы записывали текст фразы в <'''text>...</text>'''. Это, безусловно, удобно, но на самом деле - может привести к проблемам. Дело в том, что таким образом можно использовать только короткие фразы. Стоит ввести в тег длинный текст, и игра... так сказать, не переварит наш диалог.
Поэтому нужно использовать не тексты, а ссылки на них. Работает это так: Поэтому нужно использовать не тексты, а ссылки на них. Работает это так:

Версия 09:54, 5 июля 2008

Статья в процессе написания...

Содержание

Общие данные

В диалогах обычно задействуются три .xml-файла:

  • character_desc_x.xml
  • dialogs_x.xml
  • stable_dialogs_x.xml

(где x - название уровня)

Главными являются файлы dialogs_x.xml, на них, собственно, и будет направлена основная работа инструмента. В этих файлах хранится структура, скелет диалога. Кстати, x - это не обязательно название уровня. В принципе, диалоги можно помещать абсолютно произвольно, просто по локациям - это удобней для последующей работы.


Структура фраз

В общем виде диалог выглядит так:


диалог 001

фраза 0
"Так, чего хотел-то?"
следующие фразы: 1

фраза 1
"Задание для тебя есть. Возьмешься?"
следующие фразы: 21, 22

фраза 21
"Ну, давай."
следующие фразы: 3

фраза 22
"Не, иди к черту."
следующие фразы: нет
действие: выйти из диалога

[фраза 3 и дальнейшее продолжение...]

конец диалога


В файлах эта структура записывается следующим образом:

<dialog id="escape_trader_letat_gusi">
    <phrase_list>
 
        <phrase id="0">
                <text>Так, чего хотел-то?</text>
                <next>1</next>
        </phrase>
 
        <phrase id="1">
                <text>Задание для тебя есть. Возьмешься?</text>
                <next>21</next>
                <next>22</next>
        </phrase>
 
        <phrase id="21">
                <text>Ну, давай.</text>
                <next>3</next>
        </phrase>
 
        <phrase id="22">
                <text>Не, иди к черту.</text>
                <action>dialogs.break_dialog</action>
        </phrase>
 
          [...]
 
    </phrase_list>
</dialog>

Разберемся подробнее.

Во-первых, принадлежность фраз. Они могут принадлежать или игроку, или NPC, причем:

  • фраза, принадлежащая игроку, всегда идет первой, а за ней уже по древу диалога игра понимает, чья фраза кому принадлежит (например, у нас 0, 21, 22 - игрока; а 1, 3 - NPC)
  • только у фразы, принадлежащей NPC, можно выбрать несколько вариантов ответа игрока

Впрочем, и у фразы игрока можно сделать несколько вариантов ответов, но поскольку компьютер не обладает способностью самостоятельно выбирать, то каждый из вариантов должен быть заранее определен по условиям выбора (например, по наличию у игрока какого-нибудь предмета, или количества денег, или репутации и т.д.), причем условия выбора различных вариантов никогда не должны одновременно становиться подходящими. Это мы разберем позднее.

Во-вторых, структура фразы. Простейшая фраза выглядит так:

<phrase id="0">    -- открывающий тег с ID фразы
                <text>Привет.</text>    -- текст фразы
                <next>1</next>    -- ссылка на следующую фразу
        </phrase>    -- закрытие тега фразы

Но есть возможность строить и такие фразы (в данном случае она принадлежит NPC, а игрок на неё будет давать ответ):

<phrase id="1">
                <give_info>propusk_given</give_info> -- выдача инфопорции (см. объяснение №1 ниже)
                <text>Вот, держи пропуск. Теперь тебе охранник позволит войти.</text>
                <action>dialogs.give_propusk_item</action> -- ссылка на скрипт (см. объяснение №2 ниже)
                <next>21</next>
                <next>22</next>
                <next>23</next>
        </phrase>
  • 1. Здесь у нас выдается инфопорция, которая может потом использоваться в различных местах (например, её наличие может проверяться каким-нибудь охранником - и если она есть, то он, скажем, отойдет и пропустит игрока внутрь). Важно понимать отличие инфопорции от предмета. Инфопорция - это факт наличия пропуска, а лежащий в инвентаре пропуск - материальный предмет. Можно, кстати, обойтись и без инфопорций, впоследствии пользуясь скриптами, проверяющими инвентарь игрока и ищущими нужный предмет, но этот способ сложен и нам пока не понадобится.
  • 2. Это скрипт, выдающий игроку предмет "пропуск" в инвентарь. Ссылка на скрипты дается в формате имя_файла.имя_функции.

Как видите, фраза, в которой некий NPC выдает игроку пропуск, позволяющий пройти дальше, достаточно сложна.

Вот еще один пример (здесь она принадлежит игроку):

<phrase id="4">
                <has_info>propusk_given</has_info> -- проверка на наличие инфопорции propusk_given
                <text>Да, пропуск у меня есть.</text>
                <action>dialogs.break_dialog</action> -- ссылка на скрипт, завершающий диалог
            </phrase>

Здесь у нас фраза из диалога игрока с NPC - та, что после вопроса NPC "А пропуск у тебя есть?". Это один из вариантов ответа на неё. Особенность в том, что этот вариант не появится, если пропуска у вас на самом деле нет - она появляется только при наличии нужной инфопорции (за это отвечает строка с <has_info>).

Далее, поподробнее остановимся на задании условий появления фразы.
Способов это сделать - два.

   * проверка на наличие инфопорций
   * проверка через скриптовую функцию

Первый метод мы видели выше, а второй - гораздо более комплексный и многофункциональный. Он запускает скрипт, который проводит проверку определенных вещей, и возвращает true/false. Простой пример - NPC требует денег (скажем, 5000 рублей), а нам нужно, чтобы ответная фраза игрока "Вот, держи свои 5000.", могла быть доступна для выбора, только если у нас действительно есть эти деньги. Для этого пишем такую фразу:

<phrase id="8">
                <text>Вот, держи, ровно 5000.</text>
                <precondition>dialogs.actor_have_5000</precondition> -- вызываем условие (см. объяснение №1 ниже)
                <action>dialogs.transfer_5000</action> -- передача денег скриптом (см. объяснение №2 ниже)
                <next>9</next>
            </phrase>
  • 1. Этот скрипт который проверяет наличие денег: если было возвращено true, то фраза доступна.
  • 2. Вызываем другой скрипт, действие - он осуществляет саму передачу денег.

Да, кстати, порядок расстановки тегов внутри фразы не играет никакой роли - они все выполняются одновременно. Единственное - <next> всегда последний. Еще одно - есть второй вид проверки на инфопорцию - он наоборот, проверяет её отсутствие. Применяется точно так же, но называется не has_info, а dont_has_info.

Итак, что у нас есть:

  • <phrase id="..."></phrase> - общий тег фразы, задание номера фразы
  • <text>...</text> - тег, содержащий текст фразы
  • <give_info>...</give_info> - выдача инфопорции с именем, записанным в теге
  • <has_info>...</has_info> - проверка на наличие инфопорции с именем, записанным в теге
  • <dont_has_info>...</dont_has_info> - проверка на отсутствие инфопорции с именем, записанным в теге
  • <precondition>...</precondition> - запуск скрипта, возвращающего true или false в зависимости от чего-либо (скриптовая проверка)
  • <action>...</action> - запуск скрипта
  • <next>...</next> - тег ссылки на следующую фразу


В первой версии - достаточно просто окна с формами для ввода этих параметров. А программа на основе введенных данных будет собирать фразу. Например, на основе вот таких введенных в поля данных:

Номер фразы: 12

Текст: Да, там сейчас база военных.
Я не в курсе, сколько их там точно, но
могу сказать, не меньше, чем один два отряда.


Выдать инфопорцию: info_about_military_base

Проверить наличие инфопорции: info_1
Проверить отсутствие инфопорции: нет
Проверить через скрипт: dialogs.is_npc_a_friend
Совершить действие: dialogs.break_dialog

Номера следующих фраз: 13

Нам нужна вот такая запись:

<phrase id="12">
                <has_info>info_1</has_info>
                <text>Да, там сейчас база военных. Я не в курсе, сколько их там точно [...]</text>
                <precondition>dialogs.is_npc_a_friend</precondition>
                <action>dialogs.break_dialog</action>
                <give_info>info_about_military_base</give_info>
                <next>13</next>
            </phrase>


Текстовые (строковые) массивы

Мы упустили один важный нюанс, критичный для крупных диалогов.

<phrase id="54">
                <text>Здравствуй, сталкер. Чем я могу помочь тебе?</text>
                <next>55</next>
            </phrase>

Мы записывали текст фразы в <text>...</text>. Это, безусловно, удобно, но на самом деле - может привести к проблемам. Дело в том, что таким образом можно использовать только короткие фразы. Стоит ввести в тег длинный текст, и игра... так сказать, не переварит наш диалог.

Поэтому нужно использовать не тексты, а ссылки на них. Работает это так:

Изображение:Text massive explain.jpg

То есть фразу мы записываем так:

<phrase id="54">
                <text>my_text_1</text>
                <next>55</next>
            </phrase>

А в игре видим нормальный текст - игра по названию my_text_1 находит его в массиве.
Массивы (для русскоязычной версии игры) находятся в папке:

S.T.A.L.K.E.R\gamedata\config\text\rus

Нужные вам тексты фраз вы можете прописывать в любом из находящихся там .xml-файлов, их разделение на специализации - чисто формальное. Лучше всего держать тексты всех ваших диалогов в одном месте, поэтому выберите один файл - этим вы упростите работу тем, кто будет скрещивать ваш мод с другими.

Запись текста происходит в такой форме:

<string id="my_text_1"> -- в заголовке указывается имя текста, которое вызывается из диалога
		<text>Здравствуй, сталкер. Чем я могу помочь тебе?</text> -- собственно, сам текст
	</string>

Диалоги

Дополнительные сведения по диалогам

Скрипт-генерируемые диалоги

Личные инструменты