This is a combat ability to toss your shield in battle, which will deal damage to certain amount of targets within line of sight in specified radius and then come back to you. The damage amount depends on your Shield skill, Power Throw skill and the resistance stat of the shield itself. All aspects of this feature are customizable in constants...
...and they might as well be our starting point:
1)
2)
3)
4)
5)
End result:
...and they might as well be our starting point:
1)
Python:
# Shield Toss
ST_Button = key_x # the key you'd like to bind this ability on
ST_Targets = 7 # the amount of targets shield should hit before returning
ST_Radius = 1500 # the distance from player targets will be searched within
ST_Time_Factor = 16 # this factor directly affects shield moving speed. The higher it is, the faster shield will move
ST_Shield_Skill_Factor = 10 # your Shield skill level will be multiplied by this amount before being added to min/max tresholds
ST_PT_Skill_Factor = 3 # your Power Throw skill level will be multiplied by this amount before being added to max treshold only
shield_toss_slots = 409 # all the slots start from here so when you need to move them you adjust only 1 number
slot_shield_throw_state = shield_toss_slots + 1
slot_shield_throw_tracker = shield_toss_slots + 2
slot_shield_throw_target_hit = shield_toss_slots + 3
slot_shield_throw_targets_left = shield_toss_slots + 4
slot_shield_throw_cur_target = shield_toss_slots + 5
slot_shield_throw_item_id = shield_toss_slots + 6
Replace any two unused_human_animations with these. They are essentially just duplicates of native anim_defend_shield_right and anim_defend_shield_left with higher priority so they don't get overwridden by equip animations.
Python:
["shield_throw", 0, amf_priority_fall_from_horse|amf_rider_rot_shield|amf_use_defend_speed|amf_play|amf_restart|amf_client_owner_prediction|amf_use_inertia,
[0.75, "defend_shield_right", 5, 26, arf_blend_in_3],
],
["shield_catch", 0, amf_priority_fall_from_horse|amf_rider_rot_shield|amf_use_defend_speed|amf_play|amf_restart|amf_client_owner_prediction|amf_use_inertia,
[0.75, "defend_shield_left", 5, 26, arf_blend_in_3],
],
Python:
# script_send_shield_to_next_target
# Input: 1 - tracker prop id
# Output: none
# Sends the thrown shield to the next target in queue, or back to player if the queue is empty.
("send_shield_to_next_target",
[
(store_script_param_1, ":prop"),
(assign, ":target", -1),
(assign, ":min_found", -1),
(get_player_agent_no, ":player"),
(agent_get_team, ":p_team", ":player"),
(agent_get_position, pos2, ":player"),
(prop_instance_get_position, pos3, ":prop"),
(position_move_z, pos2, 150),
(try_for_agents, ":cur_agent"),
(agent_is_alive, ":cur_agent"),
(agent_is_human, ":cur_agent"),
(agent_is_non_player, ":cur_agent"),
(agent_slot_eq, ":cur_agent", slot_shield_throw_target_hit, 0),
(agent_get_team, ":a_team", ":cur_agent"),
(agent_get_position, pos4, ":cur_agent"),
(position_move_z, pos4, 150),
(get_distance_between_positions, ":cur_dist", pos4, pos2),
(le, ":cur_dist", ST_Radius),
(position_has_line_of_sight_to_position, pos4, pos2),
(teams_are_enemies, ":a_team", ":p_team"),
(try_begin),
(neq, ":min_found", 1),
(assign, ":min_dist", ":cur_dist"),
(assign, ":target", ":cur_agent"),
(assign, ":min_found", 1),
(else_try),
(lt, ":cur_dist", ":min_dist"),
(assign, ":min_dist", ":cur_dist"),
(assign, ":target", ":cur_agent"),
(try_end),
(end_try),
(try_begin),
(ge, ":target", 0),
(scene_prop_slot_ge, ":prop", slot_shield_throw_targets_left, 1),
(scene_prop_set_slot, ":prop", slot_shield_throw_state, 1), # seeking targets
(scene_prop_set_slot, ":prop", slot_shield_throw_cur_target, ":target"),
(agent_get_position, pos4, ":target"),
(agent_get_bone_position, pos5, ":target", 8, 1),
(position_copy_rotation, pos5, pos4),
(store_random_in_range, ":rot", 0, 360),
(position_rotate_z, pos5, ":rot"),
(else_try),
(scene_prop_set_slot, ":prop", slot_shield_throw_state, 2), # returning
(try_end),
(try_begin),
(scene_prop_slot_eq, ":prop", slot_shield_throw_state, 2), # returning
(scene_prop_slot_eq, ":prop", slot_shield_throw_targets_left, ST_Targets),
(scene_prop_set_slot, ":prop", slot_shield_throw_targets_left, 0),
(copy_position, pos5, pos2),
(position_move_z, pos5, 150),
(position_move_y, pos5, 1000),
(store_random_in_range, ":rot", 0, 360),
(position_rotate_z, pos5, ":rot"),
(else_try),
(scene_prop_slot_eq, ":prop", slot_shield_throw_state, 2), # returning
(scene_prop_set_slot, ":prop", slot_shield_throw_state, 0), # cought
(agent_get_bone_position, pos5, ":player", 12, 1),
(scene_prop_set_slot, ":prop", slot_shield_throw_cur_target, ":player"),
(try_end),
(get_distance_between_positions, ":f_dist", pos3, pos5),
(store_div, ":time", ":f_dist", ST_Time_Factor),
(prop_instance_animate_to_position, ":prop", pos5, ":time"),
]),
Python:
("shield_tracker", sokf_moveable, "barrier_sphere", "0",
[
(ti_on_scene_prop_is_animating,
[
(store_trigger_param_1, ":prop"),
(scene_prop_get_slot, ":tracker", ":prop", slot_shield_throw_tracker),
(prop_instance_is_valid, ":tracker"),
(prop_instance_get_position, pos20, ":prop"),
(prop_instance_set_position, ":tracker", pos20),
]),
(ti_on_scene_prop_animation_finished,
[
(store_trigger_param_1, ":prop"),
(get_player_agent_no, ":player"),
(scene_prop_get_slot, ":shield", ":prop", slot_shield_throw_item_id),
(try_begin),
(scene_prop_slot_eq, ":prop", slot_shield_throw_state, 0),
(scene_prop_get_slot, ":tracker", ":prop", slot_shield_throw_tracker),
(agent_equip_item, ":player", ":shield"),
(agent_set_wielded_item, ":player", ":shield"),
(agent_set_animation, ":player", "anim_shield_catch", 1),
(scene_prop_set_slot, ":prop", slot_shield_throw_cur_target, -1),
(try_for_agents, ":agent"),
(agent_set_slot, ":agent", slot_shield_throw_target_hit, 0),
(try_end),
(prop_instance_is_valid, ":tracker"),
(scene_prop_set_prune_time, ":tracker", 0),
(else_try),
(call_script, "script_send_shield_to_next_target", ":prop"),
(scene_prop_get_slot, ":target", ":prop", slot_shield_throw_cur_target),
(agent_is_active, ":target"),
(agent_is_non_player, ":target"),
(item_get_body_armor, ":res", ":shield"),
(store_skill_level, ":skl_shield", skl_shield),
(store_skill_level, ":skl_pt", skl_power_throw),
(store_mul, ":s_boost", ":skl_shield", ST_Shield_Skill_Factor),
(store_mul, ":pt_boost", ":skl_pt", ST_PT_Skill_Factor),
(store_add, ":min_dmg", 20, ":s_boost"),
(store_add, ":max_dmg", 60, ":s_boost"),
(val_add, ":min_dmg", ":res"),
(val_add, ":max_dmg", ":pt_boost"),
(store_random_in_range, ":real_dmg", ":min_dmg", ":max_dmg"),
(agent_deliver_damage_to_agent, ":player", ":target", ":real_dmg", "itm_maul"),
(try_begin),
(item_has_property, ":shield", itp_wooden_parry),
(assign, ":sound", "snd_shield_hit_wood_wood"),
(else_try),
(assign, ":sound", "snd_shield_hit_metal_metal"),
(try_end),
#(try_begin),
# (agent_get_troop_id, ":trp", ":target"),
# (troop_is_hero, ":trp"),
# (assign, ":sound", "snd_gong"),
#(try_end),
(agent_play_sound, ":target", ":sound"),
(agent_set_slot, ":target", slot_shield_throw_target_hit, 1),
(scene_prop_get_slot, ":tgts_left", ":prop", slot_shield_throw_targets_left),
(val_sub, ":tgts_left", 1),
(scene_prop_set_slot, ":prop", slot_shield_throw_targets_left, ":tgts_left"),
(agent_get_horse, ":horse", ":target"),
(agent_is_active, ":horse"),
(agent_start_running_away, ":horse"),
(agent_set_slot, ":horse", slot_agent_is_running_away, 1),
(agent_set_animation, ":target", "anim_rider_fall_right", 1),
(try_end),
])]),
Python:
(0, 0, 0,
[(neg|main_hero_fallen),
(key_clicked, ST_Button),],
[
(get_player_agent_no, ":player"),
(agent_get_wielded_item, ":shield", ":player", 1),
(try_begin),
(lt, ":shield", 1),
(display_message, "@You need a shield for that.", 0xFF5050),
(play_sound, "snd_quest_cancelled"),
(else_try),
(agent_unequip_item, ":player", ":shield"),
(agent_set_animation, ":player", "anim_shield_throw", 1),
(agent_play_sound, ":player", "snd_sword_swing"),
(agent_get_position, pos2, ":player"),
(position_move_z, pos2, 150),
(agent_get_bone_position, pos3, ":player", 12, 1),
(set_spawn_position, pos3),
(spawn_item_without_refill, ":shield", 0, 180),
(assign, ":s_prop", reg0),
(try_begin),
(agent_slot_eq, ":player", slot_shield_throw_tracker, 0),
(spawn_scene_prop, "spr_shield_tracker"),
(scene_prop_set_visibility, reg0, 0),
(agent_set_slot, ":player", slot_shield_throw_tracker, reg0),
(assign, ":t_prop", reg0),
(else_try),
(agent_get_slot, ":t_prop", ":player", slot_shield_throw_tracker),
(try_end),
(prop_instance_set_position, ":t_prop", pos3),
(scene_prop_set_slot, ":t_prop", slot_shield_throw_item_id, ":shield"),
(scene_prop_set_slot, ":t_prop", slot_shield_throw_tracker, ":s_prop"),
(scene_prop_set_slot, ":t_prop", slot_shield_throw_targets_left, ST_Targets),
(scene_prop_set_slot, ":t_prop", slot_shield_throw_cur_target, -1),
(scene_prop_set_slot, ":t_prop", slot_shield_throw_state, 2),
(call_script, "script_send_shield_to_next_target", ":t_prop"),
(try_end),
]),
Last edited: