ru-board: http://rusmnb.ru/index.php?topic=8964.msg332618#msg332618
How to install modmerger-pack
1. Download, unzip the latest module system: Module System (TaleWorlds Download Server)
2. Download, install Python 2.7. Take better .msi, do not have to configure Path.
3. Copy the module Native, give up the name for your new module.
4. Configure a module system for direct compilation to the folder of your module. This will greatly simplify life with the transfer of individual files manually ..
6. Download, install Modmerger 0.2.5.
7. Set up the module system version to avoid build errors:
9. To add modmerg-pack first see readme inside (if any).
9.1 Unpack modmerger-pack. Copy brf-texture-sound-etc recourses to YourMod folder if any. Copy .py-source to module_system folder.
9.2 Add new mod to mods_active list..
Repeat 9-9.3 steps for each new modmerger-pack.
As a result, you will have a list of mods that are independent of the version of the modulе_system. Just refresh Native and reinstall ModMerger if needed.
The list of examples "how to" add a new code to the module system through ModMerger
Animations:
Dialogs:
Constants:
Scenes:
Mission_templates:
How to install modmerger-pack
1. Download, unzip the latest module system: Module System (TaleWorlds Download Server)
2. Download, install Python 2.7. Take better .msi, do not have to configure Path.
3. Copy the module Native, give up the name for your new module.
4. Configure a module system for direct compilation to the folder of your module. This will greatly simplify life with the transfer of individual files manually ..
5. Build module by build_module.bat. Run the game with YourMod. There should be no errors, and differences from the Native.module_info.py said:export_dir = "D:/games/Mount&Blade Warband/Modules/YourMod/" # Direct compilation
6. Download, install Modmerger 0.2.5.
7. Set up the module system version to avoid build errors:
8. Again, do a test compilation. Run the game. There should be no errors, and differences from the Native.Module_system 1.158/modmerger_options.py said:# check and fill in defaults for certain required variables
try:
module_sys_info["version"]
except KeyError:
# assume version to be latest version that modmerger was tested on
module_sys_info["version"] = 1158
9. To add modmerg-pack first see readme inside (if any).
9.1 Unpack modmerger-pack. Copy brf-texture-sound-etc recourses to YourMod folder if any. Copy .py-source to module_system folder.
9.2 Add new mod to mods_active list..
9.3. Build module. Check add-on in-game.Module_system 1.158/modmerger_options.py said:mods_active = [
# insert the active mod names here
"NewMod", # description
# "anothermod",
]
Repeat 9-9.3 steps for each new modmerger-pack.
As a result, you will have a list of mods that are independent of the version of the modulе_system. Just refresh Native and reinstall ModMerger if needed.
The list of examples "how to" add a new code to the module system through ModMerger
Animations:
The new animation is added only to the "unused" places. For this uses a modmerge-functions that also allows you to replace the old by new anim. Example:
human_animations.py said:... default head of module_animations.py ...
add_block = [ # This animation will replace an unused_
# Walking
["run_forward", acf_enforce_lowerbody, amf_use_cycle_period|amf_client_prediction,
[2.0, "man_walk", 0, 32, arf_use_walk_progress|arf_cyclic|blend_in_walk|arf_make_walk_sound,pack2f(0.4,0.9), (0, 0, 0), 0.4],],
...
# Stand Up
["stand_up", acf_enforce_lowerbody, amf_priority_jump|amf_play|amf_client_prediction,[1.0, "stand_man", 0, 1, arf_blend_in_10],],
]
from util_animations import *
def modmerge(var_set):
try:
var_name_1 = "animations"
orig_animations = var_set[var_name_1]
modmerge_animations(orig_animations)
except KeyError:
errstring = "Variable set does not contain expected variable: "%s"." % var_name_1
raise ValueError(errstring)
def modmerge_animations(orig_animations):
try:
add_animations(orig_animations, add_block, check_duplicates = True) # replace existing and add new
except:
import sys
print "Injecton 1 failed:", sys.exc_info()[1]
raise
Dialogs:
Dialogs is a specific list acts as a filter. At the end of the list is a black hole "Surrender or die", which is displayed if the previous dialogues have not been met. Therefore, the new dialogs should be added to the top of the list. Example:
harbour_dialogs.py said:... default header from module_dialogs.py ...
dialogs_insert_block = [
# Harbour Master
# First conversation
[anyone, "start", [
(store_conversation_troop, "$g_talk_troop"),
(is_between, "$g_talk_troop", harbour_masters_begin, harbour_masters_end),
(troop_slot_eq, "$g_talk_troop", slot_troop_met_previously, 0),
],
"Good day {young man/lassie}. I'm the Captain of this port.
...
...
]
def modmerge(var_set):
try:
var_name_1 = "dialogs"
orig_dialogs = var_set[var_name_1]
modmerge_dialogs(orig_dialogs)
except KeyError:
errstring = "Variable set does not contain expected variable: "%s"." % var_name_1
raise ValueError(errstring)
def modmerge_dialogs(orig_dialogs):
try:
# Add dialogs to the top of the list
orig_dialogs.reverse() # Reverse list
orig_dialogs = dialogs_insert_block # add a new code
orig_dialogs.reverse() # revers the list back
except:
import sys
print "Injecton 1 failed:", sys.exc_info()[1]
raise
Constants:
Nothing to be scripted. Just write a new constants. Example:
ship_navigation_constants.py said:# [OSP] Ship Navigation
# Constants that uses in game
# MB Warband v1.158+
# Сode v1.0: by Shcherbyna
# Additional code vX.X: by
# -*- coding: UTF-8 -*-
# Ship steering commands
SHIP_SAIL_ON = 1 # sail on (unmooring)
SHIP_SAIL_OFF = 2 # sail off
SHIP_AHEAD = 3 # move ahead
SHIP_ASTERN = 4 # move astern
SHIP_RIGHT = 5 # turn to the right
SHIP_LEFT = 6 # turn to the left
# Ship status
SHIP_STATUS_UNDERWAY = 1 # sail on
SHIP_STATUS_ANCHORAGE = 2 # anchored
SHIP_STATUS_MOORED = 3 # moored
SHIP_STATUS_BOARDING = 4 # boarding
SHIP_STATUS_NOT_UNDER_COMMAND = 5 # sail off
# Wind power
NAVIGATION_WIND_LOW = 1
NAVIGATION_WIND_MEDIUM = 2
NAVIGATION_WIND_STRONG = 3
Scenes:
Nothing to be scripted. Just write a new scene row. Example:
harbour_scenes.py said:... default header from module_scenes.py ...
scenes = [
("town_harbour",sf_generate,"none", "none", (0,0),(240,240),-0.5,"0x000000033a000980400258960000750d80002cb9000053a6",
[],[], "outer_terrain_beach"),
]
Mission_templates:
Usually, in the absence of additional rules, ModMerger automatically connects the new data, whether scripts or menu. As it turned out, with mt this does not happen, so if you create a new scene and mt-script, the question is "how to add". Here is an example:
YourModName_mission_templates.py said:... default header from module_mission_templates.py .......
mission_templates = [
... a new mt ...
]
from util_common import *
from util_wrappers import *
def add_mission_templates(orig_mission_templates, add_mission_templates, check_duplicates = True):
addmode = ADDMODE_REPLACE_EXIST
if not check_duplicates:
addmode = ADDMODE_APPEND
return add_objects(orig_mission_templates, add_mission_templates, addmode)
def modmerge(var_set):
try:
var_name_1 = "mission_templates"
orig_mission_templates = var_set[var_name_1]
add_mission_templates(orig_mission_templates, mission_templates, True) # add a new mission_tmplt / добавить новую миссию
except KeyError:
errstring = "Variable set does not contain expected variable: "%s"." % var_name_1
raise ValueError(errstring)
New triggers are combined into a list. Then this list is added to the end of the list of triggers specified mt. This example shows how to add new triggers to the Port mt, which enable the player to control the ship. Note also the first trigger ti_on_agent_spawn (native name and new code).. when adding it will not replace the native trigger with the same name, and will be added to the end of the list of triggers. Thus, in the mt-scenario will be 2 triggers with the same names ti_on_agent_spawn: the first is native, the second a new one that will be executed, provided that the player has arrived on the scene not on horse, but on a palanquin.
YourModName_mission_templates.py said:... default header from module_mission_templates.py .......
# New triggers
on_palanquin_spawn = (
ti_on_agent_spawn, 0, 0,
[
(store_trigger_param_1, ":agent"),
(agent_get_item_id, ":horse_id", ":agent"),
(eq, ":horse_id", "itm_palanquin"),
],
[
#(store_trigger_param_1, ":agent"),
(display_message, "@Event on_palanquin_spawn"),
])
on_ahead_command = (
1, 2, 0, [(eq, "$g_sail_command", SHIP_AHEAD)],
[
(... code ...),
])
on_astern_command = (
1, 2, 0, [(eq, "$g_sail_command", SHIP_ASTERN)],
[
(... code ...),
])
on_mooring_command = (
1, 2, 0, [(eq, "$g_sail_command", SHIP_CREW_MOORING)],
[
(... code ...),
])
# Combine them in the right group
ship_triggers = [
on_ahead_command,
on_astern_command,
]
crew_triggers = [
on_mooring_command,
]
palanquin_triggers = [
on_palanquin_spawn,
]
from util_common import *
from util_wrappers import *
def modmerge_mission_templates(orig_mission_templates):
# 1) Example of adding new triggers to the specified mt
find_i = find_object(orig_mission_templates, "town_harbour") # find the specified mission
orig_mission_templates[find_i][5].extend(ship_triggers) # add new triggers
# 2) Example of adding trigger groups to several mt
for n in range(len(orig_mission_templates)):
mt_name = orig_mission_templates[n][0]
if (mt_name=="town_harbour" or mt_name=="open_sea"): # search for the exact name of the mt
orig_mission_templates[n][5].extend(ship_triggers + crew_triggers)
elif ("harbour" in mt_name or "sea" in mt_name): # search scenarios by incomplete name
orig_mission_templates[n][5].extend(ship_triggers)
# 3) Example of adding triggers to all mt-scenarios except those specified
elif (not "tutorial" in mt_name and not "multiplayer" in mt_name and not "conversation" in mt_name):
orig_mission_templates[n][5].extend(palanquin_triggers)
def modmerge(var_set):
try:
var_name_1 = "mission_templates"
orig_mission_templates = var_set[var_name_1]
modmerge_mission_templates(orig_mission_templates) # perform search-replace function
except KeyError:
errstring = "Variable set does not contain expected variable: "%s"." % var_name_1
raise ValueError(errstring)
In this example from native module_mission_templates.py is loaded a few common_triggers who injected by different number of lines of new code, with changes of insert positions :
pbod_mission_templates.py said:... default header from mt.py .......
bc_tab_press_addon = [
#PBOD - Battle Continuation
(else_try),
(party_slot_eq, "p_main_party", slot_party_pref_bc_continue, 1), #PBOD Battle Continuation On
... code ...
(finish_mission, 0),
#PBOD - Battle Continuation END
]
from util_common import *
from util_wrappers import *
def modmerge_mission_templates(orig_mission_templates):
# Loading common-names for further work with them
from module_mission_templates import common_battle_tab_press, common_battle_check_victory_condition, common_battle_order_panel
try:
# 1) Inserting a new code from the block bc_tab_press_addon before 2 rows from the searched
codeblock = TriggerWrapper(common_battle_tab_press).GetConsequenceBlock()
pos = codeblock.FindLineMatching((call_script, "script_cf_check_enemies_nearby"))
codeblock.InsertBefore(pos-1, bc_tab_press_addon) # pos-1 to jump above the else try
# 2) Inserting a new row before the searched
codeblock = TriggerWrapper(common_battle_check_victory_condition).GetConditionBlock()
pos = codeblock.FindLineMatching((neg|main_hero_fallen, 0))
codeblock.InsertBefore(pos,[(this_or_next|party_slot_eq, "p_main_party", slot_party_pref_bc_continue, 1)])
# 3) Inserting a new row after the searched
codeblock = TriggerWrapper(common_battle_order_panel).GetConsequenceBlock()
pos = codeblock.FindLineMatching((game_key_clicked, gk_view_orders))
codeblock.InsertAfter(pos,[(neg|main_hero_fallen)])
except:
import sys
print "common_triggers injecton failed:", sys.exc_info()[1]
raise
def modmerge(var_set):
try:
var_name_1 = "mission_templates"
orig_mission_templates = var_set[var_name_1]
modmerge_mission_templates(orig_mission_templates) # perform search-replace function
except KeyError:
errstring = "Variable set does not contain expected variable: "%s"." % var_name_1
raise ValueError(errstring)
This example shows the insertion, deletion, replacement parts of mt-triggers. Also note, instead of editing the mt-triggers you can add new instances of that in some cases it may be easier. Thus one mt-scenario may have, for example, several ti_on_agent_spawn: one is native, second is your, which, moreover, can only work under certain conditions.
YourModName_mission_templates.py said:... default mt header .......
# A new inject code
inject_block = [
(is_presentation_active, "prsnt_command_line"),
(try_begin),
... code ...
(try_end),
]
from util_common import *
from util_wrappers import *
def modmerge_mission_templates(orig_mission_templates):
for n in range(len(orig_mission_templates)): # Check all mt
mt_name = orig_mission_templates[n][0] # take the name of the current mt-scenario
# 1) Further code to execute for all mt-scenarios except those specified
if (not "tutorial" in mt_name and not "multiplayer" in mt_name and not "conversation" in mt_name ):
# 1.1) Example of adding a new line to the end of the trigger
trigger_i = MissionTemplateWrapper(orig_mission_templates[n]).FindTrigger_i(ti_on_agent_spawn) # find ti_on_agent_spawn trigger
if ( trigger_i != None ): # if the trigger is found => continue
trigger = orig_mission_templates[n][5][trigger_i] # take this trigger
codeblock = TriggerWrapper(trigger).GetConsequenceBlock() # take his code
codeblock.Append([(call_script, "script_scene_agent_set_name")]) # add a new row to the end
# 1.2) Example of adding a list of rows to the end of the trigger
codeblock.Append(inject_block)
# 2) Further code to execute for all mt-scenarios
# 2.1) Example of search-insert-delete
trigger_i = MissionTemplateWrapper(orig_mission_templates[n]).FindTrigger_i(1, 4, ti_once [(main_hero_fallen)]) # find trigger (1 ,4, ti_once, [(main_hero_fallen)])
if ( trigger_i != None ): # if the trigger is found => continue
trigger = orig_mission_templates[n][5][trigger_i] # take this trigger
codeblock = TriggerWrapper(trigger).GetConsequenceBlock() # take his code
pos = codeblock.FindLineMatching((assign, "$pin_player_fallen", 1)) # in the body of the trigger to find the second match (1 match skip)
if (codeblock.GetLineContent(pos 1) != (try_begin) ): # check if the next line is not (try_begin), ie this is native code and not changed..
codeblock.InsertAfter(pos, batt_continue_addon) # insert a new code from the block inject_block after searched line
codeblock.Append([(try_end)]) # and add to the end of the trigger (try_end)
if (trigger == common_siege_check_defeat_condition): # If this trigger actually bears the name common_siege_check_defeat_condition
pos = codeblock.FindLineMatching((party_slot_eq, "p_main_party", slot_party_pref_bc_charge_ko, 1)) # find a second match of the searched line
codeblock.RemoveAt(pos, 6) # and remove 6 lines below, including found
# 2.2) Example of replacing trigger's recharge-time with ti_once to 0
orig_mission_templates[n][5][trigger_i] = list(orig_mission_templates[n][5][trigger_i]) # break up trigger in the list of items
orig_mission_templates[n][5][trigger_i][2] = 0 # replace third item
orig_mission_templates[n][5][trigger_i] = tuple(orig_mission_templates[n][5][trigger_i]) #restore the structure of the trigger (collect a list of items in the immutable tuple)
def modmerge(var_set):
try:
var_name_1 = "mission_templates"
orig_mission_templates = var_set[var_name_1]
modmerge_mission_templates(orig_mission_templates) # perform search-replace function
except KeyError:
errstring = "Variable set does not contain expected variable: "%s"." % var_name_1
raise ValueError(errstring)
Last edited by a moderator: