OSP Kit Combat Fancy Damage Systems

Users who are viewing this thread

From what I gather from above, depending on the way the damage - reduction is calculated,
(ge, ":damage", ":hp"),
might not actually mean that the hit agent gets wounded/killed, does it?

You might need an extra step where, in this trigger you set a "decapitate" slot for the agent, and then in an ti_on_agent_killed_or_wounded trigger, this slot is checked for and the agent is decapitated as desired and coded to ensure that the agent is actually killed and not wounded.

But, perhaps that is unnecessary.


Also, xenoargh, are you planning on putting up here your Pike tweak that you worked on with Blood and Steel?
 
Well, that means a better glancing hit with 1 or 2 points of damage would decapitate too an already heavily wounded victim. I think only strong hits should do that.
 
Hmm. I modified the code a bit.

Code:
theoris_decapitation = (
    ti_on_agent_hit, 0, 0, [],
    [
    	(store_trigger_param_1, ":agent"),
		(agent_is_human, ":agent"),
    	(store_trigger_param_3, ":damage"),
		(ge, ":damage", 30), #strong blow
		(store_agent_hit_points, ":hp", ":agent", 1),
		(val_sub, ":hp", 5),
		(ge, ":damage", ":hp"),
		(agent_get_position, pos1, ":agent"),
		(get_distance_between_positions, ":distance", pos1, pos0),
		(is_between, ":distance", 160, 176), # *zing*
		(agent_get_item_slot, ":item", ":agent", 4), #head slot
		(try_begin),
		    (ge, ":item", 1),
			(agent_unequip_item, ":agent", ":item"),
		(try_end),
		(agent_equip_item, ":agent", "itm_invisible_head"),
		(particle_system_burst, "psys_game_blood_2", pos1, 125), #Yeah..
		#(set_spawn_position, pos1),
		#(spawn_scene_prop, "spr_physics_head"),
	]),
 
xenoargh, are you planning on putting up here your Pike tweak that you worked on with Blood and Steel?
Sure.  Here's my current build of code.  Bear in mind, I'm already starting to broaden this out into a ruleset that's specific to gameplay, i.e., you may want to remove / tweak sections, and some of it refers to Skills that aren't in Native (again, sorry, but I'm already diverging a lot).

Anyhow, here's some code with the human/horse split after "universal" events have happened.

Code:
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"),

	#EVERYBODY#
	#Critical hits for missiles
	(try_begin),
		(is_between, reg0, "itm_missile_weapons_start", "itm_missile_weapons_end"),#special def in Blood and Steel source
		(store_random_in_range, ":random_no", 1, 100),
		(try_begin),
			(le, ":random_no", 5),
			(val_min, ":damage", 20),
		(try_end),
	(try_end),	

	#Random critical hits, 3% per point of Combat Training (formerly Tactics)
	(try_begin),
		(store_skill_level, ":combat_training",  "skl_combat_training", ":attacker_troop"),
		(val_mul, ":combat_training", 3),#3 percent chance per level, per hit
		(store_random_in_range, ":random", 1, 100),
		(try_begin),
			(le, ":random", ":combat_training"),		
			(neg|agent_is_ally,":agent"),#don't critically hit non-allies
			(val_max, ":damage", 1),
			(val_mul, ":damage", 3),
		(try_end),
	(try_end),	
	
	#Damage is increased by 2 points for every point of Heroism, 3 if heroes.  Army-based skill!
	(agent_get_party_id, ":attacker_party_id", ":attacker"),
	(party_get_skill_level, ":heroism",  ":attacker_party_id", "skl_heroism"),
	(try_begin),
		(gt, ":heroism", 0),
		(try_begin),
			(troop_is_hero, ":attacker_troop"),
			(val_mul, ":heroism", 3),
			(val_add, ":damage", ":heroism"),
		(else_try),
			(val_mul, ":heroism", 2),
			(val_add, ":damage", ":heroism"),
		(try_end),
	(try_end),
	
	#HUMANS
	(try_begin),
		(agent_is_human, ":agent"),#branch if not human

		#DEFENSIVE SKILLS
		#Damage is lowered 5% per point of Toughness (formerly Ironflesh).
		(try_begin),	
			(store_skill_level, ":toughness",  "skl_toughness", ":troop"),
			(gt, ":toughness", 0),
			(val_mul, ":toughness", 5),
			(assign, ":mod_damage", ":damage"),		
			(val_mul, ":mod_damage", ":toughness"),
			(val_div, ":mod_damage", 100),#Rounded here, but whatever.
			(val_sub, ":damage", ":mod_damage"),
		(try_end),

		#Damage is avoided 5% per point of Reflexes(formerly Athletics)
		(try_begin),
			(store_skill_level, ":reflexes",  "skl_reflexes", ":troop"),
			(gt, ":reflexes", 0),	
			(val_mul, ":reflexes", 5),
			(store_random_in_range, ":random_no", 1, 100),
			(try_begin),
				(le, ":random_no", ":reflexes"),
				(assign, ":damage", 0),
				(try_begin),
					(eq, ":troop", "trp_player"),
					(display_message, "@You dodge the attack!"),
				(else_try),
					(eq, ":attacker_troop", "trp_player"),
					(display_message, "@They dodge the attack!"),
				(try_end),			
			(try_end),
		(try_end),		
	
	#HORSE DAMAGE
	(else_try),
		#Pike special rules
		(try_begin),
			(is_between, reg0, "itm_pikes_start", "itm_pikes_end"),#special def in Blood and Steel source
			(val_min, ":damage", 100),
		(try_end),
		
		#Horses randomly rear if they take damage
		(store_random_in_range, ":random_no", 1, 100),
		(try_begin),
			(gt, ":damage", 5),
			(le, ":random_no", 10),
			(agent_set_animation, ":agent","anim_horse_rear"),
		(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),
])
 
