Backgrounds tutorial/ru

From Dragon Age Toolset Wiki
Jump to: navigation, search
Инструкция по созданию предыстории
Начало / Русская DA Builder Wiki / Поделиться ВКонтакте

Вступление

В этом туториале мы расскажем вам, как можно редактировать предыстории, которые мы можем видим во время создания героя. Это пригодиться вам в создании вашей собственной кампании. Добавлять новые предыстории к оригиналу нельзя, можно лишь отредактировать или полностью заменить существующие. В данном туториале мы будем создавать отдельный модуль, который будет полностью заменять все предыстории. Изменение предысторий полезно в случае:

1 – если сюжет вашей кампании разворачивается не в мире Dragon age;

2 – если вы хотите уменьшить количество существующих предысторий.


Также мы расскажем вам об основных принципах редактирования игровых ресурсов, которые влияют на доступность расы и классов. Что самое важное: мы не будем редактировать подлинные материалы, а будем работать с копиями. Это позволит нашим изменениям быть совместимыми с будущими патчами, которые в ином случае перезапишут нашу работу.


Для прохождения данного туториала читателям рекомендуется быть ознакомленными с основами скриптинга и программирования. В ином случае удачное прохождение маловероятно. Чем больше вы будете слепо копировать код, используемый в туториале, тем выше вероятность того, что возникнут ошибки, которые вы будете не в силах исправить.

Демо модуль для предысторий

Для данного туториала подойдет любой модуль. Если вы хотите создать отдельный тестовый модуль специально для прохождения туториала, просто создайте модуль с одной локацией и начальной территорией. Убедитесь, что единственным выбранным пунктом в иерархии модуля является Core game resources(Базовые игровые ресурсы). Это будет означать, что модуль отдельный и что он не вносит никаких изменений в оригинальную кампанию или в другие модули. Давайте назовем наш модуль Backgrounds demo и будем добавлять к названиям наших файлов префикс bdm_, чтобы быть уверенными, что файла с таким названием больше нет. Мы заменим существующие предыстории тремя собственными. Вы можете использовать их как угодно. Можете написать отдельный сюжет для каждой предыстории, как это сделано в оригинале (важно, чтобы длинна сюжетов были одинакова). Или же ваша предыстория может влиять только на диалоги, plot-опции и основную часть вашей игры. Для нашей демки мы создадим модуль, сюжет которого начинается в маленькой человеческой деревушке (это поможет нам придумать предыстории, на практике мы создавать деревню не будем). В деревне есть маг, который играет в сюжете важную роль. Мы позволим игроку начать игру в качестве ученика этого мага (если игрок - маг), его слуги (если игрок человек или эльф и при этом не маг) или путешественника, который пришел навестить мага (если игрок не человек и не маг). Таким образом, у нас получилось три предыстории:

  • Слуга
  • Ученик
  • Путешественник

Создание string-переменных для предыстории

Перед тем, как мы приступим к редактированию файлов 2DA, нужно создать несколько переменных типа string. Откройте string-редактор в тулсете и создайте таблицу с названием “Background Demo”. В ней создайте следующие переменные:

Back tut talk table.png

ID-номера ваших строчек могут быть другими. Это не страшно, просто в дальнейшем вам придется заменять указанные мною ID на свои.

ВАЖНО! В игре присутствует баг, который не позволяет ID-номеру принимать значения выше 109 912 680. Чтобы исправить его, вы можете скачать фикс от сообщества. Или же вы можете зайти в свойства модуля и изменить начальное значение ID так, чтобы оно было меньше критического. После этого, string-редактор будет генерировать ID-номера, значения которых не приведут к багу. После создания переменных для предысторий, перезагрузите начальное значение ID-номера (это позволит вам избежать нужды в скачивании фикса от Bioware и уменьшит возможность несовместимости с другими модулями).

Вы, должно быть, заметили, что мы задали разные названия и описания предыстории путешественника в зависимости от расы героя. Об этом мы расскажем вам дальше.

Arrowblue.png - String editor

Редактирование 2DA-файлов

Следующим шагом будет редактирование рабочих листов документа под названием backgrounds.xls. Скопируйте этот документ: мы будем редактировать копию, а не оригинал. Рекомендую вам прочесть статью с описанием работы с 2DA-файлами. Первый лист называется “background”. Отредактируйте его так, чтобы у вас получилось как на скриншоте:

Back tut backgrounds.png

2DA-файлы соединяются и создают M2DA-файлы, которые заменяют оригиналы с аналогичными названиями. В этом случае нам надо будет заполнить неиспользуемые слоты, чтобы в модуле не было предысторий из оригинала. Поэтому два последних слота мы назвали unused1 и unused2. Названия и описания предысторий в зависимости от выбранной расы будут взяты с таблицы string-переменных, так что здесь мы можем оставить соответствующие поля пустыми(если в таблице string-переменных указаны названия и описания предысторий, столбцы NameStrRef и DesStrRef не используются. Похоже, что ToolTipStrRef также нигде не используется. Если хотите, можете его чем-то заполнить).

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

Последние три колонки определяют стартовый навык для каждой предыстории и расы. Заметьте, по умолчанию эти колонки не связаны со скриптом генерации персонажа (они содержатся в сложном блоке кода) и не используются, но мы исправим это на стадии скриптинга. Вы должны быть внимательными, так как каждая колонка связана с ID-номером расы:

1 – гном, 2 – эльф, 3 – человек.

Номера могут быть размещены в другом порядке по отношению к столбцам расы данной таблицы. Номером в колонке является значение ID-номера навыка, указанное в таблице ABI_base.xls. В этой демке мы просто зададим одинаковые навыки всем расам определенных предысторий. Слуги получат бонус к тактике боя, ученики – бонус к убеждению, а путешественники - к выживанию.

Далее мы отредактируем таблицу под названием background_names.

Back tut bg names.png

Убедитесь, что ID-номера этой таблицы совпадают с ID-номерами ваших string-переменных. Обратите внимание, что для учеников и слуг вне зависимости от расы мы используем одинаковые переменные, а для путешественников разные строчки. Это чтобы вы увидели, как одной и той же предыстории можно присваивать разные имена и описания. Все они хранятся в одном и том же ID-номере предыстории, но во время генерации персонажа игрок может увидеть разные названия, описания и иконки для одной и той же предыстории. В оригинальной кампании этот метод применялся в случае героем знатного происхождения, которое менялось на человеческое или гномье в зависимости от выбранной расы.

ПРИМЕЧАНИЕ – во время разделения единой предыстории на части вы должны быть внимательными. Названия и описания должны быть разными! Если описания будут одинаковыми, движок сочтет предыстории идентичными, даже если их названия будут разными.

Теперь отредактируйте background_desc как показано на скрине.

Back tut bg desc.png

Снова обратите внимания на различные описания для предыстории путешественника. Теперь отредактируем background_icons. В этой демке мы будем использовать иконки из оригинала, но при желании вы можете использовать собственные. “background_icons"

Back tut bg icons.png

Таблица под названием background_defaults должна содержать все возможные комбинации расы, предыстории и класса. Значение ID-номера колонки считается следующим образом: (1000 * IDрасы) + (100 * IDкласса) + Idпредыстории

Back tute bg defaults.png

В колонке “Label” должна содержаться комбинация (правда, это ни на что не влияет). В нашей демке место появления героя всех комбинации будет одинаковым (локация, выбранная в модуле по умолчанию) но если вы хотите создать индивидуальное начало для каждой предыстории, вы можете использовать для этого две следующие колонки (чтобы это сработало, нужно написать скрипт). В колонке “Template” вы можете вписать название файла с существом, которое вы хотите использовать в качестве шаблона для определенной комбинации расы\предыстории\класса. На скриншоте вы можете увидеть, что мы используем стандартные шаблоны, идущие в комплекте с тулсетом, но вы запросто можете пользоваться своими. Заметьте, что от шаблона герой получает только инвентарь, так что для шаблонных персонажей вам не нужно задавать ничего кроме инвентаря.

