OSP Code Campaign Forming a Wagon Train

Users who are viewing this thread

gaston

Sergeant
Updated April 26, 2011.

Okay, I'm declaring victory on the Wagon Train code.  The intent of the wagon train is to give the player character a place to store inventory and troops.  The wagon train only has two missions: to accompany the player party or to stay and wait.  I think this will be useful for players (especially players who don't belong to a faction) to make their party smaller so they can move faster ( for example to catch bandits).  With a wagon train you don't have to disband troops to gain speed.

Updated May 3, 2011.  Changed the budget report code thanks to advice from

Step 1.  Add a wagon_master to troops.  Just copy and rename the caravan master.  Give him "knows_pathfinding_10" so he can keep up.  Add this troop under household_possessions:
["wagon_possessions","{!}wagon_possessions","{!}wagon_possessions",tf_hero|tf_inactive|tf_is_merchant, 0,reserved,  fac_neutral,[],def_attrib|level(1:cool:,wp(60),knows_inventory_management_10, 0], 

Step 2.  Add this to parties, I put mine right under the salt mine:

("wagon_train","Wagon Train",pf_disabled|icon_gray_knight|carries_goods(20), no_menu, pt_none, fac_player_faction,0,escorted_merchant_personality,0,(-5.23,90.26),[(trp_wagon_master,1,0)]),
 
Step 3.  In module_game_menus add the following to the camp menu right before ("resume_travelling",[],"Resume travelling.",

Code:
("camp_wagon",[(eq, "$wagon_active", 0)],"Form a wagon train",
         [(set_spawn_radius, 1),
          (party_relocate_near_party, "p_wagon_train", "p_main_party", 1), (enable_party, "p_wagon_train"),
          (assign, "$wagon_active", 1),
          (display_message, "@Wagon train formed nearby."),
          ]
         ),

Step 4.  In module_dialogs add the following, I put mine under the escort merchant dialog:
Code:
[trp_wagon_master,"start", [],
    "What can I do for you, chief?", "wagon_train_talk",[]],

  [anyone|plyr,"wagon_train_talk", [], "You follow my lead and try to stay out of trouble.", "wagon_train_follow_lead",[]],
  [anyone,"wagon_train_follow_lead", [], "Alright. We'll be right behind you.", "close_window"[(party_set_ai_behavior, "$g_encountered_party", ai_bhvr_escort_party),
                                                                                                    (party_set_ai_object,"$g_encountered_party", "p_main_party"),
                                                                                                    (assign, "$g_leave_encounter", 1)]],
  
  [anyone|plyr,"wagon_train_talk", [], "You stay here. I'll be back in a while.", "wagon_train_stay_here",[]],
  [anyone,"wagon_train_stay_here", [], "Alright. We'll be waiting here for you.", "close_window",[(party_set_ai_behavior, "$g_encountered_party", ai_bhvr_hold),
                                                                                                     (assign, "$g_leave_encounter", 1)]],
        
 [anyone|plyr,"wagon_train_talk", [], "Let's check the inventory.", "start",[(change_screen_loot, "trp_wagon_possessions"),]],
  
  [anyone|plyr,"wagon_train_talk", [], "Let's check the troop assignments.", "start",[(change_screen_exchange_members, "$g_talk_troop_party"),]],

    [anyone|plyr, "wagon_train_talk", [],  "I want to disband the wagon train.", "wagon_train_disband1", []],

    [anyone,"wagon_train_disband1", [(party_get_num_companions,":num_troops","$g_encountered_party"),(gt,":num_troops",1)],
                                     "Are you sure? I still have troops.", "wagon_train_disband2",[]],

  [anyone,"wagon_train_disband1", [(party_get_num_companions,":num_troops","$g_encountered_party"),(eq,":num_troops",1)],
                                     "All right.  I'll see you around.", "close_window",[(party_clear,"p_wagon_train"),
                                                                                                        (party_add_members,"p_wagon_train","trp_wagon_master",1),
                                                                                                        (disable_party, "p_wagon_train"),
                                                                                                       (assign, "$wagon_active", 0), # To allow for creation of another one
                                                                                                        ]],

  [anyone|plyr, "wagon_train_disband2", [],  "Yes, I want to disband the wagon train.", "close_window", [(party_clear,"p_wagon_train"),
                                                                                                        (party_add_members,"p_wagon_train","trp_wagon_master",1),
                                                                                                        (disable_party, "p_wagon_train"),
                                                                                                       (assign, "$wagon_active", 0), # To allow for creation of another one
                                                                                                        ]],

  [anyone|plyr, "wagon_train_disband2", [],  "Wait. I want to look at the troops.", "start", [(change_screen_exchange_members, "$g_talk_troop_party"),]],
  

  [anyone|plyr,"wagon_train_talk", [], "Keep up the good work.", "close_window",[(assign, "$g_leave_encounter", 1)]],

Step 5.  Put the wagon train on the payroll.  Wagon Train troops cost more than troops in the players party because you don't have to buy food for them.  You pay them more and they buy their own food.  In module_presentations add the following changes to the budget report right below "(this_or_next|eq, ":party_no", "p_main_party"),"  additions are shown in green.

(this_or_next|eq, ":party_no", "p_main_party"),
        (this_or_next|eq, ":party_no", "p_wagon_train"),
(eq, ":garrison_troop", 1),
        (assign, ":total_wage", 0),
        (party_get_num_companion_stacks, ":num_stacks", ":party_no"),
        (try_for_range, ":i_stack", 0, ":num_stacks"),
          (party_stack_get_troop_id, ":stack_troop", ":party_no", ":i_stack"),
          (party_stack_get_size, ":stack_size", ":party_no", ":i_stack"),
          (call_script, "script_game_get_troop_wage", ":stack_troop", ":party_no"),
          (assign, ":cur_wage", reg0),
          (val_mul, ":cur_wage", ":stack_size"),
          (val_add, ":total_wage", ":cur_wage"),
        (try_begin),
          (eq, ":garrison_troop", 1),
          (val_div, ":total_wage", 2), #Half payment for garrisons
        (else_try),
          (eq, ":party_no", "p_main_party"),
          (store_sub, ":total_payment_ratio", 14, "$g_cur_week_half_daily_wage_payments"), #between 0 and 7
          (val_mul, ":total_wage", ":total_payment_ratio"),
          (val_div, ":total_wage", 14),
        (else_try),
          (eq, ":party_no", "p_wagon_train"),
          (party_get_num_companions, ":num_troops", ":party_no"), ## headcount for food cost
          (val_mul, ":num_troops", 12), ##approx weekly food consumption
          (store_sub, ":total_payment_ratio", 14, "$g_cur_week_half_daily_wage_payments"), #between 0 and 7
          (val_mul, ":total_wage", ":total_payment_ratio"),
          (val_div, ":total_wage", 14),
          (val_add, ":total_wage", ":num_troops"), ##food cost

      (try_end),
##        (gt, ":total_wage", 0)


That's it. 

I would like to make it clear that this was mostly not my original work.  I simply put together bits of existing code.  Thanks to everyone for their advice and special thanks to Lumos.
 
First of all, welcome to modding :smile:
For 1, you could you a global variable (like "$wagon_active") or a slot. I'll give you an example with a global variable, as you'll use it only for one object, and anyways you can convert it to a slot quickly if you want.
Code:
("camp_wagon",[(eq, "$wagon_active", 0)],"Form a wagon train",
                     [(set_spawn_radius, 1),(spawn_around_party, "p_main_party", "pt_wagon_train"),
            (assign, "$wagon_active", 1),
            (display_message, "@Wagon train formed nearby."),
            ]
        ),

The (eq, "$wagon_active", 0), in the conditions block is pretty much self-explanatory. Globals auto-initialise to 0, so this will be true upon game start. After creating the wagon train, you simply (assign, "$wagon_active", 1), and voilà, you're limited to one.

Actually, if you want only one wagon at all times it would be better if you used a party instead of a party template, so I'd replace the (set_spawn_radius, 1),(spawn_around_party, "p_main_party", "pt_wagon_train"), with (party_relocate_near_party, "p_wagon_train", "p_main_party", 1), (enable_party, "p_wagon_train"),

About 2, I'd use it like this (assuming that we're using a party instead of a template; IDK if it would work with a template. Guess not, though):
Code:
   [anyone|plyr, "wagon_train_talk", [],  "[Disband the wagon]", "close_window",
   [(disable_party, "p_wagon_train"), (assign, "$wagon_active", 0), # To allow for creation of another one
   ]],
I think your code wasn't working because you didn't set the slot_troop_leaded_party. It might be setting itself automatically, I don't know... :smile:
The code above (obviouly) does not check for items or troops. I don't know whose inventory do you use (I'll assume it's a special troop in the wagon. With more InvMag for more items, etc.) so I don't know how it would be appropriate to check for items, but about the troops in the party, I think that if you're using a special troop (could be set as the party's leader) it would be good to use (store_party_size,":wagon_size", "p_wagon_train"), (eq, ":wagon_size", 1), to check if the commander troop is the only person in it.