xenoargh said:
Sure.  Here's my current build of code.  Bear in mind, I'm already starting to broaden this out into a ruleset that's specific to gameplay, i.e., you may want to remove / tweak sections, and some of it refers to Skills that aren't in Native (again, sorry, but I'm already diverging a lot).

Anyhow, here's some code with the human/horse split after "universal" events have happened.


  #Random critical hits, 3% per point of Combat Training (formerly Tactics)
  (try_begin),
      (store_skill_level, ":combat_training",  "skl_combat_training", ":attacker_troop"),
      (val_mul, ":combat_training", 3),#3 percent chance per level, per hit
      (store_random_in_range, ":random", 1, 100),
      (try_begin),
        (le, ":random", ":combat_training"),     
        (neg|agent_is_ally,":agent"),#don't critically hit non-allies
        (val_max, ":damage", 1),
        (val_mul, ":damage", 3),
      (try_end),
  (try_end), 

Looking at this, I was thinking the opposite: the blunders (I dont know if it is right word in English, I am talk about slips, lost weapons in combat, injury friend ...)

The idea would be when the player has bad luck in his hit, random blunders occur, with message including.

When brytenwalda 1.33 is update, I like look this.
Thank you Xenoargh!


 
I toyed around with this a bit, testing how well it works. Found a couple of problems in the damage avoidance part.

It currently reduces the damage to 1 instead of 0.  I'm guessing its due to rounding thingie somebody mentinod here. 

It also doesn't always block all the damage. I'm guessing this is because you add the extra hp before the damage is dealt and the agent_set_hit_points doesn't go past agent's max hit points. So if damage received is greater than difference between current and max hitpoints you'll receive damage equal to difference between that difference and damage done... erm not sure i'm making any sense.
 
Yup, that's a problem, as is any blow that is > max hitpoints, due to order of operations.  IOW, if the blow will insta-kill you, you're always going to die, no matter what this code says.

Nothing we can do about that, basically, except ask Taleworls very nicely to fix the order of operations, so that this callin occurs just before damage is applied.  I've put this issue into the bug-tracker; it's probably a 10-minute fix, so perhaps they'll do it sometime in the next few months.
 
The trigger does occur before damage is applied - as I've mentioned several times in the past. Here's a bunch of code I made up which should work for the intended purposes.
Code:
(ti_on_agent_hit, 0, 0, [],
[(store_trigger_param_1, ":agent"),
 (store_trigger_param_3, ":damage"),
... calculate whatever cf_rolls here
 (call_script, "script_get_agent_max_hp", ":agent"), #arbitrary script name - output=35+STR+2*Ironflesh
 (ge, ":damage", reg#), #arbitrary output register - damage will be overkill
 (store_agent_hit_points, ":hp", ":agent", 1), #store current hp
 (agent_set_slot, ":agent", slot_agent_avoid, ":hp"), #inside slot
 (agent_set_no_death_knock_down_only, ":agent", 1), #disable death
]),
Companion trigger to re-enable death
Code:
(ti_on_agent_knocked_down, 0, 0,
[],
[(store_trigger_param_1, ":agent"),
 (agent_get_slot, ":hp", ":agent", slot_agent_avoid),
 (ge, ":hp", 1), #this slot was marked
 (agent_set_slot, ":agent", slot_agent_avoid, 0),
 (agent_set_hit_points, ":agent", ":hp", 1), #restore hp
 (agent_set_no_death_knock_down_only, ":agent", 0),
]),

Haven't tested this at all, but it should work given the order of trigger calls.
 
i think the (agent_set_no_death_knock_down_only) just sets damage received to 0 instead of changing death to knockdown. Or at least it seemed like that to me.

Managed to get it to work with agent_deliver_damage_to_agent and branching it out from ti_on_agent_hit. Seemed to work well enough with  quick test.  Not sure what can be used to make something run straight after finishing previous trigger.
 
Thanks, Somebody, that should work for the worst-case scenario of insta-kill ignoring the code.  I'd forgotten that you can cancel death that way  :lol:
 
OK, here's a build with various toys and additions, including Somebody's code.  Please note that you're going to get errors, if you just copy-pasta this into Native, because there are new Skills listed.  It's a guide, not a drag-and-drop, basically.

module_constants:
Code:
slot_agent_avoid      = 27

module_scripts:
Code:
("get_agent_max_hp",[
	(store_script_param_1, ":troop"),
	(store_skill_level, ":max_hp", skl_toughness, ":troop"),
	(store_attribute_level, ":attrib", ":troop", ca_strength),
	(val_mul, ":max_hp", 2),
	(val_add, ":max_hp", ":attrib"),
	(val_add, ":max_hp", 35),
	(assign, reg1, ":max_hp"),
]),

module_mission_templates:
Code:
common_damage_system_1 = (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"),
	(assign, ":dodged", 0),
	
	#EVERYBODY#
	#Critical hits for missiles
	(try_begin),
		(is_between, reg0, "itm_missile_weapons_start", "itm_missile_weapons_end"),#special def in Blood and Steel source
		(store_random_in_range, ":random_no", 1, 100),
		(try_begin),
			(le, ":random_no", 5),
			(val_max, ":damage", 20),
		(try_end),
	(else_try),
		#Random critical hits, 3% per point of Combat Training (formerly Tactics)
		(store_skill_level, ":combat_training",  "skl_combat_training", ":attacker_troop"),
		(val_mul, ":combat_training", 3),#3 percent chance per level, per hit
		(store_random_in_range, ":random", 1, 100),
		(try_begin),
			(le, ":random", ":combat_training"),		
			(neg|agent_is_ally,":agent"),#don't critically hit non-allies
			(val_max, ":damage", 7),
			(val_mul, ":damage", 3),
		(try_end),
	(try_end),	
	
	#Damage is increased by 2 points for every point of Heroism, 3 if heroes.  Army-based skill!
	(agent_get_party_id, ":attacker_party_id", ":attacker"),
	(party_get_skill_level, ":heroism",  ":attacker_party_id", "skl_heroism"),
	(try_begin),
		(gt, ":heroism", 0),
		(assign, reg1, ":heroism"),
		#(display_message, "@Heroism = {reg1}"),
		(try_begin),
			(troop_is_hero, ":attacker_troop"),
			(val_mul, ":heroism", 3),
			(val_add, ":damage", ":heroism"),
		(else_try),
			(val_mul, ":heroism", 2),
			(val_add, ":damage", ":heroism"),
		(try_end),
	(try_end),
	
	#Damage is decreased by 1 points for every point of Defensive Tactics, 2 if heroes.  Army-based skill!
	(agent_get_party_id, ":defender_party_id", ":agent"),
	(party_get_skill_level, ":defense",  ":defender_party_id", "skl_defensive_tactics"),
	(try_begin),
		(gt, ":defense", 0),
		(assign, reg1, ":defense"),
		#(display_message, "@Heroism = {reg1}"),
		(try_begin),
			(troop_is_hero, ":troop"),
			(val_mul, ":defense", 2),
			(val_sub, ":damage", ":defense"),
		(else_try),
			(val_mul, ":defense", 1),
			(val_sub, ":damage", ":defense"),
		(try_end),
	(try_end),	
	
	#HUMANS
	(try_begin),
		(agent_is_human, ":agent"),#branch if not human

		#DEFENSIVE SKILLS
		#Damage is lowered 5% per point of Toughness (formerly Ironflesh).
		(try_begin),	
			(store_skill_level, ":toughness",  "skl_toughness", ":troop"),
			(gt, ":toughness", 0),
			(val_mul, ":toughness", 5),
			(assign, ":mod_damage", ":damage"),		
			(val_mul, ":mod_damage", ":toughness"),
			(val_div, ":mod_damage", 100),#Rounded here, but whatever.
			(val_sub, ":damage", ":mod_damage"),
		(try_end),

		#Damage is avoided 5% per point of Reflexes(formerly Athletics)
		(try_begin),
			(store_skill_level, ":reflexes",  "skl_reflexes", ":troop"),
			(gt, ":reflexes", 0),	
			(val_mul, ":reflexes", 5),
			(store_random_in_range, ":random_no", 1, 100),
			(try_begin),
				(le, ":random_no", ":reflexes"),
				(assign, ":damage", 0),
				(try_begin),
					(eq, ":troop", "trp_player"),
					(display_message, "@You dodge the attack!"),
					(assign,":dodged",1),
				(else_try),
					(eq, ":attacker_troop", "trp_player"),
					(display_message, "@They dodge the attack!"),
					(assign,":dodged",1),
				(try_end),			
			(try_end),
		(try_end),		
	
	#HORSE DAMAGE
	(else_try),
		#Pike special rules
		(try_begin),
			(is_between, reg0, "itm_pikes_start", "itm_pikes_end"),
			(val_min, ":damage", 100),
		(try_end),
		
		#Horses randomly rear if they take damage
		(store_random_in_range, ":random_no", 1, 100),
		(try_begin),
			(gt, ":damage", 5),
			(le, ":random_no", 10),
			(agent_set_animation, ":agent","anim_horse_rear"),
		(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"),
	
	(try_begin),
		(eq, ":dodged", 1),
		(call_script, "script_get_agent_max_hp", ":troop"), #arbitrary script name - output=35+STR+2*Ironflesh
		(ge, ":damage", reg1), #arbitrary output register - damage will be overkill
		(store_agent_hit_points, ":hp", ":agent", 1), #store current hp
		(agent_set_slot, ":agent", slot_agent_avoid, ":hp"), #inside slot
		(agent_set_no_death_knock_down_only, ":agent", 1), #disable death
	(else_try),	
		(agent_set_hit_points,":agent",":hitpoints",1),
	(try_end),
])

common_damage_system_2 = (ti_on_agent_knocked_down, 0, 0,
[],[
	(store_trigger_param_1, ":agent"),
	(agent_get_slot, ":hp", ":agent", slot_agent_avoid),
	(ge, ":hp", 1), #this slot was marked
	(agent_set_slot, ":agent", slot_agent_avoid, 0),
	(agent_set_hit_points, ":agent", ":hp", 1), #restore hp
	(agent_set_no_death_knock_down_only, ":agent", 0),
])
 
Minor correction made to the above: dodging insta-kill only works if you've successfully dodged now.  Had guys getting up constantly after my super-duper character pwned them with single hits every time, lol.
 
Something I'm toying with is adding a requirement to the pike buff that it be used only after a stab, rather than just any time it is used to hit a horse. I'm not convinced that the AI stab/thrust with them enough to make it worthwhile, though...

It would only take these two lines:
(agent_get_action_dir, ":is_thrust", ":attacker"),
(eq, ":is_thrust", 0),

...I fear if I go down this road, then I'll need to code the whole spear-wall preparing for a charge bit, including agent_set_attack_action lines with them ready and holding thrusts until the enemy cavalry is within a certain range...

EDIT: Um. Unless I've lost my marbles, which is all together possible, doesn't the horse damage bit lower potential damage from a pike?
(val_min, ":damage", 100),
will pick whichever is smaller, ":damage" or 100, correct? It should be val_max...
 
Theoris said:
Hmm. I modified the code a bit.

Code:
theoris_decapitation = (
    ti_on_agent_hit, 0, 0, [],
    [
    	(store_trigger_param_1, ":agent"),
		(agent_is_human, ":agent"),
    	(store_trigger_param_3, ":damage"),
		(ge, ":damage", 30), #strong blow
		(store_agent_hit_points, ":hp", ":agent", 1),
		(val_sub, ":hp", 5),
		(ge, ":damage", ":hp"),
		(agent_get_position, pos1, ":agent"),
		(get_distance_between_positions, ":distance", pos1, pos0),
		(is_between, ":distance", 160, 176), # *zing*
		(agent_get_item_slot, ":item", ":agent", 4), #head slot
		(try_begin),
		    (ge, ":item", 1),
			(agent_unequip_item, ":agent", ":item"),
		(try_end),
		(agent_equip_item, ":agent", "itm_invisible_head"),
		(particle_system_burst, "psys_game_blood_2", pos1, 125), #Yeah..
		#(set_spawn_position, pos1),
		#(spawn_scene_prop, "spr_physics_head"),
	]),

I got this to work,
but I'm make it so a bloody head and helmet flies out also. (please forgive my grossness :razz:).

The problem is everyone has a different head and helmet, so one single flying "physics_head" wouldn't be optimum.

I thought of a workaround, where we assume the helmet leaves the head.
I would be easy to "spawn_item" ie the Helmet, and spawn a bloody head (so you can't see the details :razz:).

I was wonder for the head, which is a scene prop, is there any operations or methods to make gravity work on it like on agents? or do I have to code all the falling parts.

Secondly, it says, rotation gives the direction of the blow
From header_trigger:
Code:
ti_on_agent_hit          = -28.0 #can only be used in module_mission_templates triggers
# Trigger Param 1: damage inflicted agent_id
# Trigger Param 2: damage dealer agent_id
# Trigger Param 3: inflicted damage
# Register 0: damage dealer item_id
# Position Register 0: position of the blow
#                      rotation gives the direction of the blow
How does rotation work? Ie, how can I can I deduce from the rotate which direction to make the head and helmet fly?

Thanks!
 
To answer your physics question I thought
(prop_instance_enable_physics, <scene_prop_id>, <value>)
value = 0 (for disabled), 1 (for enabled)
worked to that effect...I might be wrong though as I don't really use scene props often...
 
The prop needs to have sofk_moveable and sokf_dynamic_physics flags, I think.

Then, add these values to prop_init trigger (from bugtracker)
Code:
("box_a_dynamic",sokf_moveable|sokf_dynamic_physics,"box_a","bo_box_a", [

(ti_on_init_scene_prop,
[
   (store_trigger_param_1, ":prop_instance_no"),
   (set_fixed_point_multiplier, 100),
   (position_set_x, pos0, 2500), #mass=25.0
   (position_set_y, pos0, 80), #friction coefficient = 0.8
   (position_set_z, pos0, 0), #reserved variable
   (prop_instance_dynamics_set_properties, ":prop_instance_no", pos0),
   (position_set_x, pos0, 0),
   (position_set_y, pos0, 0),
   (position_set_z, pos0, 10000),
   (prop_instance_dynamics_set_omega, ":prop_instance_no", pos0), #spin around fast
   (position_set_x, pos0, 0),
   (position_set_y, pos0, 0),
   (position_set_z, pos0, 10000),
   (prop_instance_dynamics_apply_impulse, ":prop_instance_no", pos0), # and jump 
]),
]),
 
Hmm... If I haven't mistaken, the physics engine doesn't work for multiplayer right?

Btw, shouldn't it be
(particle_system_burst, "psys_game_blood_2", pos0, 125),
instead of
(particle_system_burst, "psys_game_blood_2", pos1, 125), ?

pos0 is the position where hit, whereas pos1 is the position of agent.

 
SonKidd said:
Hmm... If I haven't mistaken, the physics engine doesn't work for multiplayer right?

Btw, shouldn't it be
(particle_system_burst, "psys_game_blood_2", pos0, 125),
instead of
(particle_system_burst, "psys_game_blood_2", pos1, 125), ?

pos0 is the position where hit, whereas pos1 is the position of agent.
Yep, physics don't work in multiplayer.
 
Back
Top Bottom