OSP Code Combat Hardcore fighting AI - Blocking, better positioning, feinting...etc

Users who are viewing this thread

Pumpkin Lord



Aye Forge,

I decided to release the codes of some of the features I once released in Vyrn OSP about a year ago or so.




Vyrn AI was a project that I worked on for a month or so. I needed to have an actual fighting AI that is smart and flexible. Dangerous, too. Hardcore stuff, player-like. Anyway, it works in certain levels that you set in game_start. You can set levels for any kind of troop you want. The lower the number, better it will fight. AI can:

  • Block
  • Feint
  • Position himself a lot better
  • Kick (needs work)
  • Chamber
  • Random hit
  • Counter-attack
  • Avoid/dodge (need the animation from Vyrn OSP)
  • Special strike (needs work)
  • Roll forward (needs animation from Vyrn OSP)
  • Jump charge (needs work & animation from Vyrn OSP)

It was an attempt on hardcore fantasy RPG. Feel free to use or edit any part you want as long as you give credits. You might need to clean it a bit from Vyrn-related stuff. Be aware of that.

Having said that, I am no coder in IRL and code could use improvements. It is a WIP. Do whatever you want with it.

Happy modding!




1 - ) Firstly, add these mission triggers to anywhere in mission_templates.py and then to any mission you want.

vyrn_ai_continue - > This trigger handles the special moves like jump charge and special strike. Both needs work, so you might not want to use them.
vyrn_ai - > This trigger is where everything is. How it works is that, it makes the necessary checks for an agent in suitable conditions, gets it vyrn_ai level and starts working each segment in combat in relation to the level of the troop's AI and a bit of random dices. It needs to work every milisecond or so, maybe a second would do. I guess that would also change the difficulty of the AI dramatically.



Code:
vyrn_ai_continue = (	
 1, 0, 0, [(eq, "$vyrn_AI_open", 1),],
  [
		#(store_mission_timer_c, ":timerc"),
		
		(get_player_agent_no, ":play"),
		(agent_is_active, ":play"),
		(agent_is_alive, ":play"),
	  #player setup
   (try_for_agents, ":agse"),
		(neq, ":agse", ":play"), #Agent is not player
		(agent_is_active, ":agse"),
		(agent_is_alive, ":agse"), 
		(agent_is_human, ":agse"),
		(agent_slot_eq, ":agse", slot_agent_is_running_away, 0), #isnt fleeing
		
		(agent_get_troop_id, ":agstrpe",":agse"),
		(troop_get_slot, ":is_AIe", ":agstrpe", slot_agent_has_vyrn_AI), #if agent has vyrn AI
		(eq, ":is_AIe", 1), #yes
		(troop_get_slot, ":chance_AIe", ":agstrpe", slot_vyrn_AI_chance),
	 
		(agent_get_team, ":ags_teame", ":agse"), 
	 
		#(assign, ":max_distance", 300), #distance between agents
		
		(agent_ai_get_look_target,":possiblee",":agse"),
		(gt,":possiblee",0), #there is at least someone
		
		(agent_is_active, ":possiblee"),
		(agent_is_alive, ":possiblee"),
		(agent_is_human, ":possiblee"),
		
		(agent_get_team, ":possible_teame", ":possiblee"),
		(neq, ":possible_teame", ":ags_teame"), #unfriendly teams
		
		(agent_get_position, pos13, ":possiblee"),
	    (agent_get_position, pos14, ":agse"),
		(neg|position_is_behind_position, pos13, pos14), #agents are not behind each other
		(get_distance_between_positions, ":diste", pos13, pos14),
		
	   # (agent_get_defend_action, ":pos_defe", ":possiblee"), #attack action
		#(agent_get_action_dir, ":pos_atkdire", ":possiblee"),
	   # (agent_get_attack_action, ":pos_atke", ":possiblee"), #attack action
		(agent_get_animation, ":agse_anime", ":agse", 1),
		(agent_get_wielded_item, ":l_wielded_itema", ":agse", 0),
		#(agent_get_wielded_item, ":r_wielded_itema", ":agse", 1),
		#(agent_get_animation, ":pos_anime", ":possiblee", 1),
		(store_random_in_range, ":chance_strengthe", 1, ":chance_AIe"), #chance is based on troop
		(eq, ":chance_strengthe", 1),
			#Jump Charge
			(try_begin),
				(is_between, ":diste", 600, 800),
				(neq, ":agse_anime", "anim_jump_charge"),
				(agent_set_animation, ":agse", "anim_jump_charge"),
				(le, ":diste", 600),
				(agent_set_attack_action, ":agse", 3, 0),
				(agent_set_position, ":agse", pos13),
			(try_end),
				# #Brutal Strike
			# (try_begin),
				# (store_random_in_range, ":dice", 1, 200),
				# (eq, ":dice", 1),
				# (le, ":diste", 200),
				# (agent_set_animation, ":agse", "anim_brutal_strike"),
				# (agent_get_bone_position, pos9, ":agse", hb_hand_r, 1),
				# (get_distance_between_positions, ":dist_brutal", pos9, pos13),
				# (le, ":dist_brutal", 200),
				# (store_random_in_range, ":brutal_damage", 35, 70),
				# (agent_deliver_damage_to_agent, ":agse", ":possiblee", ":brutal_damage", ":l_wielded_itema"),
				# (agent_set_animation, ":possiblee", "anim_vyrn_AI_fall", 1),							
			# (try_end),
	(try_end),
    ])

