[MS] Третья часть. Модульная система, файл troops.
Третья часть.
В этой части документации мы затронем файл module_troops.py и его функции. Module_troops включает в себя такие объекты как обычные войска, герои, сундуки и городских НПС. Эти объекты полностью определены - с заданными лицами, возможностями, очками опыта и инвентарем. Когда бы вам ни захотелось создать новый характер или тип войска, вы будете модифицировать именно этот файл.
3.1 Разбор записей troops/войск.
Файл module_troops.py начинается с маленького блока кода, отвечающего за расчет навыков владения оружияи, и включающего в себя некоторую часть немодифицируемого кода. Проматываем это и направляемся сразу к списку troops = [.
Здесь мы можем найти записи игрока и нескольких других важных для игры персонажей. А сразу ниже описаны различные бойцы. Они являются отличными примерами уровневого прогресса войск, потому изучим их подробно.
Пример записи из списка объектов troops:
["novice_fighter","novice_fighter","novice_fighters",tf_guarantee_boots|tf_guarantee_armor,no_scene,reserved,fac_commoners,
[itm_sword,itm_hide_boots],
str_6|agi_6|level(5),wp(60),knows_common,swadian_face1, swadian_face2],
Эта запись описывает объект troop называемый "novice fighter". "novice fighter" это низкоуровневый боец, не очень хорош как боец, имеет маленькое число очков способностей, в остальном вообще почти не заметен.
Описание элементов записи:
1) Идентификатор troop/войска. Используется для ссылки на запись войска из других файлов.
2) Название troop/войска.
3) Название во множественном числе.
4) Метки для troop/войска. Метка с префиксом tf_guarantee_ + тип детали экипировки (как например, boots (сапоги), armor (броня) и т.д.) указывает, что если в инвентаре войска находится предмет соответствующего типа, он гарантировано будет надет и использован в бою. Если вы не ставите соответствующую метку, то войско может появиться в бою без предметов экипировки, чей тип не закреплен этой меткой. Только оружие ближнего боя будет экипировано без указания соответсвующего флага/метки. (прим: в Warband появилась новая метка tf_guarantee_all, позволяющая войску одеваться полностью и забивать все слоты под завязку)
5) Сцена. Применяется только к записям объектов Heroes/герои. Определяет в какой сцене и в какой entry point/входной точке герой появится. Для примера, метка scn_reyvadin_castle|entry (1) поместит героя во входную точку (1) внутри замка Рейвадин.
6) Зарезервированный, неиспользуемый элемент. Должен быть либо reserved либо 0.
7) Фракция. Принадлежность войска к фракции, используется префикс fac_.
8) Инвентарь. Список предметов в инвентаре войска. Эти предметы будут надеты обычными войсками случайным образом.
9) Атрибуты. Очки атрибутов войска (сила, ловкость, интелект, харизма), а также уровень персонажа/солдата_войска. Работает также как и для игрока.
10) Навык владения оружием. Представляет собой очки владения оружием данного войска. Функция wp(x) случайным образом задаст навык оружия близкий к значению "x", но вы также можете поместить точное значение одного или более навыков используя префикс wp_ + название навыка + (значение навыка). Например, если вы хотите создать умелого лучника, с остальными навыками владения оружием близкими к 60, то вы пишете:
wp_archery(160)|wp(60) .
11) Умения. Такие же умения как и у игрока. Стоит отметить, что в дополнение к атрибутам и умениям которые вы определили, войско получает 1 очко к атрибутам и 1 очко к умениям за каждый уровень (случайным образом).
12) Код для лица. Игра генерирует лицо согласно этому коду. Вы можете экспортировать новый код для лица из игры зажав CTRL + E в редакторе лиц, пока редактируете мод.
13) Код для лица 2. Применим только для обычных войск, можно пренебречь для героев. Игра будет создавать случайным образом лицо со значением кода, лежащим между первым и вторым кодами для каждого солдата в отдельности.
Рассмотрим значение элементов записи Novice_fighter:
1) Идентификатор войска= "novice_fighter"
2) Имя войска = "novice_fighter"
3) Множественное число солдат данного типа = "novice_fighters"
4) Метки = tf_guarantee_boots|tf_guarantee_armor0
5) сцена = no_scene
6) Зарезервиравонно = reserved
7) Фракции = fac_commoners (простолюдин)
8) Инвентарь = [itm_sword, itm_hide_boots]
9) Атрибуты = str_6|agi_6|level(5)
10) Навык владения оружием = wp(60)
11) Умения = knows_common (метка, прописывающая общие знания)
12) Код для лица (1) = swadian_face1
13) Код для лица (2) = swadian_face2
Три вещи, которые стоит отметить:
1. Наш "novice_fighter"/молодой_боец обладает меткой tf_guarantee_armor, но никакой брони в его собственности нету. Однако, это не делает метку tf_guarantee_armor бессмысленной. Войско наденет любую броню, какую только сможет заполучить по ходу игры.
2. Вначале, (на уровне 1) "novice_fighter" обладает силой (str) 6 и ловкостью (agi) 6. Как только игра стартует, он автоматически поднимается в уровне до пятого, что в свою очередь отразится ростом его атрибутов и умений (в атрибутах у "novice-fighter" прописан 5-ый уровень)
3. Он обладает умениями, определяемыми как knows_common или общие знания. knows_common это набор умений, заданный вначале файла module_troops.py; прокрутите вверх и посмотрите на этот набор:
knows_common = knows_riding_1|knows_trade_2|knows_inventory_management_2|knows_prisoner_management_1|knows_leadership_1
Войско, которое обладает knows_common/общими знаними, будет иметь значения навыков перечисленных выше; knows_riding_1 - значит умение верховой езды = 1; knows_trade_2 - торговля=2; knows_inventory_management_2 - управление инвентарем = 2; knows_prisoner_management_1 - управление пленными = 1; knows_leadership_1 - лидерство = 1. knows_common является константой. Подобным образом, можно определить любую другую константу, которая будет состоять из любого колличества объектов, чисел, идентификаторов или даже других констант.
В данном случае, knows_common/общие знания определены как: knows_riding_1|knows_trade_2|knows_inventory_management_2|knows_prisoner_management_1|knows_leadership_1
Таким образом в результате вставки knows_common в поле умений, модульная система будет функционировать точно так, как если бы вы задали в поле умений следущие метки: knows_riding_1|knows_trade_2|knows_inventory_management_2 |knows_prisoner_management_1|knows_leadership_1
Теперь давайте взглянем на следущую запись в списке:
["regular_fighter","regular_fighter","regular_fighters",tf_guarantee_boots|tf_guarantee_armor,no_scene,reserved,fac_commoners,
[itm_sword,itm_hide_boots],
str_8|agi_8|level(11),wp(90),knows_common|knows_ironflesh_1|knows_power_strike_1|knows_athletics_1|knows_riding_1|knows_shield_2,swadian_face1, swadian_face2],
В этом примере вы видите слегка усиленного "regular fighter"/"обычного бойца"; он имеет повышенное значение способностей, он 11-го уровня и некоторые из его умений выходят за рамки knows_common/общих знаний. В игре, если некоторые из "novice fighters"/ "молодых бойцов" достигают 11-го уровня, мы сделаем возможность проапгрейдить их до "regulars fighter"/"обычных бойцов". (см. далее)
3.2 Апгрэйд/прокачка войск.
Представляет собой список, указывающий какие войска и в кого могут быть проапгрейдены ("повышены в звании", если вам удобнее). Он находится на дне файла module_troops.py. Прокрутите вниз, в конец файла.
Как вы можете увидеть, каждый из вариантов апгрейда для любого типа войск должен быть объявлен операцией upgrade(troops). Сначала идентификатор войска подлежащего апгрейду, а затем идентификатор войска образующегося в результате апгрейда. К примеру: upgrade(troops,"farmer", "watchman") позволит фермерам (farmer) апгрейдится в караульных (watchman), если первые наберут достаточно опыта.
Существует два типа операций апгрейда:
1) upgrade(troops,"source_troop", "target_troop_1") предлагает вам только один апгрейд, из "source_troop" в "target_troop_1".
2) upgrade2(troops,"source_troop", "target_troop_1", "target_troop_2") позволит игроку выбрать между апгрейдом "source_troop" в "target_troop_1" или в "target_troop_2". Два варианта это текущий максимум возможностей выбора апгрейда.
Сейчас в этом блоке нет данных о "novice_fighter", так давайти добавим их. Скопируйте upgrade(troops,"farmer", "watchman") и вставьте в конец блока. Измените "farmer" на "novice_fighter" и "watchman" на "regular_fighter". Любой "novice fighters" в вашей группе способен теперь проапгрейдится до "regular fighters".
Теперь мы пойдем немного дальше. Сделайте еще одно погружение на дно списка, а затем поднимитесь до фразы: # Add Extra Quest NPCs below this point. Здесь вы заметите квадратную скобку "]", закрывающую python-овский список troops. Новые типы войск следует добавлять перед этой скобкой, чем мы сейчас и займемся. (прим: никакой скобки рядом с этой фразой я не нашел. Она (“]”) есть, но находится ниже, ищите ее перед фразой #Troop upgrade decloration)
3.3 Добавление новых войск.
Сдвиньте скобку вниз на две строки, затем на освободившеесе место скопируйте и вставьте следующий код:
["new_troop","new_troop","new_troops",tf_guarantee_boots|tf_guarantee_armor,no_scene,reserved,fac_commoners,
[itm_sword,itm_hide_boots],
str_6|agi_6|level(5),wp(60),knows_common,swadian_face1, swadian_face2],
Это данные с которыми мы планируем поиграться, создавая новый род войск. Для начала давайте назовём новый отряд по-человечески:
["red_rider","red rider","red riders",tf_guarantee_boots|tf_guarantee_armor,no_scene,reserved,fac_commoners,
[itm_sword,itm_hide_boots],
str_6|agi_6|level(5),wp(60),knows_common,swadian_face1, swadian_face2],
Теперь дадим ему немного брони и шлем:
["red_rider","red rider","red riders",tf_guarantee_boots|tf_guarantee_armor,no_scene,reserved,fac_commoners,
[itm_sword,itm_hide_boots,itm_leather_jerkin,itm_skullcap],
str_6|agi_6|level(5),wp(60),knows_common,swadian_face1, swadian_face2],
Теперь каждый солдат из рода войск определенного как "red_rider" будет носить кожанную безрукавку. Однако, только у некоторых появится itm_skullcap, потому что в поле меток у этого рода войск гарантированны только броня и сапоги. Если мы хотим быть увереными, что все наши солдаты наденут шлемы на головы, мы должны добавить tf_guarantee_helmet в поле меток:
["red_rider","red rider","red riders",tf_guarantee_boots|tf_guarantee_armor|tf_guarantee_helmet,no_scene,reserved,fac_commoners,
[itm_sword,itm_hide_boots,itm_leather_jerkin,itm_skullcap],
str_6|agi_6|level(5),wp(60),knows_common,swadian_face1, swadian_face2],
Давайте сделаем некоторые изменения в свойствах войска. Введем силу равную 9 и ловкость 9. Затем изменим уровень на 4-ый и навык владения оружием установим на 80. Наш "new troop" будет выглядеть так:
["red_rider","red rider","red riders",tf_guarantee_boots|tf_guarantee_armor|tf_guarantee_helmet,no_scene,reserved,fac_commoners,
[itm_sword,itm_hide_boots,itm_leather_jerkin,itm_skullcap],
str_9|agi_9|level(4),wp(80),knows_common,swadian_face1, swadian_face2],
Теперь он готов быть помещеным в игру, в качестве эксперимента.
3.4 Наемники.
(прим: в версии 1.011 никакого Зендара нет, как нет и наемников Зендара. Туторитал немного устарел.) Сохраните ваш прогресc, затем откройте файл module_parties.py. Опускайтесь вниз, пока не увидете группу "zendar_mercs" (наемники Зендара):
("zendar_mercs","zendar_mercs",pf_disabled, no_menu, pt_none, fac_commoners,0,ai_bhvr_hold,0,(0,0),[(trp_farmer,15,0)]),
Это группа наемников; группа не отображенна на глобальной карте, но может быть нанята как наемники через хозяина таверны Зендара. Этот момент задан в свойствах самого хозяина таверны.
В данном случае, "zendar_mercs" состоят из 15 фермеров. Если вы запустите игру прямо сейчас, вы сможете их нанять. Однако, если мы изменим "trp_farmer" на "trp_red_rider", то сможем нанять 15 солдат, определенных как "red riders". Попробуйте сделать эти изменения.
Сохраните ваш прогресс, закройте файл module_parties.py и дважды щелкните на файле build_module.bat. Если сборка мода будет завершена без проблем, вы найдете ваших новых солдат доступных к найму через содержателя Зендарской таверны. (Вы должны начать новую игру, чтобы ваши действия возымели эффект).
Начните новую игру и наймите ваших "red riders". Когда выйдете из города, посражайтесь немного. Когда ваши новые войска наберутся опыта проапгрейдите их в "regular fighters".
3.5 NPCs
Различные наемники и NPC, которых вы видите в игре, очень похожи на обычные войска. Самый значимый, выделяющий их элемент это метка tf_hero; Каждый NPC с которым вы столкнетесь в игре отностся к типу “герой”, даже если это торговец. Главная разница между обычными войсками и героями:
1) Герои бессмертны, их здоровье представленно процентым значением, и вы не можете нанять двух или более одинаковых героев, если только они не были склонированны по ошибке или намеренно. Даже если вы намеренно создали несколько клонов, эта явно плохая идея.
2) Каждый герой занимает отдельный стэк.
3) Герой четко показан в сцене, когда его нанимают в группу.
4) Герои остаются с игроком когда он побежден врагами -- герои не захватываются врагами в плен -- но игрок может захватывать вражеских героев.
Т.к. нам следует иметь только один образец для каждого героя, то название во множественном числе не используется -- содержимое поля для названия во множественном числе будет идентично содержимому поля с названием.
Пример записи объекта героя:
["Marnid","Marnid","Marnid", tf_hero, scn_the_happy_boar|entry(4),reserved, fac_commoners,[itm_linen_tunic,itm_hide_boots,itm_club],def_attrib|level(6),wp(60),knows_trade_3|knows_inventory_management_2|knows_riding_2,0x00000000000c600301c2510211a5b292],
Вот это и есть наш друг Марнид, преданный компаньон на протяжении всей игры. Он отмечен как герой меткой tf_hero в его поле меток. Мы можем найти его в entry point/входной точке (4) в таверне счастливый вепрь. Он несколько слабоват в бою, но действительно хорош в торговле, что весьма пригодится в наших ранних странствиях, и как любой герой он бессмертен, покрайней мере если не будет удален особым скриптовым событием. Вы можете также заметить что у Марнида собственный, уникальный код лица 0x00000000000c600301c2510211a5b292. Его модификация возможна с помощью игрового редактора лиц, вам будет нужно экспортировать оттуда полученный кода лица в ваш мод. Это объясненно в части 10, "Использование внутриигрового редактора".
Другая важная деталь: несмотря на то, что идентификатор объекта Марнид в файле --"Marnid"-- использует заглавную букву M, мы должны всегда ссылаться на идентификатор начинающийся со строчной буквы. Модульная система выдаст ошибку, если вы попытаетесь использовать заглавную букву в ссылке на идентификатор из другого файла. Итак, для ссылки на Марнида мы будем использовать идентификатор "trp_marnid".
Последняя интересная деталь это данные, которые вы можете заметить в поле атрибутов Марнида - def_attrib. def_attrib такая же константа как и knows_common, но определенная в файле header_troops.py. Ее функция похожа на функцию выполняемую knows_common -- заранее заданный набор атрибутов для записей troop. Взято из header_troops.py:
def_attrib = str_5 | agi_5 | int_4 | cha_4
Это говорит нам о том, что на старте герой с def_attrib будет обладать силой 5, ловкостью 5, интелектом 4, харизмой 4. Если задать отдельно любой другой атрибут после отметки def_attrib, то указанное значение без проблем заменит соответствующее ему из def_attrib.
Теперь мы готовы создать нашего собственного героя. Скопируйте запись героя "Марнид" и вставьте сразу же за записью "red_rider" сделанной раннее.
["Geoffrey","Geoffrey","Geoffrey", tf_hero, scn_the_happy_boar|entry(4),reserved, fac_commoners,[itm_linen_tunic,itm_hide_boots,itm_club],def_attrib|level(6),wp(60),knows_trade_3|knows_inventory_management_2|knows_riding_2,0x00000000000c600301c2510211a5b292],
Здесь мы поменяли идентификатор нового героя и имя на "Geoffrey"/Джоффри. Сделайти эти изменения и вы.
Теперь, если мы кликнем два раза на файл build_module.bat, модульная система скомпилирует наш мод без проблем. Наша запись не будет конфликтовать ни с чем. Но все же, существует одна главная проблемма -- оба, Джоффри и Марнид используют одну и ту же точку входа в одной и той же сцене. В результате мы найдем там только Марнида, поскольку его запись в файле расположенна выше, и Джоффри не появится, так как точка входа будет занята.
Теперь, если мы кликнем два раза на файл build_module.bat, модульная система скомпилирует наш мод без проблем. Наша запись не будет конфликтовать ни с чем. Но все же, существует одна главная проблемма -- оба, Джоффри и Марнид используют одну и ту же точку входа в одной и той же сцене. В результате мы найдем там только Марнида, поскольку его запись в файле расположенна выше, и Джоффри не появится, так как точка входа будет занята.
Для решения этой проблемы мы присвоим Джоффри значение входной точки (6) вместо (4). Это тут же вернет его в таверну, там где он не будет никому мешать. Ваша запись должна выглядить как эта:
["Geoffrey","Geoffrey","Geoffrey", tf_hero, scn_the_happy_boar|entry(6),reserved, fac_commoners,[itm_linen_tunic,itm_hide_boots,itm_club],def_attrib|level(6),wp(60),knows_trade_3|knows_inventory_management_2|knows_riding_2,0x00000000000c600301c2510211a5b292],
Пытаясь поговорить с Джоффри, вы заметите что он не имеет диалогов связанных с ним. Это еще один пример взаимосвязи отдельных module-файлов.
Важно заметить, что так как мы просто копировали запись Марнида, то код его лица будет применён и к Джоффри. Как уже говорилось ранее, отредактировать его можно с помощью внутриигрового редактора, но не будем забегать вперёд, всему своё время.
Мы оставим Джоффри как он есть, и вернемся к нему позже, когда будем работать с файлами module_quests.py и module_dialogs.py.
3.6 Торговцы.
(прим: вы не найдете внутри файла module_troops.py версии 1.011 записи, указанной ниже)
Торговцы это особый тип героя. В дополнению к метке tf_hero, они также обладают меткой tf_is_merchant. Эта метка не позволяет им надевать предметы из их инвентаря, за исключением тех, что изначально указанны внутри записи. Другими словами, торговцы получают многие виды предметов в течении игры, но они не надевают и не используют их. Все эти предметы будут выставленны на продажу.
Пример торговца:
["zendar_weaponsmith","Dunga","Dunga",tf_hero|tf_is_merchant, scn_zendar_center|entry(3),0, fac_commoners,[itm_linen_tunic,itm_nomad_boots],def_attrib|level(2),wp(20),knows_inventory_management_10, 0x00000000000021c401f545a49b6eb2bc],
Это торговец оружие в Зендаре, по имени Dunga/ Дунга. Он почти идентичен другим торговцам из версии найтив МиБа. Если вы рассмотрите их (торговцев) поближе, единственными отличиями будут идентификатор, имя, местоположение и лицо.
(прим: с этого места и до конца раздела, я взял на себя смелость немного адаптировать текст к файлу module_troops.py версии 1.011) Добавить торговца не так просто, как оно может показаться. Они разбиты на группы по определенной причине. Скрипты МиБа обновляют инвентарь торговцев каждый день и для каждого типа по своему --делая это, скрипты сортируют торговцов исходя из положения их записей в файле module_troops.py относительно друг друга. Для примера, интервал в котором должны быть описаны торговцы броней включает в себя все начиная с "town_1_armorer" и заканчивая "town_1_weaponsmith". "town_1_weaponsmith" является вверхней границей интервала, но не входит в сам интервал, т.е. для добавления новой записи необходимо поставить ее перед "town_1_weaponsmith" (на строку выше), если мы хотим, чтобы она (новая запись) была включена в интервал отведенный для торговцев броней.
По этой причине новый торговец броней должен быть добавлен перед "town_1_weaponsmith". Новый торговей оружием перед "town_1_tavernkeeper". Новый торговец общими товарами перед строкой "merchants_end". (прим: последнюю строку я оставил так, как она есть в документации).
3.7 Сундуки.
Сундуки являются особым "типом войск", используемым только для игрового отображения инвентаря сундука (того что в нем лежит). Т.е. они реализуют лишь инвентарь, для сундука, но не сам сундук. Сундук, который вы видите в игре, является частично костяком сцены, частично данными сцены, частично войском и частично программным кодом. Сундук в целом это нечто сложное для реализации, т.к. требует работы с различными module-файлами. Здесь мы опишем только информацию касающуюся файла module_troops.py.
Пример сундука:
["zendar_chest","zendar_chest","zendar_chest",tf_hero|tf_inactive, 0,reserved, fac_vaegirs,[],def_attrib|level(18),wp(60),knows_common, 0],
Все записи сундуков должны следовать этому примеру. Только имя, индентификатор, (возможно) уровень и навыки, и инвентарь могут быть измененны при создании нового сундука. Как уже отмеченно, запись объекта типа сундук в файле module_troops.py служит лишь для внутригрового отбражения инвентаря сундука. Более того, любые предметы, которые вы добавите в инвентарь записи сундука окажутся внутри сундука на старте игры.
Сундуки требуют записи как тип войска "сундук" в файле module_troops.py для функционирования. Однако они также требуют и другие модификации в различных module-файлах, которые мы опишем в специальной по-файловой документации.
Изучив эту часть документации, вы узнаете все, что следует знать касательно файла module_troops.py. Список всех доступных меток для работы с рассмотренными здесь типами записей находится в файле header_troops.py. Не стесняйтесь экспериментировать с ними, когда будете готовы. Давайте перейдем к 4 части документации.
Комментариев 0
Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.