Часть2: Редактирование файлов модульной системы
Внимание! Информация актуальна для модульной системы старой версии игры. В новой версии (под 1.011) возможны расхождения с текстом.
Как было описано в предыдущей главе, работа с модульной системой состоит в следующем:
1) Открываем для редактирования один или более модульных файлов(они начинаются с module_ и заканчиваются расширением .py) и вносим желаемые изменения.
2) После чего, запускаем файл build_module.bat(двойным кликом на него). Этим вы произведете сборку модуля и получите список ошибок, если таковые будут.
3) Если ошибок не будет, можно запустить Mount&Blade и проверить внесенные изменения. Иногда придется начинать новую игру, чтобы увидеть внесенные изменения.
2.1 – Редактирование модульной системы
Модульная система использует списки языка Python для представления коллекций игровых объектов. (Python-список начинается '[', включает список объектов разделяемых запятыми и оканчивается ']' ) Если вы откроете и посмотрите любой модульный файл – увидите, что он содержит такие списки. Например module_map_icons.py содержит:
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
]
Тут map_icons описаны как Python-список и каждый элемент списка это описание объекта значка карты. Например, ("player",0,"player", 0.2, snd_footstep_grass) – такой объект. Эти объекты называются запись. Записи как и списки содержат элементы разделенные запятыми (но начинаются и оканчиваются круглыми скобками). Структура каждой записи описана вначале каждого модульного файла. Для значков карты каждая запись содержит:
1 ) название значка,
2 ) флаги,
3 ) название 3D модели,
4 ) масштаб,
5 ) звуковой идентификатор.
Для первой записи ("player",0,"player", 0.2, snd_footstep_grass)
1 ) название значка = "player"
2 ) флаги = 0
3 ) название 3D модели = "player"
4 ) масштаб = 0.2
5 ) звуковой идентификатор = snd_footstep_grass
Узнать структуру объектов для каждого модульного файла можно прочитав документацию вначале каждого из них.
2.2 –Добавление новых объектов
Теперь, зная структуру записей map_icons, мы можем добавить собственные значки карты. Еще раз посмотрим на список.
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
]
Новые игровые объекты в любом модульном файле можно добавлять только внутри списка. Как видно, список для module_map_icons оканчивается записью ("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass). Чтобы освободить место для нашего нового объекта опустим квадратную скобку на строчку ниже. Теперь можно добавить объект. Проще всего это сделать, скопировав уже существующий объект и отредактировав необходимые параметры. Например:
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
("new_icon",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
]
В этом примере мы скопировали ("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass) и дали ему новое имя "new_icon". Этот новый значок имеет флаг. Флаги можно взводить и сбрасывать, включая или удаляя их названия из соответствуюшего поля. Например, флаг mcn_no_shadow нашего нового значка означает, что он не будет отбрасывать тень. Уберем этот флаг у нашего нового значка. Чтобы это сделать , заменим mcn_no_shadow на 0, обозначив таким образом, что наш значок не имеет никаких флагов.
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
("new_icon",0,"City", 0.9,snd_footstep_grass),
]
Оба значка "town" и "new_icon" используют 3D модель "City", которая хранится в ресурсных файлах игры. Изменяя это поле, мы можем использовать любую 3D модель из ресурсных файлов.
Т.к. оба значка "town" и "new_icon" используют одну и туже 3D модель, в игре они будут выглядеть абсолютно одинаково. Сделаем так, чтобы "new_icon" выглядела немного подругому.
map_icons = [
("player",0,"player", 0.2, snd_footstep_grass),
("player_horseman",0,"player_horseman", 0.2, snd_gallop),
("gray_knight",0,"knight_a", 0.2, snd_gallop),
("vaegir_knight",0,"knight_b", 0.2, snd_gallop),
("peasant",0,"peasant_a", 0.2,snd_footstep_grass),
("khergit",0,"khergit_horseman", 0.2,snd_gallop),
("axeman",0,"bandit_a", 0.2,snd_footstep_grass),
("woman",0,"woman_a", 0.2,snd_footstep_grass),
("town",mcn_no_shadow,"City", 0.9,snd_footstep_grass),
("new_icon",0,"City", 5.0,snd_footstep_grass),
]
В этом примере мы изменили масштаб значка с 0.9 на 5.0. Это означает, что он будет отображаться в пять раз больше своего нормального размера. Это поможет нам отличить его от "town" после внедрения в игру.
Далее мы создадим новую группу в module_parties.py, которая будет использовать новый значок. Для этого нужно сослаться на значок из module_parties.py.
2.3 – Использование объектов в других модулях
Откроем файл module_parties.py. В нем, мы видим другой Python-список - parties = [.
Как видно, структура записи в module_parties.py сильно отличается от module_icons. Это справедливо почти для всех модульных файлов. Изучим подробнее структуру записей, описывающих группы.
Например группа:
("zendar","Zendar",icon_town|pf_is_static|pf_always_visible|pf_hide_defenders, "zendar", pt_none, fac_neutral,0,ai_bhvr_hold,0,(2,46),[(trp_swadian_knight,6,0)]),
Эта запись располагает город Zendar на карте. Различные свойства Zendar-а описаны в соответствующих полях, аналогично тому, как это было в module_icons.py.
Разберем структуру записи:
1 ) Party-id - Используется для ссылки на объект из других файлов.
2 ) Party name – Название игры, которое будет использоваться в игре. Оно может отличаться от Party-id.
3 ) Party flags – Поле содержащее флаги. В качестве первого флага указывается название значка на карте, который будет использовать группа.
4 ) Menu – Это поле не используется в игре после версии 0.730.
5 ) Party-template – Идентификатор принадлежности к группе. По умолчанию - pt_none.
6 ) Party faction – Указывается фракция к которой принадлежит группа. Это может быть любая фракция из module_factions.py.
7 ) Party personality –За пояснения можно посмотреть в header_parties.py.
8 ) AI-behaviour – Описывает поведение группы на глобальной карте.
9 ) AI-target party - Цель деятельности группы.
10 ) Initial coordinates – Начальные координаты на глобальной карте ( X, Y).
11 ) List of troop stacks – Стек войск, каждый элемент стека содержит следующие поля:
11.1 ) Troop-id – идентификатор вида войска из module_troops.py.
11.2 ) Number of troops in this stack – Количество войск данного вида в стеке.
11.3 ) Member flags – Используется по необходимости. (Флаг pmf_is_prisoner спользуется, чтобы показать войска или персонажей находящихся в плену).
Рассмотрим запись группы Zendar:
("zendar","Zendar",icon_town|pf_is_static|pf_always_visible|pf_hide_defenders, "zendar", pt_none, fac_neutral,0,ai_bhvr_hold,0,(2,46),[(trp_swadian_knight,6,0)]),
1 ) Party-id = "zendar"
2 ) Party name = "Zendar"
3 ) Party flags = icon_town|pf_is_static|pf_always_visible|pf_hide_defenders
4 ) Menu = "zendar"
5 ) Party-template = pt_none
6 ) Party faction = fac_neutral
7 ) Party personality = 0
8 ) AI-behaviour = ai_bhvr_hold
9 ) AI-target party = 0
10 ) Initial coordinates = (2,46)
11 ) List of troop stacks:
11.1 ) Troop-id = trp_swadian_knight
11.2 ) Number of troops in this stack = 6
11.3 ) Member flags = 0
Как видно, в 3-м поле записи Zendar-а ссылка на значок "town" из module_icons.py с добавленным префиксом «icon_». Этот префикс указывает системе нужный модульный файл. Соответсятвенно используются : icon_ для module_icons; fac_ для module_factions; p_ для module_parties и т.д. Префиксы соответствующие каждому файлу можно найти в конце этого раздела.
Попробуем добавить новую группу. Но прежде обратите внимание: Не стоит добавлять свой город в конец списка групп. Это может привести к нарушению функций оригинального кода. В модуле module_parties.py рекомендуется вставлять новые города между "training_ground" и "castle_1".
Скопируй те "town_14" и вставьте между "training_ground" и "castle_1".
("training_ground","Training Ground", icon_town|pf_town|pf_disabled, "training_ground", pt_none, fac_vaegirs,0,ai_bhvr_hold,0,(-2,-3),[(trp_vaegir_knight,6,0)]),
("new_town","Mod_Town", icon_town|pf_town, "town", pt_none, fac_vaegirs,0,ai_bhvr_hold,0,(-4,-37),[(trp_vaegir_knight,6,0)]),
("castle_1","Culmarr_Castle",icon_town|pf_is_static|pf_always_visible, "castle", pt_none, fac_outlaws,0,ai_bhvr_hold,0,(-47,-51),[(trp_swadian_knight,5,0),(trp_swadian_crossbowman,25,0)]),
В этом примере мы сменили идентификатор группы с "town_14" на "new_town" и название с "Halmar" на "Mod_Town".
Таким образом:
1) Чтобы сослаться на этот объект из других файлов нужно использовать идентификатор "new_town" с префиксом "p_", т.е. "p_new_town".
2) В игре мы будем видеть название "Mod Town" описывающее группу и никогда идентификатор.
3) Эта группа использует значок icon_town и флаг pf_town.Этот флаг дает группе общие свойства города.
4) "Mod Town" принадлежит фракции Vaegir-ов.
5) Координаты нашего города на глобальной карте те же, что и у Halmar-а.
("training_ground","Training Ground", icon_town|pf_town|pf_disabled, "training_ground", pt_none, fac_vaegirs,0,ai_bhvr_hold,0,(-2,-3),[(trp_vaegir_knight,6,0)]),
("new_town","Mod_Town", icon_new_icon|pf_town, "town", pt_none, fac_neutral,0,ai_bhvr_hold,0,(-1,-1),[(trp_vaegir_knight,6,0)]),
("castle_1","Culmarr_Castle",icon_town|pf_is_static|pf_always_visible, "castle", pt_none, fac_outlaws,0,ai_bhvr_hold,0,(-47,-51),[(trp_swadian_knight,5,0),(trp_swadian_crossbowman,25,0)]),
Итак, мы сменили значок нашего города с town на icon_new_icon, координаты на (-1,-1), а фракцию на fac_neutral.
Итак, все готов, чтобы увидеть новый значок на карте. Сохраните все изменения внесенные в файлы модульной системы и запустите build_module.bat. Если все пройдет успешно, можно запустить наш мод и увидеть новый город с новый город с новым значком в центре карты.
Если сборка модуля не удалась, внимательно проверьте все выполненные действия. Тщательно проверьте, что все скобки и запятые расставлены правильно. Наиболее частая причина ошибок - неверный синтакиси.
Игровой заезд в город сейчас приведет к сражению, т.к. у города нет присвоенного игрового меню. Этой задачей мы займемся в более поздних главах документации.
Список префиксов:
fac_ -- module_factions.py
icon_ -- module_map_icons.py
itm_ -- module_items.py
mnu_ -- module_game_menus.py
mno_ -- module_game_menus.py -- References an individual menu option in module_game_menus.
mt_ -- module_mission_templates.py
psys_ -- module_particle_systems.py
p_ -- module_parties.py
pt_ -- module_party_templates.py
qst_ -- module_quests.py
script_ -- module_scripts.py
scn_ -- module_scenes.py
spr_ -- module_scene_props.py
str_ -- module_strings.py
trp_ -- module_troops.py