Имя берется со string-переменных, так что если вы хотите задать герою новое имя, вам придется создать новые переменные в string-редакторе. В конце мы видим столбец с возможностями. Как и в случае с навыками в таблице предыстории, ID-номера возможностей соответствуют записям в файле ABI_base.xls. Раса, класс и предыстория являются единственными источниками стартовых возможностей. Поэтому перед тем, как вписывать в столбец ID-номер возможности, вам следует узнать, какие возможности уже добавлены. Это поможет избежать дубликатов. Последняя таблица называется chargen_preload. Два столбца этой таблицы должны точно совпадать со значениями ID-номеров и шаблонов из предыдущей.

Back tut chargen preload.png

Arrowblue.png - 2DA
- 2DA#Excel file formatting
- Background.xls

Компиляция и исправления файлов GDA

Теперь скомпилируйте файл backgrounds.xls и положите полученный в результате компиляции GDA-файл в папку AddIns\название_модуля\module\override Никогда не кладите ничего в папке AddIns\название_модуля\core\override иначе изменения коснуться всех модулей. Раньше был баг, из-за которого string-переменный с большими ID-значениями компилировались некорректно. Сейчас он исправлен. Чтобы обойти этот баг, GDA-файлы вручную редактировались в тулсете. Если же вы взглянете на ID-номера сейчас, то увидите, что они правильные.

Arrowblue.png - Compiling 2DAs
- GDA

Создание plot-файла для предыстории

Plot-файл предыстории используется для отслеживания выбранной игроком предыстории и позволяет менять диалоги в зависимости от выбора. Оригинальная кампания для отслеживания выбранной предыстории использует plot-файл под названием gen00pt_backgrounds. Вы можете найти его в папке \_Global\Generic в разделе “Plots”. Мы создадим похожий файл для наших предысторий. Создайте новый plot и назовите его bdm_000pt_backgrounds (я использую три нуля для обозначения файлов, не привязанных к конкретной локации, вы можете использовать собственное обозначение, только не забудьте о нем в процессе прохождения туториала). Добавьте главные plot-флаги, как это изображено на скриншоте.

Back tut bg plot.png

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

Arrowblue.png - Designer Resources
- Plot

Написание скриптов

Мы не будем редактировать скрипты оригинальной кампании, мы добавим свои. Для лучшего понимания того, что мы будем делать, вы можете ознакомиться со скриптами оригинала, но ни в коем случае не редактируйте их. Используя в своем модуле измененные скрипты оригинала, вы делаете ваш модуль несовместимым с возможными будущими патчами. Начнем с написания скрипта, обрабатывающего события генерации персонажа. Обычно, этот скрипт назначается модуль-скриптом. Создайте новый скрипт и назовите его bdm_module_core. Вы должны решить, какубю структуру папок использовать для распределения ваших скриптов. Советую помещать их в папке с названием модуля: это позволит отделить их от скриптов оригинала. Если вам нравится оригинальная структура, вы сможете воссоздать ее в папке скриптов вашего модуля. Модуль-скрипт оригинальной кампании называется module_core и лежит в папке \_Core Scripts. А наш модуль-скрипт под названием bdm_module_core мы положим в папку \Backgrounds demo\_Core Scripts (знак нижнего подчеркивания вынесет вашу папку в самый верх списка. Похоже, Bioware случайно создали одну папку без знака подчеркивания. Думаю, _Core и Core - одна и та же дирректория). Структуризация скриптов подобным образом упростит вашу работу.


Откройте ваш bdm_module_core и напишите в нем следующее:

