• Please note that we've updated the Mount & Blade II: Bannerlord save file system which requires you to take certain steps in order for your save files to be compatible with e1.7.1 and any later updates. You can find the instructions here.

SP Tutorial Module System [OSP][Code] New Building for Towns: Orphanages (Combo School & Mill)

Users who are viewing this thread

Malik Faris

Squire
M&BWBWF&SNW
I wasn't sure if I should make a full tutorial about adding buildings maybe I will, but this at least shows how you can add new buildings. I can't believe I figured this out on my own.
Anyways:

Adding Orphanages to Towns
By Malik Faris​

Modules you'll need:
  • Scripts
  • Simple Triggers
  • Constants
  • Game Menus

Disclaimer (and maybe someone can help me fix): This won't show up under "improvements in town" when you go to check, but it does actually function.

First, search for  #script_get_improvement_details and add my #Malik code at the bottom of this script like I've shown in the code below.
I'll explain as best I can what the code here does. Slots like slot_center_has_manor are stored in module_constants and are used to track a value, in this case a yes or no value of whether the building exists.
The store_string is what shows up when the game checks if your town has the improvement, and the 2nd one is the description it gives when you consider building it.
reg0 is the cost of the building, since mine does more than just a school, I bumped up the cost.
Code:
  #script_get_improvement_details
  # INPUT: arg1 = improvement
  # OUTPUT: reg0 = base_cost
  ("get_improvement_details",
    [(store_script_param, ":improvement_no", 1),
     (try_begin),
       (eq, ":improvement_no", slot_center_has_manor),
       (str_store_string, s0, "@Manor"),
       (str_store_string, s1, "@A manor lets you rest at the village and pay your troops half wages while you rest."),
       (assign, reg0, 8000),
     (else_try),
       (eq, ":improvement_no", slot_center_has_fish_pond),
       (str_store_string, s0, "@Mill"),
       (str_store_string, s1, "@A mill increases village prosperity by 5%."),
       (assign, reg0, 6000),
     (else_try),
       (eq, ":improvement_no", slot_center_has_watch_tower),
       (str_store_string, s0, "@Watch Tower"),
       (str_store_string, s1, "@A watch tower lets the villagers raise alarm earlier. The time it takes for enemies to loot the village increases by 50%."),
       (assign, reg0, 5000),
     (else_try),
       (eq, ":improvement_no", slot_center_has_school),
       (str_store_string, s0, "@School"),
       (str_store_string, s1, "@A school increases the loyality of the villagers to you by +1 every month."),
       (assign, reg0, 9000),
     (else_try),
       (eq, ":improvement_no", slot_center_has_messenger_post),
       (str_store_string, s0, "@Messenger Post"),
       (str_store_string, s1, "@A messenger post lets the inhabitants send you a message whenever enemies are nearby, even if you are far away from here."),
       (assign, reg0, 4000),
     (else_try),
       (eq, ":improvement_no", slot_center_has_prisoner_tower),
       (str_store_string, s0, "@Prison Tower"),
       (str_store_string, s1, "@A prison tower reduces the chance of captives held here running away successfully."),
       (assign, reg0, 7000),
#Malik Buildings
     (else_try),
       (eq, ":improvement_no", slot_center_has_orphanage),
       (str_store_string, s0, "@Orphanage"),
       (str_store_string, s1, "@An orphanage increases the loyalty of the townspeople to you by +1 every month, and increases town prosperity by 5%."),
       (assign, reg0, 11000),	   
#Malik Buildings End	   
     (try_end),
     ]),
loyalty is spelled wrong, tut tut taleworlds


There's two parts to this code, so look for the break. Search for # Checking center upgrades    and then  # Village upgrade triggers
First part was pretty easy, I just told the existing script to also check the new orphanage slot we created for the already working mill script (which was originally a fish pond)
Second part just involves changes the village references to centers, as that's what towns are.
Code:
  # Checking center upgrades
  (12,
   [(try_for_range, ":center_no", centers_begin, centers_end),
      (party_get_slot, ":cur_improvement", ":center_no", slot_center_current_improvement),
      (gt, ":cur_improvement", 0),
      (party_get_slot, ":cur_improvement_end_time", ":center_no", slot_center_improvement_end_hour),
      (store_current_hours, ":cur_hours"),
      (ge, ":cur_hours", ":cur_improvement_end_time"),
      (party_set_slot, ":center_no", ":cur_improvement", 1),
      (party_set_slot, ":center_no", slot_center_current_improvement, 0),
      (call_script, "script_get_improvement_details", ":cur_improvement"),
      (try_begin),
        (party_slot_eq, ":center_no", slot_town_lord, "trp_player"),
        (str_store_party_name, s4, ":center_no"),
        (display_log_message, "@Building of {s0} in {s4} has been completed."),
      (try_end),
#Malik Buildings
      (try_begin),
        (is_between, ":center_no", towns_begin, villages_end),
        (this_or_next|eq, ":cur_improvement", slot_center_has_fish_pond),
		(eq, ":cur_improvement", slot_center_has_orphanage),
        (call_script, "script_change_center_prosperity", ":center_no", 5),
#Malik Buildings End	
      (try_end),
    (try_end),
    ]),


NEXT PART


# Village upgrade triggers

# School
  (30 * 24,
   [(try_for_range, ":cur_village", villages_begin, villages_end),
      (party_slot_eq, ":cur_village", slot_town_lord, "trp_player"),
      (party_slot_eq, ":cur_village", slot_center_has_school, 1),
      (party_get_slot, ":cur_relation", ":cur_village", slot_center_player_relation),
      (val_add, ":cur_relation", 1),
      (val_min, ":cur_relation", 100),
      (party_set_slot, ":cur_village", slot_center_player_relation, ":cur_relation"),
    (try_end),
    ]),

#Malik Buildings
#Orphanage
  (30 * 24,
   [(try_for_range, ":cur_center", towns_begin, towns_end),
      (party_slot_eq, ":cur_center", slot_town_lord, "trp_player"),
      (party_slot_eq, ":cur_center", slot_center_has_orphanage, 1),
      (party_get_slot, ":cur_relation", ":cur_center", slot_center_player_relation),
      (val_add, ":cur_relation", 1),
      (val_min, ":cur_relation", 100),
      (party_set_slot, ":cur_center", slot_center_player_relation, ":cur_relation"),
    (try_end),
    ]),	
#Malik Buildings End	
# Quest triggers:

# Remaining days text update


This was a bit tricky as the start and ends for where it looks for these slots are kinda specific, and didn't leave any open numbers between them. I did see that nothing after 126 was being used and since this thing looks at it self to decide where things end, I just had to tack it onto the end with a unique number and chose 127 because it was available.
Code:
slot_center_improvement_end_hour  = 125

slot_party_last_traded_center     = 126 



slot_center_has_manor            = 130 #village
slot_center_has_fish_pond        = 131 #village
slot_center_has_watch_tower      = 132 #village
slot_center_has_school           = 133 #village
slot_center_has_messenger_post   = 134 #town, castle, village
slot_center_has_prisoner_tower   = 135 #town, castle
slot_center_has_orphanage		 = 127 #Malik Buildings

village_improvements_begin = slot_center_has_manor
village_improvements_end          = 135

walled_center_improvements_begin = slot_center_has_messenger_post
walled_center_improvements_end               = 136

slot_center_player_enterprise     				  = 137 #noted with the item produced


Here we see all the various improvements, because I just wanted to copy what schools already do to towns, it was fairly simple.
This is just what shows up in the menus when you go to build an improvement and checks whether you built it already or not.
Code:
    [
      ("center_build_manor",[(eq, reg6, 0),
                             (party_slot_eq, "$g_encountered_party", slot_party_type, spt_village),
                             (party_slot_eq, "$g_encountered_party", slot_center_has_manor, 0),
                                  ],
       "Build a manor.",[(assign, "$g_improvement_type", slot_center_has_manor),
                         (jump_to_menu, "mnu_center_improve"),]),
      ("center_build_fish_pond",[(eq, reg6, 0),
                                 (party_slot_eq, "$g_encountered_party", slot_party_type, spt_village),
                                 (party_slot_eq, "$g_encountered_party", slot_center_has_fish_pond, 0),
                                  ],
       "Build a mill.",[(assign, "$g_improvement_type", slot_center_has_fish_pond),
                             (jump_to_menu, "mnu_center_improve"),]),
      ("center_build_watch_tower",[(eq, reg6, 0),
                                   (party_slot_eq, "$g_encountered_party", slot_party_type, spt_village),
                                   (party_slot_eq, "$g_encountered_party", slot_center_has_watch_tower, 0),
                                  ],
       "Build a watch tower.",[(assign, "$g_improvement_type", slot_center_has_watch_tower),
                               (jump_to_menu, "mnu_center_improve"),]),
      ("center_build_school",[(eq, reg6, 0),
                              (party_slot_eq, "$g_encountered_party", slot_party_type, spt_village),
                              (party_slot_eq, "$g_encountered_party", slot_center_has_school, 0),
                                  ],
       "Build a school.",[(assign, "$g_improvement_type", slot_center_has_school),
                          (jump_to_menu, "mnu_center_improve"),]),
#Malik Buildings						  
      ("center_build_orphanage",[(eq, reg6, 0),
                              (party_slot_eq, "$g_encountered_party", slot_party_type, spt_town),
                              (party_slot_eq, "$g_encountered_party", slot_center_has_orphanage, 0),
                                  ],
       "Build a orphanage.",[(assign, "$g_improvement_type", slot_center_has_orphanage),
                          (jump_to_menu, "mnu_center_improve"),]),	
#Malik Buildings End						  
      ("center_build_messenger_post",[(eq, reg6, 0),
                                      (party_slot_eq, "$g_encountered_party", slot_center_has_messenger_post, 0),
                                       ],
       "Build a messenger post.",[(assign, "$g_improvement_type", slot_center_has_messenger_post),
                                  (jump_to_menu, "mnu_center_improve"),]),
      ("center_build_prisoner_tower",[(eq, reg6, 0),
                                      (this_or_next|party_slot_eq, "$g_encountered_party", slot_party_type, spt_town),
                                      (party_slot_eq, "$g_encountered_party", slot_party_type, spt_castle),
                                      (party_slot_eq, "$g_encountered_party", slot_center_has_prisoner_tower, 0),
                                       ],
       "Build a prisoner tower.",[(assign, "$g_improvement_type", slot_center_has_prisoner_tower),
                                  (jump_to_menu, "mnu_center_improve"),]),
                           
      ("go_back_dot",[],"Go back.",[(jump_to_menu, "$g_next_menu")]),
    ],
 

