PYTHON SCRIPT/SCHEME EXCHANGE

Users who are viewing this thread

For conditionally adding Marnid and/or Borcha to a scene depending on if they're in your party:

Code:
(modify_visitors_at_site,"scn_<your scene here>"),
(reset_visitors),
(try_begin),
(main_party_has_troop,"trp_borcha"),
(set_visitor,<mission template entry number>,"trp_borcha"),
(end_try),
(try_begin),
(main_party_has_troop,"trp_marnid"),
(set_visitor,<different mission template entry number>,"trp_marnid"),
(end_try),

Electrically,
Winter
 
Winter said:
For conditionally adding Marnid and/or Borcha to a scene depending on if they're in your party:

Code:
(modify_visitors_at_site,"scn_<your scene here>"),
(reset_visitors),
(try_begin),
(main_party_has_troop,"trp_borcha"),
(set_visitor,<mission template entry number>,"trp_borcha"),
(end_try),
(try_begin),
(main_party_has_troop,"trp_marnid"),
(set_visitor,<different mission template entry number>,"trp_marnid"),
(end_try),

Electrically,
Winter

And for any number of heroes in the party:

Code:
(modify_visitors_at_site,"scn_<your scene here>"),
(reset_visitors),
(try_for_range,reg(1),heroes_begin,heroes_end)),
(main_party_has_troop,reg(1)),
(assign,reg(2),<inital mission template entry number>),
(set_visitor,reg(2),reg(1)),
(val_add,reg(2),1),
(end_try),

Thanks for the brainstorm, Winter :smile:
 
Fujiwara said:
And for any number of heroes in the party:

Code:
(modify_visitors_at_site,"scn_<your scene here>"),
(reset_visitors),
(try_for_range,reg(1),heroes_begin,heroes_end)),
(main_party_has_troop,reg(1)),
(assign,reg(2),<inital mission template entry number>),
(set_visitor,reg(2),reg(1)),
(val_add,reg(2),1),
(end_try),

Thanks for the brainstorm, Winter :smile:

No prob, but it's not so good to add your own mod code to scripts in the script exchange, Fujiwara. heroes_begin and heroes_end are mod constants, not found in the Native module system. You should really point that out in your post.

Other than that, nice script. I love all the crazy things try_for_range can do.

Futilitarianly,
Winter
 
I'm posting a script here for other more serious scripters. The purpose of this script is to get a list of every troop stack in a given party along with of course the number of troop stacks. It currently only counts the non-prisoner troops (I think), but could be adapted to count all troops or only prisoners if needed.
If you don't know why this would be helpful, the script is probably not for you.

Included with the main script is an example script using it, which will print a list of troop stacks in the player's party on-screen. This isn't a particularly useful thing to do, but serves as a good example and base for whatever you need the script to do for you.

Special thanks to fisheye for a bit of scripting help on a more elegant way to store and incrementally reference variables using the slots of a dummy troop.

Add these lines to the end of the troop list in module_troops.py. They should be after the last troop but before the ending bracket:
Code:
#do not place a troop past this point, it marks the end of the troops
["end_troops","end_troops","end_troops",tf_hero,no_scene,reserved,fac_commoners,[],def_attrib,0,knows_common,0],

Add these string into module_strings.py, they're just used by the script example:
Code:
  ("party_contains","The party '{s3}' contains {reg9} troop stacks:"),
  ("string3","{s3}"),

Add these scripts into module_scripts.py:
Code:
  ("list_party_troops", [ #this script will check the target party (stored in "$party_to_check") and return a list of the troop types in the party
   (try_begin),[assign,"$party_stack_count",0],
	(try_for_range,reg(6), "trp_player", "trp_end_troops"),
		[party_count_companions_of_type, reg(7), "$party_to_check", reg(6)], [gt, reg(7), 0],
		[troop_set_slot,"trp_end_troops","$party_stack_count",reg(6)],
		[val_add, "$party_stack_count", 1],
	(end_try),
	#at this point, "$party_stack_count" contains the number of troop stacks in the "$party_to_check" party; "$party_stack_count" is also to be used as the end value for
	#a try_for_range loop (1 higher than the last reg with troop data), then the troop slots for the "trp_end_troops" dummy entry contain the troop id of each stack in the party.
   (end_try),
  ]),

  
  ("player_has_troops", [ #this script is an example of how to use the list_party_troops script; it will determine and print out the player's troop list on screen
   (try_begin), [assign, "$party_to_check", "p_main_party"], #set "$party_to_check" to the player's party, used for input in the list_party_troops script
    (call_script, "script_list_party_troops"), #run the script to get a list of troops in the player's party
    [str_store_party_name, 3, "$party_to_check"],(display_message, "str_party_contains"), #print out the string indicating the party name and number of troop slots
	(try_for_range, reg(6), 0, "$party_stack_count"), #loop through each troop. "$party_stack_count" contains the total number of troop references, thus where to end the loop
		[troop_get_slot,reg(7), "trp_end_troops", reg(6)], [str_store_troop_name, 3, reg(7)], (display_message, "str_string3"),
		#the list of troop references were stored in the dummy troop "trp_end_troops", starting with slot 0. Reg(7) is set to the current troop reference,
		#then the name of the troop is obtained and stored in the temporary string s(3). The troop name is then printed to the screen.
	(end_try),
   (end_try),
  ]),


Finally, add this into an operation block (in a dialog, a menu, a trigger, or wherever you want) to run the script example:
Code:
(call_script,"script_player_has_troops")


EDIT: updated the script to not rely on reg(5) and reg(9) but instead use its own variables, "$party_to_check" and "$party_stack_count".
 
Janus said:
I'm posting a script here for other more serious scripters. The purpose of this script is to get a list of every troop stack in a given party along with of course the number of troop stacks. It currently only counts the non-prisoner troops (I think), but could be adapted to count all troops or only prisoners if needed.
If you don't know why this would be helpful, the script is probably not for you.

Ha, your counting script is the exact same one I've been using for my new Craftmod features! Now we know why you wanted to increment registers, very clever.

Unfortunately the code where I've used my scripts doesn't quite work yet, due to the fact that I need some operations from the new version of M&B, but when that arrives let me assure you you're going to love it. :wink:

Pilocarpinely,
Winter
 
Winter said:
No prob, but it's not so good to add your own mod code to scripts in the script exchange, Fujiwara. heroes_begin and heroes_end are mod constants, not found in the Native module system. You should really point that out in your post.

Good point. Thanks :smile:

Other than that, nice script. I love all the crazy things try_for_range can do.

Futilitarianly,
Winter

I'd be dead in the water without try_for_range :smile:

Janus, brillant idea using trp_end_troops as a dummy storage unit. I've done the same thing with dummy scenes, storing various bits of data needed to change item abundance based on season, town location, and town size. I can definitely use this script. good job!

 
Fujiwara said:
Janus, brillant idea using trp_end_troops as a dummy storage unit. I've done the same thing with dummy scenes, storing various bits of data needed to change item abundance based on season, town location, and town size. I can definitely use this script. good job!

You should see what I've managed to cook up with it . . . :wink:

I've integrated it with the rest of my new feature to create something really astounding. Watch out for the next release for Craftmod -- I've coded some interim scripts that will let me move up the timetable. All I need to do is a little more scene design and a little more mission template code, and we'll be ready for the final beta.

Obeisantly,
Winter
 
I've got a few small changes to it to make it slightly more friendly by making it use it's own variables instead of registers.

I've also got another script which uses it that I'll post in this spot (by modifying the post) later after I get it tested. I'll update the post above at the same time, of course.

--------------------
My post above is updated, and the changes are needed for the below script to work.

Ok, the following script is to be placed in module_scripts.py and requires my script posted above.
The purpose of the script is to determine the highest skill values in the player party for every skill by checking every member of the party, including non-heroes. So, for instance, if you want to check the highest "pathfinding" skill in the party and in this case the party contains a stack of "trailblazer" units with very high pathfinding skills (higher than any other unit in the party), their pathfinding skill will be what is returned. Note that the script doesn't give the -1 to skill that .750 introduced for party skills of units other than the player (it gives the exact skills), and doesn't limit itself to only heroes. It can however be modified to do so easily enough, if that is your desire.
This script returns all 21 skills for the party. The usage is documented decently by the notes in the script.
I have tested the script with a few party configurations and verified that all 21 skills were properly identified for the party in each case.

So, without further ado, here's the script to go in module_scripts.py:
Code:
  ("read_party_skills", [ #this script determines the highest skill values in the player party for every skill by checking every member of the party, including non-heroes
   (try_begin),
    [assign, "$party_to_check", "p_main_party"], (call_script,"script_list_party_troops"),
	[assign,reg(0),0],[assign,reg(1),0],[assign,reg(2),0],[assign,reg(3),0],[assign,reg(4),0],[assign,reg(5),0],[assign,reg(6),0],
	[assign,reg(7),0],[assign,reg(8),0],[assign,reg(9),0],[assign,reg(10),0],[assign,reg(11),0],[assign,reg(12),0],[assign,reg(13),0],
	[assign,reg(14),0],[assign,reg(15),0],[assign,reg(16),0],[assign,reg(17),0],[assign,reg(18),0],[assign,reg(19),0],[assign,reg(20),0],
	(try_for_range, reg(23), 0, "$party_stack_count"), #loop through each stored troop reference. reg(9) contains the total number of troop references, thus where to end the loop
		[troop_get_slot,reg(21), "trp_end_troops", reg(23)],
		[store_skill_level,reg(22),0,reg(21)],[val_max,reg(0),reg(22)],[store_skill_level,reg(22),1,reg(21)],[val_max,reg(1),reg(22)],
		[store_skill_level,reg(22),2,reg(21)],[val_max,reg(2),reg(22)],[store_skill_level,reg(22),3,reg(21)],[val_max,reg(3),reg(22)],
		[store_skill_level,reg(22),4,reg(21)],[val_max,reg(4),reg(22)],[store_skill_level,reg(22),5,reg(21)],[val_max,reg(5),reg(22)],
		[store_skill_level,reg(22),6,reg(21)],[val_max,reg(6),reg(22)],[store_skill_level,reg(22),7,reg(21)],[val_max,reg(7),reg(22)],
		[store_skill_level,reg(22),8,reg(21)],[val_max,reg(8),reg(22)],[store_skill_level,reg(22),9,reg(21)],[val_max,reg(9),reg(22)],
		[store_skill_level,reg(22),10,reg(21)],[val_max,reg(10),reg(22)],[store_skill_level,reg(22),11,reg(21)],[val_max,reg(11),reg(22)],
		[store_skill_level,reg(22),12,reg(21)],[val_max,reg(12),reg(22)],[store_skill_level,reg(22),13,reg(21)],[val_max,reg(13),reg(22)],
		[store_skill_level,reg(22),14,reg(21)],[val_max,reg(14),reg(22)],[store_skill_level,reg(22),15,reg(21)],[val_max,reg(15),reg(22)],
		[store_skill_level,reg(22),16,reg(21)],[val_max,reg(16),reg(22)],[store_skill_level,reg(22),17,reg(21)],[val_max,reg(17),reg(22)],
		[store_skill_level,reg(22),18,reg(21)],[val_max,reg(18),reg(22)],[store_skill_level,reg(22),19,reg(21)],[val_max,reg(19),reg(22)],
		[store_skill_level,reg(22),20,reg(21)],[val_max,reg(20),reg(22)],
	(end_try), #The party's skills are stored in reg(0)-reg(20) at this point, so don't change those registers until you've checked what you need from them.
   (end_try), #You can check each skill by referring to "reg(skl_trade)", "reg(skl_leadership)", and so forth as listed in header_skills.py, as long as you have the file
  ]), # in question set to import from header_skills.py at the top (in other words, "from header_skills import *" at the top of the file your "reg(skl_trade)" reference is in)

EDIT: I could have stored those values in another dummy troop and slimmed this script down, but for simplicity of usage I decided to leave it using reg(0)-reg(20).

EDIT 2: updated to use val_max as fisheye suggested.
 
Janus: Instead of (try_begin), (gt, ) blah blah blah, you can do it all in one operation with val_max.

