This is pretty basic and crude, but I thought I'd post it and get this ball rolling.
In version 1.134 of the Warband engine, the trigger condition ti_on_agent_hit was introduced. This is a very big deal; it means that we can pretty much design whatever damage systems we'd like, making really huge changes to combat systems. For example, if you want to do an ultra-detailed damage sim for a really hardcore historical mod, including critical hits, weapons breaking (this trigger is the most efficient way to handle that) and special damage for special situations (like, say, slipping a dagger through some poor knight's visor while he's prone, or, for that matter, knocking people prone or stunned occasionally, like how I did it with the Shield Bash code) well, this is by far the way to do these things.
In short, this is a Big Deal
I'll certainly be back to this and exploring how fancy I can make it without it performing really badly when I'm back around again. It's one of the things that I really wanted to play with when Blood and Steel's core combat balance was designed, and now that it exists, I think that everybody should look at it. It will allow people to customize combat in ways that simply weren't possible before.
So, here's some very basic code to get people's brains moving. I haven't had time to flesh this out with a lot of details yet, but it's functional and it demonstrates some basic uses of this- a "natural soak" or "toughness" stat (as opposed to armor soak) and an "auto-dodge" (critical hits could use the same idea but with the opposite treatment of damage, obviously).
In module_mission_templates:
Example of use (for people who aren't familiar with using custom triggers):
In version 1.134 of the Warband engine, the trigger condition ti_on_agent_hit was introduced. This is a very big deal; it means that we can pretty much design whatever damage systems we'd like, making really huge changes to combat systems. For example, if you want to do an ultra-detailed damage sim for a really hardcore historical mod, including critical hits, weapons breaking (this trigger is the most efficient way to handle that) and special damage for special situations (like, say, slipping a dagger through some poor knight's visor while he's prone, or, for that matter, knocking people prone or stunned occasionally, like how I did it with the Shield Bash code) well, this is by far the way to do these things.
In short, this is a Big Deal
I'll certainly be back to this and exploring how fancy I can make it without it performing really badly when I'm back around again. It's one of the things that I really wanted to play with when Blood and Steel's core combat balance was designed, and now that it exists, I think that everybody should look at it. It will allow people to customize combat in ways that simply weren't possible before.
So, here's some very basic code to get people's brains moving. I haven't had time to flesh this out with a lot of details yet, but it's functional and it demonstrates some basic uses of this- a "natural soak" or "toughness" stat (as opposed to armor soak) and an "auto-dodge" (critical hits could use the same idea but with the opposite treatment of damage, obviously).
In module_mission_templates:
Code:
#Damage simulation code example by xenoargh
#Makes Ironflesh reduce damage (i.e., it's actually worth putting points into in SP)
#Makes Athletics also give an 'auto-dodge' or 'roll with punch' that reduces damage to a minimum
common_damage_system = (ti_on_agent_hit, 0, 0, [],
[
(store_trigger_param_1, ":agent"),
(store_trigger_param_2, ":attacker"),
(store_trigger_param_3, ":damage"),
(store_trigger_param_3, ":orig_damage"),
(agent_get_troop_id, ":troop", ":agent"),
(agent_get_troop_id, ":attacker_troop", ":attacker"),
(store_skill_level, ":ironflesh", "skl_ironflesh", ":troop"),
(store_skill_level, ":athletics", "skl_athletics", ":troop"),
#Damage is lowered 5% per point of Ironflesh.
(try_begin),
(gt, ":ironflesh", 0),
(val_mul, ":ironflesh", 5),
(assign, ":mod_damage", ":damage"),
(val_mul, ":mod_damage", ":ironflesh"),
(val_div, ":mod_damage", 100),#Rounded here, but whatever.
(val_sub, ":damage", ":mod_damage"),
(try_end),
#Damage is avoided 5% per point of Athletics
(try_begin),
(gt, ":athletics", 0),
(val_mul, ":athletics", 5),
(store_random_in_range, ":random_no", 1, 100),
(try_begin),
(le, ":random_no", ":athletics"),
(assign, ":damage", 1),
(try_begin),
(eq, ":troop", "trp_player"),
(display_message, "@You dodge the attack!"),
(else_try),
(eq, ":attacker_troop", "trp_player"),
(display_message, "@{He/She} dodges the attack!"),
(try_end),
(try_end),
(try_end),
(store_sub, ":diff_damage", ":damage", ":orig_damage"),
(val_mul, ":diff_damage", -1),
(store_agent_hit_points, ":hitpoints" , ":agent", 1),
(val_add, ":hitpoints", ":diff_damage"),
(agent_set_hit_points,":agent",":hitpoints",1),
])
Example of use (for people who aren't familiar with using custom triggers):
Code:
(
"back_alley_kill_local_merchant",mtf_arena_fight,-1,
"You enter the back alley",
[
(0,mtef_visitor_source|mtef_team_0,af_override_horse,aif_start_alarmed,1,[]),
(3,mtef_visitor_source|mtef_team_1,af_override_horse,aif_start_alarmed,1,[]),
],
[
common_inventory_not_available,
#Realistic Weather
common_weather_system,
#Ammunition System
common_ammunition_system,
#New Damage System
common_damage_system,
#Fade in
common_shield_bash,
order_weapon_type_triggers,
common_fade_from_black,
(ti_tab_pressed, 0, 0, [(display_message,"str_cannot_leave_now")], []),
(ti_before_mission_start, 0, 0, [], [(call_script, "script_change_banners_and_chest")]),
(0, 0, ti_once, [],
[
(call_script, "script_music_set_situation_with_culture", mtf_sit_ambushed),
]),
(0, 0, ti_once, [
(store_mission_timer_a,":cur_time"),
(ge,":cur_time",1),
(assign, ":merchant_hp", 0),
(assign, ":player_hp", 0),
(assign, ":merchant_hp", 0),
(assign, ":merchant_agent", -1),
(assign, ":player_agent", -1),
(try_for_agents, ":agent_no"),
(agent_get_troop_id, ":troop_id", ":agent_no"),
(try_begin),
(eq, ":troop_id", "trp_local_merchant"),
(store_agent_hit_points, ":merchant_hp", ":agent_no"),
(assign, ":merchant_agent", ":agent_no"),
(else_try),
(eq, ":troop_id", "trp_player"),
(store_agent_hit_points, ":player_hp",":agent_no"),
(assign, ":player_agent", ":agent_no"),
(try_end),
(try_end),
(ge, ":player_agent", 0),
(ge, ":merchant_agent", 0),
(agent_is_alive, ":player_agent"),
(agent_is_alive, ":merchant_agent"),
(is_between, ":merchant_hp", 1, 30),
(gt, ":player_hp", 50),
(start_mission_conversation, "trp_local_merchant"),
], []),
(1, 4, ti_once, [(assign, ":not_alive", 0),
(try_begin),
(call_script, "script_cf_troop_agent_is_alive", "trp_local_merchant"),
(else_try),
(assign, ":not_alive", 1),
(try_end),
(this_or_next|main_hero_fallen),
(eq, ":not_alive", 1)],
[
(try_begin),
(main_hero_fallen),
(call_script, "script_fail_quest", "qst_kill_local_merchant"),
(else_try),
(call_script, "script_change_player_relation_with_center", "$current_town", -4),
(call_script, "script_succeed_quest", "qst_kill_local_merchant"),
(try_end),
(set_rain, 0, 0),
#(set_fog_distance, 0),
(finish_mission),
]),
],
),