#include "global_objects_h"
void main(){
    event ev = GetCurrentEvent();
    int nEvent = GetEventType(ev); //извлечение с текущего события его типа
    int nEventHandled = FALSE; //флаг, следящий за тем, было ли обработано события или нет.
    switch(nEvent){
        case EVENT_TYPE_MODULE_START:{
            // -----------------------------------------------------------------
            // Initiate character generation.
            // -----------------------------------------------------------------
            PreloadCharGen(); //предварительна загрузка ресурсов для генерации персонажа
            StartCharGen(GetHero(),0,TRUE); //начало генерации
            break;
        }
        default:
        {
            // -----------------------------------------------------------------
            // Обработка отправленных движков события генерации персонажа.
            // -----------------------------------------------------------------
            if ((nEvent >= EVENT_TYPE_CHARGEN_START && nEvent <= EVENT_TYPE_CHARGEN_END) 
                || nEvent == EVENT_TYPE_PLAYERLEVELUP )
            {
                HandleEvent(ev, R"bdm_sys_chargen.ncs");
                nEventHandled = TRUE;
            }
            break;
        }
 
    }
    if (!nEventHandled) { //если событие не было обработано, оно отправляется в core-скрипт
        HandleEvent(ev, RESOURCE_SCRIPT_MODULE_CORE);
    }
}

Теперь жмите File -> Manage modules -> кнопка Properties. Установите только что написанный скрипт в качестве модуль-скрипта(module script) Теперь наш новый скрипт выполняет функцию модуль-скрипта. Посла обработки события, наш модуль-скрипт решает, нужно ли отправлять событие в module_core для дальнейшей обработки. Первое описанное нами событие носит название EVENT_TYPE_MODULE_START и отвечает за начало процесса генерации персонажа. В этом случае после начала генерации, событие передается в module_core, где собственно и происходит сам процесс генерации.

ПРИМЕЧАНИЕ: код из других секций скрипта не нуждается в редактировании. Вообще не понятно, за что он отвечает.

Дальше мы займемся целой группой событий. Если вы заглянете в нижнюю часть module_core-скрипта, то увидите, что часть написанного там за исключением некоторых деталей совпадает с нашим кодом, отвечающим за обработку событий. Вместо того, чтобы пропустить наши события, генерирующие персонажа через sys_chargen.nc, мы пропустим их через наш собственный скрипт под названием bdm_sys_chargen.ncs, который мы вскоре напишем. Если нам попадется одно из событий, генерирующих персонажа, мы должны обработать его сами и освободить от этого core-скрипт, поэтому мы установим флагу nEventHandled значение TRUE(истина): nEventHandled = TRUE; Заметьте, что все другие события обрабатываться нашим модуль-скриптом не будут, они сразу же направятся к core-скрипту. Перед созданием bdm_sys_chargen скрипта нам понадобятся несколько новых констант. В папке \Backgrounds demo\_Core Includes создайте новый скрипт с названием bdm_2da_constants_h. Откройте его и напишите внутри следующее:

// -----------------------------------------------------------------------------
// Backgrounds - rules/backgrounds.xls
// -----------------------------------------------------------------------------
const int BACKGROUND_SERVANT = 1;
const int BACKGROUND_APPRENTICE = 2;
const int BACKGROUND_TRAVELLER = 3;

Три константные переменные позволяют нам сослаться на второстепенные параметры персонажа, которые мы указали в 2DA-файлах, без использования их ID-номеров. Подобные константы также делаю ваш код более читабельным. Если во время редактирования вам нужно добавить новые параметры в 2DA-файлы, вы можете также создать для них переменные в этом скрипте(bdm_2da_constants_h). С этого момента, вместо оригинальных констант(которые вы можете увидеть в скрипте под названием 2da_constants_h) мы будем использовать собственные. Это значит, что мы должны найти все участки, где используются эти оригинальные переменные и заменить их своими. В папке \Backgrounds demo\_Systems создайте новый скрипт с названием bdm_sys_chargen и напишите в нем:

#include "bdm_sys_chargen_h"
#include "log_h"
 
const int CHARGEN_QUICKSTART_QUICK = 0;
const int CHARGEN_QUICKSTART_NORMAL = 1;
const int CHARGEN_QUICKSTART_ADVANCED = 2;
 
