PYTHON SCRIPT/SCHEME EXCHANGE

Users who are viewing this thread

please post your workin' code with details here only.. this is a no discussion thread so keep it clean pls! for all other stuff create a separate topic :smile:
 
A long (long) time ago I played an awesome RPG named Earthdawn.  One of the fun features it has is equipment that grows in power as your characters do.  So why can't we have that in M&B?

NOW YOU CAN!

This stuff is free to use for anyone who can figure out how to make it work, just give credit when releasing to other people.

How it works:
The system is pretty simple.  I eat up to 8 slots on each item and at least one item tuple per item level.  For mods that have *TONS* of items, this is not going to be ideal.  At init time I set up a bunch of data manually on each artifact item.  The setup data on an item includes a slot to see if it's an artifact, a slot storing its current exp, a slot storing its max exp until level, a slot storing the item it morphs into when it does level, and three effects that the item can give when equipped. 

There are two scripts that are crucial here:  script_game_get_item_extra_text which is used to put the nice rollover text to tell you how uber your stuff is, and script_game_get_skill_modifier_for_troop which adds the actual bonus.  There's a little messiness because I didn't want to use two slots per effect type so I bit packed it into the same value (second most significant byte is the value, lowest byte is the skill).  There's also a pile of utility scripts that push data around for ease of use and a hook that you can put into your mod for adding exp to the item.

As an added note, the slots used to store this stuff are shared for all items of a given type.  If there's a way to stick slots on an item instance, I don't know what it is.  This mod (at least the levelling bits) is for unique items only.

Also!  For those of you familiar with KON_Air's awesome set mod, I use some of the same tricks.  The two should be compatible for anyone willing to monkey with it a bit.

The code is pretty straightforward.  It's entirely possible that I've forgotten some part of it.  Let me know when you find those.  Also, I've tested this a bit but not tremendously so when you find bugs, let me know about those too.  Finally, I didn't fill everything out for all skills; I'm lazy.  It should be pretty clear what needs to be added and I've left some comments as well.

Stuff in module_constants.py which I stuck after the other item slot stuff:
# kt0:  added these
kt_slot_item_experience = 5 # currently earned experience
kt_slot_item_max_experience = 6 # max experience for this item level (not cumulative)
kt_slot_item_next_item = 7 # next item in the chain, 0 for none (can't start item list with artifacts)
kt_slot_item_is_artifact = 8 # is or isn't, no other values
kt_slot_item_effect1 = 9 # effect type #1
kt_slot_item_effect2 = 10 # effect type #2
kt_slot_item_effect3 = 11 # effect type #3

# stuff that goes into item slots but that aren't slots themselves
# we keep the high 16 bits for the value and the low 16 bits for
# the skill ID so a zero check on the slot is all we need.

# these are basically the ones i use because i'm too lazy to write out the
# code to add them inline. 
kt_item_effect_power_strike_1 = 65571
kt_item_effect_power_strike_2 = 131107
kt_item_effect_power_strike_3 = 196643
kt_item_effect_power_strike_4 = 262179
kt_item_effect_power_strike_5 = 327715
kt_item_effect_tactics_5 = 327695

New scripts in module_scripts.py (I stuck mine at the bottom):
# add artifact experience, doesn't necessarily need to be postive but was
# intended that way.  adds to all equipped artifacts though again, doesn't
# necessarily need to be that way.
# INPUT: 
#    arg1:  exp to add
# OUTPUT:  none
# SIDE EFFECTS:
#    can cause item swappage if the artifact levels.
( "kt_add_artifact_exp",
[
(store_script_param_1, ":exp"),

# check every slot for an equipped artifact
(try_for_range, ":i_equipped", ek_item_0, ek_food),
(troop_get_inventory_slot, ":item", "trp_player", ":i_equipped"),
(try_begin),
(neq, ":item", -1),
(item_slot_ge, ":item", kt_slot_item_is_artifact, 1),
(str_store_item_name, s20, ":item"),
(item_get_slot, reg10, ":item", kt_slot_item_experience),
(item_get_slot, reg11, ":item", kt_slot_item_max_experience),
(item_get_slot, reg12, ":item", kt_slot_item_next_item),
# give some exp to the thing
(val_add, reg10, ":exp"),
(try_begin),
(ge, reg10, reg11),
(neg|eq, reg12, 0),
(troop_set_inventory_slot, "trp_player", ":i_equipped", reg12),
(call_script, "script_kt_display_artifact_level_message", reg12), # display on the new item
# re-grab and add carryover exp
(store_sub, ":carryover", reg10, reg11),
(troop_get_inventory_slot, ":item", "trp_player", ":i_equipped"),
(item_set_slot, ":item", kt_slot_item_experience, ":carryover"),
(else_try),
(neg|eq, reg12, 0), # if we can't upgrade, no point in adding exp
(item_set_slot, ":item", kt_slot_item_experience, reg10),
(try_end),
(try_end),
(try_end),
]),

# displays a message to the user saying that their artifact has levelled.
# this can be tailored per level per artifact or whatnot.  i might add a
# message slot as well for more control.  it's basically a giant switch on
# type that you can fill out to your liking.
# INPUT:
#    arg1:  item ID
( "kt_display_artifact_level_message",
[
(store_script_param_1, ":item"),
(try_begin),
(this_or_next|eq, ":item", itm_sword_artifact_test_1),
(this_or_next|eq, ":item", itm_sword_artifact_test_2),
(eq, ":item", itm_sword_artifact_test_3),
(str_store_item_name, s10, ":item"),
(display_message, "@Your {s10} feels different...more...uber...", 0xFF00FFFF),
(else_try),
(eq, ":item", itm_sword_artifact_test_4),
(display_message, "@Your {s10} feels different...more...uber...", 0xFF00FFFF),
(display_message, "@You have a feeling that this is as uber as it will become.  The LAST WORD in killage!", 0xFF00FFFF),
(else_try),
(display_message, "@One of your artifacts has upgraded.", 0xFF00FFFF),
(try_end),
]),

# parses the given effect id for an artifact and fills out reg0 with the
# add value and s2 with the skill name.
# INPUT:
#    arg1:  effect mask
# OUTPUT:
#    reg0:  the bonus amount
#    s2:    the name of the skill
( "kt_parse_values_from_item_effect",
[
(store_script_param_1, ":effect"),
(str_clear, s2),
(assign, ":bonus", ":effect"),
(val_and, ":bonus", 16711680), # just a byte
(val_div, ":bonus", 65536),
(assign, ":skill", ":effect"),
(val_and, ":skill", 255), # just a byte again
(assign, reg0, ":bonus"),
# add whatever skills you want in here
(try_begin),
(eq, ":skill", skl_power_strike),
(str_store_string, s2, "@power strike"),
(else_try),
(eq, ":skill", skl_ironflesh),
(str_store_string, s2, "@ironflesh"),
(else_try),
(eq, ":skill", skl_horse_archery),
(str_store_string, s2, "@horse archery"),
(else_try),
(eq, ":skill", skl_tactics),
(str_store_string, s2, "@tactics"),
(else_try),
(str_store_string, s2, "@INVALID"),
(try_end),
]),

# parses all equipment slots for artifacts and grabs the effect ids and
# returns the cumulative bonus to the given skill given by equipment.
# INPUT:
#    arg1:  skill value
# OUTPUT:
#    reg0:  total bonus
( "kt_calculate_total_bonus_to_skill",
[
(store_script_param_1, ":skill_to_check"),
(assign, reg0, 0),
# for each item
(try_for_range, ":i_equipped", ek_item_0, ek_food),
(troop_get_inventory_slot, ":item", "trp_player", ":i_equipped"),
(try_begin),
# valid items
(neq, ":item", -1),
# which are artifacts
(item_slot_ge, ":item", kt_slot_item_is_artifact, 1),
# check effect values
(item_get_slot, ":effect", ":item", kt_slot_item_effect1),
# decode
(assign, ":bonus", ":effect"),
(val_and, ":bonus", 16711680), # just a byte
(val_div, ":bonus", 65536),
(assign, ":skill", ":effect"),
(val_and, ":skill", 255), # just a byte again
(try_begin),
(eq, ":skill", ":skill_to_check"),
(val_add, reg0, ":bonus"),
(try_end),
# check effect values slot 2
(item_get_slot, ":effect", ":item", kt_slot_item_effect2),
# decode
(assign, ":bonus", ":effect"),
(val_and, ":bonus", 16711680), # just a byte
(val_div, ":bonus", 65536),
(assign, ":skill", ":effect"),
(val_and, ":skill", 255), # just a byte again
(try_begin),
(eq, ":skill", ":skill_to_check"),
(val_add, reg0, ":bonus"),
(try_end),
# check effect values slot 3
(item_get_slot, ":effect", ":item", kt_slot_item_effect3),
# decode
(assign, ":bonus", ":effect"),
(val_and, ":bonus", 16711680), # just a byte
(val_div, ":bonus", 65536),
(assign, ":skill", ":effect"),
(val_and, ":skill", 255), # just a byte again
(try_begin),
(eq, ":skill", ":skill_to_check"),
(val_add, reg0, ":bonus"),
(try_end),
(try_end),
(try_end),
]),

Stuff that gets spliced into existing code in module_scripts.py:
Somewhere in script_game_start, splice this stuff in.  I put mine after the books get initialized.

      (item_set_slot, "itm_sword_artifact_test_1", kt_slot_item_is_artifact, 1),
      (item_set_slot, "itm_sword_artifact_test_1", kt_slot_item_experience, 0),
      (item_set_slot, "itm_sword_artifact_test_1", kt_slot_item_max_experience, 100),
      (item_set_slot, "itm_sword_artifact_test_1", kt_slot_item_next_item, itm_sword_artifact_test_2),
      (item_set_slot, "itm_sword_artifact_test_1", kt_slot_item_effect1, kt_item_effect_power_strike_1),
     
      (item_set_slot, "itm_sword_artifact_test_2", kt_slot_item_is_artifact, 1),
      (item_set_slot, "itm_sword_artifact_test_2", kt_slot_item_experience, 0),
      (item_set_slot, "itm_sword_artifact_test_2", kt_slot_item_max_experience, 200),
      (item_set_slot, "itm_sword_artifact_test_2", kt_slot_item_next_item, itm_sword_artifact_test_3),
      (item_set_slot, "itm_sword_artifact_test_2", kt_slot_item_effect1, kt_item_effect_power_strike_2),
     
      (item_set_slot, "itm_sword_artifact_test_3", kt_slot_item_is_artifact, 1),
      (item_set_slot, "itm_sword_artifact_test_3", kt_slot_item_experience, 0),
      (item_set_slot, "itm_sword_artifact_test_3", kt_slot_item_max_experience, 300),
      (item_set_slot, "itm_sword_artifact_test_3", kt_slot_item_next_item, itm_sword_artifact_test_4),
      (item_set_slot, "itm_sword_artifact_test_3", kt_slot_item_effect1, kt_item_effect_power_strike_3),
     
      (item_set_slot, "itm_sword_artifact_test_4", kt_slot_item_is_artifact, 1),
      (item_set_slot, "itm_sword_artifact_test_4", kt_slot_item_experience, 0),
      (item_set_slot, "itm_sword_artifact_test_4", kt_slot_item_max_experience, 500),
      (item_set_slot, "itm_sword_artifact_test_4", kt_slot_item_next_item, 0),
      (item_set_slot, "itm_sword_artifact_test_4", kt_slot_item_effect1, kt_item_effect_power_strike_4),
      (item_set_slot, "itm_sword_artifact_test_4", kt_slot_item_effect2, kt_item_effect_tactics_5),

