How To 

[Tutorial] Mount & Blade: Warband: Modding Companions

How to Make Your Own Companions:
The Tutorial:
Part Eight:
The Revenge of Count Gutlans:
The Reckoning

With special thanks to iggorbb for showing me how to make my own companions.
This is my tutorial I wrote a while ago.

You will need:
Python 2.7.9
https://www.python.org/downloads/release/python-279/

To install Python, refer to section 1.2 of this topic:
http://forums.taleworlds.com/index.php/topic,5408.0.html
^You must do this otherwise you won't be able to open the .py(python) files.

Mount & Blade Modsystem:
http://forums.taleworlds.com/index.php/topic,324874.0.html

You can extract the modsystem files anywhere really, but preferably in their own folder. Maybe make a new folder on your desktop called "My M&B Mod." Or you could extract it into its own folder in the M&B modules folder, that's what i did because i was constantly switching between the two.

And a clean copy of Native, if you used any mods on your native folder like tweakmb your gonna want to get a clean install, which you can get from https://www.taleworlds.com/en/Games/Warband/Download

While your at it, make a copy of your native fold and rename it so you don't screw up your native files, while making your companions.


The only 4 files you need to edit:

These four files are module_info.py, module_scripts.py, module_strings.py and module_troops.py

If you have installed python properly, to open them, right click on them and choose "Edit with IDLE" (right under open).
VfncEDa.png


Step 1: Setting the build_module export directory.

The first file you need to edit is module_info.py, it only has 4 lines of text, and you only need to change one of them.
Code:
export_dir = "C:/Program Files/Mount&Blade/Modules/Native/"
Quicknote: any line with # in front of it and colored red is a "note" meaning it doesn't do anything, the devs put it there as an instruction or reference. You will see these alot in strings and scripts.
5BaFCTy.png


Copy the file path that goes to your copy of the native folder and paste it over the file path next to "export_dir =" , WITH quotes ( " " ) around it. Your also going to have to turn all the backslashes ( \ ) into forward slashes ( / ), and make sure there is a forward slash at the end of whatever your folder is called i.e. "/Native Copy/"

If there isnt it just spits it out into the folder before it (like modules).

After you have done this, click File -> Save.

Now your done with info.py

Step 2: "Designing" your new companion.

One thing that is gonna be helpful/necessary when making your new companions is making the faces. To do this you can use the warband game create a character/face editor.
sirinan said:
Just a quick tip: Going into multiplayer and editing your profile gives quicker access to facecodes. If you play multiplayer, you might want to create a new profile though, so you don't overwrite your favorite face.

You need to have edit mode enabled first off, you can do this from the configuration window on the warband launcher under advanced. It will also help to have warband running in a window instead of fullscreen, you can edit that in configurations too.
X0U3puw.png


Then you can start up warband and either create a new character or load a game, goto your character screen, and click on your picture to open the face editor.
Design the face you want your new companion to have, then press Ctrl+E,
And a box will appear above the face:
YHwSH9C.png



We'll be using that crazy string of numbers in just a second.

Open module_troops.py (right click, edit with IDLE).

Make sure you have the window that just popped up selected, and press Ctrl+F.

This will open the Find window (ctrl+f works for a ton of other programs too like IE, Firefox, Word, Excel) type in "npc16" and press find.

zvkgT4d.png


This will take you to Klethi's troop entry:
Code:
  ["npc16","Klethi","Klethi",tf_female|tf_hero|tf_unmoveable_in_party_window, 0, reserved,  fac_commoners,[itm_peasant_dress,itm_nomad_boots, itm_dagger, itm_throwing_knives],
   str_7|agi_11|int_8|cha_7|level(2),wp(80),knows_tracker_npc|
   knows_power_throw_3|knows_athletics_2|knows_power_strike_1,
   0x00000000000c100739ce9c805d2f381300000000001cc7ad0000000000000000],
#NPC system changes end

Put a space between Klethi's info and #npc system. Then, copy her info and paste it right underneath her.
Code:
  ["npc16","Klethi","Klethi",tf_female|tf_hero|tf_unmoveable_in_party_window, 0, reserved,  fac_commoners,[itm_peasant_dress,itm_nomad_boots, itm_dagger, itm_throwing_knives],
   str_7|agi_11|int_8|cha_7|level(2),wp(80),knows_tracker_npc|
   knows_power_throw_3|knows_athletics_2|knows_power_strike_1,
   0x00000000000c100739ce9c805d2f381300000000001cc7ad0000000000000000],
  ["npc16","Klethi","Klethi",tf_female|tf_hero|tf_unmoveable_in_party_window, 0, reserved,  fac_commoners,[itm_peasant_dress,itm_nomad_boots, itm_dagger, itm_throwing_knives],
   str_7|agi_11|int_8|cha_7|level(2),wp(80),knows_tracker_npc|
   knows_power_throw_3|knows_athletics_2|knows_power_strike_1,
   0x00000000000c100739ce9c805d2f381300000000001cc7ad0000000000000000],
#npc

Change the copies "npc16" to "npc17" and you can edit the other two names (first one is singular, second one is plural, like the difference between man and men, First one affects what their name shows up as in taverns and such, second one kinda seems like what they put "lord/lady" in front of, so you can have your companions first name be like "John, the knight" and the second name be "John" and when he's given a fief and made a lord he will be "Lord John" instead of "Lord John, the knight")
Code:
  ["npc16","Klethi","Klethi",tf_female|tf_hero|tf_unmoveable_in_party_window, 0, reserved,  fac_commoners,[itm_peasant_dress,itm_nomad_boots, itm_dagger, itm_throwing_knives],
   str_7|agi_11|int_8|cha_7|level(2),wp(80),knows_tracker_npc|
   knows_power_throw_3|knows_athletics_2|knows_power_strike_1,
   0x00000000000c100739ce9c805d2f381300000000001cc7ad0000000000000000],
  ["npc17","newcompanion","newcompanion",tf_female|tf_hero|tf_unmoveable_in_party_window, 0, reserved,  fac_commoners,[itm_peasant_dress,itm_nomad_boots, itm_dagger, itm_throwing_knives],
   str_7|agi_11|int_8|cha_7|level(2),wp(80),knows_tracker_npc|
   knows_power_throw_3|knows_athletics_2|knows_power_strike_1,
   0x00000000000c100739ce9c805d2f381300000000001cc7ad0000000000000000],
#npc

For testing purposes, at this time, DO NOT change anything else about this new companion, follow the steps down to scripts and strings, just COPYING and pasting what klethi has, and changing the numbers. once you have copied klethi's(npc16) scripts & strings, save the files, run build_module.bat, and as long as it doesnt give you any errors, go in game, START A NEW GAME, and use cheats to teleport to all the cities, and go in every tavern looking for "newcompanion" once you find it, you now know that your new companion "works" and exists, now you can edit it to make it a real "person" not just a clone.

Now let me explain these tags after the names:
tf_hero means they show up in the Notes: Characters
tf_female means their female.
tf_unmovable_in_party_window means you cant like garrison them, or "disband" them
tf_guarantee_ranged means they start assigned to archers as opposed to infantry
to have them start in the cavalry group you need both tf_guarantee_horse and tf_mounted, they dont work separately.
Each of those needs to be separated by a " | " (shift+\)

The only one you really need to touch is tf_female, delete if your companion is male, put it in if it is a female.

Dont know what "0, reserved, " does, but we dont need to touch it either. same with "fac_commoners".

After those is the hero's items, you can find the other items in the game in the module_items.py, make sure each new item you add has "itm_" infront of it.
DJhuCwD.png


Next come the stats:
str_7|agi_11|int_8|cha_7|level(2),wp(80),knows_tracker_npc|
Pretty self exlpantory there.
wp is weapon proficiency, this is for ALL types of weapons, for varying proficiencies:
Ashmond said:
For weapon points, you may adjust them individually, even for npcs, for example:

wp(100)|wp_firearm(120|wp_one_handed(40) - syntax and usage starts at line 52 of the troops module.

If you want your npcs to not have extra points/ have the same amount of stat/skill points you have as a player, follow this formula when you assign skills/stats:
Code:
22=statpoints lvl1, everyone starts with 4str|4agi|4int|4cha 
so level 1 characters have 22 points to spend to increase these beyond 4.
+1 stat point per level

15=skillpoints 
lvl 1, start with no skills
+1 skill point per point in intelligence beyond 4
+1 skill point per level

The knows_tracker_npc is a set skill/stat table that is used to set their skills/stats every time you start a new game. your three choices for companions include and the skills they grant:
knows_tracker_npc:knows_riding_2|knows_trade_3|knows_inventory_management_3
knows_warrior_npc:knows_weapon_master_2|knows_ironflesh_1|knows_athletics_1|knows_power_strike_2|knows_riding_2|knows_shield_1|knows_inventory_management_2
knows_merchant_npc:knows_weapon_master_1|knows_athletics_2|knows_spotting_2|knows_pathfinding_2|knows_tracking_2|knows_ironflesh_1|knows_inventory_management_2

That's pretty self explanatory as well.
Now we come to the skills:
knows_power_throw_3|knows_athletics_2|knows_power_strike_1,

you can find the other skills in module_skills.py.
ZefQcCc.png


you can change these to whatever you want, as long as they are in the right format and are real skills, and you can probably have as many as you want, just separate them with a ( | ).

underneath the skills, is the companions face:
0x0000000f000015c836db6db6db6db6db00000000001db6db0000000000000000

the crazy string of numbers, remember the one that showed up when you were designing the characters face after you press ctrl+e?
Well now all you have to do is click on the box the numbers were in and it is copied to your clip board, so highlight the copy of klethi's face and paste the one you designed over it.

Now the companion is "designed"

Step 3: module_scripts.py
now we do the same thing for finding klethi/npc16 as we did in troops.py, ctrl+f and search for npc16, but the first thing it will find is borcha, but he is companion #1 so you can scroll down or keep ctrl+f-ing.

When you get to klethi, copy her whole thing, with some of the spaces below it:
Code:
        (troop_set_slot, "trp_npc16", slot_troop_morality_type, tmt_aristocratic), #klethi
        (troop_set_slot, "trp_npc16", slot_troop_morality_value, 4),
        (troop_set_slot, "trp_npc16", slot_troop_2ary_morality_type, tmt_humanitarian),
        (troop_set_slot, "trp_npc16", slot_troop_2ary_morality_value, -1),
        (troop_set_slot, "trp_npc16", slot_troop_personalityclash_object, "trp_npc15"), #klethi
        (troop_set_slot, "trp_npc16", slot_troop_personalityclash2_object, "trp_npc1"), #klethi - borcha
        (troop_set_slot, "trp_npc16", slot_troop_personalitymatch_object, "trp_npc7"),  #deshavi - klethi
        (troop_set_slot, "trp_npc16", slot_troop_home, "p_village_20"), #Uslum
        (troop_set_slot, "trp_npc16", slot_troop_payment_request, 200),
		(troop_set_slot, "trp_npc16", slot_troop_kingsupport_argument, argument_lords),
		(troop_set_slot, "trp_npc16", slot_troop_kingsupport_opponent, "trp_npc12"), #nizar
 		(troop_set_slot, "trp_npc16", slot_troop_town_with_contacts, "p_town_9"), #khudan
		(troop_set_slot, "trp_npc16", slot_lord_reputation_type, lrep_roguish), #
LGa8oKi.png


and again, paste it right underneath her entry, and change all the trp_npc16 to trp_npc17. a quick way to do this is change the first one double click it, which will select only trp_npc17, copy it, then double click the trp_npc16 below it and paste, repeat.

The first two things we can edit about our new companion is their two morality types and values, companions can also only have one morality if you choose, (look at nizar for an example).
This post best explains the morality types:
http://forums.taleworlds.com/index.php/topic,113974.msg2748380.html#msg2748380
and this post seems to kinda explain the morality values:
http://forums.taleworlds.com/index.php/topic,108837.msg2654420.html#msg2654420

Although neither of them really explain clearly how they both work. And I'm still murky on getting them right.

Next we get to their personality clashes and personality matches, you can see klethi dislikes artimenner and borcha, while liking deshavi.

You can change these to other trp_npcs or make your companion have their own rivals/friends from other new companions you make. If you don't want your companion to interact with anyone, you can set these fields to trp_dranton there are other options available, but they dont make a difference, you have probably encountered dranton in the arena, he is a npc who will never be in your party, so your companions can't get mad at him.

Then comes the companions home, when you get near their home, in klethi's case uslum, they will tell you about it based on whats written in module_strings.py (which we will get to in the next part)
Ashmond said:
You should check the module_parties.py It has a list of all towns, castles and villages.

Now their payment_request, klethi's is 200, which means she wants 200 denars when you recruit her in a tavern, you can change this to whatever you want your new companion to cost or you can set it to 0 if you want them to be free, like jeremus.

kingsupport_argument, is how you make your claim to throne, keeping consistent with these choices affects how other NPC lords view your claim and whether they'll switch sides to you or not.

kingsupport_opponent, is the npc who pops up and says "i heard you sent so-and-so off to blah blah blah... i dont approve"

town_with_contacts, is where they go when you ask them if they have any useful connections, and they bring back intel.

lord_reputation_type, is how they act when they are lords. This excerpt best explains the different reputation types:
stolen from: a singleplayer manual
Companions noble personality's (by SPD_Phoenix) and (Peter Ebbesen)

- Rolf: cunning.
- Baheshtur: cunning.
- Firentis: upstanding.
- Matheld: martial.
- Alayen: martial.
- Lezalit: selfrighteous.

Martial: My sword is at the disposal of my rightful liege, so long as he upholds his duty to me.

Quarrelsome: Bah. They're all a bunch of bastards. I try to make sure that the ones who wrong me learn to regret it.

Pitiless: Men will always try to cheat others of their rightful due. In this faithless world, each must remain vigilant of his own rights.

Cunning: Well, it's a harsh world, and it is our lot to face harsh choices. Sometimes one must serve a tyrant to keep the peace, but sometimes a bit of rebellion keeps the kings honest. Circumstance is all.

Sadistic: My philosophy is simple: it is better to be the wolf than the lamb.

Goodnatured: Well, you should keep faith with your promises, and not do injustice to others. Sometimes it's hard to balance those. Stick with people you trust, I think, and it's hard to go far wrong.

Upstanding: Kingship and lordship have been instituted to keep the peace and prevent the war of all against all, yet that must not blind us to the possibility of injustice.

Roguish: Hmm.. I guess I'm thinking that it's good to be a lord.

Benefactor: A good ruler makes sure all are treated justly. Personally, I intend to use my authority to better the lot of those who live in my demesne.

Custodian: A good ruler creates the proper conditions for people to prosper. Personally, I intend to use my wealth to create more wealth, for myself and for the common benefit.

Now this is the last thing but its very important we do this before going onto the next part. A little under your new companion is this line:
Code:
        (store_sub, "$number_of_npc_slots", slot_troop_strings_end, slot_troospoilertro),

        (try_for_range, ":npc", companions_begin, companions_end),


            (try_for_range, ":slot_addition", 0, "$number_of_npc_slots"),
                (store_add, ":slot", ":slot_addition", slot_troop_intro),

                (store_mul, ":string_addition", ":slot_addition", [b]16[/b]),
change the 16 to a 17 and we're done.

now save and close scripts.py and were onto the second to last part.

Step 4: strings.py, or the hard part


use ctrl+f on npc16 takes us to the start of what your new companion says when you talk to them. scroll down to "npc16_intro" copy it, paste it below it, change 16 to 17, and change what klethi says.
8tmEgXW.png


then scroll down to "npc16_intro_response_1", this is what YOU the player say as an option when you meet her, "npc16_intro_response_2" is what you say when you dont want to talk to them. copy,paste,change.

You can see what each line is for by reading what the other companions are saying.

you have to do keep doing this for EVERY SINGLE LINE until you get to "npc16_turn_against", this is the last line you have to copy,paste and change.

save and close strings.py.

Step 5: build_module.bat and meeting your new companion

Now that that is over, double click on build_module.bat and let it run until it says:
Script processing has ended.
Press any key to exit. . .
IndaJIO.png


if you saw any "errors" come up like:
NameError: name 'knows_weapon_master_11' is not defined
then its because you did something like set weapon master to 11 which you cant do.

Because I figured it would be useful, I've gone ahead and compiled a little database containing the most common errors you're likely to encounter when building the Python code into a working mod, and their meanings.

Error:
SyntaxError: invalid syntax
Meaning:
Missing a bracket, comma or quotation mark -- [], (), , or "" -- OR you have too many of them.

Error:
TypeError: list indices must be integers
Meaning:
Missing a comma/too many brackets.

Error:
ERROR: INPUT TOKEN NOT FOUND: <name>
NameError: global name 'cause_error' is not defined
Meaning:
You have a starting dialog-state -- example, [trp_constable_hareck,"constable_hareck_introduce_1", -- that isn't being led to by an ending dialog-state -- example, "close_window",[]],

Error:
ERROR: INPUT TOKEN NOT FOUND: <empty>
NameError: global name 'cause_error' is not defined
Meaning:
You have an empty starting dialog-state -- example, [trp_constable_hareck,"constable_hareck_introduce_1",

Error:
NameError: name '<something>' is not defined
Meaning:
Missing a prefix such as trp_, itm_ or mnu_ OR missing a name OR misspelled a name.

Error:
IndexError: tuple index out of range
Meaning:
Nebulous. If you're modding module_mission_templates.py, look for undefined alter flags and undefined AI flags, these are the most common source.

Error:
TypeError: int argument required
Meaning:
Missing an integer such as a mission-template flag. You can find out which calls are integers by looking at Armagan's documentation at the beginning of each module file, (int) calls being integers.

Error:
IndexError: list index out of range
Meaning:
There's an error in one of your list calls -- a list is anything between brackets.

Error:
Error: Unable to find object:<name>
ERROR: Illegal Identifier:<name>
Meaning:
The object you're trying to call does not yet exist OR there is a misspelling in the name.

That's all the ones I was able to produce reliably on short notice. Hope it helps!

Hydraulically,
Winter


Now start up warband, select your copy of native module from the drop-down list, create a character, and start going to all the taverns (probably with cheats enables and ctrl+left click) and eventually you will find your new companion in one of the taverns.

Now you just have to repeat this process and eventually you will have 45 76 companions like me :oops:

("npc1_intro", "Ho there, traveller. You wouldn't by chance be in the market for a tracker, would you?"),
("npc2_intro", "Hello. Would you be so kind as to have a cup with me? I'm down to my last five denars and I'd rather not drink alone."),
("npc3_intro", "Good day to you!"),
("npc4_intro", "Greetings. I am Rolf, son of Rolf, of the most ancient and puissant House of Rolf."),
("npc5_intro", "Greetings, traveller. Would you join me for a drink?"),
("npc6_intro", "I am lost... Lost..."),
("npc7_intro", "Yes? Keep your distance, by the way."),
("npc8_intro", "What do you want?"),
("npc9_intro", "You there, good {man/woman}, be so kind as to fetch me another drink, eh?"),
("npc10_intro", "Greetings there, {Brother/Sister}! Here's to the doom and downfall of all high-born lords and ladies!"),
("npc11_intro", "Hello there, {laddie/lassie}. Have a drink on me."),
("npc12_intro", "Greetings, fellow traveller. Perhaps you can help me."),
("npc13_intro", "Greetings, traveller. I am Nizar. No doubt you will have heard of me."),
("npc14_intro", "Yes? What is it you wish?"),
("npc15_intro", "Oh! Say, friend, are you by chance heading out of town anytime soon?"),
("npc16_intro", "Hello there. From the look of you, I'd say you're expecting to get into some fights in the near future. Are you by any chance looking for some help?"),
("npc17_intro", "Greetings, I am known as Balbanes."),
("npc18_intro", "Greetings, I am known as Zacahary."),
("npc19_intro", "Greetings, I am known as Ruslan."),
("npc20_intro", "Greetings, I am known as Porziano."),
("npc21_intro", "Greetings, I am known as Bataar."),
("npc22_intro", "Greetings, I am known as Matin."),
("npc23_intro", "Greetings, I am known as Einar."),
("npc24_intro", "Greetings, I am known as Boadicea."),
("npc25_intro", "Greetings, I am known as Karn."),
("npc26_intro", "Greetings, I am known as Argan."),
("npc27_intro", "Greetings, I am known as Ostanes."),
("npc28_intro", "Greetings, I am known as Cordelia."),
("npc29_intro", "Greetings, I am known as Blanchefleur."),
("npc30_intro", "Greetings, I am known as Artemisia."),
("npc31_intro", "Greetings, I am known as Camilla."),
("npc32_intro", "Greetings, I am known as Agustina."),
("npc33_intro", "My, my {lord/lady}! It is you! The rightful ruler of Calradia!."),
("npc34_intro", "Hail and well met, I am Edgardo."),
("npc35_intro", "Hail and well met, I am Misses Morana."),
("npc36_intro", "Hail and well met, I am Eira."),
("npc37_intro", "Hail and well met, I am Duilio."),
("npc38_intro", "Hail and well met, I am Qorin."),
("npc39_intro", "Hail and well met, I am Yareb."),
("npc40_intro", "Hail and well met, I am Miura Anjin."),
("npc41_intro", "Hail and well met, I am Xin Tian."),
("npc42_intro", "Hail and well met, I am Xin Rong."),
("npc43_intro", "Hail and well met, I am Xin Jia."),
("npc44_intro", "Hail and well met, I am Bhagwandas."),
("npc45_intro", "Hail and well met, I am Windich."),

Advanced Companion Changes:
Giving Companions Custom Lord Titles like "Tribune Bunduk"
Credits: Somebody (his actual forum name not me being stupid)
To give a companion a custom title when they are made a lord like bunduk becomes tribune bunduk, do the following:
1. Edit module_dialogs.py
2. Use ctrl+f and look for "tribune" (no quotes)
3. Add this under the "tribune" line, dont delete/overwrite any lines :
(else_try),
(eq, "$g_talk_troop", "trp_npc##"),
(str_store_string, s14, "str_'newtitle'_s12"),
4. Change the ## to the npc's number in module_troops (i.e. trp_npc17)
5. If you want more than one npc to have that same title, change it to this:
(else_try),
(this_or_next|eq, "$g_talk_troop", "trp_npc##"),
(this_or_next|eq, "$g_talk_troop", "trp_npc##"),
(eq, "$g_talk_troop", "trp_npc##"),
(str_store_string, s14, "str_newtitle_s12"),
6. Remove the middle "this or next" line if you only want 2, copy and paste it if you want 3+ just make sure it ends with "eq"
7. Now edit module_strings.py
8. use ctrl+f and search for tribune 3 times (first two times go to bunduk talking about how he wants to be a tribune)
9. under the tribune_s12 line paste this, without deleting or overwriting any lines:
("newtitle_s12", "newtitle {s12}"),
10. change the "newtitles" i mentioned previously to whatever you want your lords titles to be (i.e. duke), save the .py files, run build_module and your done.
Example: Finished Code said:
(else_try),
(eq, "$g_talk_troop", "trp_npc17"),
(str_store_string, s14, "str_duke'_s12"),
("duke_s12", "Duke {s12}"),