After seeing a few others comment on the limits of weapon usage orders (Blunt/Any, Fire/Hold Fire) it seemed worthwhile to whip up a simple code to expand order functionality.
With this simple code, the player hasthree four more orders at his/her disposal, based on weapon-type, when instructing their army. With the push of a button, the player can order the currently selected combination of battle groups/divisions to equip a weapon of a certain type: one-handed; two-handed or polearm; and ranged or throwing. Also, the commander can order their troops to equip/unequip their shields (brandish and doff, respectively, in the parlance). The order going out to the troops will scroll on screen as native orders do. (This has not, however been worked into the panel with the map.)
The combination of some orders may prove fruitful. For instance, ordering "two-handers and polearms" to your Rhodok spears will have spears/spiked staffs that can be wielded one-handed still used with a shield. Following this order up with "doff your shields" will slide their board shields on to their backs, forcing the weapons to be wielded with two hands. Repeating the shield order "brandish shields" will cause those who can to pull their shields back out, while still using their polearm.
This should be compatible with most any other code bits/mods/what have you, as it does not add any slots or globals nor does it monkey with the original source code. The only compatibility issue will be to find 4 suitable, unused keys for the orders. Currently, they are set as F9=Use One-Handed Weapons; F10=Use Two-Handed Weapons and Polearms; F11=Use Ranged/Throwing Weapons. F8=Shield Toggle. To clear weapon type orders, simply give the F3-F4, "Use Weapons at Will", order built in to the command system.
The workhorse script. Place where ever within scripts = [... The beginning works just fine.
Stick them in each of the actual mission templates you want to be able to give the order without the "order_weapon_type_triggers" title and brackets, or stick them toward the top of the file (I put them after the multiplayer_* and before the common_* around line 630) and then just include the "order_weapon_type_triggers" title in the mission templates. I tend to install extra triggers as follows:
Add to bottom of Constants.py, after customizing the keys used to your taste and ensuring no conflicts.
Two things that could be improved, off the bat:
1)If anyone knows the hex color code for troop orders (yellowish?), that would be helpful as the current color used is just an approximation. I was unable to find any reference to it. I believe it is the same a similar color as is used for your amount of Gold in multiplayer: 0xFFDDDD66 Script updated. The shade is too 'gold' and not yellow enough.
2) Similarly, if the string that is used by the engine to say who is receiving orders is known, it could be added so the orders follow the format of native orders more efficiently than the current code.
This has been tested and is working as described.
Comments, etc, welcome.
EDIT: Scripts.py code updated to include group names in the order text that scrolls on screen, such as "Infantry, ready polearms!" ...not particularly efficient code, but effective.
EDIT 2: All code bits updated to include new shield toggle.
With this simple code, the player has
The combination of some orders may prove fruitful. For instance, ordering "two-handers and polearms" to your Rhodok spears will have spears/spiked staffs that can be wielded one-handed still used with a shield. Following this order up with "doff your shields" will slide their board shields on to their backs, forcing the weapons to be wielded with two hands. Repeating the shield order "brandish shields" will cause those who can to pull their shields back out, while still using their polearm.
This should be compatible with most any other code bits/mods/what have you, as it does not add any slots or globals nor does it monkey with the original source code. The only compatibility issue will be to find 4 suitable, unused keys for the orders. Currently, they are set as F9=Use One-Handed Weapons; F10=Use Two-Handed Weapons and Polearms; F11=Use Ranged/Throwing Weapons. F8=Shield Toggle. To clear weapon type orders, simply give the F3-F4, "Use Weapons at Will", order built in to the command system.
Code:
# script_order_weapon_type_switch
# Input: Order Type
# Output: Nothing
# On key depression, try to switch division to appropriate weapon
("order_weapon_type_switch", [
(store_script_param_1, ":ordertype"),
(get_player_agent_no, ":player"),
(agent_get_team, ":playerteam", ":player"),
(try_for_agents, ":agent"),
(agent_is_alive, ":agent"),
(agent_is_human, ":agent"),
(agent_is_non_player, ":agent"),
(agent_get_team, ":team", ":agent"),
(eq, ":team", ":playerteam"), #On Player's side?
(agent_get_division, ":class", ":agent"),
(try_begin), #Mark class as in battle
(eq, ":class", 0),
(assign, ":group0_in_battle", 1),
(else_try),
(eq, ":class", 1),
(assign, ":group1_in_battle", 1),
(else_try),
(eq, ":class", 2),
(assign, ":group2_in_battle", 1),
(else_try),
(eq, ":class", 3),
(assign, ":group3_in_battle", 1),
(else_try),
(eq, ":class", 4),
(assign, ":group4_in_battle", 1),
(else_try),
(eq, ":class", 5),
(assign, ":group5_in_battle", 1),
(else_try),
(eq, ":class", 6),
(assign, ":group6_in_battle", 1),
(else_try),
(eq, ":class", 7),
(assign, ":group7_in_battle", 1),
(else_try),
(eq, ":class", 8),
(assign, ":group8_in_battle", 1),
(try_end),
(class_is_listening_order, ":team", ":class"), #Is the agent's team selected?
(try_begin), #Mark class as selected
(eq, ":class", 0),
(assign, ":group0_is_selected", 1),
(else_try),
(eq, ":class", 1),
(assign, ":group1_is_selected", 1),
(else_try),
(eq, ":class", 2),
(assign, ":group2_is_selected", 1),
(else_try),
(eq, ":class", 3),
(assign, ":group3_is_selected", 1),
(else_try),
(eq, ":class", 4),
(assign, ":group4_is_selected", 1),
(else_try),
(eq, ":class", 5),
(assign, ":group5_is_selected", 1),
(else_try),
(eq, ":class", 6),
(assign, ":group6_is_selected", 1),
(else_try),
(eq, ":class", 7),
(assign, ":group7_is_selected", 1),
(else_try),
(eq, ":class", 8),
(assign, ":group8_is_selected", 1),
(try_end),
(agent_get_troop_id, ":troop",":agent"),
(try_begin),
(troop_is_hero, ":troop"),
(assign, ":end", ek_head),
(try_for_range, ":i", ek_item_0, ":end"),
(troop_get_inventory_slot,":item",":troop",":i"),
(gt, ":item", 0),
(item_get_type, ":weapontype", ":item"),
(try_begin),
(eq, ":ordertype", ranged),
(str_store_string, s1, "@ready bows and missiles"),
(this_or_next|eq, ":weapontype", itp_type_bow),
(this_or_next|eq, ":weapontype", itp_type_crossbow),
(eq, ":weapontype", itp_type_thrown),
(agent_set_wielded_item, ":agent", ":item"),
(assign, ":end", ek_item_0),#loop breaker
(else_try),
(eq, ":ordertype", onehand),
(str_store_string, s1, "@ready side arms"),
(eq, ":weapontype", itp_type_one_handed_wpn),
(agent_set_wielded_item, ":agent", ":item"),
(assign, ":end", ek_item_0),#loop breaker
(else_try),
(eq, ":ordertype", bothhands),
(str_store_string, s1, "@ready two-handers and polearms"),
(this_or_next|eq, ":weapontype", itp_type_two_handed_wpn),
(eq, ":weapontype", itp_type_polearm),
(agent_set_wielded_item, ":agent", ":item"),
(assign, ":end", ek_item_0),#loop breaker
(else_try),
(eq, ":ordertype", shield),
(agent_get_wielded_item, ":shield", ":agent", 1),
(try_begin),
(gt, ":shield", 0),
(agent_unequip_item, ":agent", ":shield"),
(agent_equip_item, ":agent", ":shield"), #Moves shield to back
(str_store_string, s1, "@doff your shields"),
(assign, ":end", ek_item_0),#loop breaker
(else_try),
(eq, ":weapontype", itp_type_shield),
(agent_set_wielded_item, ":agent", ":item"), #Moves shield from back to hand
(str_store_string, s1, "@brandish shields"),
(assign, ":end", ek_item_0),#loop breaker
(try_end),
(try_end),
(try_end),
(else_try),#regular troops
(troop_get_inventory_capacity,":cap",":troop"),
(try_for_range, ":i", 0, ":cap"),#(slots < 10)?
(troop_get_inventory_slot,":item",":troop",":i"),
(gt, ":item", 0),
(item_get_type, ":weapontype", ":item"),
(try_begin),
(eq, ":ordertype", ranged),
(str_store_string, s1, "@ready bows and missiles"),
(this_or_next|eq, ":weapontype", itp_type_bow),
(this_or_next|eq, ":weapontype", itp_type_crossbow),
(eq, ":weapontype", itp_type_thrown),
(agent_has_item_equipped, ":agent", ":item"),
(agent_set_wielded_item, ":agent", ":item"),
(assign, ":cap", 0),#loop breaker
(else_try),
(eq, ":ordertype", onehand),
(str_store_string, s1, "@ready side arms"),
(eq, ":weapontype", itp_type_one_handed_wpn),
(agent_has_item_equipped, ":agent", ":item"),
(agent_set_wielded_item, ":agent", ":item"),
(assign, ":cap", 0),#loop breaker
(else_try),
(eq, ":ordertype", bothhands),
(str_store_string, s1, "@ready two-handers and polearms"),
(this_or_next|eq, ":weapontype", itp_type_two_handed_wpn),
(eq, ":weapontype", itp_type_polearm),
(agent_has_item_equipped, ":agent", ":item"),
(agent_set_wielded_item, ":agent", ":item"),
(assign, ":cap", 0),#loop breaker
(else_try),
(eq, ":ordertype", shield),
(agent_get_wielded_item, ":shield", ":agent", 1),
(try_begin),
(gt, ":shield", 0),
(agent_unequip_item, ":agent", ":shield"),
(agent_equip_item, ":agent", ":shield"), #Moves shield to back
(str_store_string, s1, "@doff your shields"),
(assign, ":cap", 0),#loop breaker
(else_try),
(eq, ":weapontype", itp_type_shield),
(agent_has_item_equipped, ":agent", ":item"),
(agent_set_wielded_item, ":agent", ":item"), #Moves shield from back to hand
(str_store_string, s1, "@brandish shields"),
(assign, ":cap", 0),#loop breaker
(try_end),
(try_end),
(try_end),
(try_end), #Hero v Regular Troop
(try_end), #Agent Loop
(str_clear, s2),
(str_clear, s3),
(assign, ":count_possible", 0),
(assign, ":count_selected", 0),
(try_begin),
(eq, ":group0_in_battle", 1),
(val_add, ":count_possible", 1),
(eq, ":group0_is_selected", 1),
(val_add, ":count_selected", 1),
(str_store_class_name, s2, 0),
(try_end),
(try_begin),
(eq, ":group1_in_battle", 1),
(val_add, ":count_possible", 1),
(eq, ":group1_is_selected", 1),
(val_add, ":count_selected", 1),
(try_begin),
(neg|str_is_empty, s2),
(str_store_class_name, s3, 1),
(str_store_string, s2, "@{!}{s2}, {s3}"),
(else_try),
(str_store_class_name, s2, 1),
(try_end),
(try_end),
(try_begin),
(eq, ":group2_in_battle", 1),
(val_add, ":count_possible", 1),
(eq, ":group2_is_selected", 1),
(val_add, ":count_selected", 1),
(try_begin),
(neg|str_is_empty, s2),
(str_store_class_name, s3, 2),
(str_store_string, s2, "@{!}{s2}, {s3}"),
(else_try),
(str_store_class_name, s2, 2),
(try_end),
(try_end),
(try_begin),
(eq, ":group3_in_battle", 1),
(val_add, ":count_possible", 1),
(eq, ":group3_is_selected", 1),
(val_add, ":count_selected", 1),
(try_begin),
(neg|str_is_empty, s2),
(str_store_class_name, s3, 3),
(str_store_string, s2, "@{!}{s2}, {s3}"),
(else_try),
(str_store_class_name, s2, 3),
(try_end),
(try_end),
(try_begin),
(eq, ":group4_in_battle", 1),
(val_add, ":count_possible", 1),
(eq, ":group4_is_selected", 1),
(val_add, ":count_selected", 1),
(try_begin),
(neg|str_is_empty, s2),
(str_store_class_name, s3, 4),
(str_store_string, s2, "@{!}{s2}, {s3}"),
(else_try),
(str_store_class_name, s2, 4),
(try_end),
(try_end),
(try_begin),
(eq, ":group5_in_battle", 1),
(val_add, ":count_possible", 1),
(eq, ":group5_is_selected", 1),
(val_add, ":count_selected", 1),
(try_begin),
(neg|str_is_empty, s2),
(str_store_class_name, s3, 5),
(str_store_string, s2, "@{!}{s2}, {s3}"),
(else_try),
(str_store_class_name, s2, 5),
(try_end),
(try_end),
(try_begin),
(eq, ":group6_in_battle", 1),
(val_add, ":count_possible", 1),
(eq, ":group6_is_selected", 1),
(val_add, ":count_selected", 1),
(try_begin),
(neg|str_is_empty, s2),
(str_store_class_name, s3, 6),
(str_store_string, s2, "@{!}{s2}, {s3}"),
(else_try),
(str_store_class_name, s2, 6),
(try_end),
(try_end),
(try_begin),
(eq, ":group7_in_battle", 1),
(val_add, ":count_possible", 1),
(eq, ":group7_is_selected", 1),
(val_add, ":count_selected", 1),
(try_begin),
(neg|str_is_empty, s2),
(str_store_class_name, s3, 7),
(str_store_string, s2, "@{!}{s2}, {s3}"),
(else_try),
(str_store_class_name, s2, 7),
(try_end),
(try_end),
(try_begin),
(eq, ":group8_in_battle", 1),
(val_add, ":count_possible", 1),
(eq, ":group8_is_selected", 1),
(val_add, ":count_selected", 1),
(try_begin),
(neg|str_is_empty, s2),
(str_store_class_name, s3, 8),
(str_store_string, s2, "@{!}{s2}, {s3}"),
(else_try),
(str_store_class_name, s2, 8),
(try_end),
(try_end),
(try_begin),
(eq, ":count_selected", ":count_possible"),
(str_store_string, s2, "@Everyone"),
(try_end),
(try_begin),
(gt, ":count_selected", 0),
(display_message, "@{!}{s2}, {s1}!", 0xFFDDDD66),
(try_end),
(str_clear, s2),
(str_clear, s3),
]),
Code:
order_weapon_type_triggers = [
(0, 0, 1, [(key_clicked, key_for_onehand)], [(call_script, "script_order_weapon_type_switch", onehand)]),
(0, 0, 1, [(key_clicked, key_for_bothhands)], [(call_script, "script_order_weapon_type_switch", bothhands)]),
(0, 0, 1, [(key_clicked, key_for_ranged)], [(call_script, "script_order_weapon_type_switch", ranged)]),
(0, 0, 1, [(key_clicked, key_for_shield)], [(call_script, "script_order_weapon_type_switch", shield)]),
]
Code:
(
"lead_charge",mtf_battle_mode,charge,
"You lead your men to battle.",
[
// bunch of stuff...all the way to the very end
] + order_weapon_type_triggers,
),
Code:
ranged = 0
onehand = 1
bothhands = 2
shield = 3
from header_triggers import *
key_for_onehand = key_f9
key_for_bothhands = key_f10
key_for_ranged = key_f11
key_for_shield = key_f8
Two things that could be improved, off the bat:
1)
2) Similarly, if the string that is used by the engine to say who is receiving orders is known, it could be added so the orders follow the format of native orders more efficiently than the current code.
This has been tested and is working as described.
Comments, etc, welcome.
EDIT: Scripts.py code updated to include group names in the order text that scrolls on screen, such as "Infantry, ready polearms!" ...not particularly efficient code, but effective.
EDIT 2: All code bits updated to include new shield toggle.