In script_game_get_item_extra_text, I added this at the bottom under the try block for reference books:
      (else_try),
      (item_slot_eq, ":item_no", kt_slot_item_is_artifact, 1),
      (item_get_slot, ":effect1", ":item_no", kt_slot_item_effect1),
      (item_get_slot, ":effect2", ":item_no", kt_slot_item_effect2),
      (item_get_slot, ":effect3", ":item_no", kt_slot_item_effect3),
      (item_get_slot, ":cur_exp", ":item_no", kt_slot_item_experience),
      (item_get_slot, ":max_exp", ":item_no", kt_slot_item_max_experience),
      (item_get_slot, ":next", ":item_no", kt_slot_item_next_item),

      (try_begin),
      (eq, ":extra_text_id", 0),
      (set_result_string, "@This item is an artifact."),
      (set_trigger_result, 0xFF00FFFF),
      (else_try),
      # only show exp for items with a next
      (eq, ":extra_text_id", 1),
      (neq, ":next", 0),
      (assign, reg0, ":cur_exp"),
      (assign, reg1, ":max_exp"),
      (set_result_string, "@{reg0}/{reg1} item xp"),
      (set_trigger_result, 0xFF00FFFF),
      (else_try),
      (eq, ":extra_text_id", 2),
      (gt, ":effect1", 0),
(call_script, "script_kt_parse_values_from_item_effect", ":effect1"),
      (set_result_string, "@+{reg0} to {s2} when equipped"),
      (try_begin),
      (troop_has_item_equipped, "trp_player", ":item_no"),
      (set_trigger_result, 0xFF00FFFF),
      (else_try),
      (set_trigger_result, 0xFF555555),
      (try_end),
      (else_try),
      (eq, ":extra_text_id", 3),
      (gt, ":effect2", 0),
(call_script, "script_kt_parse_values_from_item_effect", ":effect2"),
      (set_result_string, "@+{reg0} to {s2} when equipped"),
      (try_begin),
      (troop_has_item_equipped, "trp_player", ":item_no"),
      (set_trigger_result, 0xFF00FFFF),
      (else_try),
      (set_trigger_result, 0xFF555555),
      (try_end),
      (else_try),
      (eq, ":extra_text_id", 4),
      (gt, ":effect3", 0),
(call_script, "script_kt_parse_values_from_item_effect", ":effect3"),
      (set_result_string, "@+{reg0} to {s2} when equipped"),
      (try_begin),
      (troop_has_item_equipped, "trp_player", ":item_no"),
      (set_trigger_result, 0xFF00FFFF),
      (else_try),
      (set_trigger_result, 0xFF555555),
      (try_end),
      (try_end),

In script_game_get_skill_modifier_for_troop, I added this stuff at the bottom after the surgery book block:

    # kt0:  add in all the skills we care about here for artifact mods.
    # i don't add them all and don't trounce on the book ones.
    (try_begin),
    (this_or_next|eq, ":skill_no", "skl_leadership"),
    (this_or_next|eq, ":skill_no", "skl_spotting"),
    (this_or_next|eq, ":skill_no", "skl_pathfinding"),
    (this_or_next|eq, ":skill_no", "skl_tactics"),
    (this_or_next|eq, ":skill_no", "skl_tracking"),
    (this_or_next|eq, ":skill_no", "skl_horse_archery"),
    (this_or_next|eq, ":skill_no", "skl_riding"),
    (this_or_next|eq, ":skill_no", "skl_athletics"),
    (this_or_next|eq, ":skill_no", "skl_shield"),
    (this_or_next|eq, ":skill_no", "skl_power_draw"),
    (this_or_next|eq, ":skill_no", "skl_power_throw"),   
    (this_or_next|eq, ":skill_no", "skl_power_strike"),
    (eq, ":skill_no", "skl_ironflesh"),
    (call_script, "script_kt_calculate_total_bonus_to_skill", ":skill_no"),
    (gt, reg0, 0),
    (val_add, ":modifier_value", reg0),
    (try_end),

Stuff that you can stick wherever you like to make the items gain levels:
Do whatever with this.  I'll probably stick mine with renown.
    (call_script, "script_kt_add_artifact_exp", 75),

The test data I used (slightly mangled):
#
# SWORD OF ULTIMATE OVERKILL:  TEST OBJECT
#
["sword_artifact_test_1", "Sword of Ultimate Overkill", [("sword_medieval_a",0),("sword_medieval_a_scabbard", ixmesh_carry)], itp_type_one_handed_wpn|itp_primary, itc_longsword|itcf_carry_sword_left_hip|itcf_show_holster_when_drawn, 1000, weight(1.5) | difficulty(0) | spd_rtng(99)  | weapon_length(95) | swing_damage(27, cut) | thrust_damage(22, pierce), imodbits_sword_high ],
["sword_artifact_test_2", "Sword of Ultimate Overkill", [("sword_medieval_a",0),("sword_medieval_a_scabbard", ixmesh_carry)], itp_type_one_handed_wpn|itp_primary, itc_longsword|itcf_carry_sword_left_hip|itcf_show_holster_when_drawn, 2000, weight(1.5) | difficulty(0) | spd_rtng(105) | weapon_length(95) | swing_damage(31, cut) | thrust_damage(24, pierce), imodbits_sword_high ],
["sword_artifact_test_3", "Sword of Ultimate Overkill", [("sword_medieval_a",0),("sword_medieval_a_scabbard", ixmesh_carry)], itp_type_one_handed_wpn|itp_primary, itc_longsword|itcf_carry_sword_left_hip|itcf_show_holster_when_drawn, 3000, weight(1.5) | difficulty(0) | spd_rtng(115) | weapon_length(95) | swing_damage(35, cut) | thrust_damage(26, pierce), imodbits_sword_high ],
["sword_artifact_test_4", "Sword of Ultimate Overkill", [("sword_medieval_a",0),("sword_medieval_a_scabbard", ixmesh_carry)], itp_type_one_handed_wpn|itp_primary, itc_longsword|itcf_carry_sword_left_hip|itcf_show_holster_when_drawn, 5000, weight(1.5) | difficulty(0) | spd_rtng(125) | weapon_length(95) | swing_damage(39, cut) | thrust_damage(28, pierce), imodbits_sword_high ],

Enjoy!

edit:  Hey look!  A picture! 
f51xrs.jpg
 
kt0 that sounds like an epic script, but im not sure what it does, if im right, as your character level up (and stats increase) your equipment does too? Like lets say your level 10, your gear will have X armor, then at lvl 20 it will have X+20 ? Or am I wrong, what do you mean exactly?
 
MrRoy said:
kt0 that sounds like an epic script, but im not sure what it does, if im right, as your character level up (and stats increase) your equipment does too? Like lets say your level 10, your gear will have X armor, then at lvl 20 it will have X+20 ? Or am I wrong, what do you mean exactly?
That's the basic idea.  I left it open as to where you stick the levelling part.  Player EXP is the obvious place, but renown gain, honor gain, time based trigger, etc. are also possibilities.  I currently have mine hooked up to renown hence the smallish values for needed xp.  I also have it hooked up to a mod menu for testing.

If you trace through the Sword of Ultimate Overkill's levels (under test data spoiler) you can see that it gains speed and damage as it levels.  You can pretty much work with any item this way.  You can even change how they look between levels since it swaps out the item ID.  I haven't figured out how to change attributes or proficiencies if you can even do that. 
 
adding skill bonuses is easy enough, you just need to alter the script that handles these bonuses so it checks for a slot on the item and then adds a bonus. I use that for the starships in SWC, they give several skill bonuses.

attribute bonus doesn't exist. Of course it's easy enough to fake this with some sort of trigger. When the item gets equiped, raise str by 1, when it's no longer equiped, lower str by 1 (for instance). Problem is that this won't change the attribute color, so the player won't know he has a bonus. But you might be able to change the colors somewhere as well, the fact that it's done on the fly for skills means it's probably somewhere in the code, doesn't seem like something you'd hardcode.

Nice idea btw! Have some truly epic weapons and make them level up to become more powerful.
 
I'm pretty much a newbie in M&B modding, and I've been wondering how can I make a crossbow shoot a unique projectile instead of the default bolt. Can somebody please enlighten me ?
 
kt0 said:
MrRoy said:
kt0 that sounds like an epic script, but im not sure what it does, if im right, as your character level up (and stats increase) your equipment does too? Like lets say your level 10, your gear will have X armor, then at lvl 20 it will have X+20 ? Or am I wrong, what do you mean exactly?
That's the basic idea.  I left it open as to where you stick the levelling part.  Player EXP is the obvious place, but renown gain, honor gain, time based trigger, etc. are also possibilities.  I currently have mine hooked up to renown hence the smallish values for needed xp.  I also have it hooked up to a mod menu for testing.

If you trace through the Sword of Ultimate Overkill's levels (under test data spoiler) you can see that it gains speed and damage as it levels.  You can pretty much work with any item this way.  You can even change how they look between levels since it swaps out the item ID.  I haven't figured out how to change attributes or proficiencies if you can even do that.

Why not tie it in to when you make a kill with that weapon?  Kind of like a demon weapon stealing the souls of those that are slain by it.  Yes an obvious fantasy bit, but so is having a weapon level up.