Here's a fragment of the buying code in my NPCs mod:

Code:
     ## first get highest trade skill in party
    (assign, reg(14),0),
    (try_for_range,reg(12),"trp_marnid","trp_ymira"),
      (main_party_has_troop, reg(12)),   
      (store_skill_level, reg(13),skl_trade,reg(12)),
      (val_max, reg(14),reg(13)),
    (end_try,0),
 
fisheye said:
Janus: Instead of (try_begin), (gt, ) blah blah blah, you can do it all in one operation with val_max.

Would you mind explaining what val_max does? And the other strange val operations, val_mod and val_min? I'm a retard when it comes to maths, and I cannot figure it out.

Subversively,
Winter
 
fisheye said:
Janus: Instead of (try_begin), (gt, ) blah blah blah, you can do it all in one operation with val_max.
Good catch, I've used val_max before but didn't think of it for this case. I'll change it to reflect that shortly.

Winter: val_max will compare the values of the two variables, and store the larger of the two in the first one listed. val_min does the same except for being for the smaller of the two variables. val_mod... not sure.

EDIT: ah, makes sense. val_mod apparently does the same as Mod in programming, it returns the remainder of the division of the two numbers.
For instance:
reg(1) = 10
reg(2) = 3
[val_mod, reg(1), reg(2)] should set reg(1) to 1.
10/3 = 3 (3*3=9) with a remainder of 1.

EDIT 2: updated the script to use val_max.
 
A question for Winter:

I noticed that in the code you posted in the CraftMod thread, you have a line of dialog that starts out with the speaker as trp_player, but with the |plyr tag attached. While I can obviously see this isn't an illegal construction, I'm very curious about what effects it has in the game. An elucidation of this would be very helpful. I keep getting images in my head of the player walking through Zendar muttering to himself. :smile:

P.S. - Yes, I realize there isn't actually a questiont anywhere in here  :razz:
 
Fujiwara said:
A question for Winter:

I noticed that in the code you posted in the CraftMod thread, you have a line of dialog that starts out with the speaker as trp_player, but with the |plyr tag attached. While I can obviously see this isn't an illegal construction, I'm very curious about what effects it has in the game. An elucidation of this would be very helpful. I keep getting images in my head of the player walking through Zendar muttering to himself. :smile:

P.S. - Yes, I realize there isn't actually a questiont anywhere in here  :razz:

Obviously, it puts the player talking to himself. It works like any other conversation -- the only difference is that the camera doesn't shift. So, in my Craftmod code, lines by trp_player serve as system output for the crafting system, and lines by trp_player|plyr serve as system input via dialogue menu options.

Lucidly,
Winter
 
Copied from the Limited Ammo thread:

My friends of the Mod Discussion board, I present to you the Limited Ammo script.

It is free for all to use, given proper credit.

The only trouble is, it still has a few bugs I haven't caught yet, so I'm pulling it until they're fixed.

Powerfully,
Winter
 
Okay, it looks like the main problems with the limited ammo script have been solved. There may be a bug remaining somewhere, but I can't find it. Please post here if you run into one.

[EDIT] Added the AI bows, which were missing from the script and were thereby rendering it inoperable. Goes to show how many people are using this script, eh? [/EDIT]

The script, with instructions:


# MODULE_ITEMS
#
# These arrows need to be near the beginning of the module_items list, as they use troop
# slots on trp_player which are equal to the arrows' entry number. There is a limited number
# of slots, so if the arrows are (for example) number 500+ in the items file, this script
# will cease to work.
#
# Make sure none of the slots used in this script conflict with slots you may have already
# used in your mod. You can see the numbers of each item entry in ID_items.py.
#
# If you haven't modded any of trp_player's slots, then you have nothing to worry about.
#
# Replace the Native arrow entries with the following block.
#
# After you have done this, replace all mention of itm_arrows in module_troops with
# itm_ai_arrows. By doing this, AI arrows will not run out after 1 shot, they will
# not be considered by the limited ammo script, and they will not be lootable or available
# at merchants.

["ai_arrows","arrows", [("arrow",0)], itp_type_arrows|itp_unique, 0, 0,weight(3)|abundance(160)|weapon_length(95)|thrust_damage(1,pierce)|max_ammo(24),imodbits_missile],

["arrows","arrows", [("arrow",0)], itp_type_arrows|itp_merchandise, 0, 36,weight(3)|abundance(160)|weapon_length(95)|thrust_damage(1,pierce)|max_ammo(1),imodbits_missile],
["barbed_arrows","barbed_arrows", [("barbed_arrow",0)], itp_type_arrows|itp_merchandise, 0, 68,weight(3)|abundance(70)|weapon_length(95)|thrust_damage(2,pierce)|max_ammo(1),imodbits_missile],
["bodkin_arrows","bodkin_arrows", [("piercing_arrow",0)], itp_type_arrows|itp_merchandise, 0, 124,weight(3)|abundance(50)|weapon_length(100)|thrust_damage(3,pierce)|max_ammo(1),imodbits_missile],
["bolts","bolts", [("bolt",0)], itp_type_bolts|itp_merchandise, 0, 32,weight(2.25)|abundance(90)|weapon_length(55)|thrust_damage(1,pierce)|max_ammo(2),imodbits_missile],


# Replace the Native bow and crossbow entries with the following block:

["hunting_bow",         "hunting_bow", [("hunting_bow",0)], itp_type_bow |itp_merchandise|itp_primary|itp_two_handed,itcf_shoot_bow, 17 , weight( 1 )|difficulty( 0 )|spd_rtng( 94 ) | shoot_speed( 46 ) | thrust_damage( 15 , pierce ),imodbits_bow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_hunting_bow"),(assign,"$range_low","itm_arrows"),(assign,"$range_high","itm_bolts"),(call_script,"script_limited_ammo")])]],
["short_bow",         "short_bow", [("short_bow",0)], itp_type_bow |itp_merchandise|itp_primary|itp_two_handed ,itcf_shoot_bow, 58 , weight(1)|difficulty(1)|spd_rtng(9:cool: | shoot_speed(49) | thrust_damage(16 ,  pierce  ),imodbits_bow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_short_bow"),(assign,"$range_low","itm_arrows"),(assign,"$range_high","itm_bolts"),(call_script,"script_limited_ammo")])]],
["nomad_bow",         "nomad_bow", [("nomad_bow",0)], itp_type_bow |itp_merchandise|itp_primary|itp_two_handed ,itcf_shoot_bow, 154 , weight(1.25)|difficulty(2)|spd_rtng(96) | shoot_speed(51) | thrust_damage(18 ,  pierce),imodbits_bow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_nomad_bow"),(assign,"$range_low","itm_arrows"),(assign,"$range_high","itm_bolts"),(call_script,"script_limited_ammo")])]],
["long_bow",         "long_bow", [("long_bow",0)], itp_type_bow |itp_merchandise|itp_primary|itp_two_handed ,itcf_shoot_bow, 67 , weight(1.75)|difficulty(3)|spd_rtng(82) | shoot_speed(51) | thrust_damage(19 ,  pierce),imodbits_bow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_long_bow"),(assign,"$range_low","itm_arrows"),(assign,"$range_high","itm_bolts"),(call_script,"script_limited_ammo")])]],
["khergit_bow",         "khergit_bow", [("khergit_bow",0)], itp_type_bow |itp_merchandise|itp_primary|itp_two_handed,itcf_shoot_bow, 164 , weight(1.25)|difficulty(3)|spd_rtng(95) | shoot_speed(54) | thrust_damage(20 ,pierce),imodbits_bow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_khergit_bow"),(assign,"$range_low","itm_arrows"),(assign,"$range_high","itm_bolts"),(call_script,"script_limited_ammo")])]],
["strong_bow",         "strong_bow", [("strong_bow",0)], itp_type_bow |itp_merchandise|itp_primary|itp_two_handed ,itcf_shoot_bow, 251 , weight(1.25)|difficulty(3)|spd_rtng(94) | shoot_speed(55) | thrust_damage(21 ,pierce),imodbits_bow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_strong_bow"),(assign,"$range_low","itm_arrows"),(assign,"$range_high","itm_bolts"),(call_script,"script_limited_ammo")])]],
["war_bow",         "war_bow",  [("war_bow",0)],itp_type_bow|itp_merchandise|itp_primary|itp_two_handed ,itcf_shoot_bow, 304 , weight(1.5)|difficulty(4)|spd_rtng(93) | shoot_speed(56) | thrust_damage(22 ,pierce),imodbits_bow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_war_bow"),(assign,"$range_low","itm_arrows"),(assign,"$range_high","itm_bolts"),(call_script,"script_limited_ammo")])]],

["hunting_crossbow", "hunting_crossbow", [("crossbow",0)], itp_type_crossbow |itp_merchandise|itp_primary|itp_two_handed ,itcf_shoot_crossbow, 3 , weight(2.25)|difficulty(0)|spd_rtng(44) | shoot_speed(50) | thrust_damage(24 ,  pierce)|max_ammo(1),imodbits_crossbow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_hunting_crossbow"),(assign,"$range_low","itm_bolts"),(assign,"$range_high","itm_cartridges"),(call_script,"script_limited_ammo")])]],
["light_crossbow", "light_crossbow", [("light_crossbow",0)], itp_type_crossbow |itp_merchandise|itp_primary|itp_two_handed ,itcf_shoot_crossbow, 32 , weight(2.5)|difficulty(:cool:|spd_rtng(43) | shoot_speed(59) | thrust_damage(33 ,  pierce)|max_ammo(1),imodbits_crossbow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_light_crossbow"),(assign,"$range_low","itm_bolts"),(assign,"$range_high","itm_cartridges"),(call_script,"script_limited_ammo")])]],
["crossbow",         "crossbow",         [("crossbow",0)], itp_type_crossbow |itp_merchandise|itp_primary|itp_two_handed|itp_cant_use_on_horseback ,itcf_shoot_crossbow, 149 , weight(3)|difficulty(:cool:|spd_rtng(42) | shoot_speed(6:cool: | thrust_damage(42,pierce)|max_ammo(1),imodbits_crossbow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_crossbow"),(assign,"$range_low","itm_bolts"),(assign,"$range_high","itm_cartridges"),(call_script,"script_limited_ammo")])]],
["heavy_crossbow", "heavy_crossbow", [("heavy_crossbow",0)], itp_type_crossbow |itp_merchandise|itp_primary|itp_two_handed|itp_cant_use_on_horseback ,itcf_shoot_crossbow, 291 , weight(3.5)|difficulty(9)|spd_rtng(40) | shoot_speed(72) | thrust_damage(47 ,pierce)|max_ammo(1),imodbits_crossbow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_heavy_crossbow"),(assign,"$range_low","itm_bolts"),(assign,"$range_high","itm_cartridges"),(call_script,"script_limited_ammo")])]],
["sniper_crossbow", "sniper_crossbow", [("heavy_crossbow",0)], itp_type_crossbow |itp_merchandise|itp_primary|itp_two_handed|itp_cant_use_on_horseback ,itcf_shoot_crossbow, 450 , weight(3.75)|difficulty(10)|spd_rtng(3:cool: | shoot_speed(74) | thrust_damage(52 ,pierce)|max_ammo(1),imodbits_crossbow,
[(ti_on_weapon_attack, [(assign,reg(3),0),(assign,"$pin_item","itm_sniper_crossbow"),(assign,"$range_low","itm_bolts"),(assign,"$range_high","itm_cartridges"),(call_script,"script_limited_ammo")])]],

# Place extra bows and crossbows before this point, and add an AI equivalent bow at the
# same location at the end of the AI bows list.
# The AI bows have no attached scripts so that they will not drain the player's ammo.
# AI weapons are automatically placed in the inventory of all non-player troops; you can
# give them the normal scripted bows, and everything will still function as normal.

["hunting_bow_ai",         "hunting_bow", [("hunting_bow",0)], itp_type_bow |itp_unique|itp_primary|itp_two_handed,itcf_shoot_bow, 17 , weight(1)|abundance(0)|difficulty(0)|spd_rtng(100) | shoot_speed(46) | thrust_damage(14 ,  pierce),imodbits_bow ],
["short_bow_ai",         "short_bow", [("short_bow",0)], itp_type_bow |itp_unique|itp_primary|itp_two_handed ,itcf_shoot_bow, 58 , weight(1)|abundance(0)|difficulty(1)|spd_rtng(9:cool: | shoot_speed(49) | thrust_damage(16 ,  pierce  ),imodbits_bow ],
["nomad_bow_ai",         "nomad_bow", [("nomad_bow",0)], itp_type_bow |itp_unique|itp_primary|itp_two_handed ,itcf_shoot_bow, 154 , weight(1.25)|abundance(0)|difficulty(2)|spd_rtng(96) | shoot_speed(51) | thrust_damage(18 ,  pierce),imodbits_bow ],
["long_bow_ai",         "long_bow", [("long_bow",0)], itp_type_bow |itp_unique|itp_primary|itp_two_handed ,itcf_shoot_bow, 67 , weight(1.75)|abundance(0)|difficulty(3)|spd_rtng(82) | shoot_speed(51) | thrust_damage(19 ,  pierce),imodbits_bow ],
["khergit_bow_ai",         "khergit_bow", [("khergit_bow",0)], itp_type_bow |itp_unique|itp_primary|itp_two_handed,itcf_shoot_bow, 164 , weight(1.25)|abundance(0)|difficulty(3)|spd_rtng(95) | shoot_speed(54) | thrust_damage(20 ,pierce),imodbits_bow ],
["strong_bow_ai",         "strong_bow", [("strong_bow",0)], itp_type_bow |itp_unique|itp_primary|itp_two_handed ,itcf_shoot_bow, 251 , weight(1.25)|abundance(0)|difficulty(3)|spd_rtng(94) | shoot_speed(55) | thrust_damage(21 ,pierce),imodbits_bow ],
["war_bow_ai",         "war_bow",  [("war_bow",0)],itp_type_bow|itp_unique|itp_primary|itp_two_handed ,itcf_shoot_bow, 304 , weight(1.5)|abundance(0)|difficulty(4)|spd_rtng(93) | shoot_speed(56) | thrust_damage(22 ,pierce),imodbits_bow ],
["hunting_crossbow_ai", "hunting_crossbow", [("crossbow",0)], itp_type_crossbow |itp_unique|itp_primary|itp_two_handed ,itcf_shoot_crossbow, 3 , weight(2.25)|abundance(0)|difficulty(0)|spd_rtng(44) | shoot_speed(50) | thrust_damage(24 ,  pierce)|max_ammo(1),imodbits_crossbow ],
["light_crossbow_ai", "light_crossbow", [("light_crossbow",0)], itp_type_crossbow |itp_unique|itp_primary|itp_two_handed ,itcf_shoot_crossbow, 32 , weight(2.5)|abundance(0)|difficulty(:cool:|spd_rtng(43) | shoot_speed(59) | thrust_damage(33 ,  pierce)|max_ammo(1),imodbits_crossbow ],
["crossbow_ai",         "crossbow",         [("crossbow",0)], itp_type_crossbow |itp_unique|itp_primary|itp_two_handed|itp_cant_use_on_horseback ,itcf_shoot_crossbow, 149 , weight(3)|abundance(0)|difficulty(:cool:|spd_rtng(42) | shoot_speed(6:cool: | thrust_damage(42,pierce)|max_ammo(1),imodbits_crossbow ],
["heavy_crossbow_ai", "heavy_crossbow", [("heavy_crossbow",0)], itp_type_crossbow |itp_unique|itp_primary|itp_two_handed|itp_cant_use_on_horseback ,itcf_shoot_crossbow, 291 , weight(3.5)|abundance(0)|difficulty(9)|spd_rtng(40) | shoot_speed(72) | thrust_damage(47 ,pierce)|max_ammo(1),imodbits_crossbow ],
["sniper_crossbow_ai", "sniper_crossbow", [("heavy_crossbow",0)], itp_type_crossbow |itp_unique|itp_primary|itp_two_handed|itp_cant_use_on_horseback ,itcf_shoot_crossbow, 450 , weight(3.75)|abundance(0)|difficulty(10)|spd_rtng(3:cool: | shoot_speed(74) | thrust_damage(52 ,pierce)|max_ammo(1),imodbits_crossbow ],


# MODULE_SCRIPTS
# Add the following scripts to the bottom of your module_scripts file:


  ("limited_ammo",
   [
# This script subtracts the shot from the player's ammo, and removes ammo where appropriate.
(assign,reg(3),0),
(get_player_agent_no,reg(5)),
(troop_has_item_equipped,"trp_player","$pin_item"),
(try_for_range_backwards,reg(1),"$range_low","$range_high"),
(troop_has_item_equipped,"trp_player",reg(1)),
(try_begin),
(neq,reg(3),1),
(val_add,"$ammo_used",1),
(troop_get_slot,reg(2),"trp_player",reg(1)),
(val_add,reg(2),1),
(troop_set_slot,"trp_player",reg(1),reg(2)),
(str_store_item_name,1,reg(1)),
(call_script,"script_get_ammo_num"),
(assign,reg(4),"$ammo_num"),
(val_sub,reg(4),reg(2)),
(display_message,"str_arrow_fired"),
(assign,reg(3),1),
(try_begin),
(troop_get_slot,reg(2),"trp_player",reg(1)),
(ge,reg(2),"$ammo_num"),
(troop_set_slot,"trp_player",reg(1),0),
(troop_remove_items,"trp_player",reg(1),1),
(try_end),
(try_end),
(try_begin),
(troop_has_item_equipped,"trp_player",reg(1)),
(agent_refill_ammo,reg(5)),
(try_end),
(try_end),
    ]),

  ("get_ammo_num",
   [
# This script sets the appropriate maximum ammo numbers for each type of ammo.
(try_begin),
(is_between,reg(1),"itm_arrows","itm_bolts"),
(assign,"$ammo_num",24),
(else_try),
(is_between,reg(1),"itm_bolts","itm_cartridges"),
(assign,"$ammo_num",20),
(try_end),
    ]),

  ("limited_ammo_before_combat_start",
   [
# This script identifies the player's ammo and replaces all AI troops' bows with AI bows.
(assign,reg(2),0),
(try_for_range_backwards,reg(1),"itm_arrows","itm_cartridges"),
(troop_has_item_equipped,"trp_player",reg(1)),
(eq,reg(2),0),
(assign,"$ammo_type",reg(1)),
(assign,reg(2),1),
(try_end),
(try_for_range,reg(1),"trp_novice_fighter","trp_troops_end"),
(troop_set_slot,reg(1),10,0),
(troop_set_slot,reg(1),11,0),
(try_for_range,reg(2),"itm_arrows","itm_cartridges"),
(store_item_kind_count,reg(3),reg(2),reg(1)),
(gt,reg(3),0),
(troop_set_slot,reg(1),10,reg(2)),
(troop_set_slot,reg(1),11,reg(3)),
(troop_remove_items,reg(1),reg(2),reg(3)),
(troop_add_items,reg(1),"itm_ai_arrows",reg(3)),
(try_end),
(try_for_range,reg(2),"itm_hunting_bow","itm_hunting_bow_ai"),
(store_item_kind_count,reg(3),reg(2),reg(1)),
(gt,reg(3),0),
(assign,reg(4),reg(2)),
(assign,reg(5),"itm_hunting_bow"),
(assign,reg(6),"itm_hunting_bow_ai"),
(val_sub,reg(6),reg(5)),
(val_add,reg(4),reg(6)),
(troop_remove_items,reg(1),reg(2),reg(3)),
(troop_add_items,reg(1),reg(4),reg(3)),
(try_end),
(try_end),
    ]),

  ("limited_ammo_on_leave_area",
   [
# This script handles arrow recovery and puts AI bows and arrows back to normal.
(assign,reg(5),0),
(try_for_range_backwards,reg(1),"itm_arrows","itm_pilgrim_disguise"),
(troop_has_item_equipped,"trp_player",reg(1)),
(try_begin),
(gt,"$ammo_used",0),
(eq,reg(5),0),
(store_random_in_range,reg(3),0,"$ammo_used"),
(store_random_in_range,reg(4),0,"$ammo_used"),
(val_sub,reg(3),reg(4)),
(call_script,"script_get_ammo_num"),
(val_sub,"$ammo_num",1),
(troop_get_slot,reg(2),"trp_player",reg(1)),
(try_begin),
(lt,reg(3),0),
(assign,reg(3),0),
(else_try),
(assign,reg(6),reg(3)),
(val_add,reg(6),reg(2)),
(gt,reg(6),"$ammo_num"),
(assign,reg(6),"$ammo_num"),
(val_sub,reg(6),reg(2)),
(assign,reg(3),reg(6)),
(try_end),
(val_add,reg(2),reg(3)),
(troop_set_slot,"trp_player",reg(1),reg(2)),
(str_store_item_name,1,reg(1)),
(display_message,"str_recover_arrows"),
(assign,reg(5),1),
(try_end),
(try_end),
(try_begin),
(neq,"$ammo_type",0),
(neg|troop_has_item_equipped,"trp_player","$ammo_type"),
(gt,"$ammo_used",0),
(store_random_in_range,reg(3),0,"$ammo_used"),
(store_random_in_range,reg(4),0,"$ammo_used"),
(val_sub,reg(3),reg(4)),

(assign,reg(1),"$ammo_type"),
(call_script,"script_get_ammo_num"),
(val_sub,"$ammo_num",1),

(try_begin),
(lt,reg(3),5),
(assign,reg(3),0),
(else_try),
(gt,reg(3),"$ammo_num"),
(assign,reg(3),"$ammo_num"),
(try_end),
(try_begin),
(ge,reg(3),5),
(troop_add_items,"trp_player","$ammo_type",1),
(troop_get_slot,reg(2),"trp_player",reg(1)),
(val_add,reg(2),reg(3)),
(troop_set_slot,"trp_player",reg(1),reg(2)),
(str_store_item_name,1,reg(1)),
(display_message,"str_recover_arrows"),
(try_end),
(try_end),

(assign,"$ammo_used",0),

(try_for_range,reg(1),"trp_novice_fighter","trp_troops_end"),
(troop_get_slot,reg(2),reg(1),10),
(troop_get_slot,reg(3),reg(1),11),
(try_begin),
(store_item_kind_count,reg(4),"itm_ai_arrows",reg(1)),
(gt,reg(4),0),
(troop_remove_items,reg(1),"itm_ai_arrows",reg(4)),
(troop_add_items,reg(1),reg(2),reg(3)),
(try_end),
(try_for_range,reg(4),"itm_hunting_bow_ai","itm_flintlock_pistol"),
(store_item_kind_count,reg(5),reg(4),reg(1)),
(gt,reg(5),0),
(assign,reg(6),reg(4)),
(assign,reg(7),"itm_hunting_bow"),
(assign,reg(:cool:,"itm_hunting_bow_ai"),
(val_sub,reg(:cool:,reg(7)),
(val_sub,reg(6),reg(:cool:),
(troop_remove_items,reg(1),reg(4),reg(5)),
(troop_add_items,reg(1),reg(6),reg(5)),
(try_end),
(try_end),
    ]),


# MODULE_STRINGS
# Add the following strings to the bottom of your module_strings file:

  ("arrow_fired", "You have {reg4} {s1} left in this quiver!"),
  ("recover_arrows", "At the end of the battle, you manage to recover {reg3} {s1}."),


# MODULE_MISSION_TEMPLATES
# Append the following mission template triggers to any template where you wish to have
# recoverable player ammunition.
# Native templates that have combat in them:
# "lead_charge", "charge_with_allies", "castle_attack_walls", "sneak_caught_fight",
# "betrayed_by_lord".


      (ti_before_mission_start, 0, 0, [], [
(assign,"$ammo_used",0),
(call_script,"script_limited_ammo_before_combat_start"),
]),

      (ti_on_leave_area, 0, 0, [], [
(call_script,"script_limited_ammo_on_leave_area")
]),

# When done, add the following line to your chosen mission templates after every instance of (finish_mission,1)

(call_script,"script_limited_ammo_on_leave_area"),


This script is free for one and all to use, with credit. You do not need to ask for permission.

Generously,
Winter
 
Python to make missions end when you reach a certain point on the map, regardless of whatever else is going on.  This is basically just the code already in Vanilla in the mission template for the "sneak into town" mission, it's just commented out (because it doesn't work, although that's probably not the reason it wasn't included.)

In mission_templates change this:
     
(0.1, 0, 0, [],
      [
#          (neg|main_hero_fallen),
#          (get_player_agent_no, reg(1)),
#          (agent_get_position, 1, reg(1)),
#          (entry_point_get_position,2,31),
#          (get_distance_between_positions, reg(10), 1, 2),
#          (lt, reg(10), 500), #Our distance to exit is less than 4m.
#          (jump_to_menu,"mnu_sneak_into_town_caught_ran_away"),
#          (finish_mission,1),
        ]),
    ],

To this:

#Set "$test_thirty_midgets" to something other than one prior to here;
#(ti_before_mission_start, 0, 0, [], [(assign,"$test_thirty_midgets",0)]),
#works well.

    (0.1, 0, 0, [(neg|main_hero_fallen),(neq,"$test_thirty_midgets",1)],
      [
          #A Shameless Copy From Above
          (get_player_agent_no, reg(1)),
          (agent_get_position, 1, reg(1)),
          (entry_point_get_position,2,31),
          (get_distance_between_positions, reg(10), 1, 2),
          (lt, reg(10), 500), #Our distance to exit is less than 4m.
          (jump_to_menu,"mnu_frogs_taste_like_chicken"),
          (assign,"$test_thirty_midgets",1),
          (finish_mission,1),
        ]),
    ],

Basically, this just ends the mission if the player ever gets to within 4m of entry point number thirty-one, and initiates the indicated menu.  Not exactly original, as it's mostly just a shameless copy from native, but oh well.
 
Python to make people wander around town when you visit:

(
    "testy_test",0,-1,
    "Visit Testy-Test.",
    [
     (0,mtef_leader_only|mtef_team_1,0,0,1,[]),
     (1,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (2,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (3,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (4,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (5,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (6,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (7,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (8,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (9,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (10,mtef_scene_source|mtef_team_1,af_override_horse|af_override_head|af_override_weapons,aif_start_alarmed,1,[]),
     (11,mtef_scene_source|mtef_team_1,af_override_horse|af_override_head|af_override_weapons,aif_start_alarmed,1,[]),
     (12,mtef_scene_source|mtef_team_1,af_override_horse|af_override_head|af_override_weapons,aif_start_alarmed,1,[]),
     (13,mtef_scene_source|mtef_team_1,af_override_horse|af_override_head|af_override_weapons,aif_start_alarmed,1,[]),
     (14,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (15,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (16,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (17,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (18,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (19,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (20,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (21,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (22,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (23,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (24,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (25,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (26,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (27,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (28,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (29,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     (30,mtef_scene_source,af_override_horse|af_override_head|af_override_weapons,0,1,[]),
     #One Enemy Must be on Scene
     (31,mtef_scene_source|mtef_team_2,af_override_horse|af_override_weapons,aif_start_alarmed,1,[]),
   
     ],[
         
    (ti_before_mission_start,0,0,[],[
        (assign,"$walker_1",0),
        (assign,"$walker_2",0),
        (assign,"$walker_3",0),
        (assign,"$walker_4",0),
        (assign,"$enemy_walker",0),
           ]),
    #This trigger sets up the four walkers
    (.1, 0, ti_once, [],[
       (try_for_agents,reg(5)),
             (assign,reg(0),0), 
             #Not the player
             (neq, reg(5), reg(20)),
             #Not Dead
             (agent_is_alive, reg(5)),
             #Not a Horse?
             (agent_is_human, reg(5)),
             #If the Selected Troop is an Ally
             (agent_is_ally,reg(5)),
             (try_begin),
                 (eq,"$walker_1",0),
                    (assign,"$walker_1",reg(5)),
                    (agent_set_slot,"$walker_1",0,0),
                    #Set up walker_1's pattern; he will walk to all of the entry points until -1,
                    #then start back to the first
                    (agent_set_slot,"$walker_1",1,11),
                    (agent_set_slot,"$walker_1",2,10),
                    (agent_set_slot,"$walker_1",3,12),
                    (agent_set_slot,"$walker_1",4,13),
                    (agent_set_slot,"$walker_1",5,-1),
                    (assign,reg(0),1),
            (else_try),
                    (eq,"$walker_2",0),
                    (eq,reg(0),0),
                    (assign,"$walker_2",reg(5)),
                    (agent_set_slot,"$walker_2",0,0),
                    #Set up walker_2's pattern; see above
                    (agent_set_slot,"$walker_2",1,12),
                    (agent_set_slot,"$walker_2",2,10),
                    (agent_set_slot,"$walker_2",3,7),
                    (agent_set_slot,"$walker_2",4,-1),
                    (assign,reg(0),1),
            (else_try),
                    (eq,"$walker_3",0),
                    (eq,reg(0),0),
                    (assign,"$walker_3",reg(5)),
                    (agent_set_slot,"$walker_3",0,0),
                    #Set up walker_3's pattern; see above
                    (agent_set_slot,"$walker_3",1,10),
                    (agent_set_slot,"$walker_3",2,6),
                    (agent_set_slot,"$walker_3",3,-1),
                    (assign,reg(0),1),
            (else_try),
                    (eq,"$walker_4",0),
                    (eq,reg(0),0),
                    (assign,"$walker_4",reg(5)),
                    (agent_set_slot,"$walker_4",0,0),
                    #Set up walker_4's pattern; see above
                    (agent_set_slot,"$walker_4",1,13),
                    (agent_set_slot,"$walker_4",2,11),
                    (agent_set_slot,"$walker_4",3,12),
                    (agent_set_slot,"$walker_4",4,-1),
                    (assign,reg(0),1),
             (try_end),
        (try_end),
        ]),

  #This Trigger Assigns all Entry Point Positions
  (.1, 0, ti_once, [],[
        (entry_point_get_position,0,0),(entry_point_get_position,1,1),(entry_point_get_position,2,2),
        (entry_point_get_position,3,3),(entry_point_get_position,4,4),(entry_point_get_position,5,5),
        (entry_point_get_position,6,6),(entry_point_get_position,7,7),(entry_point_get_position,8,:cool:,
        (entry_point_get_position,9,9),(entry_point_get_position,10,10),(entry_point_get_position,11,11),
        (entry_point_get_position,12,12),(entry_point_get_position,13,13),(entry_point_get_position,14,14),
        (entry_point_get_position,15,15),(entry_point_get_position,16,16),(entry_point_get_position,17,17),
        (entry_point_get_position,18,1:cool:,(entry_point_get_position,19,19),(entry_point_get_position,20,20),
        (entry_point_get_position,21,21),(entry_point_get_position,22,22),(entry_point_get_position,23,23),
        (entry_point_get_position,24,24),(entry_point_get_position,25,25),(entry_point_get_position,26,26),
        (entry_point_get_position,27,27),(entry_point_get_position,28,2:cool:,(entry_point_get_position,29,29),
        (entry_point_get_position,30,30),(entry_point_get_position,31,31),
        ]),

    #This Trigger Sets up the Enemy Walker
    (.1, 0, ti_once, [],[
      (try_for_agents,reg(5)), 
            #Not the player
            (neq, reg(5), reg(20)),
            #Not Dead
            (agent_is_alive, reg(5)),
            #Not a Horse?
            (agent_is_human, reg(5)),
            #Not Friendly
            (neg|agent_is_ally,reg(5)),
            (agent_get_position,32,reg(5)),
            (get_distance_between_positions, reg(2), 32, 31),
            #If Agent is close to EP 31, it must be our enemy
            (try_begin),
                  (lt,reg(2),500),
                      (agent_set_scripted_destination,reg(5),31),
                      (assign,"$enemy_walker",reg(5)),
            (try_end),
      (try_end),
        ]),

    #Tell the Walkers to Move Around
    (.1, 0, .4, [],[
        (agent_get_position,32,"$enemy_walker"),
        (get_distance_between_positions, reg(2), 32, 31),
        (try_begin),
            (gt,reg(2),300),
            (agent_set_scripted_destination,"$enemy_walker",31),
        (else_try),
            (le,reg(2),300),
            (agent_set_scripted_destination,"$enemy_walker",30),
        (try_end),

        (try_for_range,reg(3),1,5),
            (try_begin),
                (eq,reg(3),1),
                (assign,reg(4),"$walker_1"),
            (else_try),
                (eq,reg(3),2),
                (assign,reg(4),"$walker_2"),
            (else_try),
                (eq,reg(3),3),
                (assign,reg(4),"$walker_3"),
            (else_try),
                (eq,reg(3),4),
                (assign,reg(4),"$walker_4"),
            (try_end),
       
            #Walk that Pattern!
            (try_begin),
                (neq,reg(4),0),
                (agent_get_position,32,reg(4)),
                (agent_get_slot,reg(0),reg(4),0),
                (agent_get_slot,reg(1),reg(4),reg(0)),

                (try_begin),
                    (eq,reg(0),0),
                    (agent_get_slot,reg(1),reg(4),1),
                    (agent_set_scripted_destination,reg(4),reg(1)),
                    (agent_set_slot,reg(4),0,1),
                (else_try),
                    (neq,reg(0),0),
                    (get_distance_between_positions, reg(2), 32, reg(1)),
                    (lt,reg(2),400),
                        (val_add,reg(0),1),
                        (agent_get_slot,reg(1),reg(4),reg(0)),
                        (try_begin),
                            (gt,reg(1),0),
                            (agent_set_scripted_destination,reg(4),reg(1)),
                            (agent_set_slot,reg(4),0,reg(0)),
                        (else_try),
                            (lt,reg(1),0),
                            (agent_get_slot,reg(1),reg(4),1),
                            (agent_set_scripted_destination,reg(4),reg(1)),
                            (agent_set_slot,reg(4),0,1),
                        (try_end),
                (try_end),
            (try_end),
        (try_end),     
    ]),
]),

Instructions for use:
  • 1. Add entry point (EP) 31 to the town scene, making it somewhere far out of sight and impossible to move from (ai barriers surrounding the entry point work nicely.)
  • 2. Add a troop to the scene, at EP 31.
  • 3. Add EP 30 near EP 31, so that the NPC at 31 can walk to it.
  • 4. That's it.  Just use the mission template "testy_test" (or whatever) instead of "visit_town_default" (or whatever) when you go to a town's scene.

Now, every time you use the mission template "testy_test" to go to a scene, the troops at EP's  number 10, 11, 12, and 13 will walk around.  In the code above, the troop at EP 10 will walk to EP 11, then 12, then 13, then back to EP 11.  The troop at EP 11 will walk to EP 12, then 10, then 7, then back to 12.  Hopefully, you'll notice the pattern.  If you do, you will also notice that it is a simple matter to increase/decrease the number of troops that wander around.

Caveats:  You'll probably want to weigh the walkers down with some really heavy clothes, so they actually walk around town, instead of running.

Enjoy!

EDIT:  Thanks to Winter's whining and complaining :razz: about a few war-cries, I went ahead and fixed the above so that the NPC's no longer shout.
 
silverkatana said:
Caveats:  You'll probably want to weigh the walkers down with some really heavy clothes, so they actually walk around town, instead of running.

Someone's been looking hard at Craftmod! :razz:

Another caveat you missed is that the walkers will still scream their battle cries at the tops of their lungs. I solved this for Craftmod, it'll be in the source when I get to releasing it.

Decayingly,
Winter
 
Actually, it grew out of something else that I've been trying to do (still unsuccessfully, but I haven't given up yet.)  I didn't know that you had such a system in Craftmod, but I'm not surprised.  My quest for an original idea will just have to continue, I suppose.

EDIT:  Version 2.0 of Wandering NPC's is now out!  More dancing!  Less shouting!  Fun to be had by all!  See above for details!  Disclaimer: I just threw the no-shout fix together.  It might not be the most elegant solution, but it works.  Any more complaints, Mr. Craftmod-Is-So-Great?  :wink:
 
Back
Top Bottom