void _RunChargen(int nRace, int nClass, object oChar, int nBackground)
{
 
    Chargen_InitializeCharacter(oChar);
    Chargen_SelectGender(oChar,GENDER_MALE);
    Chargen_SelectRace(oChar,nRace);
    Chargen_SelectCoreClass(oChar,nClass);
    Chargen_SelectBackground(oChar, nBackground,FALSE);
 
    int nEquipIdx = Chargen_GetEquipIndex(nRace, nClass, nBackground);
    Chargen_InitInventory(oChar,0,nEquipIdx);
    Chargen_SpendAttributePoints(oChar,PROPERTY_ATTRIBUTE_STRENGTH, 3,FALSE);
    Chargen_SpendAttributePoints(oChar,PROPERTY_ATTRIBUTE_DEXTERITY, 2,FALSE);
 
}
 
void main(){
    event   ev              =   GetCurrentEvent();
    int     nEventType      =   GetEventType(ev);
    object  oChar           =   GetEventObject(ev,0);
 
    int nMode;
    int nInt0 = GetEventInteger(ev,0);
    int nInt1 = GetEventInteger(ev,1);
    // -------------------------------------------------------------------------
    // Отладка.
    // -------------------------------------------------------------------------
    Log_Trace(LOG_CHANNEL_EVENTS_CHARGEN,"bdm_sys_chargen","Chargen Event:" + Log_GetEventNameById (nEventType) 
               + " " + ToString(nInt0) + "," + ToString(nInt1), oChar);
 
    int nEventHandled = FALSE;
 
    switch (nEventType)
    {
        // ----------------------------------------------------------------------
        // Срабатывает, когда игрок кликает по иконке одной из доступных
        // предысторий.
        //
        // nInt0 - Constant BACKGROUND_* integer
        // ----------------------------------------------------------------------
        case EVENT_TYPE_CHARGEN_SELECT_BACKGROUND: {
            int nBackground = nInt0;
            // -----------------------------------------------------------------
            // Выбор предыстории для игрока и установка соответствующих предыстории
            // plot-флагов.
            // -----------------------------------------------------------------
            Chargen_InitializeCharacter(oChar,TRUE);
            Chargen_SelectGender(oChar,GetCreatureGender(oChar));
            Chargen_SelectRace(oChar,GetCreatureRacialType(oChar));
            Chargen_SelectCoreClass(oChar,GetCreatureCoreClass(oChar));
 
            bdm_Chargen_SelectBackground(oChar, nBackground, FALSE);
            bdm_Chargen_SetupPlotFlags(oChar);
 
            // -----------------------------------------------------------------
            // Проверяет шаблоны, указанные в 2DA-файлах
            // и, руководствуясь ими создает герою инвентарь.
            // -----------------------------------------------------------------
            int nClass = GetCreatureCoreClass(oChar);
            int nRace = GetCreatureRacialType(oChar);
            int nEquipIdx = Chargen_GetEquipIndex(nRace, nClass, nBackground);
           Chargen_InitInventory(oChar,0,nEquipIdx);
            nEventHandled = TRUE;
            break;
        }
        case EVENT_TYPE_CHARGEN_END: {
            nMode = nInt0;
            int nQuickStart = nInt1;
            // 0 - quickstart
            // 1 - normal    \
            // 2 - advanced  / то же самое
            Log_Trace(LOG_CHANNEL_CHARACTER,"bdm_sys_chargen","MODE: " + IntToString(nMode) 
                       + ", Quick Start: " + IntToString(nQuickStart));
            if (nMode == CHARGEN_MODE_CREATE && nQuickStart == CHARGEN_QUICKSTART_QUICK){
                Log_Trace(LOG_CHANNEL_CHARACTER,"bdm_sys_chargen","Установка стандартный параметров для игрового персонажа.");
 
                    int nRandClass = abs((GetLowResTimer()%3)+1);
 
                    if(nRandClass == CLASS_ROGUE || nRandClass == CLASS_WARRIOR)
                    {
                        _RunChargen(RACE_HUMAN, nRandClass, oChar, BACKGROUND_SERVANT );
 
                        WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_SERVANT, TRUE);
                    }
                    else // mage
                    {
                        _RunChargen(RACE_HUMAN, nRandClass, oChar, BACKGROUND_APPRENTICE );
                        WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_APPRENTICE, TRUE);
                    }
                    Chargen_SetNumTactics(oChar);
                    SetCanLevelUp(oChar,Chargen_HasPointsToSpend(oChar));
                    SendEventModuleChargenDone("", "");
                    nEventHandled = TRUE;
            }
            break;
        }
    }    //end switch
 
    if (!nEventHandled){
        HandleEvent(ev, R"sys_chargen.ncs");
    }
 
 
}

