Авторы: DA TOOLSET WIKI
Перевод: Kelamor Plot – система логических (True/False) флагов, с помощью которых игра отслеживает состояние мира. Обычно они используются, чтобы управлять беседами и журналом игрока. Также с их помощью удобно запускать скрипты(scripts) на выполнение.
Записи в журнале
Когда в тулсете вы открываете Plot-файл, вы можете увидеть поле под названием «Текст журнала» (Journal Text) ниже поля с флагами. Журнальная запись создаётся, когда вы вводите в это поле текст, предварительно выбрав флаг, с которым эта запись ассоциируется.
Для примера, если вы хотите создать журнальную запись для флага ‘’’JOURNAL_TEST’’’ в Plot-файле ‘’’test_journal.plo’’’, тогда вам надо сделать чекаут для указанного Plot-файла, выбрать ‘’’JOURNAL_TEST’’’, и ввести ваш текст в поле «Текст журнала».
Каждый Plot-файл имеет одну-единственную тему для журнала, таким образом, все флаги изменяющие эту тему (скажем, "Золотой цыплёнок") должны быть перечислены в том же Plot-файле (скажем, "test_chicken"). Название темы журнала вы можете указать в поле "Name" в окне «Object Inspector» когда Plot-файл открыт.
Для примера, тема «Золотой цыплёнок» включает четыре части:
* QUEST_GIVEN: Отыщите, где последний раз видели цыплёнка.
* RESEARCH_DONE: Вы узнали, где последний раз видели цыплёнка: Музей птицеводства. Поговорите со смотрителем, может он знает что-нибудь о том, где сейчас золотой цыплёнок. *CURATOR_MET: Вы поговорили со смотрителем Музея птицеводства. Она оказалась разговорчивой и вы кое-что узнали. Найти золотого цыплёнка вы сможете в Подземелье вечной скорби. *CHICKEN_FOUND: Удивительно, но вы сумели найти золотого цыплёнка.
Так как все флаги находятся в одном Plot-файле, то каждый раз, когда устанавливается флаг, принадлежащая ему журнальная запись заменяет предыдущую запись в этой теме.
В журнале отображается только запись, установленная последней, однако все ранее установленные флаги не сбрасываются автоматически. Для примера, когда устанавливается ‘’’RESEARCH_DONE’’’, ‘’’QUEST_GIVEN’’’ также остаётся установленным. Конечно, в случае необходимости вы можете сбросить его самостоятельно.
Если вы хотите пошагово указывать события в журнале, то вы можете использовать подчинённые Plot-файлы(Subplot-файлы). Так, если задание отыскать, где последний раз видели золотого цыплёнка, содержит несколько шагов (посетить и исследовать несколько мест), вы можете создать несколько маленьких Plot-файлов и организовать нужные флаги в их пределах.
Для примера, если основной Plot-файл задания «Золотой цыплёнок» содержит подчинённые Plot-файлы "Исследовать пещеры", "Поговорить с профессором" и "Найти книгу поиска", тогда вы должны создать Subplot-файлы с именами " Золотой цыплёнок: Исследовать пещеры" и так далее.
Если вы хотите чтобы текст, установленный предыдущим флагом, не затирался, то вы также можете вставить первичный текст в запись журнала устанавливаемого флага.
Для количества флагов в Plot-файле установлено ограничение в 256. 128 из них могут быть стандартными (main) флагами и 128 – определяемыми (defined), которые определяются скриптами каждый раз, когда прочитываются.
Для написания курсивом или полужирным шрифтом, в поле «Текст журнала» можно использовать тэги ( and ) и ( and ) соответственно.
Если у флага столбец "Final" установлен как "Yes" тема журнала перемещается на вкладку завершённых заданий.
Кодекс
Записи кодекса являются специальным типом Plot-файлов, в которых содержится основная информация о мире.
Просто создайте новый Plot-файл, в окне «Object Inspector» для поля ‘’’Entry Type’’’ укажите требуемый вам тип кодекса. Это автоматически создаст новую чистую ячейку кодекса в игре.
Удалить ячейки кодекса, принадлежащие основной компании невозможно, так как Plot-файлы, связанные с ними – основные ресурсы игры. Однако при создании отдельного мода они останутся чистыми и не будут заполняться.
Записи кодекса о существах будут добавляться при первом его убийстве. Используемые в этом случае Plot-файлы и флаги определены в столбцах ‘’’CodexPlot’’’ и ‘’’CodexFlag’’’ (столбцы CT и CU) 2DA-файла ‘’’APR_base’’’. Таким образом, в случае необходимости вы можете, создав новый Plot-файл сделать его записи описанием для существующих либо добавленных вами существ.
Для появления в кодексе записи об размещённом объекте (Placeable) нужно просто установить переменные ‘’’PLC_CODEX_PLOT’’’ и ‘’’PLC_CODEX_FLAG’’’, и ячейка кодекса заполнится при использовании объекта.
Повествование
Для использования Plot-файла в качестве коротких выдержек из истории, появляющихся при загрузке ранее сохранённой игры, то в поле ‘’’Entry Type’’’ Plot-файла необходимо выбрать ‘’’Story Plot’’’.
Подсказки
Подсказки, появляющихся при переходах между областями не являются флагами Plot-файлов и загружаются наугад из 2DA-файла ‘’’loadhints’’’.
Чтобы исключить подсказки, связанные с Ферелденом, необходимо удалить из этого файла все записи, именуемые ‘’’Flavor’’’.
Скрипты
Для работы с Plot-файлами из скрипта необходимо включить Plot-файл в скрипт с помощью инструкции ‘’’#include’’’ с префиксом ‘’’plt_’’’. Для примера, если Plot-файл называется "kill_all_wolves", добавьте в начало вашего скрипта, который должен считывать и устанавливать флаги в указанном Plot-файле, следующий текст:
Code
#include "plt_kill_all_wolves"
Считывать и устанавливать значения флагов можно посредством функций из скрипта ‘’’wrappers_h’’’ (включите в скрипте доступ к "wrappers_h") используя имена Plot-файла и флага как констант, к примеру:
Code
#include "plt_kill_all_wolves"
#include "wrappers_h"
void main()
{
int flag_value = WR_GetPlotFlag(PLT_KILL_ALL_WOLVES, FLAG_NAME); //Считываем
WR_SetPlotFlag(PLT_KILL_ALL_WOLVES, FLAG_NAME, TRUE); //Устанавливаем
}
Скрипты событий Plot-файла
Многие задачи в Dragon Age решаются посредством скриптов, обрабатывающих события Plot-файлов и срабатывающих, когда у флага устанавливается новое значение. Способность флага хранить значения Истина/Ложь позволяет запускать события, которые должны произойти только один раз за игру, не обращаясь к локальным переменным, но необходимо заметить, что скрипт запускается каждый раз, когда устанавливается значение флага, независимо от того, меняется ли оно.
В отличие от других скриптов, обрабатывающих события, скрипт Plot-файла начинается с функции ‘’’int StartingConditional()’’’, которая и вызывается, когда флаг читается или устанавливается. Это и позволяет считывать значение флага (integer true/false), что очень важно, когда вы работаете с «определяемыми» флагами.
EVENT_TYPE_SET_PLOT посылается, каждый раз когда устанавливается значение нормального флага, название флага хранится в свойстве ‘’’1’’’ события. Заметьте, что скрипт вызывается до того, как значение флага будет установлено; значение флага не изменится, пока не будет закончено выполнение скрипта.
EVENT_TYPE_GET_PLOT посылается, когда «определяемый» флаг считывается. Функция ‘’’StartingConditional()’’’ скрипта Plot-файла возвращает значение «определяемого» флага.
Для использования скриптов события Plot-файла:
* создайте скрипт, к примеру, "kill_all_wolves.ncs"
* в окне ‘’’object inspector’’’ установите ваш скрипт (по умолчанию установлен plot_core)
* установите или считайте флаг, устанавливая последний параметр (nCallScript) в ‘’’TRUE’’’ (смотрите WR_GetPlotFlag и WR_SetPlotFlag)
Помните, что скрипт запускается каждый раз, когда флаг считывается или устанавливается.
Если вы хотите установить значение флага и запустить скрипт, то примените следующую конструкцию:
Code
WR_SetPlotFlag(PLT_KILL_ALL_WOLVES, FLAG_NAME, flag_value, TRUE);
Важно: Последний параметр должен быть TRUE. Этот параметр должен устанавливаться в TRUE каждый раз, когда вы хотите запустить скрипт Plot-файла.
Маркеры
У многих НПС, дающих задания в основной компании, над головой висит знак «!». Также на картах им отмечаются расположение таких НПС. Есть два пути для реализации этого, можно отредактировать свойство ‘’’Plot Giver’’’ существа или использовать следующую функцию в скрипте:
Code
SetPlotGiver(oObject, TRUE);
Когда задание будет взято, вам надо будет убрать восклицательный знак с головы НПС и с карты мира. Это может быть сделано используя скрипт событий Plot-файла, а именно, установка значения флага, о том, что задание взято, запускает скрипт, который должен содержать следующую функцию:
Code
SetPlotGiver(oObject, FALSE);
Для того, чтобы показать промежуточный маркер (стрелка, направленная вниз), вам необходимо отредактировать сам Plot-файл. Для этого вы должны указать тэг существа или размещённого объекта в таблице ‘’’Plot assist’’’ (снизу от флагов) отдельно для каждого флага и указать, отключается или отключается маркер (Значение Yes или No).
Порядок установки флагов
Порядок не имеет значения для стандартных Plot-Файлов, чего не скажешь о Plot-файлах кодекса.
Для стандартных Plot-файлов, какой бы флаг не был установлен последним, в журнале показывается только его значение, если для него указана заметка журнала. Если я не ошибаюсь, то после завершения задания установка дополнительных финальных флагов (имеющих признак final) текст журнала обновляться не будет.
Для Plot-файлов кодекса все активные (True) флаги отображаются в порядке от меньшего к большему. Это используется в случаях, когда записи о чём-либо имеют несколько вариантов, которые зависят от значений флагов Plot-файла.
Для примера:
0: Сладкий монстр – пожиратель печенюшек.
1: Сладкий монстр был пожирателем печенюшек.
2: Он угрожал разрушить королевство.
3: ловко уничтожил его.
4: Но купился на его сладкие печеньки.
5: Но Большая птица сделала его хорошим.
0-й флаг ставится в TRUE изначально и устанавливается в FALSE (с одновременной установкой 1-го флага в TRUE) если монстр умер.
2-й флаг всегда должен быть TRUE
Только один из 3-го,4-го или 5-го флагов может быть TRUE, в зависимости от развития событий (убил печенькового монстра, был им подкуплен или проигнорировал его). Если игрок ещё не столкнулся с ним, эти флаги будут FALSE.
Награды
Каждому флагу можно установить награду, которая будет выдаваться игроку после установки флага и которая выбирается из списка (смотрите rewards.xls и 2DA).
При желании вы можете создать rewards.GDA со своими наградами и поместить его в папке вашего модуля, награды, перечисленные в нём, будут доступны для выбора в тулсете после перезагрузки. Если вы создаёте новую компанию, вы можете полностью переделать rewards.xls, в противном случае просто расширить M2DA.
Это простой и удобный способ выдачи игроку экспы, денег, вещей или комбинаций из них.
Подчинённые и главные Plot-файлы
Иногда у Plot-файлов есть несколько подчинённых Plot-файлов, которые могут запускаться в любом порядке.
Для примера, "Найдите лимон и утку, затем на кухне сварите суп ".
Мы должны обновить журнал, когда будет найден первый ингредиент, утка или лимон.
Достаточно просто это сделать посредством трёх Plot-файлов: главный ("Суп") и два подчинённых ("Лимон" и "Утка"). Отношения «Главный-Подчинённый» достаточно просто установить в свойствах подчинённого Plot-файла (свойство «Parent plot»).
Данные отношения имеют значение только для журнала – флаги для родительских или подчинённых Plot-файлов вы устанавливаете независимо.
Теперь остался вопрос, как синхронизировать их, так, в нашем примере может оказаться что в родительском Plot-файле запись «Мне надо найти утку и лимон, затем сварить суп" будет оставаться и после того, как будет найден один из ингредиентов или оба и в подчинённом Plot-файле появится запись «Я нашёл Х» до того как суп будет реально изготовлен.
В этом случае достаточно сделать определяемый флаг в родительском Plot-файле, который будет проверять, найдены ли ингредиенты, когда мы попытаемся сварить суп. Включите в скрипт Plot-файла в секцию для событий определяемых флагов следующий текст:
Code
event eParms = GetCurrentEvent();
int nFlag = GetEventInteger(eParms, 1); // Plot-флаг
int nValue = GetEventInteger(eParms, 2); // 0=Clear 1=Set
int nResult = FALSE;
/* в секции для определяемых флагов */
switch(nFlag)
{
case DEFINED_SOUP_INGREDIENTS_FOUND:
{
nResult = (WR_GetPlotFlag(PLT_LEMON, LEMON_FOUND) && WR_GetPlotFlag(PLT_DUCK, DUCK_FOUND))
break;
}
}
plot_OutputDefinedFlag(eParms, nResult);
return nResult;
Однако если вам необходимо обновить главный журнал, когда оба подчинённых заданий выполнены ("Я нашёл лимон и утку, теперь мне надо пойти на кухню и сварить суп "), есть один важный нюанс – когда устанавливается Plot-флаг, его скрипт вызывается до того, как флаг получает новое значение.
Так, в скрипте Plot-файла "lemon", должно быть примерно следующее:
Code
event eParms = GetCurrentEvent();
int nFlag = GetEventInteger(eParms, 1); // Plot-флаг
int nValue = GetEventInteger(eParms, 2); // 0=Clear 1=Set
switch(nFlag)
{
case LEMON_FOUND:
{
if (nValue)
{
if (WR_GetPlotFlag(PLT_DUCK, DUCK_FOUND))
WR_SetPlotFlag(PLT_SOUP, SOUP_INGREDIENTS_FOUND, 1, TRUE);
}
break;
}
}
‘’’Важно:’’’Проверяя же, что оба флага установлены, вы потерпите неудачу, так как значение флага устанавливается после того, как скрипт его Plot-файла выполнится.
Конечно, если вы используете вещи, вам могут понадобиться иные способы проверки для синхронизации журнала (например, выдать запись о том, что у вас теперь есть ключ от кухни).
Свойства
General
Allow Pausing
Entry Type
GUID Уникальный внутриигровой идентификатор для Plot-файла.
Journal Image Картинка для темы журнала этого Plot-файла (опционально).
Name Имя Plot-файла, будет отображаться как название темы в журнале.
NameRequiresReTranslation Истина/Ложь – используется для указания, что данная строка требует локализации.
Parent Plot Указание на главный, по отношению к текущему, Plot-файл.
Priority Приоритет, указывается в целях сортировки в журнале.
Resource Name Уникальный строковый идентификатор для тулсета и игры, используемый для ссылки на этот ресурс.
Script Скрипт событий, ассоциированный с текущим Plot-файлом.