The current version requires WSE to be installed for singleplayer and on the server only for multiplayer. Here is a link to the WSE thread:
http://forums.taleworlds.com/index.php/topic,151194.0.htmlFeatures:- This version uses the engine's collision detection so hitboxes are no longer needed.
- Performance should be much greater than before.
- Almost completely server-side for multiplayer
- You can keep multiple ammo items of the same kind separate.
(i.e. 9mm, 30-06, .357, .45 will only work in compatible guns even if they are all itp_type_bullets)
Notes:- Ammo comsumption is not perfect since the engine doesn't remember the amount of bullets have been taken from an ammo item.
- You need to shorten the animation length of the ready animation to about 0.01 for consistant firing speed.
- Firing rate is determined by speed_rating and animation length.
- I have not tested this version with the AI, but it should work since I haven't changed the basic mechanics.
######################################################################
##################### ADD THESE BELOW OTHER IMPORTS ##################
################# THESE STORE ITEM STATS IN ITEM_SLOTS ###############
######################################################################
from module_items import *
def get_item_max_ammo():
item_max_ammo = []
for i_item in xrange(len(items)):
item_max_ammo.append((item_set_slot, i_item, slot_item_max_ammo, get_max_ammo(items[i_item][6])))
return item_max_ammo[:]
def get_item_accuracy():
item_accuracy = []
for i_item in xrange(len(items)):
item_accuracy.append((item_set_slot, i_item, slot_item_accuracy, get_leg_armor(items[i_item][6])))
return item_accuracy[:]
def get_item_shoot_speed():
item_shoot_speed = []
for i_item in xrange(len(items)):
item_shoot_speed.append((item_set_slot, i_item, slot_item_shoot_speed, get_missile_speed(items[i_item][6])))
return item_shoot_speed[:]
################ THIS IS THE SERVER TO CLIENT EVENT CODE ###############
############### PUT IT WITHIN THE CLIENT SIDE EVENT SECTION ############
(else_try),
(eq, ":event_type", multiplayer_event_autofire),
(store_script_param, ":wander", 3),
(get_player_agent_no, ":player_agent"),
(agent_set_slot, ":player_agent", slot_agent_spread, ":wander"),
########################################################################
##################### ASSIGNS ITEM VALUES TO SLOTS #####################
########################################################################
("set_auto_weapon_stats",[
(store_script_param, ":auto_item_id", 1),
(store_script_param, ":auto_recoil", 2),
(store_script_param, ":auto_shotgun", 3),
(store_script_param, ":item_sound", 4),
######################### SET VALUES TO SLOTS ##########################
(item_set_slot, ":auto_item_id", slot_item_auto_recoil, ":auto_recoil"),
(item_set_slot, ":auto_item_id", slot_item_auto_shotgun, ":auto_shotgun"),
(item_set_slot, ":auto_item_id", slot_item_sound, ":item_sound"),
]),
########################################################################
##################### FIRES WEAPON BASED ON STATS ######################
########################################################################
("fire_auto_weapon",[
(this_or_next|multiplayer_is_server),
(neg|game_in_multiplayer_mode),
(store_script_param, ":shooter_agent", 1),
(store_script_param, ":shooter_weapon", 2),
(store_script_param, ":shooter_ammo", 3),
(item_get_slot, ":auto_accuracy", ":shooter_weapon", slot_item_accuracy),
(store_sub, ":inaccuracy", 100, ":auto_accuracy"),
###################### CALCULATE AGENT INACCURACY #######################
(agent_get_troop_id, ":shooter_troop", ":shooter_agent"),
(store_proficiency_level, ":firing_skill", ":shooter_troop", wpt_firearm),
(store_sub, ":firing_disability", 500, ":firing_skill"),
(val_div, ":firing_disability", 10),
############################# CALCULATE WANDER ##########################
(item_get_slot, ":weapon_recoil", ":shooter_weapon", slot_item_auto_recoil),
(val_mul, ":weapon_recoil", 5),
(agent_get_slot, ":wander", ":shooter_agent", slot_agent_firearm_wander),
(val_add, ":wander", ":weapon_recoil"),
(store_mul, ":max_recoil", ":weapon_recoil", 10),
(val_min, ":wander", ":max_recoil"),
(agent_set_slot, ":shooter_agent", slot_agent_firearm_wander, ":wander"),
(agent_get_animation, ":cur_anim", ":shooter_agent", 0),
################# INCREASE INACCURACY DUE TO MOVEMENT ###################
(try_begin),
(is_between, ":cur_anim", "anim_run_forward", "anim_stand_to_crouch"),
(val_mul, ":wander", 2),
(try_end),
################### INCREASE INACCURACY DUE TO JUMP #####################
(try_begin),
(is_between, ":cur_anim", "anim_jump", "anim_stand_unarmed"),
(val_mul, ":wander", 3),
(try_end),
################# DECREASE INACCURACY DUE TO CROUCH #####################
# (try_begin),
# (this_or_next|eq, ":cur_anim", "anim_crouch_to_stand"),
# (eq, ":cur_anim", "anim_stand_to_crouch"),
# (val_mul, ":wander", 2),
# (val_div, ":wander", 3),
# (try_end),
################## DECREASE INACCURACY DUE TO PRONE #####################
# (try_begin),
# (this_or_next|eq, ":cur_anim", "anim_stand_to_prone"),
# (eq, ":cur_anim", "anim_prone_to_stand"),
# (val_div, ":wander", 2),
# (try_end),
(val_mul, ":wander", ":firing_disability"),
(val_div, ":wander", 1000),
(store_add, ":slot_wander", ":inaccuracy", ":wander"),
(agent_set_slot, ":shooter_agent", slot_agent_spread, ":slot_wander"),
################ SEND DATA NEEDED FOR PRSNT TO CLIENTS ##################
(try_begin),
(game_in_multiplayer_mode),
(neg|agent_is_non_player, ":shooter_agent"),
(agent_get_player_id, ":shooter_player", ":shooter_agent"),
(multiplayer_send_int_to_player, ":shooter_player", multiplayer_event_autofire, ":slot_wander"),
(try_end),
(item_get_slot, ":velocity", ":shooter_weapon", slot_item_shoot_speed),
(item_get_slot, ":shotgun", ":shooter_weapon", slot_item_auto_shotgun),
############# RAISE POS TO EYE LEVEL & MOVE TO END OF GUN ###############
(agent_get_look_position, pos1, ":shooter_agent"),
(position_move_z, pos1, 165, 0),
(position_move_y, pos1, 50, 0),
#################### SOUNDS AND PARTICLES PLAY HERE #####################
(item_get_slot, ":sound_id", ":shooter_weapon", slot_item_sound),
(agent_play_sound, ":shooter_agent", ":sound_id"),
#(particle_system_burst, "psys_gun_flash", pos1, 10),
############ GET INITIAL RANDOMIZED BULLET ANGLE ROTATION ###############
(store_random_in_range, ":y_rotation", 0, 360),
(position_rotate_y, pos1, ":y_rotation"),
(try_begin),
############ IF NOT SHOTGUN SPAWN BULLET WITH INACCURACY ################
(eq, ":shotgun", 0),
(val_add, ":inaccuracy", ":wander"),
(store_random_in_range, ":x_inaccuracy", 0, ":inaccuracy"),
(set_fixed_point_multiplier, 10),
(position_rotate_x_floating, pos1, ":x_inaccuracy"),
(set_fixed_point_multiplier, 1),
(spawn_missile, ":shooter_agent", pos1, ":velocity", ":shooter_weapon", ":shooter_ammo"),
(else_try),
############## IF SHOTGUN ROTATE X WITH WITH INACCURACY #################
(store_random_in_range, ":wander_movement", 0, ":wander"),
(set_fixed_point_multiplier, 10),
(position_rotate_x_floating, pos1, ":wander_movement"),
############# REPEAT FOR EACH PROJECTILE DEFINED BY ITEM ################
(try_for_range, ":repeat", 0, ":shotgun"),
(set_fixed_point_multiplier, 10),
(copy_position, pos2, pos1),
################ ROTATES EACH PROJECTILE INTO SECTORS ###################
(store_div, ":y_rotation", 360, ":shotgun"),
(val_mul, ":y_rotation", ":repeat"),
(position_rotate_y, pos2, ":y_rotation"),
############ SPAWN PROJECTILE WITH RANDOMIZED INACCURACY ################
(store_random_in_range, ":x_inaccuracy", 0, ":inaccuracy"),
(position_rotate_x_floating, pos2, ":x_inaccuracy"),
(set_fixed_point_multiplier, 1),
(spawn_missile, ":shooter_agent", pos2, ":velocity", ":shooter_weapon", ":shooter_ammo"),
(try_end),
(try_end),
]),
#########################################################################
################ SCRIPT TO SET ITEM STATS TO ITEM_SLOTS #################
#########################################################################
("init_item_maxammo", get_item_max_ammo()),
("init_item_accuracy", get_item_accuracy()),
("init_item_shoot_speed", get_item_shoot_speed()),
####################################################################
####################### INITIALIZE AUTOFIRE ########################
####################################################################
common_init_auto_fire = (
ti_after_mission_start, 0, ti_once, [], [
(this_or_next|multiplayer_is_server),
(neg|game_in_multiplayer_mode),
######### NEEDED TO PREVENT UNINITIALIZE SLOTS FOR CLIENTS #########
############# ADD EACH SCRIPT CALL FROM AUTO ITEM HERE #############
(try_begin),
(multiplayer_is_dedicated_server),
(call_script, "script_set_auto_weapon_stats", "itm_SPAS_12", 1, 9),
(call_script, "script_set_auto_weapon_stats", "itm_AK_47", 2, 0),
(call_script, "script_set_auto_weapon_stats", "itm_UZI", 4, 0),
(try_end),
############### NEEDED TO PREVENT UNINITIALIZE SLOTS ###############
(call_script, "script_init_item_maxammo"),
(call_script, "script_init_item_accuracy"),
(call_script, "script_init_item_shoot_speed"),
])
####################################################################
################## CHECK IF BULLET CAN BE FIRED ####################
####################################################################
common_auto_fire = (
0.1, 0, 0,
[
(assign, ":player_agent", -1),
(try_begin),
(game_in_multiplayer_mode),
(multiplayer_get_my_player, ":player_no"),
(player_is_active, ":player_no"),
(neg|player_is_busy_with_menus, ":player_no"),
(player_get_agent_id, ":player_agent", ":player_no"),
(else_try),
(neg|game_in_multiplayer_mode),
(get_player_agent_no, ":player_agent"),
(try_end),
################### START PRESENTATION IF NEEDED ###################
(try_begin),
(neq, ":player_agent", -1),
(agent_get_wielded_item, ":cur_weapon", ":player_agent", 0),
(is_between, ":cur_weapon", "itm_uzi", "itm_sevensixtwo_mm_rounds"),
(neg|is_presentation_active, "prsnt_battle"),
(neg|is_presentation_active, "prsnt_auto_weapon_reticle"),
(start_presentation, "prsnt_auto_weapon_reticle"),
(try_end),
(this_or_next|multiplayer_is_server),
(neg|game_in_multiplayer_mode),
],[
(try_for_agents, ":shooter_agent"),
(agent_is_alive, ":shooter_agent"),
(try_begin),
########### CHECK IF AGENT IS IN READY WEAPON ANIMATION ############
(agent_get_animation, ":shooter_stance", ":shooter_agent", 1),
(this_or_next|eq, ":shooter_stance", "anim_ready_pistol"),
(eq, ":shooter_stance", "anim_ready_musket"),
(agent_get_wielded_item, ":cur_weapon", ":shooter_agent", 0),
(is_between, ":cur_weapon", "itm_uzi", "itm_sevensixtwo_mm_rounds"),
(agent_get_animation_progress, ":anim_progress", ":shooter_agent", 1),
(eq, ":anim_progress", 100),
############### FIND WEAPON, GET AMMO, SET AMMO TYPE ###############
(try_for_range, ":cur_slot", 0, 4),
(agent_get_item_slot, ":cur_item", ":shooter_agent", ":cur_slot"),
(eq, ":cur_item", ":cur_weapon"),
(assign, ":weapon_slot", ":cur_slot"),
(try_end),
(agent_get_item_slot_ammo, ":ammo", ":shooter_agent", ":weapon_slot"),
(try_begin),
(eq, ":cur_weapon", "itm_uzi"),
(assign, ":ammo_item", "itm_nine_mm_rounds"),
(else_try),
(eq, ":cur_weapon", "itm_ak_47"),
(assign, ":ammo_item", "itm_sevensixtwo_mm_rounds"),
(else_try),
(eq, ":cur_weapon", "itm_spas_12"),
(assign, ":ammo_item", "itm_twelve_gauge_buckshot"),
(try_end),
######### UNEQUIPS AMMO THAT IS UNUSABLE BY WIELDED WEAPON #########
(try_for_range, ":cur_slot", 0, 4),
(agent_get_item_slot, ":cur_item", ":shooter_agent", ":cur_slot"),
(neq, ":cur_item", -1),
(neq, ":cur_item", ":ammo_item"),
(item_get_type, ":ammo_type", ":ammo_item"),
(item_get_type, ":cur_type", ":cur_item"),
(eq, ":cur_type", ":ammo_type"),
(agent_unequip_item, ":shooter_agent", ":cur_item", -1, 1),
(try_end),
########### EQUIPS AMMO THAT IS USABLE BY WIELDED WEAPON ###########
(try_begin),
(neg|agent_has_item_equipped, ":shooter_agent", ":ammo_item"),
(agent_equip_item, ":shooter_agent", ":ammo_item"),
(try_end),
############################ REDUCE AMMO ###########################
(try_begin),
(gt, ":ammo", 0),
(val_sub, ":ammo", 1),
(agent_set_item_slot_ammo, ":shooter_agent", ":weapon_slot", ":ammo"),
####################### SET FIRING ANIMATION #######################
(try_begin),
(eq, ":cur_weapon", "itm_uzi"),
(agent_set_animation, ":shooter_agent", "anim_release_uzi", 1),
(else_try),
(eq, ":cur_weapon", "itm_ak_47"),
(agent_set_animation, ":shooter_agent", "anim_release_ak_47", 1),
(else_try),
(agent_set_animation, ":shooter_agent", "anim_release_spas_12", 1),
(try_end),
(call_script, "script_fire_auto_weapon", ":shooter_agent", ":cur_weapon", ":ammo_item"),
(try_end),
(agent_set_slot, ":shooter_agent", slot_agent_cool_time, 0),
(else_try),
################## REDUCES RECOIL FOR ALL AGENTS ###################
(agent_get_slot, ":cool_time", ":shooter_agent", slot_agent_cool_time),
(agent_get_slot, ":wander", ":shooter_agent", slot_agent_spread),
(assign, ":factor", 10),
(val_mul, ":factor", ":cool_time"),
(val_sub, ":wander", ":factor"),
(val_max, ":wander", 10),
(agent_set_slot, ":shooter_agent", slot_agent_spread, ":wander"),
(val_add, ":cool_time", 1),
(agent_set_slot, ":shooter_agent", slot_agent_cool_time, ":cool_time"),
(try_end),
(try_end),
])
##########################################################################
######################## CUSTOM CROSSHAIRS/RETICLE #######################
##########################################################################
("auto_weapon_reticle", prsntf_read_only, 0, [
(ti_on_presentation_load, [
(set_fixed_point_multiplier, 10),
################################ SET SCALE ###############################
(position_set_x, pos0, 3),
(position_set_y, pos0, 3),
############################ CREATE EACH DOT #############################
(create_mesh_overlay, "$up_reticle", "mesh_white_dot"),
(overlay_set_color, "$up_reticle", 0xFF3300),
(overlay_set_size, "$up_reticle", pos0),
(overlay_set_alpha, "$up_reticle", 0xAA),
(create_mesh_overlay, "$down_reticle", "mesh_white_dot"),
(overlay_set_color, "$down_reticle", 0xFF3300),
(overlay_set_size, "$down_reticle", pos0),
(overlay_set_alpha, "$down_reticle", 0xAA),
(create_mesh_overlay, "$left_reticle", "mesh_white_dot"),
(overlay_set_color, "$left_reticle", 0xFF3300),
(overlay_set_size, "$left_reticle", pos0),
(overlay_set_alpha, "$left_reticle", 0xAA),
(create_mesh_overlay, "$right_reticle", "mesh_white_dot"),
(overlay_set_color, "$right_reticle", 0xFF3300),
(overlay_set_size, "$right_reticle", pos0),
(overlay_set_alpha, "$right_reticle", 0xAA),
(presentation_set_duration, 999999),
]),
#########################################################################
########################## UPDATES THE RETICULE #########################
#########################################################################
(ti_on_presentation_run, [
(set_fixed_point_multiplier, 1000),
(try_begin),
####################### CHECK IF PRSNT SHOULD RUN #######################
(assign, ":player_agent", -1),
(try_begin),
(game_in_multiplayer_mode),
(multiplayer_get_my_player, ":player_no"),
(player_is_active, ":player_no"),
(neg|player_is_busy_with_menus, ":player_no"),
(player_get_agent_id, ":player_agent", ":player_no"),
(else_try),
(neg|game_in_multiplayer_mode),
(get_player_agent_no, ":player_agent"),
(try_end),
(neq, ":player_agent", -1),
(neg|is_presentation_active, "prsnt_battle"),
(agent_get_wielded_item, ":cur_weapon", ":player_agent", 0),
(is_between, ":cur_weapon", "itm_uzi", "itm_sevensixtwo_mm_rounds"),
(agent_get_slot, ":inaccuracy", ":player_agent", slot_agent_spread),
########################## ADJUSTS FOR ZOOM #############################
(try_begin),
(game_key_is_down, gk_zoom),
(val_mul, ":inaccuracy", 2),
(try_end),
######################### MOVES RETICLE DOTS ############################
(assign, ":range", ":inaccuracy"),
(val_add, ":range", 375),
(position_set_x, pos0, 500),
(position_set_y, pos0, ":range"),
(overlay_set_position, "$up_reticle", pos0),
(store_mul, ":range", ":inaccuracy", -1),
(val_add, ":range", 375),
(position_set_x, pos0, 500),
(position_set_y, pos0, ":range"),
(overlay_set_position, "$down_reticle", pos0),
(store_mul, ":range", ":inaccuracy", -1),
(val_add, ":range", 500),
(position_set_x, pos0, ":range"),
(position_set_y, pos0, 375),
(overlay_set_position, "$left_reticle", pos0),
(assign, ":range", ":inaccuracy"),
(val_add, ":range", 500),
(position_set_x, pos0, ":range"),
(position_set_y, pos0, 375),
(overlay_set_position, "$right_reticle", pos0),
(else_try),
################## IF INITIAL CHECK FAILS END PRSNT ####################
(presentation_set_duration, 0),
(try_end),
]),
]),
#autofire begin
slot_agent_spread = 26
slot_agent_firearm_wander = 27
slot_agent_inaccuracy = 28
slot_agent_cool_time = 29
#autofire end
#autofire begin
slot_item_auto_inaccuracy = 62
slot_item_auto_recoil = 63
slot_item_auto_shotgun = 64
slot_item_max_ammo = 65
slot_item_accuracy = 66
slot_item_shoot_speed = 67
slot_item_sound = 68
#autofire end
#autofire begin
multiplayer_event_autofire = 48
#autofire end
##########################################################################
#################### ITEM EXAMPLE FOR AUTOMATIC GUNS #####################
############# PARAMETERS FOR script_set_auto_weapon_stats ################
##########################################################################
############################ INPUT | FORMAT ##############################
############################----------------##############################
########################## item_id | "itm_*" #############################
################ projectile recoil | 0 none - 10 extreme #################
########################## shotgun | 1+ #projectiles 0=NO ################
######################### sound_id | "snd_*" #############################
##########################################################################
["uzi", "UZI", [("flintlock_pistol",0)], itp_type_pistol |itp_merchandise|itp_primary|itp_cant_use_on_horseback|itp_extra_penetration , itcf_shoot_pistol|itcf_carry_revolver_right|itcf_reload_pistol, 67, weight(3.5)|spd_rtng(99)|shoot_speed(150)|thrust_damage(30, pierce)|max_ammo(40)|accuracy(70),imodbits_none,
[(ti_on_init_item, [(call_script, "script_set_auto_weapon_stats", "itm_UZI", 4, 0, "snd_pistol_shot"),])]],
["ak_47", "AK-47", [("flintlock_pistol",0)], itp_type_musket |itp_merchandise|itp_primary|itp_two_handed|itp_cant_use_on_horseback|itp_extra_penetration , itcf_shoot_musket|itcf_carry_crossbow_back|itcf_reload_musket, 67, weight(4.3)|spd_rtng(75)|shoot_speed(200)|thrust_damage(40, pierce)|max_ammo(30)|accuracy(90),imodbits_none,
[(ti_on_init_item, [(call_script, "script_set_auto_weapon_stats", "itm_AK_47", 2, 0, "snd_pistol_shot"),])]],
["spas_12", "SPAS 12", [("flintlock_pistol",0)], itp_type_musket |itp_merchandise|itp_primary|itp_two_handed|itp_cant_use_on_horseback|itp_extra_penetration , itcf_shoot_musket|itcf_carry_crossbow_back|itcf_reload_musket, 67, weight(4.4)|spd_rtng(75)|shoot_speed(150)|thrust_damage(10, pierce)|max_ammo(8)|accuracy(50),imodbits_none,
[(ti_on_init_item, [(call_script, "script_set_auto_weapon_stats", "itm_SPAS_12", 1, 9, "snd_pistol_shot"),])]],
################### ITEM EXAMPLE FOR AUTOMATIC AMMO ######################
["sevensixtwo_mm_rounds","7.62mm Rounds", [("cartridge_a",0)], itp_type_bullets|itp_merchandise|itp_can_penetrate_shield|itp_ignore_friction|itp_no_pick_up_from_ground, 0, 41,weight(2.25)|abundance(90)|weapon_length(3)|thrust_damage(1,pierce)|max_ammo(50),imodbits_missile],
["twelve_gauge_buckshot","12 Gauge Buckshot", [("cartridge_a",0)], itp_type_bullets|itp_merchandise|itp_can_penetrate_shield|itp_ignore_friction|itp_no_pick_up_from_ground, 0, 41,weight(2.25)|abundance(90)|weapon_length(3)|thrust_damage(1,pierce)|max_ammo(20),imodbits_missile],
["nine_mm_rounds","9mm Rounds", [("cartridge_a",0)], itp_type_bullets|itp_merchandise|itp_can_penetrate_shield|itp_ignore_friction|itp_no_pick_up_from_ground, 0, 41,weight(2.25)|abundance(90)|weapon_length(3)|thrust_damage(1,pierce)|max_ammo(50),imodbits_missile],
######################################################################
########################## EXAMPLE ANIMATIONS ########################
########## I RECOMMEND TO USE THESE EXAMPLE MASTER FLAGS #############
######## USE amf_priority_throw TO OVERRIDE READY ANIMATION ##########
######################################################################
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#
# THE READY ANIMATIONS SHOULD HAVE A DURATION OF APPROX. 0.01 #
#!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!#
["release_uzi", acf_rot_vertical_sword, amf_priority_throw|amf_use_weapon_speed|amf_play|amf_client_owner_prediction,
[0.1, "anim_human", combat+2524, combat+2527, arf_blend_in_1],],
["release_ak_47", acf_rot_vertical_bow, amf_priority_throw|amf_use_weapon_speed|amf_play|amf_client_owner_prediction,
[0.1, "anim_human", combat+1330, combat+1331, arf_blend_in_1],],
["release_spas_12", acf_rot_vertical_bow,amf_priority_throw|amf_use_weapon_speed|amf_play|amf_client_owner_prediction,
[0.5, "anim_human", combat+1330, combat+1331, arf_blend_in_1],],
Here is the link to the old version download:
http://www.mbrepository.com/file.php?id=2464Running Credits:ithilienranger - majority of coding & testing
cmpxchg8b - Warband Script Enhancer & coding assistance
All other modding experts who have helped me with questions.
Special thanks to Swyter for motivating me to make this

and for mr.master for his patience and support

.