OSP Kit SP Recruiter Kit - Version 1.30 (UPDATED 20.05.2010)

Users who are viewing this thread

hessuu

Sergeant Knight
Recruiter Kit Version 1.30

-- Download links: --
Warband:
http://www.mbrepository.com/download.php?id=1931&f=recruiter_mod_1.30.exe
Original Mount & Blade:
http://www.mbrepository.com/download.php?id=1469&f=recruiter_mod_1.20.exe

General Mod Info:
With this cool modification you can hire recruiters to recruit fresh volunteers to your garrisons. After you have chosen the amount of recruits you need and paid the expenses, a recruiter party will appear on the map. The party will then begin to gather volunteers from villages. This is especially useful for all you "bandit kings" out there, as it allows you to effectively garrison all your centers while you fight your numerous adversaries!

Screenshots showing some recruiters:



 

Current version info:
- Recruiters can be hired from castles and towns. Recruiters can not be sent during a siege. They can return during a siege, however, if they can get past the siegers.
- Recruiters can only recruit from villages.
- You are asked if you would like to have your recruits from a specific faction, or if you'd just like to get some troops of any kind as fast as possible.
- You can specify the amount of recruits the recruiter collects by choosing from preset options 5, 10, 20, 30, 40 and 50. After the recruiter has collected the amount you ordered, he brings the recruits back to the town/castle you hired him from and adds them to the garrison.
- After the recruiter has been sent on his mission, you can go and tell him to change the faction he is recruiting from.
- You can hire 2 recruiters from a castle and 4 recruiters from a town at a time.
- You must pay 20 coins for each recruit (that's double the normal price). 100% advance payment.

Adding recruiters to your module:
Warband:
Download the source code and read the README.txt here:
http://www.mbrepository.com/file.php?id=1932

Original Mount & Blade:
Here are the scripts and info about their placement in the files.
module_constants
- These can be placed anywhere in the file.
- Make sure your mod doesn't conflict with party slots 220, 221, 222 and 224, and spt 12. If this is the case however, you can change the numbers to something non-reserved.
Code:
### RECRUITER KIT BEGIN
slot_party_recruiter_needed_recruits = 220           # Amount of recruits the employer ordered.
slot_party_recruiter_origin = 221                    # Walled center from where the recruiter was hired.
slot_village_reserved_by_recruiter = 222             # This prevents recruiters from going to villages targeted by other recruiters.
slot_party_recruiter_needed_recruits_faction = 224   # Alkhadias Master, you forgot this one from the PM you sent me
spt_recruiter     = 12
## RECRUITER KIT END


module_dialogs
- Put this at the top of the dialogs list.
- There's a funny debug-command in there that was actually needed in the development.
Code:
#########################################################################################################
## Recruiter kit begin
#########################################################################################################
   [trp_recruiter, "start", [], "Hello {reg65?madame:sir}. If it's ok to you, I would like to get on with my assignment.", "recruiter_talk",[]],
   [trp_recruiter|plyr, "recruiter_talk", [], "Ok, keep going.", "close_window",[(assign, "$g_leave_encounter",1)]],
   [trp_recruiter|plyr, "recruiter_talk", [], "I want you to recruit different troops.", "recruiter_talk_2",[]],
   [trp_recruiter|plyr, "recruiter_talk", [(eq, "$cheat_mode",1)], "eat **** and die", "recruiter_eat_****_and_die", []],
   [trp_recruiter, "recruiter_eat_****_and_die", [], "Yes {reg65?madame:sir}.", "close_window",[(remove_member_from_party, "trp_recruiter", "$g_encountered_party"),
                                                                        (assign, "$g_leave_encounter",1), ]],
   
   [trp_recruiter, "recruiter_talk_2", [
   (party_get_slot, reg1, "$g_encountered_party", slot_party_recruiter_needed_recruits),
   (party_get_slot, ":recruit_faction", "$g_encountered_party", slot_party_recruiter_needed_recruits_faction),
   (try_begin),
   (eq, ":recruit_faction",-1),
   (str_store_string, s1, "@any kind of"),
   (else_try),
   (eq, ":recruit_faction", "fac_kingdom_1"),
   (str_store_string, s1, "@Swadian"),
   (else_try),
   (eq, ":recruit_faction", "fac_kingdom_2"),
   (str_store_string, s1, "@Vaegir"),
   (else_try),
   (eq, ":recruit_faction", "fac_kingdom_3"),
   (str_store_string, s1, "@Khergit"),
   (else_try),
   (eq, ":recruit_faction", "fac_kingdom_4"),
   (str_store_string, s1, "@Nord"),
   (else_try),
   (eq, ":recruit_faction", "fac_kingdom_5"),
   (str_store_string, s1, "@Rhodok"),
   (try_end),
   ], "My current task is to recruit {reg1} {s1} troops for you. Should I recruit different soldiers from now on?", "recruiter_talk_3",[]],
   [trp_recruiter|plyr, "recruiter_talk_3", [], "No, keep going.", "close_window",[(assign, "$g_leave_encounter",1)]],
   [trp_recruiter|plyr, "recruiter_talk_3", [], "Recruit Swadians now.", "recruiter_talk_4",[(assign,"$temp","fac_kingdom_1")]],
   [trp_recruiter|plyr, "recruiter_talk_3", [], "Recruit Vaegirs now.", "recruiter_talk_4",[(assign,"$temp","fac_kingdom_2")]],
   [trp_recruiter|plyr, "recruiter_talk_3", [], "Recruit Khergits now.", "recruiter_talk_4",[(assign,"$temp","fac_kingdom_3")]],
   [trp_recruiter|plyr, "recruiter_talk_3", [], "Recruit Nords now.", "recruiter_talk_4",[(assign,"$temp","fac_kingdom_4")]],
   [trp_recruiter|plyr, "recruiter_talk_3", [], "Recruit Rhodoks now.", "recruiter_talk_4",[(assign,"$temp","fac_kingdom_5")]],
   [trp_recruiter|plyr, "recruiter_talk_3", [], "Recruit any troops now.", "recruiter_talk_4",[(assign,"$temp",-1)]],
 
   [trp_recruiter, "recruiter_talk_4", [(party_set_slot, "$g_encountered_party", slot_party_recruiter_needed_recruits_faction, "$temp")], "Sure {reg65?madame:sir}. I will. Anything else you want?", "recruiter_talk",[]],
##########################################################################################################
## Recruiter kit end
##########################################################################################################

module_game_menus
- This is the town/castle menu option. I placed it under the "town_leave", but you can put it anywhere within the menu. The town_leave is included below to show you how should it look like. Use your text editor's search function to find the correct spot.
Code:
("town_leave",[],"Leave...",[
            (assign, "$g_permitted_to_center",0),
            (change_screen_return,0),
          ],"Leave Area."),
############################################################################################################################
## recruiter kit begin
############################################################################################################################
       
    ("hire_a_recruiter",
     [(neg|party_slot_eq, "$current_town", slot_village_state, svs_under_siege),
        (party_slot_eq,"$current_town", slot_town_lord, "trp_player"),
      (assign, ":y", 0),
      (try_for_parties, ":party_no"),
         (party_slot_eq,":party_no", slot_party_type, spt_recruiter),
         (party_slot_eq,":party_no", slot_party_recruiter_origin, "$current_town"),
         (val_add, ":y", 1),
      (try_end),
      (assign, reg2, ":y"),
      (try_begin),
            (party_slot_eq, "$current_town", slot_party_type, spt_castle),
            (assign, reg0, 0),
        (try_end),
      ],
        "Hire a recruiter. ({reg2}/{reg0?4:2} currently hired.)",
         [
             (jump_to_menu, "mnu_recruiter_payment"),
             ]),

############################################################################################################################
## recruiter kit end
############################################################################################################################

- Put this at the bottom of the file.
Code:
 ############################################################################################################################
## recruiter kit begin
############################################################################################################################

   ("recruiter_payment",0,
    "The recruiter will visit villages and recruit population to your forces. \
After he has collected the amount you ordered he returns to this {reg0?town:castle} and puts the recruits in the garrison. \
There's a limit for recruiters, which is 2 for castles and 4 for towns. \
What kind of recruits do you want?",
    "none",
   [
   (assign, ":recruiter_amount", 0),
 
   (try_begin),
      (party_slot_eq, "$current_town", slot_party_type, spt_town),
      (assign, ":max_recruiters", 4),
   (else_try),
      (assign, ":max_recruiters", 2),
   (try_end),
 
   (try_for_parties, ":party_no"),
      (party_slot_eq,":party_no", slot_party_type, spt_recruiter),
      (party_slot_eq, ":party_no", slot_party_recruiter_origin, "$current_town"),
      (val_add, ":recruiter_amount", 1),
   (try_end),
   (try_begin),
      (eq, ":recruiter_amount", ":max_recruiters"),
      (assign, "$recruiter_amount_check", 1),
   (else_try),
      (lt, ":recruiter_amount", ":max_recruiters"),
      (assign, "$recruiter_amount_check", 0),
   (else_try),
      (gt, ":recruiter_amount", ":max_recruiters"),
      (display_message, "@ERROR IN THE RECRUITER KIT GAME MENUS RECRUITER CALCULATION!",0xFF2222),
   (try_end),
 
   (try_begin),
        (party_slot_eq, "$current_town", slot_party_type, spt_castle),
      (assign, reg0, 0),
    (try_end),
   ],

    [("enough_recruiters",  [ (eq, "$recruiter_amount_check", 1)],
       "You have already hired the maximum amount of {reg0?4:2} recruiters from this {reg0?town:castle}.",[(jump_to_menu, "mnu_town")]),
     
   ("recruiter_faction_1",  [(eq, "$recruiter_amount_check", 0)],
         "Swadian",               [(assign,"$temp","fac_kingdom_1"),(jump_to_menu, "mnu_recruiter_payment_2")]),

   ("recruiter_faction_2", [(eq, "$recruiter_amount_check", 0)],
         "Vaegir",              [(assign,"$temp","fac_kingdom_2"),(jump_to_menu, "mnu_recruiter_payment_2")]),

   ("recruiter_faction_3", [(eq, "$recruiter_amount_check", 0)],
         "Khergit",              [(assign,"$temp","fac_kingdom_3"),(jump_to_menu, "mnu_recruiter_payment_2")]),

   ("recruiter_faction_4", [(eq, "$recruiter_amount_check", 0)],
         "Nord",              [(assign,"$temp","fac_kingdom_4"),(jump_to_menu, "mnu_recruiter_payment_2")]),

   ("recruiter_faction_5", [(eq, "$recruiter_amount_check", 0)],
         "Rhodok",              [(assign,"$temp","fac_kingdom_5"),(jump_to_menu, "mnu_recruiter_payment_2")]),
     
   ("recruiter_faction_6", [(eq, "$recruiter_amount_check", 0)],
         "Any troops",              [(assign,"$temp",-1), (jump_to_menu, "mnu_recruiter_payment_2")]),
     
  ("recruiter_option_cancel", [], "Go back.", [(jump_to_menu, "mnu_town")])]),

 
   ("recruiter_payment_2",0,
    "You must pay 20 denars for each recruit. How many recruits are you willing to pay for?",
    "none",
   [],

    [("recruiter_option_5",  [ (store_troop_gold,":gold","trp_player"), (ge,":gold",100), (eq, "$recruiter_amount_check", 0)],
         "5",               [ (call_script, "script_send_recruiter", 5, "$temp"), (jump_to_menu, "mnu_town")]),

   ("recruiter_option_10", [ (store_troop_gold,":gold","trp_player"), (ge,":gold",200), (eq, "$recruiter_amount_check", 0)],
         "10",              [ (call_script, "script_send_recruiter", 10, "$temp"), (jump_to_menu, "mnu_town")]),

   ("recruiter_option_20", [ (store_troop_gold,":gold","trp_player"), (ge,":gold",400), (eq, "$recruiter_amount_check", 0)],
         "20",              [ (call_script, "script_send_recruiter", 20, "$temp"), (jump_to_menu, "mnu_town")]),

   ("recruiter_option_30", [ (store_troop_gold,":gold","trp_player"), (ge,":gold",600), (eq, "$recruiter_amount_check", 0)],
         "30",              [ (call_script, "script_send_recruiter", 30, "$temp"), (jump_to_menu, "mnu_town")]),

   ("recruiter_option_40", [ (store_troop_gold,":gold","trp_player"), (ge,":gold",800), (eq, "$recruiter_amount_check", 0)],
         "40",              [ (call_script, "script_send_recruiter", 40, "$temp"), (jump_to_menu, "mnu_town")]),

   ("recruiter_option_50", [ (store_troop_gold,":gold","trp_player"), (ge,":gold",1000),(eq, "$recruiter_amount_check", 0)],
         "50",              [ (call_script, "script_send_recruiter", 50, "$temp"), (jump_to_menu, "mnu_town")]),
 
   ("recruiter_option_cancel", [], "Cancel.", [(jump_to_menu, "mnu_town")])]),

############################################################################################################################
## recruiter kit end
############################################################################################################################

module_party_templates
- This can be put anywhere after the hardwired templates.
Code:
 ("recruiter","Recruiter",icon_gray_knight|pf_show_faction,0,fac_neutral,merchant_personality,[(trp_recruiter,1,1)]),

module_scripts
- Put this at the bottom of the file.
Code:
############################################################################################################################
## recruiter kit begin
############################################################################################################################

("send_recruiter",
    [
    (store_script_param, ":number_of_recruits", 1),
#daedalus begin
   (store_script_param, ":faction_of_recruits", 2),
#daedalus end
   (assign, ":expenses", ":number_of_recruits"),
   (val_mul, ":expenses", 20),
   (troop_remove_gold, "trp_player", ":expenses"),
   (set_spawn_radius, 1),
    (spawn_around_party, "$current_town", "pt_recruiter"),
    (assign,":spawned_party",reg0),
    (party_set_ai_behavior, ":spawned_party", ai_bhvr_hold),
    (party_set_slot, ":spawned_party", slot_party_type, spt_recruiter),
    (party_set_slot, ":spawned_party", slot_party_recruiter_needed_recruits, ":number_of_recruits"),
   #daedalus begin
   (party_set_slot, ":spawned_party", slot_party_recruiter_needed_recruits_faction, ":faction_of_recruits"),
   #daedalus end
   (party_set_slot, ":spawned_party", slot_party_recruiter_origin, "$current_town"),
   (store_troop_faction, ":faction", "trp_player"),
   (party_set_faction, ":spawned_party", ":faction"),
    ]),

############################################################################################################################
## recruiter kit end
############################################################################################################################

- This is placed inside the script "game_event_simulate_battle".
- I included some of the original native code below to help you to find the correct spot. Copy/paste the stuff between "recruiter kit begin" and "recruiter kit end" to your module the same way as below.
Code:
(try_begin),
             (this_or_next|eq, ":new_attacker_strength", 0),
             (eq, ":new_defender_strength", 0),
             # Battle concluded! determine winner
          
             (try_begin),
               (eq, ":new_attacker_strength", 0),
               (eq, ":new_defender_strength", 0),
               (assign, ":root_winner_party", -1),
               (assign, ":root_defeated_party", -1),
               (assign, ":collective_casualties", -1),
             (else_try),
               (eq, ":new_attacker_strength", 0),
               (assign, ":root_winner_party",   ":root_defender_party"),
               (assign, ":root_defeated_party", ":root_attacker_party"),
               (assign, ":collective_casualties",    "p_collective_enemy"),
             (else_try),
               (assign, ":root_winner_party", ":root_attacker_party"),
               (assign, ":root_defeated_party",  ":root_defender_party"),
               (assign, ":collective_casualties",  "p_collective_ally"),
             (try_end),

############################################################################################################################
## Recruiter kit begin
############################################################################################################################
 # This little fella just shows a message when a recruiter is defeated.

         (try_begin),
            (party_slot_eq, ":root_defeated_party", slot_party_type, spt_recruiter),
            (party_get_slot, reg10, ":root_defeated_party", slot_party_recruiter_needed_recruits),
            (party_get_slot, ":party_origin", ":root_defeated_party", slot_party_recruiter_origin),
            (str_store_party_name_link, s13, ":party_origin"),
            (display_log_message, "@Your recruiter who was commissioned to recruit {reg10} recruits to {s13} has been defeated!", 0xFF0000),
         (try_end),

############################################################################################################################
## Recruiter kit end
############################################################################################################################              
             (try_begin),
               (ge, ":root_winner_party", 0),
               (call_script, "script_get_nonempty_party_in_group", ":root_winner_party"),
               (assign, ":nonempty_winner_party", reg0),
               (store_faction_of_party, ":faction_receiving_prisoners", ":nonempty_winner_party"),
               (store_faction_of_party, ":defeated_faction", ":root_defeated_party"),
             (else_try),
               (assign, ":nonempty_winner_party", -1),
             (try_end),

module_simple_triggers
- This is the most important script! I am pretty proud of it.  :grin:
- You should put this at the bottom of the file.
- NB! The last native's simple trigger in the file does not have a comma after it, so you have to add it yourself. You'll get an error when you try to build otherwise.
Code:
############################################################################################################################
## Recruiter kit begin
############################################################################################################################
## This trigger keeps the recruiters moving by assigning them targets.
 (0.5,
   [
   (try_for_parties, ":party_no"),
      (party_slot_eq,":party_no", slot_party_type, spt_recruiter),
      
      (party_get_slot, ":needed", ":party_no", slot_party_recruiter_needed_recruits),
      
      (party_get_num_companion_stacks, ":stacks", ":party_no"),
      (assign, ":destruction", 1),
      (assign, ":quit", 0),
      (try_for_range, ":stack_no", 0, ":stacks"),
         (party_stack_get_troop_id, ":troop_id", ":party_no", ":stack_no"),
         (eq, ":troop_id", "trp_recruiter"),
         (assign, ":destruction",0),
      (try_end),
      (try_begin),
         (party_get_battle_opponent, ":opponent", ":party_no"),
         (lt, ":opponent", 0),
         (eq, ":destruction", 1),
         (party_get_slot, ":party_origin", ":party_no", slot_party_recruiter_origin),
         (str_store_party_name_link, s13, ":party_origin"),
         (assign, reg10, ":needed"),
         (display_log_message, "@Your recruiter who was commissioned to recruit {reg10} recruits to {s13} has been defeated!", 0xFF0000),
         (remove_party, ":party_no"),
         (assign, ":quit", 1),
      (try_end),
      (eq, ":quit", 0),            
      
      (party_get_num_companions, ":amount", ":party_no"),
      (val_sub, ":amount", 1),   #the recruiter himself doesn't count.
      
   #daedalus begin
      (party_get_slot, ":recruit_faction", ":party_no", slot_party_recruiter_needed_recruits_faction),
   #daedalus end
      (lt, ":amount", ":needed"),  #If the recruiter has less troops than player ordered, new village will be set as target.
      (try_begin),
         #(get_party_ai_current_behavior, ":ai_bhvr", ":party_no"),
         #(eq, ":ai_bhvr", ai_bhvr_hold),
         (get_party_ai_object, ":previous_target", ":party_no"),
         (get_party_ai_behavior, ":previous_behavior", ":party_no"),
         (try_begin),
            (neq, ":previous_behavior", ai_bhvr_hold),
            (neq, ":previous_target", -1),
            (party_set_slot, ":previous_target", slot_village_reserved_by_recruiter, 0),
         (try_end),
         (assign, ":min_distance", 999999),
         (assign, ":closest_village", -1),
         (try_for_range, ":village", villages_begin, villages_end),
            (store_distance_to_party_from_party, ":distance", ":party_no", ":village"),
            (lt, ":distance", ":min_distance"),
            (try_begin),
               (store_faction_of_party, ":village_current_faction", ":village"),
               (assign, ":faction_relation", 100),
               (try_begin),
                  (neq, ":village_current_faction", "$players_kingdom"),    # faction relation will be checked only if the village doesn't belong to the player's current faction
                  (store_relation, ":faction_relation", "$players_kingdom", ":village_current_faction"),
               (try_end),
               (ge, ":faction_relation", 0),
               (party_get_slot, ":village_relation", ":village", slot_center_player_relation),
               (ge, ":village_relation", 0),
               (party_get_slot, ":volunteers_in_village", ":village", slot_center_volunteer_troop_amount),
               (gt, ":volunteers_in_village", 0),
            #daedalus begin
               (party_get_slot, ":village_faction", ":village", slot_center_original_faction),
               (assign,":stop",1),
               (try_begin),
                  (eq,":recruit_faction",-1),
                  (assign,":stop",0),
               (else_try),
                  (eq, ":village_faction", ":recruit_faction"),
                  (assign,":stop",0),
               (try_end),
               (neq,":stop",1),
            #daedalus end
               (neg|party_slot_eq, ":village", slot_village_state, svs_looted),
               (neg|party_slot_eq, ":village", slot_village_state, svs_being_raided),
               (neg|party_slot_ge, ":village", slot_village_infested_by_bandits, 1),
               (neg|party_slot_eq, ":village", slot_village_reserved_by_recruiter, 1), 
               (assign, ":min_distance", ":distance"),
               (assign, ":closest_village", ":village"),
            (try_end),
         (try_end),
         (gt, ":closest_village", -1),
         (party_set_ai_behavior, ":party_no", ai_bhvr_travel_to_party),
         (party_set_ai_object, ":party_no", ":closest_village"),
         (party_set_slot, ":party_no", slot_party_ai_object, ":closest_village"),
         (party_set_slot, ":closest_village", slot_village_reserved_by_recruiter, 1),
      (try_end),
      (party_get_slot, ":target", ":party_no", slot_party_ai_object),
      (gt, ":target", -1),
      (store_distance_to_party_from_party, ":distance_from_target", ":party_no", ":target"),
      (try_begin),
         (store_faction_of_party, ":target_current_faction", ":target"),
         (assign, ":faction_relation", 100),
         (try_begin),
            (neq, ":target_current_faction", "$players_kingdom"),    # faction relation will be checked only if the target doesn't belong to the player's current faction
            (store_relation, ":faction_relation", "$players_kingdom", ":target_current_faction"),
         (try_end),
         (ge, ":faction_relation", 0),
         (party_get_slot, ":target_relation", ":target", slot_center_player_relation),
         (ge, ":target_relation", 0),
      #daedalus begin
            (party_get_slot, ":target_faction", ":target", slot_center_original_faction),
            (assign,":stop",1),
            (try_begin),
            (eq,":recruit_faction",-1),
            (assign,":stop",0),
        (else_try),
            (eq, ":target_faction", ":recruit_faction"),
            (assign,":stop",0),
            (try_end),
            (neq,":stop",1),
      #daedalus end
         (neg|party_slot_eq, ":target", slot_village_state, svs_looted),
            (neg|party_slot_eq, ":target", slot_village_state, svs_being_raided),
            (neg|party_slot_ge, ":target", slot_village_infested_by_bandits, 1),
         (le, ":distance_from_target", 0),
         (party_get_slot, ":volunteers_in_target", ":target", slot_center_volunteer_troop_amount),
         (party_get_slot, ":target_volunteer_type", ":target", slot_center_volunteer_troop_type),
         (assign, ":still_needed", ":needed"),
         (val_sub, ":still_needed", ":amount"),
         (try_begin),
            (gt, ":volunteers_in_target", ":still_needed"),
            (assign, ":santas_little_helper", ":volunteers_in_target"),
            (val_sub, ":santas_little_helper", ":still_needed"),
            (assign, ":amount_to_recruit", ":volunteers_in_target"),
            (val_sub, ":amount_to_recruit", ":santas_little_helper"),
            (assign, ":new_target_volunteer_amount", ":volunteers_in_target"),
            (val_sub, ":new_target_volunteer_amount", ":amount_to_recruit"),
            (party_set_slot, ":target", slot_center_volunteer_troop_amount, ":new_target_volunteer_amount"),
            (party_add_members, ":party_no", ":target_volunteer_type", ":amount_to_recruit"),
            (party_set_ai_behavior, ":party_no", ai_bhvr_hold),
            (party_set_slot, ":target", slot_village_reserved_by_recruiter, 0),
         (else_try),
            (le, ":volunteers_in_target", ":still_needed"),
            (gt, ":volunteers_in_target", 0),
            (party_set_slot, ":target", slot_center_volunteer_troop_amount, -1),
            (party_add_members, ":party_no", ":target_volunteer_type", ":volunteers_in_target"),
            (party_set_ai_behavior, ":party_no", ai_bhvr_hold),
            (party_set_slot, ":target", slot_village_reserved_by_recruiter, 0),
         (else_try),
            (le, ":volunteers_in_target", 0),
            (party_set_ai_behavior, ":party_no", ai_bhvr_hold),
            (party_set_slot, ":target", slot_village_reserved_by_recruiter, 0),
         (else_try),
            (display_message, "@ERROR IN THE RECRUITER KIT SIMPLE TRIGGERS!",0xFF2222),
            (party_set_slot, ":target", slot_village_reserved_by_recruiter, 0),
         (try_end),
      (try_end),
   (try_end),
   (try_for_parties, ":party_no"),
      (party_slot_eq,":party_no", slot_party_type, spt_recruiter),
      (party_get_num_companions, ":amount", ":party_no"),
      (val_sub, ":amount", 1),   #the recruiter himself doesn't count
      (party_get_slot, ":needed", ":party_no", slot_party_recruiter_needed_recruits),
      (eq, ":amount", ":needed"),
      (party_get_slot, ":party_origin", ":party_no", slot_party_recruiter_origin),
      (try_begin),
         (neg|party_slot_eq, ":party_no", slot_party_ai_object, ":party_origin"),
         (party_set_slot, ":party_no", slot_party_ai_object, ":party_origin"),
         (party_set_ai_behavior, ":party_no", ai_bhvr_travel_to_party),
         (party_set_ai_object, ":party_no", ":party_origin"),
      (try_end),
      (store_distance_to_party_from_party, ":distance_from_origin", ":party_no", ":party_origin"),
      (try_begin),
         (le, ":distance_from_origin", 0),
         (party_get_num_companion_stacks, ":stacks", ":party_no"),
         (try_for_range, ":stack_no", 1, ":stacks"),
            (party_stack_get_size, ":size", ":party_no", ":stack_no"),
            (party_stack_get_troop_id, ":troop_id", ":party_no", ":stack_no"),
            (party_add_members, ":party_origin", ":troop_id", ":size"),
         (try_end),
         (str_store_party_name_link, s13, ":party_origin"),
         (assign, reg10, ":amount"),
         (display_log_message, "@A recruiter has brought {reg10} recruits to {s13}.", 0x00FF00),
         (remove_party, ":party_no"),
      (try_end),   
   (try_end),
   ]),
 
#This trigger makes sure that no village is left reserved forever.
(12,
   [
   (try_for_range, ":village", villages_begin, villages_end),
      (party_set_slot, ":village", slot_village_reserved_by_recruiter, 0),
   (try_end),
   ]),

############################################################################################################################
## Recruiter kit end
############################################################################################################################

module_troops
- This can be anywhere between "mercenaries_end" and "town_walker_1".
Code:
  ["recruiter","Recruiter","Recruiter",tf_mounted|tf_guarantee_boots|tf_guarantee_armor|tf_guarantee_gloves|tf_guarantee_horse|tf_guarantee_ranged,0,0,fac_neutral,
   [itm_sword_medieval_a,itm_leather_jerkin,itm_leather_boots,itm_courser,itm_leather_gloves,itm_light_crossbow,itm_bolts],
   def_attrib|agi_21|int_30|cha_21|level(25),wp(130),knows_common|knows_riding_7|knows_horse_archery_5|knows_leadership_7,swadian_face_young_1, swadian_face_old_2],

That's it! If you have problems, send me a PM or post in the thread. The latter is recommended.

Changelog:
1.30
- Warband compatibility.
1.20
- Change: Recruiters can now be attacked by other parties, and their nationality is visible.
- Change: Recruiters can no longer recruit from villages that have negative relation to player or from villages that belong to hostile kingdom.
- Change: A red message is displayed every time a recruiter is defeated.
- Change: The message that tells that a recruiter has returned home is now colored green.
- Fix: Two minor bugs.
1.10
- Added ability to order recruits of specified nationality.
1.0
- First version.

If you want to use this feature in your mod you don't have to ask my permission to do so. Just inform me with a PM and add as many of us* as possible in the credits.

*Credits go to:
- Hessuu                    (Coding)
- Stoker                    (Advicing me on how to implement the recruiter spawning)
- Blankin                    (Coding the dialogs)
- Alkhadias Master      (Doing most of the coding for version 1.10 scripts)
- cdvader                  (Giving an excellent example on how to implent a feature)
- Janus                      (Maker of the mod installer script)

Any help, comments, ideas and bug reports are appreciated! Feel free to modify and redistribute the mod at will!
 
Great! I was wondering if anyone had done something like that... I think I will put in my mod for personal use, thanks!

edit: I have some experience with dialogues, not much but I see the original dialogues and usually make what I want work :wink:, if you want help send me a pm today, because my mother will kill me tomorrow by the morning :wink:
 
Ho ho, dude, that is majorly awesome!  :grin:

So, it looks like they are taking them to a village. What happens if you own multiple villages/castles/towns? Do they take them to any particular one?
 
Sweet coding.  I have some dialogue experience.  I actually don't have a full understanding of scripts or triggers and do most of my coding through the module_dialogue for things I want done.  Will definitely try to use your mod.  Nice work.
 
Thank you all for your great comments!

Llew2 said:
Ho ho, dude, that is majorly awesome!  :grin:

So, it looks like they are taking them to a village. What happens if you own multiple villages/castles/towns? Do they take them to any particular one?

Every recruiter party has it's own "slot_recruiter_party_origin" constant, which contains the id of the town/castle they were hired from. When they have gathered enough recruits they head back there.
I actually haven't tested how it works with multiple cities.  :???: I'm very confident that there shouldn't be any problems but I'm gonna test it right now.
 
Cool. :grin:
Now, I don't know how you did this, but how do you make them actually recruit from villages? I'm wondering if it's possible to get enemy lord parties to recruit mercenaries.
 
This looks nice (can you add the word KIT to the OP?)

As for the dialogs that come up, do you run checks on the origin slot?  Would  be a good idea, to hunt down enemy recruiters(cutting supply lines).  It's odd that they won't run away with the merchant personality, unless you are forcing their movement.  I'll have to look at the code.
 
FrisianDude said:
Cool. :grin:
Now, I don't know how you did this, but how do you make them actually recruit from villages? I'm wondering if it's possible to get enemy lord parties to recruit mercenaries.

First they do a search for nearest village with recruits and go there. Then the trigger takes the amount of recruits, type of the recruits and puts them into recruiter's party. Then it removes the recruits from the village. Something like that. It may be possible and it would be pretty damn cool if lords could use this to get their troops. You could attack your enemies' recruiters to cut them off of recruits! Would require lots of work though.

jik said:
This looks nice (can you add the word KIT to the OP?)

As for the dialogs that come up, do you run checks on the origin slot?  Would  be a good idea, to hunt down enemy recruiters(cutting supply lines).  It's odd that they won't run away with the merchant personality, unless you are forcing their movement.  I'll have to look at the code.

Kit and also WIP added.

I have no idea about those checks. I really need somebody to do those dialogs, there is still some small bugs in target-finding, and I'm going to look at those now.
After the basis of this feature is stable I would really like to try if I could get lords to use recruiters too! It may not be even hard to do. It depends on how the current native recruitment "hardwired" to other AI behavior-controlling scripts.

Any help with the mod and bug reports are appreciated.
 
Again, I haven't looked at the code, but to get AI to use it would be based on how it's functionality is called.  If your dialogs/menus that recruit call a script that does all the calculations and such, then a trigger can call these scripts for AI during game map time.
 
jik said:
Again, I haven't looked at the code, but to get AI to use it would be based on how it's functionality is called.  If your dialogs/menus that recruit call a script that does all the calculations and such, then a trigger can call these scripts for AI during game map time.

The menu where you choose the amount of recruits only spawns a recruiter party with the amount of recruits and city of origin as constants. After that a single "simple_trigger" does all the work. I think it would require only some minor tweaking to allow AI parties to use it. After that only a trigger that spawns recruiters and editing/removal of existing recruitment system is needed.
 
The AI uses cf_reinforce_party by way of hire_men_to_kingdom_hero_party to handle recruitment/reinforcement.  There's also an AI state spai_recruiting_troops if you want to get really fancy.  My concern would be getting lords/towns into a recruitment state too often and starving the player out of recruits. 
 
I get an erorr :sad:

spt_recruiter is not defined

Edit: it's when i run module_scripts and module_simple_triggers
 
Code:
Initializing...
Compiling all global variables...
Exporting strings...
Exporting skills...
Exporting tracks...
Exporting animations...
Exporting meshes...
Exporting sounds...
Exporting skins...
Exporting map icons...
Creating new tag_uses.txt file...
Creating new quick_strings.txt file...
Exporting faction data...
Exporting item data...
Exporting scene data...
Exporting troops data
Exporting particle data...
Exporting scene props...
Exporting tableau materials data...
Exporting presentations...
WARNING: Local variable never used: value
Exporting party_template data...
Exporting parties
Exporting quest data...
Exporting scripts...
Traceback (most recent call last):
  File "process_scripts.py", line 40, in <module>
    save_scripts(variables,variable_uses,scripts,tag_uses,quick_strings)
  File "process_scripts.py", line 19, in save_scripts
    save_statement_block(file,convert_to_identifier(func[0]), 0,func[1], variabl
e_list,variable_uses,tag_uses,quick_strings)
  File "C:\Users\Moritz\Mount&Blade\Modules\Age of Machinery\ModuleSystem\proces
s_operations.py", line 449, in save_statement_block
    save_statement(ofile,opcode,no_variables,statement,variable_list,variable_us
es,local_vars, local_var_uses,tag_uses,quick_strings)
  File "C:\Users\Moritz\Mount&Blade\Modules\Age of Machinery\ModuleSystem\proces
s_operations.py", line 398, in save_statement
    ofile.write("%d %d "%(opcode, lenstatement))
TypeError: %d format: a number is required, not str
Exporting mission_template data...
WARNING: Local variable never used: num_other_cannons
WARNING: Local variable never used: player_agent
WARNING: Local variable never used: num_other_cannons
WARNING: Local variable never used: player_agent
WARNING: Local variable never used: num_other_cannons
WARNING: Local variable never used: player_agent
Exporting game menus data...
Error: Unable to find object:script_send_recruiter
ERROR: Illegal Identifier:script_send_recruiter
Error: Unable to find object:script_send_recruiter
ERROR: Illegal Identifier:script_send_recruiter
Error: Unable to find object:script_send_recruiter
ERROR: Illegal Identifier:script_send_recruiter
Error: Unable to find object:script_send_recruiter
ERROR: Illegal Identifier:script_send_recruiter
Error: Unable to find object:script_send_recruiter
ERROR: Illegal Identifier:script_send_recruiter
Error: Unable to find object:script_send_recruiter
ERROR: Illegal Identifier:script_send_recruiter
exporting simple triggers...
exporting triggers...
exporting dialogs...
Checking global variable usages...
WARNING: Global variable never used: qst_bring_back_runaway_serfs_num_parties_fl
eed
WARNING: Global variable never used: qst_follow_spy_run_away
WARNING: Global variable never used: qst_follow_spy_meeting_counter
WARNING: Global variable never used: qst_follow_spy_spy_back_in_town
WARNING: Global variable never used: qst_follow_spy_partner_back_in_town
WARNING: Global variable never used: npc_with_personality_match
WARNING: Global variable never used: g_player_banner_granted
WARNING: Global variable never used: merchant_quest_last_offerer
WARNING: Global variable never used: thanked_by_ally_leader
WARNING: Global variable never used: last_defeated_hero
WARNING: Global variable never used: last_freed_hero
WARNING: Global variable never used: capture_screen_shown
WARNING: Global variable never used: pin_number
WARNING: Global variable never used: loot_screen_shown
WARNING: Global variable never used: cant_talk_to_enemy
WARNING: Global variable never used: g_battle_simulation_auto_enter_town_after_b
attle
WARNING: Global variable never used: g_tournament_last_bet_tier
WARNING: Global variable never used: g_training_ground_training_count
WARNING: Global variable never used: temp_3
WARNING: Global variable never used: new_kills
WARNING: Global variable never used: pin_player_fallen
WARNING: Global variable never used: g_battle_us_ready
WARNING: Global variable never used: g_battle_us_wounded
WARNING: Global variable never used: g_battle_us_dead
WARNING: Global variable never used: g_battle_enemies_ready
WARNING: Global variable never used: g_battle_enemies_wounded
WARNING: Global variable never used: g_battle_enemies_dead
WARNING: Global variable never used: g_battle_allies_ready
WARNING: Global variable never used: g_battle_allies_wounded
WARNING: Global variable never used: g_battle_allies_dead
WARNING: Global variable never used: g_election_date
WARNING: Global variable never used: g_player_party_icon
WARNING: Global variable never used: g_training_ground_ranged_distance
WARNING: Global variable never used: g_player_party_morale_modifier_party_size
WARNING: Global variable never used: g_player_party_morale_modifier_leadership
WARNING: Global variable never used: g_player_party_morale_modifier_no_food
WARNING: Global variable never used: spy_quest_troop
WARNING: Global variable never used: g_ransom_offer_party
WARNING: Global variable never used: g_cur_week_half_daily_wage_payments

______________________________

Script processing has ended.
Press any key to exit. . .

doesn't work  :cry:

Edit: works now :grin: ,
i added the script at the wrong place :oops:
 
Hmm, strikes me you might want some kind of limit on the number of parties and recruits per party.

For instance you can have no more than two parties per settlement (or have it scalable - 1 for villages, 2 for castles, 3 for towns, etc.). And also have a limit of say, 25 recruits per recruiter party, of course being able to set it to less than that.

Just some ideas.  :smile:
 
Back
Top Bottom