About 3, I can't help you, sorry. Maybe quick-attach the wagon-train's party to the player's party before the payroll is initiated.
 
[list type=decimal]
[*]Like Lumos said - use a global, slot value, reference, or whatever. If you're going to use a global and respawn dynamically (for whatever reason) do it like Native and use it to store the party id. Try (neg|party_is_active, "p_wagon_train") if you reuse one party.
[*]To check for inventory, use troop_get_inventory_capacity or store_free_inventory_capacity. For the party size, check party_get_num_companions or party_get_num_companion_stacks > 0.
[*]Simply make the wagon belong to the player's faction to have it be included as a separate entry in the payroll.
[/list]
 
Thanks to everyone for their help. 

Lumos,
Your advice worked champion.  Forming and disbanding the wagon train now works like we wanted.

Somebody,
Making the wagon train party part of the player's faction did not add them to the payroll.  I've found a post about adding guards to the salt mine (and the payroll) that I can maybe adapt to work for the wagon train.  At this point, I don't even know where the income/expenses for the weekly budget report come from.

Caba`drin,
I'm afraid you underestimated my ignorance.  I don't understand "dynamic" and "static", but it's okay.  It works.

My intention is to replace my first post wih step-by-step instructions on how to do this once I get the payroll thing sorted out.
 
gaston said:
Making the wagon train party part of the player's faction did not add them to the payroll.  I've found a post about adding guards to the salt mine (and the payroll) that I can maybe adapt to work for the wagon train.  At this point, I don't even know where the income/expenses for the weekly budget report come from.
All payroll stuff is dealt with in module_presentations, specifically the budget presentation.

gaston said:
I'm afraid you underestimated my ignorance.  I don't understand "dynamic" and "static", but it's okay.  It works.
If you add a party "p_wagon_train" to module_parties.py then the wagon train party will always have the same ID/index number. Its reference will be "static" and unchanging, so you will simply activate and deactivate the party "p_wagon_train" every time you need to deal with it.

If you spawn the party based on a template, then it's ID/index number will change each time it is spawned (because technically it will be a different party with each spawn). In this way, the reference will be "dynamic" and change. Then, you would need to find that ID number each time you deal with (as it won't always be set to "p_wagon_train") and that ID number is stored in the global variable $g_encountered_party any time you are talking to the wagon train.

Tiberius Decimus Maximus said:
Wait, holy ****ing ****, why hasn't anyone thought of this yet!?!?!?!?!
Agreed, this is an excellent idea.
 
You can limit it to large armies for more historical accuracy  :grin::



("camp_wagon",[],"Form a wagon train",
                    [
    (party_get_num_companion_stacks, ":num_stacks","p_main_party"),
    (assign, ":num_men", 0),
    (try_for_range, ":i_stack", 0, ":num_stacks"),
      (party_stack_get_size, ":stack_size","p_main_party",":i_stack"),
      (val_add, ":num_men", ":stack_size"),
    (try_end),
      (try_begin),
          (gt, ":num_men", 200), # se muestra si el player tiene por lo menos 200 hombres
(set_spawn_radius, 1),(spawn_around_party, "p_main_party", "pt_wagon_train"),
            (display_message, "@Wagon train formed nearby."),
      (else_try),
        (display_message,"@ You need to have more men for this."),
      (try_end),
          ]
        ),
 
Idibil said:
You can limit it to large armies for more historical accuracy  :grin::

Idibil, I'm a big fan of yours.  Thank you for your suggestion.  I don't think I'll use it yet or, if I do, the number will be small (like 20).  The reason is that the time I really, really wanted to split my party was when chasing the Arians in Brytenwalda.  My party was about 30 troops and not only could I not catch the Arians, I couldn't keep them in sight.
There's nothing historically inaccurate about a leader splitting his party so the lead party can move faster.  Think about the "Catch Spy" quest (grrrr!).  Why wouldn't you take ten mounted companions and leave the rest of the party in camp?

Anyway, thanks for all the great work on Brytenwalda.  I'm looking forward to the next release.  I hope you've solved the too many parties probelem.
 
Ok, it was a idea only  :grin:

Anyway, thanks for all the great work on Brytenwalda.  I'm looking forward to the next release.  I hope you've solved the too many parties probelem.

We have change somethings here. However, I dont want change lords with high troops number yet, but if it is a problem, we will have change.
 
I'm working on something similar:

the code is like this now but it is not finished:

Code:
      ("make_4_horse_wagon",[(eq, "$brc_camp_inv", 2),
	                         (try_begin),
							   (player_has_item,"itm_heavy_wagon"),
							   (troop_get_inventory_capacity,":capacity","trp_player"),
							   (assign,":horses",0),
							   (try_for_range,":slot",0,":capacity"),
							     (troop_get_inventory_slot,":cur_item","trp_player",":slot"),
							     (is_between, ":cur_item", "itm_horse_0001", "itm_horse_9999"),
							     (val_add,":horses",1),
							   (try_end),
							   (ge, ":horses", 4),
							 (else_try),
							   (disable_menu_option),
							 (try_end),],"Make a new Wagon(1 heavy wagon & 4 diferent horses).",
       [(assign, "$build", 4),
	    (rest_for_hours_interactive, 3, 5, 1), #rest while attackable
        (assign,"$next_menu","mnu_build_inventory"),
        (assign, "$rest_time", 3),
        (change_screen_return),
        ]),
 
Okay, I've got the wagon train troops added to the payroll.  The final part might be to change it so that the total number of troops in the player party and the wagon train does not exceed the player's party size.  I have no idea how to do this.

Does anyone have any ideas?

If you give troops to a lord in in your own faction, does his party size enter into it? 
 
Try slapping on pf_limit_members and see if game_get_party_companion_limit gets called. It's probably easier to limit the player party's size (via the above script) than to limit it for a different party.
 
Current final code added as first post.  One thig it doesn't do is check the party size of the wagon train, so maybe you can put unlinited troops theer.  You have to pay them, though.
 
You don't need to set the spawn radius if you're relocating a party. The global isn't necessary either. Your payroll code will loop through every party looking for the wagon party you've already defined. You'll also want to check if the wagon is active before incrementing num_lines (before (store_mul, ":cur_y", 27, ":num_lines")). As for the wage calculation, add an else_try checking if the wagon is active before using (assign, ":garrison_troop", 1), then increase the wages in another else_try under (val_div, ":total_wage", 14).
 
Somebody said:
You don't need to set the spawn radius if you're relocating a party.

Okay, thank you.
Somebody said:
The global isn't necessary either.
Do you mean "$wagon_active"?  That prevents the creation of more than one wagon train party.
Somebody said:
Your payroll code will loop through every party looking for the wagon party you've already defined.

How exactly do I fix that?  Bear in mind that I don't know what a lot of this means.  I copied the payroll code and tinkered with it until it worked.  I need specific examples of what to add or delete.  Do I delete "try_for_parties"?
Somebody said:
You'll also want to check if the wagon is active before incrementing num_lines (before (store_mul, ":cur_y", 27, ":num_lines")).

I don't understand why I want to do that.  Please explain.  Exactly how do I do that?
Somebody said:
As for the wage calculation, add an else_try checking if the wagon is active before using (assign, ":garrison_troop", 1), then increase the wages in another else_try under (val_div, ":total_wage", 14).

Wouldn't it be better to check if the wagon is active right at the top and skip the whole thing if it isn't?  It appears that the goal of your suggestions is to add the wagon train to the report just like garrisons above the player's party.  Then I could eliminate the code that adds the wagon train payroll as a separate line beneath the player's party.  Is that correct?
 
gaston said:
Somebody said:
The global isn't necessary either.
Do you mean "$wagon_active"?  That prevents the creation of more than one wagon train party.
I refer you to the discussion of dynamic/static above. Since you are using a party defined in module_parties, there is only one possible wagon train party...you aren't spawning a new party based on a template, rather there is one party that gets moved around when the script says so.

Simply use (neg|party_is_active, "p_wagon_train"),
to identify if it should be activated or if it already exists.

gaston said:
Somebody said:
Your payroll code will loop through every party looking for the wagon party you've already defined.

How exactly do I fix that?  Bear in mind that I don't know what a lot of this means.  I copied the payroll code and tinkered with it until it worked.  I need specific examples of what to add or delete.  Do I delete "try_for_parties"?
Again to the dynamic/static discussion. Since you are using "p_wagon_train" the party ID never changes. You don't need to look for it among all of the parties. You just need to use "p_wagon_train" when you wish to add it to the budget presentation.

gaston said:
Somebody said:
You'll also want to check if the wagon is active before incrementing num_lines (before (store_mul, ":cur_y", 27, ":num_lines")).

I don't understand why I want to do that.  Please explain.  Exactly how do I do that?
Because, if the party isn't active, then there is no need to make the presentation larger because it won't be showing up in any case.
 
Caba`drin, Somebody,

I attempted to implement some of your suggestions and now the wagon train doesn't show up on the budget report at all.  Please feel free to copy my code into a post with your changes marked so I can do it correctly.

Thank you.
 
sorry to revive this thread but i have tried to implement it in 1.152 and it is not working....


There were a few compile errors in the dialog section,  missing commas etc.  but i "think" i have all that fixed.  It does compile with no errors, however after i spawn the wagon train and try to talk to it, all i get is attack or leave them alone.... 

so obviously something in the dialog section is still messed up.


any help?

 
Back
Top Bottom