Just on a note, this is a major advantage to the player, and weapons like this should be limited (other than being unique) in an actual game setting, unless you like the kind of game you can't lose in.
 
jik said:
Why not tie it in to when you make a kill with that weapon?  Kind of like a demon weapon stealing the souls of those that are slain by it.  Yes an obvious fantasy bit, but so is having a weapon level up.

Just on a note, this is a major advantage to the player, and weapons like this should be limited (other than being unique) in an actual game setting, unless you like the kind of game you can't lose in.
I leave all such judgements up to the mod developers.  I've been disabused over the years of the notion that I can do more than throw words at designers when presenting them with a piece of functionality.  :wink:
 
I hate the thought that a highly trained elite troop is just as unhappy about marauding about the countryside in a large party as a newly recruited peasant.  In later portions of the game (mods especially) it is super hard to keep a large army happy because of the dearth of suitable targets and the speed at which morale decays.  The following code attempts to fix this by taking troop level into account when determining morale penalty based on size. 

In module_scripts.py look for get_player_party_morale_values:
# script_get_player_party_morale_values
# Output: reg0 = player_party_morale_target
# kt0: refactored the party size morale values.
("get_player_party_morale_values",
[
# calculate the total number of guys and the cumulative level of the
# party. 
(party_get_num_companion_stacks, ":num_stacks","p_main_party"),
(assign, ":level_total", 0),
(assign, ":num_men", 0),
(try_for_range, ":i_stack", 1, ":num_stacks"),
(party_stack_get_troop_id, ":stack_troop","p_main_party", ":i_stack"),
(store_character_level, ":level", ":stack_troop"),
(try_begin),
(troop_is_hero, ":stack_troop"),
(val_add, ":num_men", 3),
(val_add, ":level_total", ":level"),
(else_try),
(party_stack_get_size, ":stack_size","p_main_party",":i_stack"),
(val_add, ":num_men", ":stack_size"),
(val_mul, ":level", ":stack_size"),
(val_add, ":level_total", ":level"),
(try_end),
(try_end),

# take the total number of guys and put it in the right range to do more
# maths on it.  divide this value by the cumulative level to get our
# morale penalty based on size.  this results in lower level troops
# being more inclined to be unhappy than higher level troops and higher
# level troops can kick guys in line up to a point.
# 5 * (count+5)^2 / (count * level)
(store_add, ":morale_penalty_for_size", ":num_men", 5),
(val_mul, ":morale_penalty_for_size", ":morale_penalty_for_size"),
(val_mul, ":morale_penalty_for_size", 5),
(val_div, ":morale_penalty_for_size", ":level_total"),
     
# the math works great for large numbers but not so great for small ones.
# if we get a value that's more than twice the size, min it to that.
(try_begin),
(store_mul, ":double", ":num_men", 2),
(gt, ":morale_penalty_for_size", ":double"),
(assign, ":morale_penalty_for_size", ":double"),
(try_end),

(assign, "$g_player_party_morale_modifier_party_size", ":morale_penalty_for_size"),

Stuff unchanged for context:
(store_skill_level, ":player_leadership", "skl_leadership", "trp_player"),
(store_mul, "$g_player_party_morale_modifier_leadership", ":player_leadership", 7),
(assign, ":new_morale", "$g_player_party_morale_modifier_leadership"),
(val_sub, ":new_morale", "$g_player_party_morale_modifier_party_size"),
(val_add, ":new_morale", 50),

With this change, higher level troops are more content to be in large bands which makes keeping larger armies far more convenient.  The function is not linear which confounds easy comparisons to the old system but the break even point is around level 5 with lower levels having a far greater penalty and higher levels having far less penalty.  Feel free to tweak for your needs.  As always, credit for use in publically released mods would be swell.
 
Mordachai said:
The following goes in your module_dialogs.py.  It must precede or replace the native prisoner dialogs (if you place it after, then it will be ignored in favor of the native code).
Code:
  ###################################################################################################
  # Prisoner Talk - Originally written by Leprechaun, majorly overhauled & extended by Mordachai
  ###################################################################################################

  # this is a dummy dialog - it sets up the globals we need
  [anyone|plyr, "prisoner_chat", [
    (store_conversation_troop,"$g_talk_troop"),
    (store_troop_faction,"$g_talk_troop_faction","$g_talk_troop"),
    (store_relation, "$g_talk_troop_faction_relation", "$g_talk_troop_faction", "fac_player_faction"),
    (call_script, "script_troop_get_player_relation", "$g_talk_troop"),
    (assign, "$g_talk_troop_relation", reg0),
    (eq, 1, 0)
  ], "", "close_window", []],

  # the following is intended to catch when you free up space for a prisoner that already agreed to join you
  [anyone|plyr, "prisoner_chat", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1),(troops_can_join, 1)], "All right, I have made room for you.", "prisoner_chat_accept_confirm", []],
  [anyone,      "prisoner_chat_accept_confirm", [], "I am at your command, my {lord/lady}.", "prisoner_chat_accept3", []],

  # and we catch the case where you still don't have any room for a pending conscripted prisoner
  [anyone|plyr, "prisoner_chat", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1),(neg|troops_can_join, 1)], "I am sorry, I still have no room for you. You'll have to wait a while longer.", "close_window",[]],

  # default entry (no prior join agreement, or they've previously refused)
  [anyone|plyr, "prisoner_chat", [(neg|troop_slot_eq, "$g_talk_troop", slot_troop_occupation, slto_kingdom_hero)], "You there!", "prisoner_chat_commoner", []],
  [anyone|plyr, "prisoner_chat", [(troop_slot_eq, "$g_talk_troop", slot_troop_occupation, slto_kingdom_hero),(str_store_troop_name, s1, "$g_talk_troop")], "{s1}", "prisoner_chat_lord", []],

  # reaction to you based on noble or low-birth
  [anyone,     "prisoner_chat_commoner", [], "Me?! (Gulp!)", "prisoner_chat_menu",[]],
  [anyone,     "prisoner_chat_lord", [(str_store_troop_name, s1, "trp_player")], "Yes, {Lord/Lady} {s1}?", "prisoner_chat_noble",[]],

  # nobles chat begin
  [anyone|plyr,"prisoner_chat_noble", [], "You are free to go.", "prisoner_chat_noble_prerelease",[]],
  [anyone|plyr,"prisoner_chat_noble", [], "You will remain my prisoner.", "prisoner_chat_noble_prekeep",[]],
  [anyone|plyr,"prisoner_chat_noble", [(gt, "$players_kingdom", 0)], "You have committed high treason!", "prisoner_chat_treason",[]],

  [anyone|plyr,"prisoner_chat_noble_prerelease", [], "Despite what you may have heard, I am a {man/woman} of honor.  You are free to go.", "prisoner_chat_noble_release", []],
  [anyone,     "prisoner_chat_noble_release", [], "I will not forget this act of Chivalry!", "close_window",
   [
    # remove the troop from prison
    (call_script, "script_remove_troop_from_prison", "$g_talk_troop"),
    (party_remove_prisoners, "p_main_party", "$g_talk_troop", 1),

    # determine how much honor and faction relation change this prisoner is worth
    (try_begin),
      # king
      (faction_slot_eq, "$g_talk_troop_faction", slot_faction_leader, "$g_talk_troop"),
      (assign, ":honor", 5),
      (assign, ":fac_reln", 15),
    (else_try),
      # other lord
      (assign, ":honor", 2),
      (assign, ":fac_reln", 5),
    (try_end),

    # give the player their honor, faction relation, and lord relation change
    (call_script, "script_change_player_relation_with_troop", "$g_talk_troop", 10),
    (call_script, "script_change_player_honor", ":honor"),
    (call_script, "script_change_player_relation_with_faction", "$g_talk_troop_faction", ":fac_reln" ),
  ]],

  [anyone|plyr,"prisoner_chat_noble_prekeep", [], "You will understand if I keep you hostage until your family can afford to... compensate me for certain expenses and hardships I have endured to keep you fed and ...safe... these past weeks.", "prisoner_chat_noble_keep",[]],

  [anyone,     "prisoner_chat_noble_keep", [(ge, "$player_honor", 10),(ge, "$g_talk_troop_relation", 0)], "Truly, this is beneath you.", "close_window",[]],
  [anyone,     "prisoner_chat_noble_keep", [], "And I trust you will be as understanding when I hunt you down like the dog you are!", "close_window",[(call_script, "script_change_player_relation_with_troop", "$g_talk_troop", -1)]],

  # commoners chat begin
  [anyone|plyr,"prisoner_chat_menu", [], "Hmmm... perhaps you're not as stupid as the rest of those rabble.", "prisoner_chat_offer",[]],
  [anyone|plyr,"prisoner_chat_menu", [], "As wretched as you are, I cannot help but feel sorry for you.", "prisoner_chat_release",[]],
  [anyone|plyr,"prisoner_chat_menu", [], "The sight of you makes me sick! You.. Die.. Now!", "prisoner_chat_die1",[]],
  [anyone|plyr,"prisoner_chat_menu", [], "Get back in line, Scum!", "close_window",[]],

  [anyone|plyr,"prisoner_chat_release", [], "I'm feeling magnanimous today.  Begone, before I change my mind!", "prisoner_chat_release2", []],
  [anyone,     "prisoner_chat_release2", [], "Oh, thank you, {sir/madam}.  Blessings on you!", "close_window",
    [(remove_troops_from_prisoners, "$g_talk_troop", 1),(call_script, "script_change_player_honor", 1)]],

  [anyone|plyr,"prisoner_chat_offer", [], "Listen, scum, you have one last chance to redeem yourself before I sell you to the slave-traders.  "\
                                      "Drop all your previous allegiances and swear fealty to me, obey my every order to the letter, and you'll be paid, fed and equipped.  "\
                                      "If you don't....well, let's just say that life as a slave will be seemingly unending years of agony, malnutrition and beatings.  "\
                                      "I'd advise you to think very, very carefully before choosing.  ", "prisoner_chat_reaction",
                                      [(call_script, "script_determine_prisoner_agreed", "$g_talk_troop", "$g_talk_troop_faction_relation")]],

  [anyone,     "prisoner_chat_reaction", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1)], "Thank you for your mercy, {sir/madam}. I swear on my mothers grave I will serve you, my {lord/lady}!","prisoner_chat_accept1",[]],
  [anyone,     "prisoner_chat_reaction", [], "I'll show you what I think of your offer! (The prisoner spits at your feet) There. Now get lost, I'm not interested.", "prisoner_chat_refuse",[]],

  [anyone|plyr,"prisoner_chat_refuse", [], "I see...", "prisoner_chat_menu",[]],

  [anyone|plyr,"prisoner_chat_die1", [], "(You advance on the prisoner...)", "prisoner_chat_die2",[]],
  [anyone,     "prisoner_chat_die2", [], "Please, {sir/madam}, don't kill me. I am a defenceless prisoner. Surely you're not that cruel?", "prisoner_chat_die3",[]],
  [anyone|plyr,"prisoner_chat_die3", [], "(Kill the prisoner)", "prisoner_chat_die4",[]],
  [anyone|plyr,"prisoner_chat_die3", [], "No, I will not sink that low.", "close_window",[]],
  [anyone|plyr,"prisoner_chat_die4", [], "(The prisoner struggles against his shackles, desperate to free himself and escape you, but to no avail. You slit their throat with a knife and watch, satisfied, as his corpse sags to the floor.)", "close_window",
   [(remove_troops_from_prisoners, "$g_talk_troop", 1),
    (call_script, "script_change_player_honor", -1)]],

  [anyone|plyr, "prisoner_chat_accept1", [], "If you so much as fail to tremble on my command, I will have you severely disciplined!", "prisoner_chat_accept2",[]],
  [anyone|plyr, "prisoner_chat_accept1", [], "In my camp we are all treated as equals.  I expect your obedience, but also your trust.", "prisoner_chat_accept2",[]],

  [anyone,      "prisoner_chat_accept2", [], "I will obey your wishes, my {lord/lady}.  I swear!", "prisoner_chat_accept3",[]],

  [anyone|plyr, "prisoner_chat_accept3", [(neg|troops_can_join, 1)], "Oh! Apparently there isn't enough room for you in my party. I will be back when I have made space.", "close_window", []],
  [anyone|plyr, "prisoner_chat_accept3", [(troops_can_join, 1)], "Excellent. Report to the quartermaster for provisions and equiment.  There is hard fighting ahead.", "close_window",
   [(troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, 0),
    (remove_troops_from_prisoners, "$g_talk_troop",1),
    (party_add_members, "p_main_party", "$g_talk_troop", 1),
    (call_script, "script_change_troop_renown", "trp_player", 1),]],

  [anyone|plyr, "prisoner_chat_treason", [(str_store_troop_name, s1, "$g_talk_troop"), (str_store_faction_name, s2, "$players_kingdom")],
    "{s1}, you have committed cimes against the {s2}, for which you will now stand trial.^How plead you?", "prisoner_chat_treason_plead",
    [
      # determine the noble's reaction to this accusation
      (store_random_in_range, reg0, 1, 5),#bug: must set upper number one higher to actually generate correct range
      #TODO: weight the reaction according to the renown?  Or at least according to king or not...
      (troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, reg0),
    ]
  ],

  [anyone,      "prisoner_chat_treason_plead", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1),],
    "Please have mercy upon my soul.  All I have done, I have done in the name of my King and Country!  I am but a patriot, as you, and I deserve your respect, if nothing else.", "prisoner_chat_treason_choose", []],
  [anyone,      "prisoner_chat_treason_plead", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 2),],
    "You are gravely mistaken!  I am an honorable Lord, and I have done nothing that you would not do were our roles exchanged.", "prisoner_chat_treason_choose", []],
  [anyone,      "prisoner_chat_treason_plead", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 3),],
    "I spit on you and yours!  You are but a cur come to put on airs, as though you were Noble and had any right whatsoever to judge me!  Me!  You are a nothing but a common brigand and a coward!  I do not bow to you.  You should drop to your knees and beg *my* forgiveness!", "prisoner_chat_treason_choose", []],
  [anyone,      "prisoner_chat_treason_plead", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 4),],
    "You dare accuse me?!  You sniveling whelpling!  I should see you flogged and put in chains in one of my prisons for your insolence!", "prisoner_chat_treason_choose", []],

  [anyone|plyr, "prisoner_chat_treason_choose", [], "I am a {man/woman} of honor.  I shall spare your life this day!", "prisoner_chat_treason_not_guilty",
    [
      #TODO: have the relation with the prison have a mixed (random) result - relief, anger, etc, which dictates their final monologue to the player before exiting the dialog

      # make sure we don't try to recruit this prisoner later!
      (troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, 0),
    ]
  ],

  [anyone,      "prisoner_chat_treason_not_guilty", [(str_store_troop_name, s1, "trp_player")], "There is yet hope for you, {s1}.", "close_window", []],

  [anyone|plyr, "prisoner_chat_treason_choose", [], "You do not deserve leiniency.  You must pay for your crimes with your life.", "prisoner_chat_treason_guilty", []],

  [anyone|plyr, "prisoner_chat_treason_guilty", [], "For your many crimes against {s1}, I hereby sentence you to death, to be carried out immediately.  Have you any final words to say?", "prisoner_chat_treason_final_words",
    [(store_random_in_range, reg0, 1, 6), (troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, reg0)]],

  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1)], "I believe you will one day come to regret your actions.  There is only one who is worthy to decide another's fate... and that one is not you.", "prisoner_chat_treason_execute", []],
  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 2)], "You are a coward and a dog!  May your soul rot eternal, damn you!", "prisoner_chat_treason_execute", []],
  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 3)], "Winter's mortality,^locked in frozen indifference,^melts with Spring's rebirth.", "prisoner_chat_treason_execute", []],
  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 4)], "You will find no peace on this earth!  I shall haunt thee eternal!  Unto death you will find nothing but unhappiness and fear.  And beyond... only torture and pain!", "prisoner_chat_treason_execute", []],
  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 5)], "Who are you?^A day passes^We are but children", "prisoner_chat_treason_execute", []],

  [anyone|plyr, "prisoner_chat_treason_execute", [],
    "(The prisoner struggles against his shackles, desperate to free himself and escape you, but to no avail. You slit his throat and watch, satisfied, as his corpse sags to the floor.)",
    "close_window",
    [
      # attempt to allow the player to see the consequences of their actions
      #(set_show_messages, 1),  # this not only fails - but messages are hereafter disabled in the main game...

      # make sure we don't try to recruit this prisoner stack later!
      (troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, 0),

      # "kill" the NPC - force the 48 hr respawn kingdom heros trigger to ignore this troop (no party will be created for this troop, ever again)
      # [q.v. script_create_kingdom_hero_party]
      (troop_set_slot, "$g_talk_troop", slot_troop_occupation, slto_dead),

      # remove them from their faction
      (troop_set_slot, "$g_talk_troop", slot_troop_change_to_faction, "fac_no_faction"),
      (troop_set_slot, "$g_talk_troop", slot_troop_original_faction, "fac_no_faction"),

      # determine the penalty for this act (based on the honor of the troop they've killed)
      (troop_get_slot, ":impact", "$g_talk_troop", slot_troop_renown),
      (val_div, ":impact", -33),
      (store_div, ":half", ":impact", 2),

      # reduce the player's relationship with every village, town, and castle
      (try_for_range, ":center", centers_begin, centers_end),
        (store_faction_of_party, ":faction", ":center"),
        (store_relation, ":relation", ":faction", "$g_talk_troop_faction"),
        (try_begin),
          (le, ":relation", -10),
          # enemies, half impact
          (call_script, "script_change_player_relation_with_center", ":center", ":half"),
        (else_try),
          # not at war, full impact
          (call_script, "script_change_player_relation_with_center", ":center", ":impact"),
        (try_end),
      (try_end),

      # reduce the player's relationship with every hero, companion, lady, and daughter
      (try_for_range, ":troop", trp_npc1, trp_heroes_end),
        # don't make the dead any angrier than they already are!
        (neg|troop_slot_eq, ":troop", slot_troop_occupation, slto_dead),
        (store_troop_faction, ":faction", ":troop"),
        (store_relation, ":relation", ":faction", "$g_talk_troop_faction"),
        (try_begin),
          (le, ":relation", -10),
          # enemies, half impact
          (call_script, "script_change_player_relation_with_troop", ":troop", ":half"),
        (else_try),
          # not at war, full impact
          (call_script, "script_change_player_relation_with_troop", ":troop", ":impact"),
        (try_end),
      (try_end),

      # reduce the player's relationship with every faction (enemies 1/2 as much)
      (try_for_range, ":faction", kingdoms_begin, kingdoms_end),
        (store_relation, ":relation", ":faction", "$g_talk_troop_faction"),
        (try_begin),
          (le, ":relation", -10),
          # enemies, half impact
          (call_script, "script_change_player_relation_with_faction", ":faction", ":half"),
        (else_try),
          # not at war, full impact
          (call_script, "script_change_player_relation_with_faction", ":faction", ":impact"),
        (try_end),
      (try_end),

      # apply the honor hit
      (call_script, "script_change_player_honor", ":impact"),

      # party morale takes a hit as well
      (call_script, "script_change_player_party_morale", ":half"),

      # but give them renown for this evil deed (their deed spreads upon every tongue, impressing some, and cowing others)
      (val_mul, ":impact", -1),
      (call_script, "script_change_troop_renown", "trp_player" , ":impact"),

      # start with the assumption that the fief should return to its faction for redistribution
      (assign, ":fief_faction", "$g_talk_troop_faction"),

      (try_begin),
        # handle executing the King!
        (faction_slot_eq, "$g_talk_troop_faction", slot_faction_leader, "$g_talk_troop"),

        # find best candidate to become king
        (assign, ":best_troop", -1),
        (assign, ":best_renown", -1),
        (try_for_range, ":troop", kingdom_heroes_begin, kingdom_heroes_end),
          (neg|troop_slot_eq, ":troop", slot_troop_occupation, slto_dead),  #can't choose a dead hero!
          (store_troop_faction, ":faction", ":troop"),
          (eq, ":faction", "$g_talk_troop_faction"),
          (troop_slot_eq, ":troop", slot_troop_occupation, slto_kingdom_hero),  #only other heros of this faction may become the king
          (troop_get_slot, ":renown", ":troop", slot_troop_renown),
          (gt, ":renown", ":best_renown"),
          (assign, ":best_troop", ":troop"),
          (assign, ":best_renown", ":renown"),
        (try_end),

        (try_begin),
          # check if a candidate was found
          (neq, ":best_troop", -1),

          # make them king
          (faction_set_slot, "$g_talk_troop_faction", slot_faction_leader, ":best_troop"),

          # announce it!
          #TODO: generate a presentation for this! (start_presentation, "prsnt_enemy_succession"),
          (str_store_troop_name, s1, ":best_troop"),
          (str_store_faction_name, s2, "$g_talk_troop_faction"),
          (display_message, "@{s1} is the new King of the {s2}!!!", 0xFFFF2222),
          #TODO: update the game log for this event
        (else_try),
          # all of the lords have been eliminated - so eliminate the faction by making their last fief neutral (q.v. trigger: # Check if a faction is defeated every day)
          (assign, ":fief_faction", "fac_no_faction"),
        (try_end),
      (try_end),

      # free up the deceased's fief
      (try_for_range, ":fief", centers_begin, centers_end),
        (party_get_slot, ":lord", ":fief", slot_town_lord),
        (eq, ":lord", "$g_talk_troop"),
        (call_script, "script_give_center_to_faction", ":fief", ":fief_faction"),
      (try_end),

      # no longer our prisoner
      (call_script, "script_remove_troop_from_prison", "$g_talk_troop"),
      (remove_troops_from_prisoners, "$g_talk_troop", 1),
    ]
  ],

  ###################################################################################################
  # End Prisoner Talk
  ###################################################################################################

Please note that slto_dead is not a native symbol - if you want to use the above you'll also need to add slto_dead = 86 in your module_constants.py.

Please note that slot_prisoner_agreed is not a native symbol - simply add slot_prisoner_agreed = 142 to your module_constants.py.  Actually, 142 is arbitrary - any unused slot will do.

Additionally, you'll need to add this script to module_scripts.py - I added it towards the end, as the last script in the file, but you're welcome to place it anywhere within the list of scripts within that file:
Code:
  #MORDACHAI - update whether the specified prisoner would like to join the player's party
  # script_determine_prisoner_agreed
  # Input: arg1 = troop, arg2 = troop faction relation
  # Output: slot_prisoner_agreed is set to 1 if they agreed, or 0 if not
  #         reg0 = agreed or not
  ("determine_prisoner_agreed",
    [
      (store_script_param, ":troop", 1),
      (store_script_param, ":relation", 2),

      # upper bound = Persuasion*3 + Charisma + Leadership*3 + Honor/2 + Renown/100
      (store_attribute_level, ":charisma", "trp_player", ca_charisma),
      (store_skill_level, ":persuasion", "skl_persuasion", "trp_player"),
      (store_skill_level, ":leadership", "skl_leadership", "trp_player"),
      (val_mul, ":persuasion", 3),
      (val_mul, ":leadership", 3),
      (store_div, ":half_honor", "$player_honor", 2),
      (troop_get_slot, ":renown_factor", slot_troop_renown),
      (val_div, ":renown_factor", 100),
      (assign, ":upper_bound", ":persuasion"),
      (val_add, ":upper_bound", ":leadership"),
      (val_add, ":upper_bound", ":charisma"),
      (val_add, ":upper_bound", ":half_honor"),
      (val_add, ":upper_bound", ":renown_factor"),
      (val_min, ":relation", ":upper_bound"),

      # determine their reaction (relation...upper_bound)
      (store_random_in_range, ":reaction", ":relation", ":upper_bound"),
      (assign, reg1, ":reaction"),
      (assign, reg2, ":relation"),
      (assign, reg3, ":upper_bound"),
      #(display_message, "@Prisoner Agrees Check: rolled a {reg1} out of a possible {reg2}-{reg3}"),#diagnostic only

      # record whether they agree or not
      (try_begin),
        (ge, ":reaction", 0),
        (troop_set_slot, ":troop", slot_prisoner_agreed, 1),
      (else_try),
        (troop_set_slot, ":troop", slot_prisoner_agreed, 0),
      (try_end),

      # return the results
      (troop_get_slot, reg0, ":troop", slot_prisoner_agreed),
      #(display_message, "@Prisoner Agrees Check: slot_prisoner_agreed = {reg0?yes:no}"),#diagnostic only
    ]
  ),


So Mordachai, I've tried to follow your instructions, and this is what I've got.
Constants:
# Camp training modes
ctm_melee    = 1
ctm_ranged  = 2
ctm_mounted  = 3
ctm_training = 4

# Village bandits attack modes
vba_normal          = 1
vba_after_training  = 2

arena_tier1_opponents_to_beat = 3
arena_tier1_prize = 15
arena_tier2_opponents_to_beat = 6
arena_tier2_prize = 35
arena_tier3_opponents_to_beat = 10
arena_tier3_prize = 75
arena_tier4_opponents_to_beat = 20
arena_tier4_prize = 180
arena_grand_prize = 400

# Duel Mod Troop Slots

slot_troop_duel_won              = 142      #duel mod - how many duels player won against this troop
slot_troop_duel_lost          = 143      #duel mod - how many duels player lost against this troop
slot_troop_duel_started          = 144      #duel mod - if player started dueling with this troop

#prisoner chat

slto_dead = 86
slot_prisoner_agreed = 146

Dialogues:
 
###################################################################################################
  # Prisoner Talk - Originally written by Leprechaun, majorly overhauled & extended by Mordachai
  ###################################################################################################

  # this is a dummy dialog - it sets up the globals we need
  [anyone|plyr, "prisoner_chat",
  [
    (store_conversation_troop, "$g_talk_troop"),

    (try_begin),
      (troop_is_hero, "$g_talk_troop"),
      (call_script, "script_troop_get_player_relation", "$g_talk_troop"),
      (assign, "$g_talk_troop_relation", reg0),
      (store_troop_faction, "$g_talk_troop_faction", "$g_talk_troop"),
      (store_relation, "$g_talk_troop_faction_relation", "fac_player_supporters_faction", "$g_talk_troop_faction"),
    (else_try),

      # NOTE: as it turns out, non-heros don't have a meaningful faction, therefore they don't have a meaningful relationship with the player
      (try_begin),
        (is_between, "$g_talk_troop", "trp_swadian_recruit", "trp_vaegir_recruit"),
        (assign, "$g_talk_troop_faction", "fac_kingdom_1"),
      (else_try),
        (is_between, "$g_talk_troop", "trp_vaegir_recruit", "trp_khergit_tribesman"),
        (assign, "$g_talk_troop_faction", "fac_kingdom_2"),
      (else_try),
        (is_between, "$g_talk_troop", "trp_khergit_tribesman", "trp_nord_recruit"),
        (assign, "$g_talk_troop_faction", "fac_kingdom_3"),
      (else_try),
        (is_between, "$g_talk_troop", "trp_nord_recruit", "trp_rhodok_tribesman"),
        (assign, "$g_talk_troop_faction", "fac_kingdom_4"),
      (else_try),
        (is_between, "$g_talk_troop", "trp_rhodok_tribesman", "trp_ief_velites"),
        (assign, "$g_talk_troop_faction", "fac_kingdom_5"),
      (else_try),
        (is_between, "$g_talk_troop", "trp_ief_velites", "trp_sod_peasant1"),
        (assign, "$g_talk_troop_faction", "fac_kingdom_6"),
      (else_try),
        # simply treat everything else as outlaws for this purpose
        (assign, "$g_talk_troop_faction", "fac_outlaws"),
      (try_end),

      # so use our grunt's real faction to get faction relations
      (store_relation, "$g_talk_troop_faction_relation", "fac_player_supporters_faction", "$g_talk_troop_faction"),

      # don't generate a relation value more than once per individual
      (troop_get_slot, "$g_talk_troop_relation", "$g_talk_troop", slot_troop_player_relation),
      (eq, "$g_talk_troop_relation", 0),

      # and use a modified version of that as this individual's relation
      (store_random_in_range, ":roll", -20, +21),
      (store_add, "$g_talk_troop_relation", "$g_talk_troop_faction_relation", ":roll"),
      (val_clamp, "$g_talk_troop_relation", -100, 101),
      (troop_set_slot, "$g_talk_troop", slot_troop_player_relation, "$g_talk_troop_relation"),
    (try_end),

    # debug
    (try_begin),
      (eq, "$g_sod_debug", 1),

      (str_store_faction_name_link, s2, "$g_talk_troop_faction"),
      (assign, reg2, "$g_talk_troop_faction_relation"),
      (assign, reg4, "$g_talk_troop_faction"),
      (display_message, "@{s2} ({reg4}) relation = {reg2}", debug_color),

      (str_store_troop_name_link, s1, "$g_talk_troop"),
      (assign, reg1, "$g_talk_troop_relation"),
      (display_message, "@{s1} relation = {reg1}", debug_color),
    (try_end),
    (talk_info_show, 1),
    (call_script, "script_setup_talk_info"),
    (eq, 1, 0)
  ], "", "close_window", []],

  # the following is intended to catch when you free up space for a prisoner that already agreed to join you
  [anyone|plyr, "prisoner_chat", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1), (troops_can_join, 1)], "All right, I have made room for you.", "prisoner_chat_accept_confirm", []],
  [anyone,      "prisoner_chat_accept_confirm", [], "I am at your command, my {lord/lady}.", "prisoner_chat_accept3", []],

  # and we catch the case where you still don't have any room for a pending conscripted prisoner
  [anyone|plyr, "prisoner_chat", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1), (neg|troops_can_join, 1)], "I am sorry, I still have no room for you. You'll have to wait a while longer.", "close_window", []],

  # default entry (no prior join agreement, or they've previously refused)
  [anyone|plyr, "prisoner_chat", [(neg|troop_slot_eq, "$g_talk_troop", slot_troop_occupation, slto_kingdom_hero)], "You there!", "prisoner_chat_commoner", []],
  [anyone|plyr, "prisoner_chat", [(troop_slot_eq, "$g_talk_troop", slot_troop_occupation, slto_kingdom_hero), (str_store_troop_name, s1, "$g_talk_troop")], "{s1}", "prisoner_chat_lord", []],

  # reaction to you based on noble or low-birth
  [anyone,    "prisoner_chat_commoner", [], "Me?! (Gulp)", "prisoner_chat_menu", []],
  [anyone,    "prisoner_chat_lord", [(str_store_troop_name, s1, "trp_player")], "Yes, {Lord/Lady} {s1}?", "prisoner_chat_noble", []],

  # nobles chat begin
  [anyone|plyr, "prisoner_chat_noble", [], "You are free to go.", "prisoner_chat_noble_prerelease", []],
  [anyone|plyr, "prisoner_chat_noble", [], "You will remain my prisoner.", "prisoner_chat_noble_prekeep", []],
  [anyone|plyr, "prisoner_chat_noble", [(gt, "$players_kingdom", 0)], "You have committed high treason!", "prisoner_chat_treason", []],

  [anyone|plyr, "prisoner_chat_noble_prerelease", [], "Despite what you may have heard, I am a {man/woman} of honor.  You are free to go.", "prisoner_chat_noble_release", []],
  [anyone,    "prisoner_chat_noble_release", [], "I will not forget this act of Chivalry!", "close_window",
  [
    # remove the troop from prison
    (call_script, "script_remove_troop_from_prison", "$g_talk_troop"),
    (party_remove_prisoners, "p_main_party", "$g_talk_troop", 1),

    # determine how much honor and faction relation change this prisoner is worth
    (try_begin),
      # king
      (faction_slot_eq, "$g_talk_troop_faction", slot_faction_leader, "$g_talk_troop"),
      (assign, ":honor", 5),
      (assign, ":fac_reln", 15),
    (else_try),
      # other lord
      (assign, ":honor", 2),
      (assign, ":fac_reln", 5),
    (try_end),

    # give the player their honor, faction relation, and lord relation change
    (call_script, "script_change_player_relation_with_troop", "$g_talk_troop", 10),
    (call_script, "script_change_player_honor", ":honor"),
    (call_script, "script_change_player_relation_with_faction", "$g_talk_troop_faction", ":fac_reln" ),
  ]],

  [anyone|plyr, "prisoner_chat_noble_prekeep", [], "You will understand if I keep you hostage until your family can afford to... compensate me for certain expenses and hardships I have endured to keep you fed and ...safe... these past weeks.", "prisoner_chat_noble_keep", []],

  [anyone,    "prisoner_chat_noble_keep", [(ge, "$player_honor", 10), (ge, "$g_talk_troop_relation", 0)], "Truly, this is beneath you.", "close_window", []],
  [anyone,    "prisoner_chat_noble_keep", [], "And I trust you will be as understanding when I hunt you down like the dog you are!", "close_window", [(call_script, "script_change_player_relation_with_troop", "$g_talk_troop", -1)]],

  # commoners chat begin
  [anyone|plyr, "prisoner_chat_menu", [(store_current_day, ":today"), (neg|troop_slot_eq, "$g_talk_troop", slot_prisoner_rejected_day, ":today")],
    "Hmmm... I may have a use for you.", "prisoner_chat_offer", []],
  [anyone|plyr, "prisoner_chat_menu", [(store_current_day, ":today"), (troop_slot_eq, "$g_talk_troop", slot_prisoner_rejected_day, ":today")],
    "Are you sure you will not reconsider my offer?", "prisoner_chat_offer_again", [(store_random_in_range, reg60, 0, 100), (store_skill_level, reg61, "skl_persuasion", "trp_player"), ]],
  [anyone|plyr, "prisoner_chat_menu", [], "As wretched as you are, I cannot help but feel sorry for you.", "prisoner_chat_release", []],
  [anyone|plyr, "prisoner_chat_menu", [], "The sight of you makes me sick! You.. Die.. Now!", "prisoner_chat_die1", []],
  [anyone|plyr, "prisoner_chat_menu", [], "Get back in line, maggot!", "close_window", []],

  [anyone, "prisoner_chat_offer_again", [(lt, reg60, reg61)], "Hmmm.... perhaps, perhaps.  What was your offer, again?", "prisoner_chat_offer", []],
  [anyone, "prisoner_chat_offer_again", [(ge, reg60, reg61)], "Listen {sir/madam}, I already told you!  I will not join you!  Leave me to my misery!", "prisoner_chat_offer_again_end", []],
  [anyone|plyr, "prisoner_chat_offer_again_end", [], "More time in your chains will cool your attitude!", "close_window", []],

  [anyone|plyr, "prisoner_chat_release", [], "I'm feeling magnanimous today.  Begone, before I change my mind!", "prisoner_chat_release2", []],
  [anyone,    "prisoner_chat_release2", [], "Oh, thank you, {sir/madam}.  Blessings on you!", "close_window",
    [(remove_troops_from_prisoners, "$g_talk_troop", 1), (call_script, "script_change_player_honor", 1)]],

  [anyone|plyr, "prisoner_chat_offer", [], "You have one last chance to redeem yourself before I sell you to the slave-traders.  "\
                                      "Drop all your previous allegiances and swear fealty to me, obey my every order to the letter, and you'll be paid, fed and equipped.  "\
                                      "If you don't....well, let's just say that life as a slave will be seemingly unending years of agony, malnutrition and beatings.  "\
                                      "I'd advise you to think very, very carefully before choosing.", "prisoner_chat_reaction",
                                      [(call_script, "script_determine_prisoner_agreed", "$g_talk_troop", "$g_talk_troop_relation")]],

  [anyone,    "prisoner_chat_reaction", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1)], "Thank you for your mercy, {sir/madam}. I swear on my mothers grave I will serve you, my {lord/lady}!", "prisoner_chat_accept1", []],
  [anyone,    "prisoner_chat_reaction", [], "I'll show you what I think of your offer! (The prisoner spits at your feet) There. Now get lost, I'm not interested.", "prisoner_chat_refuse", []],

  [anyone|plyr, "prisoner_chat_refuse", [], "I see...", "prisoner_chat_menu", [(store_current_day, ":today"), (troop_set_slot, "$g_talk_troop", slot_prisoner_rejected_day, ":today")]],

  [anyone|plyr, "prisoner_chat_die1", [], "(You advance on the prisoner...)", "prisoner_chat_die2", []],
  [anyone,    "prisoner_chat_die2", [], "Please, {sir/madam}, don't kill me. I am a defenceless prisoner. Surely you're not that cruel?", "prisoner_chat_die3", []],
  [anyone|plyr, "prisoner_chat_die3", [], "(Kill the prisoner)", "prisoner_chat_die4", []],
  [anyone|plyr, "prisoner_chat_die3", [], "No, I will not sink that low.", "close_window", []],
  [anyone|plyr, "prisoner_chat_die4", [], "(The prisoner struggles against his shackles, desperate to free himself and escape you, but to no avail. You slit their throat with a knife and watch, satisfied, as his corpse sags to the floor.)", "close_window",
  [(remove_troops_from_prisoners, "$g_talk_troop", 1),
    (call_script, "script_change_player_honor", -1)]],

  [anyone|plyr, "prisoner_chat_accept1", [], "If you so much as fail to tremble on my command, I will have you severely disciplined!", "prisoner_chat_accept2", []],
  [anyone|plyr, "prisoner_chat_accept1", [], "In my camp we are all treated as equals.  I expect your obedience, but also your trust.", "prisoner_chat_accept2", []],

  [anyone,      "prisoner_chat_accept2", [], "I will obey your wishes, my {lord/lady}.  I swear!", "prisoner_chat_accept3", []],

  [anyone|plyr, "prisoner_chat_accept3", [(neg|troops_can_join, 1)], "Oh! Apparently there isn't enough room for you in my party. I will be back when I have made space.", "close_window", []],
  [anyone|plyr, "prisoner_chat_accept3", [(troops_can_join, 1)], "Excellent. Report to the quartermaster for provisions and equiment.  There is hard fighting ahead.", "close_window",
  [(troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, 0),
    (remove_troops_from_prisoners, "$g_talk_troop", 1),
    (party_add_members, "p_main_party", "$g_talk_troop", 1),
    (store_random_in_range, ":roll", 0, 100),
    (store_character_level, ":chance", "$g_talk_troop"),
    (try_begin),
      (lt, ":roll", ":chance"),
      (call_script, "script_change_troop_renown", "trp_player", 1),
    (try_end),
  ]],

  [anyone|plyr, "prisoner_chat_treason", [(str_store_troop_name, s1, "$g_talk_troop"), (str_store_faction_name, s2, "$players_kingdom")],
    "{s1}, you have committed cimes against the {s2}, for which you will now stand trial.^How plead you?", "prisoner_chat_treason_plead",
    [
      # determine the noble's reaction to this accusation
      (store_random_in_range, reg0, 0, 100),
      (val_mod, reg0, 4),
      #TODO: weight the reaction according to the renown?  Or at least according to king or not...
      (troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, reg0),
    ]
  ],

  [anyone,      "prisoner_chat_treason_plead", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 0), ],
    "Please have mercy upon my soul.  All I have done, I have done in the name of my King and Country!  I am but a patriot, as you, and I deserve your respect, if nothing else.", "prisoner_chat_treason_choose", []],
  [anyone,      "prisoner_chat_treason_plead", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1), ],
    "You are gravely mistaken!  I am an honorable Lord, and I have done nothing that you would not do were our roles exchanged.", "prisoner_chat_treason_choose", []],
  [anyone,      "prisoner_chat_treason_plead", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 2), ],
    "I spit on you and yours!  You are but a cur come to put on airs, as though you were Noble and had any right whatsoever to judge me!  Me!  You are a nothing but a common brigand and a coward!  I do not bow to you.  You should drop to your knees and beg *my* forgiveness!", "prisoner_chat_treason_choose", []],
  [anyone,      "prisoner_chat_treason_plead", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 3), ],
    "You dare accuse me?!  You sniveling whelpling!  I should see you flogged and put in chains in one of my prisons for your insolence!", "prisoner_chat_treason_choose", []],

  [anyone|plyr, "prisoner_chat_treason_choose", [], "I am a {man/woman} of honor.  I shall spare your life this day!", "prisoner_chat_treason_not_guilty",
    [
      #TODO: have the relation with the prison have a mixed (random) result - relief, anger, etc, which dictates their final monologue to the player before exiting the dialog

      # make sure we don't try to recruit this prisoner later!
      (troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, 0),
    ]
  ],

  [anyone,      "prisoner_chat_treason_not_guilty", [(str_store_troop_name, s1, "trp_player")], "There is yet hope for you, {s1}.", "close_window", []],

  [anyone|plyr, "prisoner_chat_treason_choose", [], "You do not deserve leiniency.  You must pay for your crimes with your life.", "prisoner_chat_treason_guilty", []],

  [anyone|plyr, "prisoner_chat_treason_guilty", [], "For your many crimes against {s1}, I hereby sentence you to death, to be carried out immediately.  Have you any final words to say?", "prisoner_chat_treason_final_words",
    [
      (store_random_in_range, reg0, 0, 100),
      (val_mod, reg0, 5),
      (troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, reg0),
    ]
  ],

  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 0)], "Who are you?^A day passes^We are but children", "prisoner_chat_treason_execute", []],
  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 1)], "I believe you will one day come to regret your actions.  There is only one who is worthy to decide another's fate... and that one is not you.", "prisoner_chat_treason_execute", []],
  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 2)], "You are a coward and a dog!  May your soul rot eternal, damn you!", "prisoner_chat_treason_execute", []],
  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 3)], "Winter's mortality, ^locked in frozen indifference, ^melts with Spring's rebirth.", "prisoner_chat_treason_execute", []],
  [anyone,      "prisoner_chat_treason_final_words", [(troop_slot_eq, "$g_talk_troop", slot_prisoner_agreed, 4)], "You will find no peace on this earth!  I shall haunt thee eternal!  Unto death you will find nothing but unhappiness and fear.  And beyond... only torture and pain!", "prisoner_chat_treason_execute", []],

  [anyone|plyr, "prisoner_chat_treason_execute", [],
    "(The prisoner struggles against his shackles, desperate to free himself and escape you, but to no avail. You slit his throat and watch, satisfied, as his corpse sags to the floor.)",
    "close_window",
    [
      # make sure we don't try to recruit this prisoner stack later!
      (troop_set_slot, "$g_talk_troop", slot_prisoner_agreed, 0),

      # "kill" the NPC - force the 48 hr respawn kingdom heros trigger to ignore this troop (no party will be created for this troop, ever again)
      # [q.v. script_create_kingdom_hero_party]
      (troop_set_slot, "$g_talk_troop", slot_troop_occupation, slto_dead),

      # remove them from their faction
      (troop_set_slot, "$g_talk_troop", slot_troop_change_to_faction, "fac_no_faction"),
      (troop_set_slot, "$g_talk_troop", slot_troop_original_faction, "fac_no_faction"),

      # determine the penalty for this act (based on the honor of the troop they've killed)
      (troop_get_slot, ":impact", "$g_talk_troop", slot_troop_renown),
      (val_div, ":impact", -33),
      (store_div, ":half", ":impact", 2),

      # don't overwhlem the display with too many messages, otherwise it won't show any of them
      (set_show_messages, 0),

      # reduce the player's relationship with every village, town, and castle
      (try_for_range, ":center", centers_begin, centers_end),
        (store_faction_of_party, ":faction", ":center"),
        (store_relation, ":relation", ":faction", "$g_talk_troop_faction"),
        (try_begin),
          (le, ":relation", -5),
          # enemies, half impact
          (call_script, "script_change_player_relation_with_center", ":center", ":half"),
        (else_try),
          # not at war, full impact
          (call_script, "script_change_player_relation_with_center", ":center", ":impact"),
        (try_end),
      (try_end),

      # reduce the player's relationship with every hero, companion, lady, and daughter
      (try_for_range, ":troop", trp_npc1, trp_heroes_end),
        # don't make the dead any angrier than they already are!
        (neg|troop_slot_eq, ":troop", slot_troop_occupation, slto_dead),
        (store_troop_faction, ":faction", ":troop"),
        (store_relation, ":relation", ":faction", "$g_talk_troop_faction"),
        (try_begin),
          (le, ":relation", -5),
          # enemies, half impact
          (call_script, "script_change_player_relation_with_troop", ":troop", ":half"),
        (else_try),
          # not at war, full impact
          (call_script, "script_change_player_relation_with_troop", ":troop", ":impact"),
        (try_end),
      (try_end),

      # don't overwhlem the display with too many messages, otherwise it won't show any of them
      (set_show_messages, 1),

      # reduce the player's relationship with every faction (enemies 1/2 as much)
      (try_for_range, ":faction", kingdoms_begin, kingdoms_end),
        (store_relation, ":relation", ":faction", "$g_talk_troop_faction"),
        (try_begin),
          (le, ":relation", -10),
          # enemies, half impact
          (call_script, "script_change_player_relation_with_faction", ":faction", ":half"),
        (else_try),
          # not at war, full impact
          (call_script, "script_change_player_relation_with_faction", ":faction", ":impact"),
        (try_end),
      (try_end),

      # apply the honor hit
      (call_script, "script_change_player_honor", ":impact"),

      # party morale takes a hit as well
      (call_script, "script_change_player_party_morale", ":half"),

      # but give them renown for this evil deed (their deed spreads upon every tongue, impressing some, and cowing others)
      (val_mul, ":impact", -1),
      (call_script, "script_change_troop_renown", "trp_player" , ":impact"),

      # start with the assumption that the fief should return to its faction for redistribution
      (assign, ":fief_faction", "$g_talk_troop_faction"),

      (try_begin),
        # handle executing the King!
        (faction_slot_eq, "$g_talk_troop_faction", slot_faction_leader, "$g_talk_troop"),

        # find best candidate to become king
        (assign, ":best_troop", -1),
        (assign, ":best_renown", -1),
        (try_for_range, ":troop", kingdom_heroes_begin, kingdom_heroes_end),
          (neg|troop_slot_eq, ":troop", slot_troop_occupation, slto_dead),  #can't choose a dead hero!
          (store_troop_faction, ":faction", ":troop"),
          (eq, ":faction", "$g_talk_troop_faction"),
          (troop_slot_eq, ":troop", slot_troop_occupation, slto_kingdom_hero),  #only other heros of this faction may become the king
          (troop_get_slot, ":renown", ":troop", slot_troop_renown),
          (gt, ":renown", ":best_renown"),
          (assign, ":best_troop", ":troop"),
          (assign, ":best_renown", ":renown"),
        (try_end),

        (try_begin),
          # check if a candidate was found
          (neq, ":best_troop", -1),

          # make them king
          (faction_set_slot, "$g_talk_troop_faction", slot_faction_leader, ":best_troop"),

          # announce it!
          #TODO: generate a presentation for this! (start_presentation, "prsnt_enemy_succession"),
          (str_store_troop_name_link, s1, ":best_troop"),
          (str_store_faction_name_link, s2, "$g_talk_troop_faction"),
          (display_message, "@{s1} is the new King of the {s2}!!!", red),
          #TODO: update the game log for this event
          #script_add_log_entry
        (else_try),
          # all of the lords have been eliminated - so eliminate the faction by making their last fief neutral (q.v. trigger: # Check if a faction is defeated every day)
          (assign, ":fief_faction", "fac_no_faction"),
        (try_end),
      (try_end),

      # free up the deceased's fief
      (try_for_range, ":fief", centers_begin, centers_end),
        (party_get_slot, ":lord", ":fief", slot_town_lord),
        (eq, ":lord", "$g_talk_troop"),
        (party_set_slot, ":lord", ":fief", slot_town_lord, stl_unassigned),
        (call_script, "script_give_center_to_faction", ":fief", ":fief_faction"),
      (try_end),

      # no longer our prisoner
      (call_script, "script_remove_troop_from_prison", "$g_talk_troop"),
      (remove_troops_from_prisoners, "$g_talk_troop", 1),
    ]
  ],

  ###################################################################################################
  # End Prisoner Talk
  ###################################################################################################
 
Initializing...
Traceback (most recent call last):
  File "process_global_variables.py", line 6, in <module>
    from module_dialogs import *
  File "C:\Program Files\SAFE ModuleSystemADOE\module_dialogs.py", line 12724, i
n <module>
    (display_message, "@{s2} ({reg4}) relation = {reg2}", debug_color),
NameError: name 'debug_color' is not defined
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...
Exporting party_template data...
Exporting parties
Exporting quest data...
Exporting scripts...
Exporting mission_template data...
Exporting game menus data...
exporting simple triggers...
Traceback (most recent call last):
  File "process_dialogs.py", line 6, in <module>
    from module_dialogs import *
  File "C:\Program Files\SAFE ModuleSystemADOE\module_dialogs.py", line 12724, i
n <module>
    (display_message, "@{s2} ({reg4}) relation = {reg2}", debug_color),
NameError: name 'debug_color' is not defined
Checking global variable usages...

______________________________

Script processing has ended.
Press any key to exit. . .
How it compiles.
Triple post because I can't have more than 40000 characters.
 
The latest code that I sent you has various dependencies on SoD features.  e.g. the debug_color.  Just define one in your module_constants.py, or comment out the debug statements (they're only there to debug it).

e.g.:

debug_color = 0xFFFF0000      # solid red

Similarly, most debug sections are inside of a (try_begin), (eq, "$g_sod_debug", 1) ...  Simply comment out the entire debug block, or go ahead and add a $g_sod_debug to your mod (assign it to zero in script_start_game), and add yourself a menu option to set it to 1 when you want to see debug messages (and you can easily extend that to all of your work - simply put debug messages within try blocks that are enabled if your debug global is set to true (1).

There are probably a bunch of other dependencies in there - e.g. I reference trp_ief_*   which are the SoD faction that attacks later in the game.  Those won't be in your module, so you'll have to swap out those references with ones that make sense in your game.  e.g. that section of code determines which faction a given troop belongs to, since M&B don't store that info with troops (they're normally fac_neutral).  So, I have a series of (is_between, <first_troop>,<last_troop>+1) type statements to figure out their real faction.  So just look in your module_troop.py file and figure out what makes sense in your mod.  e.g. take out the section that has to do with the IEF, and instead look to see what troop follows the Rhodocks, and place that instead of the ief as the terminal end of the Rhodocks range.

I think I probably added another slot since I wrote the above as well, to ensure that you can't just keep asking the troop over & over until you get a good roll - so it remembers when you last talked to them and forces you to wait for the next day before trying again.  The slot number you  use for that can be any unused troop slot in your mod.  If you're not using troop slot #232, then assign that to it (Its up to you to figure out for your mod which slots you're using on which entity types.  So for troops, you're using one set of slots, which has nothing to do with parties, or factions, and so on).

Does that all make sense?
 
What's this?  Two BLAMs in one day?!  Yes!  (Previous BLAM here, re:  freecam after death http://forums.taleworlds.com/index.php/topic,63178.msg1641483.html#msg1641483).

I hate the phrase "Kingdom Management" because people bandy it about with seeming indifference typically referring to Highlander's AoM implementation which just about every mod under the sun seems to use.  Undaunted by this, I built my own because I'm like that.  Here's one tasty bit of it in presentation form.

This is a very simple presentation that chugs through all the centers on the map and displays a list of them belonging to the player's faction while printing out some useful information.  It could be easily modified for various nefarious purposes not limited to changing the faction compared against, changing the data displayed, and color coding stuff in a more useful way.  Stuff it at the bottom of module_presentations.py and call from a menu or whatnot as you desire.  It handles multiple pages of stuff reasonably well adding "more" and "prev" buttons at the bottom when it's called for.

As always, credit if the code is used in a released mod would be swell.
("show_centers", 0, mesh_load_window,
[
(ti_on_presentation_load,
[
(presentation_set_duration, 999999),
(set_fixed_point_multiplier, 1000),
(create_button_overlay, "$g_presentation_obj_1", "@Done.", tf_center_justify),
(position_set_x, pos1, 500),
(position_set_y, pos1, 80),
(overlay_set_position, "$g_presentation_obj_1", pos1),

# clear both of these out so we don't get confused if we don't use them
(assign, "$g_presentation_obj_2", -1),
(assign, "$g_presentation_obj_3", -1),

# instruction header
(str_store_faction_name, s10, "fac_player_supporters_faction"),
(str_store_string, s0, "@All fiefs of {s10}"),
(create_text_overlay, reg1, s0, tf_center_justify),
(position_set_x, pos1, 500),
(position_set_y, pos1, 700),
(overlay_set_position, reg1, pos1),

# column_header
(assign, ":cur_y", 650),
(assign, ":y_stride", 25),
(create_text_overlay, ":eek:verlay_id", "@Name"),
(position_set_x, pos1, 50),
(position_set_y, pos1, ":cur_y"),
(overlay_set_position, ":eek:verlay_id", pos1),
(overlay_set_color, ":eek:verlay_id", 0x0000FF),
(create_text_overlay, ":eek:verlay_id", "@Lord"),
(position_set_x, pos1, 275),
(position_set_y, pos1, ":cur_y"),
(overlay_set_position, ":eek:verlay_id", pos1),
(overlay_set_color, ":eek:verlay_id", 0x0000FF),
(create_text_overlay, ":eek:verlay_id", "@Pop"),
(position_set_x, pos1, 450),
(position_set_y, pos1, ":cur_y"),
(overlay_set_position, ":eek:verlay_id", pos1),
(overlay_set_color, ":eek:verlay_id", 0x0000FF),
(create_text_overlay, ":eek:verlay_id", "@Prosp"),
(position_set_x, pos1, 550),
(position_set_y, pos1, ":cur_y"),
(overlay_set_position, ":eek:verlay_id", pos1),
(overlay_set_color, ":eek:verlay_id", 0x0000FF),
(create_text_overlay, ":eek:verlay_id", "@Improvements"),
(position_set_x, pos1, 625),
(position_set_y, pos1, ":cur_y"),
(overlay_set_position, ":eek:verlay_id", pos1),
(overlay_set_color, ":eek:verlay_id", 0x0000FF),
(val_sub, ":cur_y", ":y_stride"),

# chug through all walled centers
(assign, ":center_count", 0),
(assign, ":centers_displayed", 0),
(try_for_range, ":center", centers_begin, centers_end),
(try_begin),
(ge, ":center_count", "$g_kt_menu_count"),
(lt, ":centers_displayed", kt_slot_faction_line_count),
(party_get_slot, ":lord", ":center", slot_town_lord),
# player faction stuff only!
(store_faction_of_party, ":center_faction", ":center"),
(eq, ":center_faction", "fac_player_supporters_faction"),
(val_add, ":center_count", 1), # bugfix
# is this center not owned by the player?  if so, display in red.
(assign, ":color", 0x000000),
(try_begin),
(neg|party_slot_eq, ":center", slot_town_lord, "trp_player"),
(assign, ":color", 0xFF0000),
(try_end),
# center name
(str_store_party_name, s10, ":center"),
(create_text_overlay, ":eek:verlay_id", "@{s10}"),
(position_set_x, pos1, 50),
(position_set_y, pos1, ":cur_y"),
(overlay_set_position, ":eek:verlay_id", pos1),
(overlay_set_color, ":eek:verlay_id", ":color"),
# owner
(try_begin),
(ge, ":lord", 0),
(str_store_troop_name, s13, ":lord"),
(else_try),
(str_store_string, "@Unclaimed"),
(try_end),
(create_text_overlay, reg1, s13),
(position_set_x, pos1, 275),
(position_set_y, pos1, ":cur_y"),
(overlay_set_position, reg1, pos1),
# prosperity
(party_get_slot, reg11, ":center", slot_town_prosperity),
(create_text_overlay, reg1, "@{reg11}"),
(position_set_x, pos1, 550),
(position_set_y, pos1, ":cur_y"),
(overlay_set_position, reg1, pos1),
# improvements, no display if none
(call_script, "script_kt_print_improvements_abrv_to_s0", ":center"),
(try_begin),
(gt, reg0, 0),
(create_text_overlay, reg1, "@{reg0}: {s0}"),
(position_set_x, pos1, 625),
(position_set_y, pos1, ":cur_y"),
(overlay_set_position, reg1, pos1),
(try_end),
# advance stuff
(val_sub, ":cur_y", ":y_stride"),
(val_add, ":centers_displayed", 1),
(try_end),
(try_end),

# if center count is max centers, display the more button
(try_begin),
(ge, ":centers_displayed", kt_slot_faction_line_count),
(create_button_overlay, "$g_presentation_obj_2", "@More centers", tf_center_justify),
(position_set_x, pos1, 500),
(position_set_y, pos1, 55),
(overlay_set_position, "$g_presentation_obj_2", pos1),
(try_end),

# if "$g_kt_menu_count" > 0, display the prev button
(try_begin),
(ge, "$g_kt_menu_count", kt_slot_faction_line_count),
(create_button_overlay, "$g_presentation_obj_3", "@Previous centers", tf_center_justify),
(position_set_x, pos1, 500),
(position_set_y, pos1, 30),
(overlay_set_position, "$g_presentation_obj_3", pos1),
(try_end),
]),

(ti_on_presentation_event_state_change,
[
(store_trigger_param_1, ":eek:bject"),
(assign, reg10, ":eek:bject"),
#(display_message, "@DEBUGHAX:  active object is {reg10}", 0xFFFFF00),
(try_begin),
(eq, ":eek:bject", "$g_presentation_obj_1"),
(presentation_set_duration, 0),
(change_screen_return),
(jump_to_menu, "mnu_camp"), # change this to wherever you want to return to
(else_try),
(eq, ":eek:bject", "$g_presentation_obj_2"),
(val_add, "$g_kt_menu_count", kt_slot_faction_line_count),
(change_screen_return),
(start_presentation, "prsnt_show_centers"),
(else_try),
(eq, ":eek:bject", "$g_presentation_obj_3"),
(val_sub, "$g_kt_menu_count", kt_slot_faction_line_count),
(change_screen_return),
(start_presentation, "prsnt_show_centers"),
(try_end),
]),
]), # end show_center

Stick this stuff in module_scripts.py wherever's convenient:
# builds a display list of the current improvements of a center to s0
# in abbreviated form.  also fills out reg0 with the improvement count.
# INPUT:  arg1:  center number
# OUTPUT:  s0:    improvement names
#          reg0:  improvement count
#          s17:  center type name
# SIDE EFFECTS:
# - nukes s18 for temp space
( "kt_print_improvements_abrv_to_s0",
[
(store_script_param_1, ":center"),
(assign, ":num_improvements", 0),
(str_clear, s1:cool:,

(try_begin),
(party_slot_eq, ":center", slot_party_type, spt_village),
(assign, ":begin", village_improvements_begin),
(assign, ":end", village_improvements_end),
(str_store_string, s17, "@village"),
(else_try),
# this is sneaky!  :begin and :end are set for this block
# and the next because the eq is done afterward
(assign, ":begin", walled_center_improvements_begin),
(assign, ":end", walled_center_improvements_end),
(party_slot_eq, ":center", slot_party_type, spt_town),
(str_store_string, s17, "@town"),
(else_try),
(str_store_string, s17, "@castle"),
(try_end),

(try_for_range, ":improvement_no", ":begin", ":end"),
(party_slot_ge, ":center", ":improvement_no", 1),
(val_add,  ":num_improvements", 1),
# note that this script nukes s0
(call_script, "script_kt_get_improvement_name_abrv", ":improvement_no"),
(try_begin),
(eq,  ":num_improvements", 1),
(str_store_string, s18, "@{s0}"),
(else_try),
(str_store_string, s18, "@{s18}, {s0}"),
(try_end),
(try_end),

(try_begin),
(eq, ":num_improvements", 0),
(str_store_string, s18, "@No improvements"),
(try_end),

(str_store_string_reg, s0, s1:cool:,
(assign, reg0, ":num_improvements"),
]),

# script_kt_get_improvement_name_abrv
# INPUT:  arg1 = improvement
# OUTPUT:  s0 = abbreviated improvement name
("kt_get_improvement_name_abrv",
[
(store_script_param, ":improvement_no", 1),
(try_begin),
(eq, ":improvement_no", slot_center_has_manor),
(str_store_string, s0, "@MNR"),
(else_try),
(eq, ":improvement_no", slot_center_has_mill),
(str_store_string, s0, "@MIL"),
(else_try),
(eq, ":improvement_no", slot_center_has_watch_tower),
(str_store_string, s0, "@WT"),
(else_try),
(eq, ":improvement_no", slot_center_has_school),
(str_store_string, s0, "@SCH"),
(else_try),
(eq, ":improvement_no", slot_center_has_messenger_post),
(str_store_string, s0, "@MP"),
(else_try),
(eq, ":improvement_no", slot_center_has_prisoner_tower),
(str_store_string, s0, "@PT"),
(else_try),
(assign, reg0, ":improvement_no"),
(str_store_string, s0, "@ERROR"),
(try_end),
]),

Some caveats:
- it's a data window, so it's pretty dense (see screenie) and there's no pretty picture
- you will need to define kt_slot_faction_line_count somewhere like module_constants.py to 20 or so which is the number of entries per page
- there's a hefty gap between the lord and prosperity column where I stash some of my mod-specific stuff which you can see in the screenie (I also have different buildings)
- you probably don't want the presentation to bail back to the camp menu
- for the love of all that you hold dear, clear $g_kt_menu_count to zero before you start the presentation
- if you've added buildings, it's reasonably straightforward to add them to the list
- this isn't the exact code I use; mine has some other trickery and some extra stuff so I haven't tested exactly this code

Screenie:
r1lr12.jpg

5-11-2009:  fixed a bug where the counts were off (my test case was where I owned all the fiefs)
 
Back
Top Bottom