В оригинальном sys_chargen скрипте есть два события, связанные с генерацией персонажа. Мы должны их отредактировать. Первое называется EVENT_TYPE_CHARGEN_SELECT_BACKGROUND, второе - EVENT_TYPE_CHARGEN_END. Во втором событии мы должны изменить только случай, в котором персонаж был создан в Режиме быстрой загрузки. Нашей целью является изменение всего, что надо и передача всех оставшихся событий в оригинальный sys_chargen скрипт. Сравните sys_chargen от Bioware с тем, что вы только что создали.

Вы заметите, что мы подключили скрипт с названием bdm_sys_chargen_h и использовали функции с префиксом bdm_. Эти функции будут содержаться в скрипте, который мы сейчас напишем. По сути, они являются усовершенствованными аналогами функций с инклуд-файла под названием sys_chargen_h. В папке \Backgrounds demo\_Systems\Includes создайте новый скрипт и назовите его bdm_sys_chargen_h. Внутри напишите это:

#include "sys_chargen_h"
#include "bdm_2da_constants_h"
#include "wrappers_h"
#include "plt_bdm_000pt_backgrounds"
 
void bdm_Chargen_SelectBackground(object oChar, int nBackground, int bUnApply = FALSE)
{
     Log_Chargen("bdm_Chargen_SelectBackground","-- " + (bUnApply?"Un":"") +"Selecting BG: " + ToString(nBackground),oChar);
    // -------------------------------------------------------------------------
    // 1. Установка переменной предыстории
    //          - создание внешности героя (или использование одной из заготовок)
    //          
    // -------------------------------------------------------------------------
    if (bUnApply)
    {
        SetCreatureProperty(oChar, PROPERTY_SIMPLE_BACKGROUND, 0.0, PROPERTY_VALUE_BASE);
    }
    else
    {
       SetCreatureProperty(oChar, PROPERTY_SIMPLE_BACKGROUND, IntToFloat(nBackground), PROPERTY_VALUE_BASE);
    }
    // -------------------------------------------------------------------------
    // 2. Игрок получает один навык.
    //    - найти нужный навык в файле backgrounds.xls
    //    - присвоить его игроку.
    // -------------------------------------------------------------------------
    int nAbility = ChargenGetBackgroundSkill(GetCreatureRacialType(oChar), nBackground);
    if (nAbility)
    {
        _AddAbility (oChar, nAbility, bUnApply);
    }
}
 
void bdm_Chargen_SetupPlotFlags(object oChar)
{
    int nRace       =  GetCreatureRacialType(oChar);
    int nBackground = GetPlayerBackground(oChar);
 
    Log_Trace(LOG_CHANNEL_CHARACTER,"bdm_sys_chargen_h","Установка plot-флагов расы: " 
               + IntToString(nRace) + ", background: " + IntToString(nBackground));
 
    // Сперва происходит инициализация всех флагов
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_SERVANT,FALSE);
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_APPRENTICE,FALSE);
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_DWARF_TRAVELLER,FALSE);
    WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_ELF_TRAVELLER,FALSE);
 
    switch (nBackground)
    {
        case BACKGROUND_SERVANT:
        {
            WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_SERVANT,TRUE); break;
            break;
        }
        case BACKGROUND_APPRENTICE:
        {
            WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_APPRENTICE,TRUE); break;
            break;
        }
        case BACKGROUND_TRAVELLER:
        {
            switch(nRace)
            {
                case RACE_DWARF: WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_DWARF_TRAVELLER,TRUE); break;
                case RACE_ELF: WR_SetPlotFlag(PLT_BDM_000PT_BACKGROUNDS, BDM_GEN_BACK_ELF_TRAVELLER,TRUE); break;
            }
            break;
        }
    }
}