Somebody

Code Pope
Baron
WBWF&S
I recommend combining the triggers like so
Code:
  (30 * 24,
   [(try_for_range, ":cur_village", villages_begin, villages_end),
      (party_slot_eq, ":cur_village", slot_town_lord, "trp_player"),
      (party_get_slot, ":cur_relation", ":cur_village", slot_center_player_relation),
      (try_begin),
        (party_slot_eq, ":cur_village", slot_center_has_school, 1),
        (val_add, ":cur_relation", 1),
      (try_end),
      (try_begin),
        (party_slot_eq, ":cur_village", slot_center_has_orphanage, 1),
        (val_add, ":cur_relation", 1),
      (try_end),
      (val_min, ":cur_relation", 100),
      (party_set_slot, ":cur_village", slot_center_player_relation, ":cur_relation"),
    (try_end),
    ]),

Also, the +5 prosperity probably won't work unless you break it into two lines.
Code:
(this_or_next|eq, ":cur_improvement", slot_center_has_fish_pond),
(eq, ":cur_improvement", slot_center_has_orphanage),
 

Malik Faris

Squire
M&BWBWF&SNW
Thanks for the code correction, Prosperity is hard to check as is, and the compiler didn't complain about it so i assumed it understood.

I kinda wanna keep the other trigger separate though, in case you want it to occur at different times, also I'm pretty sure towns aren't villages and thus require different codes.

Also this made me see that it wouldn't have worked anyways because it was still only looking at the range of villages to apply the script, so I increased it to include towns (and castles, as a result) as well.

And Somebody, maybe you can explain to me if you know how the whole script for prosperity is working, I'm wondering if it increases prosperity by 5 every 12 ingame hours, or only checks every 12 ingame hours and increases it once through the games lifetime?

Code:
  # Checking center upgrades
  (12,
   [(try_for_range, ":center_no", centers_begin, centers_end),
      (party_get_slot, ":cur_improvement", ":center_no", slot_center_current_improvement),
      (gt, ":cur_improvement", 0),
      (party_get_slot, ":cur_improvement_end_time", ":center_no", slot_center_improvement_end_hour),
      (store_current_hours, ":cur_hours"),
      (ge, ":cur_hours", ":cur_improvement_end_time"),
      (party_set_slot, ":center_no", ":cur_improvement", 1),
      (party_set_slot, ":center_no", slot_center_current_improvement, 0),
      (call_script, "script_get_improvement_details", ":cur_improvement"),
      (try_begin),
        (party_slot_eq, ":center_no", slot_town_lord, "trp_player"),
        (str_store_party_name, s4, ":center_no"),
        (display_log_message, "@Building of {s0} in {s4} has been completed."),
      (try_end),
#Malik Buildings
      (try_begin),
        (is_between, ":center_no", towns_begin, villages_end),
        (this_or_next|eq, ":cur_improvement", slot_center_has_fish_pond),
		(eq, ":cur_improvement", slot_center_has_orphanage),
        (call_script, "script_change_center_prosperity", ":center_no", 5),
#Malik Buildings End		
      (try_end),
    (try_end),
    ]),
 

Somebody

Code Pope
Baron
WBWF&S
Checks every 12 hours for building progression, and if it completes prosperity is increased once for the center.
 
The crowded slot spot taleworlds decided to put center improvements in is quite a pain when you're adding new ones.

Be aware of the two pairs of "improvements_begin/end" assigned below in moduke_constants.py. They're probably used in generating the list of improvements and your improvement is outside it, so it's getting ignored. If you're just adding the one building, shift all the slots down by one so you can fit the new improvement at 135. However it might be an idea to shift them all down past slot 380, which should give you plenty of breathing space.

Also always, always keep slots in order. Among other things it makes shifting slots around a lot easier. It also prevents confusion between variables (slot_whatever) and constants (svs_whatever, slto_whatever, somethingthatisn'tslot_whatever)
 
Top Bottom