vyrn_ai = (
  0, 0, 0, [(eq, "$vyrn_AI_open", 1),], [
    
		(get_player_agent_no, ":pla"),
		(agent_is_active, ":pla"),
		(agent_is_alive, ":pla"),
	  #player setup
   (try_for_agents, ":ags"),
		(neq, ":ags", ":pla"), #Agent is not player
		(agent_is_active, ":ags"),
		(agent_is_alive, ":ags"), 
		(agent_is_human, ":ags"),
		(agent_slot_eq, ":ags", slot_agent_is_running_away, 0), #isnt fleeing
		
		(agent_get_troop_id, ":agstrp",":ags"),
		(troop_get_slot, ":is_AI", ":agstrp", slot_agent_has_vyrn_AI), #if agent has vyrn AI
		(eq, ":is_AI", 1), #yes
		(troop_get_slot, ":chance_AI", ":agstrp", slot_vyrn_AI_chance),
	 
		(agent_get_team, ":ags_team", ":ags"), 
	 
		#(assign, ":max_distance", 300), #distance between agents
		
		(agent_ai_get_look_target,":possible",":ags"),
		(gt,":possible",0), #there is at least someone
		
		(agent_is_active, ":possible"),
		(agent_is_alive, ":possible"),
		(agent_is_human, ":possible"),
		
		(agent_get_team, ":possible_team", ":possible"),
		(neq, ":possible_team", ":ags_team"), #unfriendly teams
		
		(agent_get_position, pos11, ":possible"),
	    (agent_get_position, pos12, ":ags"),
		(neg|position_is_behind_position, pos11, pos12), #agents are not behind each other
		(get_distance_between_positions, ":dist", pos11, pos12),
		
	    (agent_get_defend_action, ":pos_def", ":possible"), #attack action
		(agent_get_action_dir, ":pos_atkdir", ":possible"),
	    (agent_get_attack_action, ":pos_atk", ":possible"), #attack action
		(agent_get_animation, ":ags_anim", ":ags", 1),
		(agent_get_animation, ":pos_anim", ":possible", 1),
		(store_random_in_range, ":chance_strength", 1, ":chance_AI"), #chance is based on troop
		(eq, ":chance_strength", 1),
		#Footwork
		(try_begin),
			(try_begin),
				(le, ":dist", 500),
				(agent_force_rethink, ":ags"),
				(agent_set_scripted_destination, ":ags", pos11, 0, 1),
			(else_try),
				(is_between, ":dist", 0, 300),
				(agent_force_rethink, ":ags"),
				(store_random_in_range, ":dice_for_footwork", 0, 5),
				(eq, ":dice_for_footwork", 1),
				(store_random_in_range, ":random", -60, 60),
				(position_move_x, pos11, ":random", 0),
				(position_move_y, pos11, ":random", 0),
				(position_rotate_x, pos11, ":random", 0),
				(position_rotate_y, pos11, ":random", 0),
				(agent_set_scripted_destination, ":ags", pos11, 0, 1),
			(try_end),
		(try_end),
		#Chambering
			(try_begin),
				(le, ":dist", 200),
				(store_random_in_range, ":extra_dice", 1, 80),
				(neq, ":pos_atk", 1),
				(eq, ":pos_atk", 2),
				(eq, ":extra_dice", 1),
				(try_begin),					
					(eq, ":pos_atkdir", 0),
					(agent_set_attack_action, ":ags", 0, 0),
				(else_try),
					(eq, ":pos_atkdir", 1),
					(agent_set_attack_action,":ags", 2, 0),
				(else_try),
					(eq, ":pos_atkdir", 2),
					(agent_set_attack_action, ":ags", 1, 0),
				(else_try),
					(eq, ":pos_atkdir", 3),
					(agent_set_attack_action, ":ags", 3, 0),
			(try_end),
			(try_end),
			#Chamber disarming
			(try_begin),
				(eq, ":pos_def", 1),
				(neq, ":pos_def", 2),
				(eq, ":pos_atkdir", 1),
				(eq, ":pos_atkdir", 2),
				(neq, ":pos_atk", 1),
				(eq, ":pos_atk", 2),
				(agent_is_in_parried_animation, ":possible"),
				(agent_get_wielded_item, ":weapon", ":ags", 0),
				(agent_unequip_item, ":ags", ":weapon"),
				(agent_get_bone_position, pos2, ":ags", hb_hand_r, 1),
				(store_random_in_range, ":z_rotation", 0, 360),
				(store_random_in_range, ":y_rotation", -60, 60),
				(store_random_in_range, ":x_pos", -90, 90),
				(store_random_in_range, ":y_pos", -90, 90),
				(position_rotate_z, pos2,":z_rotation"),
				(position_rotate_y, pos2,":y_rotation"),
				(position_move_x, pos2, ":x_pos"),
				(position_move_y, pos2, ":y_pos"),
				(position_set_z_to_ground_level, pos2),
				(position_move_z, pos2, 5),
				(set_spawn_position, pos2),
				(spawn_item, ":weapon"),
			(try_end),
			#Feinting
			(try_begin),
					(store_random_in_range, ":dice", 1, 60),
					(store_random_in_range, ":style", 1, 5),
					(store_random_in_range, ":random_dir", 0, 3),
					(store_random_in_range, ":random_action", 0, 1),
					(le, ":dist", 200),
					(eq, ":dice", 1),
					(eq, ":pos_def", 2),
					(assign, ":continue", 0),
					(eq, ":continue", 0),
				(try_begin),
					(eq, ":style", 1),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 1),
				(else_try),
					(eq, ":style", 2),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 1),
				(else_try),
					(eq, ":style", 3),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 1),
				(else_try),
					(eq, ":style", 4),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 0),
					(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
					(assign, ":continue", 1),
				(try_end),
			(try_end),
			#Counter-attack
			(try_begin),
				(le, ":dist", 200),
				(this_or_next|eq, ":pos_atk", 6),
				(eq, ":pos_atk", 3),
				(store_random_in_range, ":random_dir", 1, 3),
				(store_random_in_range, ":random_action", 0, 1),
				(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
			(try_end),
			#Attacking
			(try_begin),
			(try_begin),
				(le, ":dist", 300),
				(store_random_in_range, ":random_dir", 0, 3),
				(store_random_in_range, ":random_action", 0, 1),
				(eq, ":pos_def", 2),
				(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
			(else_try),
				(le, ":dist", 200),
				(store_random_in_range, ":random_dir", 1, 3),
				(store_random_in_range, ":random_action", 0, 1),
				(eq, ":pos_def", 2),
				(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
			(try_end),
			(try_end),
			#Blocking
		(try_begin),
		(neq, ":pos_atk", 1), #readying attack
		(eq, ":pos_atk", 2), #releasing attack	
		(le, ":dist", 200),
		#(store_random_in_range, ":random_chance", 1, 150),
		(try_begin),
			(eq, ":pos_atkdir", 0),
			(agent_set_defend_action, ":ags", 0, 0),
		(else_try),
			(eq, ":pos_atkdir", 1),
			(agent_set_defend_action, ":ags", 1, 0),
		(else_try),
			(eq, ":pos_atkdir", 2),
			(agent_set_defend_action, ":ags", 2, 0),
		(else_try),
			(eq, ":pos_atkdir", 3),
			(agent_set_defend_action, ":ags", 3, 0),
		(try_end),
		(try_end),
		#Avoid
		(try_begin),
			(le, ":dist", 200),
		    (neq, ":pos_atk", 1), #readying attack
			(eq, ":pos_atk", 2), #releasing attack
			(this_or_next|eq, ":pos_atkdir", 0),
			(eq, ":pos_atkdir", 3),
			(store_random_in_range, ":dice_for_avoid", 0, 15),
			(store_random_in_range, ":chance", 0, 2),
			(eq, ":dice_for_avoid", 1),
				(try_begin),
					(eq, ":chance", 1),
					(agent_set_defend_action, ":ags", -2, 0),
					(agent_set_animation, ":ags", "anim_avoid_right_start"),
				(else_try),
					(eq, ":chance", 2),
					(agent_set_defend_action, ":ags", -2, 0),
					(agent_set_animation, ":ags", "anim_avoid_left_start"),
				(try_end),
		(try_end),
		#AI kick
		(try_begin),
			(neq, ":ags_anim", "anim_brutal_strike"),
			(le, ":dist", 100),
			(store_random_in_range,":kickchance", 1, 360),	
			(eq,":kickchance",1), #5-ish% chance per check
			(agent_set_animation, ":ags", "anim_vyrn_AI_kick"),
			(agent_get_bone_position, pos5, ":ags", hb_foot_r, 1),
			(get_distance_between_positions, ":dist_to_leg", pos5, pos11),
			(le, ":dist_to_leg", 150),
			(store_random_in_range, ":rndm_damage", 0, 5),# anim_prepare_kick_0 exists as well
			(agent_deliver_damage_to_agent, ":ags", ":possible", ":rndm_damage"),#3 damage done atm.
			(agent_set_animation, ":possible", "anim_strike3_abdomen_front"),#Get Kicked
			(eq, ":pos_anim", "anim_strike3_abdomen_front"),
			(store_random_in_range, ":random_dir", 0, 3),
			(store_random_in_range, ":random_action", 0, 1),
			(agent_set_attack_action, ":ags", ":random_dir", ":random_action"),
	   (try_end),
   (try_end),
    ])

2 - ) Secondly, add these constants to anywhere in module_constants.py.

Code:
slot_agent_has_vyrn_AI = 29
slot_vyrn_AI_chance = 30

3 - ) Set the level of the AI in the beginning of the game like this:  I used it in game_start

P.S - The name of the constant can be confusing. I do not know what I was thinking when I named a constant with 'agent' when I used it for a 'troop'. It is a constant that is used for a troop that is later on used in mission trigger to adjust the agents of that troop.

Enables the AI for specific troop.


Code:
  (try_begin),	  
	   (troop_set_slot, "trp_blue_raven", slot_agent_has_vyrn_AI, 1),
	   (troop_set_slot, "trp_kingdom_2_lord", slot_agent_has_vyrn_AI, 1),
	   (troop_set_slot, "trp_kingdom_1_lord", slot_agent_has_vyrn_AI, 1),
	   (troop_set_slot, "trp_urulvin", slot_agent_has_vyrn_AI, 1),
	   (troop_set_slot, "trp_monvil", slot_agent_has_vyrn_AI, 1),
	   (troop_set_slot, "trp_vildon", slot_agent_has_vyrn_AI, 1),
	   (troop_set_slot, "trp_urulvin_cinematic", slot_agent_has_vyrn_AI, 1),
	   (troop_set_slot, "trp_vand", slot_agent_has_vyrn_AI, 1),
	  (try_end),
 
Level of the AI is handled below. Smaller the number is, better it will fight. Below 3 is really really hard to beat, just to warn you. Around 3-5 is quite a fun and challenging AI. In video, it was 2.

Code:
#AI - smaller, better blocking	  
 (try_begin),	  
	(troop_set_slot, "trp_blue_raven", slot_vyrn_AI_chance, 2),
	  
	(troop_set_slot, "trp_urulvin", slot_vyrn_AI_chance, 1),
	(troop_set_slot, "trp_monvil", slot_vyrn_AI_chance, 2),

	(troop_set_slot, "trp_vand", slot_vyrn_AI_chance, 5),
	(troop_set_slot, "trp_vildon", slot_vyrn_AI_chance, 3),
		
	(troop_set_slot, "trp_azulan", slot_vyrn_AI_chance, 3),
	(troop_set_slot, "trp_toras", slot_vyrn_AI_chance, 4),
	   
	(troop_set_slot, "trp_kingdom_1_lord", slot_vyrn_AI_chance, 2),
	(troop_set_slot, "trp_kingdom_2_lord", slot_vyrn_AI_chance, 1),
 (try_end),

And, finally put this somewhere in game_start, too. It just enables the trigger. You can use it to disable the AI.

Code:
(assign, "$vyrn_AI_open", 1),

Cheers! :party:

Credits to Barabas & Zarthas for the inspirational codes.
 
Awesome. Thanks for sharing!

I've got ideas to put this into invasion mode, with low blocking scores for slightly more dangerous enemies. Fencer type enemies for example

I gotta check out the full osp, for sure :O
 
HarryPham123 said:
hi there i have a problem with the error

WARNING: Local variable never used: l_wielded_item, at: 0

how to fix this

This is just a warning. Feel free to ignore. Or uncomment it.
 
Thank you for sharing.

Is this designed for 1vs1's or will it also work in big battles? I'd like to try it out on a companion.
 
Razors said:
Thank you for sharing.

Is this designed for 1vs1's or will it also work in big battles? I'd like to try it out on a companion.

Works for both, but designed for duels.

If you want a battle AI - I advise you check out Oliveran's AI.
 
Efe Karacar said:
Razors said:
Thank you for sharing.

Is this designed for 1vs1's or will it also work in big battles? I'd like to try it out on a companion.

Works for both, but designed for duels.

If you want a battle AI - I advise you check out Oliveran's AI.

Alright, I'll try it out, again thanks!

Do you perhaps have a link? Tried searching but couldn't find it

EDIT: Never mind found it :smile:
 
Updated this for the "Battle for NA" mod. AI now fights like a proper competitive player, here is the source code. A lot of changes and improvements.

You can take a peek at the AI in this trailer here:


module_mission_templates.py
Code:
advanced_ai = (
0, 0, 0, [

(eq, "$advanced_ai_open", 1),
# (neg|main_hero_fallen),
(neg|all_enemies_defeated),

], [
 
    (get_player_agent_no, ":player"),
    (agent_is_active, ":player"),
    (agent_is_alive, ":player"),
 
    # (store_mission_timer_a, ":timer"),
    (store_mission_timer_b, ":timer_b"),
    # (store_mission_timer_c, ":timer_c"),
    # (store_mission_timer_a_msec, ":timer_mili"),
 
   (try_for_agents, ":agents"),
        # SOURCE CHECK
        (neq, ":agents", ":player"),    # Source Agent is not player
        (agent_is_active, ":agents"),   # Source Agent is present
        (agent_is_alive, ":agents"),    # Source Agent is alive
        (agent_is_human, ":agents"),    # Source Agent is not horse
        (agent_slot_eq, ":agents", slot_agent_is_running_away, 0), # Source Agent is not fleeing
    
        (agent_get_troop_id, ":troop_no", ":agents"),   # Get troop reference of the source agent
    
        (troop_get_slot, ":is_AI", ":troop_no", player_knows_how_to_play), # Source troop has AI
        (eq, ":is_AI", 1), # Source troop has AI
        (troop_get_slot, ":chance_AI", ":troop_no", player_skill_level), # # Source troop skill level
 
        (agent_get_team, ":agent_team", ":agents"),  # Get source team
        (team_get_movement_order, ":cur_team_order", ":agent_team"),
        (eq, ":cur_team_order", mordr_charge, grc_everyone),
    
        (agent_ai_get_look_target, ":target", ":agents"),   # Get the current enemy of the source agent
        (gt, ":target", 0),   # If there is a target
    
        # TARGET CHECK
        (agent_is_active, ":target"),
        (agent_is_alive, ":target"),
        (agent_is_human, ":target"),
    
        (agent_get_team, ":target_team", ":target"),
        (neq, ":target_team", ":agent_team"), #unfriendly teams
    
        # WEAPONS
        (try_begin),
            (agent_get_wielded_item, ":left_item_source", ":agents", 1),
            (gt, ":left_item_source", 0),
            # (item_get_type, ":left_item_type_source", ":left_item_source"),
        (try_end),
    
        (try_begin),
            (agent_get_wielded_item, ":right_item_source", ":agents", 0),
            (gt, ":right_item_source", 0),
            # (item_get_type, ":right_item_type_source", ":right_item_source"),
            # (item_get_weapon_length, ":weapon_length_right_source", ":right_item_source"),
        (try_end),
        # HORSE
        (agent_get_horse, ":horse", ":agents"),
        (eq, ":horse", -1), # no horse
    
        # (agent_get_animation, ":source_animation", ":agents"),
        (agent_get_animation, ":target_animation", ":target"),
    
        (agent_get_bone_position, pos55, ":agents", hb_foot_l, 1),
        (agent_get_bone_position, pos56, ":agents", hb_head, 1),
    
        # POSITION
        (agent_get_position, pos11, ":target"),
        (agent_get_position, pos12, ":agents"),
        (neg|position_is_behind_position, pos11, pos12), #agents are not behind each other
        (get_distance_between_positions, ":dist", pos11, pos12),
    
        # COMBAT INFO
        (agent_get_defend_action, ":pos_def", ":target"), #attack action
        (agent_get_action_dir, ":pos_atkdir", ":target"),
        (agent_get_attack_action, ":pos_atk", ":target"), #attack action
        # (agent_get_combat_state, ":pos_state", ":target"),
  
        # (agent_get_combat_state, ":source_state", ":agents"),
        # (agent_get_defend_action, ":source_defend_action", ":agents"), #defend action
        (agent_get_action_dir, ":source_attack_dir", ":agents"), # attack/block direction
        (agent_get_attack_action, ":source_attack_action", ":agents"), #attack action
    
        # (assign, reg5, ":source_attack_dir"),
        # (display_message, "@{reg5}"),
    
        (assign, ":continue", 0),
        (try_begin),
            (ge, ":chance_AI", 1),
            (assign, ":continue", 1),
        (else_try),
            (store_random_in_range, ":chance_strength", 0, ":chance_AI"), #chance is based on troop
            (eq, ":chance_strength", 0),
            (assign, ":continue", 1),
        (try_end),
        (eq, ":continue", 1),
    
        # switch between passive / agressive
        # (try_begin),
            # (eq, ":timer_b", 10),
            # (try_begin),
                # (agent_slot_eq, ":agents", play_passive, 0),
                # (agent_set_slot, ":agents", play_passive, 1),
                # (agent_ai_set_aggressiveness, ":agents", 30),
                # (display_message, "@I am passive now."),
            # (else_try),
                # (agent_slot_eq, ":agents", play_passive, 1),
                # (agent_set_slot, ":agents", play_passive, 0),
                # (agent_ai_set_aggressiveness, ":agents", 100),
                # (display_message, "@I am agressive now."),
            # (try_end),
            # (reset_mission_timer_b),
        # (try_end),
        
        # (store_random_in_range, ":decision", 1, 10),
    
        # (agent_set_slot, ":agents", run_block, 1),
        # (agent_set_slot, ":agents", run_feint, 1),
        # (agent_set_slot, ":agents", run_footwork, 1),
        # (agent_set_slot, ":agents", run_attack, 1),
        # (agent_set_slot, ":agents", run_counter_attack, 1),
        # (agent_set_slot, ":agents", run_chamber, 1),
    
        # (try_begin),
            # (troop_slot_ge, ":troop_no", this_guy_only_blocks, 1),
            # (agent_set_slot, ":agents", run_feint, -1),
            # (agent_set_slot, ":agents", run_footwork, -1),
            # (agent_set_slot, ":agents", run_attack, -1),
            # (agent_set_slot, ":agents", run_counter_attack, -1),
            # (agent_set_slot, ":agents", run_chamber, -1),
        # (try_end),
      
        # (try_begin),
            # (troop_slot_ge, ":troop_no", this_guy_only_s, 1),
            # (agent_set_slot, ":agents", run_feint, -1),
            # (agent_set_slot, ":agents", run_block, -1),
            # (agent_set_slot, ":agents", run_footwork, -1),
            # (agent_set_slot, ":agents", run_counter_attack, -1),
            # (agent_set_slot, ":agents", run_chamber, -1),
        # (try_end),
    

    
        # make ai block more when their hp is low
    
        # Chambering
        (try_begin),
            (store_random_in_range, ":dice_chamber", 0, 500),
            (eq, ":dice_chamber", 250),
            # (eq, ":source_attack_action", 0), # if free
            # (agent_slot_ge, ":agents", run_chamber, 1), # troop constraints
            (le, ":dist", 200), # IF close enough
            (eq, ":pos_atk", 2), # release attack
            # (eq, ":decision", 5), # decided to chamber
            (try_begin),               
                (eq, ":pos_atkdir", 0), # enemy is attackin down
                (agent_set_attack_action, ":agents", 0, 0), # attack down
            (else_try),
                (eq, ":pos_atkdir", 1), # enemy is attackin right
                (agent_set_attack_action,":agents", 2, 0),  # attack left
            (else_try),
                (eq, ":pos_atkdir", 2), # enemy is attackin left
                (agent_set_attack_action, ":agents", 1, 0), # attack right
            (else_try),
                (eq, ":pos_atkdir", 3), # enemy is attacking up
                (agent_set_attack_action, ":agents", 3, 0), # attack up
            (try_end),
        (try_end),
    
        # Release swing if he is readying
        (try_begin),
            (store_random_in_range, ":dice_to_release", 0, 5),
            (eq, ":dice_to_release", 3),
            (eq, ":source_attack_action", 1),
            (this_or_next|eq, ":pos_def", 1),
            (this_or_next|eq, ":pos_def", 2),
            (eq, ":pos_def", 0),
        
            (this_or_next|eq, ":pos_atk", 3),
            (this_or_next|eq, ":pos_atk", 4),
            (this_or_next|eq, ":pos_atk", 6),
            (this_or_next|eq, ":pos_atk", 7),
            (eq, ":pos_atk", 0),
            (agent_set_attack_action, ":agents", ":source_attack_dir", 0),
            # (display_message, "@Release"),
        (try_end),
    
    
    
    
        # Make holds
        (try_begin),
            (eq, ":timer_b", 15),
            (store_random_in_range, ":random_dir", 1, 3),
            (agent_set_attack_action, ":agents", ":random_dir", 1),
            (agent_set_slot, ":agents", agent_cur_action, action_hold),
        (try_end),
        
        (try_begin),
            (agent_slot_eq, ":agents", agent_cur_action, action_hold),
            (eq, ":timer_b", 16),
            (agent_set_attack_action, ":agents", ":source_attack_dir", 0),
            (agent_set_slot, ":agents", agent_cur_action, action_feint),
            (reset_mission_timer_b),
        (try_end),
    
    
        #Counter-attack
        (try_begin),
            # (agent_slot_ge, ":agents", run_counter_attack, 1),
            (le, ":dist", 200),
            (store_random_in_range, ":dice_counter", 0, 20),
            (eq, ":dice_counter", 15),
            (this_or_next|eq, ":pos_def", 1),
            (this_or_next|eq, ":pos_def", 2),
            (eq, ":pos_def", 0),
        
            (this_or_next|eq, ":pos_atk", 3),
            (this_or_next|eq, ":pos_atk", 4),
            (this_or_next|eq, ":pos_atk", 6),
            (this_or_next|eq, ":pos_atk", 7),
            (eq, ":pos_atk", 0),
            (store_random_in_range, ":random_dir", 1, 3),
            (store_random_in_range, ":random_action", 0, 1),
            (agent_set_attack_action, ":agents", ":random_dir", ":random_action"),
            # (display_message, "@Counter-attack"),
        (try_end),
    
        #Feinting
        (try_begin),
            # (ge, ":timer", 10), # ai starts feinting after 10 seconds into duel
        
            # (neg|agent_slot_eq, ":agents", agent_cur_action, action_hold),
            # (agent_slot_ge, ":agents", run_feint, 1),
                # dice
            # (is_between, ":decision", 6, 8),
            # if distance is close enough
            # (eq, ":pos_def", 2),
            (le, ":dist", 225),
        
            (this_or_next|eq, ":pos_def", 1),
            (this_or_next|eq, ":pos_def", 2),
            (eq, ":pos_def", 0),
        
            (this_or_next|eq, ":pos_atk", 3),
            (this_or_next|eq, ":pos_atk", 4),
            (this_or_next|eq, ":pos_atk", 6),
            (this_or_next|eq, ":pos_atk", 7),
            (eq, ":pos_atk", 0),
        
            # (display_message, "@Feinting."),
            (store_random_in_range, ":feint_times", 3, 12),
            (store_div, ":start_releasing", ":feint_times", 3),
            # Feint to different directions
            (try_for_range, ":feinting_amount", 0, ":feint_times"),
            
                # (eq, ":pos_atkdir", ":source_attack_dir"),
                (store_random_in_range, ":random_dir", 0, 4), # store direction
                (neq, ":random_dir", "$last_direction"), # if it is not equal to last direction
            
                # (assign, ":continue", 1),
                # (try_begin),
                    # (eq, ":random_dir", 0),
                    # (le, ":dist", 100),
                    # (assign, ":continue", 0),
                    # (agent_force_rethink, ":agents"),
                # (try_end),
                # (eq, ":continue", 1),
            
                # (agent_set_speed_modifier, ":agents", 50),
            
                # (neq, ":pos_atkdir", ":source_attack_dir"),
                (agent_force_rethink, ":agents"),
                (try_begin),
                    (ge, ":feinting_amount", ":start_releasing"),
                    (agent_set_attack_action, ":agents", ":random_dir", 0), # attack
                (else_try),
                    (agent_set_attack_action, ":agents", ":random_dir", 1),
                (try_end),
            
                (assign, "$last_direction", ":random_dir"), # store the last used direction
                # (assign, ":feint_times", -1),
                # (display_message, "@Feint"),
                (eq, ":feinting_amount", ":feint_times"),
                (assign, ":feinting_amount", -1),
            (try_end),
        (try_end),
    
    
        # Track how many feints player do in a second and if its above 3, %100 hit

    
        # Footwork
        (try_begin),
            # (agent_slot_ge, ":agents", run_footwork, 1),
            # When distance is too far, come closer to target
            (try_begin),
                # (try_begin),
                    # (troop_slot_ge, ":troop_no", this_guy_only_s, 1),
                    # (val_mul, pos11, -1),
                # (else_try),
                    (ge, ":dist", 225),
                # (try_end),
            
                (agent_force_rethink, ":agents"),
                (agent_set_scripted_destination, ":agents", pos11, 0, 1),
            # When close enough,
            (else_try),
                (store_random_in_range, ":right", -150, -450),
                (store_random_in_range, ":left", 150, 350),
                # (store_random_in_range, ":up", 25, 75),
                (store_random_in_range, ":forward", 50, 150),
                # (store_random_in_range, ":up_down", 150, -150),
                # (store_random_in_range, ":blocking", -500, 500),
                (agent_force_rethink, ":agents"),
                # (copy_position, pos13, pos12),
                # (store_random_in_range, ":dice_for_footwork", 0, 3),
                # (eq, ":dice_for_footwork", 2),
                (agent_clear_scripted_mode, ":agents"),
                # ATTACKING / BLOCKING
                (try_begin),
                    # # WITH SHIELD
                    # # ONLY BLOCK
                    # (gt, ":left_item_source", 0), # if he has item on left hand
                    # (eq, ":left_item_type_source", itp_type_shield), # if the item is shield
                    # (eq, ":source_animation", "anim_defend_shield"),
                    # # (eq, ":source_attack_action", 2), # guarding
                    # (position_move_x, pos12, ":shield"),
                    # (display_message, "@I have shield."),
                # (else_try),
                    # NO SHIELD
                    # BY SOURCE POS
                    # ATTACK
                    (try_begin),
                        (eq, ":source_attack_dir", 0), #down
                        (position_move_x, pos12, ":right"),
                    
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 6),
                            # (eq, ":dice_forward", 5),
                            (position_move_y, pos12, ":forward"),
                        # (try_end),
                    (else_try),
                        (eq, ":source_attack_dir", 1), #slashright
                        (position_move_x, pos12, ":right"),
                    
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 6),
                            # (eq, ":dice_forward", 5),
                            (position_move_y, pos12, ":forward"),
                        # (try_end),
                    (else_try),
                        (eq, ":source_attack_dir", 2), #slashleft
                        (position_move_x, pos12, ":left"),
                    
                         # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 6),
                            # (eq, ":dice_forward", 5),
                            (position_move_y, pos12, ":forward"),
                        # (try_end),
                    (else_try),
                        (eq, ":source_attack_dir", 3), #overswing
                        (position_move_x, pos12, ":left"),
                    
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 6),
                            # (eq, ":dice_forward", 5),
                            (position_move_y, pos12, ":forward"),
                        # (try_end),
                    (try_end),
                    # BY TARGET POS
                      # ATTACK
                    # (try_begin),
                        # (eq, ":source_attack_dir", 0), #down
                        # (position_move_x, pos11, ":right"),
                    
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 10),
                            # (eq, ":dice_forward", 5),
                            # (position_move_y, pos11, ":forward"),
                        # (try_end),
                    
                    # (else_try),
                        # (eq, ":source_attack_dir", 1), #slashright
                        # (position_move_x, pos11, ":right"),
                    
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 10),
                            # (eq, ":dice_forward", 5),
                            # (position_move_y, pos11, ":forward"),
                        # (try_end),
                        # (position_move_y, pos11, ":up_down"),
                    
                    # (else_try),
                        # (eq, ":source_attack_dir", 2), #slashleft
                        # (position_move_x, pos11, ":left"),
                    
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 10),
                            # (eq, ":dice_forward", 5),
                            # (position_move_y, pos11, ":forward"),
                        # (try_end),
                        # (position_move_y, pos11, ":up_down"),
                    
                    # (else_try),
                        # (eq, ":source_attack_dir", 3), #overswing
                        # (position_move_x, pos11, ":left"),
                    
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 10),
                            # (eq, ":dice_forward", 5),
                            # (position_move_y, pos11, ":forward"),
                        # (try_end),
                        # (position_move_y, pos11, ":forward"),
                    # (try_end),
                    # (display_message, "@I have no shield."),
                (try_end),
                # (try_begin),
                    # (troop_slot_ge, ":troop_no", this_guy_only_s, 1),
                    # (agent_set_scripted_destination, ":agents", pos13, 0, 1),
                # (else_try),
                    # (agent_set_speed_modifier, ":agents", 100),
                    # (agent_clear_scripted_mode, ":agents"),
                    (try_begin),
                        # (store_random_in_range, ":move_by_player", 0, 2),
                        # (try_begin),
                            # (eq, ":move_by_player", 0),
                            (agent_set_scripted_destination, ":agents", pos12, 0, 1),
                        # (else_try),
                            # (agent_set_scripted_destination, ":agents", pos11, 0, 1),
                        # (try_end),
                    (try_end),
            
            (try_end),
        (try_end),
    
        # Move agent back after completing a release
        # (try_begin),
            # (this_or_next|eq, ":source_attack_action", 6),
            # (eq, ":source_attack_action", 3),
            # (position_move_y, pos12, -600),
            # (agent_set_scripted_destination, ":agents", pos12, 0, 1),
        # (try_end),
        # make footwork inverse for allowed players
    
        # Target Switching
    
    
        # Make head of the source move up and down when is attacking
        # (try_begin),
        
            # (store_random_in_range, ":look", 0, 2),
            # (try_begin),
                # (eq, ":look", 0),
                # (agent_set_look_target_position, ":agents", pos55),
                # # (display_message, "@look at foot"),
            # (else_try),
                 # (agent_set_look_target_position, ":agents", pos56),
                 # # (display_message, "@look at head"),
             # (try_end),
        # (try_end),
    
        # Cavalry
        # Bump-lance
    
        # Archers
        # Leg shot
    
        # AI kick
        # (try_begin),
            # (neq, ":source_animation", "anim_prepare_kick_0"),
            # (store_random_in_range, ":dice_kick", 0, 100),
            # (eq, ":dice_kick", 50),
            # (le, ":dist", 80),
            # (eq, ":timer", 30),
            # (agent_set_attack_action, ":agents", -2, -2),
            # (agent_set_attack_action, ":target", -2, -2),
            # (agent_set_defend_action, ":agents", -2, -2),
            # (agent_set_defend_action, ":target", -2, -2),
            # (agent_set_animation, ":agents", "anim_prepare_kick_0"),
            # (agent_deliver_damage_to_agent, ":agents", ":target", 3),
            # (agent_set_animation, ":target", -1),
            # (agent_set_animation, ":target", "anim_strike3_abdomen_front"), # Get Kicked
            # (store_random_in_range, ":random_dir", 0, 3), # store direction
            # (agent_set_attack_action, ":agents", ":random_dir", 0), # attack
            # (display_message, "@Agent kicks."),
        # (try_end),
        # AI kicks over jumps
        (try_begin),
            (le, ":dist", 200),
            (eq, ":target_animation", "anim_prepare_kick_0"),
            (agent_set_attack_action, ":agents", -2, -2),
            (agent_set_attack_action, ":target", -2, -2),
            (agent_set_defend_action, ":agents", -2, -2),
            (agent_set_defend_action, ":target", -2, -2),
            (agent_set_animation, ":agents", "anim_jump"),
            (display_message, "@Agent avoids kicks."),
        (try_end),
    
    

    
        #Blocking
        (try_begin),
            # (agent_slot_ge, ":agents", run_block, 1),
            # (try_begin),
                # (troop_slot_ge, ":troop_no", this_guy_only_blocks, 1),
            # (else_try),
                # (this_or_next|eq, ":pos_atk", 3), # completing attack after hit
            # (assign, ":continue", 0),
            # (try_begin),
                # (agent_slot_eq, ":agents", play_passive, 1),
                # (assign, ":continue", 1),
            # (else_try),
                # (agent_slot_eq, ":agents", play_passive, 0),
                # (store_random_in_range, ":dice_block", 0, 15),
                # (try_begin),
                    # (eq, ":dice_block", 12),
                    (eq, ":pos_atk", 2), # releasing attack
                # (else_try),
                    # (eq, ":pos_atk", 2), # readying attack
                # (try_end),
                # (eq, ":pos_def", 0),
                # (assign, ":continue", 1),
            # (try_end),
            # (eq, ":continue", 1),
        
             (le, ":dist", 400), # close enough
                # (le, ":decision", 4), # decision made
            # (try_end),
            (agent_force_rethink, ":agents"),
            #(store_random_in_range, ":random_chance", 1, 150),
            (try_begin),
                (eq, ":pos_atkdir", 0),
                (agent_set_defend_action, ":agents", 0, 0),
            (else_try),
                (eq, ":pos_atkdir", 1),
                (agent_set_defend_action, ":agents", 1, 0),
            (else_try),
                (eq, ":pos_atkdir", 2),
                (agent_set_defend_action, ":agents", 2, 0),
            (else_try),
                (eq, ":pos_atkdir", 3),
                (agent_set_defend_action, ":agents", 3, 0),
            (try_end),
        (try_end),
    (try_end),
 
 
    ])