Давайте рассмотрим эти две функции. Для начала сравните их с оригинальными. Наша функция bdm_Chargen_SelectBackground является более универсальной и может работать с любыми предысториями. Мы убрали сложные значения, определяющие начальные возможности для персонажа каждой предыстории и теперь используем функцию ChargenGetBackgroundSkill(), которая берет возможности с 2DA-файла предыстории, который мы отредактировали раньше (вспомните три последние столбца, определяющих начальные способности в зависимости от расы и предыстории). Если этот способ вам не подходит, и вам нужна более сложная логика распределения возможностей (как в предыстории аристократа), вы всегда можете вернуться к методу кодирования, как это сделали Bioware. Вторая функция называется bdm_Chargen_SetupPlotFlags(). Что она делает, можно понять из названия. Помните plot-файл, созданный нами ранее? Здесь мы устанавливаем нужный нам флаг в зависимости от выбранной расы и предыстории.

Arrowblue.png - Script

Проверка работоспособности

Теперь скомпилируйте ваши скрипты и экспортируйте их в модуль. Также убедитесь, что вы экспортировали вашу string-таблицу.

ВАЖНО! После экспорта всегда проверяйте, есть ли что-то в папке \Dragon Age\packages\core\override. Наличие каких-либо файлов может привести к багу и повредить оригинальную кампанию.

Теперь вы можете запустить игру и увидеть созданные вами предыстории. Если вы хотите проверить, правильно ли установлены plot-флаги, добавьте в стартовую локацию непися, создайте для него диалоги, в котором каждая строчка будет выводиться в зависимости от расы\класса\предыстории\пола героя. Также стоит убедиться, что герой получает возможности, указанные в 2DA-файлах.

NOTE Кажется, изменить сообщение, которое выводится в начале генерации персонажа невозможно.

Arrowblue.png - Exporting a module

Опциональные расширения

У Bioware есть парочка других скриптов, которые имеют отношение к константам предысторий. Их можно не менять, так как они нигде не используются. Скрипт из туториала по генерации использует проверку предыстории, но вам она не нужна, разве что вы хотите использовать свой модуль для написания туториала. Также есть, по крайней мере, один отладочный скрипт, который использует предыстории из оригинала (чтобы гарантировано установить нужный plot-флаг). Если вы хотите, чтобы ваши предыстории обрабатывались подобным образом, вы должны написать для себя схожий скрипт.

Описания расы и пола

Если действие вашего модуля происходит не в Ферелдене, вы, возможно, пожелаете изменить описания расы и пола, которое появляется во время генерации персонажа. Описание расы содержится в столбце “Description”(описание) в документе RACE_base 2DA. Вам просто надо изменить строчки, указанные там. Используйте значения ID-номеров в районе 100000000. К сожалению, описание пола сложно закодировано в string-переменной с ID-номером 377283. К счастью, вы можете сделать локальную версию этой строчки. Они будет применяться исключительно для вашей кампании. Или же, если вы опытный пользователь и знакомы с UI туториалом, то нужная нам строчка содержится в файле Localization.as в виде переменной LOC_GENDER_DESCRIPTION = 377283, которая позже используется в файле RaceGenderScene.as. После редактирования файла Localization.as вы должны скомпилировать его и внедрить в соответствующие .gfx-файлы.

Заключение

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

Язык: English  • русский