ardaarsen01
Sergeant
Hiya crowd ,
Today i will share my problem and reasonable codes about adding a "Parrying bot" to multiplayer servers .
Once I used to train myself with Champion bot which is located at Nditions duel server . Then i got bored of its poor algorithm . But i deduced that it was the fastest way of getting warmed (up to a point of course ) . I said , this champion bred might have great use for recruiting if i had it . So i became half modder ( i mean im pretty beginner at this ) .This is realy weird . None of users have opened a topic that handles Aİ ( except improved commander codes ) .
Now , let me share my knowledge ,
Champion bot and the others are taken from tutorial . At first i tried basic spawn_agent and set_visitor functions but they didnt work . By the way you can have a champion bot in your tutorial mode by disabling the function that can be found in Module_mission_templates.py (Line:5650)
Here ,
# (agent_set_scripted_destination_no_attack, ":trainer_agent", pos1), #This is the function that makes training bot pure blocker while you are interacting with it . İf you disable this , bot will both attack and block
Here is algorithm of tutorial bots .
(0, 0, 0,
[
(get_player_agent_no, ":player_agent"),
(neq, "$g_tutorial_training_ground_melee_trainer_attack", -1),
(mission_disable_talk),
(try_for_agents, ":cur_agent"),
(agent_get_troop_id, ":cur_agent_troop", ":cur_agent"),
(eq, ":cur_agent_troop", "$g_tutorial_training_ground_melee_trainer_attack"),
(assign, ":trainer_agent", ":cur_agent"),
(try_end),
(try_begin),
(eq, "$g_tutorial_training_ground_melee_state", 0),
(try_begin),
(try_for_agents, ":cur_agent"), #Visitor bots have training functions now
(agent_get_troop_id, ":cur_agent_troop", ":cur_agent"),
(this_or_next|eq, ":cur_agent_troop", "trp_tutorial_fighter_1"),
(this_or_next|eq, ":cur_agent_troop", "trp_tutorial_fighter_2"),
(this_or_next|eq, ":cur_agent_troop", "trp_tutorial_fighter_3"),
(eq, ":cur_agent_troop", "trp_tutorial_fighter_4"),
(agent_set_team, ":cur_agent", 7),
(agent_get_slot, ":spawn_point", ":cur_agent", slot_agent_spawn_entry_point),
(entry_point_get_position, pos1, ":spawn_point"),
(agent_set_scripted_destination, ":cur_agent", pos1),
(agent_force_rethink, ":cur_agent"), # bot reacts and starts to attack
(try_end),
(agent_set_wielded_item, ":trainer_agent", "itm_practice_sword"), #TODO: change this ( Bot wields wooden thingie)
(store_random_in_range, "$g_tutorial_training_ground_melee_state", 1, 5),
#random attack direction(this causes random swings , left/right/overhead/stab)
(assign, "$g_tutorial_update_mouse_presentation", 1),
(assign, "$g_tutorial_training_ground_next_score_time", 0),
(try_end),
(else_try),
(gt, "$g_tutorial_training_ground_melee_state", 0),
(try_begin),
(agent_set_team, ":player_agent", 1),
(agent_set_team, ":trainer_agent", 2),
(agent_get_position, pos1, ":player_agent"),
(agent_set_scripted_destination_no_attack, ":trainer_agent", pos1), # bot always goes to its initial spawnpoint after each duel. İf you hit bot , it wont care untill it gets its spawn .
(agent_get_attack_action, ":attack_action", ":player_agent"),
(try_begin),
(eq, ":attack_action", 2), # attack action equals to 2 if user releases its sword , i mean bot is seeking for your swing released in order to block .
(agent_get_action_dir, ":action_dir_attacker", ":player_agent"), # bot is supposed to block our swings
(try_begin), #Here is blocking code which is very simple .
(eq, ":action_dir_attacker", 0), #down
(agent_set_defend_action, ":trainer_agent", 0, 1),
(else_try),
(eq, ":action_dir_attacker", 3), #up
(agent_set_defend_action, ":trainer_agent", 3, 1),
(else_try),
(eq, ":action_dir_attacker", 1), #right
(agent_set_defend_action, ":trainer_agent", 2, 1),
(else_try),
(eq, ":action_dir_attacker", 2), #left
(agent_set_defend_action, ":trainer_agent", 1, 1),
(try_end),
(try_end),
(try_begin),
(ge, "$g_tutorial_training_ground_current_score", 5),
(tutorial_message, -1),
(assign, "$g_tutorial_training_ground_melee_state", 0),
(agent_set_team, ":player_agent", 0),
(agent_set_team, ":trainer_agent", 7),
(agent_set_hit_points, ":player_agent", 100, 0), #Healing both side after challenge .
(agent_set_hit_points, ":trainer_agent", 100, 0),
## (assign, "$g_tutorial_training_ground_melee_trainer_attack_completed", 1), #not used
(assign, "$g_tutorial_training_ground_conversation_state", 9), #attack complete
(start_mission_conversation, "$g_tutorial_training_ground_melee_trainer_attack"),
(assign, "$g_tutorial_training_ground_melee_trainer_attack", -1),
(try_end),
(try_end),
(try_end),
[
(get_player_agent_no, ":player_agent"),
(neq, "$g_tutorial_training_ground_melee_trainer_attack", -1),
(mission_disable_talk),
(try_for_agents, ":cur_agent"),
(agent_get_troop_id, ":cur_agent_troop", ":cur_agent"),
(eq, ":cur_agent_troop", "$g_tutorial_training_ground_melee_trainer_attack"),
(assign, ":trainer_agent", ":cur_agent"),
(try_end),
(try_begin),
(eq, "$g_tutorial_training_ground_melee_state", 0),
(try_begin),
(try_for_agents, ":cur_agent"), #Visitor bots have training functions now
(agent_get_troop_id, ":cur_agent_troop", ":cur_agent"),
(this_or_next|eq, ":cur_agent_troop", "trp_tutorial_fighter_1"),
(this_or_next|eq, ":cur_agent_troop", "trp_tutorial_fighter_2"),
(this_or_next|eq, ":cur_agent_troop", "trp_tutorial_fighter_3"),
(eq, ":cur_agent_troop", "trp_tutorial_fighter_4"),
(agent_set_team, ":cur_agent", 7),
(agent_get_slot, ":spawn_point", ":cur_agent", slot_agent_spawn_entry_point),
(entry_point_get_position, pos1, ":spawn_point"),
(agent_set_scripted_destination, ":cur_agent", pos1),
(agent_force_rethink, ":cur_agent"), # bot reacts and starts to attack
(try_end),
(agent_set_wielded_item, ":trainer_agent", "itm_practice_sword"), #TODO: change this ( Bot wields wooden thingie)
(store_random_in_range, "$g_tutorial_training_ground_melee_state", 1, 5),
#random attack direction(this causes random swings , left/right/overhead/stab)
(assign, "$g_tutorial_update_mouse_presentation", 1),
(assign, "$g_tutorial_training_ground_next_score_time", 0),
(try_end),
(else_try),
(gt, "$g_tutorial_training_ground_melee_state", 0),
(try_begin),
(agent_set_team, ":player_agent", 1),
(agent_set_team, ":trainer_agent", 2),
(agent_get_position, pos1, ":player_agent"),
(agent_set_scripted_destination_no_attack, ":trainer_agent", pos1), # bot always goes to its initial spawnpoint after each duel. İf you hit bot , it wont care untill it gets its spawn .
(agent_get_attack_action, ":attack_action", ":player_agent"),
(try_begin),
(eq, ":attack_action", 2), # attack action equals to 2 if user releases its sword , i mean bot is seeking for your swing released in order to block .
(agent_get_action_dir, ":action_dir_attacker", ":player_agent"), # bot is supposed to block our swings
(try_begin), #Here is blocking code which is very simple .
(eq, ":action_dir_attacker", 0), #down
(agent_set_defend_action, ":trainer_agent", 0, 1),
(else_try),
(eq, ":action_dir_attacker", 3), #up
(agent_set_defend_action, ":trainer_agent", 3, 1),
(else_try),
(eq, ":action_dir_attacker", 1), #right
(agent_set_defend_action, ":trainer_agent", 2, 1),
(else_try),
(eq, ":action_dir_attacker", 2), #left
(agent_set_defend_action, ":trainer_agent", 1, 1),
(try_end),
(try_end),
(try_begin),
(ge, "$g_tutorial_training_ground_current_score", 5),
(tutorial_message, -1),
(assign, "$g_tutorial_training_ground_melee_state", 0),
(agent_set_team, ":player_agent", 0),
(agent_set_team, ":trainer_agent", 7),
(agent_set_hit_points, ":player_agent", 100, 0), #Healing both side after challenge .
(agent_set_hit_points, ":trainer_agent", 100, 0),
## (assign, "$g_tutorial_training_ground_melee_trainer_attack_completed", 1), #not used
(assign, "$g_tutorial_training_ground_conversation_state", 9), #attack complete
(start_mission_conversation, "$g_tutorial_training_ground_melee_trainer_attack"),
(assign, "$g_tutorial_training_ground_melee_trainer_attack", -1),
(try_end),
(try_end),
(try_end),
And i took fresh usable part
# Agent represents parrying bot and player is player ...
(agent_is_active, ":duelist_agent_no"),
(neg|eq,":duelist_agent_no",":duelist_player_no"),
(agent_get_player_id, ":duelist_player_no", ":duelist_agent_no"),
(try_for_agents, ":duelist_agent_no"),
(agent_get_attack_action, ":attack_action", ":duelist_player_no"),
(try_begin),
(eq, ":attack_action", 2), #release
(agent_get_action_dir, ":action_dir_attacker", ":duelist_player_no"),
(try_begin),
(eq, ":action_dir_attacker", 0), #down
(agent_set_defend_action, ":duelist_agent_no", 0, 1),
(else_try),
(eq, ":action_dir_attacker", 3), #up
(agent_set_defend_action, ":duelist_agent_no", 3, 1),
(else_try),
(eq, ":action_dir_attacker", 1), #right
(agent_set_defend_action, ":duelist_agent_no", 2, 1),
(else_try),
(eq, ":action_dir_attacker", 2), #left
(agent_set_defend_action, ":duelist_agent_no", 1, 1),
(try_end),
(try_end),
(try_end),
(agent_is_active, ":duelist_agent_no"),
(neg|eq,":duelist_agent_no",":duelist_player_no"),
(agent_get_player_id, ":duelist_player_no", ":duelist_agent_no"),
(try_for_agents, ":duelist_agent_no"),
(agent_get_attack_action, ":attack_action", ":duelist_player_no"),
(try_begin),
(eq, ":attack_action", 2), #release
(agent_get_action_dir, ":action_dir_attacker", ":duelist_player_no"),
(try_begin),
(eq, ":action_dir_attacker", 0), #down
(agent_set_defend_action, ":duelist_agent_no", 0, 1),
(else_try),
(eq, ":action_dir_attacker", 3), #up
(agent_set_defend_action, ":duelist_agent_no", 3, 1),
(else_try),
(eq, ":action_dir_attacker", 1), #right
(agent_set_defend_action, ":duelist_agent_no", 2, 1),
(else_try),
(eq, ":action_dir_attacker", 2), #left
(agent_set_defend_action, ":duelist_agent_no", 1, 1),
(try_end),
(try_end),
(try_end),
And copied it right into duel mode section ( Line :14300) . ( exactly patched up to end of the script starts with " (ti_on_agent_killed_or_wounded, 0, 0, [], ..... " (Line : 14420)
After this point , i lost my control as a newbie codder ...
(ti_on_agent_killed_or_wounded, 0, 0, [],
[
(store_trigger_param_1, ":dead_agent_no"),
(store_trigger_param_2, ":killer_agent_no"),
(call_script, "script_multiplayer_server_on_agent_killed_or_wounded_common", ":dead_agent_no", ":killer_agent_no"),
(try_begin),
(get_player_agent_no, ":player_agent"),
(agent_is_active, ":player_agent"),
(agent_slot_ge, ":player_agent", slot_agent_in_duel_with, 0),
(try_begin),
(eq, ":dead_agent_no", ":player_agent"),
(display_message, "str_you_have_lost_a_duel"),
(else_try),
(agent_slot_eq, ":player_agent", slot_agent_in_duel_with, ":dead_agent_no"),
(display_message, "str_you_have_won_a_duel"),
(try_end),
(try_end),
(try_begin),
(agent_slot_ge, ":dead_agent_no", slot_agent_in_duel_with, 0),
(agent_get_slot, ":duelist_agent_no", ":dead_agent_no", slot_agent_in_duel_with),
(agent_set_slot, ":dead_agent_no", slot_agent_in_duel_with, -1),
(try_begin),
(agent_is_active, ":duelist_agent_no"),
(agent_set_slot, ":duelist_agent_no", slot_agent_in_duel_with, -1),
(agent_clear_relations_with_agents, ":duelist_agent_no"),
(try_begin),
(agent_get_player_id, ":duelist_player_no", ":duelist_agent_no"),
(neg|player_is_active, ":duelist_player_no"), #might be AI
(agent_force_rethink, ":duelist_agent_no"),
########
## (neg|eq,":duelist_agent_no",":duelist_player_no"), Dont know why i added this ...lol
(agent_get_player_id, ":duelist_player_no", ":duelist_agent_no"),
(try_for_agents, ":duelist_agent_no"),
(agent_get_attack_action, ":attack_action", ":duelist_player_no"),
(try_begin),
(eq, ":attack_action", 2), #release
(agent_get_action_dir, ":action_dir_attacker", ":duelist_player_no"),
(try_begin),
(eq, ":action_dir_attacker", 0), #down
(agent_set_defend_action, ":duelist_agent_no", 0, 1),
(else_try),
(eq, ":action_dir_attacker", 3), #up
(agent_set_defend_action, ":duelist_agent_no", 3, 1),
(else_try),
(eq, ":action_dir_attacker", 1), #right
(agent_set_defend_action, ":duelist_agent_no", 2, 1),
(else_try),
(eq, ":action_dir_attacker", 2), #left
(agent_set_defend_action, ":duelist_agent_no", 1, 1),
(try_end),
(try_end),
(try_end),
##############
(try_end),
(try_end),
(try_end),
]),
[
(store_trigger_param_1, ":dead_agent_no"),
(store_trigger_param_2, ":killer_agent_no"),
(call_script, "script_multiplayer_server_on_agent_killed_or_wounded_common", ":dead_agent_no", ":killer_agent_no"),
(try_begin),
(get_player_agent_no, ":player_agent"),
(agent_is_active, ":player_agent"),
(agent_slot_ge, ":player_agent", slot_agent_in_duel_with, 0),
(try_begin),
(eq, ":dead_agent_no", ":player_agent"),
(display_message, "str_you_have_lost_a_duel"),
(else_try),
(agent_slot_eq, ":player_agent", slot_agent_in_duel_with, ":dead_agent_no"),
(display_message, "str_you_have_won_a_duel"),
(try_end),
(try_end),
(try_begin),
(agent_slot_ge, ":dead_agent_no", slot_agent_in_duel_with, 0),
(agent_get_slot, ":duelist_agent_no", ":dead_agent_no", slot_agent_in_duel_with),
(agent_set_slot, ":dead_agent_no", slot_agent_in_duel_with, -1),
(try_begin),
(agent_is_active, ":duelist_agent_no"),
(agent_set_slot, ":duelist_agent_no", slot_agent_in_duel_with, -1),
(agent_clear_relations_with_agents, ":duelist_agent_no"),
(try_begin),
(agent_get_player_id, ":duelist_player_no", ":duelist_agent_no"),
(neg|player_is_active, ":duelist_player_no"), #might be AI
(agent_force_rethink, ":duelist_agent_no"),
########
## (neg|eq,":duelist_agent_no",":duelist_player_no"), Dont know why i added this ...lol
(agent_get_player_id, ":duelist_player_no", ":duelist_agent_no"),
(try_for_agents, ":duelist_agent_no"),
(agent_get_attack_action, ":attack_action", ":duelist_player_no"),
(try_begin),
(eq, ":attack_action", 2), #release
(agent_get_action_dir, ":action_dir_attacker", ":duelist_player_no"),
(try_begin),
(eq, ":action_dir_attacker", 0), #down
(agent_set_defend_action, ":duelist_agent_no", 0, 1),
(else_try),
(eq, ":action_dir_attacker", 3), #up
(agent_set_defend_action, ":duelist_agent_no", 3, 1),
(else_try),
(eq, ":action_dir_attacker", 1), #right
(agent_set_defend_action, ":duelist_agent_no", 2, 1),
(else_try),
(eq, ":action_dir_attacker", 2), #left
(agent_set_defend_action, ":duelist_agent_no", 1, 1),
(try_end),
(try_end),
(try_end),
##############
(try_end),
(try_end),
(try_end),
]),
Bots should behave like champion bot . But when i hosted , bots were as dumb as what they were . I think hardcoded Aİ codes dominate other opensource codes if it colides with other . ( dont make fun of me , its just an assumption ... ) I also tried to create independent script next to other duel scripts in module_mission_templates.py ( but failed again) .Maybe i should modify tutorial scene with some multiplayer codes instead of modifying multiplayer scenes with other external/tutorial codes ... thats why Nditions have max 4 bots , isnt it ... They are only able to bring 4 trainer bots ...
Guys , whether i am a cool modder or not , the subject of topic is assessable i think .Add comments please tell me if i got either wrong way or true path ...I am glad if you post your feedbacks . Sincerely , a new member .
Edit : by the way , i will modify my post with better less fugly codes soon