This is needed for this to work with orders.

Code:
ai_order = (
ti_on_order_issued, 0, 0, [],
[
    (store_trigger_param_1, ":order"),
  
    # Run AI only when order is charge
    (try_begin),
        (eq, ":order", mordr_charge),
        (assign, "$advanced_ai_open", 1),
        (display_message, "@On"),
    (else_try),
        (assign, "$advanced_ai_open", 0),
        (display_message, "@Off"),
    (try_end),
  
    # Restart the AI or default AI
    (try_for_agents, ":agents"), 
        (agent_is_human, ":agents"),
        (agent_is_alive, ":agents"),
        (agent_clear_scripted_mode, ":agents"),
        (agent_force_rethink, ":agents"),
    (try_end),

])

Hope you like it!
 
Last edited:
Updated this for the "Battle for NA" mod. AI now fights like a proper competitive player, here is the source code. A lot of changes and improvements.

You can take a peek at the AI in this trailer here:


module_mission_templates.py
Code:
advanced_ai = (
0, 0, 0, [

(eq, "$advanced_ai_open", 1),
# (neg|main_hero_fallen),
(neg|all_enemies_defeated),

], [
 
    (get_player_agent_no, ":player"),
    (agent_is_active, ":player"),
    (agent_is_alive, ":player"),
 
    # (store_mission_timer_a, ":timer"),
    (store_mission_timer_b, ":timer_b"),
    # (store_mission_timer_c, ":timer_c"),
    # (store_mission_timer_a_msec, ":timer_mili"),
 
   (try_for_agents, ":agents"),
        # SOURCE CHECK
        (neq, ":agents", ":player"),    # Source Agent is not player
        (agent_is_active, ":agents"),   # Source Agent is present
        (agent_is_alive, ":agents"),    # Source Agent is alive
        (agent_is_human, ":agents"),    # Source Agent is not horse
        (agent_slot_eq, ":agents", slot_agent_is_running_away, 0), # Source Agent is not fleeing
   
        (agent_get_troop_id, ":troop_no", ":agents"),   # Get troop reference of the source agent
   
        (troop_get_slot, ":is_AI", ":troop_no", player_knows_how_to_play), # Source troop has AI
        (eq, ":is_AI", 1), # Source troop has AI
        (troop_get_slot, ":chance_AI", ":troop_no", player_skill_level), # # Source troop skill level
 
        (agent_get_team, ":agent_team", ":agents"),  # Get source team
        (team_get_movement_order, ":cur_team_order", ":agent_team"),
        (eq, ":cur_team_order", mordr_charge, grc_everyone),
   
        (agent_ai_get_look_target, ":target", ":agents"),   # Get the current enemy of the source agent
        (gt, ":target", 0),   # If there is a target
   
        # TARGET CHECK
        (agent_is_active, ":target"),
        (agent_is_alive, ":target"),
        (agent_is_human, ":target"),
   
        (agent_get_team, ":target_team", ":target"),
        (neq, ":target_team", ":agent_team"), #unfriendly teams
   
        # WEAPONS
        (try_begin),
            (agent_get_wielded_item, ":left_item_source", ":agents", 1),
            (gt, ":left_item_source", 0),
            # (item_get_type, ":left_item_type_source", ":left_item_source"),
        (try_end),
   
        (try_begin),
            (agent_get_wielded_item, ":right_item_source", ":agents", 0),
            (gt, ":right_item_source", 0),
            # (item_get_type, ":right_item_type_source", ":right_item_source"),
            # (item_get_weapon_length, ":weapon_length_right_source", ":right_item_source"),
        (try_end),
        # HORSE
        (agent_get_horse, ":horse", ":agents"),
        (eq, ":horse", -1), # no horse
   
        # (agent_get_animation, ":source_animation", ":agents"),
        (agent_get_animation, ":target_animation", ":target"),
   
        (agent_get_bone_position, pos55, ":agents", hb_foot_l, 1),
        (agent_get_bone_position, pos56, ":agents", hb_head, 1),
   
        # POSITION
        (agent_get_position, pos11, ":target"),
        (agent_get_position, pos12, ":agents"),
        (neg|position_is_behind_position, pos11, pos12), #agents are not behind each other
        (get_distance_between_positions, ":dist", pos11, pos12),
   
        # COMBAT INFO
        (agent_get_defend_action, ":pos_def", ":target"), #attack action
        (agent_get_action_dir, ":pos_atkdir", ":target"),
        (agent_get_attack_action, ":pos_atk", ":target"), #attack action
        # (agent_get_combat_state, ":pos_state", ":target"),
 
        # (agent_get_combat_state, ":source_state", ":agents"),
        # (agent_get_defend_action, ":source_defend_action", ":agents"), #defend action
        (agent_get_action_dir, ":source_attack_dir", ":agents"), # attack/block direction
        (agent_get_attack_action, ":source_attack_action", ":agents"), #attack action
   
        # (assign, reg5, ":source_attack_dir"),
        # (display_message, "@{reg5}"),
   
        (assign, ":continue", 0),
        (try_begin),
            (ge, ":chance_AI", 1),
            (assign, ":continue", 1),
        (else_try),
            (store_random_in_range, ":chance_strength", 0, ":chance_AI"), #chance is based on troop
            (eq, ":chance_strength", 0),
            (assign, ":continue", 1),
        (try_end),
        (eq, ":continue", 1),
   
        # switch between passive / agressive
        # (try_begin),
            # (eq, ":timer_b", 10),
            # (try_begin),
                # (agent_slot_eq, ":agents", play_passive, 0),
                # (agent_set_slot, ":agents", play_passive, 1),
                # (agent_ai_set_aggressiveness, ":agents", 30),
                # (display_message, "@I am passive now."),
            # (else_try),
                # (agent_slot_eq, ":agents", play_passive, 1),
                # (agent_set_slot, ":agents", play_passive, 0),
                # (agent_ai_set_aggressiveness, ":agents", 100),
                # (display_message, "@I am agressive now."),
            # (try_end),
            # (reset_mission_timer_b),
        # (try_end),
       
        # (store_random_in_range, ":decision", 1, 10),
   
        # (agent_set_slot, ":agents", run_block, 1),
        # (agent_set_slot, ":agents", run_feint, 1),
        # (agent_set_slot, ":agents", run_footwork, 1),
        # (agent_set_slot, ":agents", run_attack, 1),
        # (agent_set_slot, ":agents", run_counter_attack, 1),
        # (agent_set_slot, ":agents", run_chamber, 1),
   
        # (try_begin),
            # (troop_slot_ge, ":troop_no", this_guy_only_blocks, 1),
            # (agent_set_slot, ":agents", run_feint, -1),
            # (agent_set_slot, ":agents", run_footwork, -1),
            # (agent_set_slot, ":agents", run_attack, -1),
            # (agent_set_slot, ":agents", run_counter_attack, -1),
            # (agent_set_slot, ":agents", run_chamber, -1),
        # (try_end),
     
        # (try_begin),
            # (troop_slot_ge, ":troop_no", this_guy_only_s, 1),
            # (agent_set_slot, ":agents", run_feint, -1),
            # (agent_set_slot, ":agents", run_block, -1),
            # (agent_set_slot, ":agents", run_footwork, -1),
            # (agent_set_slot, ":agents", run_counter_attack, -1),
            # (agent_set_slot, ":agents", run_chamber, -1),
        # (try_end),
   

   
        # make ai block more when their hp is low
   
        # Chambering
        (try_begin),
            (store_random_in_range, ":dice_chamber", 0, 500),
            (eq, ":dice_chamber", 250),
            # (eq, ":source_attack_action", 0), # if free
            # (agent_slot_ge, ":agents", run_chamber, 1), # troop constraints
            (le, ":dist", 200), # IF close enough
            (eq, ":pos_atk", 2), # release attack
            # (eq, ":decision", 5), # decided to chamber
            (try_begin),              
                (eq, ":pos_atkdir", 0), # enemy is attackin down
                (agent_set_attack_action, ":agents", 0, 0), # attack down
            (else_try),
                (eq, ":pos_atkdir", 1), # enemy is attackin right
                (agent_set_attack_action,":agents", 2, 0),  # attack left
            (else_try),
                (eq, ":pos_atkdir", 2), # enemy is attackin left
                (agent_set_attack_action, ":agents", 1, 0), # attack right
            (else_try),
                (eq, ":pos_atkdir", 3), # enemy is attacking up
                (agent_set_attack_action, ":agents", 3, 0), # attack up
            (try_end),
        (try_end),
   
        # Release swing if he is readying
        (try_begin),
            (store_random_in_range, ":dice_to_release", 0, 5),
            (eq, ":dice_to_release", 3),
            (eq, ":source_attack_action", 1),
            (this_or_next|eq, ":pos_def", 1),
            (this_or_next|eq, ":pos_def", 2),
            (eq, ":pos_def", 0),
       
            (this_or_next|eq, ":pos_atk", 3),
            (this_or_next|eq, ":pos_atk", 4),
            (this_or_next|eq, ":pos_atk", 6),
            (this_or_next|eq, ":pos_atk", 7),
            (eq, ":pos_atk", 0),
            (agent_set_attack_action, ":agents", ":source_attack_dir", 0),
            # (display_message, "@Release"),
        (try_end),
   
   
   
   
        # Make holds
        (try_begin),
            (eq, ":timer_b", 15),
            (store_random_in_range, ":random_dir", 1, 3),
            (agent_set_attack_action, ":agents", ":random_dir", 1),
            (agent_set_slot, ":agents", agent_cur_action, action_hold),
        (try_end),
       
        (try_begin),
            (agent_slot_eq, ":agents", agent_cur_action, action_hold),
            (eq, ":timer_b", 16),
            (agent_set_attack_action, ":agents", ":source_attack_dir", 0),
            (agent_set_slot, ":agents", agent_cur_action, action_feint),
            (reset_mission_timer_b),
        (try_end),
   
   
        #Counter-attack
        (try_begin),
            # (agent_slot_ge, ":agents", run_counter_attack, 1),
            (le, ":dist", 200),
            (store_random_in_range, ":dice_counter", 0, 20),
            (eq, ":dice_counter", 15),
            (this_or_next|eq, ":pos_def", 1),
            (this_or_next|eq, ":pos_def", 2),
            (eq, ":pos_def", 0),
       
            (this_or_next|eq, ":pos_atk", 3),
            (this_or_next|eq, ":pos_atk", 4),
            (this_or_next|eq, ":pos_atk", 6),
            (this_or_next|eq, ":pos_atk", 7),
            (eq, ":pos_atk", 0),
            (store_random_in_range, ":random_dir", 1, 3),
            (store_random_in_range, ":random_action", 0, 1),
            (agent_set_attack_action, ":agents", ":random_dir", ":random_action"),
            # (display_message, "@Counter-attack"),
        (try_end),
   
        #Feinting
        (try_begin),
            # (ge, ":timer", 10), # ai starts feinting after 10 seconds into duel
       
            # (neg|agent_slot_eq, ":agents", agent_cur_action, action_hold),
            # (agent_slot_ge, ":agents", run_feint, 1),
                # dice
            # (is_between, ":decision", 6, 8),
            # if distance is close enough
            # (eq, ":pos_def", 2),
            (le, ":dist", 225),
       
            (this_or_next|eq, ":pos_def", 1),
            (this_or_next|eq, ":pos_def", 2),
            (eq, ":pos_def", 0),
       
            (this_or_next|eq, ":pos_atk", 3),
            (this_or_next|eq, ":pos_atk", 4),
            (this_or_next|eq, ":pos_atk", 6),
            (this_or_next|eq, ":pos_atk", 7),
            (eq, ":pos_atk", 0),
       
            # (display_message, "@Feinting."),
            (store_random_in_range, ":feint_times", 3, 12),
            (store_div, ":start_releasing", ":feint_times", 3),
            # Feint to different directions
            (try_for_range, ":feinting_amount", 0, ":feint_times"),
           
                # (eq, ":pos_atkdir", ":source_attack_dir"),
                (store_random_in_range, ":random_dir", 0, 4), # store direction
                (neq, ":random_dir", "$last_direction"), # if it is not equal to last direction
           
                # (assign, ":continue", 1),
                # (try_begin),
                    # (eq, ":random_dir", 0),
                    # (le, ":dist", 100),
                    # (assign, ":continue", 0),
                    # (agent_force_rethink, ":agents"),
                # (try_end),
                # (eq, ":continue", 1),
           
                # (agent_set_speed_modifier, ":agents", 50),
           
                # (neq, ":pos_atkdir", ":source_attack_dir"),
                (agent_force_rethink, ":agents"),
                (try_begin),
                    (ge, ":feinting_amount", ":start_releasing"),
                    (agent_set_attack_action, ":agents", ":random_dir", 0), # attack
                (else_try),
                    (agent_set_attack_action, ":agents", ":random_dir", 1),
                (try_end),
           
                (assign, "$last_direction", ":random_dir"), # store the last used direction
                # (assign, ":feint_times", -1),
                # (display_message, "@Feint"),
                (eq, ":feinting_amount", ":feint_times"),
                (assign, ":feinting_amount", -1),
            (try_end),
        (try_end),
   
   
        # Track how many feints player do in a second and if its above 3, %100 hit

   
        # Footwork
        (try_begin),
            # (agent_slot_ge, ":agents", run_footwork, 1),
            # When distance is too far, come closer to target
            (try_begin),
                # (try_begin),
                    # (troop_slot_ge, ":troop_no", this_guy_only_s, 1),
                    # (val_mul, pos11, -1),
                # (else_try),
                    (ge, ":dist", 225),
                # (try_end),
           
                (agent_force_rethink, ":agents"),
                (agent_set_scripted_destination, ":agents", pos11, 0, 1),
            # When close enough,
            (else_try),
                (store_random_in_range, ":right", -150, -450),
                (store_random_in_range, ":left", 150, 350),
                # (store_random_in_range, ":up", 25, 75),
                (store_random_in_range, ":forward", 50, 150),
                # (store_random_in_range, ":up_down", 150, -150),
                # (store_random_in_range, ":blocking", -500, 500),
                (agent_force_rethink, ":agents"),
                # (copy_position, pos13, pos12),
                # (store_random_in_range, ":dice_for_footwork", 0, 3),
                # (eq, ":dice_for_footwork", 2),
                (agent_clear_scripted_mode, ":agents"),
                # ATTACKING / BLOCKING
                (try_begin),
                    # # WITH SHIELD
                    # # ONLY BLOCK
                    # (gt, ":left_item_source", 0), # if he has item on left hand
                    # (eq, ":left_item_type_source", itp_type_shield), # if the item is shield
                    # (eq, ":source_animation", "anim_defend_shield"),
                    # # (eq, ":source_attack_action", 2), # guarding
                    # (position_move_x, pos12, ":shield"),
                    # (display_message, "@I have shield."),
                # (else_try),
                    # NO SHIELD
                    # BY SOURCE POS
                    # ATTACK
                    (try_begin),
                        (eq, ":source_attack_dir", 0), #down
                        (position_move_x, pos12, ":right"),
                   
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 6),
                            # (eq, ":dice_forward", 5),
                            (position_move_y, pos12, ":forward"),
                        # (try_end),
                    (else_try),
                        (eq, ":source_attack_dir", 1), #slashright
                        (position_move_x, pos12, ":right"),
                   
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 6),
                            # (eq, ":dice_forward", 5),
                            (position_move_y, pos12, ":forward"),
                        # (try_end),
                    (else_try),
                        (eq, ":source_attack_dir", 2), #slashleft
                        (position_move_x, pos12, ":left"),
                   
                         # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 6),
                            # (eq, ":dice_forward", 5),
                            (position_move_y, pos12, ":forward"),
                        # (try_end),
                    (else_try),
                        (eq, ":source_attack_dir", 3), #overswing
                        (position_move_x, pos12, ":left"),
                   
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 6),
                            # (eq, ":dice_forward", 5),
                            (position_move_y, pos12, ":forward"),
                        # (try_end),
                    (try_end),
                    # BY TARGET POS
                      # ATTACK
                    # (try_begin),
                        # (eq, ":source_attack_dir", 0), #down
                        # (position_move_x, pos11, ":right"),
                   
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 10),
                            # (eq, ":dice_forward", 5),
                            # (position_move_y, pos11, ":forward"),
                        # (try_end),
                   
                    # (else_try),
                        # (eq, ":source_attack_dir", 1), #slashright
                        # (position_move_x, pos11, ":right"),
                   
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 10),
                            # (eq, ":dice_forward", 5),
                            # (position_move_y, pos11, ":forward"),
                        # (try_end),
                        # (position_move_y, pos11, ":up_down"),
                   
                    # (else_try),
                        # (eq, ":source_attack_dir", 2), #slashleft
                        # (position_move_x, pos11, ":left"),
                   
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 10),
                            # (eq, ":dice_forward", 5),
                            # (position_move_y, pos11, ":forward"),
                        # (try_end),
                        # (position_move_y, pos11, ":up_down"),
                   
                    # (else_try),
                        # (eq, ":source_attack_dir", 3), #overswing
                        # (position_move_x, pos11, ":left"),
                   
                        # (try_begin),
                            # (store_random_in_range, ":dice_forward", 0, 10),
                            # (eq, ":dice_forward", 5),
                            # (position_move_y, pos11, ":forward"),
                        # (try_end),
                        # (position_move_y, pos11, ":forward"),
                    # (try_end),
                    # (display_message, "@I have no shield."),
                (try_end),
                # (try_begin),
                    # (troop_slot_ge, ":troop_no", this_guy_only_s, 1),
                    # (agent_set_scripted_destination, ":agents", pos13, 0, 1),
                # (else_try),
                    # (agent_set_speed_modifier, ":agents", 100),
                    # (agent_clear_scripted_mode, ":agents"),
                    (try_begin),
                        # (store_random_in_range, ":move_by_player", 0, 2),
                        # (try_begin),
                            # (eq, ":move_by_player", 0),
                            (agent_set_scripted_destination, ":agents", pos12, 0, 1),
                        # (else_try),
                            # (agent_set_scripted_destination, ":agents", pos11, 0, 1),
                        # (try_end),
                    (try_end),
           
            (try_end),
        (try_end),
   
        # Move agent back after completing a release
        # (try_begin),
            # (this_or_next|eq, ":source_attack_action", 6),
            # (eq, ":source_attack_action", 3),
            # (position_move_y, pos12, -600),
            # (agent_set_scripted_destination, ":agents", pos12, 0, 1),
        # (try_end),
        # make footwork inverse for allowed players
   
        # Target Switching
   
   
        # Make head of the source move up and down when is attacking
        # (try_begin),
       
            # (store_random_in_range, ":look", 0, 2),
            # (try_begin),
                # (eq, ":look", 0),
                # (agent_set_look_target_position, ":agents", pos55),
                # # (display_message, "@look at foot"),
            # (else_try),
                 # (agent_set_look_target_position, ":agents", pos56),
                 # # (display_message, "@look at head"),
             # (try_end),
        # (try_end),
   
        # Cavalry
        # Bump-lance
   
        # Archers
        # Leg shot
   
        # AI kick
        # (try_begin),
            # (neq, ":source_animation", "anim_prepare_kick_0"),
            # (store_random_in_range, ":dice_kick", 0, 100),
            # (eq, ":dice_kick", 50),
            # (le, ":dist", 80),
            # (eq, ":timer", 30),
            # (agent_set_attack_action, ":agents", -2, -2),
            # (agent_set_attack_action, ":target", -2, -2),
            # (agent_set_defend_action, ":agents", -2, -2),
            # (agent_set_defend_action, ":target", -2, -2),
            # (agent_set_animation, ":agents", "anim_prepare_kick_0"),
            # (agent_deliver_damage_to_agent, ":agents", ":target", 3),
            # (agent_set_animation, ":target", -1),
            # (agent_set_animation, ":target", "anim_strike3_abdomen_front"), # Get Kicked
            # (store_random_in_range, ":random_dir", 0, 3), # store direction
            # (agent_set_attack_action, ":agents", ":random_dir", 0), # attack
            # (display_message, "@Agent kicks."),
        # (try_end),
        # AI kicks over jumps
        (try_begin),
            (le, ":dist", 200),
            (eq, ":target_animation", "anim_prepare_kick_0"),
            (agent_set_attack_action, ":agents", -2, -2),
            (agent_set_attack_action, ":target", -2, -2),
            (agent_set_defend_action, ":agents", -2, -2),
            (agent_set_defend_action, ":target", -2, -2),
            (agent_set_animation, ":agents", "anim_jump"),
            (display_message, "@Agent avoids kicks."),
        (try_end),
   
   

   
        #Blocking
        (try_begin),
            # (agent_slot_ge, ":agents", run_block, 1),
            # (try_begin),
                # (troop_slot_ge, ":troop_no", this_guy_only_blocks, 1),
            # (else_try),
                # (this_or_next|eq, ":pos_atk", 3), # completing attack after hit
            # (assign, ":continue", 0),
            # (try_begin),
                # (agent_slot_eq, ":agents", play_passive, 1),
                # (assign, ":continue", 1),
            # (else_try),
                # (agent_slot_eq, ":agents", play_passive, 0),
                # (store_random_in_range, ":dice_block", 0, 15),
                # (try_begin),
                    # (eq, ":dice_block", 12),
                    (eq, ":pos_atk", 2), # releasing attack
                # (else_try),
                    # (eq, ":pos_atk", 2), # readying attack
                # (try_end),
                # (eq, ":pos_def", 0),
                # (assign, ":continue", 1),
            # (try_end),
            # (eq, ":continue", 1),
       
             (le, ":dist", 400), # close enough
                # (le, ":decision", 4), # decision made
            # (try_end),
            (agent_force_rethink, ":agents"),
            #(store_random_in_range, ":random_chance", 1, 150),
            (try_begin),
                (eq, ":pos_atkdir", 0),
                (agent_set_defend_action, ":agents", 0, 0),
            (else_try),
                (eq, ":pos_atkdir", 1),
                (agent_set_defend_action, ":agents", 1, 0),
            (else_try),
                (eq, ":pos_atkdir", 2),
                (agent_set_defend_action, ":agents", 2, 0),
            (else_try),
                (eq, ":pos_atkdir", 3),
                (agent_set_defend_action, ":agents", 3, 0),
            (try_end),
        (try_end),
    (try_end),
 
 
    ])


This is needed for this to work with orders.

Code:
ai_order = (
ti_on_order_issued, 0, 0, [],
[
    (store_trigger_param_1, ":order"),
 
    # Run AI only when order is charge
    (try_begin),
        (eq, ":order", mordr_charge),
        (assign, "$advanced_ai_open", 1),
        (display_message, "@On"),
    (else_try),
        (assign, "$advanced_ai_open", 0),
        (display_message, "@Off"),
    (try_end),
 
    # Restart the AI or default AI
    (try_for_agents, ":agents"),
        (agent_is_human, ":agents"),
        (agent_is_alive, ":agents"),
        (agent_clear_scripted_mode, ":agents"),
        (agent_force_rethink, ":agents"),
    (try_end),

])

Hope you like it!

Thanks for this. Awesome
 
Back
Top Bottom