Sinisterius
Okay, so I decided to script multiplayer shield bash. Would be awesome if xenoargh would add this to the OP (original post). If anything doesn't work, then feel free to tell me!
Explanations: most of the stuff is run client-side, so no strain goes on server. You must block and then press the attack button in order to bash. The scripts get the closest agent in front of you within 1.75metres.
It won't move the agent backwards if the distance between the ground and agent is higher than 25 (aka you can't bash them off ledges.. feel free to change this but I did it so there wouldn't be any glitchers, e.g glitching through invisible barriers).
Here are the scripts, with instructions.
Explanations: most of the stuff is run client-side, so no strain goes on server. You must block and then press the attack button in order to bash. The scripts get the closest agent in front of you within 1.75metres.
It won't move the agent backwards if the distance between the ground and agent is higher than 25 (aka you can't bash them off ledges.. feel free to change this but I did it so there wouldn't be any glitchers, e.g glitching through invisible barriers).
Here are the scripts, with instructions.
Code:
## Shield bash begin.
#Initially developed by xenoargh for singleplayer,
#rewritten/revamped for multiplayer by Sinisterius.
#This goes into module_mission_templates.py, at the top.
#Then, you must add "mp_shield_bash," (without quotations)
#to the mission template where you want the shield bash to
#be allowed. For example, the multiplayer_bt template.
mp_shield_bash = (
0, 0, 0,
[
(game_key_is_down, gk_defend),
(game_key_clicked, gk_attack),
(game_is_in_multiplayer_mode),
],
[
#Get local player data.
(multiplayer_get_my_player, ":player"),
(player_is_active, ":player"),
(player_get_agent_id, ":agent", ":player"),
(agent_is_active, ":agent"),
#Check if we're in the right condition.
(agent_get_wielded_item, ":shield", ":agent", 1), #Offhand item.
(is_between, ":shield", "itm_wooden_shield", "itm_steel_shield_herald03"),
(agent_get_defend_action, ":action", ":agent"),
(eq, ":action", 2), #Blocking.
(agent_get_animation, ":anim", ":agent", 0),
(neq, ":anim", "anim_shield_bash"),
(agent_get_horse, ":horse", ":agent"),
(eq, ":horse", -1), #No horse.
#If everything is correct, then set agent up for bash.
(multiplayer_send_2_int_to_server, mp_agent_set_animation_human, ":agent", "anim_shield_bash"), #Set animation.
(player_get_troop_id, ":troop", ":player"),
(troop_get_type, ":type", ":troop"),
(try_begin),
(eq, ":type", tf_male),
(multiplayer_send_2_int_to_server, mp_agent_play_sound, ":agent", "snd_man_yell"), #Play sound.
(else_try),
(eq, ":type", tf_female),
(multiplayer_send_2_int_to_server, mp_agent_play_sound, ":agent", "snd_woman_yell"), #Play sound.
(try_end),
#Bash. Get the closest agent within 175cm~1.75m.
(agent_get_position, pos1, ":agent"),
(assign, ":minimum_distance", 400),
(assign, ":victim", -1),
(try_for_agents, ":suspect"),
(neq, ":suspect", ":agent"), #Suspect can't be our local agent.
(agent_is_active, ":suspect"),
(agent_is_alive, ":suspect"),
(agent_is_human, ":suspect"),
#Compare distances.
(agent_get_position, pos2, ":suspect"),
(neg|position_is_behind_position, pos2, pos1),
(get_distance_between_positions, ":distance", pos1, pos2),
(le, ":distance", ":minimum_distance"),
#If distance is sufficient..
(assign, ":minimum_distance", ":distance"),
(assign, ":victim", ":suspect"),
(try_end),
#If we have the victim, aka the closest agent, then deal with him. Else, do nothing.
(ge, ":victim", 0),
(agent_get_horse, ":horse", ":victim"),
(eq, ":horse", -1), #No horse.
(multiplayer_send_2_int_to_server, mp_agent_play_sound, ":victim", "snd_wooden_hit_low_armor_high_damage"), #Play sound.
(agent_get_position, pos2, ":victim"),
(position_move_y, pos2, -25),
(position_get_distance_to_ground_level, ":distance", pos2),
(try_begin),
(le, ":distance", 25),
(multiplayer_send_2_int_to_server, mp_agent_set_position, ":victim", pos2), #Set position.
(multiplayer_send_2_int_to_server, mp_agent_set_animation_human, ":victim", "anim_shield_strike"),
(else_try),
(gt, ":distance", 25),
(multiplayer_send_2_int_to_server, mp_agent_set_animation_human, ":victim", "anim_shield_strike"),
(try_end),
])
#Server/client events.
#Copy-paste this stuff right after the store_script_params in game_receive_network_message.
(try_begin),
(eq, ":event_type", mp_agent_set_animation_human),
(store_script_param, ":agent", 3),
(store_script_param, ":anim", 4),
#Play anim.
(agent_is_active, ":agent"),
(agent_is_alive, ":agent"),
(agent_is_human, ":agent"),
(agent_set_animation, ":agent", ":anim"),
(else_try),
(eq, ":event_type", mp_agent_play_sound),
(store_script_param, ":agent", 3),
(store_script_param, ":sound", 4),
#Send sound data to players.
(agent_is_active, ":agent"),
(agent_is_alive, ":agent"),
(get_max_players, ":max_players"),
(try_for_range, ":player", 0, ":max_players"),
(player_is_active, ":player"),
(multiplayer_send_2_int_to_player, ":player", mp_agent_play_sound_client, ":agent", ":sound"),
(try_end),
(else_try),
(eq, ":event_type", mp_agent_set_position),
(store_script_param, ":agent", 3),
(store_script_param, ":position", 4),
#Set position.
(agent_is_active, ":agent"),
(agent_is_alive, ":agent"),
(agent_set_position, ":agent", ":position"),
(else_try),
(neq, multiplayer_is_server),
(try_begin),
(eq, ":event_type", mp_agent_play_sound_client),
(store_script_param, ":agent", 3),
(store_script_param, ":sound", 4),
#Play sound.
(agent_is_active, ":agent"),
(agent_is_alive, ":agent"),
(agent_play_sound, ":agent", ":sound"),
(try_end),
(try_end),
#These animations go into module_animations.py
#They MUST replace existing unused animations.
["shield_bash", 0, amf_play|amf_priority_defend|amf_use_defend_speed|amf_client_owner_prediction,
[0.75, "defend_shield_parry_all", 1, 50, blend_in_defense], #Adjust duration for balance. Currently at 0.75 seconds, fixed.
[0.75, "defend_shield_right", 1, 50, blend_in_defense],
[0.75, "defend_shield_left", 1, 50, blend_in_defense],
[0.75, "defend_shield_right", 1, 50, blend_in_defense],
],
["shield_strike", acf_enforce_all|acf_align_with_ground, amf_priority_striked|amf_play|amf_accurate_body|amf_restart,
[1.0, "anim_human", blow+5000, blow+5010, arf_blend_in_3|arf_make_custom_sound],
[1.7, "anim_human", blow+5400, blow+5453, arf_blend_in_2|arf_make_custom_sound],
[1.44, "anim_human", blow+5400, blow+5445, arf_blend_in_2|arf_make_custom_sound],
],
## Shield bash end.