From: Mario <zacjardine@y7mail.com>
Date: Fri, 14 Nov 2014 09:09:39 +0000 (+1100)
Subject: Revert "Merge branch 'Mario/despawn_effects'"
X-Git-Tag: xonotic-v0.8.0~151
X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=5fcaa5e1251bcbbdedf31d885bdca0b2b75811c7;p=xonotic%2Fxonotic-data.pk3dir.git

Revert "Merge branch 'Mario/despawn_effects'"

This reverts commit 28931c8069eb1d283f01a26f31ad91d921294d9c, reversing
changes made to d55940c3b65bffebfd3c571067398c65b29e9488.
---

diff --git a/_hud_common.cfg b/_hud_common.cfg
index 5aa1bbfee..4a4999706 100644
--- a/_hud_common.cfg
+++ b/_hud_common.cfg
@@ -23,7 +23,6 @@ seta hud_colorset_background "7" "neutral/unimportant text"
 seta hud_panel_weapons_ammo_full_shells 60 "show 100% of the status bar at this ammo count"
 seta hud_panel_weapons_ammo_full_nails 320 "show 100% of the status bar at this ammo count"
 seta hud_panel_weapons_ammo_full_cells 180 "show 100% of the status bar at this ammo count"
-seta hud_panel_weapons_ammo_full_plasma 180 "show 100% of the status bar at this ammo count"
 seta hud_panel_weapons_ammo_full_rockets 160 "show 100% of the status bar at this ammo count"
 seta hud_panel_weapons_ammo_full_fuel 100 "show 100% of the status bar at this ammo count"
 
diff --git a/bal-wep-rev.cfg b/bal-wep-rev.cfg
deleted file mode 100644
index 99599dd15..000000000
--- a/bal-wep-rev.cfg
+++ /dev/null
@@ -1,753 +0,0 @@
-// {{{ #1: Blaster
-set g_balance_blaster_primary_animtime 0.2
-set g_balance_blaster_primary_damage 25
-set g_balance_blaster_primary_delay 0
-set g_balance_blaster_primary_edgedamage 12.5
-set g_balance_blaster_primary_force 300
-set g_balance_blaster_primary_force_zscale 1.25
-set g_balance_blaster_primary_lifetime 5
-set g_balance_blaster_primary_radius 60
-set g_balance_blaster_primary_refire 0.7
-set g_balance_blaster_primary_shotangle 0
-set g_balance_blaster_primary_speed 6000
-set g_balance_blaster_primary_spread 0
-set g_balance_blaster_secondary 0
-set g_balance_blaster_secondary_animtime 0.2
-set g_balance_blaster_secondary_damage 25
-set g_balance_blaster_secondary_delay 0
-set g_balance_blaster_secondary_edgedamage 12.5
-set g_balance_blaster_secondary_force 300
-set g_balance_blaster_secondary_force_zscale 1.2
-set g_balance_blaster_secondary_lifetime 5
-set g_balance_blaster_secondary_radius 70
-set g_balance_blaster_secondary_refire 0.7
-set g_balance_blaster_secondary_shotangle 0
-set g_balance_blaster_secondary_speed 6000
-set g_balance_blaster_secondary_spread 0
-set g_balance_blaster_switchdelay_drop 0.2
-set g_balance_blaster_switchdelay_raise 0.2
-set g_balance_blaster_weaponreplace ""
-set g_balance_blaster_weaponstart 1
-set g_balance_blaster_weaponstartoverride -1
-set g_balance_blaster_weaponthrowable 0
-// }}}
-// {{{ #2: Shotgun
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_animtime 0.2
-set g_balance_shotgun_primary_bullets 14
-set g_balance_shotgun_primary_damage 4
-set g_balance_shotgun_primary_force 15
-set g_balance_shotgun_primary_refire 0.75
-set g_balance_shotgun_primary_solidpenetration 3.8
-set g_balance_shotgun_primary_spread 0.12
-set g_balance_shotgun_reload_ammo 0
-set g_balance_shotgun_reload_time 2
-set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_animtime 1
-set g_balance_shotgun_secondary_damage 80
-set g_balance_shotgun_secondary_force 200
-set g_balance_shotgun_secondary_melee_delay 0.25
-set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_melee_nonplayerdamage 40
-set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing_side 120
-set g_balance_shotgun_secondary_melee_swing_up 30
-set g_balance_shotgun_secondary_melee_time 0.15
-set g_balance_shotgun_secondary_melee_traces 10
-set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_switchdelay_drop 0.2
-set g_balance_shotgun_switchdelay_raise 0.2
-set g_balance_shotgun_weaponreplace ""
-set g_balance_shotgun_weaponstart 1
-set g_balance_shotgun_weaponstartoverride -1
-set g_balance_shotgun_weaponthrowable 1
-// }}}
-// {{{ #3: Machine Gun
-set g_balance_machinegun_burst 3
-set g_balance_machinegun_burst_ammo 3
-set g_balance_machinegun_burst_animtime 0.3
-set g_balance_machinegun_burst_refire 0.06
-set g_balance_machinegun_burst_refire2 0.45
-set g_balance_machinegun_burst_speed 0
-set g_balance_machinegun_first 1
-set g_balance_machinegun_first_ammo 1
-set g_balance_machinegun_first_damage 14
-set g_balance_machinegun_first_force 5
-set g_balance_machinegun_first_refire 0.125
-set g_balance_machinegun_first_spread 0.03
-set g_balance_machinegun_mode 1
-set g_balance_machinegun_reload_ammo 60
-set g_balance_machinegun_reload_time 2
-set g_balance_machinegun_solidpenetration 13.1
-set g_balance_machinegun_spread_add 0.012
-set g_balance_machinegun_spread_max 0.05
-set g_balance_machinegun_spread_min 0.02
-set g_balance_machinegun_sustained_ammo 1
-set g_balance_machinegun_sustained_damage 10
-set g_balance_machinegun_sustained_force 5
-set g_balance_machinegun_sustained_refire 0.1
-set g_balance_machinegun_sustained_spread 0.03
-set g_balance_machinegun_switchdelay_drop 0.2
-set g_balance_machinegun_switchdelay_raise 0.2
-set g_balance_machinegun_weaponreplace "arc machinegun"
-set g_balance_machinegun_weaponstart 0
-set g_balance_machinegun_weaponstartoverride -1
-set g_balance_machinegun_weaponthrowable 1
-// }}}
-// {{{ #4: Mortar
-set g_balance_mortar_bouncefactor 0.5
-set g_balance_mortar_bouncestop 0.075
-set g_balance_mortar_primary_ammo 2
-set g_balance_mortar_primary_animtime 0.3
-set g_balance_mortar_primary_damage 50
-set g_balance_mortar_primary_damageforcescale 0
-set g_balance_mortar_primary_edgedamage 25
-set g_balance_mortar_primary_force 250
-set g_balance_mortar_primary_health 15
-set g_balance_mortar_primary_lifetime 5
-set g_balance_mortar_primary_lifetime_stick 0
-set g_balance_mortar_primary_radius 120
-set g_balance_mortar_primary_refire 0.8
-set g_balance_mortar_primary_remote_minbouncecnt 0
-set g_balance_mortar_primary_speed 1900
-set g_balance_mortar_primary_speed_up 225
-set g_balance_mortar_primary_speed_z 0
-set g_balance_mortar_primary_spread 0
-set g_balance_mortar_primary_type 0
-set g_balance_mortar_reload_ammo 0
-set g_balance_mortar_reload_time 2
-set g_balance_mortar_secondary_ammo 2
-set g_balance_mortar_secondary_animtime 0.3
-set g_balance_mortar_secondary_damage 55
-set g_balance_mortar_secondary_damageforcescale 4
-set g_balance_mortar_secondary_edgedamage 30
-set g_balance_mortar_secondary_force 250
-set g_balance_mortar_secondary_health 30
-set g_balance_mortar_secondary_lifetime 5
-set g_balance_mortar_secondary_lifetime_bounce 0.5
-set g_balance_mortar_secondary_lifetime_stick 0
-set g_balance_mortar_secondary_radius 120
-set g_balance_mortar_secondary_refire 0.7
-set g_balance_mortar_secondary_remote_detonateprimary 0
-set g_balance_mortar_secondary_speed 1400
-set g_balance_mortar_secondary_speed_up 150
-set g_balance_mortar_secondary_speed_z 0
-set g_balance_mortar_secondary_spread 0
-set g_balance_mortar_secondary_type 1
-set g_balance_mortar_switchdelay_drop 0.2
-set g_balance_mortar_switchdelay_raise 0.2
-set g_balance_mortar_weaponreplace ""
-set g_balance_mortar_weaponstart 0
-set g_balance_mortar_weaponstartoverride -1
-set g_balance_mortar_weaponthrowable 1
-// }}}
-// {{{ #5: Mine Layer (MUTATOR WEAPON)
-set g_balance_minelayer_ammo 4
-set g_balance_minelayer_animtime 0.4
-set g_balance_minelayer_damage 40
-set g_balance_minelayer_damageforcescale 0
-set g_balance_minelayer_detonatedelay -1
-set g_balance_minelayer_edgedamage 20
-set g_balance_minelayer_force 250
-set g_balance_minelayer_health 15
-set g_balance_minelayer_lifetime 10
-set g_balance_minelayer_lifetime_countdown 0.5
-set g_balance_minelayer_limit 3
-set g_balance_minelayer_protection 0
-set g_balance_minelayer_proximityradius 150
-set g_balance_minelayer_radius 175
-set g_balance_minelayer_refire 1.5
-set g_balance_minelayer_reload_ammo 0
-set g_balance_minelayer_reload_time 2
-set g_balance_minelayer_remote_damage 45
-set g_balance_minelayer_remote_edgedamage 40
-set g_balance_minelayer_remote_force 300
-set g_balance_minelayer_remote_radius 200
-set g_balance_minelayer_speed 1000
-set g_balance_minelayer_switchdelay_drop 0.2
-set g_balance_minelayer_switchdelay_raise 0.2
-set g_balance_minelayer_time 0.5
-set g_balance_minelayer_weaponreplace ""
-set g_balance_minelayer_weaponstart 0
-set g_balance_minelayer_weaponstartoverride -1
-set g_balance_minelayer_weaponthrowable 1
-// }}}
-// {{{ #6: Electro
-set g_balance_electro_combo_comboradius 250
-set g_balance_electro_combo_comboradius_thruwall 200
-set g_balance_electro_combo_damage 50
-set g_balance_electro_combo_edgedamage 25
-set g_balance_electro_combo_force 120
-set g_balance_electro_combo_radius 100
-set g_balance_electro_combo_safeammocheck 1
-set g_balance_electro_combo_speed 2000
-set g_balance_electro_primary_ammo 4
-set g_balance_electro_primary_animtime 0.3
-set g_balance_electro_primary_comboradius 300
-set g_balance_electro_primary_damage 40
-set g_balance_electro_primary_edgedamage 20
-set g_balance_electro_primary_force 200
-set g_balance_electro_primary_lifetime 5
-set g_balance_electro_primary_midaircombo_explode 1
-set g_balance_electro_primary_midaircombo_interval 0.1
-set g_balance_electro_primary_midaircombo_radius 100
-set g_balance_electro_primary_radius 100
-set g_balance_electro_primary_refire 0.6
-set g_balance_electro_primary_speed 2500
-set g_balance_electro_primary_spread 0
-set g_balance_electro_reload_ammo 0
-set g_balance_electro_reload_time 2
-set g_balance_electro_secondary_ammo 2
-set g_balance_electro_secondary_animtime 0.2
-set g_balance_electro_secondary_bouncefactor 0.3
-set g_balance_electro_secondary_bouncestop 0.05
-set g_balance_electro_secondary_count 3
-set g_balance_electro_secondary_damage 40
-set g_balance_electro_secondary_damagedbycontents 1
-set g_balance_electro_secondary_damageforcescale 4
-set g_balance_electro_secondary_edgedamage 20
-set g_balance_electro_secondary_force 50
-set g_balance_electro_secondary_health 5
-set g_balance_electro_secondary_lifetime 4
-set g_balance_electro_secondary_radius 150
-set g_balance_electro_secondary_refire 0.2
-set g_balance_electro_secondary_refire2 1.6
-set g_balance_electro_secondary_speed 1000
-set g_balance_electro_secondary_speed_up 200
-set g_balance_electro_secondary_speed_z 0
-set g_balance_electro_secondary_spread 0.04
-set g_balance_electro_secondary_touchexplode 0
-set g_balance_electro_switchdelay_drop 0.2
-set g_balance_electro_switchdelay_raise 0.2
-set g_balance_electro_weaponreplace ""
-set g_balance_electro_weaponstart 0
-set g_balance_electro_weaponstartoverride -1
-set g_balance_electro_weaponthrowable 1
-// }}}
-// {{{ #7: Crylink
-set g_balance_crylink_primary_ammo 3
-set g_balance_crylink_primary_animtime 0.3
-set g_balance_crylink_primary_bouncedamagefactor 0.5
-set g_balance_crylink_primary_bounces 1
-set g_balance_crylink_primary_damage 12
-set g_balance_crylink_primary_edgedamage 6
-set g_balance_crylink_primary_force -60
-set g_balance_crylink_primary_joindelay 0.1
-set g_balance_crylink_primary_joinexplode 1
-set g_balance_crylink_primary_joinexplode_damage 0
-set g_balance_crylink_primary_joinexplode_edgedamage 0
-set g_balance_crylink_primary_joinexplode_force 0
-set g_balance_crylink_primary_joinexplode_radius 0
-set g_balance_crylink_primary_joinspread 0.2
-set g_balance_crylink_primary_linkexplode 1
-set g_balance_crylink_primary_middle_fadetime 5
-set g_balance_crylink_primary_middle_lifetime 5
-set g_balance_crylink_primary_other_fadetime 5
-set g_balance_crylink_primary_other_lifetime 5
-set g_balance_crylink_primary_radius 80
-set g_balance_crylink_primary_refire 0.7
-set g_balance_crylink_primary_shots 6
-set g_balance_crylink_primary_speed 2000
-set g_balance_crylink_primary_spread 0.08
-set g_balance_crylink_reload_ammo 0
-set g_balance_crylink_reload_time 2
-set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_ammo 2
-set g_balance_crylink_secondary_animtime 0.2
-set g_balance_crylink_secondary_bouncedamagefactor 0.5
-set g_balance_crylink_secondary_bounces 1
-set g_balance_crylink_secondary_damage 5
-set g_balance_crylink_secondary_edgedamage 0
-set g_balance_crylink_secondary_force -40
-set g_balance_crylink_secondary_joindelay 0
-set g_balance_crylink_secondary_joinexplode 0
-set g_balance_crylink_secondary_joinexplode_damage 0
-set g_balance_crylink_secondary_joinexplode_edgedamage 0
-set g_balance_crylink_secondary_joinexplode_force 0
-set g_balance_crylink_secondary_joinexplode_radius 0
-set g_balance_crylink_secondary_joinspread 0
-set g_balance_crylink_secondary_linkexplode 1
-set g_balance_crylink_secondary_middle_fadetime 5
-set g_balance_crylink_secondary_middle_lifetime 5
-set g_balance_crylink_secondary_other_fadetime 5
-set g_balance_crylink_secondary_other_lifetime 5
-set g_balance_crylink_secondary_radius 70
-set g_balance_crylink_secondary_refire 0.2
-set g_balance_crylink_secondary_shots 3
-set g_balance_crylink_secondary_speed 2000
-set g_balance_crylink_secondary_spread 0.02
-set g_balance_crylink_secondary_spreadtype 1
-set g_balance_crylink_switchdelay_drop 0.2
-set g_balance_crylink_switchdelay_raise 0.2
-set g_balance_crylink_weaponreplace ""
-set g_balance_crylink_weaponstart 0
-set g_balance_crylink_weaponstartoverride -1
-set g_balance_crylink_weaponthrowable 1
-// }}}
-// {{{ #8: Vortex
-set g_balance_vortex_charge 1
-set g_balance_vortex_charge_animlimit 0.5
-set g_balance_vortex_charge_limit 1
-set g_balance_vortex_charge_maxspeed 800
-set g_balance_vortex_charge_mindmg 40
-set g_balance_vortex_charge_minspeed 400
-set g_balance_vortex_charge_rate 0.4
-set g_balance_vortex_charge_rot_pause 0
-set g_balance_vortex_charge_rot_rate 0
-set g_balance_vortex_charge_shot_multiplier 0
-set g_balance_vortex_charge_start 0.5
-set g_balance_vortex_charge_velocity_rate 0
-set g_balance_vortex_primary_ammo 6
-set g_balance_vortex_primary_animtime 0.4
-set g_balance_vortex_primary_damage 90
-set g_balance_vortex_primary_damagefalloff_forcehalflife 0
-set g_balance_vortex_primary_damagefalloff_halflife 0
-set g_balance_vortex_primary_damagefalloff_maxdist 0
-set g_balance_vortex_primary_damagefalloff_mindist 0
-set g_balance_vortex_primary_force 400
-set g_balance_vortex_primary_refire 1.5
-set g_balance_vortex_reload_ammo 0
-set g_balance_vortex_reload_time 2
-set g_balance_vortex_secondary 0
-set g_balance_vortex_secondary_ammo 2
-set g_balance_vortex_secondary_animtime 0
-set g_balance_vortex_secondary_chargepool 0
-set g_balance_vortex_secondary_chargepool_pause_regen 1
-set g_balance_vortex_secondary_chargepool_regen 0.15
-set g_balance_vortex_secondary_damage 0
-set g_balance_vortex_secondary_damagefalloff_forcehalflife 0
-set g_balance_vortex_secondary_damagefalloff_halflife 0
-set g_balance_vortex_secondary_damagefalloff_maxdist 0
-set g_balance_vortex_secondary_damagefalloff_mindist 0
-set g_balance_vortex_secondary_force 0
-set g_balance_vortex_secondary_refire 0
-set g_balance_vortex_switchdelay_drop 0.25
-set g_balance_vortex_switchdelay_raise 0.25
-set g_balance_vortex_weaponreplace ""
-set g_balance_vortex_weaponstart 0
-set g_balance_vortex_weaponstartoverride -1
-set g_balance_vortex_weaponthrowable 1
-// }}}
-// {{{ #9: Hagar
-set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_primary_damage 25
-set g_balance_hagar_primary_damageforcescale 0
-set g_balance_hagar_primary_edgedamage 12.5
-set g_balance_hagar_primary_force 100
-set g_balance_hagar_primary_health 15
-set g_balance_hagar_primary_lifetime 5
-set g_balance_hagar_primary_radius 65
-set g_balance_hagar_primary_refire 0.16667
-set g_balance_hagar_primary_speed 2200
-set g_balance_hagar_primary_spread 0.03
-set g_balance_hagar_reload_ammo 0
-set g_balance_hagar_reload_time 2
-set g_balance_hagar_secondary 1
-set g_balance_hagar_secondary_ammo 1
-set g_balance_hagar_secondary_damage 40
-set g_balance_hagar_secondary_damageforcescale 0
-set g_balance_hagar_secondary_edgedamage 20
-set g_balance_hagar_secondary_force 75
-set g_balance_hagar_secondary_health 15
-set g_balance_hagar_secondary_lifetime_min 10
-set g_balance_hagar_secondary_lifetime_rand 0
-set g_balance_hagar_secondary_load 1
-set g_balance_hagar_secondary_load_abort 1
-set g_balance_hagar_secondary_load_animtime 0.2
-set g_balance_hagar_secondary_load_hold 4
-set g_balance_hagar_secondary_load_linkexplode 0
-set g_balance_hagar_secondary_load_max 4
-set g_balance_hagar_secondary_load_releasedeath 0
-set g_balance_hagar_secondary_load_speed 0.5
-set g_balance_hagar_secondary_load_spread 0.075
-set g_balance_hagar_secondary_load_spread_bias 0.5
-set g_balance_hagar_secondary_radius 80
-set g_balance_hagar_secondary_refire 0.5
-set g_balance_hagar_secondary_speed 2000
-set g_balance_hagar_secondary_spread 0.05
-set g_balance_hagar_switchdelay_drop 0.2
-set g_balance_hagar_switchdelay_raise 0.2
-set g_balance_hagar_weaponreplace ""
-set g_balance_hagar_weaponstart 0
-set g_balance_hagar_weaponstartoverride -1
-set g_balance_hagar_weaponthrowable 1
-// }}}
-// {{{ #10: Devastator
-set g_balance_devastator_ammo 4
-set g_balance_devastator_animtime 0.4
-set g_balance_devastator_damage 80
-set g_balance_devastator_damageforcescale 1
-set g_balance_devastator_detonatedelay 0.02
-set g_balance_devastator_edgedamage 40
-set g_balance_devastator_force 400
-set g_balance_devastator_guidedelay 0.2
-set g_balance_devastator_guidegoal 512
-set g_balance_devastator_guiderate 90
-set g_balance_devastator_guideratedelay 0.01
-set g_balance_devastator_guidestop 0
-set g_balance_devastator_health 30
-set g_balance_devastator_lifetime 10
-set g_balance_devastator_radius 110
-set g_balance_devastator_refire 1.1
-set g_balance_devastator_reload_ammo 0
-set g_balance_devastator_reload_time 2
-set g_balance_devastator_remote_damage 70
-set g_balance_devastator_remote_edgedamage 35
-set g_balance_devastator_remote_force 400
-set g_balance_devastator_remote_jump_damage 70
-set g_balance_devastator_remote_jump_radius 0
-set g_balance_devastator_remote_jump_velocity_z_add 400
-set g_balance_devastator_remote_jump_velocity_z_max 1500
-set g_balance_devastator_remote_jump_velocity_z_min 400
-set g_balance_devastator_remote_radius 110
-set g_balance_devastator_speed 1300
-set g_balance_devastator_speedaccel 1300
-set g_balance_devastator_speedstart 1000
-set g_balance_devastator_switchdelay_drop 0.2
-set g_balance_devastator_switchdelay_raise 0.2
-set g_balance_devastator_weaponreplace ""
-set g_balance_devastator_weaponstart 0
-set g_balance_devastator_weaponstartoverride -1
-set g_balance_devastator_weaponthrowable 1
-// }}}
-// {{{ #11: Port-O-Launch
-set g_balance_porto_primary_animtime 0.3
-set g_balance_porto_primary_lifetime 5
-set g_balance_porto_primary_refire 1.5
-set g_balance_porto_primary_speed 1000
-set g_balance_porto_secondary 1
-set g_balance_porto_secondary_animtime 0.3
-set g_balance_porto_secondary_lifetime 5
-set g_balance_porto_secondary_refire 1.5
-set g_balance_porto_secondary_speed 1000
-set g_balance_porto_switchdelay_drop 0.2
-set g_balance_porto_switchdelay_raise 0.2
-set g_balance_porto_weaponreplace ""
-set g_balance_porto_weaponstart 0
-set g_balance_porto_weaponstartoverride -1
-set g_balance_porto_weaponthrowable 1
-// }}}
-// {{{ #12: Vaporizer
-set g_balance_vaporizer_primary_ammo 10
-set g_balance_vaporizer_primary_animtime 0.3
-set g_balance_vaporizer_primary_refire 1
-set g_balance_vaporizer_reload_ammo 0
-set g_balance_vaporizer_reload_time 0
-set g_balance_vaporizer_secondary_ammo 0
-set g_balance_vaporizer_secondary_animtime 0.2
-set g_balance_vaporizer_secondary_damage 25
-set g_balance_vaporizer_secondary_delay 0
-set g_balance_vaporizer_secondary_edgedamage 12.5
-set g_balance_vaporizer_secondary_force 400
-set g_balance_vaporizer_secondary_lifetime 5
-set g_balance_vaporizer_secondary_radius 70
-set g_balance_vaporizer_secondary_refire 0.7
-set g_balance_vaporizer_secondary_shotangle 0
-set g_balance_vaporizer_secondary_speed 6000
-set g_balance_vaporizer_secondary_spread 0
-set g_balance_vaporizer_switchdelay_drop 0.2
-set g_balance_vaporizer_switchdelay_raise 0.2
-set g_balance_vaporizer_weaponreplace ""
-set g_balance_vaporizer_weaponstart 0
-set g_balance_vaporizer_weaponstartoverride -1
-set g_balance_vaporizer_weaponthrowable 0
-// }}}
-// {{{ #13: Grappling Hook
-set g_balance_hook_primary_ammo 5
-set g_balance_hook_primary_animtime 0.3
-set g_balance_hook_primary_hooked_ammo 5
-set g_balance_hook_primary_hooked_time_free 2
-set g_balance_hook_primary_hooked_time_max 0
-set g_balance_hook_primary_refire 0.2
-set g_balance_hook_secondary_animtime 0.3
-set g_balance_hook_secondary_damage 25
-set g_balance_hook_secondary_damageforcescale 0
-set g_balance_hook_secondary_duration 1.5
-set g_balance_hook_secondary_edgedamage 5
-set g_balance_hook_secondary_force -2000
-set g_balance_hook_secondary_gravity 5
-set g_balance_hook_secondary_health 15
-set g_balance_hook_secondary_lifetime 5
-set g_balance_hook_secondary_power 3
-set g_balance_hook_secondary_radius 500
-set g_balance_hook_secondary_refire 3
-set g_balance_hook_secondary_speed 0
-set g_balance_hook_switchdelay_drop 0.2
-set g_balance_hook_switchdelay_raise 0.2
-set g_balance_hook_weaponreplace ""
-set g_balance_hook_weaponstart 0
-set g_balance_hook_weaponstartoverride -1
-set g_balance_hook_weaponthrowable 1
-// }}}
-// {{{ #14: Heavy Laser Assault Cannon (MUTATOR WEAPON)
-set g_balance_hlac_primary_ammo 1
-set g_balance_hlac_primary_animtime 0.4
-set g_balance_hlac_primary_damage 18
-set g_balance_hlac_primary_edgedamage 9
-set g_balance_hlac_primary_force 90
-set g_balance_hlac_primary_lifetime 5
-set g_balance_hlac_primary_radius 70
-set g_balance_hlac_primary_refire 0.15
-set g_balance_hlac_primary_speed 9000
-set g_balance_hlac_primary_spread_add 0.0045
-set g_balance_hlac_primary_spread_crouchmod 0.25
-set g_balance_hlac_primary_spread_max 0.25
-set g_balance_hlac_primary_spread_min 0.01
-set g_balance_hlac_reload_ammo 0
-set g_balance_hlac_reload_time 2
-set g_balance_hlac_secondary 1
-set g_balance_hlac_secondary_ammo 10
-set g_balance_hlac_secondary_animtime 0.3
-set g_balance_hlac_secondary_damage 15
-set g_balance_hlac_secondary_edgedamage 7.5
-set g_balance_hlac_secondary_force 90
-set g_balance_hlac_secondary_lifetime 5
-set g_balance_hlac_secondary_radius 70
-set g_balance_hlac_secondary_refire 1
-set g_balance_hlac_secondary_shots 6
-set g_balance_hlac_secondary_speed 9000
-set g_balance_hlac_secondary_spread 0.15
-set g_balance_hlac_secondary_spread_crouchmod 0.5
-set g_balance_hlac_switchdelay_drop 0.2
-set g_balance_hlac_switchdelay_raise 0.2
-set g_balance_hlac_weaponreplace ""
-set g_balance_hlac_weaponstart 0
-set g_balance_hlac_weaponstartoverride -1
-set g_balance_hlac_weaponthrowable 1
-// }}}
-// {{{ #15: @!#%'n Tuba
-set g_balance_tuba_animtime 0.05
-set g_balance_tuba_attenuation 0.5
-set g_balance_tuba_damage 5
-set g_balance_tuba_edgedamage 0
-set g_balance_tuba_force 40
-set g_balance_tuba_radius 200
-set g_balance_tuba_refire 0.05
-set g_balance_tuba_switchdelay_drop 0.2
-set g_balance_tuba_switchdelay_raise 0.2
-set g_balance_tuba_weaponreplace ""
-set g_balance_tuba_weaponstart 0
-set g_balance_tuba_weaponstartoverride -1
-set g_balance_tuba_weaponthrowable 1
-// }}}
-// {{{ #16: Rifle (MUTATOR WEAPON)
-set g_balance_rifle_bursttime 0
-set g_balance_rifle_primary_ammo 10
-set g_balance_rifle_primary_animtime 0.4
-set g_balance_rifle_primary_bullethail 0
-set g_balance_rifle_primary_burstcost 0
-set g_balance_rifle_primary_damage 80
-set g_balance_rifle_primary_force 100
-set g_balance_rifle_primary_refire 1.2
-set g_balance_rifle_primary_shots 1
-set g_balance_rifle_primary_solidpenetration 62.2
-set g_balance_rifle_primary_spread 0
-set g_balance_rifle_primary_tracer 1
-set g_balance_rifle_reload_ammo 80
-set g_balance_rifle_reload_time 2
-set g_balance_rifle_secondary 1
-set g_balance_rifle_secondary_ammo 10
-set g_balance_rifle_secondary_animtime 0.3
-set g_balance_rifle_secondary_bullethail 0
-set g_balance_rifle_secondary_burstcost 0
-set g_balance_rifle_secondary_damage 20
-set g_balance_rifle_secondary_force 50
-set g_balance_rifle_secondary_refire 0.9
-set g_balance_rifle_secondary_reload 0
-set g_balance_rifle_secondary_shots 4
-set g_balance_rifle_secondary_solidpenetration 15.5
-set g_balance_rifle_secondary_spread 0.04
-set g_balance_rifle_secondary_tracer 0
-set g_balance_rifle_switchdelay_drop 0.2
-set g_balance_rifle_switchdelay_raise 0.2
-set g_balance_rifle_weaponreplace ""
-set g_balance_rifle_weaponstart 0
-set g_balance_rifle_weaponstartoverride -1
-set g_balance_rifle_weaponthrowable 1
-// }}}
-// {{{ #17: Fireball
-set g_balance_fireball_primary_animtime 0.4
-set g_balance_fireball_primary_bfgdamage 100
-set g_balance_fireball_primary_bfgforce 0
-set g_balance_fireball_primary_bfgradius 1000
-set g_balance_fireball_primary_damage 200
-set g_balance_fireball_primary_damageforcescale 0
-set g_balance_fireball_primary_edgedamage 50
-set g_balance_fireball_primary_force 600
-set g_balance_fireball_primary_health 0
-set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 80
-set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 256
-set g_balance_fireball_primary_lifetime 15
-set g_balance_fireball_primary_radius 200
-set g_balance_fireball_primary_refire 2
-set g_balance_fireball_primary_refire2 0
-set g_balance_fireball_primary_speed 1200
-set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_animtime 0.3
-set g_balance_fireball_secondary_damage 40
-set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_damagetime 5
-set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 50
-set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 110
-set g_balance_fireball_secondary_lifetime 7
-set g_balance_fireball_secondary_refire 1.5
-set g_balance_fireball_secondary_speed 900
-set g_balance_fireball_secondary_speed_up 100
-set g_balance_fireball_secondary_speed_z 0
-set g_balance_fireball_secondary_spread 0
-set g_balance_fireball_switchdelay_drop 0.2
-set g_balance_fireball_switchdelay_raise 0.2
-set g_balance_fireball_weaponreplace ""
-set g_balance_fireball_weaponstart 0
-set g_balance_fireball_weaponstartoverride -1
-set g_balance_fireball_weaponthrowable 0
-// }}}
-// {{{ #18: T.A.G. Seeker (MUTATOR WEAPON)
-set g_balance_seeker_flac_ammo 1
-set g_balance_seeker_flac_animtime 0.1
-set g_balance_seeker_flac_damage 15
-set g_balance_seeker_flac_edgedamage 10
-set g_balance_seeker_flac_force 50
-set g_balance_seeker_flac_lifetime 0.1
-set g_balance_seeker_flac_lifetime_rand 0.05
-set g_balance_seeker_flac_radius 100
-set g_balance_seeker_flac_refire 0.1
-set g_balance_seeker_flac_speed 3000
-set g_balance_seeker_flac_speed_up 1000
-set g_balance_seeker_flac_speed_z 0
-set g_balance_seeker_flac_spread 0.4
-set g_balance_seeker_missile_accel 1400
-set g_balance_seeker_missile_ammo 2
-set g_balance_seeker_missile_animtime 0.2
-set g_balance_seeker_missile_count 3
-set g_balance_seeker_missile_damage 30
-set g_balance_seeker_missile_damageforcescale 4
-set g_balance_seeker_missile_decel 1400
-set g_balance_seeker_missile_delay 0.25
-set g_balance_seeker_missile_edgedamage 10
-set g_balance_seeker_missile_force 150
-set g_balance_seeker_missile_health 5
-set g_balance_seeker_missile_lifetime 15
-set g_balance_seeker_missile_proxy 0
-set g_balance_seeker_missile_proxy_delay 0.2
-set g_balance_seeker_missile_proxy_maxrange 45
-set g_balance_seeker_missile_radius 80
-set g_balance_seeker_missile_refire 0.5
-set g_balance_seeker_missile_smart 1
-set g_balance_seeker_missile_smart_mindist 800
-set g_balance_seeker_missile_smart_trace_max 2500
-set g_balance_seeker_missile_smart_trace_min 1000
-set g_balance_seeker_missile_speed 700
-set g_balance_seeker_missile_speed_max 1300
-set g_balance_seeker_missile_speed_up 300
-set g_balance_seeker_missile_speed_z 0
-set g_balance_seeker_missile_spread 0
-set g_balance_seeker_missile_turnrate 0.65
-set g_balance_seeker_reload_ammo 0
-set g_balance_seeker_reload_time 2
-set g_balance_seeker_switchdelay_drop 0.2
-set g_balance_seeker_switchdelay_raise 0.2
-set g_balance_seeker_tag_ammo 1
-set g_balance_seeker_tag_animtime 0.2
-set g_balance_seeker_tag_damageforcescale 4
-set g_balance_seeker_tag_health 5
-set g_balance_seeker_tag_lifetime 15
-set g_balance_seeker_tag_refire 0.75
-set g_balance_seeker_tag_speed 5000
-set g_balance_seeker_tag_spread 0
-set g_balance_seeker_tag_tracker_lifetime 10
-set g_balance_seeker_type 0
-set g_balance_seeker_weaponreplace ""
-set g_balance_seeker_weaponstart 0
-set g_balance_seeker_weaponstartoverride -1
-set g_balance_seeker_weaponthrowable 1
-// }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
-set g_balance_shockwave_blast_animtime 0.3
-set g_balance_shockwave_blast_damage 20
-set g_balance_shockwave_blast_distance 1000
-set g_balance_shockwave_blast_edgedamage 0
-set g_balance_shockwave_blast_force 200
-set g_balance_shockwave_blast_force_forwardbias 50
-set g_balance_shockwave_blast_force_zscale 2
-set g_balance_shockwave_blast_jump_damage 20
-set g_balance_shockwave_blast_jump_edgedamage 0
-set g_balance_shockwave_blast_jump_force 300
-set g_balance_shockwave_blast_jump_force_velocitybias 0
-set g_balance_shockwave_blast_jump_force_zscale 1.25
-set g_balance_shockwave_blast_jump_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_jump_multiplier_distance 0.5
-set g_balance_shockwave_blast_jump_multiplier_min 0
-set g_balance_shockwave_blast_jump_radius 150
-set g_balance_shockwave_blast_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_multiplier_distance 0.5
-set g_balance_shockwave_blast_multiplier_min 0
-set g_balance_shockwave_blast_refire 0.75
-set g_balance_shockwave_blast_splash_damage 15
-set g_balance_shockwave_blast_splash_edgedamage 0
-set g_balance_shockwave_blast_splash_force 100
-set g_balance_shockwave_blast_splash_force_forwardbias 50
-set g_balance_shockwave_blast_splash_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_splash_multiplier_distance 0.5
-set g_balance_shockwave_blast_splash_multiplier_min 0
-set g_balance_shockwave_blast_splash_radius 70
-set g_balance_shockwave_blast_spread_max 120
-set g_balance_shockwave_blast_spread_min 25
-set g_balance_shockwave_melee_animtime 1.3
-set g_balance_shockwave_melee_damage 80
-set g_balance_shockwave_melee_delay 0.25
-set g_balance_shockwave_melee_force 200
-set g_balance_shockwave_melee_multihit 1
-set g_balance_shockwave_melee_no_doubleslap 1
-set g_balance_shockwave_melee_nonplayerdamage 40
-set g_balance_shockwave_melee_range 120
-set g_balance_shockwave_melee_refire 1.25
-set g_balance_shockwave_melee_swing_side 120
-set g_balance_shockwave_melee_swing_up 30
-set g_balance_shockwave_melee_time 0.15
-set g_balance_shockwave_melee_traces 10
-set g_balance_shockwave_switchdelay_drop 0.2
-set g_balance_shockwave_switchdelay_raise 0.2
-set g_balance_shockwave_weaponreplace ""
-set g_balance_shockwave_weaponstart 1
-set g_balance_shockwave_weaponstartoverride -1
-set g_balance_shockwave_weaponthrowable 0
-// }}}
-// {{{ #20: Arc
-set g_balance_arc_beam_ammo 4
-set g_balance_arc_beam_animtime 0.2
-set g_balance_arc_beam_botaimlifetime 0
-set g_balance_arc_beam_botaimspeed 0
-set g_balance_arc_beam_damage 115
-set g_balance_arc_beam_degreespersegment 1
-set g_balance_arc_beam_distancepersegment 0
-set g_balance_arc_beam_falloff_halflifedist 0
-set g_balance_arc_beam_falloff_maxdist 0
-set g_balance_arc_beam_falloff_mindist 0
-set g_balance_arc_beam_force 900
-set g_balance_arc_beam_healing_amax 200
-set g_balance_arc_beam_healing_aps 50
-set g_balance_arc_beam_healing_hmax 200
-set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_beam_maxangle 10
-set g_balance_arc_beam_nonplayerdamage 80
-set g_balance_arc_beam_range 1000
-set g_balance_arc_beam_refire 0.5
-set g_balance_arc_beam_returnspeed 8
-set g_balance_arc_beam_tightness 0.5
-set g_balance_arc_burst_ammo 15
-set g_balance_arc_burst_damage 500
-set g_balance_arc_burst_healing_aps 100
-set g_balance_arc_burst_healing_hps 100
-set g_balance_arc_switchdelay_drop 0.3
-set g_balance_arc_switchdelay_raise 0.3
-set g_balance_arc_weaponreplace ""
-set g_balance_arc_weaponstart 0
-set g_balance_arc_weaponstartoverride -1
-set g_balance_arc_weaponthrowable 1
-// }}}
diff --git a/bal-wep-xonotic.cfg b/bal-wep-xonotic.cfg
deleted file mode 100644
index 867e9932d..000000000
--- a/bal-wep-xonotic.cfg
+++ /dev/null
@@ -1,753 +0,0 @@
-// {{{ #1: Blaster
-set g_balance_blaster_primary_animtime 0.2
-set g_balance_blaster_primary_damage 25
-set g_balance_blaster_primary_delay 0
-set g_balance_blaster_primary_edgedamage 12.5
-set g_balance_blaster_primary_force 300
-set g_balance_blaster_primary_force_zscale 1.2
-set g_balance_blaster_primary_lifetime 5
-set g_balance_blaster_primary_radius 70
-set g_balance_blaster_primary_refire 0.7
-set g_balance_blaster_primary_shotangle 0
-set g_balance_blaster_primary_speed 6000
-set g_balance_blaster_primary_spread 0
-set g_balance_blaster_secondary 0
-set g_balance_blaster_secondary_animtime 0.2
-set g_balance_blaster_secondary_damage 25
-set g_balance_blaster_secondary_delay 0
-set g_balance_blaster_secondary_edgedamage 12.5
-set g_balance_blaster_secondary_force 300
-set g_balance_blaster_secondary_force_zscale 1.2
-set g_balance_blaster_secondary_lifetime 5
-set g_balance_blaster_secondary_radius 70
-set g_balance_blaster_secondary_refire 0.7
-set g_balance_blaster_secondary_shotangle 0
-set g_balance_blaster_secondary_speed 6000
-set g_balance_blaster_secondary_spread 0
-set g_balance_blaster_switchdelay_drop 0.15
-set g_balance_blaster_switchdelay_raise 0.15
-set g_balance_blaster_weaponreplace ""
-set g_balance_blaster_weaponstart 1
-set g_balance_blaster_weaponstartoverride -1
-set g_balance_blaster_weaponthrowable 0
-// }}}
-// {{{ #2: Shotgun
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_animtime 0.2
-set g_balance_shotgun_primary_bullets 14
-set g_balance_shotgun_primary_damage 4
-set g_balance_shotgun_primary_force 15
-set g_balance_shotgun_primary_refire 0.75
-set g_balance_shotgun_primary_solidpenetration 3.8
-set g_balance_shotgun_primary_spread 0.12
-set g_balance_shotgun_reload_ammo 0
-set g_balance_shotgun_reload_time 2
-set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_animtime 1
-set g_balance_shotgun_secondary_damage 80
-set g_balance_shotgun_secondary_force 200
-set g_balance_shotgun_secondary_melee_delay 0.25
-set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_melee_nonplayerdamage 40
-set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing_side 120
-set g_balance_shotgun_secondary_melee_swing_up 30
-set g_balance_shotgun_secondary_melee_time 0.15
-set g_balance_shotgun_secondary_melee_traces 10
-set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_switchdelay_drop 0.2
-set g_balance_shotgun_switchdelay_raise 0.2
-set g_balance_shotgun_weaponreplace ""
-set g_balance_shotgun_weaponstart 1
-set g_balance_shotgun_weaponstartoverride -1
-set g_balance_shotgun_weaponthrowable 1
-// }}}
-// {{{ #3: Machine Gun
-set g_balance_machinegun_burst 3
-set g_balance_machinegun_burst_ammo 3
-set g_balance_machinegun_burst_animtime 0.3
-set g_balance_machinegun_burst_refire 0.06
-set g_balance_machinegun_burst_refire2 0.45
-set g_balance_machinegun_burst_speed 0
-set g_balance_machinegun_first 1
-set g_balance_machinegun_first_ammo 1
-set g_balance_machinegun_first_damage 14
-set g_balance_machinegun_first_force 5
-set g_balance_machinegun_first_refire 0.125
-set g_balance_machinegun_first_spread 0.03
-set g_balance_machinegun_mode 1
-set g_balance_machinegun_reload_ammo 60
-set g_balance_machinegun_reload_time 2
-set g_balance_machinegun_solidpenetration 13.1
-set g_balance_machinegun_spread_add 0.012
-set g_balance_machinegun_spread_max 0.05
-set g_balance_machinegun_spread_min 0.02
-set g_balance_machinegun_sustained_ammo 1
-set g_balance_machinegun_sustained_damage 10
-set g_balance_machinegun_sustained_force 5
-set g_balance_machinegun_sustained_refire 0.1
-set g_balance_machinegun_sustained_spread 0.03
-set g_balance_machinegun_switchdelay_drop 0.2
-set g_balance_machinegun_switchdelay_raise 0.2
-set g_balance_machinegun_weaponreplace "arc machinegun"
-set g_balance_machinegun_weaponstart 0
-set g_balance_machinegun_weaponstartoverride -1
-set g_balance_machinegun_weaponthrowable 1
-// }}}
-// {{{ #4: Mortar
-set g_balance_mortar_bouncefactor 0.5
-set g_balance_mortar_bouncestop 0.075
-set g_balance_mortar_primary_ammo 2
-set g_balance_mortar_primary_animtime 0.3
-set g_balance_mortar_primary_damage 50
-set g_balance_mortar_primary_damageforcescale 0
-set g_balance_mortar_primary_edgedamage 25
-set g_balance_mortar_primary_force 250
-set g_balance_mortar_primary_health 15
-set g_balance_mortar_primary_lifetime 5
-set g_balance_mortar_primary_lifetime_stick 0
-set g_balance_mortar_primary_radius 120
-set g_balance_mortar_primary_refire 0.8
-set g_balance_mortar_primary_remote_minbouncecnt 0
-set g_balance_mortar_primary_speed 1900
-set g_balance_mortar_primary_speed_up 225
-set g_balance_mortar_primary_speed_z 0
-set g_balance_mortar_primary_spread 0
-set g_balance_mortar_primary_type 0
-set g_balance_mortar_reload_ammo 0
-set g_balance_mortar_reload_time 2
-set g_balance_mortar_secondary_ammo 2
-set g_balance_mortar_secondary_animtime 0.3
-set g_balance_mortar_secondary_damage 60
-set g_balance_mortar_secondary_damageforcescale 4
-set g_balance_mortar_secondary_edgedamage 30
-set g_balance_mortar_secondary_force 250
-set g_balance_mortar_secondary_health 30
-set g_balance_mortar_secondary_lifetime 5
-set g_balance_mortar_secondary_lifetime_bounce 0.5
-set g_balance_mortar_secondary_lifetime_stick 0
-set g_balance_mortar_secondary_radius 120
-set g_balance_mortar_secondary_refire 0.7
-set g_balance_mortar_secondary_remote_detonateprimary 0
-set g_balance_mortar_secondary_speed 1400
-set g_balance_mortar_secondary_speed_up 150
-set g_balance_mortar_secondary_speed_z 0
-set g_balance_mortar_secondary_spread 0
-set g_balance_mortar_secondary_type 1
-set g_balance_mortar_switchdelay_drop 0.2
-set g_balance_mortar_switchdelay_raise 0.2
-set g_balance_mortar_weaponreplace ""
-set g_balance_mortar_weaponstart 0
-set g_balance_mortar_weaponstartoverride -1
-set g_balance_mortar_weaponthrowable 1
-// }}}
-// {{{ #5: Mine Layer (MUTATOR WEAPON)
-set g_balance_minelayer_ammo 4
-set g_balance_minelayer_animtime 0.4
-set g_balance_minelayer_damage 40
-set g_balance_minelayer_damageforcescale 0
-set g_balance_minelayer_detonatedelay -1
-set g_balance_minelayer_edgedamage 20
-set g_balance_minelayer_force 250
-set g_balance_minelayer_health 15
-set g_balance_minelayer_lifetime 10
-set g_balance_minelayer_lifetime_countdown 0.5
-set g_balance_minelayer_limit 3
-set g_balance_minelayer_protection 0
-set g_balance_minelayer_proximityradius 150
-set g_balance_minelayer_radius 175
-set g_balance_minelayer_refire 1.5
-set g_balance_minelayer_reload_ammo 0
-set g_balance_minelayer_reload_time 2
-set g_balance_minelayer_remote_damage 45
-set g_balance_minelayer_remote_edgedamage 40
-set g_balance_minelayer_remote_force 300
-set g_balance_minelayer_remote_radius 200
-set g_balance_minelayer_speed 1000
-set g_balance_minelayer_switchdelay_drop 0.2
-set g_balance_minelayer_switchdelay_raise 0.2
-set g_balance_minelayer_time 0.5
-set g_balance_minelayer_weaponreplace ""
-set g_balance_minelayer_weaponstart 0
-set g_balance_minelayer_weaponstartoverride -1
-set g_balance_minelayer_weaponthrowable 1
-// }}}
-// {{{ #6: Electro
-set g_balance_electro_combo_comboradius 300
-set g_balance_electro_combo_comboradius_thruwall 200
-set g_balance_electro_combo_damage 50
-set g_balance_electro_combo_edgedamage 25
-set g_balance_electro_combo_force 120
-set g_balance_electro_combo_radius 150
-set g_balance_electro_combo_safeammocheck 1
-set g_balance_electro_combo_speed 2000
-set g_balance_electro_primary_ammo 4
-set g_balance_electro_primary_animtime 0.3
-set g_balance_electro_primary_comboradius 300
-set g_balance_electro_primary_damage 40
-set g_balance_electro_primary_edgedamage 20
-set g_balance_electro_primary_force 200
-set g_balance_electro_primary_lifetime 5
-set g_balance_electro_primary_midaircombo_explode 1
-set g_balance_electro_primary_midaircombo_interval 0.1
-set g_balance_electro_primary_midaircombo_radius 100
-set g_balance_electro_primary_radius 100
-set g_balance_electro_primary_refire 0.6
-set g_balance_electro_primary_speed 2500
-set g_balance_electro_primary_spread 0
-set g_balance_electro_reload_ammo 0
-set g_balance_electro_reload_time 2
-set g_balance_electro_secondary_ammo 2
-set g_balance_electro_secondary_animtime 0.2
-set g_balance_electro_secondary_bouncefactor 0.3
-set g_balance_electro_secondary_bouncestop 0.05
-set g_balance_electro_secondary_count 3
-set g_balance_electro_secondary_damage 40
-set g_balance_electro_secondary_damagedbycontents 1
-set g_balance_electro_secondary_damageforcescale 4
-set g_balance_electro_secondary_edgedamage 20
-set g_balance_electro_secondary_force 50
-set g_balance_electro_secondary_health 5
-set g_balance_electro_secondary_lifetime 4
-set g_balance_electro_secondary_radius 150
-set g_balance_electro_secondary_refire 0.2
-set g_balance_electro_secondary_refire2 1.6
-set g_balance_electro_secondary_speed 1000
-set g_balance_electro_secondary_speed_up 200
-set g_balance_electro_secondary_speed_z 0
-set g_balance_electro_secondary_spread 0.04
-set g_balance_electro_secondary_touchexplode 0
-set g_balance_electro_switchdelay_drop 0.2
-set g_balance_electro_switchdelay_raise 0.2
-set g_balance_electro_weaponreplace ""
-set g_balance_electro_weaponstart 0
-set g_balance_electro_weaponstartoverride -1
-set g_balance_electro_weaponthrowable 1
-// }}}
-// {{{ #7: Crylink
-set g_balance_crylink_primary_ammo 3
-set g_balance_crylink_primary_animtime 0.3
-set g_balance_crylink_primary_bouncedamagefactor 0.5
-set g_balance_crylink_primary_bounces 1
-set g_balance_crylink_primary_damage 12
-set g_balance_crylink_primary_edgedamage 6
-set g_balance_crylink_primary_force -50
-set g_balance_crylink_primary_joindelay 0.1
-set g_balance_crylink_primary_joinexplode 1
-set g_balance_crylink_primary_joinexplode_damage 0
-set g_balance_crylink_primary_joinexplode_edgedamage 0
-set g_balance_crylink_primary_joinexplode_force 0
-set g_balance_crylink_primary_joinexplode_radius 0
-set g_balance_crylink_primary_joinspread 0.2
-set g_balance_crylink_primary_linkexplode 1
-set g_balance_crylink_primary_middle_fadetime 5
-set g_balance_crylink_primary_middle_lifetime 5
-set g_balance_crylink_primary_other_fadetime 5
-set g_balance_crylink_primary_other_lifetime 5
-set g_balance_crylink_primary_radius 80
-set g_balance_crylink_primary_refire 0.7
-set g_balance_crylink_primary_shots 6
-set g_balance_crylink_primary_speed 2000
-set g_balance_crylink_primary_spread 0.08
-set g_balance_crylink_reload_ammo 0
-set g_balance_crylink_reload_time 2
-set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_ammo 2
-set g_balance_crylink_secondary_animtime 0.2
-set g_balance_crylink_secondary_bouncedamagefactor 0.5
-set g_balance_crylink_secondary_bounces 0
-set g_balance_crylink_secondary_damage 10
-set g_balance_crylink_secondary_edgedamage 5
-set g_balance_crylink_secondary_force -250
-set g_balance_crylink_secondary_joindelay 0
-set g_balance_crylink_secondary_joinexplode 0
-set g_balance_crylink_secondary_joinexplode_damage 0
-set g_balance_crylink_secondary_joinexplode_edgedamage 0
-set g_balance_crylink_secondary_joinexplode_force 0
-set g_balance_crylink_secondary_joinexplode_radius 0
-set g_balance_crylink_secondary_joinspread 0
-set g_balance_crylink_secondary_linkexplode 1
-set g_balance_crylink_secondary_middle_fadetime 5
-set g_balance_crylink_secondary_middle_lifetime 5
-set g_balance_crylink_secondary_other_fadetime 5
-set g_balance_crylink_secondary_other_lifetime 5
-set g_balance_crylink_secondary_radius 100
-set g_balance_crylink_secondary_refire 0.7
-set g_balance_crylink_secondary_shots 5
-set g_balance_crylink_secondary_speed 3000
-set g_balance_crylink_secondary_spread 0.01
-set g_balance_crylink_secondary_spreadtype 1
-set g_balance_crylink_switchdelay_drop 0.2
-set g_balance_crylink_switchdelay_raise 0.2
-set g_balance_crylink_weaponreplace ""
-set g_balance_crylink_weaponstart 0
-set g_balance_crylink_weaponstartoverride -1
-set g_balance_crylink_weaponthrowable 1
-// }}}
-// {{{ #8: Vortex
-set g_balance_vortex_charge 1
-set g_balance_vortex_charge_animlimit 0.5
-set g_balance_vortex_charge_limit 1
-set g_balance_vortex_charge_maxspeed 800
-set g_balance_vortex_charge_mindmg 40
-set g_balance_vortex_charge_minspeed 400
-set g_balance_vortex_charge_rate 0.4
-set g_balance_vortex_charge_rot_pause 0
-set g_balance_vortex_charge_rot_rate 0
-set g_balance_vortex_charge_shot_multiplier 0
-set g_balance_vortex_charge_start 0.5
-set g_balance_vortex_charge_velocity_rate 0
-set g_balance_vortex_primary_ammo 6
-set g_balance_vortex_primary_animtime 0.6
-set g_balance_vortex_primary_damage 80
-set g_balance_vortex_primary_damagefalloff_forcehalflife 0
-set g_balance_vortex_primary_damagefalloff_halflife 0
-set g_balance_vortex_primary_damagefalloff_maxdist 0
-set g_balance_vortex_primary_damagefalloff_mindist 0
-set g_balance_vortex_primary_force 400
-set g_balance_vortex_primary_refire 1.5
-set g_balance_vortex_reload_ammo 0
-set g_balance_vortex_reload_time 2
-set g_balance_vortex_secondary 0
-set g_balance_vortex_secondary_ammo 2
-set g_balance_vortex_secondary_animtime 0
-set g_balance_vortex_secondary_chargepool 0
-set g_balance_vortex_secondary_chargepool_pause_regen 1
-set g_balance_vortex_secondary_chargepool_regen 0.15
-set g_balance_vortex_secondary_damage 0
-set g_balance_vortex_secondary_damagefalloff_forcehalflife 0
-set g_balance_vortex_secondary_damagefalloff_halflife 0
-set g_balance_vortex_secondary_damagefalloff_maxdist 0
-set g_balance_vortex_secondary_damagefalloff_mindist 0
-set g_balance_vortex_secondary_force 0
-set g_balance_vortex_secondary_refire 0
-set g_balance_vortex_switchdelay_drop 0.2
-set g_balance_vortex_switchdelay_raise 0.2
-set g_balance_vortex_weaponreplace ""
-set g_balance_vortex_weaponstart 0
-set g_balance_vortex_weaponstartoverride -1
-set g_balance_vortex_weaponthrowable 1
-// }}}
-// {{{ #9: Hagar
-set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_primary_damage 25
-set g_balance_hagar_primary_damageforcescale 0
-set g_balance_hagar_primary_edgedamage 12.5
-set g_balance_hagar_primary_force 100
-set g_balance_hagar_primary_health 15
-set g_balance_hagar_primary_lifetime 5
-set g_balance_hagar_primary_radius 65
-set g_balance_hagar_primary_refire 0.16667
-set g_balance_hagar_primary_speed 2500
-set g_balance_hagar_primary_spread 0.03
-set g_balance_hagar_reload_ammo 0
-set g_balance_hagar_reload_time 2
-set g_balance_hagar_secondary 1
-set g_balance_hagar_secondary_ammo 1
-set g_balance_hagar_secondary_damage 40
-set g_balance_hagar_secondary_damageforcescale 0
-set g_balance_hagar_secondary_edgedamage 20
-set g_balance_hagar_secondary_force 75
-set g_balance_hagar_secondary_health 15
-set g_balance_hagar_secondary_lifetime_min 10
-set g_balance_hagar_secondary_lifetime_rand 0
-set g_balance_hagar_secondary_load 1
-set g_balance_hagar_secondary_load_abort 0
-set g_balance_hagar_secondary_load_animtime 0.2
-set g_balance_hagar_secondary_load_hold 4
-set g_balance_hagar_secondary_load_linkexplode 0
-set g_balance_hagar_secondary_load_max 4
-set g_balance_hagar_secondary_load_releasedeath 0
-set g_balance_hagar_secondary_load_speed 0.5
-set g_balance_hagar_secondary_load_spread 0.075
-set g_balance_hagar_secondary_load_spread_bias 0.5
-set g_balance_hagar_secondary_radius 80
-set g_balance_hagar_secondary_refire 0.5
-set g_balance_hagar_secondary_speed 2500
-set g_balance_hagar_secondary_spread 0.05
-set g_balance_hagar_switchdelay_drop 0.2
-set g_balance_hagar_switchdelay_raise 0.2
-set g_balance_hagar_weaponreplace ""
-set g_balance_hagar_weaponstart 0
-set g_balance_hagar_weaponstartoverride -1
-set g_balance_hagar_weaponthrowable 1
-// }}}
-// {{{ #10: Devastator
-set g_balance_devastator_ammo 4
-set g_balance_devastator_animtime 0.4
-set g_balance_devastator_damage 70
-set g_balance_devastator_damageforcescale 1
-set g_balance_devastator_detonatedelay 0.02
-set g_balance_devastator_edgedamage 35
-set g_balance_devastator_force 450
-set g_balance_devastator_guidedelay 0.2
-set g_balance_devastator_guidegoal 512
-set g_balance_devastator_guiderate 70
-set g_balance_devastator_guideratedelay 0.01
-set g_balance_devastator_guidestop 0
-set g_balance_devastator_health 30
-set g_balance_devastator_lifetime 10
-set g_balance_devastator_radius 110
-set g_balance_devastator_refire 1.2
-set g_balance_devastator_reload_ammo 0
-set g_balance_devastator_reload_time 2
-set g_balance_devastator_remote_damage 70
-set g_balance_devastator_remote_edgedamage 35
-set g_balance_devastator_remote_force 400
-set g_balance_devastator_remote_jump_damage 70
-set g_balance_devastator_remote_jump_radius 0
-set g_balance_devastator_remote_jump_velocity_z_add 400
-set g_balance_devastator_remote_jump_velocity_z_max 1500
-set g_balance_devastator_remote_jump_velocity_z_min 400
-set g_balance_devastator_remote_radius 110
-set g_balance_devastator_speed 1300
-set g_balance_devastator_speedaccel 1300
-set g_balance_devastator_speedstart 1000
-set g_balance_devastator_switchdelay_drop 0.2
-set g_balance_devastator_switchdelay_raise 0.2
-set g_balance_devastator_weaponreplace ""
-set g_balance_devastator_weaponstart 0
-set g_balance_devastator_weaponstartoverride -1
-set g_balance_devastator_weaponthrowable 1
-// }}}
-// {{{ #11: Port-O-Launch
-set g_balance_porto_primary_animtime 0.3
-set g_balance_porto_primary_lifetime 5
-set g_balance_porto_primary_refire 1.5
-set g_balance_porto_primary_speed 1000
-set g_balance_porto_secondary 1
-set g_balance_porto_secondary_animtime 0.3
-set g_balance_porto_secondary_lifetime 5
-set g_balance_porto_secondary_refire 1.5
-set g_balance_porto_secondary_speed 1000
-set g_balance_porto_switchdelay_drop 0.2
-set g_balance_porto_switchdelay_raise 0.2
-set g_balance_porto_weaponreplace ""
-set g_balance_porto_weaponstart 0
-set g_balance_porto_weaponstartoverride -1
-set g_balance_porto_weaponthrowable 1
-// }}}
-// {{{ #12: Vaporizer
-set g_balance_vaporizer_primary_ammo 10
-set g_balance_vaporizer_primary_animtime 0.3
-set g_balance_vaporizer_primary_refire 1
-set g_balance_vaporizer_reload_ammo 0
-set g_balance_vaporizer_reload_time 0
-set g_balance_vaporizer_secondary_ammo 0
-set g_balance_vaporizer_secondary_animtime 0.2
-set g_balance_vaporizer_secondary_damage 25
-set g_balance_vaporizer_secondary_delay 0
-set g_balance_vaporizer_secondary_edgedamage 12.5
-set g_balance_vaporizer_secondary_force 400
-set g_balance_vaporizer_secondary_lifetime 5
-set g_balance_vaporizer_secondary_radius 70
-set g_balance_vaporizer_secondary_refire 0.7
-set g_balance_vaporizer_secondary_shotangle 0
-set g_balance_vaporizer_secondary_speed 6000
-set g_balance_vaporizer_secondary_spread 0
-set g_balance_vaporizer_switchdelay_drop 0.2
-set g_balance_vaporizer_switchdelay_raise 0.2
-set g_balance_vaporizer_weaponreplace ""
-set g_balance_vaporizer_weaponstart 0
-set g_balance_vaporizer_weaponstartoverride -1
-set g_balance_vaporizer_weaponthrowable 0
-// }}}
-// {{{ #13: Grappling Hook
-set g_balance_hook_primary_ammo 5
-set g_balance_hook_primary_animtime 0.3
-set g_balance_hook_primary_hooked_ammo 5
-set g_balance_hook_primary_hooked_time_free 2
-set g_balance_hook_primary_hooked_time_max 0
-set g_balance_hook_primary_refire 0.2
-set g_balance_hook_secondary_animtime 0.3
-set g_balance_hook_secondary_damage 25
-set g_balance_hook_secondary_damageforcescale 0
-set g_balance_hook_secondary_duration 1.5
-set g_balance_hook_secondary_edgedamage 5
-set g_balance_hook_secondary_force -2000
-set g_balance_hook_secondary_gravity 5
-set g_balance_hook_secondary_health 15
-set g_balance_hook_secondary_lifetime 5
-set g_balance_hook_secondary_power 3
-set g_balance_hook_secondary_radius 500
-set g_balance_hook_secondary_refire 3
-set g_balance_hook_secondary_speed 0
-set g_balance_hook_switchdelay_drop 0.2
-set g_balance_hook_switchdelay_raise 0.2
-set g_balance_hook_weaponreplace ""
-set g_balance_hook_weaponstart 0
-set g_balance_hook_weaponstartoverride -1
-set g_balance_hook_weaponthrowable 1
-// }}}
-// {{{ #14: Heavy Laser Assault Cannon (MUTATOR WEAPON)
-set g_balance_hlac_primary_ammo 1
-set g_balance_hlac_primary_animtime 0.4
-set g_balance_hlac_primary_damage 18
-set g_balance_hlac_primary_edgedamage 9
-set g_balance_hlac_primary_force 90
-set g_balance_hlac_primary_lifetime 5
-set g_balance_hlac_primary_radius 70
-set g_balance_hlac_primary_refire 0.15
-set g_balance_hlac_primary_speed 9000
-set g_balance_hlac_primary_spread_add 0.0045
-set g_balance_hlac_primary_spread_crouchmod 0.25
-set g_balance_hlac_primary_spread_max 0.25
-set g_balance_hlac_primary_spread_min 0.01
-set g_balance_hlac_reload_ammo 0
-set g_balance_hlac_reload_time 2
-set g_balance_hlac_secondary 1
-set g_balance_hlac_secondary_ammo 10
-set g_balance_hlac_secondary_animtime 0.3
-set g_balance_hlac_secondary_damage 15
-set g_balance_hlac_secondary_edgedamage 7.5
-set g_balance_hlac_secondary_force 90
-set g_balance_hlac_secondary_lifetime 5
-set g_balance_hlac_secondary_radius 70
-set g_balance_hlac_secondary_refire 1
-set g_balance_hlac_secondary_shots 6
-set g_balance_hlac_secondary_speed 9000
-set g_balance_hlac_secondary_spread 0.15
-set g_balance_hlac_secondary_spread_crouchmod 0.5
-set g_balance_hlac_switchdelay_drop 0.2
-set g_balance_hlac_switchdelay_raise 0.2
-set g_balance_hlac_weaponreplace ""
-set g_balance_hlac_weaponstart 0
-set g_balance_hlac_weaponstartoverride -1
-set g_balance_hlac_weaponthrowable 1
-// }}}
-// {{{ #15: @!#%'n Tuba
-set g_balance_tuba_animtime 0.05
-set g_balance_tuba_attenuation 0.5
-set g_balance_tuba_damage 5
-set g_balance_tuba_edgedamage 0
-set g_balance_tuba_force 40
-set g_balance_tuba_radius 200
-set g_balance_tuba_refire 0.05
-set g_balance_tuba_switchdelay_drop 0.2
-set g_balance_tuba_switchdelay_raise 0.2
-set g_balance_tuba_weaponreplace ""
-set g_balance_tuba_weaponstart 0
-set g_balance_tuba_weaponstartoverride -1
-set g_balance_tuba_weaponthrowable 1
-// }}}
-// {{{ #16: Rifle (MUTATOR WEAPON)
-set g_balance_rifle_bursttime 0
-set g_balance_rifle_primary_ammo 10
-set g_balance_rifle_primary_animtime 0.4
-set g_balance_rifle_primary_bullethail 0
-set g_balance_rifle_primary_burstcost 0
-set g_balance_rifle_primary_damage 80
-set g_balance_rifle_primary_force 100
-set g_balance_rifle_primary_refire 1.2
-set g_balance_rifle_primary_shots 1
-set g_balance_rifle_primary_solidpenetration 62.2
-set g_balance_rifle_primary_spread 0
-set g_balance_rifle_primary_tracer 1
-set g_balance_rifle_reload_ammo 80
-set g_balance_rifle_reload_time 2
-set g_balance_rifle_secondary 1
-set g_balance_rifle_secondary_ammo 10
-set g_balance_rifle_secondary_animtime 0.3
-set g_balance_rifle_secondary_bullethail 0
-set g_balance_rifle_secondary_burstcost 0
-set g_balance_rifle_secondary_damage 20
-set g_balance_rifle_secondary_force 50
-set g_balance_rifle_secondary_refire 0.9
-set g_balance_rifle_secondary_reload 0
-set g_balance_rifle_secondary_shots 4
-set g_balance_rifle_secondary_solidpenetration 15.5
-set g_balance_rifle_secondary_spread 0.04
-set g_balance_rifle_secondary_tracer 0
-set g_balance_rifle_switchdelay_drop 0.2
-set g_balance_rifle_switchdelay_raise 0.2
-set g_balance_rifle_weaponreplace ""
-set g_balance_rifle_weaponstart 0
-set g_balance_rifle_weaponstartoverride -1
-set g_balance_rifle_weaponthrowable 1
-// }}}
-// {{{ #17: Fireball
-set g_balance_fireball_primary_animtime 0.2
-set g_balance_fireball_primary_bfgdamage 100
-set g_balance_fireball_primary_bfgforce 0
-set g_balance_fireball_primary_bfgradius 1000
-set g_balance_fireball_primary_damage 200
-set g_balance_fireball_primary_damageforcescale 0
-set g_balance_fireball_primary_edgedamage 50
-set g_balance_fireball_primary_force 600
-set g_balance_fireball_primary_health 0
-set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 80
-set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 256
-set g_balance_fireball_primary_lifetime 15
-set g_balance_fireball_primary_radius 200
-set g_balance_fireball_primary_refire 2
-set g_balance_fireball_primary_refire2 0
-set g_balance_fireball_primary_speed 1200
-set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_animtime 0.3
-set g_balance_fireball_secondary_damage 40
-set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_damagetime 5
-set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 50
-set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 110
-set g_balance_fireball_secondary_lifetime 7
-set g_balance_fireball_secondary_refire 1.5
-set g_balance_fireball_secondary_speed 900
-set g_balance_fireball_secondary_speed_up 100
-set g_balance_fireball_secondary_speed_z 0
-set g_balance_fireball_secondary_spread 0
-set g_balance_fireball_switchdelay_drop 0.2
-set g_balance_fireball_switchdelay_raise 0.2
-set g_balance_fireball_weaponreplace ""
-set g_balance_fireball_weaponstart 0
-set g_balance_fireball_weaponstartoverride -1
-set g_balance_fireball_weaponthrowable 0
-// }}}
-// {{{ #18: T.A.G. Seeker (MUTATOR WEAPON)
-set g_balance_seeker_flac_ammo 1
-set g_balance_seeker_flac_animtime 0.1
-set g_balance_seeker_flac_damage 15
-set g_balance_seeker_flac_edgedamage 10
-set g_balance_seeker_flac_force 50
-set g_balance_seeker_flac_lifetime 0.1
-set g_balance_seeker_flac_lifetime_rand 0.05
-set g_balance_seeker_flac_radius 100
-set g_balance_seeker_flac_refire 0.1
-set g_balance_seeker_flac_speed 3000
-set g_balance_seeker_flac_speed_up 1000
-set g_balance_seeker_flac_speed_z 0
-set g_balance_seeker_flac_spread 0.4
-set g_balance_seeker_missile_accel 1400
-set g_balance_seeker_missile_ammo 2
-set g_balance_seeker_missile_animtime 0.2
-set g_balance_seeker_missile_count 3
-set g_balance_seeker_missile_damage 30
-set g_balance_seeker_missile_damageforcescale 4
-set g_balance_seeker_missile_decel 1400
-set g_balance_seeker_missile_delay 0.25
-set g_balance_seeker_missile_edgedamage 10
-set g_balance_seeker_missile_force 150
-set g_balance_seeker_missile_health 5
-set g_balance_seeker_missile_lifetime 15
-set g_balance_seeker_missile_proxy 0
-set g_balance_seeker_missile_proxy_delay 0.2
-set g_balance_seeker_missile_proxy_maxrange 45
-set g_balance_seeker_missile_radius 80
-set g_balance_seeker_missile_refire 0.5
-set g_balance_seeker_missile_smart 1
-set g_balance_seeker_missile_smart_mindist 800
-set g_balance_seeker_missile_smart_trace_max 2500
-set g_balance_seeker_missile_smart_trace_min 1000
-set g_balance_seeker_missile_speed 700
-set g_balance_seeker_missile_speed_max 1300
-set g_balance_seeker_missile_speed_up 300
-set g_balance_seeker_missile_speed_z 0
-set g_balance_seeker_missile_spread 0
-set g_balance_seeker_missile_turnrate 0.65
-set g_balance_seeker_reload_ammo 0
-set g_balance_seeker_reload_time 2
-set g_balance_seeker_switchdelay_drop 0.2
-set g_balance_seeker_switchdelay_raise 0.2
-set g_balance_seeker_tag_ammo 1
-set g_balance_seeker_tag_animtime 0.2
-set g_balance_seeker_tag_damageforcescale 4
-set g_balance_seeker_tag_health 5
-set g_balance_seeker_tag_lifetime 15
-set g_balance_seeker_tag_refire 0.75
-set g_balance_seeker_tag_speed 5000
-set g_balance_seeker_tag_spread 0
-set g_balance_seeker_tag_tracker_lifetime 10
-set g_balance_seeker_type 0
-set g_balance_seeker_weaponreplace ""
-set g_balance_seeker_weaponstart 0
-set g_balance_seeker_weaponstartoverride -1
-set g_balance_seeker_weaponthrowable 1
-// }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
-set g_balance_shockwave_blast_animtime 0.3
-set g_balance_shockwave_blast_damage 20
-set g_balance_shockwave_blast_distance 1000
-set g_balance_shockwave_blast_edgedamage 0
-set g_balance_shockwave_blast_force 200
-set g_balance_shockwave_blast_force_forwardbias 50
-set g_balance_shockwave_blast_force_zscale 2
-set g_balance_shockwave_blast_jump_damage 20
-set g_balance_shockwave_blast_jump_edgedamage 0
-set g_balance_shockwave_blast_jump_force 300
-set g_balance_shockwave_blast_jump_force_velocitybias 0
-set g_balance_shockwave_blast_jump_force_zscale 1.25
-set g_balance_shockwave_blast_jump_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_jump_multiplier_distance 0.5
-set g_balance_shockwave_blast_jump_multiplier_min 0
-set g_balance_shockwave_blast_jump_radius 150
-set g_balance_shockwave_blast_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_multiplier_distance 0.5
-set g_balance_shockwave_blast_multiplier_min 0
-set g_balance_shockwave_blast_refire 0.75
-set g_balance_shockwave_blast_splash_damage 15
-set g_balance_shockwave_blast_splash_edgedamage 0
-set g_balance_shockwave_blast_splash_force 100
-set g_balance_shockwave_blast_splash_force_forwardbias 50
-set g_balance_shockwave_blast_splash_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_splash_multiplier_distance 0.5
-set g_balance_shockwave_blast_splash_multiplier_min 0
-set g_balance_shockwave_blast_splash_radius 70
-set g_balance_shockwave_blast_spread_max 120
-set g_balance_shockwave_blast_spread_min 25
-set g_balance_shockwave_melee_animtime 1.3
-set g_balance_shockwave_melee_damage 80
-set g_balance_shockwave_melee_delay 0.25
-set g_balance_shockwave_melee_force 200
-set g_balance_shockwave_melee_multihit 1
-set g_balance_shockwave_melee_no_doubleslap 1
-set g_balance_shockwave_melee_nonplayerdamage 40
-set g_balance_shockwave_melee_range 120
-set g_balance_shockwave_melee_refire 1.25
-set g_balance_shockwave_melee_swing_side 120
-set g_balance_shockwave_melee_swing_up 30
-set g_balance_shockwave_melee_time 0.15
-set g_balance_shockwave_melee_traces 10
-set g_balance_shockwave_switchdelay_drop 0.2
-set g_balance_shockwave_switchdelay_raise 0.2
-set g_balance_shockwave_weaponreplace ""
-set g_balance_shockwave_weaponstart 1
-set g_balance_shockwave_weaponstartoverride -1
-set g_balance_shockwave_weaponthrowable 0
-// }}}
-// {{{ #20: Arc
-set g_balance_arc_beam_ammo 4
-set g_balance_arc_beam_animtime 0.2
-set g_balance_arc_beam_botaimlifetime 0
-set g_balance_arc_beam_botaimspeed 0
-set g_balance_arc_beam_damage 115
-set g_balance_arc_beam_degreespersegment 1
-set g_balance_arc_beam_distancepersegment 0
-set g_balance_arc_beam_falloff_halflifedist 0
-set g_balance_arc_beam_falloff_maxdist 0
-set g_balance_arc_beam_falloff_mindist 0
-set g_balance_arc_beam_force 900
-set g_balance_arc_beam_healing_amax 200
-set g_balance_arc_beam_healing_aps 50
-set g_balance_arc_beam_healing_hmax 200
-set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_beam_maxangle 10
-set g_balance_arc_beam_nonplayerdamage 80
-set g_balance_arc_beam_range 1000
-set g_balance_arc_beam_refire 0.5
-set g_balance_arc_beam_returnspeed 8
-set g_balance_arc_beam_tightness 0.5
-set g_balance_arc_burst_ammo 15
-set g_balance_arc_burst_damage 500
-set g_balance_arc_burst_healing_aps 100
-set g_balance_arc_burst_healing_hps 100
-set g_balance_arc_switchdelay_drop 0.3
-set g_balance_arc_switchdelay_raise 0.3
-set g_balance_arc_weaponreplace ""
-set g_balance_arc_weaponstart 0
-set g_balance_arc_weaponstartoverride -1
-set g_balance_arc_weaponthrowable 1
-// }}}
diff --git a/bal-wep-xpm.cfg b/bal-wep-xpm.cfg
deleted file mode 100644
index f0b222a6a..000000000
--- a/bal-wep-xpm.cfg
+++ /dev/null
@@ -1,753 +0,0 @@
-// {{{ #1: Blaster
-set g_balance_blaster_primary_animtime 0.2
-set g_balance_blaster_primary_damage 25
-set g_balance_blaster_primary_delay 0
-set g_balance_blaster_primary_edgedamage 12.5
-set g_balance_blaster_primary_force 300
-set g_balance_blaster_primary_force_zscale 1.2
-set g_balance_blaster_primary_lifetime 5
-set g_balance_blaster_primary_radius 70
-set g_balance_blaster_primary_refire 0.7
-set g_balance_blaster_primary_shotangle 0
-set g_balance_blaster_primary_speed 6000
-set g_balance_blaster_primary_spread 0
-set g_balance_blaster_secondary 0
-set g_balance_blaster_secondary_animtime 0.2
-set g_balance_blaster_secondary_damage 25
-set g_balance_blaster_secondary_delay 0
-set g_balance_blaster_secondary_edgedamage 12.5
-set g_balance_blaster_secondary_force 300
-set g_balance_blaster_secondary_force_zscale 1.2
-set g_balance_blaster_secondary_lifetime 5
-set g_balance_blaster_secondary_radius 70
-set g_balance_blaster_secondary_refire 0.7
-set g_balance_blaster_secondary_shotangle 0
-set g_balance_blaster_secondary_speed 6000
-set g_balance_blaster_secondary_spread 0
-set g_balance_blaster_switchdelay_drop 0.15
-set g_balance_blaster_switchdelay_raise 0.15
-set g_balance_blaster_weaponreplace ""
-set g_balance_blaster_weaponstart 1
-set g_balance_blaster_weaponstartoverride -1
-set g_balance_blaster_weaponthrowable 0
-// }}}
-// {{{ #2: Shotgun
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_animtime 0.2
-set g_balance_shotgun_primary_bullets 14
-set g_balance_shotgun_primary_damage 4
-set g_balance_shotgun_primary_force 15
-set g_balance_shotgun_primary_refire 0.75
-set g_balance_shotgun_primary_solidpenetration 3.8
-set g_balance_shotgun_primary_spread 0.12
-set g_balance_shotgun_reload_ammo 0
-set g_balance_shotgun_reload_time 2
-set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_animtime 1
-set g_balance_shotgun_secondary_damage 80
-set g_balance_shotgun_secondary_force 200
-set g_balance_shotgun_secondary_melee_delay 0.25
-set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_melee_nonplayerdamage 40
-set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing_side 120
-set g_balance_shotgun_secondary_melee_swing_up 30
-set g_balance_shotgun_secondary_melee_time 0.15
-set g_balance_shotgun_secondary_melee_traces 10
-set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_switchdelay_drop 0.2
-set g_balance_shotgun_switchdelay_raise 0.2
-set g_balance_shotgun_weaponreplace ""
-set g_balance_shotgun_weaponstart 1
-set g_balance_shotgun_weaponstartoverride -1
-set g_balance_shotgun_weaponthrowable 1
-// }}}
-// {{{ #3: Machine Gun
-set g_balance_machinegun_burst 3
-set g_balance_machinegun_burst_ammo 3
-set g_balance_machinegun_burst_animtime 0.3
-set g_balance_machinegun_burst_refire 0.06
-set g_balance_machinegun_burst_refire2 0.45
-set g_balance_machinegun_burst_speed 0
-set g_balance_machinegun_first 1
-set g_balance_machinegun_first_ammo 1
-set g_balance_machinegun_first_damage 14
-set g_balance_machinegun_first_force 5
-set g_balance_machinegun_first_refire 0.125
-set g_balance_machinegun_first_spread 0.03
-set g_balance_machinegun_mode 1
-set g_balance_machinegun_reload_ammo 60
-set g_balance_machinegun_reload_time 2
-set g_balance_machinegun_solidpenetration 13.1
-set g_balance_machinegun_spread_add 0.012
-set g_balance_machinegun_spread_max 0.05
-set g_balance_machinegun_spread_min 0.02
-set g_balance_machinegun_sustained_ammo 1
-set g_balance_machinegun_sustained_damage 10
-set g_balance_machinegun_sustained_force 5
-set g_balance_machinegun_sustained_refire 0.1
-set g_balance_machinegun_sustained_spread 0.03
-set g_balance_machinegun_switchdelay_drop 0.2
-set g_balance_machinegun_switchdelay_raise 0.2
-set g_balance_machinegun_weaponreplace "arc machinegun"
-set g_balance_machinegun_weaponstart 0
-set g_balance_machinegun_weaponstartoverride -1
-set g_balance_machinegun_weaponthrowable 1
-// }}}
-// {{{ #4: Mortar
-set g_balance_mortar_bouncefactor 0.5
-set g_balance_mortar_bouncestop 0.075
-set g_balance_mortar_primary_ammo 2
-set g_balance_mortar_primary_animtime 0.3
-set g_balance_mortar_primary_damage 50
-set g_balance_mortar_primary_damageforcescale 0
-set g_balance_mortar_primary_edgedamage 25
-set g_balance_mortar_primary_force 250
-set g_balance_mortar_primary_health 15
-set g_balance_mortar_primary_lifetime 5
-set g_balance_mortar_primary_lifetime_stick 0
-set g_balance_mortar_primary_radius 120
-set g_balance_mortar_primary_refire 0.8
-set g_balance_mortar_primary_remote_minbouncecnt 0
-set g_balance_mortar_primary_speed 1900
-set g_balance_mortar_primary_speed_up 225
-set g_balance_mortar_primary_speed_z 0
-set g_balance_mortar_primary_spread 0
-set g_balance_mortar_primary_type 0
-set g_balance_mortar_reload_ammo 0
-set g_balance_mortar_reload_time 2
-set g_balance_mortar_secondary_ammo 2
-set g_balance_mortar_secondary_animtime 0.3
-set g_balance_mortar_secondary_damage 60
-set g_balance_mortar_secondary_damageforcescale 4
-set g_balance_mortar_secondary_edgedamage 30
-set g_balance_mortar_secondary_force 250
-set g_balance_mortar_secondary_health 30
-set g_balance_mortar_secondary_lifetime 5
-set g_balance_mortar_secondary_lifetime_bounce 0.5
-set g_balance_mortar_secondary_lifetime_stick 0
-set g_balance_mortar_secondary_radius 120
-set g_balance_mortar_secondary_refire 0.7
-set g_balance_mortar_secondary_remote_detonateprimary 0
-set g_balance_mortar_secondary_speed 1400
-set g_balance_mortar_secondary_speed_up 150
-set g_balance_mortar_secondary_speed_z 0
-set g_balance_mortar_secondary_spread 0
-set g_balance_mortar_secondary_type 1
-set g_balance_mortar_switchdelay_drop 0.2
-set g_balance_mortar_switchdelay_raise 0.2
-set g_balance_mortar_weaponreplace ""
-set g_balance_mortar_weaponstart 0
-set g_balance_mortar_weaponstartoverride -1
-set g_balance_mortar_weaponthrowable 1
-// }}}
-// {{{ #5: Mine Layer (MUTATOR WEAPON)
-set g_balance_minelayer_ammo 4
-set g_balance_minelayer_animtime 0.4
-set g_balance_minelayer_damage 40
-set g_balance_minelayer_damageforcescale 0
-set g_balance_minelayer_detonatedelay -1
-set g_balance_minelayer_edgedamage 20
-set g_balance_minelayer_force 250
-set g_balance_minelayer_health 15
-set g_balance_minelayer_lifetime 10
-set g_balance_minelayer_lifetime_countdown 0.5
-set g_balance_minelayer_limit 3
-set g_balance_minelayer_protection 0
-set g_balance_minelayer_proximityradius 150
-set g_balance_minelayer_radius 175
-set g_balance_minelayer_refire 1.5
-set g_balance_minelayer_reload_ammo 0
-set g_balance_minelayer_reload_time 2
-set g_balance_minelayer_remote_damage 45
-set g_balance_minelayer_remote_edgedamage 40
-set g_balance_minelayer_remote_force 300
-set g_balance_minelayer_remote_radius 200
-set g_balance_minelayer_speed 1000
-set g_balance_minelayer_switchdelay_drop 0.2
-set g_balance_minelayer_switchdelay_raise 0.2
-set g_balance_minelayer_time 0.5
-set g_balance_minelayer_weaponreplace ""
-set g_balance_minelayer_weaponstart 0
-set g_balance_minelayer_weaponstartoverride -1
-set g_balance_minelayer_weaponthrowable 1
-// }}}
-// {{{ #6: Electro
-set g_balance_electro_combo_comboradius 300
-set g_balance_electro_combo_comboradius_thruwall 200
-set g_balance_electro_combo_damage 50
-set g_balance_electro_combo_edgedamage 25
-set g_balance_electro_combo_force 120
-set g_balance_electro_combo_radius 150
-set g_balance_electro_combo_safeammocheck 1
-set g_balance_electro_combo_speed 2000
-set g_balance_electro_primary_ammo 4
-set g_balance_electro_primary_animtime 0.3
-set g_balance_electro_primary_comboradius 300
-set g_balance_electro_primary_damage 40
-set g_balance_electro_primary_edgedamage 20
-set g_balance_electro_primary_force 200
-set g_balance_electro_primary_lifetime 5
-set g_balance_electro_primary_midaircombo_explode 1
-set g_balance_electro_primary_midaircombo_interval 0.1
-set g_balance_electro_primary_midaircombo_radius 100
-set g_balance_electro_primary_radius 100
-set g_balance_electro_primary_refire 0.6
-set g_balance_electro_primary_speed 2500
-set g_balance_electro_primary_spread 0
-set g_balance_electro_reload_ammo 0
-set g_balance_electro_reload_time 2
-set g_balance_electro_secondary_ammo 2
-set g_balance_electro_secondary_animtime 0.2
-set g_balance_electro_secondary_bouncefactor 0.3
-set g_balance_electro_secondary_bouncestop 0.05
-set g_balance_electro_secondary_count 3
-set g_balance_electro_secondary_damage 40
-set g_balance_electro_secondary_damagedbycontents 1
-set g_balance_electro_secondary_damageforcescale 4
-set g_balance_electro_secondary_edgedamage 20
-set g_balance_electro_secondary_force 50
-set g_balance_electro_secondary_health 5
-set g_balance_electro_secondary_lifetime 4
-set g_balance_electro_secondary_radius 150
-set g_balance_electro_secondary_refire 0.2
-set g_balance_electro_secondary_refire2 1.6
-set g_balance_electro_secondary_speed 1000
-set g_balance_electro_secondary_speed_up 200
-set g_balance_electro_secondary_speed_z 0
-set g_balance_electro_secondary_spread 0.04
-set g_balance_electro_secondary_touchexplode 0
-set g_balance_electro_switchdelay_drop 0.2
-set g_balance_electro_switchdelay_raise 0.2
-set g_balance_electro_weaponreplace ""
-set g_balance_electro_weaponstart 0
-set g_balance_electro_weaponstartoverride -1
-set g_balance_electro_weaponthrowable 1
-// }}}
-// {{{ #7: Crylink
-set g_balance_crylink_primary_ammo 3
-set g_balance_crylink_primary_animtime 0.3
-set g_balance_crylink_primary_bouncedamagefactor 0.5
-set g_balance_crylink_primary_bounces 1
-set g_balance_crylink_primary_damage 12
-set g_balance_crylink_primary_edgedamage 6
-set g_balance_crylink_primary_force -50
-set g_balance_crylink_primary_joindelay 0.1
-set g_balance_crylink_primary_joinexplode 1
-set g_balance_crylink_primary_joinexplode_damage 0
-set g_balance_crylink_primary_joinexplode_edgedamage 0
-set g_balance_crylink_primary_joinexplode_force 0
-set g_balance_crylink_primary_joinexplode_radius 0
-set g_balance_crylink_primary_joinspread 0.2
-set g_balance_crylink_primary_linkexplode 1
-set g_balance_crylink_primary_middle_fadetime 5
-set g_balance_crylink_primary_middle_lifetime 5
-set g_balance_crylink_primary_other_fadetime 5
-set g_balance_crylink_primary_other_lifetime 5
-set g_balance_crylink_primary_radius 80
-set g_balance_crylink_primary_refire 0.7
-set g_balance_crylink_primary_shots 6
-set g_balance_crylink_primary_speed 2000
-set g_balance_crylink_primary_spread 0.08
-set g_balance_crylink_reload_ammo 0
-set g_balance_crylink_reload_time 2
-set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_ammo 2
-set g_balance_crylink_secondary_animtime 0.2
-set g_balance_crylink_secondary_bouncedamagefactor 0.5
-set g_balance_crylink_secondary_bounces 0
-set g_balance_crylink_secondary_damage 10
-set g_balance_crylink_secondary_edgedamage 5
-set g_balance_crylink_secondary_force -250
-set g_balance_crylink_secondary_joindelay 0
-set g_balance_crylink_secondary_joinexplode 0
-set g_balance_crylink_secondary_joinexplode_damage 0
-set g_balance_crylink_secondary_joinexplode_edgedamage 0
-set g_balance_crylink_secondary_joinexplode_force 0
-set g_balance_crylink_secondary_joinexplode_radius 0
-set g_balance_crylink_secondary_joinspread 0
-set g_balance_crylink_secondary_linkexplode 1
-set g_balance_crylink_secondary_middle_fadetime 5
-set g_balance_crylink_secondary_middle_lifetime 5
-set g_balance_crylink_secondary_other_fadetime 5
-set g_balance_crylink_secondary_other_lifetime 5
-set g_balance_crylink_secondary_radius 100
-set g_balance_crylink_secondary_refire 0.7
-set g_balance_crylink_secondary_shots 5
-set g_balance_crylink_secondary_speed 3000
-set g_balance_crylink_secondary_spread 0.01
-set g_balance_crylink_secondary_spreadtype 1
-set g_balance_crylink_switchdelay_drop 0.2
-set g_balance_crylink_switchdelay_raise 0.2
-set g_balance_crylink_weaponreplace ""
-set g_balance_crylink_weaponstart 0
-set g_balance_crylink_weaponstartoverride -1
-set g_balance_crylink_weaponthrowable 1
-// }}}
-// {{{ #8: Vortex
-set g_balance_vortex_charge 1
-set g_balance_vortex_charge_animlimit 0.5
-set g_balance_vortex_charge_limit 1
-set g_balance_vortex_charge_maxspeed 800
-set g_balance_vortex_charge_mindmg 40
-set g_balance_vortex_charge_minspeed 400
-set g_balance_vortex_charge_rate 0.4
-set g_balance_vortex_charge_rot_pause 0
-set g_balance_vortex_charge_rot_rate 0
-set g_balance_vortex_charge_shot_multiplier 0
-set g_balance_vortex_charge_start 0.5
-set g_balance_vortex_charge_velocity_rate 0
-set g_balance_vortex_primary_ammo 6
-set g_balance_vortex_primary_animtime 0.6
-set g_balance_vortex_primary_damage 80
-set g_balance_vortex_primary_damagefalloff_forcehalflife 0
-set g_balance_vortex_primary_damagefalloff_halflife 0
-set g_balance_vortex_primary_damagefalloff_maxdist 0
-set g_balance_vortex_primary_damagefalloff_mindist 0
-set g_balance_vortex_primary_force 400
-set g_balance_vortex_primary_refire 1.5
-set g_balance_vortex_reload_ammo 0
-set g_balance_vortex_reload_time 2
-set g_balance_vortex_secondary 0
-set g_balance_vortex_secondary_ammo 2
-set g_balance_vortex_secondary_animtime 0
-set g_balance_vortex_secondary_chargepool 0
-set g_balance_vortex_secondary_chargepool_pause_regen 1
-set g_balance_vortex_secondary_chargepool_regen 0.15
-set g_balance_vortex_secondary_damage 0
-set g_balance_vortex_secondary_damagefalloff_forcehalflife 0
-set g_balance_vortex_secondary_damagefalloff_halflife 0
-set g_balance_vortex_secondary_damagefalloff_maxdist 0
-set g_balance_vortex_secondary_damagefalloff_mindist 0
-set g_balance_vortex_secondary_force 0
-set g_balance_vortex_secondary_refire 0
-set g_balance_vortex_switchdelay_drop 0.2
-set g_balance_vortex_switchdelay_raise 0.2
-set g_balance_vortex_weaponreplace ""
-set g_balance_vortex_weaponstart 0
-set g_balance_vortex_weaponstartoverride -1
-set g_balance_vortex_weaponthrowable 1
-// }}}
-// {{{ #9: Hagar
-set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_primary_damage 25
-set g_balance_hagar_primary_damageforcescale 0
-set g_balance_hagar_primary_edgedamage 12.5
-set g_balance_hagar_primary_force 100
-set g_balance_hagar_primary_health 15
-set g_balance_hagar_primary_lifetime 5
-set g_balance_hagar_primary_radius 65
-set g_balance_hagar_primary_refire 0.16667
-set g_balance_hagar_primary_speed 2500
-set g_balance_hagar_primary_spread 0.03
-set g_balance_hagar_reload_ammo 0
-set g_balance_hagar_reload_time 2
-set g_balance_hagar_secondary 1
-set g_balance_hagar_secondary_ammo 1
-set g_balance_hagar_secondary_damage 40
-set g_balance_hagar_secondary_damageforcescale 0
-set g_balance_hagar_secondary_edgedamage 20
-set g_balance_hagar_secondary_force 75
-set g_balance_hagar_secondary_health 15
-set g_balance_hagar_secondary_lifetime_min 10
-set g_balance_hagar_secondary_lifetime_rand 0
-set g_balance_hagar_secondary_load 1
-set g_balance_hagar_secondary_load_abort 0
-set g_balance_hagar_secondary_load_animtime 0.2
-set g_balance_hagar_secondary_load_hold 4
-set g_balance_hagar_secondary_load_linkexplode 0
-set g_balance_hagar_secondary_load_max 4
-set g_balance_hagar_secondary_load_releasedeath 0
-set g_balance_hagar_secondary_load_speed 0.5
-set g_balance_hagar_secondary_load_spread 0.075
-set g_balance_hagar_secondary_load_spread_bias 0.5
-set g_balance_hagar_secondary_radius 80
-set g_balance_hagar_secondary_refire 0.5
-set g_balance_hagar_secondary_speed 2000
-set g_balance_hagar_secondary_spread 0.05
-set g_balance_hagar_switchdelay_drop 0.2
-set g_balance_hagar_switchdelay_raise 0.2
-set g_balance_hagar_weaponreplace ""
-set g_balance_hagar_weaponstart 0
-set g_balance_hagar_weaponstartoverride -1
-set g_balance_hagar_weaponthrowable 1
-// }}}
-// {{{ #10: Devastator
-set g_balance_devastator_ammo 4
-set g_balance_devastator_animtime 0.4
-set g_balance_devastator_damage 70
-set g_balance_devastator_damageforcescale 1
-set g_balance_devastator_detonatedelay 0.02
-set g_balance_devastator_edgedamage 35
-set g_balance_devastator_force 450
-set g_balance_devastator_guidedelay 0.2
-set g_balance_devastator_guidegoal 512
-set g_balance_devastator_guiderate 70
-set g_balance_devastator_guideratedelay 0.01
-set g_balance_devastator_guidestop 0
-set g_balance_devastator_health 30
-set g_balance_devastator_lifetime 10
-set g_balance_devastator_radius 110
-set g_balance_devastator_refire 1.2
-set g_balance_devastator_reload_ammo 0
-set g_balance_devastator_reload_time 2
-set g_balance_devastator_remote_damage 70
-set g_balance_devastator_remote_edgedamage 35
-set g_balance_devastator_remote_force 400
-set g_balance_devastator_remote_jump_damage 70
-set g_balance_devastator_remote_jump_radius 0
-set g_balance_devastator_remote_jump_velocity_z_add 400
-set g_balance_devastator_remote_jump_velocity_z_max 1500
-set g_balance_devastator_remote_jump_velocity_z_min 400
-set g_balance_devastator_remote_radius 110
-set g_balance_devastator_speed 1300
-set g_balance_devastator_speedaccel 1300
-set g_balance_devastator_speedstart 1000
-set g_balance_devastator_switchdelay_drop 0.2
-set g_balance_devastator_switchdelay_raise 0.2
-set g_balance_devastator_weaponreplace ""
-set g_balance_devastator_weaponstart 0
-set g_balance_devastator_weaponstartoverride -1
-set g_balance_devastator_weaponthrowable 1
-// }}}
-// {{{ #11: Port-O-Launch
-set g_balance_porto_primary_animtime 0.3
-set g_balance_porto_primary_lifetime 5
-set g_balance_porto_primary_refire 1.5
-set g_balance_porto_primary_speed 1000
-set g_balance_porto_secondary 1
-set g_balance_porto_secondary_animtime 0.3
-set g_balance_porto_secondary_lifetime 5
-set g_balance_porto_secondary_refire 1.5
-set g_balance_porto_secondary_speed 1000
-set g_balance_porto_switchdelay_drop 0.2
-set g_balance_porto_switchdelay_raise 0.2
-set g_balance_porto_weaponreplace ""
-set g_balance_porto_weaponstart 0
-set g_balance_porto_weaponstartoverride -1
-set g_balance_porto_weaponthrowable 1
-// }}}
-// {{{ #12: Vaporizer
-set g_balance_vaporizer_primary_ammo 10
-set g_balance_vaporizer_primary_animtime 0.3
-set g_balance_vaporizer_primary_refire 1
-set g_balance_vaporizer_reload_ammo 0
-set g_balance_vaporizer_reload_time 0
-set g_balance_vaporizer_secondary_ammo 0
-set g_balance_vaporizer_secondary_animtime 0.2
-set g_balance_vaporizer_secondary_damage 25
-set g_balance_vaporizer_secondary_delay 0
-set g_balance_vaporizer_secondary_edgedamage 12.5
-set g_balance_vaporizer_secondary_force 400
-set g_balance_vaporizer_secondary_lifetime 5
-set g_balance_vaporizer_secondary_radius 70
-set g_balance_vaporizer_secondary_refire 0.7
-set g_balance_vaporizer_secondary_shotangle 0
-set g_balance_vaporizer_secondary_speed 6000
-set g_balance_vaporizer_secondary_spread 0
-set g_balance_vaporizer_switchdelay_drop 0.2
-set g_balance_vaporizer_switchdelay_raise 0.2
-set g_balance_vaporizer_weaponreplace ""
-set g_balance_vaporizer_weaponstart 0
-set g_balance_vaporizer_weaponstartoverride -1
-set g_balance_vaporizer_weaponthrowable 0
-// }}}
-// {{{ #13: Grappling Hook
-set g_balance_hook_primary_ammo 5
-set g_balance_hook_primary_animtime 0.3
-set g_balance_hook_primary_hooked_ammo 5
-set g_balance_hook_primary_hooked_time_free 2
-set g_balance_hook_primary_hooked_time_max 0
-set g_balance_hook_primary_refire 0.2
-set g_balance_hook_secondary_animtime 0.3
-set g_balance_hook_secondary_damage 25
-set g_balance_hook_secondary_damageforcescale 0
-set g_balance_hook_secondary_duration 1.5
-set g_balance_hook_secondary_edgedamage 5
-set g_balance_hook_secondary_force -2000
-set g_balance_hook_secondary_gravity 5
-set g_balance_hook_secondary_health 15
-set g_balance_hook_secondary_lifetime 5
-set g_balance_hook_secondary_power 3
-set g_balance_hook_secondary_radius 500
-set g_balance_hook_secondary_refire 3
-set g_balance_hook_secondary_speed 0
-set g_balance_hook_switchdelay_drop 0.2
-set g_balance_hook_switchdelay_raise 0.2
-set g_balance_hook_weaponreplace ""
-set g_balance_hook_weaponstart 0
-set g_balance_hook_weaponstartoverride -1
-set g_balance_hook_weaponthrowable 1
-// }}}
-// {{{ #14: Heavy Laser Assault Cannon (MUTATOR WEAPON)
-set g_balance_hlac_primary_ammo 1
-set g_balance_hlac_primary_animtime 0.4
-set g_balance_hlac_primary_damage 18
-set g_balance_hlac_primary_edgedamage 9
-set g_balance_hlac_primary_force 90
-set g_balance_hlac_primary_lifetime 5
-set g_balance_hlac_primary_radius 70
-set g_balance_hlac_primary_refire 0.15
-set g_balance_hlac_primary_speed 9000
-set g_balance_hlac_primary_spread_add 0.0045
-set g_balance_hlac_primary_spread_crouchmod 0.25
-set g_balance_hlac_primary_spread_max 0.25
-set g_balance_hlac_primary_spread_min 0.01
-set g_balance_hlac_reload_ammo 0
-set g_balance_hlac_reload_time 2
-set g_balance_hlac_secondary 1
-set g_balance_hlac_secondary_ammo 10
-set g_balance_hlac_secondary_animtime 0.3
-set g_balance_hlac_secondary_damage 15
-set g_balance_hlac_secondary_edgedamage 7.5
-set g_balance_hlac_secondary_force 90
-set g_balance_hlac_secondary_lifetime 5
-set g_balance_hlac_secondary_radius 70
-set g_balance_hlac_secondary_refire 1
-set g_balance_hlac_secondary_shots 6
-set g_balance_hlac_secondary_speed 9000
-set g_balance_hlac_secondary_spread 0.15
-set g_balance_hlac_secondary_spread_crouchmod 0.5
-set g_balance_hlac_switchdelay_drop 0.2
-set g_balance_hlac_switchdelay_raise 0.2
-set g_balance_hlac_weaponreplace ""
-set g_balance_hlac_weaponstart 0
-set g_balance_hlac_weaponstartoverride -1
-set g_balance_hlac_weaponthrowable 1
-// }}}
-// {{{ #15: @!#%'n Tuba
-set g_balance_tuba_animtime 0.05
-set g_balance_tuba_attenuation 0.5
-set g_balance_tuba_damage 5
-set g_balance_tuba_edgedamage 0
-set g_balance_tuba_force 40
-set g_balance_tuba_radius 200
-set g_balance_tuba_refire 0.05
-set g_balance_tuba_switchdelay_drop 0.2
-set g_balance_tuba_switchdelay_raise 0.2
-set g_balance_tuba_weaponreplace ""
-set g_balance_tuba_weaponstart 0
-set g_balance_tuba_weaponstartoverride -1
-set g_balance_tuba_weaponthrowable 1
-// }}}
-// {{{ #16: Rifle (MUTATOR WEAPON)
-set g_balance_rifle_bursttime 0
-set g_balance_rifle_primary_ammo 10
-set g_balance_rifle_primary_animtime 0.4
-set g_balance_rifle_primary_bullethail 0
-set g_balance_rifle_primary_burstcost 0
-set g_balance_rifle_primary_damage 80
-set g_balance_rifle_primary_force 100
-set g_balance_rifle_primary_refire 1.2
-set g_balance_rifle_primary_shots 1
-set g_balance_rifle_primary_solidpenetration 62.2
-set g_balance_rifle_primary_spread 0
-set g_balance_rifle_primary_tracer 1
-set g_balance_rifle_reload_ammo 80
-set g_balance_rifle_reload_time 2
-set g_balance_rifle_secondary 1
-set g_balance_rifle_secondary_ammo 10
-set g_balance_rifle_secondary_animtime 0.3
-set g_balance_rifle_secondary_bullethail 0
-set g_balance_rifle_secondary_burstcost 0
-set g_balance_rifle_secondary_damage 20
-set g_balance_rifle_secondary_force 50
-set g_balance_rifle_secondary_refire 0.9
-set g_balance_rifle_secondary_reload 0
-set g_balance_rifle_secondary_shots 4
-set g_balance_rifle_secondary_solidpenetration 15.5
-set g_balance_rifle_secondary_spread 0.04
-set g_balance_rifle_secondary_tracer 0
-set g_balance_rifle_switchdelay_drop 0.2
-set g_balance_rifle_switchdelay_raise 0.2
-set g_balance_rifle_weaponreplace ""
-set g_balance_rifle_weaponstart 0
-set g_balance_rifle_weaponstartoverride -1
-set g_balance_rifle_weaponthrowable 1
-// }}}
-// {{{ #17: Fireball
-set g_balance_fireball_primary_animtime 0.2
-set g_balance_fireball_primary_bfgdamage 100
-set g_balance_fireball_primary_bfgforce 0
-set g_balance_fireball_primary_bfgradius 1000
-set g_balance_fireball_primary_damage 200
-set g_balance_fireball_primary_damageforcescale 0
-set g_balance_fireball_primary_edgedamage 50
-set g_balance_fireball_primary_force 600
-set g_balance_fireball_primary_health 0
-set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 80
-set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 256
-set g_balance_fireball_primary_lifetime 15
-set g_balance_fireball_primary_radius 200
-set g_balance_fireball_primary_refire 2
-set g_balance_fireball_primary_refire2 0
-set g_balance_fireball_primary_speed 1200
-set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_animtime 0.3
-set g_balance_fireball_secondary_damage 40
-set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_damagetime 5
-set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 50
-set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 110
-set g_balance_fireball_secondary_lifetime 7
-set g_balance_fireball_secondary_refire 1.5
-set g_balance_fireball_secondary_speed 900
-set g_balance_fireball_secondary_speed_up 100
-set g_balance_fireball_secondary_speed_z 0
-set g_balance_fireball_secondary_spread 0
-set g_balance_fireball_switchdelay_drop 0.2
-set g_balance_fireball_switchdelay_raise 0.2
-set g_balance_fireball_weaponreplace ""
-set g_balance_fireball_weaponstart 0
-set g_balance_fireball_weaponstartoverride -1
-set g_balance_fireball_weaponthrowable 0
-// }}}
-// {{{ #18: T.A.G. Seeker (MUTATOR WEAPON)
-set g_balance_seeker_flac_ammo 1
-set g_balance_seeker_flac_animtime 0.1
-set g_balance_seeker_flac_damage 15
-set g_balance_seeker_flac_edgedamage 10
-set g_balance_seeker_flac_force 50
-set g_balance_seeker_flac_lifetime 0.1
-set g_balance_seeker_flac_lifetime_rand 0.05
-set g_balance_seeker_flac_radius 100
-set g_balance_seeker_flac_refire 0.1
-set g_balance_seeker_flac_speed 3000
-set g_balance_seeker_flac_speed_up 1000
-set g_balance_seeker_flac_speed_z 0
-set g_balance_seeker_flac_spread 0.4
-set g_balance_seeker_missile_accel 1400
-set g_balance_seeker_missile_ammo 2
-set g_balance_seeker_missile_animtime 0.2
-set g_balance_seeker_missile_count 3
-set g_balance_seeker_missile_damage 30
-set g_balance_seeker_missile_damageforcescale 4
-set g_balance_seeker_missile_decel 1400
-set g_balance_seeker_missile_delay 0.25
-set g_balance_seeker_missile_edgedamage 10
-set g_balance_seeker_missile_force 150
-set g_balance_seeker_missile_health 5
-set g_balance_seeker_missile_lifetime 15
-set g_balance_seeker_missile_proxy 0
-set g_balance_seeker_missile_proxy_delay 0.2
-set g_balance_seeker_missile_proxy_maxrange 45
-set g_balance_seeker_missile_radius 80
-set g_balance_seeker_missile_refire 0.5
-set g_balance_seeker_missile_smart 1
-set g_balance_seeker_missile_smart_mindist 800
-set g_balance_seeker_missile_smart_trace_max 2500
-set g_balance_seeker_missile_smart_trace_min 1000
-set g_balance_seeker_missile_speed 700
-set g_balance_seeker_missile_speed_max 1300
-set g_balance_seeker_missile_speed_up 300
-set g_balance_seeker_missile_speed_z 0
-set g_balance_seeker_missile_spread 0
-set g_balance_seeker_missile_turnrate 0.65
-set g_balance_seeker_reload_ammo 0
-set g_balance_seeker_reload_time 2
-set g_balance_seeker_switchdelay_drop 0.2
-set g_balance_seeker_switchdelay_raise 0.2
-set g_balance_seeker_tag_ammo 1
-set g_balance_seeker_tag_animtime 0.2
-set g_balance_seeker_tag_damageforcescale 4
-set g_balance_seeker_tag_health 5
-set g_balance_seeker_tag_lifetime 15
-set g_balance_seeker_tag_refire 0.75
-set g_balance_seeker_tag_speed 5000
-set g_balance_seeker_tag_spread 0
-set g_balance_seeker_tag_tracker_lifetime 10
-set g_balance_seeker_type 0
-set g_balance_seeker_weaponreplace ""
-set g_balance_seeker_weaponstart 0
-set g_balance_seeker_weaponstartoverride -1
-set g_balance_seeker_weaponthrowable 1
-// }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
-set g_balance_shockwave_blast_animtime 0.3
-set g_balance_shockwave_blast_damage 20
-set g_balance_shockwave_blast_distance 1000
-set g_balance_shockwave_blast_edgedamage 0
-set g_balance_shockwave_blast_force 200
-set g_balance_shockwave_blast_force_forwardbias 50
-set g_balance_shockwave_blast_force_zscale 2
-set g_balance_shockwave_blast_jump_damage 20
-set g_balance_shockwave_blast_jump_edgedamage 0
-set g_balance_shockwave_blast_jump_force 300
-set g_balance_shockwave_blast_jump_force_velocitybias 0
-set g_balance_shockwave_blast_jump_force_zscale 1.25
-set g_balance_shockwave_blast_jump_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_jump_multiplier_distance 0.5
-set g_balance_shockwave_blast_jump_multiplier_min 0
-set g_balance_shockwave_blast_jump_radius 150
-set g_balance_shockwave_blast_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_multiplier_distance 0.5
-set g_balance_shockwave_blast_multiplier_min 0
-set g_balance_shockwave_blast_refire 0.75
-set g_balance_shockwave_blast_splash_damage 15
-set g_balance_shockwave_blast_splash_edgedamage 0
-set g_balance_shockwave_blast_splash_force 100
-set g_balance_shockwave_blast_splash_force_forwardbias 50
-set g_balance_shockwave_blast_splash_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_splash_multiplier_distance 0.5
-set g_balance_shockwave_blast_splash_multiplier_min 0
-set g_balance_shockwave_blast_splash_radius 70
-set g_balance_shockwave_blast_spread_max 120
-set g_balance_shockwave_blast_spread_min 25
-set g_balance_shockwave_melee_animtime 1.3
-set g_balance_shockwave_melee_damage 80
-set g_balance_shockwave_melee_delay 0.25
-set g_balance_shockwave_melee_force 200
-set g_balance_shockwave_melee_multihit 1
-set g_balance_shockwave_melee_no_doubleslap 1
-set g_balance_shockwave_melee_nonplayerdamage 40
-set g_balance_shockwave_melee_range 120
-set g_balance_shockwave_melee_refire 1.25
-set g_balance_shockwave_melee_swing_side 120
-set g_balance_shockwave_melee_swing_up 30
-set g_balance_shockwave_melee_time 0.15
-set g_balance_shockwave_melee_traces 10
-set g_balance_shockwave_switchdelay_drop 0.2
-set g_balance_shockwave_switchdelay_raise 0.2
-set g_balance_shockwave_weaponreplace ""
-set g_balance_shockwave_weaponstart 1
-set g_balance_shockwave_weaponstartoverride -1
-set g_balance_shockwave_weaponthrowable 0
-// }}}
-// {{{ #20: Arc
-set g_balance_arc_beam_ammo 4
-set g_balance_arc_beam_animtime 0.2
-set g_balance_arc_beam_botaimlifetime 0
-set g_balance_arc_beam_botaimspeed 0
-set g_balance_arc_beam_damage 115
-set g_balance_arc_beam_degreespersegment 1
-set g_balance_arc_beam_distancepersegment 0
-set g_balance_arc_beam_falloff_halflifedist 0
-set g_balance_arc_beam_falloff_maxdist 0
-set g_balance_arc_beam_falloff_mindist 0
-set g_balance_arc_beam_force 900
-set g_balance_arc_beam_healing_amax 200
-set g_balance_arc_beam_healing_aps 50
-set g_balance_arc_beam_healing_hmax 200
-set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_beam_maxangle 10
-set g_balance_arc_beam_nonplayerdamage 80
-set g_balance_arc_beam_range 1000
-set g_balance_arc_beam_refire 0.5
-set g_balance_arc_beam_returnspeed 8
-set g_balance_arc_beam_tightness 0.5
-set g_balance_arc_burst_ammo 15
-set g_balance_arc_burst_damage 500
-set g_balance_arc_burst_healing_aps 100
-set g_balance_arc_burst_healing_hps 100
-set g_balance_arc_switchdelay_drop 0.3
-set g_balance_arc_switchdelay_raise 0.3
-set g_balance_arc_weaponreplace ""
-set g_balance_arc_weaponstart 0
-set g_balance_arc_weaponstartoverride -1
-set g_balance_arc_weaponthrowable 1
-// }}}
diff --git a/balance-rev.cfg b/balance-rev.cfg
deleted file mode 100644
index c7e78963e..000000000
--- a/balance-rev.cfg
+++ /dev/null
@@ -1,223 +0,0 @@
-g_mod_balance Xonotic
-
-// {{{ starting gear
-set g_balance_health_start 100
-set g_balance_armor_start 0
-set g_start_ammo_shells 15
-set g_start_ammo_nails 0
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_plasma 0
-set g_start_ammo_fuel 0
-set g_warmup_start_health 100 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_plasma 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 200
-set g_lms_start_armor 200
-set g_lms_start_ammo_shells 60
-set g_lms_start_ammo_nails 320
-set g_lms_start_ammo_rockets 160
-set g_lms_start_ammo_cells 180
-set g_lms_start_ammo_plasma 180
-set g_lms_start_ammo_fuel 0
-set g_balance_nix_roundtime 25
-set g_balance_nix_incrtime 1.6
-set g_balance_nix_ammo_shells 60
-set g_balance_nix_ammo_nails 320
-set g_balance_nix_ammo_rockets 160
-set g_balance_nix_ammo_cells 180
-set g_balance_nix_ammo_plasma 180
-set g_balance_nix_ammo_fuel 0
-set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
-set g_balance_nix_ammoincr_nails 6
-set g_balance_nix_ammoincr_rockets 2
-set g_balance_nix_ammoincr_cells 2
-set g_balance_nix_ammoincr_plasma 2
-set g_balance_nix_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_ammo_anyway 1
-set g_pickup_weapons_anyway 1
-set g_pickup_shells 15
-set g_pickup_shells_weapon 15
-set g_pickup_shells_max 60
-set g_pickup_nails 80
-set g_pickup_nails_weapon 80
-set g_pickup_nails_max 320
-set g_pickup_rockets 40
-set g_pickup_rockets_weapon 40
-set g_pickup_rockets_max 160
-set g_pickup_cells 30
-set g_pickup_cells_weapon 30
-set g_pickup_cells_max 180
-set g_pickup_plasma 30
-set g_pickup_plasma_weapon 30
-set g_pickup_plasma_max 180
-set g_pickup_fuel 50
-set g_pickup_fuel_weapon 50
-set g_pickup_fuel_jetpack 100
-set g_pickup_fuel_max 100
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 200
-set g_pickup_armorsmall_anyway 0
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 100
-set g_pickup_armormedium_anyway 0
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 100
-set g_pickup_armorbig_anyway 0
-set g_pickup_armorlarge 100
-set g_pickup_armorlarge_max 200
-set g_pickup_armorlarge_anyway 0
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 200
-set g_pickup_healthsmall_anyway 0
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 100
-set g_pickup_healthmedium_anyway 0
-set g_pickup_healthlarge 50
-set g_pickup_healthlarge_max 100
-set g_pickup_healthlarge_anyway 0
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 200
-set g_pickup_healthmega_anyway 0
-set g_pickup_respawntime_short 15
-set g_pickup_respawntime_medium 20
-set g_pickup_respawntime_long 30
-set g_pickup_respawntime_powerup 120
-set g_pickup_respawntime_weapon 10
-set g_pickup_respawntime_superweapon 120
-set g_pickup_respawntime_ammo 15
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 30
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_superweapon 10
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0.08
-set g_balance_health_regenlinear 0.5
-set g_balance_pause_health_regen 5
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0.03
-set g_balance_health_rotlinear 0.75
-set g_balance_pause_health_rot 1
-set g_balance_pause_health_rot_spawn 5
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 999
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0.03
-set g_balance_armor_rotlinear 0.75
-set g_balance_pause_armor_rot 1
-set g_balance_pause_armor_rot_spawn 5
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 999
-set g_balance_armor_blockpercent 0.6
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 999
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0.65
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.75
-set g_throughfloor_force 0.75
-set g_projectiles_damage -2
-// possible values:
-// -2: absolutely no damage to projectiles (no exceptions)
-// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
-// 0: only damage from contents (lava/slime) or exceptions
-// 1: only self damage or damage from contents or exceptions
-// 2: allow all damage to projectiles normally
-set g_projectiles_keep_owner 0
-set g_projectiles_newton_style 0
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-set g_projectiles_newton_style_2_minfactor 0.8
-set g_projectiles_newton_style_2_maxfactor 1.5
-set g_projectiles_spread_style 7
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 250
-set g_balance_falldamage_minspeed 900
-set g_balance_falldamage_factor 0.20
-set g_balance_falldamage_maxdamage 40
-set g_balance_damagepush_speedfactor 2.5
-set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
-set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
-set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
-set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
-set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
-set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken
-set g_balance_powerup_invincible_time 30
-set g_balance_powerup_strength_damage 3
-set g_balance_powerup_strength_force 3
-set g_balance_powerup_strength_time 30
-set g_balance_powerup_strength_selfdamage 1.5
-set g_balance_powerup_strength_selfforce 1.5
-set g_balance_superweapons_time 30
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_attenuation 2 "jetpack sound attenuation"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 50
-set g_balance_grapplehook_damagedbycontents 1
-set g_balance_grapplehook_refire 0.2
-// }}}
-
-exec bal-wep-xonotic.cfg
diff --git a/balance-xonotic.cfg b/balance-xonotic.cfg
deleted file mode 100644
index 4c3dcdb7a..000000000
--- a/balance-xonotic.cfg
+++ /dev/null
@@ -1,223 +0,0 @@
-g_mod_balance Xonotic
-
-// {{{ starting gear
-set g_balance_health_start 100
-set g_balance_armor_start 0
-set g_start_ammo_shells 15
-set g_start_ammo_nails 0
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_plasma 0
-set g_start_ammo_fuel 0
-set g_warmup_start_health 100 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_plasma 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 200
-set g_lms_start_armor 200
-set g_lms_start_ammo_shells 60
-set g_lms_start_ammo_nails 320
-set g_lms_start_ammo_rockets 160
-set g_lms_start_ammo_cells 180
-set g_lms_start_ammo_plasma 180
-set g_lms_start_ammo_fuel 0
-set g_balance_nix_roundtime 25
-set g_balance_nix_incrtime 1.6
-set g_balance_nix_ammo_shells 60
-set g_balance_nix_ammo_nails 320
-set g_balance_nix_ammo_rockets 160
-set g_balance_nix_ammo_cells 180
-set g_balance_nix_ammo_plasma 180
-set g_balance_nix_ammo_fuel 0
-set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
-set g_balance_nix_ammoincr_nails 6
-set g_balance_nix_ammoincr_rockets 2
-set g_balance_nix_ammoincr_cells 2
-set g_balance_nix_ammoincr_plasma 2
-set g_balance_nix_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_ammo_anyway 1
-set g_pickup_weapons_anyway 1
-set g_pickup_shells 15
-set g_pickup_shells_weapon 15
-set g_pickup_shells_max 60
-set g_pickup_nails 80
-set g_pickup_nails_weapon 80
-set g_pickup_nails_max 320
-set g_pickup_rockets 40
-set g_pickup_rockets_weapon 40
-set g_pickup_rockets_max 160
-set g_pickup_cells 30
-set g_pickup_cells_weapon 30
-set g_pickup_cells_max 180
-set g_pickup_plasma 30
-set g_pickup_plasma_weapon 30
-set g_pickup_plasma_max 180
-set g_pickup_fuel 50
-set g_pickup_fuel_weapon 50
-set g_pickup_fuel_jetpack 100
-set g_pickup_fuel_max 100
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 200
-set g_pickup_armorsmall_anyway 1
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 200
-set g_pickup_armormedium_anyway 1
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 200
-set g_pickup_armorbig_anyway 1
-set g_pickup_armorlarge 100
-set g_pickup_armorlarge_max 200
-set g_pickup_armorlarge_anyway 1
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 200
-set g_pickup_healthsmall_anyway 1
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 200
-set g_pickup_healthmedium_anyway 1
-set g_pickup_healthlarge 50
-set g_pickup_healthlarge_max 200
-set g_pickup_healthlarge_anyway 1
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 200
-set g_pickup_healthmega_anyway 1
-set g_pickup_respawntime_short 15
-set g_pickup_respawntime_medium 20
-set g_pickup_respawntime_long 30
-set g_pickup_respawntime_powerup 120
-set g_pickup_respawntime_weapon 10
-set g_pickup_respawntime_superweapon 120
-set g_pickup_respawntime_ammo 10
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 30
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_superweapon 10
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0.08
-set g_balance_health_regenlinear 0.5
-set g_balance_pause_health_regen 5
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0.04
-set g_balance_health_rotlinear 0.75
-set g_balance_pause_health_rot 1
-set g_balance_pause_health_rot_spawn 5
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 999
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0.04
-set g_balance_armor_rotlinear 0.75
-set g_balance_pause_armor_rot 1
-set g_balance_pause_armor_rot_spawn 5
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 999
-set g_balance_armor_blockpercent 0.6
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 999
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0.65
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.75
-set g_throughfloor_force 0.75
-set g_projectiles_damage 2
-// possible values:
-// -2: absolutely no damage to projectiles (no exceptions)
-// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
-// 0: only damage from contents (lava/slime) or exceptions
-// 1: only self damage or damage from contents or exceptions
-// 2: allow all damage to projectiles normally
-set g_projectiles_keep_owner 0
-set g_projectiles_newton_style 2
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-set g_projectiles_newton_style_2_minfactor 0.8
-set g_projectiles_newton_style_2_maxfactor 1.5
-set g_projectiles_spread_style 7
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 250
-set g_balance_falldamage_minspeed 900
-set g_balance_falldamage_factor 0.20
-set g_balance_falldamage_maxdamage 40
-set g_balance_damagepush_speedfactor 2.5
-set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
-set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
-set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
-set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
-set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
-set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken
-set g_balance_powerup_invincible_time 30
-set g_balance_powerup_strength_damage 3
-set g_balance_powerup_strength_force 3
-set g_balance_powerup_strength_time 30
-set g_balance_powerup_strength_selfdamage 1.5
-set g_balance_powerup_strength_selfforce 1.5
-set g_balance_superweapons_time 30
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_attenuation 2 "jetpack sound attenuation"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 50
-set g_balance_grapplehook_damagedbycontents 1
-set g_balance_grapplehook_refire 0.2
-// }}}
-
-exec bal-wep-xonotic.cfg
diff --git a/balance-xpm.cfg b/balance-xpm.cfg
deleted file mode 100644
index 7a310da1a..000000000
--- a/balance-xpm.cfg
+++ /dev/null
@@ -1,223 +0,0 @@
-g_mod_balance Xonotic
-
-// {{{ starting gear
-set g_balance_health_start 100
-set g_balance_armor_start 0
-set g_start_ammo_shells 15
-set g_start_ammo_nails 0
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_plasma 0
-set g_start_ammo_fuel 0
-set g_warmup_start_health 100 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_plasma 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 200
-set g_lms_start_armor 200
-set g_lms_start_ammo_shells 60
-set g_lms_start_ammo_nails 320
-set g_lms_start_ammo_rockets 160
-set g_lms_start_ammo_cells 180
-set g_lms_start_ammo_plasma 180
-set g_lms_start_ammo_fuel 0
-set g_balance_nix_roundtime 25
-set g_balance_nix_incrtime 1.6
-set g_balance_nix_ammo_shells 60
-set g_balance_nix_ammo_nails 320
-set g_balance_nix_ammo_rockets 160
-set g_balance_nix_ammo_cells 180
-set g_balance_nix_ammo_plasma 180
-set g_balance_nix_ammo_fuel 0
-set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
-set g_balance_nix_ammoincr_nails 6
-set g_balance_nix_ammoincr_rockets 2
-set g_balance_nix_ammoincr_cells 2
-set g_balance_nix_ammoincr_plasma 2
-set g_balance_nix_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_ammo_anyway 1
-set g_pickup_weapons_anyway 1
-set g_pickup_shells 15
-set g_pickup_shells_weapon 15
-set g_pickup_shells_max 60
-set g_pickup_nails 80
-set g_pickup_nails_weapon 80
-set g_pickup_nails_max 320
-set g_pickup_rockets 40
-set g_pickup_rockets_weapon 40
-set g_pickup_rockets_max 160
-set g_pickup_cells 30
-set g_pickup_cells_weapon 30
-set g_pickup_cells_max 180
-set g_pickup_plasma 30
-set g_pickup_plasma_weapon 30
-set g_pickup_plasma_max 180
-set g_pickup_fuel 50
-set g_pickup_fuel_weapon 50
-set g_pickup_fuel_jetpack 100
-set g_pickup_fuel_max 100
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 200
-set g_pickup_armorsmall_anyway 0
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 100
-set g_pickup_armormedium_anyway 0
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 100
-set g_pickup_armorbig_anyway 0
-set g_pickup_armorlarge 100
-set g_pickup_armorlarge_max 200
-set g_pickup_armorlarge_anyway 0
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 200
-set g_pickup_healthsmall_anyway 0
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 100
-set g_pickup_healthmedium_anyway 0
-set g_pickup_healthlarge 50
-set g_pickup_healthlarge_max 100
-set g_pickup_healthlarge_anyway 0
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 200
-set g_pickup_healthmega_anyway 0
-set g_pickup_respawntime_short 15
-set g_pickup_respawntime_medium 20
-set g_pickup_respawntime_long 30
-set g_pickup_respawntime_powerup 120
-set g_pickup_respawntime_weapon 10
-set g_pickup_respawntime_superweapon 120
-set g_pickup_respawntime_ammo 15
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 30
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_superweapon 10
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0.08
-set g_balance_health_regenlinear 0.5
-set g_balance_pause_health_regen 5
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0.03
-set g_balance_health_rotlinear 0.75
-set g_balance_pause_health_rot 1
-set g_balance_pause_health_rot_spawn 5
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 999
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0.03
-set g_balance_armor_rotlinear 0.75
-set g_balance_pause_armor_rot 1
-set g_balance_pause_armor_rot_spawn 5
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 999
-set g_balance_armor_blockpercent 0.6
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 999
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0.65
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.75
-set g_throughfloor_force 0.75
-set g_projectiles_damage 1
-// possible values:
-// -2: absolutely no damage to projectiles (no exceptions)
-// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
-// 0: only damage from contents (lava/slime) or exceptions
-// 1: only self damage or damage from contents or exceptions
-// 2: allow all damage to projectiles normally
-set g_projectiles_keep_owner 0
-set g_projectiles_newton_style 0
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-set g_projectiles_newton_style_2_minfactor 0.8
-set g_projectiles_newton_style_2_maxfactor 1.5
-set g_projectiles_spread_style 7
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 250
-set g_balance_falldamage_minspeed 900
-set g_balance_falldamage_factor 0.20
-set g_balance_falldamage_maxdamage 40
-set g_balance_damagepush_speedfactor 2.5
-set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
-set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
-set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
-set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
-set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
-set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken
-set g_balance_powerup_invincible_time 30
-set g_balance_powerup_strength_damage 3
-set g_balance_powerup_strength_force 3
-set g_balance_powerup_strength_time 30
-set g_balance_powerup_strength_selfdamage 1.5
-set g_balance_powerup_strength_selfforce 1.5
-set g_balance_superweapons_time 30
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_attenuation 2 "jetpack sound attenuation"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 50
-set g_balance_grapplehook_damagedbycontents 1
-set g_balance_grapplehook_refire 0.2
-// }}}
-
-exec bal-wep-xonotic.cfg
diff --git a/balance25.cfg b/balance25.cfg
new file mode 100644
index 000000000..be0e84f3f
--- /dev/null
+++ b/balance25.cfg
@@ -0,0 +1,706 @@
+g_mod_balance Nexuiz25
+
+// {{{ starting gear
+set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_balance_health_start 150
+set g_balance_armor_start 0
+set g_start_ammo_shells 40
+set g_start_ammo_nails 0
+set g_start_ammo_rockets 0
+set g_start_ammo_cells 0
+set g_start_ammo_fuel 0
+set g_warmup_start_health 250 "starting values when being in warmup-stage"
+set g_warmup_start_armor 100 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
+set g_lms_start_health 250
+set g_lms_start_armor 100
+set g_lms_start_ammo_shells 50
+set g_lms_start_ammo_nails 150
+set g_lms_start_ammo_rockets 50
+set g_lms_start_ammo_cells 50
+set g_lms_start_ammo_fuel 0
+set g_balance_nix_roundtime 25
+set g_balance_nix_incrtime 1.6
+set g_balance_nix_ammo_shells 15
+set g_balance_nix_ammo_nails 45
+set g_balance_nix_ammo_rockets 15
+set g_balance_nix_ammo_cells 15
+set g_balance_nix_ammo_fuel 0
+set g_balance_nix_ammoincr_shells 2
+set g_balance_nix_ammoincr_nails 6
+set g_balance_nix_ammoincr_rockets 2
+set g_balance_nix_ammoincr_cells 2
+set g_balance_nix_ammoincr_fuel 2
+// }}}
+
+// {{{ pickup items
+set g_pickup_ammo_anyway 0
+set g_pickup_weapons_anyway 0
+set g_pickup_shells 15
+set g_pickup_shells_weapon 15
+set g_pickup_shells_max 999
+set g_pickup_nails 80
+set g_pickup_nails_weapon 80
+set g_pickup_nails_max 999
+set g_pickup_rockets 15
+set g_pickup_rockets_weapon 15
+set g_pickup_rockets_max 999
+set g_pickup_cells 25
+set g_pickup_cells_weapon 25
+set g_pickup_cells_max 999
+set g_pickup_fuel 25
+set g_pickup_fuel_weapon 25
+set g_pickup_fuel_jetpack 50
+set g_pickup_fuel_max 999
+set g_pickup_armorsmall 5
+set g_pickup_armorsmall_max 999
+set g_pickup_armorsmall_anyway 0
+set g_pickup_armormedium 25
+set g_pickup_armormedium_max 999
+set g_pickup_armormedium_anyway 0
+set g_pickup_armorbig 50
+set g_pickup_armorbig_max 999
+set g_pickup_armorbig_anyway 0
+set g_pickup_armorlarge 100
+set g_pickup_armorlarge_max 999
+set g_pickup_armorlarge_anyway 0
+set g_pickup_healthsmall 5
+set g_pickup_healthsmall_max 999
+set g_pickup_healthsmall_anyway 0
+set g_pickup_healthmedium 25
+set g_pickup_healthmedium_max 999
+set g_pickup_healthmedium_anyway 0
+set g_pickup_healthlarge 50
+set g_pickup_healthlarge_max 999
+set g_pickup_healthlarge_anyway 0
+set g_pickup_healthmega 100
+set g_pickup_healthmega_max 999
+set g_pickup_healthmega_anyway 0
+set g_pickup_respawntime_short 15
+set g_pickup_respawntime_medium 20
+set g_pickup_respawntime_long 30
+set g_pickup_respawntime_powerup 120
+set g_pickup_respawntime_weapon 15
+set g_pickup_respawntime_superweapon 120
+set g_pickup_respawntime_ammo 15
+set g_pickup_respawntimejitter_short 0
+set g_pickup_respawntimejitter_medium 0
+set g_pickup_respawntimejitter_long 0
+set g_pickup_respawntimejitter_powerup 10
+set g_pickup_respawntimejitter_weapon 0
+set g_pickup_respawntimejitter_superweapon 10
+set g_pickup_respawntimejitter_ammo 0
+// }}}
+
+// {{{ regen/rot
+set g_balance_health_regen 0.1
+set g_balance_health_regenlinear 0
+set g_balance_pause_health_regen 5
+set g_balance_pause_health_regen_spawn 0
+set g_balance_health_rot 0.1
+set g_balance_health_rotlinear 0
+set g_balance_pause_health_rot 5
+set g_balance_pause_health_rot_spawn 10
+set g_balance_health_regenstable 100
+set g_balance_health_rotstable 100
+set g_balance_health_limit 999
+set g_balance_armor_regen 0
+set g_balance_armor_regenlinear 0
+set g_balance_armor_rot 0.1
+set g_balance_armor_rotlinear 0
+set g_balance_pause_armor_rot 5
+set g_balance_pause_armor_rot_spawn 10
+set g_balance_armor_regenstable 100
+set g_balance_armor_rotstable 100
+set g_balance_armor_limit 999
+set g_balance_armor_blockpercent 0.6
+set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
+set g_balance_fuel_regenlinear 0
+set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
+set g_balance_fuel_rot 0.05
+set g_balance_fuel_rotlinear 0
+set g_balance_pause_fuel_rot 5
+set g_balance_pause_fuel_rot_spawn 10
+set g_balance_fuel_regenstable 50
+set g_balance_fuel_rotstable 100
+set g_balance_fuel_limit 999
+// }}}
+
+// {{{ misc
+set g_balance_selfdamagepercent 0.6
+set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
+set g_weaponratefactor 1 "weapon fire rate multiplier"
+set g_weapondamagefactor 1 "weapon damage multiplier"
+set g_weaponforcefactor 1 "weapon force multiplier"
+set g_weaponspreadfactor 1 "weapon spread multiplier"
+set g_balance_firetransfer_time 0.9
+set g_balance_firetransfer_damage 0.8
+set g_throughfloor_damage 1
+set g_throughfloor_force 1
+set g_projectiles_damage 2
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
+// 0: only damage from contents (lava/slime) or exceptions
+// 1: only self damage or damage from contents or exceptions
+// 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
+set g_projectiles_newton_style 2
+// possible values:
+// 0: absolute velocity projectiles (like Quake)
+// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
+// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
+set g_projectiles_newton_style_2_minfactor 0.7
+set g_projectiles_newton_style_2_maxfactor 5
+set g_projectiles_spread_style 0
+// possible values:
+// 0: forward + solid sphere (like Quake) - varies velocity
+// 1: forward + flattened solid sphere
+// 2: forward + solid circle
+// 3: forward + normal distribution 3D - varies velocity
+// 4: forward + normal distribution on a plane
+// 5: forward + circle with 1-r falloff
+// 6: forward + circle with 1-r^2 falloff
+// 7: forward + circle with (1-r)(2-r) falloff
+set g_balance_falldamage_deadminspeed 150
+set g_balance_falldamage_minspeed 1400
+set g_balance_falldamage_factor 0.15
+set g_balance_falldamage_maxdamage 25
+set g_balance_damagepush_speedfactor 0
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
+// }}}
+
+// {{{ powerups
+set g_balance_powerup_invincible_takedamage 0.2
+set g_balance_powerup_invincible_time 30
+set g_balance_powerup_strength_damage 3
+set g_balance_powerup_strength_force 4
+set g_balance_powerup_strength_time 30
+set g_balance_powerup_strength_selfdamage 1.5
+set g_balance_powerup_strength_selfforce 1.5
+set g_balance_superweapons_time 30
+// }}}
+
+// {{{ jetpack/hook
+set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
+set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
+set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
+set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction"
+set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
+set g_jetpack_fuel 8 "fuel per second for jetpack"
+set g_jetpack_attenuation 2 "jetpack sound attenuation"
+
+set g_grappling_hook_tarzan 2 // 2: can also pull players
+set g_balance_grapplehook_speed_fly 1800
+set g_balance_grapplehook_speed_pull 2000
+set g_balance_grapplehook_force_rubber 2000
+set g_balance_grapplehook_force_rubber_overstretch 1000
+set g_balance_grapplehook_length_min 50
+set g_balance_grapplehook_stretch 50
+set g_balance_grapplehook_airfriction 0.2
+set g_balance_grapplehook_health 130
+set g_balance_grapplehook_damagedbycontents 0
+set g_balance_grapplehook_refire 0.2
+// }}}
+
+// {{{ weapon properties
+// {{{ laser
+set g_balance_laser_primary_damage 35
+set g_balance_laser_primary_edgedamage 10
+set g_balance_laser_primary_force 400
+set g_balance_laser_primary_radius 70
+set g_balance_laser_primary_speed 9000
+set g_balance_laser_primary_spread 0
+set g_balance_laser_primary_refire 0.7
+set g_balance_laser_primary_animtime 0.3
+set g_balance_laser_primary_lifetime 30
+set g_balance_laser_primary_shotangle 0
+set g_balance_laser_primary_delay 0.05
+set g_balance_laser_primary_gauntlet 0
+set g_balance_laser_primary_force_zscale 1
+set g_balance_laser_primary_force_velocitybias 0
+set g_balance_laser_primary_force_other_scale 1
+set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
+set g_balance_laser_secondary_damage 35
+set g_balance_laser_secondary_edgedamage 10
+set g_balance_laser_secondary_force 400
+set g_balance_laser_secondary_radius 70
+set g_balance_laser_secondary_speed 9000
+set g_balance_laser_secondary_spread 0
+set g_balance_laser_secondary_refire 0.7
+set g_balance_laser_secondary_animtime 0.3
+set g_balance_laser_secondary_lifetime 30
+set g_balance_laser_secondary_shotangle 0
+set g_balance_laser_secondary_delay 0
+set g_balance_laser_secondary_gauntlet 0
+set g_balance_laser_secondary_force_zscale 1
+set g_balance_laser_secondary_force_velocitybias 0
+set g_balance_laser_secondary_force_other_scale 1
+set g_balance_laser_switchdelay_drop 0.15
+set g_balance_laser_switchdelay_raise 0.15
+set g_balance_laser_reload_ammo 0 //default: 6
+set g_balance_laser_reload_time 2
+// }}}
+// {{{ shotgun
+set g_balance_shotgun_primary_bullets 6
+set g_balance_shotgun_primary_damage 9
+set g_balance_shotgun_primary_force 60
+set g_balance_shotgun_primary_spread 0.07
+set g_balance_shotgun_primary_refire 0.5
+set g_balance_shotgun_primary_animtime 0.2
+set g_balance_shotgun_primary_ammo 1
+set g_balance_shotgun_primary_solidpenetration 3.8
+set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
+set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 0
+set g_balance_shotgun_secondary_melee_multihit 1
+set g_balance_shotgun_secondary_damage 115
+set g_balance_shotgun_secondary_force 150
+set g_balance_shotgun_secondary_refire 1.1
+set g_balance_shotgun_secondary_animtime 1
+set g_balance_shotgun_switchdelay_drop 0.15
+set g_balance_shotgun_switchdelay_raise 0.15
+set g_balance_shotgun_reload_ammo 0 //default: 5
+set g_balance_shotgun_reload_time 2
+// }}}
+// {{{ uzi
+set g_balance_uzi_mode 0 				// Activates varible spread for sustained & burst mode secondary
+set g_balance_uzi_spread_min 0.02
+set g_balance_uzi_spread_max 0.6
+set g_balance_uzi_spread_add 0.012
+
+set g_balance_uzi_burst 0				// # of bullets in a burst (if set to 2 or more)
+set g_balance_uzi_burst_animtime 0.75
+set g_balance_uzi_burst_refire 0.05		// refire between burst bullets
+set g_balance_uzi_burst_refire2 0.75	// refire after burst
+set g_balance_uzi_burst_spread 0.04
+set g_balance_uzi_burst_damage 18
+set g_balance_uzi_burst_force 50
+set g_balance_uzi_burst_ammo 3
+
+set g_balance_uzi_first 1
+set g_balance_uzi_first_damage 30
+set g_balance_uzi_first_force 50
+set g_balance_uzi_first_spread 0.015
+set g_balance_uzi_first_refire 0.2
+set g_balance_uzi_first_ammo 1
+
+set g_balance_uzi_sustained_damage 15
+set g_balance_uzi_sustained_force 27
+set g_balance_uzi_sustained_spread 0.05
+set g_balance_uzi_sustained_refire 0.1
+set g_balance_uzi_sustained_ammo 1
+
+set g_balance_uzi_solidpenetration 13.1
+
+set g_balance_uzi_switchdelay_drop 0.15
+set g_balance_uzi_switchdelay_raise 0.15
+
+set g_balance_uzi_reload_ammo 0 //default: 30
+set g_balance_uzi_reload_time 2
+// }}}
+// {{{ mortar
+set g_balance_grenadelauncher_primary_type 0
+set g_balance_grenadelauncher_primary_damage 70
+set g_balance_grenadelauncher_primary_edgedamage 38
+set g_balance_grenadelauncher_primary_force 400
+set g_balance_grenadelauncher_primary_radius 140
+set g_balance_grenadelauncher_primary_speed 2000
+set g_balance_grenadelauncher_primary_speed_up 200
+set g_balance_grenadelauncher_primary_speed_z 0
+set g_balance_grenadelauncher_primary_spread 0
+set g_balance_grenadelauncher_primary_lifetime 30
+set g_balance_grenadelauncher_primary_lifetime2 1
+set g_balance_grenadelauncher_primary_refire 0.8
+set g_balance_grenadelauncher_primary_animtime 0.3
+set g_balance_grenadelauncher_primary_ammo 2
+set g_balance_grenadelauncher_primary_health 25
+set g_balance_grenadelauncher_primary_damageforcescale 4
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+
+set g_balance_grenadelauncher_secondary_type 1
+set g_balance_grenadelauncher_secondary_damage 70
+set g_balance_grenadelauncher_secondary_edgedamage 38
+set g_balance_grenadelauncher_secondary_force 400
+set g_balance_grenadelauncher_secondary_radius 140
+set g_balance_grenadelauncher_secondary_speed 1400
+set g_balance_grenadelauncher_secondary_speed_up 200
+set g_balance_grenadelauncher_secondary_speed_z 0
+set g_balance_grenadelauncher_secondary_spread 0
+set g_balance_grenadelauncher_secondary_lifetime 2.5
+set g_balance_grenadelauncher_secondary_lifetime_bounce 0
+set g_balance_grenadelauncher_secondary_lifetime_stick 0
+set g_balance_grenadelauncher_secondary_refire 0.7
+set g_balance_grenadelauncher_secondary_animtime 0.3
+set g_balance_grenadelauncher_secondary_ammo 2
+set g_balance_grenadelauncher_secondary_health 10
+set g_balance_grenadelauncher_secondary_damageforcescale 4
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
+
+set g_balance_grenadelauncher_bouncefactor 0.5
+set g_balance_grenadelauncher_bouncestop 0.075
+
+set g_balance_grenadelauncher_switchdelay_drop 0.15
+set g_balance_grenadelauncher_switchdelay_raise 0.15
+
+set g_balance_grenadelauncher_reload_ammo 0 //default: 12
+set g_balance_grenadelauncher_reload_time 2
+// }}}
+// {{{ electro
+set g_balance_electro_lightning 0
+set g_balance_electro_primary_damage 65
+set g_balance_electro_primary_edgedamage 0
+set g_balance_electro_primary_force 200
+set g_balance_electro_primary_force_up 0
+set g_balance_electro_primary_radius 150
+set g_balance_electro_primary_comboradius 0
+set g_balance_electro_primary_speed 2000
+set g_balance_electro_primary_spread 0
+set g_balance_electro_primary_lifetime 30
+set g_balance_electro_primary_refire 0.6
+set g_balance_electro_primary_animtime 0.3
+set g_balance_electro_primary_ammo 2
+set g_balance_electro_primary_range 0
+set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius
+set g_balance_electro_primary_falloff_maxdist 850
+set g_balance_electro_primary_falloff_halflifedist 425
+set g_balance_electro_secondary_damage 50
+set g_balance_electro_secondary_edgedamage 0
+set g_balance_electro_secondary_force 200
+set g_balance_electro_secondary_radius 150
+set g_balance_electro_secondary_speed 900
+set g_balance_electro_secondary_speed_up 200
+set g_balance_electro_secondary_speed_z 0
+set g_balance_electro_secondary_spread 0
+set g_balance_electro_secondary_lifetime 5
+set g_balance_electro_secondary_refire 0.3
+set g_balance_electro_secondary_refire2 0
+set g_balance_electro_secondary_animtime 0.3
+set g_balance_electro_secondary_ammo 2
+set g_balance_electro_secondary_health 5
+set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_damagedbycontents 0
+set g_balance_electro_secondary_count 1
+set g_balance_electro_secondary_bouncefactor 0.5
+set g_balance_electro_secondary_bouncestop 0.075
+set g_balance_electro_combo_damage 80
+set g_balance_electro_combo_edgedamage 0
+set g_balance_electro_combo_force 200
+set g_balance_electro_combo_radius 250
+set g_balance_electro_combo_comboradius 0
+set g_balance_electro_combo_speed 2000
+set g_balance_electro_combo_safeammocheck 0
+set g_balance_electro_switchdelay_drop 0.15
+set g_balance_electro_switchdelay_raise 0.15
+set g_balance_electro_reload_ammo 0 //default: 20
+set g_balance_electro_reload_time 2
+// }}}
+// {{{ crylink
+set g_balance_crylink_primary_damage 18
+set g_balance_crylink_primary_edgedamage 0
+set g_balance_crylink_primary_force -55
+set g_balance_crylink_primary_radius 80
+set g_balance_crylink_primary_speed 7000
+set g_balance_crylink_primary_spread 0.03
+set g_balance_crylink_primary_shots 4
+set g_balance_crylink_primary_bounces 1
+set g_balance_crylink_primary_refire 0.4
+set g_balance_crylink_primary_animtime 0.3
+set g_balance_crylink_primary_ammo 2
+set g_balance_crylink_primary_bouncedamagefactor 0.5
+set g_balance_crylink_primary_joindelay 0
+set g_balance_crylink_primary_joinspread 0
+set g_balance_crylink_primary_joinexplode 0
+set g_balance_crylink_primary_joinexplode_damage 0
+set g_balance_crylink_primary_joinexplode_edgedamage 0
+set g_balance_crylink_primary_joinexplode_radius 0
+set g_balance_crylink_primary_joinexplode_force 0
+set g_balance_crylink_primary_linkexplode 1
+
+set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_primary_middle_fadetime 5
+set g_balance_crylink_primary_other_lifetime 0.1 // range: 700 full, fades to 2450
+set g_balance_crylink_primary_other_fadetime 0.25
+
+set g_balance_crylink_secondary 1
+set g_balance_crylink_secondary_damage 18
+set g_balance_crylink_secondary_edgedamage 0
+set g_balance_crylink_secondary_force -55
+set g_balance_crylink_secondary_radius 3
+set g_balance_crylink_secondary_speed 7000
+set g_balance_crylink_secondary_spread 0.08
+set g_balance_crylink_secondary_spreadtype 0
+set g_balance_crylink_secondary_shots 7
+set g_balance_crylink_secondary_bounces 0
+set g_balance_crylink_secondary_refire 0.5
+set g_balance_crylink_secondary_animtime 0.3
+set g_balance_crylink_secondary_ammo 2
+set g_balance_crylink_secondary_bouncedamagefactor 0.5
+set g_balance_crylink_secondary_joindelay 0
+set g_balance_crylink_secondary_joinspread 0
+set g_balance_crylink_secondary_joinexplode 0
+set g_balance_crylink_secondary_joinexplode_damage 0
+set g_balance_crylink_secondary_joinexplode_edgedamage 0
+set g_balance_crylink_secondary_joinexplode_radius 0
+set g_balance_crylink_secondary_joinexplode_force 0
+set g_balance_crylink_secondary_linkexplode 1
+
+set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_secondary_middle_fadetime 5
+set g_balance_crylink_secondary_line_lifetime 2 // range: 35000 full, fades to 70000
+set g_balance_crylink_secondary_line_fadetime 2
+
+set g_balance_crylink_switchdelay_drop 0.15
+set g_balance_crylink_switchdelay_raise 0.15
+
+set g_balance_crylink_reload_ammo 0 //default: 10
+set g_balance_crylink_reload_time 2
+// }}}
+// {{{ nex
+set g_balance_nex_primary_damage 100
+set g_balance_nex_primary_force 600
+set g_balance_nex_primary_refire 1.5
+set g_balance_nex_primary_animtime 0.3
+set g_balance_nex_primary_ammo 5
+set g_balance_nex_primary_damagefalloff_mindist 0
+set g_balance_nex_primary_damagefalloff_maxdist 0
+set g_balance_nex_primary_damagefalloff_halflife 0
+set g_balance_nex_primary_damagefalloff_forcehalflife 0
+
+set g_balance_nex_secondary 0
+set g_balance_nex_secondary_charge 0
+set g_balance_nex_secondary_charge_rate 0.1
+set g_balance_nex_secondary_chargepool 0
+set g_balance_nex_secondary_chargepool_regen 0.15
+set g_balance_nex_secondary_chargepool_pause_regen 1
+set g_balance_nex_secondary_chargepool_pause_health_regen 1
+set g_balance_nex_secondary_damage 100
+set g_balance_nex_secondary_force 600
+set g_balance_nex_secondary_refire 1.5
+set g_balance_nex_secondary_animtime 0.3
+set g_balance_nex_secondary_ammo 5
+set g_balance_nex_secondary_damagefalloff_mindist 0
+set g_balance_nex_secondary_damagefalloff_maxdist 0
+set g_balance_nex_secondary_damagefalloff_halflife 0
+set g_balance_nex_secondary_damagefalloff_forcehalflife 0
+
+set g_balance_nex_charge 0
+set g_balance_nex_charge_mindmg 40
+set g_balance_nex_charge_start 0
+set g_balance_nex_charge_rate 0.1
+set g_balance_nex_charge_animlimit 0.5
+set g_balance_nex_charge_limit 0.5
+set g_balance_nex_charge_rot_rate 0
+set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button
+set g_balance_nex_charge_shot_multiplier 0.5
+set g_balance_nex_charge_velocity_rate 0.2
+set g_balance_nex_charge_minspeed 400
+set g_balance_nex_charge_maxspeed 1000
+
+set g_balance_nex_switchdelay_drop 0.15
+set g_balance_nex_switchdelay_raise 0.15
+
+set g_balance_nex_reload_ammo 0 //default: 25
+set g_balance_nex_reload_time 2
+// }}}
+// {{{ minstanex
+set g_balance_minstanex_refire 1
+set g_balance_minstanex_animtime 0.3
+set g_balance_minstanex_ammo 10
+set g_balance_minstanex_laser_ammo 0
+set g_balance_minstanex_laser_animtime 0.3
+set g_balance_minstanex_laser_refire 0.7
+set g_balance_minstanex_switchdelay_drop 0.15
+set g_balance_minstanex_switchdelay_raise 0.15
+set g_balance_minstanex_reload_ammo 0 //default: 50
+set g_balance_minstanex_reload_time 2
+// }}}
+// {{{ hagar
+set g_balance_hagar_primary_damage 37
+set g_balance_hagar_primary_edgedamage 15
+set g_balance_hagar_primary_force 100
+set g_balance_hagar_primary_health 0
+set g_balance_hagar_primary_damageforcescale 0
+set g_balance_hagar_primary_radius 65
+set g_balance_hagar_primary_spread 0.010
+set g_balance_hagar_primary_speed 3000
+set g_balance_hagar_primary_lifetime 30
+set g_balance_hagar_primary_refire 0.15
+set g_balance_hagar_primary_ammo 1
+set g_balance_hagar_secondary 1
+set g_balance_hagar_secondary_load 0
+set g_balance_hagar_secondary_load_speed 0.6
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
+set g_balance_hagar_secondary_load_max 4
+set g_balance_hagar_secondary_load_hold 0
+set g_balance_hagar_secondary_load_releasedeath 1
+set g_balance_hagar_secondary_load_abort 1
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
+set g_balance_hagar_secondary_damage 37
+set g_balance_hagar_secondary_edgedamage 15
+set g_balance_hagar_secondary_force 100
+set g_balance_hagar_secondary_health 0
+set g_balance_hagar_secondary_damageforcescale 0
+set g_balance_hagar_secondary_radius 65
+set g_balance_hagar_secondary_spread 0.015
+set g_balance_hagar_secondary_speed 1400
+set g_balance_hagar_secondary_lifetime_min 30
+set g_balance_hagar_secondary_lifetime_rand 0
+set g_balance_hagar_secondary_refire 0.15
+set g_balance_hagar_secondary_ammo 1
+set g_balance_hagar_switchdelay_drop 0.15
+set g_balance_hagar_switchdelay_raise 0.15
+set g_balance_hagar_reload_ammo 0 //default: 25
+set g_balance_hagar_reload_time 2
+// }}}
+// {{{ rocketlauncher
+set g_balance_rocketlauncher_damage 105
+set g_balance_rocketlauncher_edgedamage 40
+set g_balance_rocketlauncher_force 600
+set g_balance_rocketlauncher_radius 150
+set g_balance_rocketlauncher_speed 850
+set g_balance_rocketlauncher_speedaccel 0
+set g_balance_rocketlauncher_speedstart 850
+set g_balance_rocketlauncher_lifetime 30
+set g_balance_rocketlauncher_refire 1
+set g_balance_rocketlauncher_animtime 0.3
+set g_balance_rocketlauncher_ammo 3
+set g_balance_rocketlauncher_health 40
+set g_balance_rocketlauncher_damageforcescale 4
+set g_balance_rocketlauncher_detonatedelay 0.2 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_rocketlauncher_guiderate 90 // max degrees per second
+set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
+set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
+set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in
+set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again
+set g_balance_rocketlauncher_remote_damage 105
+set g_balance_rocketlauncher_remote_edgedamage 40
+set g_balance_rocketlauncher_remote_radius 150
+set g_balance_rocketlauncher_remote_force 600
+set g_balance_rocketlauncher_switchdelay_drop 0.15
+set g_balance_rocketlauncher_switchdelay_raise 0.15
+set g_balance_rocketlauncher_reload_ammo 0 //default: 25
+set g_balance_rocketlauncher_reload_time 2
+// }}}
+// {{{ porto
+set g_balance_porto_primary_refire 1.5
+set g_balance_porto_primary_animtime 0.3
+set g_balance_porto_primary_speed 2000
+set g_balance_porto_primary_lifetime 30
+set g_balance_porto_secondary 0
+set g_balance_porto_secondary_refire 1.5
+set g_balance_porto_secondary_animtime 0.3
+set g_balance_porto_secondary_speed 2000
+set g_balance_porto_secondary_lifetime 30
+set g_balance_porto_switchdelay_drop 0.15
+set g_balance_porto_switchdelay_raise 0.15
+set g_balance_portal_health 200 // these get recharged whenever the portal is used
+set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
+// }}}
+// {{{ hook
+set g_balance_hook_primary_fuel 5 // hook monkeys set 0
+set g_balance_hook_primary_refire 0.2 // hook monkeys set 0
+set g_balance_hook_primary_animtime 0.3 // good shoot anim
+set g_balance_hook_primary_hooked_time_max 0 // infinite
+set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
+set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked
+set g_balance_hook_secondary_damage 25 // not much
+set g_balance_hook_secondary_edgedamage 5 // not much
+set g_balance_hook_secondary_radius 500 // LOTS
+set g_balance_hook_secondary_force -2000 // LOTS
+set g_balance_hook_secondary_ammo 50 // a whole pack
+set g_balance_hook_secondary_lifetime 30 // infinite
+set g_balance_hook_secondary_speed 0 // not much throwing
+set g_balance_hook_secondary_gravity 5 // fast falling
+set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
+set g_balance_hook_secondary_animtime 0.3 // good shoot anim
+set g_balance_hook_secondary_power 3 // effect behaves like a square function
+set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 0
+set g_balance_hook_secondary_damageforcescale 0
+set g_balance_hook_switchdelay_drop 0.15
+set g_balance_hook_switchdelay_raise 0.15
+// }}}
+// {{{ tuba
+set g_balance_tuba_refire 0.05
+set g_balance_tuba_animtime 0.05
+set g_balance_tuba_attenuation 0.5
+set g_balance_tuba_volume 1
+set g_balance_tuba_fadetime 0.25
+set g_balance_tuba_damage 5
+set g_balance_tuba_edgedamage 0
+set g_balance_tuba_radius 200
+set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
+set g_balance_tuba_switchdelay_drop 0.15
+set g_balance_tuba_switchdelay_raise 0.15
+// }}}
+// {{{ fireball
+set g_balance_fireball_primary_animtime 0.15
+set g_balance_fireball_primary_bfgdamage 100
+set g_balance_fireball_primary_bfgforce 0
+set g_balance_fireball_primary_bfgradius 1000
+set g_balance_fireball_primary_damage 200
+set g_balance_fireball_primary_damageforcescale 4
+set g_balance_fireball_primary_edgedamage 0
+set g_balance_fireball_primary_force 700
+set g_balance_fireball_primary_health 50
+set g_balance_fireball_primary_laserburntime 0.5
+set g_balance_fireball_primary_laserdamage 80
+set g_balance_fireball_primary_laseredgedamage 20
+set g_balance_fireball_primary_laserradius 256
+set g_balance_fireball_primary_lifetime 15
+set g_balance_fireball_primary_radius 200
+set g_balance_fireball_primary_refire 5
+set g_balance_fireball_primary_refire2 0
+set g_balance_fireball_primary_speed 650
+set g_balance_fireball_primary_spread 0
+set g_balance_fireball_secondary_animtime 0.3
+set g_balance_fireball_secondary_damage 40
+set g_balance_fireball_secondary_damageforcescale 4
+set g_balance_fireball_secondary_damagetime 5
+set g_balance_fireball_secondary_force 100
+set g_balance_fireball_secondary_laserburntime 0.5
+set g_balance_fireball_secondary_laserdamage 50
+set g_balance_fireball_secondary_laseredgedamage 20
+set g_balance_fireball_secondary_laserradius 110
+set g_balance_fireball_secondary_lifetime 7
+set g_balance_fireball_secondary_refire 2
+set g_balance_fireball_secondary_speed 900
+set g_balance_fireball_secondary_speed_up 100
+set g_balance_fireball_secondary_speed_z 0
+set g_balance_fireball_secondary_spread 0
+set g_balance_fireball_switchdelay_drop 0.15
+set g_balance_fireball_switchdelay_raise 0.15
+// }}}
diff --git a/balanceFruitieX.cfg b/balanceFruitieX.cfg
new file mode 100644
index 000000000..99d458d1d
--- /dev/null
+++ b/balanceFruitieX.cfg
@@ -0,0 +1,706 @@
+g_mod_balance FruitieX
+
+// {{{ starting gear
+set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_balance_health_start 125
+set g_balance_armor_start 0
+set g_start_ammo_shells 20
+set g_start_ammo_nails 0
+set g_start_ammo_rockets 0
+set g_start_ammo_cells 0
+set g_start_ammo_fuel 0
+set g_warmup_start_health 200 "starting values when being in warmup-stage"
+set g_warmup_start_armor 100 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
+set g_lms_start_health 200
+set g_lms_start_armor 100
+set g_lms_start_ammo_shells 30
+set g_lms_start_ammo_nails 200
+set g_lms_start_ammo_rockets 150
+set g_lms_start_ammo_cells 150
+set g_lms_start_ammo_fuel 0
+set g_balance_nix_roundtime 25
+set g_balance_nix_incrtime 1.6
+set g_balance_nix_ammo_shells 15
+set g_balance_nix_ammo_nails 45
+set g_balance_nix_ammo_rockets 15
+set g_balance_nix_ammo_cells 15
+set g_balance_nix_ammo_fuel 0
+set g_balance_nix_ammoincr_shells 2
+set g_balance_nix_ammoincr_nails 6
+set g_balance_nix_ammoincr_rockets 2
+set g_balance_nix_ammoincr_cells 2
+set g_balance_nix_ammoincr_fuel 2
+// }}}
+
+// {{{ pickup items
+set g_pickup_ammo_anyway 1
+set g_pickup_weapons_anyway 1
+set g_pickup_shells 20
+set g_pickup_shells_weapon 10
+set g_pickup_shells_max 45
+set g_pickup_nails 120
+set g_pickup_nails_weapon 60
+set g_pickup_nails_max 300
+set g_pickup_rockets 25
+set g_pickup_rockets_weapon 15
+set g_pickup_rockets_max 150
+set g_pickup_cells 30
+set g_pickup_cells_weapon 20
+set g_pickup_cells_max 150
+set g_pickup_fuel 25
+set g_pickup_fuel_weapon 15
+set g_pickup_fuel_jetpack 50
+set g_pickup_fuel_max 100
+set g_pickup_armorsmall 5
+set g_pickup_armorsmall_max 150
+set g_pickup_armorsmall_anyway 1
+set g_pickup_armormedium 25
+set g_pickup_armormedium_max 50
+set g_pickup_armormedium_anyway 0
+set g_pickup_armorbig 50
+set g_pickup_armorbig_max 75; // LOG: to allow a little more armor from medium armor
+set g_pickup_armorbig_anyway 0
+set g_pickup_armorlarge 100
+set g_pickup_armorlarge_max 150
+set g_pickup_armorlarge_anyway 1
+set g_pickup_healthsmall 5
+set g_pickup_healthsmall_max 250
+set g_pickup_healthsmall_anyway 1
+set g_pickup_healthmedium 25
+set g_pickup_healthmedium_max 100
+set g_pickup_healthmedium_anyway 0
+set g_pickup_healthlarge 50
+set g_pickup_healthlarge_max 150
+set g_pickup_healthlarge_anyway 0
+set g_pickup_healthmega 100
+set g_pickup_healthmega_max 250
+set g_pickup_healthmega_anyway 1
+set g_pickup_respawntime_short 15
+set g_pickup_respawntime_medium 20
+set g_pickup_respawntime_long 30
+set g_pickup_respawntime_powerup 120
+set g_pickup_respawntime_weapon 10
+set g_pickup_respawntime_superweapon 120
+set g_pickup_respawntime_ammo 25
+set g_pickup_respawntimejitter_short 0
+set g_pickup_respawntimejitter_medium 0
+set g_pickup_respawntimejitter_long 0
+set g_pickup_respawntimejitter_powerup 10
+set g_pickup_respawntimejitter_weapon 0
+set g_pickup_respawntimejitter_superweapon 10
+set g_pickup_respawntimejitter_ammo 0
+// }}}
+
+// {{{ regen/rot
+set g_balance_health_regen 0.05
+set g_balance_health_regenlinear 0
+set g_balance_pause_health_regen 5
+set g_balance_pause_health_regen_spawn 0
+set g_balance_health_rot 0
+set g_balance_health_rotlinear 1
+set g_balance_pause_health_rot 1
+set g_balance_pause_health_rot_spawn 0
+set g_balance_health_regenstable 100
+set g_balance_health_rotstable 100
+set g_balance_health_limit 999
+set g_balance_armor_regen 0
+set g_balance_armor_regenlinear 0
+set g_balance_armor_rot 0
+set g_balance_armor_rotlinear 1
+set g_balance_pause_armor_rot 1
+set g_balance_pause_armor_rot_spawn 0
+set g_balance_armor_regenstable 100
+set g_balance_armor_rotstable 100
+set g_balance_armor_limit 999
+set g_balance_armor_blockpercent 0.7
+set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
+set g_balance_fuel_regenlinear 0
+set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
+set g_balance_fuel_rot 0.05
+set g_balance_fuel_rotlinear 0
+set g_balance_pause_fuel_rot 5
+set g_balance_pause_fuel_rot_spawn 10
+set g_balance_fuel_regenstable 50
+set g_balance_fuel_rotstable 100
+set g_balance_fuel_limit 999
+// }}}
+
+// {{{ misc
+set g_balance_selfdamagepercent 0.65
+set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
+set g_weaponratefactor 1 "weapon fire rate multiplier"
+set g_weapondamagefactor 1 "weapon damage multiplier"
+set g_weaponforcefactor 1 "weapon force multiplier"
+set g_weaponspreadfactor 1 "weapon spread multiplier"
+set g_balance_firetransfer_time 0.9
+set g_balance_firetransfer_damage 0.8
+set g_throughfloor_damage 0.7
+set g_throughfloor_force 0.8
+set g_projectiles_damage 2
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
+// 0: only damage from contents (lava/slime) or exceptions
+// 1: only self damage or damage from contents or exceptions
+// 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
+set g_projectiles_newton_style 2
+// possible values:
+// 0: absolute velocity projectiles (like Quake)
+// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
+// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
+set g_projectiles_newton_style_2_minfactor 0.7
+set g_projectiles_newton_style_2_maxfactor 5
+set g_projectiles_spread_style 7
+// possible values:
+// 0: forward + solid sphere (like Quake) - varies velocity
+// 1: forward + flattened solid sphere
+// 2: forward + solid circle
+// 3: forward + normal distribution 3D - varies velocity
+// 4: forward + normal distribution on a plane
+// 5: forward + circle with 1-r falloff
+// 6: forward + circle with 1-r^2 falloff
+// 7: forward + circle with (1-r)(2-r) falloff
+set g_balance_falldamage_deadminspeed 150
+set g_balance_falldamage_minspeed 800
+set g_balance_falldamage_factor 0.20
+set g_balance_falldamage_maxdamage 15
+set g_balance_damagepush_speedfactor 2.5
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
+// }}}
+
+// {{{ powerups
+set g_balance_powerup_invincible_takedamage 0.6
+set g_balance_powerup_invincible_time 30
+set g_balance_powerup_strength_damage 3
+set g_balance_powerup_strength_force 4
+set g_balance_powerup_strength_time 30
+set g_balance_powerup_strength_selfdamage 1.5
+set g_balance_powerup_strength_selfforce 1.5
+set g_balance_superweapons_time 30
+// }}}
+
+// {{{ jetpack/hook
+set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
+set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
+set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
+set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction"
+set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
+set g_jetpack_fuel 8 "fuel per second for jetpack"
+set g_jetpack_attenuation 2 "jetpack sound attenuation"
+
+set g_grappling_hook_tarzan 2 // 2: can also pull players
+set g_balance_grapplehook_speed_fly 1800
+set g_balance_grapplehook_speed_pull 2000
+set g_balance_grapplehook_force_rubber 2000
+set g_balance_grapplehook_force_rubber_overstretch 1000
+set g_balance_grapplehook_length_min 50
+set g_balance_grapplehook_stretch 50
+set g_balance_grapplehook_airfriction 0.2
+set g_balance_grapplehook_health 130
+set g_balance_grapplehook_damagedbycontents 0
+set g_balance_grapplehook_refire 0.2
+// }}}
+
+// {{{ weapon properties
+// {{{ laser
+set g_balance_laser_primary_damage 20 // dps 33, hope that's not too high
+set g_balance_laser_primary_edgedamage 20
+set g_balance_laser_primary_force 150 // this looks insanely low, but actually isn't with zscale and velocitybias
+set g_balance_laser_primary_radius 60
+set g_balance_laser_primary_speed 5000
+set g_balance_laser_primary_spread 0
+set g_balance_laser_primary_refire 0.6
+set g_balance_laser_primary_animtime 0.4
+set g_balance_laser_primary_lifetime 5
+set g_balance_laser_primary_shotangle 0
+set g_balance_laser_primary_delay 0
+set g_balance_laser_primary_gauntlet 0
+set g_balance_laser_primary_force_zscale 2 // 300 upforce
+set g_balance_laser_primary_force_velocitybias 0.3
+set g_balance_laser_primary_force_other_scale 2.5 // force 375 when pushing others around
+set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
+set g_balance_laser_secondary_damage 200 // dps
+set g_balance_laser_secondary_edgedamage 0
+set g_balance_laser_secondary_force 1300
+set g_balance_laser_secondary_radius 60
+set g_balance_laser_secondary_speed 0
+set g_balance_laser_secondary_spread 0
+set g_balance_laser_secondary_refire 0.066
+set g_balance_laser_secondary_animtime 0.066
+set g_balance_laser_secondary_lifetime 0
+set g_balance_laser_secondary_shotangle 0
+set g_balance_laser_secondary_delay 0
+set g_balance_laser_secondary_gauntlet 1
+set g_balance_laser_secondary_force_zscale 1.25
+set g_balance_laser_secondary_force_velocitybias 0
+set g_balance_laser_secondary_force_other_scale 0
+set g_balance_laser_switchdelay_drop 0.15
+set g_balance_laser_switchdelay_raise 0.15
+set g_balance_laser_reload_ammo 0 //default: 6
+set g_balance_laser_reload_time 2
+// }}}
+// {{{ shotgun
+set g_balance_shotgun_primary_bullets 18
+set g_balance_shotgun_primary_damage 3.5 // LOG: changed from 4 to 3.5, total damage 63
+set g_balance_shotgun_primary_force 20
+set g_balance_shotgun_primary_spread 0.16 // LOG: changed from 0.18 -> 0.16 to compensate a little for lower damage
+set g_balance_shotgun_primary_refire 1
+set g_balance_shotgun_primary_animtime 0.3
+set g_balance_shotgun_primary_ammo 1
+set g_balance_shotgun_primary_solidpenetration 3.8
+set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
+set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 0
+set g_balance_shotgun_secondary_melee_multihit 1
+set g_balance_shotgun_secondary_damage 110
+set g_balance_shotgun_secondary_force 150
+set g_balance_shotgun_secondary_refire 1.1
+set g_balance_shotgun_secondary_animtime 1
+set g_balance_shotgun_switchdelay_drop 0.15
+set g_balance_shotgun_switchdelay_raise 0.15
+set g_balance_shotgun_reload_ammo 0 //default: 5
+set g_balance_shotgun_reload_time 2
+// }}}
+// {{{ uzi
+set g_balance_uzi_mode 1 				// Activates varible spread for sustained & burst mode secondary
+set g_balance_uzi_spread_min 0.02
+set g_balance_uzi_spread_max 0.3 // LOG: 0.6 -> 0.3
+set g_balance_uzi_spread_add 0.008
+
+set g_balance_uzi_burst 3				// # of bullets in a burst (if set to 2 or more)
+set g_balance_uzi_burst_animtime 0.45
+set g_balance_uzi_burst_refire 0.05		// refire between burst bullets
+set g_balance_uzi_burst_refire2 0.45 	// refire after burst
+set g_balance_uzi_burst_spread 0.07
+set g_balance_uzi_burst_damage 25
+set g_balance_uzi_burst_force 50
+set g_balance_uzi_burst_ammo 3
+
+set g_balance_uzi_first 1
+set g_balance_uzi_first_damage 15 / f/ LOG: 22 -> 15
+set g_balance_uzi_first_force 50
+set g_balance_uzi_first_spread 0.03
+set g_balance_uzi_first_refire 0.2
+set g_balance_uzi_first_ammo 2
+
+set g_balance_uzi_sustained_damage 12   // 120 dps
+set g_balance_uzi_sustained_force 12
+set g_balance_uzi_sustained_spread 0.06
+set g_balance_uzi_sustained_refire 0.1
+set g_balance_uzi_sustained_ammo 1
+
+set g_balance_uzi_solidpenetration 13.1
+
+set g_balance_uzi_switchdelay_drop 0.15
+set g_balance_uzi_switchdelay_raise 0.15
+
+set g_balance_uzi_reload_ammo 0 //default: 30
+set g_balance_uzi_reload_time 2
+// }}}
+// {{{ mortar
+set g_balance_grenadelauncher_primary_type 0
+set g_balance_grenadelauncher_primary_damage 44
+set g_balance_grenadelauncher_primary_edgedamage 32
+set g_balance_grenadelauncher_primary_force 300
+set g_balance_grenadelauncher_primary_radius 115
+set g_balance_grenadelauncher_primary_speed 1500
+set g_balance_grenadelauncher_primary_speed_up 225
+set g_balance_grenadelauncher_primary_speed_z 0
+set g_balance_grenadelauncher_primary_spread 0
+set g_balance_grenadelauncher_primary_lifetime 5
+set g_balance_grenadelauncher_primary_lifetime2 0.65
+set g_balance_grenadelauncher_primary_refire 0.8
+set g_balance_grenadelauncher_primary_animtime 0.3
+set g_balance_grenadelauncher_primary_ammo 2
+set g_balance_grenadelauncher_primary_health 80
+set g_balance_grenadelauncher_primary_damageforcescale 0
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+
+set g_balance_grenadelauncher_secondary_type 1
+set g_balance_grenadelauncher_secondary_damage 62
+set g_balance_grenadelauncher_secondary_edgedamage 32
+set g_balance_grenadelauncher_secondary_force 300
+set g_balance_grenadelauncher_secondary_radius 150
+set g_balance_grenadelauncher_secondary_speed 1000
+set g_balance_grenadelauncher_secondary_speed_up 250
+set g_balance_grenadelauncher_secondary_speed_z 0
+set g_balance_grenadelauncher_secondary_spread 0
+set g_balance_grenadelauncher_secondary_lifetime 3
+set g_balance_grenadelauncher_secondary_lifetime_bounce 0
+set g_balance_grenadelauncher_secondary_lifetime_stick 0.65
+set g_balance_grenadelauncher_secondary_refire 0.8
+set g_balance_grenadelauncher_secondary_animtime 0.3
+set g_balance_grenadelauncher_secondary_ammo 2
+set g_balance_grenadelauncher_secondary_health 40
+set g_balance_grenadelauncher_secondary_damageforcescale 0
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
+
+set g_balance_grenadelauncher_bouncefactor 0.5
+set g_balance_grenadelauncher_bouncestop 0.12
+
+set g_balance_grenadelauncher_switchdelay_drop 0.15
+set g_balance_grenadelauncher_switchdelay_raise 0.15
+
+set g_balance_grenadelauncher_reload_ammo 0 //default: 12
+set g_balance_grenadelauncher_reload_time 2
+// }}}
+// {{{ electro
+set g_balance_electro_lightning 1
+set g_balance_electro_primary_damage 100
+set g_balance_electro_primary_edgedamage 0
+set g_balance_electro_primary_force 425
+set g_balance_electro_primary_force_up 125
+set g_balance_electro_primary_radius 850
+set g_balance_electro_primary_comboradius 150
+set g_balance_electro_primary_speed 0
+set g_balance_electro_primary_spread 0
+set g_balance_electro_primary_lifetime 0
+set g_balance_electro_primary_refire 0.4
+set g_balance_electro_primary_animtime 0.2
+set g_balance_electro_primary_ammo 5
+set g_balance_electro_primary_range 800
+set g_balance_electro_primary_falloff_mindist 0
+set g_balance_electro_primary_falloff_maxdist 0
+set g_balance_electro_primary_falloff_halflifedist 0
+set g_balance_electro_secondary_damage 25
+set g_balance_electro_secondary_edgedamage 0
+set g_balance_electro_secondary_force 100
+set g_balance_electro_secondary_radius 100
+set g_balance_electro_secondary_speed 700
+set g_balance_electro_secondary_speed_up 200
+set g_balance_electro_secondary_speed_z 0
+set g_balance_electro_secondary_spread 0.08
+set g_balance_electro_secondary_lifetime 3.5
+set g_balance_electro_secondary_refire 0.2
+set g_balance_electro_secondary_refire2 2
+set g_balance_electro_secondary_animtime 0.2
+set g_balance_electro_secondary_ammo 2
+set g_balance_electro_secondary_health 10
+set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_damagedbycontents 0
+set g_balance_electro_secondary_count 3
+set g_balance_electro_secondary_bouncefactor 0.5
+set g_balance_electro_secondary_bouncestop 0.075
+set g_balance_electro_combo_damage 50
+set g_balance_electro_combo_edgedamage 0
+set g_balance_electro_combo_force 80
+set g_balance_electro_combo_radius 250
+set g_balance_electro_combo_comboradius 0
+set g_balance_electro_combo_speed 400
+set g_balance_electro_combo_safeammocheck 1
+set g_balance_electro_switchdelay_drop 0.15
+set g_balance_electro_switchdelay_raise 0.15
+set g_balance_electro_reload_ammo 0 //default: 20
+set g_balance_electro_reload_time 2
+// }}}
+// {{{ crylink
+set g_balance_crylink_primary_damage 7 // LOG: 10 -> 7
+set g_balance_crylink_primary_edgedamage 4 // LOG: 6 -> 4
+set g_balance_crylink_primary_force 35
+set g_balance_crylink_primary_radius 80
+set g_balance_crylink_primary_speed 1500
+set g_balance_crylink_primary_spread 0.05
+set g_balance_crylink_primary_shots 7
+set g_balance_crylink_primary_bounces 2
+set g_balance_crylink_primary_refire 0.8
+set g_balance_crylink_primary_animtime 0.3
+set g_balance_crylink_primary_ammo 2
+set g_balance_crylink_primary_bouncedamagefactor 0.2
+set g_balance_crylink_primary_joindelay 0
+set g_balance_crylink_primary_joinspread 0.2
+set g_balance_crylink_primary_joinexplode 0
+set g_balance_crylink_primary_joinexplode_damage 0
+set g_balance_crylink_primary_joinexplode_edgedamage 0
+set g_balance_crylink_primary_joinexplode_radius 0
+set g_balance_crylink_primary_joinexplode_force 0
+set g_balance_crylink_primary_linkexplode 1
+
+set g_balance_crylink_primary_middle_lifetime 5 // range: 10000 full, fades to 20000
+set g_balance_crylink_primary_middle_fadetime 5
+set g_balance_crylink_primary_other_lifetime 2 // range: 800 full, fades to 1300
+set g_balance_crylink_primary_other_fadetime 0.25
+
+set g_balance_crylink_secondary 1
+set g_balance_crylink_secondary_damage 5 // LOG: 8 -> 5
+set g_balance_crylink_secondary_edgedamage 3
+set g_balance_crylink_secondary_force 16 // LOG: 20 -> 16
+set g_balance_crylink_secondary_radius 15 // LOG: 20 -> 15
+set g_balance_crylink_secondary_speed 1250 // LOG: 1500 -> 1250
+set g_balance_crylink_secondary_spread 0.1
+set g_balance_crylink_secondary_spreadtype 0
+set g_balance_crylink_secondary_shots 6
+set g_balance_crylink_secondary_bounces 2
+set g_balance_crylink_secondary_refire 0.9 // LOG: 0.8 -> 0.9
+set g_balance_crylink_secondary_animtime 0.3
+set g_balance_crylink_secondary_ammo 3 // LOG: 2 -> 3
+set g_balance_crylink_secondary_bouncedamagefactor 0.4 // LOG: 0.2 -> 0.4
+set g_balance_crylink_secondary_joindelay 0
+set g_balance_crylink_secondary_joinspread 0.2
+set g_balance_crylink_secondary_joinexplode 0
+set g_balance_crylink_secondary_joinexplode_damage 0
+set g_balance_crylink_secondary_joinexplode_edgedamage 0
+set g_balance_crylink_secondary_joinexplode_radius 0
+set g_balance_crylink_secondary_joinexplode_force 0
+set g_balance_crylink_secondary_linkexplode 0
+
+set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to 10000
+set g_balance_crylink_secondary_middle_fadetime 5
+set g_balance_crylink_secondary_line_lifetime 2 // range: 4000 full, fades to 8000
+set g_balance_crylink_secondary_line_fadetime 0.25
+
+set g_balance_crylink_switchdelay_drop 0.15
+set g_balance_crylink_switchdelay_raise 0.15
+
+set g_balance_crylink_reload_ammo 0 //default: 10
+set g_balance_crylink_reload_time 2
+// }}}
+// {{{ nex
+set g_balance_nex_primary_damage 90
+set g_balance_nex_primary_force 500
+set g_balance_nex_primary_refire 1
+set g_balance_nex_primary_animtime 0.3
+set g_balance_nex_primary_ammo 5
+set g_balance_nex_primary_damagefalloff_mindist 0
+set g_balance_nex_primary_damagefalloff_maxdist 0
+set g_balance_nex_primary_damagefalloff_halflife 0
+set g_balance_nex_primary_damagefalloff_forcehalflife 0
+
+set g_balance_nex_secondary 0 // LOG: disable secondary
+set g_balance_nex_secondary_charge 0 // LOG: disable secondary charge
+set g_balance_nex_secondary_charge_rate 0.4
+set g_balance_nex_secondary_chargepool 1
+set g_balance_nex_secondary_chargepool_regen 0.25
+set g_balance_nex_secondary_chargepool_pause_regen 2
+set g_balance_nex_secondary_chargepool_pause_health_regen 0.5
+set g_balance_nex_secondary_damage 0
+set g_balance_nex_secondary_force 0
+set g_balance_nex_secondary_refire 0
+set g_balance_nex_secondary_animtime 0
+set g_balance_nex_secondary_ammo 0.4 // full charge pool is 1, so it depletes in 2.5 secs
+set g_balance_nex_secondary_damagefalloff_mindist 0
+set g_balance_nex_secondary_damagefalloff_maxdist 0
+set g_balance_nex_secondary_damagefalloff_halflife 0
+set g_balance_nex_secondary_damagefalloff_forcehalflife 0
+
+set g_balance_nex_charge 1
+set g_balance_nex_charge_mindmg 20
+set g_balance_nex_charge_start 0.5
+set g_balance_nex_charge_rate 0.5
+set g_balance_nex_charge_animlimit 0.5
+set g_balance_nex_charge_limit 1 // LOG: 0.5 -> 1 - allow to fully charge automaticaly
+set g_balance_nex_charge_rot_rate 0 // LOG: 0.1 -> 0 - disable rot
+set g_balance_nex_charge_rot_pause 0.5 // Dont rot down until this long after release of charge button
+set g_balance_nex_charge_shot_multiplier 0
+set g_balance_nex_charge_velocity_rate 0
+set g_balance_nex_charge_minspeed 600
+set g_balance_nex_charge_maxspeed 1000
+
+set g_balance_nex_switchdelay_drop 0.15
+set g_balance_nex_switchdelay_raise 0.15
+
+set g_balance_nex_reload_ammo 0 //default: 25
+set g_balance_nex_reload_time 2
+// }}}
+// {{{ minstanex
+set g_balance_minstanex_refire 1
+set g_balance_minstanex_animtime 0.50
+set g_balance_minstanex_ammo 10
+set g_balance_minstanex_laser_ammo 0
+set g_balance_minstanex_laser_animtime 0.3
+set g_balance_minstanex_laser_refire 0.6
+set g_balance_minstanex_switchdelay_drop 0.15
+set g_balance_minstanex_switchdelay_raise 0.15
+set g_balance_minstanex_reload_ammo 0 //default: 50
+set g_balance_minstanex_reload_time 2
+// }}}
+// {{{ hagar
+set g_balance_hagar_primary_damage 14
+set g_balance_hagar_primary_edgedamage 6
+set g_balance_hagar_primary_force 70
+set g_balance_hagar_primary_health 0
+set g_balance_hagar_primary_damageforcescale 0
+set g_balance_hagar_primary_radius 110
+set g_balance_hagar_primary_spread 0.1
+set g_balance_hagar_primary_speed 1800
+set g_balance_hagar_primary_lifetime 5
+set g_balance_hagar_primary_refire 0.12
+set g_balance_hagar_primary_ammo 1
+set g_balance_hagar_secondary 1
+set g_balance_hagar_secondary_load 0
+set g_balance_hagar_secondary_load_speed 0.6
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
+set g_balance_hagar_secondary_load_max 4
+set g_balance_hagar_secondary_load_hold 0
+set g_balance_hagar_secondary_load_releasedeath 1
+set g_balance_hagar_secondary_load_abort 1
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
+set g_balance_hagar_secondary_damage 14 // default for _load: 32
+set g_balance_hagar_secondary_edgedamage 6 // default for _load: 10
+set g_balance_hagar_secondary_force 70 // default for _load: 160
+set g_balance_hagar_secondary_health 0
+set g_balance_hagar_secondary_damageforcescale 0
+set g_balance_hagar_secondary_radius 125
+set g_balance_hagar_secondary_spread 0.15 // default for _load: 0.08
+set g_balance_hagar_secondary_speed 1800
+set g_balance_hagar_secondary_lifetime_min 5
+set g_balance_hagar_secondary_lifetime_rand 0
+set g_balance_hagar_secondary_refire 0.12 // default for _load: 0.8
+set g_balance_hagar_secondary_ammo 1
+set g_balance_hagar_switchdelay_drop 0.15
+set g_balance_hagar_switchdelay_raise 0.15
+set g_balance_hagar_reload_ammo 0 //default: 25
+set g_balance_hagar_reload_time 2
+// }}}
+// {{{ rocketlauncher
+set g_balance_rocketlauncher_damage 82
+set g_balance_rocketlauncher_edgedamage 32
+set g_balance_rocketlauncher_force 350
+set g_balance_rocketlauncher_radius 130
+set g_balance_rocketlauncher_speed 1400
+set g_balance_rocketlauncher_speedaccel 1400
+set g_balance_rocketlauncher_speedstart 800
+set g_balance_rocketlauncher_lifetime 5
+set g_balance_rocketlauncher_refire 1
+set g_balance_rocketlauncher_animtime 0.3
+set g_balance_rocketlauncher_ammo 3
+set g_balance_rocketlauncher_health 0
+set g_balance_rocketlauncher_damageforcescale 0
+set g_balance_rocketlauncher_detonatedelay 0.05 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_rocketlauncher_guiderate 42 // max degrees per second
+set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
+set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
+set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in
+set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again
+set g_balance_rocketlauncher_remote_damage 60
+set g_balance_rocketlauncher_remote_edgedamage 20
+set g_balance_rocketlauncher_remote_radius 120
+set g_balance_rocketlauncher_remote_force 350
+set g_balance_rocketlauncher_switchdelay_drop 0.15
+set g_balance_rocketlauncher_switchdelay_raise 0.15
+set g_balance_rocketlauncher_reload_ammo 0 //default: 25
+set g_balance_rocketlauncher_reload_time 2
+// }}}
+// {{{ porto
+set g_balance_porto_primary_refire 1.5
+set g_balance_porto_primary_animtime 0.2
+set g_balance_porto_primary_speed 2000
+set g_balance_porto_primary_lifetime 5
+set g_balance_porto_secondary 0
+set g_balance_porto_secondary_refire 1.5
+set g_balance_porto_secondary_animtime 0.2
+set g_balance_porto_secondary_speed 2000
+set g_balance_porto_secondary_lifetime 5
+set g_balance_porto_switchdelay_drop 0.15
+set g_balance_porto_switchdelay_raise 0.15
+set g_balance_portal_health 200 // these get recharged whenever the portal is used
+set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
+// }}}
+// {{{ hook
+set g_balance_hook_primary_fuel 5 // hook monkeys set 0
+set g_balance_hook_primary_refire 0.2 // hook monkeys set 0
+set g_balance_hook_primary_animtime 0.2 // good shoot anim
+set g_balance_hook_primary_hooked_time_max 0 // infinite
+set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
+set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked
+set g_balance_hook_secondary_damage 25 // not much
+set g_balance_hook_secondary_edgedamage 5 // not much
+set g_balance_hook_secondary_radius 500 // LOTS
+set g_balance_hook_secondary_force -2000 // LOTS
+set g_balance_hook_secondary_ammo 50 // a whole pack
+set g_balance_hook_secondary_lifetime 5 // infinite
+set g_balance_hook_secondary_speed 0 // not much throwing
+set g_balance_hook_secondary_gravity 5 // fast falling
+set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
+set g_balance_hook_secondary_animtime 0.2 // good shoot anim
+set g_balance_hook_secondary_power 3 // effect behaves like a square function
+set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 0
+set g_balance_hook_secondary_damageforcescale 0
+set g_balance_hook_switchdelay_drop 0.15
+set g_balance_hook_switchdelay_raise 0.15
+// }}}
+// {{{ tuba
+set g_balance_tuba_refire 0.05
+set g_balance_tuba_animtime 0.05
+set g_balance_tuba_attenuation 0.5
+set g_balance_tuba_volume 1
+set g_balance_tuba_fadetime 0.25
+set g_balance_tuba_damage 5
+set g_balance_tuba_edgedamage 0
+set g_balance_tuba_radius 200
+set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
+set g_balance_tuba_switchdelay_drop 0.15
+set g_balance_tuba_switchdelay_raise 0.15
+// }}}
+// {{{ fireball
+set g_balance_fireball_primary_animtime 0.2
+set g_balance_fireball_primary_bfgdamage 100
+set g_balance_fireball_primary_bfgforce 0
+set g_balance_fireball_primary_bfgradius 1000
+set g_balance_fireball_primary_damage 200
+set g_balance_fireball_primary_damageforcescale 4
+set g_balance_fireball_primary_edgedamage 0
+set g_balance_fireball_primary_force 700
+set g_balance_fireball_primary_health 50
+set g_balance_fireball_primary_laserburntime 0.5
+set g_balance_fireball_primary_laserdamage 80
+set g_balance_fireball_primary_laseredgedamage 20
+set g_balance_fireball_primary_laserradius 256
+set g_balance_fireball_primary_lifetime 15
+set g_balance_fireball_primary_radius 200
+set g_balance_fireball_primary_refire 5
+set g_balance_fireball_primary_refire2 0
+set g_balance_fireball_primary_speed 650
+set g_balance_fireball_primary_spread 0
+set g_balance_fireball_secondary_animtime 0.2
+set g_balance_fireball_secondary_damage 40
+set g_balance_fireball_secondary_damageforcescale 4
+set g_balance_fireball_secondary_damagetime 5
+set g_balance_fireball_secondary_force 100
+set g_balance_fireball_secondary_laserburntime 0.5
+set g_balance_fireball_secondary_laserdamage 50
+set g_balance_fireball_secondary_laseredgedamage 20
+set g_balance_fireball_secondary_laserradius 110
+set g_balance_fireball_secondary_lifetime 7
+set g_balance_fireball_secondary_refire 2
+set g_balance_fireball_secondary_speed 900
+set g_balance_fireball_secondary_speed_up 100
+set g_balance_fireball_secondary_speed_z 0
+set g_balance_fireball_secondary_spread 0
+set g_balance_fireball_switchdelay_drop 0.15
+set g_balance_fireball_switchdelay_raise 0.15
+// }}}
diff --git a/balanceXDF.cfg b/balanceXDF.cfg
new file mode 100644
index 000000000..41d193619
--- /dev/null
+++ b/balanceXDF.cfg
@@ -0,0 +1,706 @@
+g_mod_balance XDF
+
+// {{{ starting gear
+set g_start_weapon_laser 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_shotgun 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_uzi 1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" // UNTIL IT CAN BE REMOVED FROM CODE
+set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_balance_health_start 100
+set g_balance_armor_start 0
+set g_start_ammo_shells 15
+set g_start_ammo_nails 0
+set g_start_ammo_rockets 0
+set g_start_ammo_cells 0
+set g_start_ammo_fuel 0
+set g_warmup_start_health 100 "starting values when being in warmup-stage"
+set g_warmup_start_armor 100 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
+set g_lms_start_health 200
+set g_lms_start_armor 200
+set g_lms_start_ammo_shells 60
+set g_lms_start_ammo_nails 320
+set g_lms_start_ammo_rockets 160
+set g_lms_start_ammo_cells 180
+set g_lms_start_ammo_fuel 0
+set g_balance_nix_roundtime 25
+set g_balance_nix_incrtime 1.6
+set g_balance_nix_ammo_shells 60
+set g_balance_nix_ammo_nails 320
+set g_balance_nix_ammo_rockets 160
+set g_balance_nix_ammo_cells 180
+set g_balance_nix_ammo_fuel 0
+set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
+set g_balance_nix_ammoincr_nails 6
+set g_balance_nix_ammoincr_rockets 2
+set g_balance_nix_ammoincr_cells 2
+set g_balance_nix_ammoincr_fuel 2
+// }}}
+
+// {{{ pickup items
+set g_pickup_ammo_anyway 1
+set g_pickup_weapons_anyway 1
+set g_pickup_shells 15
+set g_pickup_shells_weapon 15
+set g_pickup_shells_max 60
+set g_pickup_nails 80
+set g_pickup_nails_weapon 80
+set g_pickup_nails_max 320
+set g_pickup_rockets 40
+set g_pickup_rockets_weapon 40
+set g_pickup_rockets_max 160
+set g_pickup_cells 30
+set g_pickup_cells_weapon 30
+set g_pickup_cells_max 180
+set g_pickup_fuel 50
+set g_pickup_fuel_weapon 50
+set g_pickup_fuel_jetpack 100
+set g_pickup_fuel_max 100
+set g_pickup_armorsmall 5
+set g_pickup_armorsmall_max 200
+set g_pickup_armorsmall_anyway 1
+set g_pickup_armormedium 25
+set g_pickup_armormedium_max 200
+set g_pickup_armormedium_anyway 1
+set g_pickup_armorbig 50
+set g_pickup_armorbig_max 200
+set g_pickup_armorbig_anyway 1
+set g_pickup_armorlarge 100
+set g_pickup_armorlarge_max 200
+set g_pickup_armorlarge_anyway 1
+set g_pickup_healthsmall 5
+set g_pickup_healthsmall_max 200
+set g_pickup_healthsmall_anyway 1
+set g_pickup_healthmedium 25
+set g_pickup_healthmedium_max 200
+set g_pickup_healthmedium_anyway 1
+set g_pickup_healthlarge 50
+set g_pickup_healthlarge_max 200
+set g_pickup_healthlarge_anyway 1
+set g_pickup_healthmega 100
+set g_pickup_healthmega_max 200
+set g_pickup_healthmega_anyway 1
+set g_pickup_respawntime_short 0.1
+set g_pickup_respawntime_medium 0.1
+set g_pickup_respawntime_long 0.1
+set g_pickup_respawntime_powerup 0.1
+set g_pickup_respawntime_weapon 0.1
+set g_pickup_respawntime_superweapon 0.1
+set g_pickup_respawntime_ammo 0.1
+set g_pickup_respawntimejitter_short 0
+set g_pickup_respawntimejitter_medium 0
+set g_pickup_respawntimejitter_long 0
+set g_pickup_respawntimejitter_powerup 30
+set g_pickup_respawntimejitter_weapon 0
+set g_pickup_respawntimejitter_superweapon 10
+set g_pickup_respawntimejitter_ammo 0
+// }}}
+
+// {{{ regen/rot
+set g_balance_health_regen 0.08
+set g_balance_health_regenlinear 0.5
+set g_balance_pause_health_regen 5
+set g_balance_pause_health_regen_spawn 0
+set g_balance_health_rot 0.04
+set g_balance_health_rotlinear 0.75
+set g_balance_pause_health_rot 1
+set g_balance_pause_health_rot_spawn 5
+set g_balance_health_regenstable 100
+set g_balance_health_rotstable 100
+set g_balance_health_limit 999
+set g_balance_armor_regen 0
+set g_balance_armor_regenlinear 0
+set g_balance_armor_rot 0.04
+set g_balance_armor_rotlinear 0.75
+set g_balance_pause_armor_rot 1
+set g_balance_pause_armor_rot_spawn 5
+set g_balance_armor_regenstable 100
+set g_balance_armor_rotstable 100
+set g_balance_armor_limit 999
+set g_balance_armor_blockpercent 0.6
+set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
+set g_balance_fuel_regenlinear 0
+set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
+set g_balance_fuel_rot 0.05
+set g_balance_fuel_rotlinear 0
+set g_balance_pause_fuel_rot 5
+set g_balance_pause_fuel_rot_spawn 10
+set g_balance_fuel_regenstable 50
+set g_balance_fuel_rotstable 100
+set g_balance_fuel_limit 999
+// }}}
+
+// {{{ misc
+set g_balance_selfdamagepercent 0
+set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
+set g_weaponratefactor 1 "weapon fire rate multiplier"
+set g_weapondamagefactor 1 "weapon damage multiplier"
+set g_weaponforcefactor 1 "weapon force multiplier"
+set g_weaponspreadfactor 1 "weapon spread multiplier"
+set g_balance_firetransfer_time 0.9
+set g_balance_firetransfer_damage 0.8
+set g_throughfloor_damage 0.4
+set g_throughfloor_force 0.7
+set g_projectiles_damage 2
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
+// 0: only damage from contents (lava/slime) or exceptions
+// 1: only self damage or damage from contents or exceptions
+// 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
+set g_projectiles_newton_style 2
+// possible values:
+// 0: absolute velocity projectiles (like Quake)
+// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
+// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
+set g_projectiles_newton_style_2_minfactor 0.8
+set g_projectiles_newton_style_2_maxfactor 1.5
+set g_projectiles_spread_style 7
+// possible values:
+// 0: forward + solid sphere (like Quake) - varies velocity
+// 1: forward + flattened solid sphere
+// 2: forward + solid circle
+// 3: forward + normal distribution 3D - varies velocity
+// 4: forward + normal distribution on a plane
+// 5: forward + circle with 1-r falloff
+// 6: forward + circle with 1-r^2 falloff
+// 7: forward + circle with (1-r)(2-r) falloff
+set g_balance_falldamage_deadminspeed 250
+set g_balance_falldamage_minspeed 900
+set g_balance_falldamage_factor 0.20
+set g_balance_falldamage_maxdamage 40
+set g_balance_damagepush_speedfactor 2.5
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
+// }}}
+
+// {{{ powerups
+set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken
+set g_balance_powerup_invincible_time 999
+set g_balance_powerup_strength_damage 3
+set g_balance_powerup_strength_force 3
+set g_balance_powerup_strength_time 999
+set g_balance_powerup_strength_selfdamage 1.5
+set g_balance_powerup_strength_selfforce 1.5
+set g_balance_superweapons_time 30
+// }}}
+
+// {{{ jetpack/hook
+set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
+set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
+set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
+set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
+set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
+set g_jetpack_fuel 8 "fuel per second for jetpack"
+set g_jetpack_attenuation 2 "jetpack sound attenuation"
+
+set g_grappling_hook_tarzan 2 // 2: can also pull players
+set g_balance_grapplehook_speed_fly 1800
+set g_balance_grapplehook_speed_pull 2000
+set g_balance_grapplehook_force_rubber 2000
+set g_balance_grapplehook_force_rubber_overstretch 1000
+set g_balance_grapplehook_length_min 50
+set g_balance_grapplehook_stretch 50
+set g_balance_grapplehook_airfriction 0.2
+set g_balance_grapplehook_health 130
+set g_balance_grapplehook_damagedbycontents 0
+set g_balance_grapplehook_refire 0.2
+// }}}
+
+// {{{ weapon properties
+// {{{ laser
+set g_balance_laser_primary_damage 25
+set g_balance_laser_primary_edgedamage 12.5
+set g_balance_laser_primary_force 250
+set g_balance_laser_primary_radius 70
+set g_balance_laser_primary_speed 6000
+set g_balance_laser_primary_spread 0
+set g_balance_laser_primary_refire 0.7
+set g_balance_laser_primary_animtime 0.3
+set g_balance_laser_primary_lifetime 5
+set g_balance_laser_primary_shotangle 0
+set g_balance_laser_primary_delay 0
+set g_balance_laser_primary_gauntlet 0
+set g_balance_laser_primary_force_zscale 1.5
+set g_balance_laser_primary_force_velocitybias 0
+set g_balance_laser_primary_force_other_scale 1
+set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
+set g_balance_laser_secondary_damage 25
+set g_balance_laser_secondary_edgedamage 12.5
+set g_balance_laser_secondary_force 400
+set g_balance_laser_secondary_radius 70
+set g_balance_laser_secondary_speed 12000
+set g_balance_laser_secondary_spread 0
+set g_balance_laser_secondary_refire 0.7
+set g_balance_laser_secondary_animtime 0.3
+set g_balance_laser_secondary_lifetime 5
+set g_balance_laser_secondary_shotangle -90
+set g_balance_laser_secondary_delay 0
+set g_balance_laser_secondary_gauntlet 0
+set g_balance_laser_secondary_force_zscale 1.25
+set g_balance_laser_secondary_force_velocitybias 0
+set g_balance_laser_secondary_force_other_scale 1
+set g_balance_laser_switchdelay_drop 0
+set g_balance_laser_switchdelay_raise 0
+set g_balance_laser_reload_ammo 0 //default: 6
+set g_balance_laser_reload_time 2
+// }}}
+// {{{ shotgun
+set g_balance_shotgun_primary_bullets 14
+set g_balance_shotgun_primary_damage 4
+set g_balance_shotgun_primary_force 15
+set g_balance_shotgun_primary_spread 0.12
+set g_balance_shotgun_primary_refire 0.75
+set g_balance_shotgun_primary_animtime 0.2
+set g_balance_shotgun_primary_ammo 1
+set g_balance_shotgun_primary_solidpenetration 3.8
+set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
+set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 40
+set g_balance_shotgun_secondary_melee_multihit 1
+set g_balance_shotgun_secondary_damage 80
+set g_balance_shotgun_secondary_force 200
+set g_balance_shotgun_secondary_refire 1.25
+set g_balance_shotgun_secondary_animtime 1
+set g_balance_shotgun_switchdelay_drop 0
+set g_balance_shotgun_switchdelay_raise 0
+set g_balance_shotgun_reload_ammo 0 //default: 5
+set g_balance_shotgun_reload_time 2
+// }}}
+// {{{ uzi
+set g_balance_uzi_mode 1 				// Activates varible spread for sustained & burst mode secondary
+set g_balance_uzi_spread_min 0
+set g_balance_uzi_spread_max 0
+set g_balance_uzi_spread_add 0
+
+set g_balance_uzi_burst 3				// # of bullets in a burst (if set to 2 or more)
+set g_balance_uzi_burst_animtime 0.3
+set g_balance_uzi_burst_refire 0.06		// refire between burst bullets
+set g_balance_uzi_burst_refire2 0.45	// refire after burst
+set g_balance_uzi_burst_spread 0.03
+set g_balance_uzi_burst_damage 25
+set g_balance_uzi_burst_force 20
+set g_balance_uzi_burst_ammo 3
+
+set g_balance_uzi_first 1
+set g_balance_uzi_first_damage 14
+set g_balance_uzi_first_force 5
+set g_balance_uzi_first_spread 0.03
+set g_balance_uzi_first_refire 0.4
+set g_balance_uzi_first_ammo 1
+
+set g_balance_uzi_sustained_damage 12
+set g_balance_uzi_sustained_force 5
+set g_balance_uzi_sustained_spread 0
+set g_balance_uzi_sustained_refire 0.1
+set g_balance_uzi_sustained_ammo 1
+
+set g_balance_uzi_solidpenetration 13.1
+
+set g_balance_uzi_switchdelay_drop 0
+set g_balance_uzi_switchdelay_raise 0
+
+set g_balance_uzi_reload_ammo 0 //default: 30
+set g_balance_uzi_reload_time 2
+// }}}
+// {{{ mortar
+set g_balance_grenadelauncher_primary_type 0
+set g_balance_grenadelauncher_primary_damage 50
+set g_balance_grenadelauncher_primary_edgedamage 25
+set g_balance_grenadelauncher_primary_force 250
+set g_balance_grenadelauncher_primary_radius 100
+set g_balance_grenadelauncher_primary_speed 2000
+set g_balance_grenadelauncher_primary_speed_up 200
+set g_balance_grenadelauncher_primary_speed_z 0
+set g_balance_grenadelauncher_primary_spread 0
+set g_balance_grenadelauncher_primary_lifetime 5
+set g_balance_grenadelauncher_primary_lifetime2 1
+set g_balance_grenadelauncher_primary_refire 0.7
+set g_balance_grenadelauncher_primary_animtime 0.3
+set g_balance_grenadelauncher_primary_ammo 2
+set g_balance_grenadelauncher_primary_health 0
+set g_balance_grenadelauncher_primary_damageforcescale 0
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+
+set g_balance_grenadelauncher_secondary_type 1
+set g_balance_grenadelauncher_secondary_damage 60
+set g_balance_grenadelauncher_secondary_edgedamage 30
+set g_balance_grenadelauncher_secondary_force 300
+set g_balance_grenadelauncher_secondary_radius 200
+set g_balance_grenadelauncher_secondary_speed 800
+set g_balance_grenadelauncher_secondary_speed_up 0
+set g_balance_grenadelauncher_secondary_speed_z 200
+set g_balance_grenadelauncher_secondary_spread 0
+set g_balance_grenadelauncher_secondary_lifetime 8
+set g_balance_grenadelauncher_secondary_lifetime_bounce 0.5
+set g_balance_grenadelauncher_secondary_lifetime_stick 0
+set g_balance_grenadelauncher_secondary_refire 0.7
+set g_balance_grenadelauncher_secondary_animtime 0.5
+set g_balance_grenadelauncher_secondary_ammo 2
+set g_balance_grenadelauncher_secondary_health 0
+set g_balance_grenadelauncher_secondary_damageforcescale 0
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
+
+set g_balance_grenadelauncher_bouncefactor 0.5
+set g_balance_grenadelauncher_bouncestop 0.075
+
+set g_balance_grenadelauncher_switchdelay_drop 0
+set g_balance_grenadelauncher_switchdelay_raise 0
+
+set g_balance_grenadelauncher_reload_ammo 0 //default: 12
+set g_balance_grenadelauncher_reload_time 2
+// }}}
+// {{{ electro
+set g_balance_electro_lightning 0
+set g_balance_electro_primary_damage 55
+set g_balance_electro_primary_edgedamage 27.5
+set g_balance_electro_primary_force 200
+set g_balance_electro_primary_force_up 0
+set g_balance_electro_primary_radius 100
+set g_balance_electro_primary_comboradius 150
+set g_balance_electro_primary_speed 2500
+set g_balance_electro_primary_spread 0
+set g_balance_electro_primary_lifetime 5
+set g_balance_electro_primary_refire 0.6
+set g_balance_electro_primary_animtime 0.1
+set g_balance_electro_primary_ammo 4
+set g_balance_electro_primary_range 0
+set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius
+set g_balance_electro_primary_falloff_maxdist 850
+set g_balance_electro_primary_falloff_halflifedist 425
+set g_balance_electro_secondary_damage 40
+set g_balance_electro_secondary_edgedamage 20
+set g_balance_electro_secondary_force 200
+set g_balance_electro_secondary_radius 150
+set g_balance_electro_secondary_speed 900
+set g_balance_electro_secondary_speed_up 200
+set g_balance_electro_secondary_speed_z 0
+set g_balance_electro_secondary_spread 0.05
+set g_balance_electro_secondary_lifetime 3
+set g_balance_electro_secondary_refire 0.2
+set g_balance_electro_secondary_refire2 1.5
+set g_balance_electro_secondary_animtime 0.2
+set g_balance_electro_secondary_ammo 2
+set g_balance_electro_secondary_health 5
+set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_damagedbycontents 1
+set g_balance_electro_secondary_count 3
+set g_balance_electro_secondary_bouncefactor 0.4
+set g_balance_electro_secondary_bouncestop 0.05
+set g_balance_electro_combo_damage 40
+set g_balance_electro_combo_edgedamage 20
+set g_balance_electro_combo_force 120
+set g_balance_electro_combo_radius 175
+set g_balance_electro_combo_comboradius 275
+set g_balance_electro_combo_speed 2000
+set g_balance_electro_combo_safeammocheck 1
+set g_balance_electro_switchdelay_drop 0
+set g_balance_electro_switchdelay_raise 0
+set g_balance_electro_reload_ammo 0 //default: 20
+set g_balance_electro_reload_time 2
+// }}}
+// {{{ crylink
+set g_balance_crylink_primary_damage 12
+set g_balance_crylink_primary_edgedamage 6
+set g_balance_crylink_primary_force -50
+set g_balance_crylink_primary_radius 80
+set g_balance_crylink_primary_speed 2000
+set g_balance_crylink_primary_spread 0.08
+set g_balance_crylink_primary_shots 6
+set g_balance_crylink_primary_bounces 1
+set g_balance_crylink_primary_refire 0.7
+set g_balance_crylink_primary_animtime 0.3
+set g_balance_crylink_primary_ammo 3
+set g_balance_crylink_primary_bouncedamagefactor 0.5
+set g_balance_crylink_primary_joindelay 0.1
+set g_balance_crylink_primary_joinspread 0.2
+set g_balance_crylink_primary_joinexplode 1
+set g_balance_crylink_primary_joinexplode_damage 0
+set g_balance_crylink_primary_joinexplode_edgedamage 0
+set g_balance_crylink_primary_joinexplode_radius 0
+set g_balance_crylink_primary_joinexplode_force 0
+set g_balance_crylink_primary_linkexplode 1
+
+set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_primary_middle_fadetime 5
+set g_balance_crylink_primary_other_lifetime 5
+set g_balance_crylink_primary_other_fadetime 5
+
+set g_balance_crylink_secondary 1
+set g_balance_crylink_secondary_damage 10
+set g_balance_crylink_secondary_edgedamage 5
+set g_balance_crylink_secondary_force -150
+set g_balance_crylink_secondary_radius 100
+set g_balance_crylink_secondary_speed 3000
+set g_balance_crylink_secondary_spread 0.01
+set g_balance_crylink_secondary_spreadtype 1
+set g_balance_crylink_secondary_shots 5
+set g_balance_crylink_secondary_bounces 0
+set g_balance_crylink_secondary_refire 0.7
+set g_balance_crylink_secondary_animtime 0.2
+set g_balance_crylink_secondary_ammo 2
+set g_balance_crylink_secondary_bouncedamagefactor 0.5
+set g_balance_crylink_secondary_joindelay 0
+set g_balance_crylink_secondary_joinspread 0
+set g_balance_crylink_secondary_joinexplode 0
+set g_balance_crylink_secondary_joinexplode_damage 0
+set g_balance_crylink_secondary_joinexplode_edgedamage 0
+set g_balance_crylink_secondary_joinexplode_radius 0
+set g_balance_crylink_secondary_joinexplode_force 0
+set g_balance_crylink_secondary_linkexplode 1
+
+set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_secondary_middle_fadetime 5
+set g_balance_crylink_secondary_line_lifetime 5
+set g_balance_crylink_secondary_line_fadetime 5
+
+set g_balance_crylink_switchdelay_drop 0
+set g_balance_crylink_switchdelay_raise 0
+
+set g_balance_crylink_reload_ammo 0 //default: 10
+set g_balance_crylink_reload_time 2
+// }}}
+// {{{ nex
+set g_balance_nex_primary_damage 90
+set g_balance_nex_primary_force 400
+set g_balance_nex_primary_refire 1.5
+set g_balance_nex_primary_animtime 0.4
+set g_balance_nex_primary_ammo 6
+set g_balance_nex_primary_damagefalloff_mindist 0 // 1000    For tZork ;3
+set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000
+set g_balance_nex_primary_damagefalloff_halflife 0 // 1500
+set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 1500
+
+set g_balance_nex_secondary 0
+set g_balance_nex_secondary_charge 0
+set g_balance_nex_secondary_charge_rate 0.1
+set g_balance_nex_secondary_chargepool 0
+set g_balance_nex_secondary_chargepool_regen 0.15
+set g_balance_nex_secondary_chargepool_pause_regen 1
+set g_balance_nex_secondary_chargepool_pause_health_regen 1
+set g_balance_nex_secondary_damage 0
+set g_balance_nex_secondary_force 0
+set g_balance_nex_secondary_refire 0
+set g_balance_nex_secondary_animtime 0
+set g_balance_nex_secondary_ammo 2
+set g_balance_nex_secondary_damagefalloff_mindist 0
+set g_balance_nex_secondary_damagefalloff_maxdist 0
+set g_balance_nex_secondary_damagefalloff_halflife 0
+set g_balance_nex_secondary_damagefalloff_forcehalflife 0
+
+set g_balance_nex_charge 1
+set g_balance_nex_charge_mindmg 40
+set g_balance_nex_charge_start 0.5
+set g_balance_nex_charge_rate 0.4
+set g_balance_nex_charge_animlimit 0.5
+set g_balance_nex_charge_limit 1
+set g_balance_nex_charge_rot_rate 0
+set g_balance_nex_charge_rot_pause 0 // Dont rot down untill this long after release of charge button
+set g_balance_nex_charge_shot_multiplier 0
+set g_balance_nex_charge_velocity_rate 0
+set g_balance_nex_charge_minspeed 400
+set g_balance_nex_charge_maxspeed 800
+
+set g_balance_nex_switchdelay_drop 0
+set g_balance_nex_switchdelay_raise 0
+
+set g_balance_nex_reload_ammo 0 //default: 25
+set g_balance_nex_reload_time 2
+// }}}
+// {{{ minstanex
+set g_balance_minstanex_refire 1
+set g_balance_minstanex_animtime 0.3
+set g_balance_minstanex_ammo 10
+set g_balance_minstanex_laser_ammo 0
+set g_balance_minstanex_laser_animtime 0.3
+set g_balance_minstanex_laser_refire 0.7
+set g_balance_minstanex_switchdelay_drop 0
+set g_balance_minstanex_switchdelay_raise 0
+set g_balance_minstanex_reload_ammo 0 //default: 50
+set g_balance_minstanex_reload_time 2
+// }}}
+// {{{ hagar
+set g_balance_hagar_primary_damage 25
+set g_balance_hagar_primary_edgedamage 12.5
+set g_balance_hagar_primary_force 92
+set g_balance_hagar_primary_health 15
+set g_balance_hagar_primary_damageforcescale 0
+set g_balance_hagar_primary_radius 25
+set g_balance_hagar_primary_spread 0.03
+set g_balance_hagar_primary_speed 2000
+set g_balance_hagar_primary_lifetime 5
+set g_balance_hagar_primary_refire 0.11
+set g_balance_hagar_primary_ammo 1
+set g_balance_hagar_secondary 0
+set g_balance_hagar_secondary_load 1
+set g_balance_hagar_secondary_load_speed 0.5
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
+set g_balance_hagar_secondary_load_max 4
+set g_balance_hagar_secondary_load_hold 4
+set g_balance_hagar_secondary_load_releasedeath 0
+set g_balance_hagar_secondary_load_abort 0
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
+set g_balance_hagar_secondary_damage 40
+set g_balance_hagar_secondary_edgedamage 20
+set g_balance_hagar_secondary_force 75
+set g_balance_hagar_secondary_health 15
+set g_balance_hagar_secondary_damageforcescale 0
+set g_balance_hagar_secondary_radius 80
+set g_balance_hagar_secondary_spread 0.05
+set g_balance_hagar_secondary_speed 2000
+set g_balance_hagar_secondary_lifetime_min 10
+set g_balance_hagar_secondary_lifetime_rand 0
+set g_balance_hagar_secondary_refire 0.5
+set g_balance_hagar_secondary_ammo 1
+set g_balance_hagar_switchdelay_drop 0
+set g_balance_hagar_switchdelay_raise 0
+set g_balance_hagar_reload_ammo 0 //default: 25
+set g_balance_hagar_reload_time 2
+// }}}
+// {{{ rocketlauncher
+set g_balance_rocketlauncher_damage 80
+set g_balance_rocketlauncher_edgedamage 40
+set g_balance_rocketlauncher_force 350
+set g_balance_rocketlauncher_radius 110
+set g_balance_rocketlauncher_speed 1000
+set g_balance_rocketlauncher_speedaccel 0
+set g_balance_rocketlauncher_speedstart 1000
+set g_balance_rocketlauncher_lifetime 100
+set g_balance_rocketlauncher_refire 0.9
+set g_balance_rocketlauncher_animtime 0.7
+set g_balance_rocketlauncher_ammo 4
+set g_balance_rocketlauncher_health 0 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time.
+set g_balance_rocketlauncher_damageforcescale 0 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn
+set g_balance_rocketlauncher_detonatedelay 999 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_rocketlauncher_guiderate 0 // max degrees per second
+set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
+set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
+set g_balance_rocketlauncher_guidedelay 0.2 // delay before guiding kicks in
+set g_balance_rocketlauncher_guidestop 1 // stop guiding when firing again
+set g_balance_rocketlauncher_remote_damage 70
+set g_balance_rocketlauncher_remote_edgedamage 35
+set g_balance_rocketlauncher_remote_radius 110
+set g_balance_rocketlauncher_remote_force 350
+set g_balance_rocketlauncher_switchdelay_drop 0
+set g_balance_rocketlauncher_switchdelay_raise 0
+set g_balance_rocketlauncher_reload_ammo 0 //default: 25
+set g_balance_rocketlauncher_reload_time 2
+// }}}
+// {{{ porto
+set g_balance_porto_primary_refire 1.5
+set g_balance_porto_primary_animtime 0.3
+set g_balance_porto_primary_speed 5000
+set g_balance_porto_primary_lifetime 5
+set g_balance_porto_secondary 1
+set g_balance_porto_secondary_refire 1.5
+set g_balance_porto_secondary_animtime 0.3
+set g_balance_porto_secondary_speed 1000
+set g_balance_porto_secondary_lifetime 5
+set g_balance_porto_switchdelay_drop 0
+set g_balance_porto_switchdelay_raise 0
+set g_balance_portal_health 200 // these get recharged whenever the portal is used
+set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
+// }}}
+// {{{ hook
+set g_balance_hook_primary_fuel 5 // hook monkeys set 0
+set g_balance_hook_primary_refire 0.2 // hook monkeys set 0
+set g_balance_hook_primary_animtime 0.3 // good shoot anim
+set g_balance_hook_primary_hooked_time_max 0 // infinite
+set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
+set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked
+set g_balance_hook_secondary_damage 25 // not much
+set g_balance_hook_secondary_edgedamage 5 // not much
+set g_balance_hook_secondary_radius 500 // LOTS
+set g_balance_hook_secondary_force -2000 // LOTS
+set g_balance_hook_secondary_ammo 50 // a whole pack
+set g_balance_hook_secondary_lifetime 5 // infinite
+set g_balance_hook_secondary_speed 0 // not much throwing
+set g_balance_hook_secondary_gravity 5 // fast falling
+set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
+set g_balance_hook_secondary_animtime 0.3 // good shoot anim
+set g_balance_hook_secondary_power 3 // effect behaves like a square function
+set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 15
+set g_balance_hook_secondary_damageforcescale 0
+set g_balance_hook_switchdelay_drop 0
+set g_balance_hook_switchdelay_raise 0
+// }}}
+// {{{ tuba
+set g_balance_tuba_refire 0.05
+set g_balance_tuba_animtime 0.05
+set g_balance_tuba_attenuation 0.5
+set g_balance_tuba_volume 1
+set g_balance_tuba_fadetime 0.25
+set g_balance_tuba_damage 5
+set g_balance_tuba_edgedamage 0
+set g_balance_tuba_radius 200
+set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
+set g_balance_tuba_switchdelay_drop 0
+set g_balance_tuba_switchdelay_raise 0
+// }}}
+// {{{ fireball // this is a superweapon -- lets make it behave as one.
+set g_balance_fireball_primary_animtime 0.2
+set g_balance_fireball_primary_bfgdamage 100
+set g_balance_fireball_primary_bfgforce 0
+set g_balance_fireball_primary_bfgradius 1000
+set g_balance_fireball_primary_damage 200
+set g_balance_fireball_primary_damageforcescale 0
+set g_balance_fireball_primary_edgedamage 50
+set g_balance_fireball_primary_force 600
+set g_balance_fireball_primary_health 0
+set g_balance_fireball_primary_laserburntime 0.5
+set g_balance_fireball_primary_laserdamage 80
+set g_balance_fireball_primary_laseredgedamage 20
+set g_balance_fireball_primary_laserradius 256
+set g_balance_fireball_primary_lifetime 15
+set g_balance_fireball_primary_radius 200
+set g_balance_fireball_primary_refire 2
+set g_balance_fireball_primary_refire2 0
+set g_balance_fireball_primary_speed 1200
+set g_balance_fireball_primary_spread 0
+set g_balance_fireball_secondary_animtime 0.3
+set g_balance_fireball_secondary_damage 40
+set g_balance_fireball_secondary_damageforcescale 4
+set g_balance_fireball_secondary_damagetime 5
+set g_balance_fireball_secondary_force 100
+set g_balance_fireball_secondary_laserburntime 0.5
+set g_balance_fireball_secondary_laserdamage 50
+set g_balance_fireball_secondary_laseredgedamage 20
+set g_balance_fireball_secondary_laserradius 110
+set g_balance_fireball_secondary_lifetime 7
+set g_balance_fireball_secondary_refire 1.5
+set g_balance_fireball_secondary_speed 900
+set g_balance_fireball_secondary_speed_up 100
+set g_balance_fireball_secondary_speed_z 0
+set g_balance_fireball_secondary_spread 0
+set g_balance_fireball_switchdelay_drop 0
+set g_balance_fireball_switchdelay_raise 0
+// }}}
diff --git a/balanceXPM.cfg b/balanceXPM.cfg
new file mode 100644
index 000000000..f560aee10
--- /dev/null
+++ b/balanceXPM.cfg
@@ -0,0 +1,706 @@
+g_mod_balance XPM
+
+// {{{ starting gear
+set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE
+set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_balance_health_start 100
+set g_balance_armor_start 0
+set g_start_ammo_shells 15
+set g_start_ammo_nails 0
+set g_start_ammo_rockets 0
+set g_start_ammo_cells 0
+set g_start_ammo_fuel 0
+set g_warmup_start_health 100 "starting values when being in warmup-stage"
+set g_warmup_start_armor 100 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
+set g_lms_start_health 200
+set g_lms_start_armor 200
+set g_lms_start_ammo_shells 60
+set g_lms_start_ammo_nails 320
+set g_lms_start_ammo_rockets 160
+set g_lms_start_ammo_cells 180
+set g_lms_start_ammo_fuel 0
+set g_balance_nix_roundtime 25
+set g_balance_nix_incrtime 1.6
+set g_balance_nix_ammo_shells 60
+set g_balance_nix_ammo_nails 320
+set g_balance_nix_ammo_rockets 160
+set g_balance_nix_ammo_cells 180
+set g_balance_nix_ammo_fuel 0
+set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
+set g_balance_nix_ammoincr_nails 6
+set g_balance_nix_ammoincr_rockets 2
+set g_balance_nix_ammoincr_cells 2
+set g_balance_nix_ammoincr_fuel 2
+// }}}
+
+// {{{ pickup items
+set g_pickup_ammo_anyway 1
+set g_pickup_weapons_anyway 1
+set g_pickup_shells 15
+set g_pickup_shells_weapon 15
+set g_pickup_shells_max 60
+set g_pickup_nails 80
+set g_pickup_nails_weapon 80
+set g_pickup_nails_max 320
+set g_pickup_rockets 40
+set g_pickup_rockets_weapon 40
+set g_pickup_rockets_max 160
+set g_pickup_cells 30
+set g_pickup_cells_weapon 30
+set g_pickup_cells_max 180
+set g_pickup_fuel 50
+set g_pickup_fuel_weapon 50
+set g_pickup_fuel_jetpack 100
+set g_pickup_fuel_max 100
+set g_pickup_armorsmall 5
+set g_pickup_armorsmall_max 200
+set g_pickup_armorsmall_anyway 0
+set g_pickup_armormedium 25
+set g_pickup_armormedium_max 100
+set g_pickup_armormedium_anyway 0
+set g_pickup_armorbig 50
+set g_pickup_armorbig_max 100
+set g_pickup_armorbig_anyway 0
+set g_pickup_armorlarge 100
+set g_pickup_armorlarge_max 200
+set g_pickup_armorlarge_anyway 0
+set g_pickup_healthsmall 5
+set g_pickup_healthsmall_max 200
+set g_pickup_healthsmall_anyway 0
+set g_pickup_healthmedium 25
+set g_pickup_healthmedium_max 100
+set g_pickup_healthmedium_anyway 0
+set g_pickup_healthlarge 50
+set g_pickup_healthlarge_max 100
+set g_pickup_healthlarge_anyway 0
+set g_pickup_healthmega 100
+set g_pickup_healthmega_max 200
+set g_pickup_healthmega_anyway 0
+set g_pickup_respawntime_short 15
+set g_pickup_respawntime_medium 20
+set g_pickup_respawntime_long 30
+set g_pickup_respawntime_powerup 120
+set g_pickup_respawntime_weapon 10
+set g_pickup_respawntime_superweapon 120
+set g_pickup_respawntime_ammo 15
+set g_pickup_respawntimejitter_short 0
+set g_pickup_respawntimejitter_medium 0
+set g_pickup_respawntimejitter_long 0
+set g_pickup_respawntimejitter_powerup 30
+set g_pickup_respawntimejitter_weapon 0
+set g_pickup_respawntimejitter_superweapon 10
+set g_pickup_respawntimejitter_ammo 0
+// }}}
+
+// {{{ regen/rot
+set g_balance_health_regen 0.08
+set g_balance_health_regenlinear 0.5
+set g_balance_pause_health_regen 5
+set g_balance_pause_health_regen_spawn 0
+set g_balance_health_rot 0.03
+set g_balance_health_rotlinear 0.75
+set g_balance_pause_health_rot 1
+set g_balance_pause_health_rot_spawn 5
+set g_balance_health_regenstable 100
+set g_balance_health_rotstable 100
+set g_balance_health_limit 999
+set g_balance_armor_regen 0
+set g_balance_armor_regenlinear 0
+set g_balance_armor_rot 0.03
+set g_balance_armor_rotlinear 0.75
+set g_balance_pause_armor_rot 1
+set g_balance_pause_armor_rot_spawn 5
+set g_balance_armor_regenstable 100
+set g_balance_armor_rotstable 100
+set g_balance_armor_limit 999
+set g_balance_armor_blockpercent 0.6
+set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
+set g_balance_fuel_regenlinear 0
+set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
+set g_balance_fuel_rot 0.05
+set g_balance_fuel_rotlinear 0
+set g_balance_pause_fuel_rot 5
+set g_balance_pause_fuel_rot_spawn 10
+set g_balance_fuel_regenstable 50
+set g_balance_fuel_rotstable 100
+set g_balance_fuel_limit 999
+// }}}
+
+// {{{ misc
+set g_balance_selfdamagepercent 0.65
+set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
+set g_weaponratefactor 1 "weapon fire rate multiplier"
+set g_weapondamagefactor 1 "weapon damage multiplier"
+set g_weaponforcefactor 1 "weapon force multiplier"
+set g_weaponspreadfactor 1 "weapon spread multiplier"
+set g_balance_firetransfer_time 0.9
+set g_balance_firetransfer_damage 0.8
+set g_throughfloor_damage 0.75
+set g_throughfloor_force 0.75
+set g_projectiles_damage 1
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
+// 0: only damage from contents (lava/slime) or exceptions
+// 1: only self damage or damage from contents or exceptions
+// 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
+set g_projectiles_newton_style 0
+// possible values:
+// 0: absolute velocity projectiles (like Quake)
+// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
+// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
+set g_projectiles_newton_style_2_minfactor 0.8
+set g_projectiles_newton_style_2_maxfactor 1.5
+set g_projectiles_spread_style 7
+// possible values:
+// 0: forward + solid sphere (like Quake) - varies velocity
+// 1: forward + flattened solid sphere
+// 2: forward + solid circle
+// 3: forward + normal distribution 3D - varies velocity
+// 4: forward + normal distribution on a plane
+// 5: forward + circle with 1-r falloff
+// 6: forward + circle with 1-r^2 falloff
+// 7: forward + circle with (1-r)(2-r) falloff
+set g_balance_falldamage_deadminspeed 250
+set g_balance_falldamage_minspeed 900
+set g_balance_falldamage_factor 0.20
+set g_balance_falldamage_maxdamage 40
+set g_balance_damagepush_speedfactor 2.5
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
+// }}}
+
+// {{{ powerups
+set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken
+set g_balance_powerup_invincible_time 30
+set g_balance_powerup_strength_damage 3
+set g_balance_powerup_strength_force 3
+set g_balance_powerup_strength_time 30
+set g_balance_powerup_strength_selfdamage 1.5
+set g_balance_powerup_strength_selfforce 1.5
+set g_balance_superweapons_time 30
+// }}}
+
+// {{{ jetpack/hook
+set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
+set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
+set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
+set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
+set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
+set g_jetpack_fuel 8 "fuel per second for jetpack"
+set g_jetpack_attenuation 2 "jetpack sound attenuation"
+
+set g_grappling_hook_tarzan 2 // 2: can also pull players
+set g_balance_grapplehook_speed_fly 1800
+set g_balance_grapplehook_speed_pull 2000
+set g_balance_grapplehook_force_rubber 2000
+set g_balance_grapplehook_force_rubber_overstretch 1000
+set g_balance_grapplehook_length_min 50
+set g_balance_grapplehook_stretch 50
+set g_balance_grapplehook_airfriction 0.2
+set g_balance_grapplehook_health 50
+set g_balance_grapplehook_damagedbycontents 1
+set g_balance_grapplehook_refire 0.2
+// }}}
+
+// {{{ weapon properties
+// {{{ laser
+set g_balance_laser_primary_damage 25
+set g_balance_laser_primary_edgedamage 12.5
+set g_balance_laser_primary_force 300
+set g_balance_laser_primary_radius 70
+set g_balance_laser_primary_speed 6000
+set g_balance_laser_primary_spread 0
+set g_balance_laser_primary_refire 0.7
+set g_balance_laser_primary_animtime 0.2
+set g_balance_laser_primary_lifetime 5
+set g_balance_laser_primary_shotangle 0
+set g_balance_laser_primary_delay 0
+set g_balance_laser_primary_gauntlet 0
+set g_balance_laser_primary_force_zscale 1.2
+set g_balance_laser_primary_force_velocitybias 0
+set g_balance_laser_primary_force_other_scale 1
+set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
+set g_balance_laser_secondary_damage 25
+set g_balance_laser_secondary_edgedamage 12.5
+set g_balance_laser_secondary_force 400
+set g_balance_laser_secondary_radius 70
+set g_balance_laser_secondary_speed 12000
+set g_balance_laser_secondary_spread 0
+set g_balance_laser_secondary_refire 0.7
+set g_balance_laser_secondary_animtime 0.2
+set g_balance_laser_secondary_lifetime 5
+set g_balance_laser_secondary_shotangle -90
+set g_balance_laser_secondary_delay 0
+set g_balance_laser_secondary_gauntlet 0
+set g_balance_laser_secondary_force_zscale 1.25
+set g_balance_laser_secondary_force_velocitybias 0
+set g_balance_laser_secondary_force_other_scale 1
+set g_balance_laser_switchdelay_drop 0.15
+set g_balance_laser_switchdelay_raise 0.15
+set g_balance_laser_reload_ammo 0 //default: 6
+set g_balance_laser_reload_time 2
+// }}}
+// {{{ shotgun
+set g_balance_shotgun_primary_bullets 14
+set g_balance_shotgun_primary_damage 4
+set g_balance_shotgun_primary_force 15
+set g_balance_shotgun_primary_spread 0.12
+set g_balance_shotgun_primary_refire 0.75
+set g_balance_shotgun_primary_animtime 0.2
+set g_balance_shotgun_primary_ammo 1
+set g_balance_shotgun_primary_solidpenetration 3.8
+set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
+set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 40
+set g_balance_shotgun_secondary_melee_multihit 1
+set g_balance_shotgun_secondary_damage 80
+set g_balance_shotgun_secondary_force 200
+set g_balance_shotgun_secondary_refire 1.25
+set g_balance_shotgun_secondary_animtime 1
+set g_balance_shotgun_switchdelay_drop 0.2
+set g_balance_shotgun_switchdelay_raise 0.2
+set g_balance_shotgun_reload_ammo 0 //default: 5
+set g_balance_shotgun_reload_time 2
+// }}}
+// {{{ uzi
+set g_balance_uzi_mode 1 				// Activates varible spread for sustained & burst mode secondary
+set g_balance_uzi_spread_min 0.02
+set g_balance_uzi_spread_max 0.05
+set g_balance_uzi_spread_add 0.012
+
+set g_balance_uzi_burst 3				// # of bullets in a burst (if set to 2 or more)
+set g_balance_uzi_burst_animtime 0.3
+set g_balance_uzi_burst_refire 0.06		// refire between burst bullets
+set g_balance_uzi_burst_refire2 0.45	// refire after burst
+set g_balance_uzi_burst_spread 0.02
+set g_balance_uzi_burst_damage 25
+set g_balance_uzi_burst_force 20
+set g_balance_uzi_burst_ammo 3
+
+set g_balance_uzi_first 1
+set g_balance_uzi_first_damage 14
+set g_balance_uzi_first_force 5
+set g_balance_uzi_first_spread 0.03
+set g_balance_uzi_first_refire 0.125
+set g_balance_uzi_first_ammo 1
+
+set g_balance_uzi_sustained_damage 10 // 100 dps
+set g_balance_uzi_sustained_force 5
+set g_balance_uzi_sustained_spread 0.03
+set g_balance_uzi_sustained_refire 0.1
+set g_balance_uzi_sustained_ammo 1
+
+set g_balance_uzi_solidpenetration 13.1
+
+set g_balance_uzi_switchdelay_drop 0.2
+set g_balance_uzi_switchdelay_raise 0.2
+
+set g_balance_uzi_reload_ammo 60 //default: 30
+set g_balance_uzi_reload_time 2
+// }}}
+// {{{ mortar
+set g_balance_grenadelauncher_primary_type 0
+set g_balance_grenadelauncher_primary_damage 50
+set g_balance_grenadelauncher_primary_edgedamage 25
+set g_balance_grenadelauncher_primary_force 250
+set g_balance_grenadelauncher_primary_radius 120
+set g_balance_grenadelauncher_primary_speed 1900
+set g_balance_grenadelauncher_primary_speed_up 225
+set g_balance_grenadelauncher_primary_speed_z 0
+set g_balance_grenadelauncher_primary_spread 0
+set g_balance_grenadelauncher_primary_lifetime 5
+set g_balance_grenadelauncher_primary_lifetime2 1
+set g_balance_grenadelauncher_primary_refire 0.8
+set g_balance_grenadelauncher_primary_animtime 0.3
+set g_balance_grenadelauncher_primary_ammo 2
+set g_balance_grenadelauncher_primary_health 15
+set g_balance_grenadelauncher_primary_damageforcescale 0
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+
+set g_balance_grenadelauncher_secondary_type 1
+set g_balance_grenadelauncher_secondary_damage 60
+set g_balance_grenadelauncher_secondary_edgedamage 30
+set g_balance_grenadelauncher_secondary_force 250
+set g_balance_grenadelauncher_secondary_radius 120
+set g_balance_grenadelauncher_secondary_speed 1400
+set g_balance_grenadelauncher_secondary_speed_up 150
+set g_balance_grenadelauncher_secondary_speed_z 0
+set g_balance_grenadelauncher_secondary_spread 0
+set g_balance_grenadelauncher_secondary_lifetime 5
+set g_balance_grenadelauncher_secondary_lifetime_bounce 0.5
+set g_balance_grenadelauncher_secondary_lifetime_stick 0
+set g_balance_grenadelauncher_secondary_refire 0.7
+set g_balance_grenadelauncher_secondary_animtime 0.3
+set g_balance_grenadelauncher_secondary_ammo 2
+set g_balance_grenadelauncher_secondary_health 30
+set g_balance_grenadelauncher_secondary_damageforcescale 4
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
+
+set g_balance_grenadelauncher_bouncefactor 0.5
+set g_balance_grenadelauncher_bouncestop 0.075
+
+set g_balance_grenadelauncher_switchdelay_drop 0.2
+set g_balance_grenadelauncher_switchdelay_raise 0.2
+
+set g_balance_grenadelauncher_reload_ammo 0 //default: 12
+set g_balance_grenadelauncher_reload_time 2
+// }}}
+// {{{ electro
+set g_balance_electro_lightning 0
+set g_balance_electro_primary_damage 40
+set g_balance_electro_primary_edgedamage 20
+set g_balance_electro_primary_force 200
+set g_balance_electro_primary_force_up 0
+set g_balance_electro_primary_radius 100
+set g_balance_electro_primary_comboradius 300
+set g_balance_electro_primary_speed 2500
+set g_balance_electro_primary_spread 0
+set g_balance_electro_primary_lifetime 5
+set g_balance_electro_primary_refire 0.6
+set g_balance_electro_primary_animtime 0.3
+set g_balance_electro_primary_ammo 4
+set g_balance_electro_primary_range 0
+set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius
+set g_balance_electro_primary_falloff_maxdist 850
+set g_balance_electro_primary_falloff_halflifedist 425
+set g_balance_electro_secondary_damage 40
+set g_balance_electro_secondary_edgedamage 20
+set g_balance_electro_secondary_force 50
+set g_balance_electro_secondary_radius 150
+set g_balance_electro_secondary_speed 1000
+set g_balance_electro_secondary_speed_up 200
+set g_balance_electro_secondary_speed_z 0
+set g_balance_electro_secondary_spread 0.04
+set g_balance_electro_secondary_lifetime 4
+set g_balance_electro_secondary_refire 0.2
+set g_balance_electro_secondary_refire2 1.6
+set g_balance_electro_secondary_animtime 0.2
+set g_balance_electro_secondary_ammo 2
+set g_balance_electro_secondary_health 5
+set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_damagedbycontents 1
+set g_balance_electro_secondary_count 3
+set g_balance_electro_secondary_bouncefactor 0.3
+set g_balance_electro_secondary_bouncestop 0.05
+set g_balance_electro_combo_damage 50
+set g_balance_electro_combo_edgedamage 25
+set g_balance_electro_combo_force 120
+set g_balance_electro_combo_radius 150
+set g_balance_electro_combo_comboradius 300
+set g_balance_electro_combo_speed 2000
+set g_balance_electro_combo_safeammocheck 1
+set g_balance_electro_switchdelay_drop 0.2
+set g_balance_electro_switchdelay_raise 0.2
+set g_balance_electro_reload_ammo 0 //default: 20
+set g_balance_electro_reload_time 2
+// }}}
+// {{{ crylink
+set g_balance_crylink_primary_damage 12
+set g_balance_crylink_primary_edgedamage 6
+set g_balance_crylink_primary_force -50
+set g_balance_crylink_primary_radius 80
+set g_balance_crylink_primary_speed 2000
+set g_balance_crylink_primary_spread 0.08
+set g_balance_crylink_primary_shots 6
+set g_balance_crylink_primary_bounces 1
+set g_balance_crylink_primary_refire 0.7
+set g_balance_crylink_primary_animtime 0.3
+set g_balance_crylink_primary_ammo 3
+set g_balance_crylink_primary_bouncedamagefactor 0.5
+set g_balance_crylink_primary_joindelay 0.1
+set g_balance_crylink_primary_joinspread 0.2
+set g_balance_crylink_primary_joinexplode 1
+set g_balance_crylink_primary_joinexplode_damage 0
+set g_balance_crylink_primary_joinexplode_edgedamage 0
+set g_balance_crylink_primary_joinexplode_radius 0
+set g_balance_crylink_primary_joinexplode_force 0
+set g_balance_crylink_primary_linkexplode 1
+
+set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_primary_middle_fadetime 5
+set g_balance_crylink_primary_other_lifetime 5
+set g_balance_crylink_primary_other_fadetime 5
+
+set g_balance_crylink_secondary 1
+set g_balance_crylink_secondary_damage 10
+set g_balance_crylink_secondary_edgedamage 5
+set g_balance_crylink_secondary_force -250
+set g_balance_crylink_secondary_radius 100
+set g_balance_crylink_secondary_speed 3000
+set g_balance_crylink_secondary_spread 0.01
+set g_balance_crylink_secondary_spreadtype 1
+set g_balance_crylink_secondary_shots 5
+set g_balance_crylink_secondary_bounces 0
+set g_balance_crylink_secondary_refire 0.7
+set g_balance_crylink_secondary_animtime 0.2
+set g_balance_crylink_secondary_ammo 2
+set g_balance_crylink_secondary_bouncedamagefactor 0.5
+set g_balance_crylink_secondary_joindelay 0
+set g_balance_crylink_secondary_joinspread 0
+set g_balance_crylink_secondary_joinexplode 0
+set g_balance_crylink_secondary_joinexplode_damage 0
+set g_balance_crylink_secondary_joinexplode_edgedamage 0
+set g_balance_crylink_secondary_joinexplode_radius 0
+set g_balance_crylink_secondary_joinexplode_force 0
+set g_balance_crylink_secondary_linkexplode 1
+
+set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_secondary_middle_fadetime 5
+set g_balance_crylink_secondary_line_lifetime 5
+set g_balance_crylink_secondary_line_fadetime 5
+
+set g_balance_crylink_switchdelay_drop 0.2
+set g_balance_crylink_switchdelay_raise 0.2
+
+set g_balance_crylink_reload_ammo 0 //default: 10
+set g_balance_crylink_reload_time 2
+// }}}
+// {{{ nex
+set g_balance_nex_primary_damage 80
+set g_balance_nex_primary_force 400
+set g_balance_nex_primary_refire 1.5
+set g_balance_nex_primary_animtime 0.6
+set g_balance_nex_primary_ammo 6
+set g_balance_nex_primary_damagefalloff_mindist 0 // 1000    For tZork ;3
+set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000
+set g_balance_nex_primary_damagefalloff_halflife 0 // 1500
+set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 1500
+
+set g_balance_nex_secondary 0
+set g_balance_nex_secondary_charge 0
+set g_balance_nex_secondary_charge_rate 0.1
+set g_balance_nex_secondary_chargepool 0
+set g_balance_nex_secondary_chargepool_regen 0.15
+set g_balance_nex_secondary_chargepool_pause_regen 1
+set g_balance_nex_secondary_chargepool_pause_health_regen 1
+set g_balance_nex_secondary_damage 0
+set g_balance_nex_secondary_force 0
+set g_balance_nex_secondary_refire 0
+set g_balance_nex_secondary_animtime 0
+set g_balance_nex_secondary_ammo 2
+set g_balance_nex_secondary_damagefalloff_mindist 0
+set g_balance_nex_secondary_damagefalloff_maxdist 0
+set g_balance_nex_secondary_damagefalloff_halflife 0
+set g_balance_nex_secondary_damagefalloff_forcehalflife 0
+
+set g_balance_nex_charge 1
+set g_balance_nex_charge_mindmg 40
+set g_balance_nex_charge_start 0.5
+set g_balance_nex_charge_rate 0.4
+set g_balance_nex_charge_animlimit 0.5
+set g_balance_nex_charge_limit 1
+set g_balance_nex_charge_rot_rate 0
+set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button
+set g_balance_nex_charge_shot_multiplier 0
+set g_balance_nex_charge_velocity_rate 0
+set g_balance_nex_charge_minspeed 400
+set g_balance_nex_charge_maxspeed 800
+
+set g_balance_nex_switchdelay_drop 0.3
+set g_balance_nex_switchdelay_raise 0.25
+
+set g_balance_nex_reload_ammo 0 //default: 25
+set g_balance_nex_reload_time 2
+// }}}
+// {{{ minstanex
+set g_balance_minstanex_refire 1
+set g_balance_minstanex_animtime 0.3
+set g_balance_minstanex_ammo 10
+set g_balance_minstanex_laser_ammo 0
+set g_balance_minstanex_laser_animtime 0.3
+set g_balance_minstanex_laser_refire 0.7
+set g_balance_minstanex_switchdelay_drop 0.2
+set g_balance_minstanex_switchdelay_raise 0.2
+set g_balance_minstanex_reload_ammo 0 //default: 50
+set g_balance_minstanex_reload_time 2
+// }}}
+// {{{ hagar
+set g_balance_hagar_primary_damage 25
+set g_balance_hagar_primary_edgedamage 12.5
+set g_balance_hagar_primary_force 100
+set g_balance_hagar_primary_health 15
+set g_balance_hagar_primary_damageforcescale 0
+set g_balance_hagar_primary_radius 65
+set g_balance_hagar_primary_spread 0.03
+set g_balance_hagar_primary_speed 2500
+set g_balance_hagar_primary_lifetime 5
+set g_balance_hagar_primary_refire 0.16667 // 6 rockets per second
+set g_balance_hagar_primary_ammo 1
+set g_balance_hagar_secondary 1
+set g_balance_hagar_secondary_load 1
+set g_balance_hagar_secondary_load_speed 0.5
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
+set g_balance_hagar_secondary_load_max 4
+set g_balance_hagar_secondary_load_hold 4
+set g_balance_hagar_secondary_load_releasedeath 0
+set g_balance_hagar_secondary_load_abort 0
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
+set g_balance_hagar_secondary_damage 40
+set g_balance_hagar_secondary_edgedamage 20
+set g_balance_hagar_secondary_force 75
+set g_balance_hagar_secondary_health 15
+set g_balance_hagar_secondary_damageforcescale 0
+set g_balance_hagar_secondary_radius 80
+set g_balance_hagar_secondary_spread 0.05
+set g_balance_hagar_secondary_speed 2000
+set g_balance_hagar_secondary_lifetime_min 10
+set g_balance_hagar_secondary_lifetime_rand 0
+set g_balance_hagar_secondary_refire 0.5
+set g_balance_hagar_secondary_ammo 1
+set g_balance_hagar_switchdelay_drop 0.2
+set g_balance_hagar_switchdelay_raise 0.2
+set g_balance_hagar_reload_ammo 0 //default: 25
+set g_balance_hagar_reload_time 2
+// }}}
+// {{{ rocketlauncher
+set g_balance_rocketlauncher_damage 70
+set g_balance_rocketlauncher_edgedamage 35
+set g_balance_rocketlauncher_force 450
+set g_balance_rocketlauncher_radius 110
+set g_balance_rocketlauncher_speed 1300
+set g_balance_rocketlauncher_speedaccel 1300
+set g_balance_rocketlauncher_speedstart 1000
+set g_balance_rocketlauncher_lifetime 10
+set g_balance_rocketlauncher_refire 1.2
+set g_balance_rocketlauncher_animtime 0.4
+set g_balance_rocketlauncher_ammo 4
+set g_balance_rocketlauncher_health 30 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time.
+set g_balance_rocketlauncher_damageforcescale 1 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn
+set g_balance_rocketlauncher_detonatedelay 0.02 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_rocketlauncher_guiderate 70 // max degrees per second
+set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
+set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
+set g_balance_rocketlauncher_guidedelay 0.2 // delay before guiding kicks in
+set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again
+set g_balance_rocketlauncher_remote_damage 70
+set g_balance_rocketlauncher_remote_edgedamage 35
+set g_balance_rocketlauncher_remote_radius 110
+set g_balance_rocketlauncher_remote_force 400
+set g_balance_rocketlauncher_switchdelay_drop 0.3
+set g_balance_rocketlauncher_switchdelay_raise 0.2
+set g_balance_rocketlauncher_reload_ammo 0 //default: 25
+set g_balance_rocketlauncher_reload_time 2
+// }}}
+// {{{ porto
+set g_balance_porto_primary_refire 1.5
+set g_balance_porto_primary_animtime 0.3
+set g_balance_porto_primary_speed 1000
+set g_balance_porto_primary_lifetime 5
+set g_balance_porto_secondary 1
+set g_balance_porto_secondary_refire 1.5
+set g_balance_porto_secondary_animtime 0.3
+set g_balance_porto_secondary_speed 1000
+set g_balance_porto_secondary_lifetime 5
+set g_balance_porto_switchdelay_drop 0.2
+set g_balance_porto_switchdelay_raise 0.2
+set g_balance_portal_health 200 // these get recharged whenever the portal is used
+set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
+// }}}
+// {{{ hook
+set g_balance_hook_primary_fuel 5 // hook monkeys set 0
+set g_balance_hook_primary_refire 0.2 // hook monkeys set 0
+set g_balance_hook_primary_animtime 0.3 // good shoot anim
+set g_balance_hook_primary_hooked_time_max 0 // infinite
+set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
+set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked
+set g_balance_hook_secondary_damage 25 // not much
+set g_balance_hook_secondary_edgedamage 5 // not much
+set g_balance_hook_secondary_radius 500 // LOTS
+set g_balance_hook_secondary_force -2000 // LOTS
+set g_balance_hook_secondary_ammo 30 // a whole pack
+set g_balance_hook_secondary_lifetime 5 // infinite
+set g_balance_hook_secondary_speed 0 // not much throwing
+set g_balance_hook_secondary_gravity 5 // fast falling
+set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
+set g_balance_hook_secondary_animtime 0.3 // good shoot anim
+set g_balance_hook_secondary_power 3 // effect behaves like a square function
+set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 15
+set g_balance_hook_secondary_damageforcescale 0
+set g_balance_hook_switchdelay_drop 0.2
+set g_balance_hook_switchdelay_raise 0.2
+// }}}
+// {{{ tuba
+set g_balance_tuba_refire 0.05
+set g_balance_tuba_animtime 0.05
+set g_balance_tuba_attenuation 0.5
+set g_balance_tuba_volume 1
+set g_balance_tuba_fadetime 0.25
+set g_balance_tuba_damage 5
+set g_balance_tuba_edgedamage 0
+set g_balance_tuba_radius 200
+set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
+set g_balance_tuba_switchdelay_drop 0.2
+set g_balance_tuba_switchdelay_raise 0.2
+// }}}
+// {{{ fireball // this is a superweapon -- lets make it behave as one.
+set g_balance_fireball_primary_animtime 0.2
+set g_balance_fireball_primary_bfgdamage 100
+set g_balance_fireball_primary_bfgforce 0
+set g_balance_fireball_primary_bfgradius 1000
+set g_balance_fireball_primary_damage 200
+set g_balance_fireball_primary_damageforcescale 0
+set g_balance_fireball_primary_edgedamage 50
+set g_balance_fireball_primary_force 600
+set g_balance_fireball_primary_health 0
+set g_balance_fireball_primary_laserburntime 0.5
+set g_balance_fireball_primary_laserdamage 80
+set g_balance_fireball_primary_laseredgedamage 20
+set g_balance_fireball_primary_laserradius 256
+set g_balance_fireball_primary_lifetime 15
+set g_balance_fireball_primary_radius 200
+set g_balance_fireball_primary_refire 2
+set g_balance_fireball_primary_refire2 0
+set g_balance_fireball_primary_speed 1200
+set g_balance_fireball_primary_spread 0
+set g_balance_fireball_secondary_animtime 0.3
+set g_balance_fireball_secondary_damage 40
+set g_balance_fireball_secondary_damageforcescale 4
+set g_balance_fireball_secondary_damagetime 5
+set g_balance_fireball_secondary_force 100
+set g_balance_fireball_secondary_laserburntime 0.5
+set g_balance_fireball_secondary_laserdamage 50
+set g_balance_fireball_secondary_laseredgedamage 20
+set g_balance_fireball_secondary_laserradius 110
+set g_balance_fireball_secondary_lifetime 7
+set g_balance_fireball_secondary_refire 1.5
+set g_balance_fireball_secondary_speed 900
+set g_balance_fireball_secondary_speed_up 100
+set g_balance_fireball_secondary_speed_z 0
+set g_balance_fireball_secondary_spread 0
+set g_balance_fireball_switchdelay_drop 0.2
+set g_balance_fireball_switchdelay_raise 0.2
+// }}}
diff --git a/balanceXonotic.cfg b/balanceXonotic.cfg
new file mode 100644
index 000000000..198801547
--- /dev/null
+++ b/balanceXonotic.cfg
@@ -0,0 +1,706 @@
+g_mod_balance Xonotic
+
+// {{{ starting gear
+set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" // UNTIL IT CAN BE REMOVED FROM CODE
+set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
+set g_balance_health_start 100
+set g_balance_armor_start 0
+set g_start_ammo_shells 15
+set g_start_ammo_nails 0
+set g_start_ammo_rockets 0
+set g_start_ammo_cells 0
+set g_start_ammo_fuel 0
+set g_warmup_start_health 100 "starting values when being in warmup-stage"
+set g_warmup_start_armor 100 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
+set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
+set g_lms_start_health 200
+set g_lms_start_armor 200
+set g_lms_start_ammo_shells 60
+set g_lms_start_ammo_nails 320
+set g_lms_start_ammo_rockets 160
+set g_lms_start_ammo_cells 180
+set g_lms_start_ammo_fuel 0
+set g_balance_nix_roundtime 25
+set g_balance_nix_incrtime 1.6
+set g_balance_nix_ammo_shells 60
+set g_balance_nix_ammo_nails 320
+set g_balance_nix_ammo_rockets 160
+set g_balance_nix_ammo_cells 180
+set g_balance_nix_ammo_fuel 0
+set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
+set g_balance_nix_ammoincr_nails 6
+set g_balance_nix_ammoincr_rockets 2
+set g_balance_nix_ammoincr_cells 2
+set g_balance_nix_ammoincr_fuel 2
+// }}}
+
+// {{{ pickup items
+set g_pickup_ammo_anyway 1
+set g_pickup_weapons_anyway 1
+set g_pickup_shells 15
+set g_pickup_shells_weapon 15
+set g_pickup_shells_max 60
+set g_pickup_nails 80
+set g_pickup_nails_weapon 80
+set g_pickup_nails_max 320
+set g_pickup_rockets 40
+set g_pickup_rockets_weapon 40
+set g_pickup_rockets_max 160
+set g_pickup_cells 30
+set g_pickup_cells_weapon 30
+set g_pickup_cells_max 180
+set g_pickup_fuel 50
+set g_pickup_fuel_weapon 50
+set g_pickup_fuel_jetpack 100
+set g_pickup_fuel_max 100
+set g_pickup_armorsmall 5
+set g_pickup_armorsmall_max 200
+set g_pickup_armorsmall_anyway 1
+set g_pickup_armormedium 25
+set g_pickup_armormedium_max 200
+set g_pickup_armormedium_anyway 1
+set g_pickup_armorbig 50
+set g_pickup_armorbig_max 200
+set g_pickup_armorbig_anyway 1
+set g_pickup_armorlarge 100
+set g_pickup_armorlarge_max 200
+set g_pickup_armorlarge_anyway 1
+set g_pickup_healthsmall 5
+set g_pickup_healthsmall_max 200
+set g_pickup_healthsmall_anyway 1
+set g_pickup_healthmedium 25
+set g_pickup_healthmedium_max 200
+set g_pickup_healthmedium_anyway 1
+set g_pickup_healthlarge 50
+set g_pickup_healthlarge_max 200
+set g_pickup_healthlarge_anyway 1
+set g_pickup_healthmega 100
+set g_pickup_healthmega_max 200
+set g_pickup_healthmega_anyway 1
+set g_pickup_respawntime_short 15
+set g_pickup_respawntime_medium 20
+set g_pickup_respawntime_long 30
+set g_pickup_respawntime_powerup 120
+set g_pickup_respawntime_weapon 10
+set g_pickup_respawntime_superweapon 120
+set g_pickup_respawntime_ammo 10
+set g_pickup_respawntimejitter_short 0
+set g_pickup_respawntimejitter_medium 0
+set g_pickup_respawntimejitter_long 0
+set g_pickup_respawntimejitter_powerup 30
+set g_pickup_respawntimejitter_weapon 0
+set g_pickup_respawntimejitter_superweapon 10
+set g_pickup_respawntimejitter_ammo 0
+// }}}
+
+// {{{ regen/rot
+set g_balance_health_regen 0.08
+set g_balance_health_regenlinear 0.5
+set g_balance_pause_health_regen 5
+set g_balance_pause_health_regen_spawn 0
+set g_balance_health_rot 0.04
+set g_balance_health_rotlinear 0.75
+set g_balance_pause_health_rot 1
+set g_balance_pause_health_rot_spawn 5
+set g_balance_health_regenstable 100
+set g_balance_health_rotstable 100
+set g_balance_health_limit 999
+set g_balance_armor_regen 0
+set g_balance_armor_regenlinear 0
+set g_balance_armor_rot 0.04
+set g_balance_armor_rotlinear 0.75
+set g_balance_pause_armor_rot 1
+set g_balance_pause_armor_rot_spawn 5
+set g_balance_armor_regenstable 100
+set g_balance_armor_rotstable 100
+set g_balance_armor_limit 999
+set g_balance_armor_blockpercent 0.6
+set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
+set g_balance_fuel_regenlinear 0
+set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
+set g_balance_fuel_rot 0.05
+set g_balance_fuel_rotlinear 0
+set g_balance_pause_fuel_rot 5
+set g_balance_pause_fuel_rot_spawn 10
+set g_balance_fuel_regenstable 50
+set g_balance_fuel_rotstable 100
+set g_balance_fuel_limit 999
+// }}}
+
+// {{{ misc
+set g_balance_selfdamagepercent 0.65
+set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
+set g_weaponratefactor 1 "weapon fire rate multiplier"
+set g_weapondamagefactor 1 "weapon damage multiplier"
+set g_weaponforcefactor 1 "weapon force multiplier"
+set g_weaponspreadfactor 1 "weapon spread multiplier"
+set g_balance_firetransfer_time 0.9
+set g_balance_firetransfer_damage 0.8
+set g_throughfloor_damage 0.75
+set g_throughfloor_force 0.75
+set g_projectiles_damage 2
+// possible values:
+// -2: absolutely no damage to projectiles (no exceptions)
+// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
+// 0: only damage from contents (lava/slime) or exceptions
+// 1: only self damage or damage from contents or exceptions
+// 2: allow all damage to projectiles normally
+set g_projectiles_keep_owner 0
+set g_projectiles_newton_style 2
+// possible values:
+// 0: absolute velocity projectiles (like Quake)
+// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
+// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
+set g_projectiles_newton_style_2_minfactor 0.8
+set g_projectiles_newton_style_2_maxfactor 1.5
+set g_projectiles_spread_style 7
+// possible values:
+// 0: forward + solid sphere (like Quake) - varies velocity
+// 1: forward + flattened solid sphere
+// 2: forward + solid circle
+// 3: forward + normal distribution 3D - varies velocity
+// 4: forward + normal distribution on a plane
+// 5: forward + circle with 1-r falloff
+// 6: forward + circle with 1-r^2 falloff
+// 7: forward + circle with (1-r)(2-r) falloff
+set g_balance_falldamage_deadminspeed 250
+set g_balance_falldamage_minspeed 900
+set g_balance_falldamage_factor 0.20
+set g_balance_falldamage_maxdamage 40
+set g_balance_damagepush_speedfactor 2.5
+set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
+set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
+set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
+set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
+set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
+set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
+set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
+// }}}
+
+// {{{ powerups
+set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken
+set g_balance_powerup_invincible_time 30
+set g_balance_powerup_strength_damage 3
+set g_balance_powerup_strength_force 3
+set g_balance_powerup_strength_time 30
+set g_balance_powerup_strength_selfdamage 1.5
+set g_balance_powerup_strength_selfforce 1.5
+set g_balance_superweapons_time 30
+// }}}
+
+// {{{ jetpack/hook
+set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
+set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
+set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
+set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
+set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
+set g_jetpack_fuel 8 "fuel per second for jetpack"
+set g_jetpack_attenuation 2 "jetpack sound attenuation"
+
+set g_grappling_hook_tarzan 2 // 2: can also pull players
+set g_balance_grapplehook_speed_fly 1800
+set g_balance_grapplehook_speed_pull 2000
+set g_balance_grapplehook_force_rubber 2000
+set g_balance_grapplehook_force_rubber_overstretch 1000
+set g_balance_grapplehook_length_min 50
+set g_balance_grapplehook_stretch 50
+set g_balance_grapplehook_airfriction 0.2
+set g_balance_grapplehook_health 50
+set g_balance_grapplehook_damagedbycontents 1
+set g_balance_grapplehook_refire 0.2
+// }}}
+
+// {{{ weapon properties
+// {{{ laser
+set g_balance_laser_primary_damage 25
+set g_balance_laser_primary_edgedamage 12.5
+set g_balance_laser_primary_force 300
+set g_balance_laser_primary_radius 70
+set g_balance_laser_primary_speed 6000
+set g_balance_laser_primary_spread 0
+set g_balance_laser_primary_refire 0.7
+set g_balance_laser_primary_animtime 0.2
+set g_balance_laser_primary_lifetime 5
+set g_balance_laser_primary_shotangle 0
+set g_balance_laser_primary_delay 0
+set g_balance_laser_primary_gauntlet 0
+set g_balance_laser_primary_force_zscale 1.2
+set g_balance_laser_primary_force_velocitybias 0
+set g_balance_laser_primary_force_other_scale 1
+set g_balance_laser_secondary 0 // when 1, a secondary laser mode exists
+set g_balance_laser_secondary_damage 25
+set g_balance_laser_secondary_edgedamage 12.5
+set g_balance_laser_secondary_force 400
+set g_balance_laser_secondary_radius 70
+set g_balance_laser_secondary_speed 12000
+set g_balance_laser_secondary_spread 0
+set g_balance_laser_secondary_refire 0.7
+set g_balance_laser_secondary_animtime 0.2
+set g_balance_laser_secondary_lifetime 5
+set g_balance_laser_secondary_shotangle -90
+set g_balance_laser_secondary_delay 0
+set g_balance_laser_secondary_gauntlet 0
+set g_balance_laser_secondary_force_zscale 1.25
+set g_balance_laser_secondary_force_velocitybias 0
+set g_balance_laser_secondary_force_other_scale 1
+set g_balance_laser_switchdelay_drop 0.15
+set g_balance_laser_switchdelay_raise 0.15
+set g_balance_laser_reload_ammo 0 //default: 6
+set g_balance_laser_reload_time 2
+// }}}
+// {{{ shotgun
+set g_balance_shotgun_primary_bullets 14
+set g_balance_shotgun_primary_damage 4
+set g_balance_shotgun_primary_force 15
+set g_balance_shotgun_primary_spread 0.12
+set g_balance_shotgun_primary_refire 0.75
+set g_balance_shotgun_primary_animtime 0.2
+set g_balance_shotgun_primary_ammo 1
+set g_balance_shotgun_primary_solidpenetration 3.8
+set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
+set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 40
+set g_balance_shotgun_secondary_melee_multihit 1
+set g_balance_shotgun_secondary_damage 80
+set g_balance_shotgun_secondary_force 200
+set g_balance_shotgun_secondary_refire 1.25
+set g_balance_shotgun_secondary_animtime 1
+set g_balance_shotgun_switchdelay_drop 0.2
+set g_balance_shotgun_switchdelay_raise 0.2
+set g_balance_shotgun_reload_ammo 0 //default: 5
+set g_balance_shotgun_reload_time 2
+// }}}
+// {{{ uzi
+set g_balance_uzi_mode 1 				// Activates varible spread for sustained & burst mode secondary
+set g_balance_uzi_spread_min 0.02
+set g_balance_uzi_spread_max 0.05
+set g_balance_uzi_spread_add 0.012
+
+set g_balance_uzi_burst 3				// # of bullets in a burst (if set to 2 or more)
+set g_balance_uzi_burst_animtime 0.3
+set g_balance_uzi_burst_refire 0.06		// refire between burst bullets
+set g_balance_uzi_burst_refire2 0.45	// refire after burst
+set g_balance_uzi_burst_spread 0.02
+set g_balance_uzi_burst_damage 25
+set g_balance_uzi_burst_force 20
+set g_balance_uzi_burst_ammo 3
+
+set g_balance_uzi_first 1
+set g_balance_uzi_first_damage 14
+set g_balance_uzi_first_force 5
+set g_balance_uzi_first_spread 0.03
+set g_balance_uzi_first_refire 0.125
+set g_balance_uzi_first_ammo 1
+
+set g_balance_uzi_sustained_damage 10 // 100 dps
+set g_balance_uzi_sustained_force 5
+set g_balance_uzi_sustained_spread 0.03
+set g_balance_uzi_sustained_refire 0.1
+set g_balance_uzi_sustained_ammo 1
+
+set g_balance_uzi_solidpenetration 13.1
+
+set g_balance_uzi_switchdelay_drop 0.2
+set g_balance_uzi_switchdelay_raise 0.2
+
+set g_balance_uzi_reload_ammo 60 //default: 30
+set g_balance_uzi_reload_time 2
+// }}}
+// {{{ mortar
+set g_balance_grenadelauncher_primary_type 0
+set g_balance_grenadelauncher_primary_damage 50
+set g_balance_grenadelauncher_primary_edgedamage 25
+set g_balance_grenadelauncher_primary_force 250
+set g_balance_grenadelauncher_primary_radius 120
+set g_balance_grenadelauncher_primary_speed 1900
+set g_balance_grenadelauncher_primary_speed_up 225
+set g_balance_grenadelauncher_primary_speed_z 0
+set g_balance_grenadelauncher_primary_spread 0
+set g_balance_grenadelauncher_primary_lifetime 5
+set g_balance_grenadelauncher_primary_lifetime2 1
+set g_balance_grenadelauncher_primary_refire 0.8
+set g_balance_grenadelauncher_primary_animtime 0.3
+set g_balance_grenadelauncher_primary_ammo 2
+set g_balance_grenadelauncher_primary_health 15
+set g_balance_grenadelauncher_primary_damageforcescale 0
+set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
+
+set g_balance_grenadelauncher_secondary_type 1
+set g_balance_grenadelauncher_secondary_damage 60
+set g_balance_grenadelauncher_secondary_edgedamage 30
+set g_balance_grenadelauncher_secondary_force 250
+set g_balance_grenadelauncher_secondary_radius 120
+set g_balance_grenadelauncher_secondary_speed 1400
+set g_balance_grenadelauncher_secondary_speed_up 150
+set g_balance_grenadelauncher_secondary_speed_z 0
+set g_balance_grenadelauncher_secondary_spread 0
+set g_balance_grenadelauncher_secondary_lifetime 5
+set g_balance_grenadelauncher_secondary_lifetime_bounce 0.5
+set g_balance_grenadelauncher_secondary_lifetime_stick 0
+set g_balance_grenadelauncher_secondary_refire 0.7
+set g_balance_grenadelauncher_secondary_animtime 0.3
+set g_balance_grenadelauncher_secondary_ammo 2
+set g_balance_grenadelauncher_secondary_health 30
+set g_balance_grenadelauncher_secondary_damageforcescale 4
+set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
+
+set g_balance_grenadelauncher_bouncefactor 0.5
+set g_balance_grenadelauncher_bouncestop 0.075
+
+set g_balance_grenadelauncher_switchdelay_drop 0.2
+set g_balance_grenadelauncher_switchdelay_raise 0.2
+
+set g_balance_grenadelauncher_reload_ammo 0 //default: 12
+set g_balance_grenadelauncher_reload_time 2
+// }}}
+// {{{ electro
+set g_balance_electro_lightning 0
+set g_balance_electro_primary_damage 40
+set g_balance_electro_primary_edgedamage 20
+set g_balance_electro_primary_force 200
+set g_balance_electro_primary_force_up 0
+set g_balance_electro_primary_radius 100
+set g_balance_electro_primary_comboradius 300
+set g_balance_electro_primary_speed 2500
+set g_balance_electro_primary_spread 0
+set g_balance_electro_primary_lifetime 5
+set g_balance_electro_primary_refire 0.6
+set g_balance_electro_primary_animtime 0.3
+set g_balance_electro_primary_ammo 4
+set g_balance_electro_primary_range 0
+set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius
+set g_balance_electro_primary_falloff_maxdist 850
+set g_balance_electro_primary_falloff_halflifedist 425
+set g_balance_electro_secondary_damage 40
+set g_balance_electro_secondary_edgedamage 20
+set g_balance_electro_secondary_force 50
+set g_balance_electro_secondary_radius 150
+set g_balance_electro_secondary_speed 1000
+set g_balance_electro_secondary_speed_up 200
+set g_balance_electro_secondary_speed_z 0
+set g_balance_electro_secondary_spread 0.04
+set g_balance_electro_secondary_lifetime 4
+set g_balance_electro_secondary_refire 0.2
+set g_balance_electro_secondary_refire2 1.6
+set g_balance_electro_secondary_animtime 0.2
+set g_balance_electro_secondary_ammo 2
+set g_balance_electro_secondary_health 5
+set g_balance_electro_secondary_damageforcescale 4
+set g_balance_electro_secondary_damagedbycontents 1
+set g_balance_electro_secondary_count 3
+set g_balance_electro_secondary_bouncefactor 0.3
+set g_balance_electro_secondary_bouncestop 0.05
+set g_balance_electro_combo_damage 50
+set g_balance_electro_combo_edgedamage 25
+set g_balance_electro_combo_force 120
+set g_balance_electro_combo_radius 150
+set g_balance_electro_combo_comboradius 300
+set g_balance_electro_combo_speed 2000
+set g_balance_electro_combo_safeammocheck 1
+set g_balance_electro_switchdelay_drop 0.2
+set g_balance_electro_switchdelay_raise 0.2
+set g_balance_electro_reload_ammo 0 //default: 20
+set g_balance_electro_reload_time 2
+// }}}
+// {{{ crylink
+set g_balance_crylink_primary_damage 12
+set g_balance_crylink_primary_edgedamage 6
+set g_balance_crylink_primary_force -50
+set g_balance_crylink_primary_radius 80
+set g_balance_crylink_primary_speed 2000
+set g_balance_crylink_primary_spread 0.08
+set g_balance_crylink_primary_shots 6
+set g_balance_crylink_primary_bounces 1
+set g_balance_crylink_primary_refire 0.7
+set g_balance_crylink_primary_animtime 0.3
+set g_balance_crylink_primary_ammo 3
+set g_balance_crylink_primary_bouncedamagefactor 0.5
+set g_balance_crylink_primary_joindelay 0.1
+set g_balance_crylink_primary_joinspread 0.2
+set g_balance_crylink_primary_joinexplode 1
+set g_balance_crylink_primary_joinexplode_damage 0
+set g_balance_crylink_primary_joinexplode_edgedamage 0
+set g_balance_crylink_primary_joinexplode_radius 0
+set g_balance_crylink_primary_joinexplode_force 0
+set g_balance_crylink_primary_linkexplode 1
+
+set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_primary_middle_fadetime 5
+set g_balance_crylink_primary_other_lifetime 5
+set g_balance_crylink_primary_other_fadetime 5
+
+set g_balance_crylink_secondary 1
+set g_balance_crylink_secondary_damage 10
+set g_balance_crylink_secondary_edgedamage 5
+set g_balance_crylink_secondary_force -250
+set g_balance_crylink_secondary_radius 100
+set g_balance_crylink_secondary_speed 3000
+set g_balance_crylink_secondary_spread 0.01
+set g_balance_crylink_secondary_spreadtype 1
+set g_balance_crylink_secondary_shots 5
+set g_balance_crylink_secondary_bounces 0
+set g_balance_crylink_secondary_refire 0.7
+set g_balance_crylink_secondary_animtime 0.2
+set g_balance_crylink_secondary_ammo 2
+set g_balance_crylink_secondary_bouncedamagefactor 0.5
+set g_balance_crylink_secondary_joindelay 0
+set g_balance_crylink_secondary_joinspread 0
+set g_balance_crylink_secondary_joinexplode 0
+set g_balance_crylink_secondary_joinexplode_damage 0
+set g_balance_crylink_secondary_joinexplode_edgedamage 0
+set g_balance_crylink_secondary_joinexplode_radius 0
+set g_balance_crylink_secondary_joinexplode_force 0
+set g_balance_crylink_secondary_linkexplode 1
+
+set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
+set g_balance_crylink_secondary_middle_fadetime 5
+set g_balance_crylink_secondary_line_lifetime 5
+set g_balance_crylink_secondary_line_fadetime 5
+
+set g_balance_crylink_switchdelay_drop 0.2
+set g_balance_crylink_switchdelay_raise 0.2
+
+set g_balance_crylink_reload_ammo 0 //default: 10
+set g_balance_crylink_reload_time 2
+// }}}
+// {{{ nex
+set g_balance_nex_primary_damage 80
+set g_balance_nex_primary_force 400
+set g_balance_nex_primary_refire 1.5
+set g_balance_nex_primary_animtime 0.6
+set g_balance_nex_primary_ammo 6
+set g_balance_nex_primary_damagefalloff_mindist 0 // 1000    For tZork ;3
+set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000
+set g_balance_nex_primary_damagefalloff_halflife 0 // 1500
+set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 1500
+
+set g_balance_nex_secondary 0
+set g_balance_nex_secondary_charge 0
+set g_balance_nex_secondary_charge_rate 0.1
+set g_balance_nex_secondary_chargepool 0
+set g_balance_nex_secondary_chargepool_regen 0.15
+set g_balance_nex_secondary_chargepool_pause_regen 1
+set g_balance_nex_secondary_chargepool_pause_health_regen 1
+set g_balance_nex_secondary_damage 0
+set g_balance_nex_secondary_force 0
+set g_balance_nex_secondary_refire 0
+set g_balance_nex_secondary_animtime 0
+set g_balance_nex_secondary_ammo 2
+set g_balance_nex_secondary_damagefalloff_mindist 0
+set g_balance_nex_secondary_damagefalloff_maxdist 0
+set g_balance_nex_secondary_damagefalloff_halflife 0
+set g_balance_nex_secondary_damagefalloff_forcehalflife 0
+
+set g_balance_nex_charge 1
+set g_balance_nex_charge_mindmg 40
+set g_balance_nex_charge_start 0.5
+set g_balance_nex_charge_rate 0.4
+set g_balance_nex_charge_animlimit 0.5
+set g_balance_nex_charge_limit 1
+set g_balance_nex_charge_rot_rate 0
+set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button
+set g_balance_nex_charge_shot_multiplier 0
+set g_balance_nex_charge_velocity_rate 0
+set g_balance_nex_charge_minspeed 400
+set g_balance_nex_charge_maxspeed 800
+
+set g_balance_nex_switchdelay_drop 0.3
+set g_balance_nex_switchdelay_raise 0.25
+
+set g_balance_nex_reload_ammo 0 //default: 25
+set g_balance_nex_reload_time 2
+// }}}
+// {{{ minstanex
+set g_balance_minstanex_refire 1
+set g_balance_minstanex_animtime 0.3
+set g_balance_minstanex_ammo 10
+set g_balance_minstanex_laser_ammo 0
+set g_balance_minstanex_laser_animtime 0.3
+set g_balance_minstanex_laser_refire 0.7
+set g_balance_minstanex_switchdelay_drop 0.2
+set g_balance_minstanex_switchdelay_raise 0.2
+set g_balance_minstanex_reload_ammo 0 //default: 50
+set g_balance_minstanex_reload_time 2
+// }}}
+// {{{ hagar
+set g_balance_hagar_primary_damage 25
+set g_balance_hagar_primary_edgedamage 12.5
+set g_balance_hagar_primary_force 100
+set g_balance_hagar_primary_health 15
+set g_balance_hagar_primary_damageforcescale 0
+set g_balance_hagar_primary_radius 65
+set g_balance_hagar_primary_spread 0.03
+set g_balance_hagar_primary_speed 2500
+set g_balance_hagar_primary_lifetime 5
+set g_balance_hagar_primary_refire 0.16667 // 6 rockets per second
+set g_balance_hagar_primary_ammo 1
+set g_balance_hagar_secondary 1
+set g_balance_hagar_secondary_load 1
+set g_balance_hagar_secondary_load_speed 0.5
+set g_balance_hagar_secondary_load_spread 0.075
+set g_balance_hagar_secondary_load_spread_bias 0.5
+set g_balance_hagar_secondary_load_max 4
+set g_balance_hagar_secondary_load_hold 4
+set g_balance_hagar_secondary_load_releasedeath 0
+set g_balance_hagar_secondary_load_abort 0
+set g_balance_hagar_secondary_load_linkexplode 0
+set g_balance_hagar_secondary_load_animtime 0.2
+set g_balance_hagar_secondary_damage 40
+set g_balance_hagar_secondary_edgedamage 20
+set g_balance_hagar_secondary_force 75
+set g_balance_hagar_secondary_health 15
+set g_balance_hagar_secondary_damageforcescale 0
+set g_balance_hagar_secondary_radius 80
+set g_balance_hagar_secondary_spread 0.05
+set g_balance_hagar_secondary_speed 2500
+set g_balance_hagar_secondary_lifetime_min 10
+set g_balance_hagar_secondary_lifetime_rand 0
+set g_balance_hagar_secondary_refire 0.5
+set g_balance_hagar_secondary_ammo 1
+set g_balance_hagar_switchdelay_drop 0.2
+set g_balance_hagar_switchdelay_raise 0.2
+set g_balance_hagar_reload_ammo 0 //default: 25
+set g_balance_hagar_reload_time 2
+// }}}
+// {{{ rocketlauncher
+set g_balance_rocketlauncher_damage 70
+set g_balance_rocketlauncher_edgedamage 35
+set g_balance_rocketlauncher_force 450
+set g_balance_rocketlauncher_radius 110
+set g_balance_rocketlauncher_speed 1300
+set g_balance_rocketlauncher_speedaccel 1300
+set g_balance_rocketlauncher_speedstart 1000
+set g_balance_rocketlauncher_lifetime 10
+set g_balance_rocketlauncher_refire 1.2
+set g_balance_rocketlauncher_animtime 0.4
+set g_balance_rocketlauncher_ammo 4
+set g_balance_rocketlauncher_health 30 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time.
+set g_balance_rocketlauncher_damageforcescale 1 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn
+set g_balance_rocketlauncher_detonatedelay 0.02 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_rocketlauncher_guiderate 70 // max degrees per second
+set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
+set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
+set g_balance_rocketlauncher_guidedelay 0.2 // delay before guiding kicks in
+set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again
+set g_balance_rocketlauncher_remote_damage 70
+set g_balance_rocketlauncher_remote_edgedamage 35
+set g_balance_rocketlauncher_remote_radius 110
+set g_balance_rocketlauncher_remote_force 400
+set g_balance_rocketlauncher_switchdelay_drop 0.3
+set g_balance_rocketlauncher_switchdelay_raise 0.2
+set g_balance_rocketlauncher_reload_ammo 0 //default: 25
+set g_balance_rocketlauncher_reload_time 2
+// }}}
+// {{{ porto
+set g_balance_porto_primary_refire 1.5
+set g_balance_porto_primary_animtime 0.3
+set g_balance_porto_primary_speed 1000
+set g_balance_porto_primary_lifetime 5
+set g_balance_porto_secondary 1
+set g_balance_porto_secondary_refire 1.5
+set g_balance_porto_secondary_animtime 0.3
+set g_balance_porto_secondary_speed 1000
+set g_balance_porto_secondary_lifetime 5
+set g_balance_porto_switchdelay_drop 0.2
+set g_balance_porto_switchdelay_raise 0.2
+set g_balance_portal_health 200 // these get recharged whenever the portal is used
+set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
+// }}}
+// {{{ hook
+set g_balance_hook_primary_fuel 5 // hook monkeys set 0
+set g_balance_hook_primary_refire 0.2 // hook monkeys set 0
+set g_balance_hook_primary_animtime 0.3 // good shoot anim
+set g_balance_hook_primary_hooked_time_max 0 // infinite
+set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
+set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked
+set g_balance_hook_secondary_damage 25 // not much
+set g_balance_hook_secondary_edgedamage 5 // not much
+set g_balance_hook_secondary_radius 500 // LOTS
+set g_balance_hook_secondary_force -2000 // LOTS
+set g_balance_hook_secondary_ammo 30 // a whole pack
+set g_balance_hook_secondary_lifetime 5 // infinite
+set g_balance_hook_secondary_speed 0 // not much throwing
+set g_balance_hook_secondary_gravity 5 // fast falling
+set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
+set g_balance_hook_secondary_animtime 0.3 // good shoot anim
+set g_balance_hook_secondary_power 3 // effect behaves like a square function
+set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
+set g_balance_hook_secondary_health 15
+set g_balance_hook_secondary_damageforcescale 0
+set g_balance_hook_switchdelay_drop 0.2
+set g_balance_hook_switchdelay_raise 0.2
+// }}}
+// {{{ tuba
+set g_balance_tuba_refire 0.05
+set g_balance_tuba_animtime 0.05
+set g_balance_tuba_attenuation 0.5
+set g_balance_tuba_volume 1
+set g_balance_tuba_fadetime 0.25
+set g_balance_tuba_damage 5
+set g_balance_tuba_edgedamage 0
+set g_balance_tuba_radius 200
+set g_balance_tuba_force 40
+set g_balance_tuba_pitchstep 6
+set g_balance_tuba_switchdelay_drop 0.2
+set g_balance_tuba_switchdelay_raise 0.2
+// }}}
+// {{{ fireball // this is a superweapon -- lets make it behave as one.
+set g_balance_fireball_primary_animtime 0.2
+set g_balance_fireball_primary_bfgdamage 100
+set g_balance_fireball_primary_bfgforce 0
+set g_balance_fireball_primary_bfgradius 1000
+set g_balance_fireball_primary_damage 200
+set g_balance_fireball_primary_damageforcescale 0
+set g_balance_fireball_primary_edgedamage 50
+set g_balance_fireball_primary_force 600
+set g_balance_fireball_primary_health 0
+set g_balance_fireball_primary_laserburntime 0.5
+set g_balance_fireball_primary_laserdamage 80
+set g_balance_fireball_primary_laseredgedamage 20
+set g_balance_fireball_primary_laserradius 256
+set g_balance_fireball_primary_lifetime 15
+set g_balance_fireball_primary_radius 200
+set g_balance_fireball_primary_refire 2
+set g_balance_fireball_primary_refire2 0
+set g_balance_fireball_primary_speed 1200
+set g_balance_fireball_primary_spread 0
+set g_balance_fireball_secondary_animtime 0.3
+set g_balance_fireball_secondary_damage 40
+set g_balance_fireball_secondary_damageforcescale 4
+set g_balance_fireball_secondary_damagetime 5
+set g_balance_fireball_secondary_force 100
+set g_balance_fireball_secondary_laserburntime 0.5
+set g_balance_fireball_secondary_laserdamage 50
+set g_balance_fireball_secondary_laseredgedamage 20
+set g_balance_fireball_secondary_laserradius 110
+set g_balance_fireball_secondary_lifetime 7
+set g_balance_fireball_secondary_refire 1.5
+set g_balance_fireball_secondary_speed 900
+set g_balance_fireball_secondary_speed_up 100
+set g_balance_fireball_secondary_speed_z 0
+set g_balance_fireball_secondary_spread 0
+set g_balance_fireball_switchdelay_drop 0.2
+set g_balance_fireball_switchdelay_raise 0.2
+// }}}
diff --git a/check-cvars.sh b/check-cvars.sh
index 031613a7b..78985b819 100755
--- a/check-cvars.sh
+++ b/check-cvars.sh
@@ -23,7 +23,7 @@ check_files()
 	done
 }
 
-check_files "balance-xonotic.cfg" "balance-*.cfg" "/^seta? g_/"
+check_files "balanceXonotic.cfg" "balance*.cfg" "/^seta? g_/"
 check_files "_hud_descriptions.cfg" "hud_*.cfg" "/^seta? hud_/"
 
 if $errord; then
diff --git a/crosshairs.cfg b/crosshairs.cfg
index 6a9d8822c..c6a9e837b 100644
--- a/crosshairs.cfg
+++ b/crosshairs.cfg
@@ -41,9 +41,87 @@ seta crosshair_color_special 1 "special color handling for crosshair... 1 = per-
 seta crosshair_color_special_rainbow_delay 0.1
 seta crosshair_color_special_rainbow_brightness 20 "color brightness of the random crosshair colors"
 
-// per-weapon crosshairs
+
+// ===============================
+//  Per weapon crosshair settings
+// ===============================
+// main settings
 seta crosshair_per_weapon 1	"when 1, each gun will display a different crosshair"
 
+// per weapon settings
+seta crosshair_laser ""	"crosshair to display when wielding the laser"
+seta crosshair_laser_color "1 0.35 0.2"	"crosshair color to display when wielding the laser"
+seta crosshair_laser_alpha 0.75	"crosshair alpha value to display when wielding the laser"
+seta crosshair_laser_size 0.4	"crosshair size when wielding the laser"
+seta crosshair_shotgun ""	"crosshair to display when wielding the shotgun"
+seta crosshair_shotgun_color "0.7 0.7 0.7"	"crosshair color to display when wielding the shotgun"
+seta crosshair_shotgun_alpha 1.1	"crosshair alpha value to display when wielding the shotgun"
+seta crosshair_shotgun_size 0.65	"crosshair size when wielding the shotgun"
+seta crosshair_uzi ""	"crosshair to display when wielding the machinegun"
+seta crosshair_uzi_color "0.4 0.9 0.35"	"crosshair color to display when wielding the machinegun"
+seta crosshair_uzi_alpha 0.9	"crosshair alpha value to display when wielding the machinegun"
+seta crosshair_uzi_size 0.6	"crosshair size when wielding the machinegun"
+seta crosshair_grenadelauncher ""	"crosshair to display when wielding the mortar"
+seta crosshair_grenadelauncher_color "1 0.15 0"	"crosshair color to display when wielding the mortar"
+seta crosshair_grenadelauncher_alpha 1.15	"crosshair alpha value to display when wielding the mortar"
+seta crosshair_grenadelauncher_size 0.7	"crosshair size when wielding the mortar"
+seta crosshair_minelayer ""	"crosshair to display when wielding the mortar"
+seta crosshair_minelayer_color "0.75 0.75 0"	"crosshair color to display when wielding the mortar"
+seta crosshair_minelayer_alpha 1.15	"crosshair alpha value to display when wielding the mortar"
+seta crosshair_minelayer_size 0.9	"crosshair size when wielding the mortar"
+seta crosshair_electro ""	"crosshair to display when wielding the electro"
+seta crosshair_electro_color "0.35 0.5 1"	"crosshair color to display when wielding the electro"
+seta crosshair_electro_alpha 1	"crosshair alpha value to display when wielding the electro"
+seta crosshair_electro_size 0.5	"crosshair size when wielding the electro"
+seta crosshair_crylink ""	"crosshair to display when wielding the crylink"
+seta crosshair_crylink_color "0.85 0.25 1"	"crosshair color to display when wielding the crylink"
+seta crosshair_crylink_alpha 0.85	"crosshair alpha value to display when wielding the crylink"
+seta crosshair_crylink_size 0.4	"crosshair size when wielding the crylink"
+seta crosshair_nex ""	"crosshair to display when wielding the nex gun"
+seta crosshair_nex_color "0 0.9 1"	"crosshair color to display when wielding the nex gun"
+seta crosshair_nex_alpha 0.85	"crosshair alpha value to display when wielding the nex gun"
+seta crosshair_nex_size 0.65	"crosshair size when wielding the nex gun"
+seta crosshair_hagar ""	"crosshair to display when wielding the hagar"
+seta crosshair_hagar_color "0.85 0.5 0.35"	"crosshair color to display when wielding the hagar"
+seta crosshair_hagar_alpha 1	"crosshair alpha value to display when wielding the hagar"
+seta crosshair_hagar_size 0.8	"crosshair size when wielding the hagar"
+seta crosshair_rocketlauncher ""	"crosshair to display when wielding the rocketlauncher"
+seta crosshair_rocketlauncher_color "1 0.75 0.2"	"crosshair color to display when wielding the rocketlauncher"
+seta crosshair_rocketlauncher_alpha 1	"crosshair alpha value to display when wielding the rocketlauncher"
+seta crosshair_rocketlauncher_size 0.5875	"crosshair size when wielding the rocketlauncher"
+seta crosshair_porto ""	"crosshair to display when wielding the porto"
+seta crosshair_porto_color "0.5 1 0.5"	"crosshair color to display when wielding the porto"
+seta crosshair_porto_alpha 0.85	"crosshair alpha value to display when wielding the porto"
+seta crosshair_porto_size 0.6	"crosshair size when wielding the porto"
+seta crosshair_minstanex ""	"crosshair to display when wielding the minstanex gun"
+seta crosshair_minstanex_color "0.65 0.65 1"	"crosshair color to display when wielding the minstanex gun"
+seta crosshair_minstanex_alpha 1	"crosshair alpha value to display when wielding the minstanex gun"
+seta crosshair_minstanex_size 0.4	"crosshair size when wielding the minstanex gun"
+seta crosshair_hook ""	"crosshair to display when wielding the hook"
+seta crosshair_hook_color "0.65 1 0.85"	"crosshair color to display when wielding the hook"
+seta crosshair_hook_alpha 0.85	"crosshair alpha value to display when wielding the hook"
+seta crosshair_hook_size 0.5	"crosshair size when wielding the hook"
+seta crosshair_hlac ""	"crosshair to display when wielding the H.L.A.C"
+seta crosshair_hlac_color "1 0.65 0.2"	"crosshair color to display when wielding the H.L.A.C."
+seta crosshair_hlac_alpha 1	"crosshair alpha value to display when wielding the H.L.A.C."
+seta crosshair_hlac_size 0.6	"crosshair size when wielding the H.L.A.C."
+seta crosshair_seeker ""	"crosshair to display when wielding the TAG Seeker"
+seta crosshair_seeker_color "1 0.35 0.35"	"crosshair color to display when wielding the TAG seeker"
+seta crosshair_seeker_alpha 0.9	"crosshair alpha value to display when wielding the TAG seeker"
+seta crosshair_seeker_size 0.8	"crosshair size when wielding the TAG seeker"
+seta crosshair_rifle ""	"crosshair to display when wielding the rifle"
+seta crosshair_rifle_color "0.85 0.5 0.25"	"crosshair color to display when wielding the rifle"
+seta crosshair_rifle_alpha 1	"crosshair alpha value to display when wielding the rifle"
+seta crosshair_rifle_size 0.5	"crosshair size when wielding the rifle"
+seta crosshair_tuba ""	"crosshair to display when wielding the tuba"
+seta crosshair_tuba_color "0.85 0.5 0.25"	"crosshair color to display when wielding the tuba"
+seta crosshair_tuba_alpha 1	"crosshair alpha value to display when wielding the tuba"
+seta crosshair_tuba_size 1	"crosshair size when wielding the tuba"
+seta crosshair_fireball ""	"crosshair to display when wielding the fireball"
+seta crosshair_fireball_color "0.2 1.0 0.2"	"crosshair color to display when wielding the fireball"
+seta crosshair_fireball_alpha 1	"crosshair alpha value to display when wielding the fireball"
+seta crosshair_fireball_size 1	"crosshair size when wielding the fireball"
+
 
 // =========================
 //  Crosshair ring settings
@@ -55,15 +133,15 @@ seta crosshair_ring_inner 0 "allow inner rings to be drawn too"
 seta crosshair_ring_size 2	"ring size"
 seta crosshair_ring_alpha 0.2	"ring alpha"
 
-// vortex ring // WEAPONTODO: Make this part of the crosshair line in REGISTER_WEAPON
-seta crosshair_ring_vortex 1 "draw a ring showing the current charge of the vortex"
-seta crosshair_ring_vortex_alpha 0.15
-seta crosshair_ring_vortex_inner_alpha 0.15
-seta crosshair_ring_vortex_inner_color_red 0.8
-seta crosshair_ring_vortex_inner_color_green 0
-seta crosshair_ring_vortex_inner_color_blue 0
-seta crosshair_ring_vortex_currentcharge_scale 30
-seta crosshair_ring_vortex_currentcharge_movingavg_rate 0.05
+// nexgun ring
+seta crosshair_ring_nex 1 "draw a ring showing the current charge of the nexgun"
+seta crosshair_ring_nex_alpha 0.15
+seta crosshair_ring_nex_inner_alpha 0.15
+seta crosshair_ring_nex_inner_color_red 0.8
+seta crosshair_ring_nex_inner_color_green 0
+seta crosshair_ring_nex_inner_color_blue 0
+seta crosshair_ring_nex_currentcharge_scale 30
+seta crosshair_ring_nex_currentcharge_movingavg_rate 0.05
 
 // minelayer ring
 seta crosshair_ring_minelayer 1
diff --git a/defaultXPM.cfg b/defaultXPM.cfg
index f6f25d338..4a55a5ee7 100644
--- a/defaultXPM.cfg
+++ b/defaultXPM.cfg
@@ -3,7 +3,7 @@
 // ==================
 
 exec defaultXonotic.cfg
-exec balance-xpm.cfg
+exec balanceXPM.cfg
 
 // general gameplay
 set g_norecoil 1
diff --git a/defaultXonotic.cfg b/defaultXonotic.cfg
index 9480860c6..18af3e895 100644
--- a/defaultXonotic.cfg
+++ b/defaultXonotic.cfg
@@ -57,7 +57,7 @@ _cl_playerskin 0
 
 seta cl_reticle 1 "control for toggling whether ANY zoom reticles are shown"
 seta cl_reticle_stretch 0 "whether to stretch reticles so they fit the screen (breaks image proportions)"
-seta cl_reticle_item_vortex 1 "draw aiming reticle for the vortex weapon's zoom, 0 disables and values between 0 and 1 change alpha"
+seta cl_reticle_item_nex 1 "draw aiming reticle for the nex weapon's zoom, 0 disables and values between 0 and 1 change alpha"
 seta cl_reticle_item_normal 1 "draw reticle when zooming with the zoom button, 0 disables and values between 0 and 1 change alpha"
 fov 100
 seta cl_velocityzoom 0	"velocity based zooming of fov, negative values zoom out"
@@ -360,9 +360,9 @@ set bot_ai_keyboard_threshold 0.57
 set bot_ai_aimskill_offset 0.3 "Amount of error induced to the bots aim"
 set bot_ai_aimskill_think 1 "Aiming velocity. Use values below 1 for slower aiming"
 set bot_ai_custom_weapon_priority_distances "300 850"	"Define close and far distances in any order. Based on the distance to the enemy bots will choose different weapons"
-set bot_ai_custom_weapon_priority_far   "vaporizer vortex rifle electro devastator grenadelauncher hagar hlac crylink laser machinegun fireball seeker shotgun tuba minelayer"	"Desired weapons for far distances ordered by priority"
-set bot_ai_custom_weapon_priority_mid   "vaporizer devastator vortex fireball seeker mortar electro machinegun crylink hlac hagar shotgun blaster rifle tuba minelayer arc shockwave"	"Desired weapons for middle distances ordered by priority"
-set bot_ai_custom_weapon_priority_close "vaporizer shotgun vortex machinegun hlac tuba seeker hagar crylink mortar electro rocketlauncher blaster fireball rifle minelayer arc shockwave"	"Desired weapons for close distances ordered by priority"
+set bot_ai_custom_weapon_priority_far   "minstanex nex rifle electro rocketlauncher grenadelauncher hagar hlac crylink laser uzi fireball seeker shotgun tuba minelayer"	"Desired weapons for far distances ordered by priority"
+set bot_ai_custom_weapon_priority_mid   "minstanex rocketlauncher nex fireball seeker grenadelauncher electro uzi crylink hlac hagar shotgun laser rifle tuba minelayer"	"Desired weapons for middle distances ordered by priority"
+set bot_ai_custom_weapon_priority_close "minstanex shotgun nex uzi hlac tuba seeker hagar crylink grenadelauncher electro rocketlauncher laser fireball rifle minelayer"	"Desired weapons for close distances ordered by priority"
 set bot_ai_weapon_combo 1	"Enable bots to do weapon combos"
 set bot_ai_weapon_combo_threshold 0.4	"Try to make a combo N seconds after the last attack"
 set bot_ai_friends_aware_pickup_radius "500"	"Bots will not pickup items if a team mate is this distance near the item"
@@ -1144,12 +1144,12 @@ sv_allowdownloads 0 // download protocol is evil
 
 set g_jump_grunt 0	"Do you make a grunting noise every time you jump? Is it the same grunting noise every time?"
 
-seta cl_weaponpriority "minstanex vortex fireball grenadelauncher machinegun hagar rifle electro rocketlauncher crylink minelayer shotgun hlac tuba laser porto seeker hook" "weapon priority list"
+seta cl_weaponpriority "minstanex nex fireball grenadelauncher uzi hagar rifle electro rocketlauncher crylink minelayer shotgun hlac tuba laser porto seeker hook" "weapon priority list"
 seta cl_weaponpriority_useforcycling 0 "when set, weapon cycling by the mouse wheel makes use of the weapon priority list (the special value 2 uses the weapon ID list for cycling)"
 seta cl_weaponpriority0 "rocketlauncher grenadelauncher hagar seeker fireball" "use impulse 200 for prev gun from this list, 210 for best gun, 220 for next gun.  Default value: explosives"
-seta cl_weaponpriority1 "minstanex vortex crylink hlac electro laser"             "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun.  Default value: energy"
-seta cl_weaponpriority2 "minstanex vortex rifle"                           "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun.  Default value: hitscan exact"
-seta cl_weaponpriority3 "minstanex vortex rifle machinegun shotgun"               "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun.  Default value: hitscan all"
+seta cl_weaponpriority1 "minstanex nex crylink hlac electro laser"             "use impulse 201 for prev gun from this list, 211 for best gun, 221 for next gun.  Default value: energy"
+seta cl_weaponpriority2 "minstanex nex rifle"                           "use impulse 202 for prev gun from this list, 212 for best gun, 222 for next gun.  Default value: hitscan exact"
+seta cl_weaponpriority3 "minstanex nex rifle uzi shotgun"               "use impulse 203 for prev gun from this list, 213 for best gun, 223 for next gun.  Default value: hitscan all"
 seta cl_weaponpriority4 "grenadelauncher minelayer hlac hagar crylink seeker shotgun"    "use impulse 204 for prev gun from this list, 214 for best gun, 224 for next gun.  Default value: spam weapons"
 seta cl_weaponpriority5 "laser hook porto"                                     "use impulse 205 for prev gun from this list, 215 for best gun, 225 for next gun.  Default value: weapons for moving"
 seta cl_weaponpriority6 "" "use impulse 206 for prev gun from this list, 216 for best gun, 226 for next gun"
@@ -1383,19 +1383,19 @@ cl_decals_newsystem 1
 // set the cvars to "0" to totally disable a weapon
 set g_weaponreplace_laser ""
 set g_weaponreplace_shotgun ""
-set g_weaponreplace_machinegun ""
+set g_weaponreplace_uzi ""
 set g_weaponreplace_grenadelauncher ""
 set g_weaponreplace_electro ""
 set g_weaponreplace_crylink ""
-set g_weaponreplace_vortex ""
+set g_weaponreplace_nex ""
 set g_weaponreplace_hagar ""
 set g_weaponreplace_rocketlauncher ""
 set g_weaponreplace_porto ""
-set g_weaponreplace_vaporizer ""
+set g_weaponreplace_minstanex ""
 set g_weaponreplace_hook ""
 set g_weaponreplace_tuba ""
 set g_weaponreplace_fireball ""
-set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping machinegun and shotgun (for Q3A map compatibility in mapinfo files)"
+set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping uzi and shotgun (for Q3A map compatibility in mapinfo files)"
 
 set g_movement_highspeed 1 "movement speed modification factor (only changes movement when above maxspeed)"
 
@@ -1549,7 +1549,8 @@ scr_loadingscreen_scale_base 1
 scr_loadingscreen_scale_limit 2
 
 // other config files
-exec balance-xonotic.cfg
+exec mutator_new_toys.cfg // run BEFORE balance to make sure balance wins
+exec balanceXonotic.cfg
 exec effects-normal.cfg
 exec physicsX.cfg
 exec turrets.cfg
diff --git a/effectinfo.txt b/effectinfo.txt
index 0ca352eea..782521447 100644
--- a/effectinfo.txt
+++ b/effectinfo.txt
@@ -7411,8 +7411,8 @@ velocityjitter 64 64 64
 //lightcolor 1 0.9 0.7
 //lightshadow 1
 
-
 // heal ray muzzleflash
+
 effect healray_muzzleflash
 countabsolute 1
 type smoke
@@ -8949,48 +8949,3 @@ alpha 644 956 2500
 originjitter 64 64 64
 velocityjitter 324 324 324
 rotate -180 180 -100 100
-
-// shockwave_attack
-// used nowhere in code
-effect shockwave_attack // glow and light
-	//countabsolute 1
-	//type smoke
-	//color 0xcc0000 0xff0000
-	//tex 65 65
-	//size 10 15
-	//alpha 256 512 6280
-	//airfriction 10
-	//sizeincrease 1.5
-	//stretchfactor 2
-	//lightradius 200
-	//lightradiusfade 2000
-	//lightcolor 3 0.1 0.1
-effect shockwave_attack // electricity
-	count 1
-	type spark
-	color 0xb44215 0xff0000
-	tex 43 43
-	size 5 7
-	bounce 0
-	alpha 4096 4096 20000
-	airfriction 1
-	originjitter 2 2 2
-	velocityjitter 10 10 10
-	velocitymultiplier 10
-	sizeincrease 1.5
-	stretchfactor 2.3
-	rotate -180 180 4000 -4000
-effect shockwave_attack // fire
-	count 1
-	type spark
-	color 0xff4200 0xff0000
-	tex 8 15
-	size 7 9
-	bounce 0
-	alpha 4096 4096 20000
-	airfriction 1
-	originjitter 2 2 2
-	velocityjitter 10 10 10
-	velocitymultiplier 10
-	sizeincrease 1.5
-	stretchfactor 2
diff --git a/models/weapons/g_arc.md3 b/models/weapons/g_arc.md3
deleted file mode 100755
index 878373964..000000000
Binary files a/models/weapons/g_arc.md3 and /dev/null differ
diff --git a/models/weapons/h_arc.iqm b/models/weapons/h_arc.iqm
deleted file mode 100755
index 9c4a29dbb..000000000
Binary files a/models/weapons/h_arc.iqm and /dev/null differ
diff --git a/models/weapons/h_arc.iqm.framegroups b/models/weapons/h_arc.iqm.framegroups
deleted file mode 100755
index 1c95207bd..000000000
--- a/models/weapons/h_arc.iqm.framegroups
+++ /dev/null
@@ -1,6 +0,0 @@
-1 8 20 0 // fire
-9 23 20 0 // fire2
-32 200 20 1 // idle
-232 40 20 0 // reload
-// compile opts used in the iqm exporter (apparently needed to prevent insane ram usage):
-// fire:1:8, fire2:1:23, idle:1:200, reload:1:40
diff --git a/models/weapons/v_arc.md3 b/models/weapons/v_arc.md3
deleted file mode 100755
index 7415aba60..000000000
Binary files a/models/weapons/v_arc.md3 and /dev/null differ
diff --git a/models/weapons/w_crylink.zym b/models/weapons/w_crylink.zym
new file mode 100644
index 000000000..4aea5b861
Binary files /dev/null and b/models/weapons/w_crylink.zym differ
diff --git a/models/weapons/w_electro.zym b/models/weapons/w_electro.zym
new file mode 100644
index 000000000..70cbd174e
Binary files /dev/null and b/models/weapons/w_electro.zym differ
diff --git a/models/weapons/w_gl.zym b/models/weapons/w_gl.zym
new file mode 100644
index 000000000..5f28a0a1d
Binary files /dev/null and b/models/weapons/w_gl.zym differ
diff --git a/models/weapons/w_hagar.zym b/models/weapons/w_hagar.zym
new file mode 100644
index 000000000..d8d78710f
Binary files /dev/null and b/models/weapons/w_hagar.zym differ
diff --git a/models/weapons/w_laser.zym b/models/weapons/w_laser.zym
new file mode 100644
index 000000000..459b932ac
Binary files /dev/null and b/models/weapons/w_laser.zym differ
diff --git a/models/weapons/w_nex.zym b/models/weapons/w_nex.zym
new file mode 100644
index 000000000..26ae92476
Binary files /dev/null and b/models/weapons/w_nex.zym differ
diff --git a/models/weapons/w_rl.zym b/models/weapons/w_rl.zym
new file mode 100644
index 000000000..6d3f70193
Binary files /dev/null and b/models/weapons/w_rl.zym differ
diff --git a/models/weapons/w_shotgun.zym b/models/weapons/w_shotgun.zym
new file mode 100644
index 000000000..031fa8609
Binary files /dev/null and b/models/weapons/w_shotgun.zym differ
diff --git a/models/weapons/w_uzi.zym b/models/weapons/w_uzi.zym
new file mode 100644
index 000000000..f86923748
Binary files /dev/null and b/models/weapons/w_uzi.zym differ
diff --git a/mutator_new_toys.cfg b/mutator_new_toys.cfg
new file mode 100644
index 000000000..9835f41dd
--- /dev/null
+++ b/mutator_new_toys.cfg
@@ -0,0 +1,166 @@
+set g_new_toys 0 "Mutator 'New Toys': enable extra fun guns"
+set g_new_toys_autoreplace 2 "0: never replace, 1: always auto replace guns by available new toys, 2: randomly auto replace guns by available new toys"
+
+set g_weaponreplace_hlac ""
+set g_weaponreplace_minelayer ""
+set g_weaponreplace_rifle ""
+set g_weaponreplace_seeker ""
+
+set g_start_weapon_hlac -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE
+set g_start_weapon_minelayer -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+set g_start_weapon_rifle -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE
+set g_start_weapon_seeker -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
+
+// {{{ hlac
+set g_balance_hlac_primary_spread_min 0.01
+set g_balance_hlac_primary_spread_max 0.25
+set g_balance_hlac_primary_spread_add 0.0045
+set g_balance_hlac_primary_spread_crouchmod 0.25
+
+set g_balance_hlac_primary_damage 18
+set g_balance_hlac_primary_edgedamage 9
+set g_balance_hlac_primary_force 90
+set g_balance_hlac_primary_radius 70
+set g_balance_hlac_primary_speed 9000
+set g_balance_hlac_primary_lifetime 5
+
+set g_balance_hlac_primary_refire 0.15
+set g_balance_hlac_primary_animtime 0.4
+set g_balance_hlac_primary_ammo 1
+
+set g_balance_hlac_secondary 1
+set g_balance_hlac_secondary_spread 0.15
+set g_balance_hlac_secondary_spread_crouchmod 0.5
+
+set g_balance_hlac_secondary_damage 15
+set g_balance_hlac_secondary_edgedamage 7.5
+set g_balance_hlac_secondary_force 90
+set g_balance_hlac_secondary_radius 70
+set g_balance_hlac_secondary_speed 9000
+set g_balance_hlac_secondary_lifetime 5
+
+set g_balance_hlac_secondary_refire 1
+set g_balance_hlac_secondary_animtime 0.3
+set g_balance_hlac_secondary_ammo 10
+set g_balance_hlac_secondary_shots 6
+
+set g_balance_hlac_switchdelay_drop 0.2
+set g_balance_hlac_switchdelay_raise 0.2
+
+set g_balance_hlac_reload_ammo 0 //default: 20
+set g_balance_hlac_reload_time 2
+// }}}
+// {{{ minelayer
+set g_balance_minelayer_damage 40
+set g_balance_minelayer_edgedamage 20
+set g_balance_minelayer_force 250
+set g_balance_minelayer_radius 175
+set g_balance_minelayer_proximityradius 150
+set g_balance_minelayer_speed 1000
+set g_balance_minelayer_lifetime 10
+set g_balance_minelayer_lifetime_countdown 0.5
+set g_balance_minelayer_refire 1.5
+set g_balance_minelayer_animtime 0.4
+set g_balance_minelayer_ammo 4
+set g_balance_minelayer_health 15
+set g_balance_minelayer_limit 3 // 0 disables the limit
+set g_balance_minelayer_protection 0 // don't explode if the mine would hurt the owner or a team mate
+set g_balance_minelayer_damageforcescale 0
+set g_balance_minelayer_detonatedelay -1 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
+set g_balance_minelayer_time 0.5
+set g_balance_minelayer_remote_damage 45
+set g_balance_minelayer_remote_edgedamage 40
+set g_balance_minelayer_remote_radius 200
+set g_balance_minelayer_remote_force 300
+set g_balance_minelayer_switchdelay_drop 0.2
+set g_balance_minelayer_switchdelay_raise 0.2
+set g_balance_minelayer_reload_ammo 0 //default: 15
+set g_balance_minelayer_reload_time 2
+// }}}
+// {{{ rifle
+set g_balance_rifle_bursttime 0
+set g_balance_rifle_primary_tracer 1
+set g_balance_rifle_primary_shots 1
+set g_balance_rifle_primary_damage 80
+set g_balance_rifle_primary_spread 0
+set g_balance_rifle_primary_force 100
+set g_balance_rifle_primary_refire 1.2
+set g_balance_rifle_primary_animtime 0.4
+set g_balance_rifle_primary_ammo 10
+set g_balance_rifle_primary_solidpenetration 62.2
+set g_balance_rifle_primary_burstcost 0
+set g_balance_rifle_primary_bullethail 0 // empty magazine on shot
+set g_balance_rifle_secondary 1
+set g_balance_rifle_secondary_reload 0
+set g_balance_rifle_secondary_tracer 0
+set g_balance_rifle_secondary_shots 4
+set g_balance_rifle_secondary_damage 20
+set g_balance_rifle_secondary_spread 0.04
+set g_balance_rifle_secondary_force 50
+set g_balance_rifle_secondary_refire 0.9
+set g_balance_rifle_secondary_animtime 0.3
+set g_balance_rifle_secondary_ammo 10
+set g_balance_rifle_secondary_solidpenetration 15.5
+set g_balance_rifle_secondary_burstcost 0
+set g_balance_rifle_secondary_bullethail 0 // empty magazine on shot
+set g_balance_rifle_switchdelay_drop 0.2
+set g_balance_rifle_switchdelay_raise 0.2
+set g_balance_rifle_reload_ammo 80 //default: 80
+set g_balance_rifle_reload_time 2
+// }}}
+// {{{ seeker
+set g_balance_seeker_type 0 // 0 = old seeker, 1 = new seeker
+set g_balance_seeker_flac_ammo 1
+set g_balance_seeker_flac_animtime 0.1
+set g_balance_seeker_flac_damage 15
+set g_balance_seeker_flac_edgedamage 10
+set g_balance_seeker_flac_force 50
+set g_balance_seeker_flac_lifetime 0.1
+set g_balance_seeker_flac_lifetime_rand 0.05
+set g_balance_seeker_flac_radius 100
+set g_balance_seeker_flac_refire 0.1
+set g_balance_seeker_flac_speed 3000
+set g_balance_seeker_flac_speed_up 1000
+set g_balance_seeker_flac_speed_z 0
+set g_balance_seeker_flac_spread 0.4
+set g_balance_seeker_tag_ammo 1
+set g_balance_seeker_tag_animtime 0.2
+set g_balance_seeker_tag_damageforcescale 4
+set g_balance_seeker_tag_health 5
+set g_balance_seeker_tag_lifetime 15
+set g_balance_seeker_tag_refire 0.75 // LOG: 0.7 -> 0.75
+set g_balance_seeker_tag_speed 5000
+set g_balance_seeker_tag_spread 0
+set g_balance_seeker_tag_tracker_lifetime 10
+set g_balance_seeker_missile_accel 1400
+set g_balance_seeker_missile_ammo 2
+set g_balance_seeker_missile_animtime 0.2
+set g_balance_seeker_missile_count 3 // LOG: 8 -> 3
+set g_balance_seeker_missile_damage 30 // LOG: 15 -> 30
+set g_balance_seeker_missile_damageforcescale 4
+set g_balance_seeker_missile_decel 1400
+set g_balance_seeker_missile_delay 0.25
+set g_balance_seeker_missile_edgedamage 10
+set g_balance_seeker_missile_force 150 // LOG: 100 -> 150
+set g_balance_seeker_missile_health 5
+set g_balance_seeker_missile_lifetime 15
+set g_balance_seeker_missile_proxy 0
+set g_balance_seeker_missile_proxy_delay 0.2
+set g_balance_seeker_missile_proxy_maxrange 45
+set g_balance_seeker_missile_radius 80
+set g_balance_seeker_missile_refire 0.5
+set g_balance_seeker_missile_smart 1
+set g_balance_seeker_missile_smart_mindist 800
+set g_balance_seeker_missile_smart_trace_max 2500
+set g_balance_seeker_missile_smart_trace_min 1000
+set g_balance_seeker_missile_speed 700
+set g_balance_seeker_missile_speed_up 300
+set g_balance_seeker_missile_speed_z 0
+set g_balance_seeker_missile_speed_max 1300 // LOG: 1400 -> 1300
+set g_balance_seeker_missile_spread 0
+set g_balance_seeker_missile_turnrate 0.65
+set g_balance_seeker_switchdelay_drop 0.2
+set g_balance_seeker_switchdelay_raise 0.2
+set g_balance_seeker_reload_ammo 0 //default: 15
+set g_balance_seeker_reload_time 2
+// End new seeker
diff --git a/mutators.cfg b/mutators.cfg
index 6873aa89e..4b7904867 100644
--- a/mutators.cfg
+++ b/mutators.cfg
@@ -231,13 +231,6 @@ set g_campcheck_damage 100
 set g_campcheck_distance 1800
 
 
-<<<<<<< HEAD
-// ==========
-//  New Toys
-// ==========
-set g_new_toys 0 "Mutator 'New Toys': enable extra fun guns"
-set g_new_toys_autoreplace 2 "0: never replace, 1: always auto replace guns by available new toys, 2: randomly auto replace guns by available new toys"
-=======
 // =======
 //  buffs
 // =======
@@ -284,4 +277,3 @@ set g_buffs_flight_gravity 0.3 "player gravity multiplier while holding flight b
 set g_buffs_invisible 1 "invisible buff: carrier becomes invisible"
 set g_buffs_invisible_alpha 0.4 "player invisibility multiplier while holding invisible buff"
 
->>>>>>> master
diff --git a/oldbalance25.cfg b/oldbalance25.cfg
deleted file mode 100644
index df43b549e..000000000
--- a/oldbalance25.cfg
+++ /dev/null
@@ -1,780 +0,0 @@
-g_mod_balance Nexuiz25
-
-// {{{ starting gear
-set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_balance_health_start 150
-set g_balance_armor_start 0
-set g_start_ammo_shells 40
-set g_start_ammo_nails 0
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_fuel 0
-set g_warmup_start_health 250 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 250
-set g_lms_start_armor 100
-set g_lms_start_ammo_shells 50
-set g_lms_start_ammo_nails 150
-set g_lms_start_ammo_rockets 50
-set g_lms_start_ammo_cells 50
-set g_lms_start_ammo_fuel 0
-set g_balance_nix_roundtime 25
-set g_balance_nix_incrtime 1.6
-set g_balance_nix_ammo_shells 15
-set g_balance_nix_ammo_nails 45
-set g_balance_nix_ammo_rockets 15
-set g_balance_nix_ammo_cells 15
-set g_balance_nix_ammo_fuel 0
-set g_balance_nix_ammoincr_shells 2
-set g_balance_nix_ammoincr_nails 6
-set g_balance_nix_ammoincr_rockets 2
-set g_balance_nix_ammoincr_cells 2
-set g_balance_nix_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_ammo_anyway 0
-set g_pickup_weapons_anyway 0
-set g_pickup_shells 15
-set g_pickup_shells_weapon 15
-set g_pickup_shells_max 999
-set g_pickup_nails 80
-set g_pickup_nails_weapon 80
-set g_pickup_nails_max 999
-set g_pickup_rockets 15
-set g_pickup_rockets_weapon 15
-set g_pickup_rockets_max 999
-set g_pickup_cells 25
-set g_pickup_cells_weapon 25
-set g_pickup_cells_max 999
-set g_pickup_fuel 25
-set g_pickup_fuel_weapon 25
-set g_pickup_fuel_jetpack 50
-set g_pickup_fuel_max 999
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 999
-set g_pickup_armorsmall_anyway 0
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 999
-set g_pickup_armormedium_anyway 0
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 999
-set g_pickup_armorbig_anyway 0
-set g_pickup_armorlarge 100
-set g_pickup_armorlarge_max 999
-set g_pickup_armorlarge_anyway 0
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 999
-set g_pickup_healthsmall_anyway 0
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 999
-set g_pickup_healthmedium_anyway 0
-set g_pickup_healthlarge 50
-set g_pickup_healthlarge_max 999
-set g_pickup_healthlarge_anyway 0
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 999
-set g_pickup_healthmega_anyway 0
-set g_pickup_respawntime_short 15
-set g_pickup_respawntime_medium 20
-set g_pickup_respawntime_long 30
-set g_pickup_respawntime_powerup 120
-set g_pickup_respawntime_weapon 15
-set g_pickup_respawntime_superweapon 120
-set g_pickup_respawntime_ammo 15
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 10
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_superweapon 10
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0.1
-set g_balance_health_regenlinear 0
-set g_balance_pause_health_regen 5
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0.1
-set g_balance_health_rotlinear 0
-set g_balance_pause_health_rot 5
-set g_balance_pause_health_rot_spawn 10
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 999
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0.1
-set g_balance_armor_rotlinear 0
-set g_balance_pause_armor_rot 5
-set g_balance_pause_armor_rot_spawn 10
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 999
-set g_balance_armor_blockpercent 0.6
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 999
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0.6
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 1
-set g_throughfloor_force 1
-set g_projectiles_damage 2
-// possible values:
-// -2: absolutely no damage to projectiles (no exceptions)
-// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
-// 0: only damage from contents (lava/slime) or exceptions
-// 1: only self damage or damage from contents or exceptions
-// 2: allow all damage to projectiles normally
-set g_projectiles_keep_owner 0
-set g_projectiles_newton_style 2
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-set g_projectiles_newton_style_2_minfactor 0.7
-set g_projectiles_newton_style_2_maxfactor 5
-set g_projectiles_spread_style 0
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 150
-set g_balance_falldamage_minspeed 1400
-set g_balance_falldamage_factor 0.15
-set g_balance_falldamage_maxdamage 25
-set g_balance_damagepush_speedfactor 0
-set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
-set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
-set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
-set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
-set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
-set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.2
-set g_balance_powerup_invincible_time 30
-set g_balance_powerup_strength_damage 3
-set g_balance_powerup_strength_force 4
-set g_balance_powerup_strength_time 30
-set g_balance_powerup_strength_selfdamage 1.5
-set g_balance_powerup_strength_selfforce 1.5
-set g_balance_superweapons_time 30
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_attenuation 2 "jetpack sound attenuation"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 130
-set g_balance_grapplehook_damagedbycontents 0
-set g_balance_grapplehook_refire 0.2
-// }}}
-
-// {{{ weapon properties
-// {{{ laser
-set g_balance_laser_melee_animtime 0.3
-set g_balance_laser_melee_damage 80
-set g_balance_laser_melee_delay 0.25
-set g_balance_laser_melee_force 200
-set g_balance_laser_melee_multihit 1
-set g_balance_laser_melee_no_doubleslap 1
-set g_balance_laser_melee_nonplayerdamage 40
-set g_balance_laser_melee_range 120
-set g_balance_laser_melee_refire 1.25
-set g_balance_laser_melee_swing_side 120
-set g_balance_laser_melee_swing_up 30
-set g_balance_laser_melee_time 0.15
-set g_balance_laser_melee_traces 10
-
-set g_balance_laser_primary 1 // 0 = shockwave attack, 1 = projectile primary
-set g_balance_laser_primary_damage 35
-set g_balance_laser_primary_edgedamage 10
-set g_balance_laser_primary_force 400
-set g_balance_laser_primary_radius 70
-set g_balance_laser_primary_speed 9000
-set g_balance_laser_primary_spread 0
-set g_balance_laser_primary_refire 0.7
-set g_balance_laser_primary_animtime 0.3
-set g_balance_laser_primary_lifetime 30
-set g_balance_laser_primary_shotangle 0
-set g_balance_laser_primary_delay 0.05
-set g_balance_laser_primary_force_zscale 1
-set g_balance_laser_primary_force_velocitybias 0
-set g_balance_laser_primary_force_other_scale 1
-
-set g_balance_laser_secondary 0 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary
-set g_balance_laser_secondary_damage 35
-set g_balance_laser_secondary_edgedamage 10
-set g_balance_laser_secondary_force 400
-set g_balance_laser_secondary_radius 70
-set g_balance_laser_secondary_speed 9000
-set g_balance_laser_secondary_spread 0
-set g_balance_laser_secondary_refire 0.7
-set g_balance_laser_secondary_animtime 0.3
-set g_balance_laser_secondary_lifetime 30
-set g_balance_laser_secondary_shotangle 0
-set g_balance_laser_secondary_delay 0
-set g_balance_laser_secondary_force_zscale 1
-set g_balance_laser_secondary_force_velocitybias 0
-set g_balance_laser_secondary_force_other_scale 1
-
-set g_balance_laser_shockwave_damage 20
-set g_balance_laser_shockwave_distance 2000
-set g_balance_laser_shockwave_edgedamage 0
-set g_balance_laser_shockwave_force 200
-set g_balance_laser_shockwave_force_forwardbias 50
-set g_balance_laser_shockwave_force_zscale 1.5
-set g_balance_laser_shockwave_jump_damage 20
-set g_balance_laser_shockwave_jump_edgedamage 0
-set g_balance_laser_shockwave_jump_force 300
-set g_balance_laser_shockwave_jump_force_velocitybias 0
-set g_balance_laser_shockwave_jump_force_zscale 1.25
-set g_balance_laser_shockwave_jump_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_jump_multiplier_distance 0.5
-set g_balance_laser_shockwave_jump_multiplier_min 0
-set g_balance_laser_shockwave_jump_radius 150
-set g_balance_laser_shockwave_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_multiplier_distance 0.5
-set g_balance_laser_shockwave_multiplier_min 0
-set g_balance_laser_shockwave_splash_damage 15
-set g_balance_laser_shockwave_splash_edgedamage 0
-set g_balance_laser_shockwave_splash_force 100
-set g_balance_laser_shockwave_splash_force_forwardbias 50
-set g_balance_laser_shockwave_splash_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_splash_multiplier_distance 0.5
-set g_balance_laser_shockwave_splash_multiplier_min 0
-set g_balance_laser_shockwave_splash_radius 70
-set g_balance_laser_shockwave_spread_max 100
-set g_balance_laser_shockwave_spread_min 20
-
-set g_balance_laser_switchdelay_drop 0.15
-set g_balance_laser_switchdelay_raise 0.15
-set g_balance_laser_reload_ammo 0 //default: 6
-set g_balance_laser_reload_time 2
-// }}}
-// {{{ shotgun
-set g_balance_shotgun_primary_bullets 6
-set g_balance_shotgun_primary_damage 9
-set g_balance_shotgun_primary_force 60
-set g_balance_shotgun_primary_spread 0.07
-set g_balance_shotgun_primary_refire 0.5
-set g_balance_shotgun_primary_animtime 0.2
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_solidpenetration 3.8
-set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
-set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing_side 120
-set g_balance_shotgun_secondary_melee_swing_up 30
-set g_balance_shotgun_secondary_melee_time 0.15
-set g_balance_shotgun_secondary_melee_traces 10
-set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_melee_nonplayerdamage 0
-set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_damage 115
-set g_balance_shotgun_secondary_force 150
-set g_balance_shotgun_secondary_refire 1.1
-set g_balance_shotgun_secondary_animtime 1
-set g_balance_shotgun_switchdelay_drop 0.15
-set g_balance_shotgun_switchdelay_raise 0.15
-set g_balance_shotgun_reload_ammo 0 //default: 5
-set g_balance_shotgun_reload_time 2
-// }}}
-// {{{ uzi
-set g_balance_uzi_mode 0 				// Activates varible spread for sustained & burst mode secondary
-set g_balance_uzi_spread_min 0.02
-set g_balance_uzi_spread_max 0.6
-set g_balance_uzi_spread_add 0.012
-
-set g_balance_uzi_burst 0				// # of bullets in a burst (if set to 2 or more)
-set g_balance_uzi_burst_animtime 0.75
-set g_balance_uzi_burst_refire 0.05		// refire between burst bullets
-set g_balance_uzi_burst_refire2 0.75	// refire after burst
-set g_balance_uzi_burst_spread 0.04
-set g_balance_uzi_burst_damage 18
-set g_balance_uzi_burst_force 50
-set g_balance_uzi_burst_ammo 3
-
-set g_balance_uzi_first 1
-set g_balance_uzi_first_damage 30
-set g_balance_uzi_first_force 50
-set g_balance_uzi_first_spread 0.015
-set g_balance_uzi_first_refire 0.2
-set g_balance_uzi_first_ammo 1
-
-set g_balance_uzi_sustained_damage 15
-set g_balance_uzi_sustained_force 27
-set g_balance_uzi_sustained_spread 0.05
-set g_balance_uzi_sustained_refire 0.1
-set g_balance_uzi_sustained_ammo 1
-
-set g_balance_uzi_solidpenetration 13.1
-
-set g_balance_uzi_switchdelay_drop 0.15
-set g_balance_uzi_switchdelay_raise 0.15
-
-set g_balance_uzi_reload_ammo 0 //default: 30
-set g_balance_uzi_reload_time 2
-// }}}
-// {{{ mortar
-set g_balance_grenadelauncher_primary_type 0
-set g_balance_grenadelauncher_primary_damage 70
-set g_balance_grenadelauncher_primary_edgedamage 38
-set g_balance_grenadelauncher_primary_force 400
-set g_balance_grenadelauncher_primary_radius 140
-set g_balance_grenadelauncher_primary_speed 2000
-set g_balance_grenadelauncher_primary_speed_up 200
-set g_balance_grenadelauncher_primary_speed_z 0
-set g_balance_grenadelauncher_primary_spread 0
-set g_balance_grenadelauncher_primary_lifetime 30
-set g_balance_grenadelauncher_primary_lifetime2 1
-set g_balance_grenadelauncher_primary_refire 0.8
-set g_balance_grenadelauncher_primary_animtime 0.3
-set g_balance_grenadelauncher_primary_ammo 2
-set g_balance_grenadelauncher_primary_health 25
-set g_balance_grenadelauncher_primary_damageforcescale 4
-set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
-
-set g_balance_grenadelauncher_secondary_type 1
-set g_balance_grenadelauncher_secondary_damage 70
-set g_balance_grenadelauncher_secondary_edgedamage 38
-set g_balance_grenadelauncher_secondary_force 400
-set g_balance_grenadelauncher_secondary_radius 140
-set g_balance_grenadelauncher_secondary_speed 1400
-set g_balance_grenadelauncher_secondary_speed_up 200
-set g_balance_grenadelauncher_secondary_speed_z 0
-set g_balance_grenadelauncher_secondary_spread 0
-set g_balance_grenadelauncher_secondary_lifetime 2.5
-set g_balance_grenadelauncher_secondary_lifetime_bounce 0
-set g_balance_grenadelauncher_secondary_lifetime_stick 0
-set g_balance_grenadelauncher_secondary_refire 0.7
-set g_balance_grenadelauncher_secondary_animtime 0.3
-set g_balance_grenadelauncher_secondary_ammo 2
-set g_balance_grenadelauncher_secondary_health 10
-set g_balance_grenadelauncher_secondary_damageforcescale 4
-set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
-
-set g_balance_grenadelauncher_bouncefactor 0.5
-set g_balance_grenadelauncher_bouncestop 0.075
-
-set g_balance_grenadelauncher_switchdelay_drop 0.15
-set g_balance_grenadelauncher_switchdelay_raise 0.15
-
-set g_balance_grenadelauncher_reload_ammo 0 //default: 12
-set g_balance_grenadelauncher_reload_time 2
-// }}}
-// {{{ electro
-set g_balance_electro_lightning 0
-set g_balance_electro_primary_damage 65
-set g_balance_electro_primary_edgedamage 0
-set g_balance_electro_primary_force 200
-set g_balance_electro_primary_force_up 0
-set g_balance_electro_primary_radius 150
-set g_balance_electro_primary_comboradius 0
-set g_balance_electro_primary_speed 2000
-set g_balance_electro_primary_spread 0
-set g_balance_electro_primary_lifetime 30
-set g_balance_electro_primary_refire 0.6
-set g_balance_electro_primary_animtime 0.3
-set g_balance_electro_primary_ammo 2
-set g_balance_electro_primary_range 0
-set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius
-set g_balance_electro_primary_falloff_maxdist 850
-set g_balance_electro_primary_falloff_halflifedist 425
-set g_balance_electro_secondary_damage 50
-set g_balance_electro_secondary_edgedamage 0
-set g_balance_electro_secondary_force 200
-set g_balance_electro_secondary_radius 150
-set g_balance_electro_secondary_speed 900
-set g_balance_electro_secondary_speed_up 200
-set g_balance_electro_secondary_speed_z 0
-set g_balance_electro_secondary_spread 0
-set g_balance_electro_secondary_lifetime 5
-set g_balance_electro_secondary_refire 0.3
-set g_balance_electro_secondary_refire2 0
-set g_balance_electro_secondary_animtime 0.3
-set g_balance_electro_secondary_ammo 2
-set g_balance_electro_secondary_health 5
-set g_balance_electro_secondary_damageforcescale 4
-set g_balance_electro_secondary_damagedbycontents 0
-set g_balance_electro_secondary_count 1
-set g_balance_electro_secondary_bouncefactor 0.5
-set g_balance_electro_secondary_bouncestop 0.075
-set g_balance_electro_combo_damage 80
-set g_balance_electro_combo_edgedamage 0
-set g_balance_electro_combo_force 200
-set g_balance_electro_combo_radius 250
-set g_balance_electro_combo_comboradius 0
-set g_balance_electro_combo_speed 2000
-set g_balance_electro_combo_safeammocheck 0
-set g_balance_electro_switchdelay_drop 0.15
-set g_balance_electro_switchdelay_raise 0.15
-set g_balance_electro_reload_ammo 0 //default: 20
-set g_balance_electro_reload_time 2
-// }}}
-// {{{ lightning
-set g_balance_lightning_primary_ammo 5
-set g_balance_lightning_primary_animtime 0.2
-set g_balance_lightning_primary_damage 100
-set g_balance_lightning_primary_edgedamage 0
-set g_balance_lightning_primary_falloff_mindist 0
-set g_balance_lightning_primary_falloff_maxdist 0
-set g_balance_lightning_primary_falloff_halflifedist 0
-set g_balance_lightning_primary_force 425
-set g_balance_lightning_primary_lifetime 0
-set g_balance_lightning_primary_radius 850
-set g_balance_lightning_primary_range 800
-set g_balance_lightning_primary_refire 0.4
-set g_balance_lightning_primary_speed 0
-set g_balance_lightning_primary_spread 0
-set g_balance_lightning_secondary_ammo 5
-set g_balance_lightning_secondary_animtime 0.5
-set g_balance_lightning_secondary_damage 100
-set g_balance_lightning_secondary_damageforcescale 4
-set g_balance_lightning_secondary_edgedamage 80
-set g_balance_lightning_secondary_flyingdamage 1
-set g_balance_lightning_secondary_flyingforce -80
-set g_balance_lightning_secondary_flyingradius 200
-set g_balance_lightning_secondary_force -200
-set g_balance_lightning_secondary_health 1
-set g_balance_lightning_secondary_lifetime 30
-set g_balance_lightning_secondary_radius 300
-set g_balance_lightning_secondary_refire 5
-set g_balance_lightning_secondary_speed 600
-// }}}
-// {{{ crylink
-set g_balance_crylink_primary_damage 18
-set g_balance_crylink_primary_edgedamage 0
-set g_balance_crylink_primary_force -55
-set g_balance_crylink_primary_radius 80
-set g_balance_crylink_primary_speed 7000
-set g_balance_crylink_primary_spread 0.03
-set g_balance_crylink_primary_shots 4
-set g_balance_crylink_primary_bounces 1
-set g_balance_crylink_primary_refire 0.4
-set g_balance_crylink_primary_animtime 0.3
-set g_balance_crylink_primary_ammo 2
-set g_balance_crylink_primary_bouncedamagefactor 0.5
-set g_balance_crylink_primary_joindelay 0
-set g_balance_crylink_primary_joinspread 0
-set g_balance_crylink_primary_joinexplode 0
-set g_balance_crylink_primary_joinexplode_damage 0
-set g_balance_crylink_primary_joinexplode_edgedamage 0
-set g_balance_crylink_primary_joinexplode_radius 0
-set g_balance_crylink_primary_joinexplode_force 0
-set g_balance_crylink_primary_linkexplode 1
-
-set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000
-set g_balance_crylink_primary_middle_fadetime 5
-set g_balance_crylink_primary_other_lifetime 0.1 // range: 700 full, fades to 2450
-set g_balance_crylink_primary_other_fadetime 0.25
-
-set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_damage 18
-set g_balance_crylink_secondary_edgedamage 0
-set g_balance_crylink_secondary_force -55
-set g_balance_crylink_secondary_radius 3
-set g_balance_crylink_secondary_speed 7000
-set g_balance_crylink_secondary_spread 0.08
-set g_balance_crylink_secondary_spreadtype 0
-set g_balance_crylink_secondary_shots 7
-set g_balance_crylink_secondary_bounces 0
-set g_balance_crylink_secondary_refire 0.5
-set g_balance_crylink_secondary_animtime 0.3
-set g_balance_crylink_secondary_ammo 2
-set g_balance_crylink_secondary_bouncedamagefactor 0.5
-set g_balance_crylink_secondary_joindelay 0
-set g_balance_crylink_secondary_joinspread 0
-set g_balance_crylink_secondary_joinexplode 0
-set g_balance_crylink_secondary_joinexplode_damage 0
-set g_balance_crylink_secondary_joinexplode_edgedamage 0
-set g_balance_crylink_secondary_joinexplode_radius 0
-set g_balance_crylink_secondary_joinexplode_force 0
-set g_balance_crylink_secondary_linkexplode 1
-
-set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
-set g_balance_crylink_secondary_middle_fadetime 5
-set g_balance_crylink_secondary_line_lifetime 2 // range: 35000 full, fades to 70000
-set g_balance_crylink_secondary_line_fadetime 2
-
-set g_balance_crylink_switchdelay_drop 0.15
-set g_balance_crylink_switchdelay_raise 0.15
-
-set g_balance_crylink_reload_ammo 0 //default: 10
-set g_balance_crylink_reload_time 2
-// }}}
-// {{{ nex
-set g_balance_nex_primary_damage 100
-set g_balance_nex_primary_force 600
-set g_balance_nex_primary_refire 1.5
-set g_balance_nex_primary_animtime 0.3
-set g_balance_nex_primary_ammo 5
-set g_balance_nex_primary_damagefalloff_mindist 0
-set g_balance_nex_primary_damagefalloff_maxdist 0
-set g_balance_nex_primary_damagefalloff_halflife 0
-set g_balance_nex_primary_damagefalloff_forcehalflife 0
-
-set g_balance_nex_secondary 0
-set g_balance_nex_secondary_charge 0
-set g_balance_nex_secondary_charge_rate 0.1
-set g_balance_nex_secondary_chargepool 0
-set g_balance_nex_secondary_chargepool_regen 0.15
-set g_balance_nex_secondary_chargepool_pause_regen 1
-set g_balance_nex_secondary_chargepool_pause_health_regen 1
-set g_balance_nex_secondary_damage 100
-set g_balance_nex_secondary_force 600
-set g_balance_nex_secondary_refire 1.5
-set g_balance_nex_secondary_animtime 0.3
-set g_balance_nex_secondary_ammo 5
-set g_balance_nex_secondary_damagefalloff_mindist 0
-set g_balance_nex_secondary_damagefalloff_maxdist 0
-set g_balance_nex_secondary_damagefalloff_halflife 0
-set g_balance_nex_secondary_damagefalloff_forcehalflife 0
-
-set g_balance_nex_charge 0
-set g_balance_nex_charge_mindmg 40
-set g_balance_nex_charge_start 0
-set g_balance_nex_charge_rate 0.1
-set g_balance_nex_charge_animlimit 0.5
-set g_balance_nex_charge_limit 0.5
-set g_balance_nex_charge_rot_rate 0
-set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button
-set g_balance_nex_charge_shot_multiplier 0.5
-set g_balance_nex_charge_velocity_rate 0.2
-set g_balance_nex_charge_minspeed 400
-set g_balance_nex_charge_maxspeed 1000
-
-set g_balance_nex_switchdelay_drop 0.15
-set g_balance_nex_switchdelay_raise 0.15
-
-set g_balance_nex_reload_ammo 0 //default: 25
-set g_balance_nex_reload_time 2
-// }}}
-// {{{ minstanex
-set g_balance_minstanex_refire 1
-set g_balance_minstanex_animtime 0.3
-set g_balance_minstanex_ammo 10
-set g_balance_minstanex_laser_ammo 0
-set g_balance_minstanex_laser_animtime 0.3
-set g_balance_minstanex_laser_refire 0.7
-set g_balance_minstanex_switchdelay_drop 0.15
-set g_balance_minstanex_switchdelay_raise 0.15
-set g_balance_minstanex_reload_ammo 0 //default: 50
-set g_balance_minstanex_reload_time 2
-// }}}
-// {{{ hagar
-set g_balance_hagar_primary_damage 37
-set g_balance_hagar_primary_edgedamage 15
-set g_balance_hagar_primary_force 100
-set g_balance_hagar_primary_health 0
-set g_balance_hagar_primary_damageforcescale 0
-set g_balance_hagar_primary_radius 65
-set g_balance_hagar_primary_spread 0.010
-set g_balance_hagar_primary_speed 3000
-set g_balance_hagar_primary_lifetime 30
-set g_balance_hagar_primary_refire 0.15
-set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_secondary 1
-set g_balance_hagar_secondary_load 0
-set g_balance_hagar_secondary_load_speed 0.6
-set g_balance_hagar_secondary_load_spread 0.075
-set g_balance_hagar_secondary_load_spread_bias 0.5
-set g_balance_hagar_secondary_load_max 4
-set g_balance_hagar_secondary_load_hold 0
-set g_balance_hagar_secondary_load_releasedeath 1
-set g_balance_hagar_secondary_load_abort 1
-set g_balance_hagar_secondary_load_linkexplode 0
-set g_balance_hagar_secondary_load_animtime 0.2
-set g_balance_hagar_secondary_damage 37
-set g_balance_hagar_secondary_edgedamage 15
-set g_balance_hagar_secondary_force 100
-set g_balance_hagar_secondary_health 0
-set g_balance_hagar_secondary_damageforcescale 0
-set g_balance_hagar_secondary_radius 65
-set g_balance_hagar_secondary_spread 0.015
-set g_balance_hagar_secondary_speed 1400
-set g_balance_hagar_secondary_lifetime_min 30
-set g_balance_hagar_secondary_lifetime_rand 0
-set g_balance_hagar_secondary_refire 0.15
-set g_balance_hagar_secondary_ammo 1
-set g_balance_hagar_switchdelay_drop 0.15
-set g_balance_hagar_switchdelay_raise 0.15
-set g_balance_hagar_reload_ammo 0 //default: 25
-set g_balance_hagar_reload_time 2
-// }}}
-// {{{ rocketlauncher
-set g_balance_rocketlauncher_damage 105
-set g_balance_rocketlauncher_edgedamage 40
-set g_balance_rocketlauncher_force 600
-set g_balance_rocketlauncher_radius 150
-set g_balance_rocketlauncher_speed 850
-set g_balance_rocketlauncher_speedaccel 0
-set g_balance_rocketlauncher_speedstart 850
-set g_balance_rocketlauncher_lifetime 30
-set g_balance_rocketlauncher_refire 1
-set g_balance_rocketlauncher_animtime 0.3
-set g_balance_rocketlauncher_ammo 3
-set g_balance_rocketlauncher_health 40
-set g_balance_rocketlauncher_damageforcescale 4
-set g_balance_rocketlauncher_detonatedelay 0.2 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
-set g_balance_rocketlauncher_guiderate 90 // max degrees per second
-set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
-set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
-set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in
-set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again
-set g_balance_rocketlauncher_remote_damage 105
-set g_balance_rocketlauncher_remote_edgedamage 40
-set g_balance_rocketlauncher_remote_radius 150
-set g_balance_rocketlauncher_remote_force 600
-set g_balance_rocketlauncher_switchdelay_drop 0.15
-set g_balance_rocketlauncher_switchdelay_raise 0.15
-set g_balance_rocketlauncher_reload_ammo 0 //default: 25
-set g_balance_rocketlauncher_reload_time 2
-// }}}
-// {{{ porto
-set g_balance_porto_primary_refire 1.5
-set g_balance_porto_primary_animtime 0.3
-set g_balance_porto_primary_speed 2000
-set g_balance_porto_primary_lifetime 30
-set g_balance_porto_secondary 0
-set g_balance_porto_secondary_refire 1.5
-set g_balance_porto_secondary_animtime 0.3
-set g_balance_porto_secondary_speed 2000
-set g_balance_porto_secondary_lifetime 30
-set g_balance_porto_switchdelay_drop 0.15
-set g_balance_porto_switchdelay_raise 0.15
-set g_balance_portal_health 200 // these get recharged whenever the portal is used
-set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
-// }}}
-// {{{ hook
-set g_balance_hook_primary_fuel 5 // hook monkeys set 0
-set g_balance_hook_primary_refire 0.2 // hook monkeys set 0
-set g_balance_hook_primary_animtime 0.3 // good shoot anim
-set g_balance_hook_primary_hooked_time_max 0 // infinite
-set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
-set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked
-set g_balance_hook_secondary_damage 25 // not much
-set g_balance_hook_secondary_edgedamage 5 // not much
-set g_balance_hook_secondary_radius 500 // LOTS
-set g_balance_hook_secondary_force -2000 // LOTS
-set g_balance_hook_secondary_ammo 50 // a whole pack
-set g_balance_hook_secondary_lifetime 30 // infinite
-set g_balance_hook_secondary_speed 0 // not much throwing
-set g_balance_hook_secondary_gravity 5 // fast falling
-set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
-set g_balance_hook_secondary_animtime 0.3 // good shoot anim
-set g_balance_hook_secondary_power 3 // effect behaves like a square function
-set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
-set g_balance_hook_secondary_health 0
-set g_balance_hook_secondary_damageforcescale 0
-set g_balance_hook_switchdelay_drop 0.15
-set g_balance_hook_switchdelay_raise 0.15
-// }}}
-// {{{ tuba
-set g_balance_tuba_refire 0.05
-set g_balance_tuba_animtime 0.05
-set g_balance_tuba_attenuation 0.5
-set g_balance_tuba_volume 1
-set g_balance_tuba_fadetime 0.25
-set g_balance_tuba_damage 5
-set g_balance_tuba_edgedamage 0
-set g_balance_tuba_radius 200
-set g_balance_tuba_force 40
-set g_balance_tuba_pitchstep 6
-set g_balance_tuba_switchdelay_drop 0.15
-set g_balance_tuba_switchdelay_raise 0.15
-// }}}
-// {{{ fireball
-set g_balance_fireball_primary_animtime 0.15
-set g_balance_fireball_primary_bfgdamage 100
-set g_balance_fireball_primary_bfgforce 0
-set g_balance_fireball_primary_bfgradius 1000
-set g_balance_fireball_primary_damage 200
-set g_balance_fireball_primary_damageforcescale 4
-set g_balance_fireball_primary_edgedamage 0
-set g_balance_fireball_primary_force 700
-set g_balance_fireball_primary_health 50
-set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 80
-set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 256
-set g_balance_fireball_primary_lifetime 15
-set g_balance_fireball_primary_radius 200
-set g_balance_fireball_primary_refire 5
-set g_balance_fireball_primary_refire2 0
-set g_balance_fireball_primary_speed 650
-set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_animtime 0.3
-set g_balance_fireball_secondary_damage 40
-set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_damagetime 5
-set g_balance_fireball_secondary_force 100
-set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 50
-set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 110
-set g_balance_fireball_secondary_lifetime 7
-set g_balance_fireball_secondary_refire 2
-set g_balance_fireball_secondary_speed 900
-set g_balance_fireball_secondary_speed_up 100
-set g_balance_fireball_secondary_speed_z 0
-set g_balance_fireball_secondary_spread 0
-set g_balance_fireball_switchdelay_drop 0.15
-set g_balance_fireball_switchdelay_raise 0.15
-// }}}
diff --git a/oldbalanceFruitieX.cfg b/oldbalanceFruitieX.cfg
deleted file mode 100644
index d5b6a9a2d..000000000
--- a/oldbalanceFruitieX.cfg
+++ /dev/null
@@ -1,780 +0,0 @@
-g_mod_balance FruitieX
-
-// {{{ starting gear
-set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_balance_health_start 125
-set g_balance_armor_start 0
-set g_start_ammo_shells 20
-set g_start_ammo_nails 0
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_fuel 0
-set g_warmup_start_health 200 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 50 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 150 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 50 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 50 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 200
-set g_lms_start_armor 100
-set g_lms_start_ammo_shells 30
-set g_lms_start_ammo_nails 200
-set g_lms_start_ammo_rockets 150
-set g_lms_start_ammo_cells 150
-set g_lms_start_ammo_fuel 0
-set g_balance_nix_roundtime 25
-set g_balance_nix_incrtime 1.6
-set g_balance_nix_ammo_shells 15
-set g_balance_nix_ammo_nails 45
-set g_balance_nix_ammo_rockets 15
-set g_balance_nix_ammo_cells 15
-set g_balance_nix_ammo_fuel 0
-set g_balance_nix_ammoincr_shells 2
-set g_balance_nix_ammoincr_nails 6
-set g_balance_nix_ammoincr_rockets 2
-set g_balance_nix_ammoincr_cells 2
-set g_balance_nix_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_ammo_anyway 1
-set g_pickup_weapons_anyway 1
-set g_pickup_shells 20
-set g_pickup_shells_weapon 10
-set g_pickup_shells_max 45
-set g_pickup_nails 120
-set g_pickup_nails_weapon 60
-set g_pickup_nails_max 300
-set g_pickup_rockets 25
-set g_pickup_rockets_weapon 15
-set g_pickup_rockets_max 150
-set g_pickup_cells 30
-set g_pickup_cells_weapon 20
-set g_pickup_cells_max 150
-set g_pickup_fuel 25
-set g_pickup_fuel_weapon 15
-set g_pickup_fuel_jetpack 50
-set g_pickup_fuel_max 100
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 150
-set g_pickup_armorsmall_anyway 1
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 50
-set g_pickup_armormedium_anyway 0
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 75; // LOG: to allow a little more armor from medium armor
-set g_pickup_armorbig_anyway 0
-set g_pickup_armorlarge 100
-set g_pickup_armorlarge_max 150
-set g_pickup_armorlarge_anyway 1
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 250
-set g_pickup_healthsmall_anyway 1
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 100
-set g_pickup_healthmedium_anyway 0
-set g_pickup_healthlarge 50
-set g_pickup_healthlarge_max 150
-set g_pickup_healthlarge_anyway 0
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 250
-set g_pickup_healthmega_anyway 1
-set g_pickup_respawntime_short 15
-set g_pickup_respawntime_medium 20
-set g_pickup_respawntime_long 30
-set g_pickup_respawntime_powerup 120
-set g_pickup_respawntime_weapon 10
-set g_pickup_respawntime_superweapon 120
-set g_pickup_respawntime_ammo 25
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 10
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_superweapon 10
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0.05
-set g_balance_health_regenlinear 0
-set g_balance_pause_health_regen 5
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0
-set g_balance_health_rotlinear 1
-set g_balance_pause_health_rot 1
-set g_balance_pause_health_rot_spawn 0
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 999
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0
-set g_balance_armor_rotlinear 1
-set g_balance_pause_armor_rot 1
-set g_balance_pause_armor_rot_spawn 0
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 999
-set g_balance_armor_blockpercent 0.7
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 999
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0.65
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.7
-set g_throughfloor_force 0.8
-set g_projectiles_damage 2
-// possible values:
-// -2: absolutely no damage to projectiles (no exceptions)
-// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
-// 0: only damage from contents (lava/slime) or exceptions
-// 1: only self damage or damage from contents or exceptions
-// 2: allow all damage to projectiles normally
-set g_projectiles_keep_owner 0
-set g_projectiles_newton_style 2
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-set g_projectiles_newton_style_2_minfactor 0.7
-set g_projectiles_newton_style_2_maxfactor 5
-set g_projectiles_spread_style 7
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 150
-set g_balance_falldamage_minspeed 800
-set g_balance_falldamage_factor 0.20
-set g_balance_falldamage_maxdamage 15
-set g_balance_damagepush_speedfactor 2.5
-set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
-set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
-set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
-set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
-set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
-set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.6
-set g_balance_powerup_invincible_time 30
-set g_balance_powerup_strength_damage 3
-set g_balance_powerup_strength_force 4
-set g_balance_powerup_strength_time 30
-set g_balance_powerup_strength_selfdamage 1.5
-set g_balance_powerup_strength_selfforce 1.5
-set g_balance_superweapons_time 30
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1500 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_attenuation 2 "jetpack sound attenuation"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 130
-set g_balance_grapplehook_damagedbycontents 0
-set g_balance_grapplehook_refire 0.2
-// }}}
-
-// {{{ weapon properties
-// {{{ laser
-set g_balance_laser_melee_animtime 0.3
-set g_balance_laser_melee_damage 80
-set g_balance_laser_melee_delay 0.25
-set g_balance_laser_melee_force 200
-set g_balance_laser_melee_multihit 1
-set g_balance_laser_melee_no_doubleslap 1
-set g_balance_laser_melee_nonplayerdamage 40
-set g_balance_laser_melee_range 120
-set g_balance_laser_melee_refire 1.25
-set g_balance_laser_melee_swing_side 120
-set g_balance_laser_melee_swing_up 30
-set g_balance_laser_melee_time 0.15
-set g_balance_laser_melee_traces 10
-
-set g_balance_laser_primary 1 // 0 = shockwave attack, 1 = projectile primary
-set g_balance_laser_primary_damage 20 // dps 33, hope that's not too high
-set g_balance_laser_primary_edgedamage 20
-set g_balance_laser_primary_force 150 // this looks insanely low, but actually isn't with zscale and velocitybias
-set g_balance_laser_primary_radius 60
-set g_balance_laser_primary_speed 5000
-set g_balance_laser_primary_spread 0
-set g_balance_laser_primary_refire 0.6
-set g_balance_laser_primary_animtime 0.4
-set g_balance_laser_primary_lifetime 5
-set g_balance_laser_primary_shotangle 0
-set g_balance_laser_primary_delay 0
-set g_balance_laser_primary_force_zscale 2 // 300 upforce
-set g_balance_laser_primary_force_velocitybias 0.3
-set g_balance_laser_primary_force_other_scale 2.5 // force 375 when pushing others around
-
-set g_balance_laser_secondary 0 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary
-set g_balance_laser_secondary_damage 200 // dps
-set g_balance_laser_secondary_edgedamage 0
-set g_balance_laser_secondary_force 1300
-set g_balance_laser_secondary_radius 60
-set g_balance_laser_secondary_speed 0
-set g_balance_laser_secondary_spread 0
-set g_balance_laser_secondary_refire 0.066
-set g_balance_laser_secondary_animtime 0.066
-set g_balance_laser_secondary_lifetime 0
-set g_balance_laser_secondary_shotangle 0
-set g_balance_laser_secondary_delay 0
-set g_balance_laser_secondary_force_zscale 1.25
-set g_balance_laser_secondary_force_velocitybias 0
-set g_balance_laser_secondary_force_other_scale 0
-
-set g_balance_laser_shockwave_damage 20
-set g_balance_laser_shockwave_distance 2000
-set g_balance_laser_shockwave_edgedamage 0
-set g_balance_laser_shockwave_force 200
-set g_balance_laser_shockwave_force_forwardbias 50
-set g_balance_laser_shockwave_force_zscale 1.5
-set g_balance_laser_shockwave_jump_damage 20
-set g_balance_laser_shockwave_jump_edgedamage 0
-set g_balance_laser_shockwave_jump_force 300
-set g_balance_laser_shockwave_jump_force_velocitybias 0
-set g_balance_laser_shockwave_jump_force_zscale 1.25
-set g_balance_laser_shockwave_jump_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_jump_multiplier_distance 0.5
-set g_balance_laser_shockwave_jump_multiplier_min 0
-set g_balance_laser_shockwave_jump_radius 150
-set g_balance_laser_shockwave_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_multiplier_distance 0.5
-set g_balance_laser_shockwave_multiplier_min 0
-set g_balance_laser_shockwave_splash_damage 15
-set g_balance_laser_shockwave_splash_edgedamage 0
-set g_balance_laser_shockwave_splash_force 100
-set g_balance_laser_shockwave_splash_force_forwardbias 50
-set g_balance_laser_shockwave_splash_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_splash_multiplier_distance 0.5
-set g_balance_laser_shockwave_splash_multiplier_min 0
-set g_balance_laser_shockwave_splash_radius 70
-set g_balance_laser_shockwave_spread_max 100
-set g_balance_laser_shockwave_spread_min 20
-
-set g_balance_laser_switchdelay_drop 0.15
-set g_balance_laser_switchdelay_raise 0.15
-set g_balance_laser_reload_ammo 0 //default: 6
-set g_balance_laser_reload_time 2
-// }}}
-// {{{ shotgun
-set g_balance_shotgun_primary_bullets 18
-set g_balance_shotgun_primary_damage 3.5 // LOG: changed from 4 to 3.5, total damage 63
-set g_balance_shotgun_primary_force 20
-set g_balance_shotgun_primary_spread 0.16 // LOG: changed from 0.18 -> 0.16 to compensate a little for lower damage
-set g_balance_shotgun_primary_refire 1
-set g_balance_shotgun_primary_animtime 0.3
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_solidpenetration 3.8
-set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
-set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing_side 120
-set g_balance_shotgun_secondary_melee_swing_up 30
-set g_balance_shotgun_secondary_melee_time 0.15
-set g_balance_shotgun_secondary_melee_traces 10
-set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_melee_nonplayerdamage 0
-set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_damage 110
-set g_balance_shotgun_secondary_force 150
-set g_balance_shotgun_secondary_refire 1.1
-set g_balance_shotgun_secondary_animtime 1
-set g_balance_shotgun_switchdelay_drop 0.15
-set g_balance_shotgun_switchdelay_raise 0.15
-set g_balance_shotgun_reload_ammo 0 //default: 5
-set g_balance_shotgun_reload_time 2
-// }}}
-// {{{ uzi
-set g_balance_uzi_mode 1 				// Activates varible spread for sustained & burst mode secondary
-set g_balance_uzi_spread_min 0.02
-set g_balance_uzi_spread_max 0.3 // LOG: 0.6 -> 0.3
-set g_balance_uzi_spread_add 0.008
-
-set g_balance_uzi_burst 3				// # of bullets in a burst (if set to 2 or more)
-set g_balance_uzi_burst_animtime 0.45
-set g_balance_uzi_burst_refire 0.05		// refire between burst bullets
-set g_balance_uzi_burst_refire2 0.45 	// refire after burst
-set g_balance_uzi_burst_spread 0.07
-set g_balance_uzi_burst_damage 25
-set g_balance_uzi_burst_force 50
-set g_balance_uzi_burst_ammo 3
-
-set g_balance_uzi_first 1
-set g_balance_uzi_first_damage 15 / f/ LOG: 22 -> 15
-set g_balance_uzi_first_force 50
-set g_balance_uzi_first_spread 0.03
-set g_balance_uzi_first_refire 0.2
-set g_balance_uzi_first_ammo 2
-
-set g_balance_uzi_sustained_damage 12   // 120 dps
-set g_balance_uzi_sustained_force 12
-set g_balance_uzi_sustained_spread 0.06
-set g_balance_uzi_sustained_refire 0.1
-set g_balance_uzi_sustained_ammo 1
-
-set g_balance_uzi_solidpenetration 13.1
-
-set g_balance_uzi_switchdelay_drop 0.15
-set g_balance_uzi_switchdelay_raise 0.15
-
-set g_balance_uzi_reload_ammo 0 //default: 30
-set g_balance_uzi_reload_time 2
-// }}}
-// {{{ mortar
-set g_balance_grenadelauncher_primary_type 0
-set g_balance_grenadelauncher_primary_damage 44
-set g_balance_grenadelauncher_primary_edgedamage 32
-set g_balance_grenadelauncher_primary_force 300
-set g_balance_grenadelauncher_primary_radius 115
-set g_balance_grenadelauncher_primary_speed 1500
-set g_balance_grenadelauncher_primary_speed_up 225
-set g_balance_grenadelauncher_primary_speed_z 0
-set g_balance_grenadelauncher_primary_spread 0
-set g_balance_grenadelauncher_primary_lifetime 5
-set g_balance_grenadelauncher_primary_lifetime2 0.65
-set g_balance_grenadelauncher_primary_refire 0.8
-set g_balance_grenadelauncher_primary_animtime 0.3
-set g_balance_grenadelauncher_primary_ammo 2
-set g_balance_grenadelauncher_primary_health 80
-set g_balance_grenadelauncher_primary_damageforcescale 0
-set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
-
-set g_balance_grenadelauncher_secondary_type 1
-set g_balance_grenadelauncher_secondary_damage 62
-set g_balance_grenadelauncher_secondary_edgedamage 32
-set g_balance_grenadelauncher_secondary_force 300
-set g_balance_grenadelauncher_secondary_radius 150
-set g_balance_grenadelauncher_secondary_speed 1000
-set g_balance_grenadelauncher_secondary_speed_up 250
-set g_balance_grenadelauncher_secondary_speed_z 0
-set g_balance_grenadelauncher_secondary_spread 0
-set g_balance_grenadelauncher_secondary_lifetime 3
-set g_balance_grenadelauncher_secondary_lifetime_bounce 0
-set g_balance_grenadelauncher_secondary_lifetime_stick 0.65
-set g_balance_grenadelauncher_secondary_refire 0.8
-set g_balance_grenadelauncher_secondary_animtime 0.3
-set g_balance_grenadelauncher_secondary_ammo 2
-set g_balance_grenadelauncher_secondary_health 40
-set g_balance_grenadelauncher_secondary_damageforcescale 0
-set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
-
-set g_balance_grenadelauncher_bouncefactor 0.5
-set g_balance_grenadelauncher_bouncestop 0.12
-
-set g_balance_grenadelauncher_switchdelay_drop 0.15
-set g_balance_grenadelauncher_switchdelay_raise 0.15
-
-set g_balance_grenadelauncher_reload_ammo 0 //default: 12
-set g_balance_grenadelauncher_reload_time 2
-// }}}
-// {{{ electro
-set g_balance_electro_lightning 1
-set g_balance_electro_primary_damage 100
-set g_balance_electro_primary_edgedamage 0
-set g_balance_electro_primary_force 425
-set g_balance_electro_primary_force_up 125
-set g_balance_electro_primary_radius 850
-set g_balance_electro_primary_comboradius 150
-set g_balance_electro_primary_speed 0
-set g_balance_electro_primary_spread 0
-set g_balance_electro_primary_lifetime 0
-set g_balance_electro_primary_refire 0.4
-set g_balance_electro_primary_animtime 0.2
-set g_balance_electro_primary_ammo 5
-set g_balance_electro_primary_range 800
-set g_balance_electro_primary_falloff_mindist 0
-set g_balance_electro_primary_falloff_maxdist 0
-set g_balance_electro_primary_falloff_halflifedist 0
-set g_balance_electro_secondary_damage 25
-set g_balance_electro_secondary_edgedamage 0
-set g_balance_electro_secondary_force 100
-set g_balance_electro_secondary_radius 100
-set g_balance_electro_secondary_speed 700
-set g_balance_electro_secondary_speed_up 200
-set g_balance_electro_secondary_speed_z 0
-set g_balance_electro_secondary_spread 0.08
-set g_balance_electro_secondary_lifetime 3.5
-set g_balance_electro_secondary_refire 0.2
-set g_balance_electro_secondary_refire2 2
-set g_balance_electro_secondary_animtime 0.2
-set g_balance_electro_secondary_ammo 2
-set g_balance_electro_secondary_health 10
-set g_balance_electro_secondary_damageforcescale 4
-set g_balance_electro_secondary_damagedbycontents 0
-set g_balance_electro_secondary_count 3
-set g_balance_electro_secondary_bouncefactor 0.5
-set g_balance_electro_secondary_bouncestop 0.075
-set g_balance_electro_combo_damage 50
-set g_balance_electro_combo_edgedamage 0
-set g_balance_electro_combo_force 80
-set g_balance_electro_combo_radius 250
-set g_balance_electro_combo_comboradius 0
-set g_balance_electro_combo_speed 400
-set g_balance_electro_combo_safeammocheck 1
-set g_balance_electro_switchdelay_drop 0.15
-set g_balance_electro_switchdelay_raise 0.15
-set g_balance_electro_reload_ammo 0 //default: 20
-set g_balance_electro_reload_time 2
-// }}}
-// {{{ lightning
-set g_balance_lightning_primary_ammo 5
-set g_balance_lightning_primary_animtime 0.2
-set g_balance_lightning_primary_damage 100
-set g_balance_lightning_primary_edgedamage 0
-set g_balance_lightning_primary_falloff_mindist 0
-set g_balance_lightning_primary_falloff_maxdist 0
-set g_balance_lightning_primary_falloff_halflifedist 0
-set g_balance_lightning_primary_force 425
-set g_balance_lightning_primary_lifetime 0
-set g_balance_lightning_primary_radius 850
-set g_balance_lightning_primary_range 800
-set g_balance_lightning_primary_refire 0.4
-set g_balance_lightning_primary_speed 0
-set g_balance_lightning_primary_spread 0
-set g_balance_lightning_secondary_ammo 5
-set g_balance_lightning_secondary_animtime 0.5
-set g_balance_lightning_secondary_damage 100
-set g_balance_lightning_secondary_damageforcescale 4
-set g_balance_lightning_secondary_edgedamage 80
-set g_balance_lightning_secondary_flyingdamage 1
-set g_balance_lightning_secondary_flyingforce -80
-set g_balance_lightning_secondary_flyingradius 200
-set g_balance_lightning_secondary_force -200
-set g_balance_lightning_secondary_health 1
-set g_balance_lightning_secondary_lifetime 30
-set g_balance_lightning_secondary_radius 300
-set g_balance_lightning_secondary_refire 5
-set g_balance_lightning_secondary_speed 600
-// }}}
-// {{{ crylink
-set g_balance_crylink_primary_damage 7 // LOG: 10 -> 7
-set g_balance_crylink_primary_edgedamage 4 // LOG: 6 -> 4
-set g_balance_crylink_primary_force 35
-set g_balance_crylink_primary_radius 80
-set g_balance_crylink_primary_speed 1500
-set g_balance_crylink_primary_spread 0.05
-set g_balance_crylink_primary_shots 7
-set g_balance_crylink_primary_bounces 2
-set g_balance_crylink_primary_refire 0.8
-set g_balance_crylink_primary_animtime 0.3
-set g_balance_crylink_primary_ammo 2
-set g_balance_crylink_primary_bouncedamagefactor 0.2
-set g_balance_crylink_primary_joindelay 0
-set g_balance_crylink_primary_joinspread 0.2
-set g_balance_crylink_primary_joinexplode 0
-set g_balance_crylink_primary_joinexplode_damage 0
-set g_balance_crylink_primary_joinexplode_edgedamage 0
-set g_balance_crylink_primary_joinexplode_radius 0
-set g_balance_crylink_primary_joinexplode_force 0
-set g_balance_crylink_primary_linkexplode 1
-
-set g_balance_crylink_primary_middle_lifetime 5 // range: 10000 full, fades to 20000
-set g_balance_crylink_primary_middle_fadetime 5
-set g_balance_crylink_primary_other_lifetime 2 // range: 800 full, fades to 1300
-set g_balance_crylink_primary_other_fadetime 0.25
-
-set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_damage 5 // LOG: 8 -> 5
-set g_balance_crylink_secondary_edgedamage 3
-set g_balance_crylink_secondary_force 16 // LOG: 20 -> 16
-set g_balance_crylink_secondary_radius 15 // LOG: 20 -> 15
-set g_balance_crylink_secondary_speed 1250 // LOG: 1500 -> 1250
-set g_balance_crylink_secondary_spread 0.1
-set g_balance_crylink_secondary_spreadtype 0
-set g_balance_crylink_secondary_shots 6
-set g_balance_crylink_secondary_bounces 2
-set g_balance_crylink_secondary_refire 0.9 // LOG: 0.8 -> 0.9
-set g_balance_crylink_secondary_animtime 0.3
-set g_balance_crylink_secondary_ammo 3 // LOG: 2 -> 3
-set g_balance_crylink_secondary_bouncedamagefactor 0.4 // LOG: 0.2 -> 0.4
-set g_balance_crylink_secondary_joindelay 0
-set g_balance_crylink_secondary_joinspread 0.2
-set g_balance_crylink_secondary_joinexplode 0
-set g_balance_crylink_secondary_joinexplode_damage 0
-set g_balance_crylink_secondary_joinexplode_edgedamage 0
-set g_balance_crylink_secondary_joinexplode_radius 0
-set g_balance_crylink_secondary_joinexplode_force 0
-set g_balance_crylink_secondary_linkexplode 0
-
-set g_balance_crylink_secondary_middle_lifetime 5 // range: 10000 full, fades to 10000
-set g_balance_crylink_secondary_middle_fadetime 5
-set g_balance_crylink_secondary_line_lifetime 2 // range: 4000 full, fades to 8000
-set g_balance_crylink_secondary_line_fadetime 0.25
-
-set g_balance_crylink_switchdelay_drop 0.15
-set g_balance_crylink_switchdelay_raise 0.15
-
-set g_balance_crylink_reload_ammo 0 //default: 10
-set g_balance_crylink_reload_time 2
-// }}}
-// {{{ nex
-set g_balance_nex_primary_damage 90
-set g_balance_nex_primary_force 500
-set g_balance_nex_primary_refire 1
-set g_balance_nex_primary_animtime 0.3
-set g_balance_nex_primary_ammo 5
-set g_balance_nex_primary_damagefalloff_mindist 0
-set g_balance_nex_primary_damagefalloff_maxdist 0
-set g_balance_nex_primary_damagefalloff_halflife 0
-set g_balance_nex_primary_damagefalloff_forcehalflife 0
-
-set g_balance_nex_secondary 0 // LOG: disable secondary
-set g_balance_nex_secondary_charge 0 // LOG: disable secondary charge
-set g_balance_nex_secondary_charge_rate 0.4
-set g_balance_nex_secondary_chargepool 1
-set g_balance_nex_secondary_chargepool_regen 0.25
-set g_balance_nex_secondary_chargepool_pause_regen 2
-set g_balance_nex_secondary_chargepool_pause_health_regen 0.5
-set g_balance_nex_secondary_damage 0
-set g_balance_nex_secondary_force 0
-set g_balance_nex_secondary_refire 0
-set g_balance_nex_secondary_animtime 0
-set g_balance_nex_secondary_ammo 0.4 // full charge pool is 1, so it depletes in 2.5 secs
-set g_balance_nex_secondary_damagefalloff_mindist 0
-set g_balance_nex_secondary_damagefalloff_maxdist 0
-set g_balance_nex_secondary_damagefalloff_halflife 0
-set g_balance_nex_secondary_damagefalloff_forcehalflife 0
-
-set g_balance_nex_charge 1
-set g_balance_nex_charge_mindmg 20
-set g_balance_nex_charge_start 0.5
-set g_balance_nex_charge_rate 0.5
-set g_balance_nex_charge_animlimit 0.5
-set g_balance_nex_charge_limit 1 // LOG: 0.5 -> 1 - allow to fully charge automaticaly
-set g_balance_nex_charge_rot_rate 0 // LOG: 0.1 -> 0 - disable rot
-set g_balance_nex_charge_rot_pause 0.5 // Dont rot down until this long after release of charge button
-set g_balance_nex_charge_shot_multiplier 0
-set g_balance_nex_charge_velocity_rate 0
-set g_balance_nex_charge_minspeed 600
-set g_balance_nex_charge_maxspeed 1000
-
-set g_balance_nex_switchdelay_drop 0.15
-set g_balance_nex_switchdelay_raise 0.15
-
-set g_balance_nex_reload_ammo 0 //default: 25
-set g_balance_nex_reload_time 2
-// }}}
-// {{{ minstanex
-set g_balance_minstanex_refire 1
-set g_balance_minstanex_animtime 0.50
-set g_balance_minstanex_ammo 10
-set g_balance_minstanex_laser_ammo 0
-set g_balance_minstanex_laser_animtime 0.3
-set g_balance_minstanex_laser_refire 0.6
-set g_balance_minstanex_switchdelay_drop 0.15
-set g_balance_minstanex_switchdelay_raise 0.15
-set g_balance_minstanex_reload_ammo 0 //default: 50
-set g_balance_minstanex_reload_time 2
-// }}}
-// {{{ hagar
-set g_balance_hagar_primary_damage 14
-set g_balance_hagar_primary_edgedamage 6
-set g_balance_hagar_primary_force 70
-set g_balance_hagar_primary_health 0
-set g_balance_hagar_primary_damageforcescale 0
-set g_balance_hagar_primary_radius 110
-set g_balance_hagar_primary_spread 0.1
-set g_balance_hagar_primary_speed 1800
-set g_balance_hagar_primary_lifetime 5
-set g_balance_hagar_primary_refire 0.12
-set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_secondary 1
-set g_balance_hagar_secondary_load 0
-set g_balance_hagar_secondary_load_speed 0.6
-set g_balance_hagar_secondary_load_spread 0.075
-set g_balance_hagar_secondary_load_spread_bias 0.5
-set g_balance_hagar_secondary_load_max 4
-set g_balance_hagar_secondary_load_hold 0
-set g_balance_hagar_secondary_load_releasedeath 1
-set g_balance_hagar_secondary_load_abort 1
-set g_balance_hagar_secondary_load_linkexplode 0
-set g_balance_hagar_secondary_load_animtime 0.2
-set g_balance_hagar_secondary_damage 14 // default for _load: 32
-set g_balance_hagar_secondary_edgedamage 6 // default for _load: 10
-set g_balance_hagar_secondary_force 70 // default for _load: 160
-set g_balance_hagar_secondary_health 0
-set g_balance_hagar_secondary_damageforcescale 0
-set g_balance_hagar_secondary_radius 125
-set g_balance_hagar_secondary_spread 0.15 // default for _load: 0.08
-set g_balance_hagar_secondary_speed 1800
-set g_balance_hagar_secondary_lifetime_min 5
-set g_balance_hagar_secondary_lifetime_rand 0
-set g_balance_hagar_secondary_refire 0.12 // default for _load: 0.8
-set g_balance_hagar_secondary_ammo 1
-set g_balance_hagar_switchdelay_drop 0.15
-set g_balance_hagar_switchdelay_raise 0.15
-set g_balance_hagar_reload_ammo 0 //default: 25
-set g_balance_hagar_reload_time 2
-// }}}
-// {{{ rocketlauncher
-set g_balance_rocketlauncher_damage 82
-set g_balance_rocketlauncher_edgedamage 32
-set g_balance_rocketlauncher_force 350
-set g_balance_rocketlauncher_radius 130
-set g_balance_rocketlauncher_speed 1400
-set g_balance_rocketlauncher_speedaccel 1400
-set g_balance_rocketlauncher_speedstart 800
-set g_balance_rocketlauncher_lifetime 5
-set g_balance_rocketlauncher_refire 1
-set g_balance_rocketlauncher_animtime 0.3
-set g_balance_rocketlauncher_ammo 3
-set g_balance_rocketlauncher_health 0
-set g_balance_rocketlauncher_damageforcescale 0
-set g_balance_rocketlauncher_detonatedelay 0.05 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
-set g_balance_rocketlauncher_guiderate 42 // max degrees per second
-set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
-set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
-set g_balance_rocketlauncher_guidedelay 0.15 // delay before guiding kicks in
-set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again
-set g_balance_rocketlauncher_remote_damage 60
-set g_balance_rocketlauncher_remote_edgedamage 20
-set g_balance_rocketlauncher_remote_radius 120
-set g_balance_rocketlauncher_remote_force 350
-set g_balance_rocketlauncher_switchdelay_drop 0.15
-set g_balance_rocketlauncher_switchdelay_raise 0.15
-set g_balance_rocketlauncher_reload_ammo 0 //default: 25
-set g_balance_rocketlauncher_reload_time 2
-// }}}
-// {{{ porto
-set g_balance_porto_primary_refire 1.5
-set g_balance_porto_primary_animtime 0.2
-set g_balance_porto_primary_speed 2000
-set g_balance_porto_primary_lifetime 5
-set g_balance_porto_secondary 0
-set g_balance_porto_secondary_refire 1.5
-set g_balance_porto_secondary_animtime 0.2
-set g_balance_porto_secondary_speed 2000
-set g_balance_porto_secondary_lifetime 5
-set g_balance_porto_switchdelay_drop 0.15
-set g_balance_porto_switchdelay_raise 0.15
-set g_balance_portal_health 200 // these get recharged whenever the portal is used
-set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
-// }}}
-// {{{ hook
-set g_balance_hook_primary_fuel 5 // hook monkeys set 0
-set g_balance_hook_primary_refire 0.2 // hook monkeys set 0
-set g_balance_hook_primary_animtime 0.2 // good shoot anim
-set g_balance_hook_primary_hooked_time_max 0 // infinite
-set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
-set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked
-set g_balance_hook_secondary_damage 25 // not much
-set g_balance_hook_secondary_edgedamage 5 // not much
-set g_balance_hook_secondary_radius 500 // LOTS
-set g_balance_hook_secondary_force -2000 // LOTS
-set g_balance_hook_secondary_ammo 50 // a whole pack
-set g_balance_hook_secondary_lifetime 5 // infinite
-set g_balance_hook_secondary_speed 0 // not much throwing
-set g_balance_hook_secondary_gravity 5 // fast falling
-set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
-set g_balance_hook_secondary_animtime 0.2 // good shoot anim
-set g_balance_hook_secondary_power 3 // effect behaves like a square function
-set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
-set g_balance_hook_secondary_health 0
-set g_balance_hook_secondary_damageforcescale 0
-set g_balance_hook_switchdelay_drop 0.15
-set g_balance_hook_switchdelay_raise 0.15
-// }}}
-// {{{ tuba
-set g_balance_tuba_refire 0.05
-set g_balance_tuba_animtime 0.05
-set g_balance_tuba_attenuation 0.5
-set g_balance_tuba_volume 1
-set g_balance_tuba_fadetime 0.25
-set g_balance_tuba_damage 5
-set g_balance_tuba_edgedamage 0
-set g_balance_tuba_radius 200
-set g_balance_tuba_force 40
-set g_balance_tuba_pitchstep 6
-set g_balance_tuba_switchdelay_drop 0.15
-set g_balance_tuba_switchdelay_raise 0.15
-// }}}
-// {{{ fireball
-set g_balance_fireball_primary_animtime 0.2
-set g_balance_fireball_primary_bfgdamage 100
-set g_balance_fireball_primary_bfgforce 0
-set g_balance_fireball_primary_bfgradius 1000
-set g_balance_fireball_primary_damage 200
-set g_balance_fireball_primary_damageforcescale 4
-set g_balance_fireball_primary_edgedamage 0
-set g_balance_fireball_primary_force 700
-set g_balance_fireball_primary_health 50
-set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 80
-set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 256
-set g_balance_fireball_primary_lifetime 15
-set g_balance_fireball_primary_radius 200
-set g_balance_fireball_primary_refire 5
-set g_balance_fireball_primary_refire2 0
-set g_balance_fireball_primary_speed 650
-set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_animtime 0.2
-set g_balance_fireball_secondary_damage 40
-set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_damagetime 5
-set g_balance_fireball_secondary_force 100
-set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 50
-set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 110
-set g_balance_fireball_secondary_lifetime 7
-set g_balance_fireball_secondary_refire 2
-set g_balance_fireball_secondary_speed 900
-set g_balance_fireball_secondary_speed_up 100
-set g_balance_fireball_secondary_speed_z 0
-set g_balance_fireball_secondary_spread 0
-set g_balance_fireball_switchdelay_drop 0.15
-set g_balance_fireball_switchdelay_raise 0.15
-// }}}
diff --git a/oldbalanceXDF.cfg b/oldbalanceXDF.cfg
deleted file mode 100644
index cbc380bfa..000000000
--- a/oldbalanceXDF.cfg
+++ /dev/null
@@ -1,750 +0,0 @@
-g_mod_balance XDF
-
-// {{{ starting gear
-set g_start_weapon_laser 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_shotgun 0 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_uzi 1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default" // UNTIL IT CAN BE REMOVED FROM CODE
-set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default"
-set g_balance_health_start 100
-set g_balance_armor_start 0
-set g_start_ammo_shells 15
-set g_start_ammo_nails 0
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_fuel 0
-set g_warmup_start_health 100 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 200
-set g_lms_start_armor 200
-set g_lms_start_ammo_shells 60
-set g_lms_start_ammo_nails 320
-set g_lms_start_ammo_rockets 160
-set g_lms_start_ammo_cells 180
-set g_lms_start_ammo_fuel 0
-set g_balance_nix_roundtime 25
-set g_balance_nix_incrtime 1.6
-set g_balance_nix_ammo_shells 60
-set g_balance_nix_ammo_nails 320
-set g_balance_nix_ammo_rockets 160
-set g_balance_nix_ammo_cells 180
-set g_balance_nix_ammo_fuel 0
-set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
-set g_balance_nix_ammoincr_nails 6
-set g_balance_nix_ammoincr_rockets 2
-set g_balance_nix_ammoincr_cells 2
-set g_balance_nix_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_ammo_anyway 1
-set g_pickup_weapons_anyway 1
-set g_pickup_shells 15
-set g_pickup_shells_weapon 15
-set g_pickup_shells_max 60
-set g_pickup_nails 80
-set g_pickup_nails_weapon 80
-set g_pickup_nails_max 320
-set g_pickup_rockets 40
-set g_pickup_rockets_weapon 40
-set g_pickup_rockets_max 160
-set g_pickup_cells 30
-set g_pickup_cells_weapon 30
-set g_pickup_cells_max 180
-set g_pickup_fuel 50
-set g_pickup_fuel_weapon 50
-set g_pickup_fuel_jetpack 100
-set g_pickup_fuel_max 100
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 200
-set g_pickup_armorsmall_anyway 1
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 200
-set g_pickup_armormedium_anyway 1
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 200
-set g_pickup_armorbig_anyway 1
-set g_pickup_armorlarge 100
-set g_pickup_armorlarge_max 200
-set g_pickup_armorlarge_anyway 1
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 200
-set g_pickup_healthsmall_anyway 1
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 200
-set g_pickup_healthmedium_anyway 1
-set g_pickup_healthlarge 50
-set g_pickup_healthlarge_max 200
-set g_pickup_healthlarge_anyway 1
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 200
-set g_pickup_healthmega_anyway 1
-set g_pickup_respawntime_short 0.1
-set g_pickup_respawntime_medium 0.1
-set g_pickup_respawntime_long 0.1
-set g_pickup_respawntime_powerup 0.1
-set g_pickup_respawntime_weapon 0.1
-set g_pickup_respawntime_superweapon 0.1
-set g_pickup_respawntime_ammo 0.1
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 30
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_superweapon 10
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0.08
-set g_balance_health_regenlinear 0.5
-set g_balance_pause_health_regen 5
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0.04
-set g_balance_health_rotlinear 0.75
-set g_balance_pause_health_rot 1
-set g_balance_pause_health_rot_spawn 5
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 999
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0.04
-set g_balance_armor_rotlinear 0.75
-set g_balance_pause_armor_rot 1
-set g_balance_pause_armor_rot_spawn 5
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 999
-set g_balance_armor_blockpercent 0.6
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 999
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.4
-set g_throughfloor_force 0.7
-set g_projectiles_damage 2
-// possible values:
-// -2: absolutely no damage to projectiles (no exceptions)
-// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
-// 0: only damage from contents (lava/slime) or exceptions
-// 1: only self damage or damage from contents or exceptions
-// 2: allow all damage to projectiles normally
-set g_projectiles_keep_owner 0
-set g_projectiles_newton_style 2
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-set g_projectiles_newton_style_2_minfactor 0.8
-set g_projectiles_newton_style_2_maxfactor 1.5
-set g_projectiles_spread_style 7
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 250
-set g_balance_falldamage_minspeed 900
-set g_balance_falldamage_factor 0.20
-set g_balance_falldamage_maxdamage 40
-set g_balance_damagepush_speedfactor 2.5
-set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
-set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
-set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
-set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
-set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
-set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken
-set g_balance_powerup_invincible_time 999
-set g_balance_powerup_strength_damage 3
-set g_balance_powerup_strength_force 3
-set g_balance_powerup_strength_time 999
-set g_balance_powerup_strength_selfdamage 1.5
-set g_balance_powerup_strength_selfforce 1.5
-set g_balance_superweapons_time 30
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_attenuation 2 "jetpack sound attenuation"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 130
-set g_balance_grapplehook_damagedbycontents 0
-set g_balance_grapplehook_refire 0.2
-// }}}
-
-// {{{ weapon properties
-// {{{ laser
-set g_balance_laser_melee_animtime 0.3
-set g_balance_laser_melee_damage 80
-set g_balance_laser_melee_delay 0.25
-set g_balance_laser_melee_force 200
-set g_balance_laser_melee_multihit 1
-set g_balance_laser_melee_no_doubleslap 1
-set g_balance_laser_melee_nonplayerdamage 40
-set g_balance_laser_melee_range 120
-set g_balance_laser_melee_refire 1.25
-set g_balance_laser_melee_swing_side 120
-set g_balance_laser_melee_swing_up 30
-set g_balance_laser_melee_time 0.15
-set g_balance_laser_melee_traces 10
-
-set g_balance_laser_primary 1 // 0 = shockwave attack, 1 = projectile primary
-set g_balance_laser_primary_damage 25
-set g_balance_laser_primary_edgedamage 12.5
-set g_balance_laser_primary_force 250
-set g_balance_laser_primary_radius 70
-set g_balance_laser_primary_speed 6000
-set g_balance_laser_primary_spread 0
-set g_balance_laser_primary_refire 0.7
-set g_balance_laser_primary_animtime 0.3
-set g_balance_laser_primary_lifetime 5
-set g_balance_laser_primary_shotangle 0
-set g_balance_laser_primary_delay 0
-set g_balance_laser_primary_force_zscale 1.5
-set g_balance_laser_primary_force_velocitybias 0
-set g_balance_laser_primary_force_other_scale 1
-
-set g_balance_laser_secondary 0 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary
-set g_balance_laser_secondary_damage 25
-set g_balance_laser_secondary_edgedamage 12.5
-set g_balance_laser_secondary_force 400
-set g_balance_laser_secondary_radius 70
-set g_balance_laser_secondary_speed 12000
-set g_balance_laser_secondary_spread 0
-set g_balance_laser_secondary_refire 0.7
-set g_balance_laser_secondary_animtime 0.2
-set g_balance_laser_secondary_lifetime 5
-set g_balance_laser_secondary_shotangle -90
-set g_balance_laser_secondary_delay 0
-set g_balance_laser_secondary_force_zscale 1.25
-set g_balance_laser_secondary_force_velocitybias 0
-set g_balance_laser_secondary_force_other_scale 1
-
-set g_balance_laser_shockwave_damage 20
-set g_balance_laser_shockwave_distance 2000
-set g_balance_laser_shockwave_edgedamage 0
-set g_balance_laser_shockwave_force 200
-set g_balance_laser_shockwave_force_forwardbias 50
-set g_balance_laser_shockwave_force_zscale 2
-set g_balance_laser_shockwave_jump_damage 20
-set g_balance_laser_shockwave_jump_edgedamage 0
-set g_balance_laser_shockwave_jump_force 300
-set g_balance_laser_shockwave_jump_force_velocitybias 0
-set g_balance_laser_shockwave_jump_force_zscale 1.25
-set g_balance_laser_shockwave_jump_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_jump_multiplier_distance 0.5
-set g_balance_laser_shockwave_jump_multiplier_min 0
-set g_balance_laser_shockwave_jump_radius 150
-set g_balance_laser_shockwave_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_multiplier_distance 0.5
-set g_balance_laser_shockwave_multiplier_min 0
-set g_balance_laser_shockwave_splash_damage 15
-set g_balance_laser_shockwave_splash_edgedamage 0
-set g_balance_laser_shockwave_splash_force 100
-set g_balance_laser_shockwave_splash_force_forwardbias 50
-set g_balance_laser_shockwave_splash_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_splash_multiplier_distance 0.5
-set g_balance_laser_shockwave_splash_multiplier_min 0
-set g_balance_laser_shockwave_splash_radius 70
-set g_balance_laser_shockwave_spread_max 120
-set g_balance_laser_shockwave_spread_min 25
-
-set g_balance_laser_switchdelay_drop 0
-set g_balance_laser_switchdelay_raise 0
-set g_balance_laser_reload_ammo 0 //default: 6
-set g_balance_laser_reload_time 2
-// }}}
-// {{{ shotgun
-set g_balance_shotgun_primary_bullets 14
-set g_balance_shotgun_primary_damage 4
-set g_balance_shotgun_primary_force 15
-set g_balance_shotgun_primary_spread 0.12
-set g_balance_shotgun_primary_refire 0.75
-set g_balance_shotgun_primary_animtime 0.2
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_solidpenetration 3.8
-set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
-set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing_side 120
-set g_balance_shotgun_secondary_melee_swing_up 30
-set g_balance_shotgun_secondary_melee_time 0.15
-set g_balance_shotgun_secondary_melee_traces 10
-set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_melee_nonplayerdamage 40
-set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_damage 80
-set g_balance_shotgun_secondary_force 200
-set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_secondary_animtime 1
-set g_balance_shotgun_switchdelay_drop 0
-set g_balance_shotgun_switchdelay_raise 0
-set g_balance_shotgun_reload_ammo 0 //default: 5
-set g_balance_shotgun_reload_time 2
-// }}}
-// {{{ uzi
-set g_balance_uzi_mode 1 				// Activates varible spread for sustained & burst mode secondary
-set g_balance_uzi_spread_min 0
-set g_balance_uzi_spread_max 0
-set g_balance_uzi_spread_add 0
-
-set g_balance_uzi_burst 3				// # of bullets in a burst (if set to 2 or more)
-set g_balance_uzi_burst_animtime 0.3
-set g_balance_uzi_burst_refire 0.06		// refire between burst bullets
-set g_balance_uzi_burst_refire2 0.45	// refire after burst
-set g_balance_uzi_burst_spread 0.03
-set g_balance_uzi_burst_damage 25
-set g_balance_uzi_burst_force 20
-set g_balance_uzi_burst_ammo 3
-
-set g_balance_uzi_first 1
-set g_balance_uzi_first_damage 14
-set g_balance_uzi_first_force 5
-set g_balance_uzi_first_spread 0.03
-set g_balance_uzi_first_refire 0.4
-set g_balance_uzi_first_ammo 1
-
-set g_balance_uzi_sustained_damage 12
-set g_balance_uzi_sustained_force 5
-set g_balance_uzi_sustained_spread 0
-set g_balance_uzi_sustained_refire 0.1
-set g_balance_uzi_sustained_ammo 1
-
-set g_balance_uzi_solidpenetration 13.1
-
-set g_balance_uzi_switchdelay_drop 0
-set g_balance_uzi_switchdelay_raise 0
-
-set g_balance_uzi_reload_ammo 0 //default: 30
-set g_balance_uzi_reload_time 2
-// }}}
-// {{{ mortar
-set g_balance_grenadelauncher_primary_type 0
-set g_balance_grenadelauncher_primary_damage 50
-set g_balance_grenadelauncher_primary_edgedamage 25
-set g_balance_grenadelauncher_primary_force 250
-set g_balance_grenadelauncher_primary_radius 100
-set g_balance_grenadelauncher_primary_speed 2000
-set g_balance_grenadelauncher_primary_speed_up 200
-set g_balance_grenadelauncher_primary_speed_z 0
-set g_balance_grenadelauncher_primary_spread 0
-set g_balance_grenadelauncher_primary_lifetime 5
-set g_balance_grenadelauncher_primary_lifetime2 1
-set g_balance_grenadelauncher_primary_refire 0.7
-set g_balance_grenadelauncher_primary_animtime 0.3
-set g_balance_grenadelauncher_primary_ammo 2
-set g_balance_grenadelauncher_primary_health 0
-set g_balance_grenadelauncher_primary_damageforcescale 0
-set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
-
-set g_balance_grenadelauncher_secondary_type 1
-set g_balance_grenadelauncher_secondary_damage 60
-set g_balance_grenadelauncher_secondary_edgedamage 30
-set g_balance_grenadelauncher_secondary_force 300
-set g_balance_grenadelauncher_secondary_radius 200
-set g_balance_grenadelauncher_secondary_speed 800
-set g_balance_grenadelauncher_secondary_speed_up 0
-set g_balance_grenadelauncher_secondary_speed_z 200
-set g_balance_grenadelauncher_secondary_spread 0
-set g_balance_grenadelauncher_secondary_lifetime 8
-set g_balance_grenadelauncher_secondary_lifetime_bounce 0.5
-set g_balance_grenadelauncher_secondary_lifetime_stick 0
-set g_balance_grenadelauncher_secondary_refire 0.7
-set g_balance_grenadelauncher_secondary_animtime 0.5
-set g_balance_grenadelauncher_secondary_ammo 2
-set g_balance_grenadelauncher_secondary_health 0
-set g_balance_grenadelauncher_secondary_damageforcescale 0
-set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
-
-set g_balance_grenadelauncher_bouncefactor 0.5
-set g_balance_grenadelauncher_bouncestop 0.075
-
-set g_balance_grenadelauncher_switchdelay_drop 0
-set g_balance_grenadelauncher_switchdelay_raise 0
-
-set g_balance_grenadelauncher_reload_ammo 0 //default: 12
-set g_balance_grenadelauncher_reload_time 2
-// }}}
-// {{{ electro
-set g_balance_electro_lightning 0
-set g_balance_electro_primary_damage 55
-set g_balance_electro_primary_edgedamage 27.5
-set g_balance_electro_primary_force 200
-set g_balance_electro_primary_force_up 0
-set g_balance_electro_primary_radius 100
-set g_balance_electro_primary_comboradius 150
-set g_balance_electro_primary_speed 2500
-set g_balance_electro_primary_spread 0
-set g_balance_electro_primary_lifetime 5
-set g_balance_electro_primary_refire 0.6
-set g_balance_electro_primary_animtime 0.1
-set g_balance_electro_primary_ammo 4
-set g_balance_electro_primary_range 0
-set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius
-set g_balance_electro_primary_falloff_maxdist 850
-set g_balance_electro_primary_falloff_halflifedist 425
-set g_balance_electro_secondary_damage 40
-set g_balance_electro_secondary_edgedamage 20
-set g_balance_electro_secondary_force 200
-set g_balance_electro_secondary_radius 150
-set g_balance_electro_secondary_speed 900
-set g_balance_electro_secondary_speed_up 200
-set g_balance_electro_secondary_speed_z 0
-set g_balance_electro_secondary_spread 0.05
-set g_balance_electro_secondary_lifetime 3
-set g_balance_electro_secondary_refire 0.2
-set g_balance_electro_secondary_refire2 1.5
-set g_balance_electro_secondary_animtime 0.2
-set g_balance_electro_secondary_ammo 2
-set g_balance_electro_secondary_health 5
-set g_balance_electro_secondary_damageforcescale 4
-set g_balance_electro_secondary_damagedbycontents 1
-set g_balance_electro_secondary_count 3
-set g_balance_electro_secondary_bouncefactor 0.4
-set g_balance_electro_secondary_bouncestop 0.05
-set g_balance_electro_combo_damage 40
-set g_balance_electro_combo_edgedamage 20
-set g_balance_electro_combo_force 120
-set g_balance_electro_combo_radius 175
-set g_balance_electro_combo_comboradius 275
-set g_balance_electro_combo_speed 2000
-set g_balance_electro_combo_safeammocheck 1
-set g_balance_electro_switchdelay_drop 0
-set g_balance_electro_switchdelay_raise 0
-set g_balance_electro_reload_ammo 0 //default: 20
-set g_balance_electro_reload_time 2
-// }}}
-// {{{ crylink
-set g_balance_crylink_primary_damage 12
-set g_balance_crylink_primary_edgedamage 6
-set g_balance_crylink_primary_force -50
-set g_balance_crylink_primary_radius 80
-set g_balance_crylink_primary_speed 2000
-set g_balance_crylink_primary_spread 0.08
-set g_balance_crylink_primary_shots 6
-set g_balance_crylink_primary_bounces 1
-set g_balance_crylink_primary_refire 0.7
-set g_balance_crylink_primary_animtime 0.3
-set g_balance_crylink_primary_ammo 3
-set g_balance_crylink_primary_bouncedamagefactor 0.5
-set g_balance_crylink_primary_joindelay 0.1
-set g_balance_crylink_primary_joinspread 0.2
-set g_balance_crylink_primary_joinexplode 1
-set g_balance_crylink_primary_joinexplode_damage 0
-set g_balance_crylink_primary_joinexplode_edgedamage 0
-set g_balance_crylink_primary_joinexplode_radius 0
-set g_balance_crylink_primary_joinexplode_force 0
-set g_balance_crylink_primary_linkexplode 1
-
-set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000
-set g_balance_crylink_primary_middle_fadetime 5
-set g_balance_crylink_primary_other_lifetime 5
-set g_balance_crylink_primary_other_fadetime 5
-
-set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_damage 10
-set g_balance_crylink_secondary_edgedamage 5
-set g_balance_crylink_secondary_force -150
-set g_balance_crylink_secondary_radius 100
-set g_balance_crylink_secondary_speed 3000
-set g_balance_crylink_secondary_spread 0.01
-set g_balance_crylink_secondary_spreadtype 1
-set g_balance_crylink_secondary_shots 5
-set g_balance_crylink_secondary_bounces 0
-set g_balance_crylink_secondary_refire 0.7
-set g_balance_crylink_secondary_animtime 0.2
-set g_balance_crylink_secondary_ammo 2
-set g_balance_crylink_secondary_bouncedamagefactor 0.5
-set g_balance_crylink_secondary_joindelay 0
-set g_balance_crylink_secondary_joinspread 0
-set g_balance_crylink_secondary_joinexplode 0
-set g_balance_crylink_secondary_joinexplode_damage 0
-set g_balance_crylink_secondary_joinexplode_edgedamage 0
-set g_balance_crylink_secondary_joinexplode_radius 0
-set g_balance_crylink_secondary_joinexplode_force 0
-set g_balance_crylink_secondary_linkexplode 1
-
-set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
-set g_balance_crylink_secondary_middle_fadetime 5
-set g_balance_crylink_secondary_line_lifetime 5
-set g_balance_crylink_secondary_line_fadetime 5
-
-set g_balance_crylink_switchdelay_drop 0
-set g_balance_crylink_switchdelay_raise 0
-
-set g_balance_crylink_reload_ammo 0 //default: 10
-set g_balance_crylink_reload_time 2
-// }}}
-// {{{ nex
-set g_balance_nex_primary_damage 90
-set g_balance_nex_primary_force 400
-set g_balance_nex_primary_refire 1.5
-set g_balance_nex_primary_animtime 0.4
-set g_balance_nex_primary_ammo 6
-set g_balance_nex_primary_damagefalloff_mindist 0 // 1000    For tZork ;3
-set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000
-set g_balance_nex_primary_damagefalloff_halflife 0 // 1500
-set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 1500
-
-set g_balance_nex_secondary 0
-set g_balance_nex_secondary_charge 0
-set g_balance_nex_secondary_charge_rate 0.1
-set g_balance_nex_secondary_chargepool 0
-set g_balance_nex_secondary_chargepool_regen 0.15
-set g_balance_nex_secondary_chargepool_pause_regen 1
-set g_balance_nex_secondary_chargepool_pause_health_regen 1
-set g_balance_nex_secondary_damage 0
-set g_balance_nex_secondary_force 0
-set g_balance_nex_secondary_refire 0
-set g_balance_nex_secondary_animtime 0
-set g_balance_nex_secondary_ammo 2
-set g_balance_nex_secondary_damagefalloff_mindist 0
-set g_balance_nex_secondary_damagefalloff_maxdist 0
-set g_balance_nex_secondary_damagefalloff_halflife 0
-set g_balance_nex_secondary_damagefalloff_forcehalflife 0
-
-set g_balance_nex_charge 1
-set g_balance_nex_charge_mindmg 40
-set g_balance_nex_charge_start 0.5
-set g_balance_nex_charge_rate 0.4
-set g_balance_nex_charge_animlimit 0.5
-set g_balance_nex_charge_limit 1
-set g_balance_nex_charge_rot_rate 0
-set g_balance_nex_charge_rot_pause 0 // Dont rot down untill this long after release of charge button
-set g_balance_nex_charge_shot_multiplier 0
-set g_balance_nex_charge_velocity_rate 0
-set g_balance_nex_charge_minspeed 400
-set g_balance_nex_charge_maxspeed 800
-
-set g_balance_nex_switchdelay_drop 0
-set g_balance_nex_switchdelay_raise 0
-
-set g_balance_nex_reload_ammo 0 //default: 25
-set g_balance_nex_reload_time 2
-// }}}
-// {{{ minstanex
-set g_balance_minstanex_refire 1
-set g_balance_minstanex_animtime 0.3
-set g_balance_minstanex_ammo 10
-set g_balance_minstanex_laser_ammo 0
-set g_balance_minstanex_laser_animtime 0.3
-set g_balance_minstanex_laser_refire 0.7
-set g_balance_minstanex_switchdelay_drop 0
-set g_balance_minstanex_switchdelay_raise 0
-set g_balance_minstanex_reload_ammo 0 //default: 50
-set g_balance_minstanex_reload_time 2
-// }}}
-// {{{ hagar
-set g_balance_hagar_primary_damage 25
-set g_balance_hagar_primary_edgedamage 12.5
-set g_balance_hagar_primary_force 92
-set g_balance_hagar_primary_health 15
-set g_balance_hagar_primary_damageforcescale 0
-set g_balance_hagar_primary_radius 25
-set g_balance_hagar_primary_spread 0.03
-set g_balance_hagar_primary_speed 2000
-set g_balance_hagar_primary_lifetime 5
-set g_balance_hagar_primary_refire 0.11
-set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_secondary 0
-set g_balance_hagar_secondary_load 1
-set g_balance_hagar_secondary_load_speed 0.5
-set g_balance_hagar_secondary_load_spread 0.075
-set g_balance_hagar_secondary_load_spread_bias 0.5
-set g_balance_hagar_secondary_load_max 4
-set g_balance_hagar_secondary_load_hold 4
-set g_balance_hagar_secondary_load_releasedeath 0
-set g_balance_hagar_secondary_load_abort 0
-set g_balance_hagar_secondary_load_linkexplode 0
-set g_balance_hagar_secondary_load_animtime 0.2
-set g_balance_hagar_secondary_damage 40
-set g_balance_hagar_secondary_edgedamage 20
-set g_balance_hagar_secondary_force 75
-set g_balance_hagar_secondary_health 15
-set g_balance_hagar_secondary_damageforcescale 0
-set g_balance_hagar_secondary_radius 80
-set g_balance_hagar_secondary_spread 0.05
-set g_balance_hagar_secondary_speed 2000
-set g_balance_hagar_secondary_lifetime_min 10
-set g_balance_hagar_secondary_lifetime_rand 0
-set g_balance_hagar_secondary_refire 0.5
-set g_balance_hagar_secondary_ammo 1
-set g_balance_hagar_switchdelay_drop 0
-set g_balance_hagar_switchdelay_raise 0
-set g_balance_hagar_reload_ammo 0 //default: 25
-set g_balance_hagar_reload_time 2
-// }}}
-// {{{ rocketlauncher
-set g_balance_rocketlauncher_damage 80
-set g_balance_rocketlauncher_edgedamage 40
-set g_balance_rocketlauncher_force 350
-set g_balance_rocketlauncher_radius 110
-set g_balance_rocketlauncher_speed 1000
-set g_balance_rocketlauncher_speedaccel 0
-set g_balance_rocketlauncher_speedstart 1000
-set g_balance_rocketlauncher_lifetime 100
-set g_balance_rocketlauncher_refire 0.9
-set g_balance_rocketlauncher_animtime 0.7
-set g_balance_rocketlauncher_ammo 4
-set g_balance_rocketlauncher_health 0 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time.
-set g_balance_rocketlauncher_damageforcescale 0 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn
-set g_balance_rocketlauncher_detonatedelay 999 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
-set g_balance_rocketlauncher_guiderate 0 // max degrees per second
-set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
-set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
-set g_balance_rocketlauncher_guidedelay 0.2 // delay before guiding kicks in
-set g_balance_rocketlauncher_guidestop 1 // stop guiding when firing again
-set g_balance_rocketlauncher_remote_damage 70
-set g_balance_rocketlauncher_remote_edgedamage 35
-set g_balance_rocketlauncher_remote_radius 110
-set g_balance_rocketlauncher_remote_force 350
-set g_balance_rocketlauncher_switchdelay_drop 0
-set g_balance_rocketlauncher_switchdelay_raise 0
-set g_balance_rocketlauncher_reload_ammo 0 //default: 25
-set g_balance_rocketlauncher_reload_time 2
-// }}}
-// {{{ porto
-set g_balance_porto_primary_refire 1.5
-set g_balance_porto_primary_animtime 0.3
-set g_balance_porto_primary_speed 5000
-set g_balance_porto_primary_lifetime 5
-set g_balance_porto_secondary 1
-set g_balance_porto_secondary_refire 1.5
-set g_balance_porto_secondary_animtime 0.3
-set g_balance_porto_secondary_speed 1000
-set g_balance_porto_secondary_lifetime 5
-set g_balance_porto_switchdelay_drop 0
-set g_balance_porto_switchdelay_raise 0
-set g_balance_portal_health 200 // these get recharged whenever the portal is used
-set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
-// }}}
-// {{{ hook
-set g_balance_hook_primary_fuel 5 // hook monkeys set 0
-set g_balance_hook_primary_refire 0.2 // hook monkeys set 0
-set g_balance_hook_primary_animtime 0.3 // good shoot anim
-set g_balance_hook_primary_hooked_time_max 0 // infinite
-set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
-set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked
-set g_balance_hook_secondary_damage 25 // not much
-set g_balance_hook_secondary_edgedamage 5 // not much
-set g_balance_hook_secondary_radius 500 // LOTS
-set g_balance_hook_secondary_force -2000 // LOTS
-set g_balance_hook_secondary_ammo 50 // a whole pack
-set g_balance_hook_secondary_lifetime 5 // infinite
-set g_balance_hook_secondary_speed 0 // not much throwing
-set g_balance_hook_secondary_gravity 5 // fast falling
-set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
-set g_balance_hook_secondary_animtime 0.3 // good shoot anim
-set g_balance_hook_secondary_power 3 // effect behaves like a square function
-set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
-set g_balance_hook_secondary_health 15
-set g_balance_hook_secondary_damageforcescale 0
-set g_balance_hook_switchdelay_drop 0
-set g_balance_hook_switchdelay_raise 0
-// }}}
-// {{{ tuba
-set g_balance_tuba_refire 0.05
-set g_balance_tuba_animtime 0.05
-set g_balance_tuba_attenuation 0.5
-set g_balance_tuba_volume 1
-set g_balance_tuba_fadetime 0.25
-set g_balance_tuba_damage 5
-set g_balance_tuba_edgedamage 0
-set g_balance_tuba_radius 200
-set g_balance_tuba_force 40
-set g_balance_tuba_pitchstep 6
-set g_balance_tuba_switchdelay_drop 0
-set g_balance_tuba_switchdelay_raise 0
-// }}}
-// {{{ fireball // this is a superweapon -- lets make it behave as one.
-set g_balance_fireball_primary_animtime 0.2
-set g_balance_fireball_primary_bfgdamage 100
-set g_balance_fireball_primary_bfgforce 0
-set g_balance_fireball_primary_bfgradius 1000
-set g_balance_fireball_primary_damage 200
-set g_balance_fireball_primary_damageforcescale 0
-set g_balance_fireball_primary_edgedamage 50
-set g_balance_fireball_primary_force 600
-set g_balance_fireball_primary_health 0
-set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 80
-set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 256
-set g_balance_fireball_primary_lifetime 15
-set g_balance_fireball_primary_radius 200
-set g_balance_fireball_primary_refire 2
-set g_balance_fireball_primary_refire2 0
-set g_balance_fireball_primary_speed 1200
-set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_animtime 0.3
-set g_balance_fireball_secondary_damage 40
-set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_damagetime 5
-set g_balance_fireball_secondary_force 100
-set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 50
-set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 110
-set g_balance_fireball_secondary_lifetime 7
-set g_balance_fireball_secondary_refire 1.5
-set g_balance_fireball_secondary_speed 900
-set g_balance_fireball_secondary_speed_up 100
-set g_balance_fireball_secondary_speed_z 0
-set g_balance_fireball_secondary_spread 0
-set g_balance_fireball_switchdelay_drop 0
-set g_balance_fireball_switchdelay_raise 0
-// }}}
diff --git a/oldbalanceXPM.cfg b/oldbalanceXPM.cfg
deleted file mode 100644
index f7b088aae..000000000
--- a/oldbalanceXPM.cfg
+++ /dev/null
@@ -1,780 +0,0 @@
-g_mod_balance XPM
-
-// {{{ starting gear
-set g_start_weapon_laser -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_shotgun -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_uzi -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_grenadelauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_electro -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_crylink -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_nex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hagar -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms" // UNTIL IT CAN BE REMOVED FROM CODE
-set g_start_weapon_rocketlauncher -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_minstanex -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_porto -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_hook -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_tuba -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_start_weapon_fireball -1 "0 = never provide the weapon, 1 = always provide the weapon, -1 = game mode default, -2 = provide the weapon in ca and lms"
-set g_balance_health_start 100
-set g_balance_armor_start 0
-set g_start_ammo_shells 15
-set g_start_ammo_nails 0
-set g_start_ammo_rockets 0
-set g_start_ammo_cells 0
-set g_start_ammo_fuel 0
-set g_warmup_start_health 100 "starting values when being in warmup-stage"
-set g_warmup_start_armor 100 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_shells 30 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_nails 160 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_rockets 80 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_cells 90 "starting values when being in warmup-stage"
-set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
-set g_lms_start_health 200
-set g_lms_start_armor 200
-set g_lms_start_ammo_shells 60
-set g_lms_start_ammo_nails 320
-set g_lms_start_ammo_rockets 160
-set g_lms_start_ammo_cells 180
-set g_lms_start_ammo_fuel 0
-set g_balance_nix_roundtime 25
-set g_balance_nix_incrtime 1.6
-set g_balance_nix_ammo_shells 60
-set g_balance_nix_ammo_nails 320
-set g_balance_nix_ammo_rockets 160
-set g_balance_nix_ammo_cells 180
-set g_balance_nix_ammo_fuel 0
-set g_balance_nix_ammoincr_shells 2 // eh this will need figured out later I assume
-set g_balance_nix_ammoincr_nails 6
-set g_balance_nix_ammoincr_rockets 2
-set g_balance_nix_ammoincr_cells 2
-set g_balance_nix_ammoincr_fuel 2
-// }}}
-
-// {{{ pickup items
-set g_pickup_ammo_anyway 1
-set g_pickup_weapons_anyway 1
-set g_pickup_shells 15
-set g_pickup_shells_weapon 15
-set g_pickup_shells_max 60
-set g_pickup_nails 80
-set g_pickup_nails_weapon 80
-set g_pickup_nails_max 320
-set g_pickup_rockets 40
-set g_pickup_rockets_weapon 40
-set g_pickup_rockets_max 160
-set g_pickup_cells 30
-set g_pickup_cells_weapon 30
-set g_pickup_cells_max 180
-set g_pickup_fuel 50
-set g_pickup_fuel_weapon 50
-set g_pickup_fuel_jetpack 100
-set g_pickup_fuel_max 100
-set g_pickup_armorsmall 5
-set g_pickup_armorsmall_max 200
-set g_pickup_armorsmall_anyway 0
-set g_pickup_armormedium 25
-set g_pickup_armormedium_max 100
-set g_pickup_armormedium_anyway 0
-set g_pickup_armorbig 50
-set g_pickup_armorbig_max 100
-set g_pickup_armorbig_anyway 0
-set g_pickup_armorlarge 100
-set g_pickup_armorlarge_max 200
-set g_pickup_armorlarge_anyway 0
-set g_pickup_healthsmall 5
-set g_pickup_healthsmall_max 200
-set g_pickup_healthsmall_anyway 0
-set g_pickup_healthmedium 25
-set g_pickup_healthmedium_max 100
-set g_pickup_healthmedium_anyway 0
-set g_pickup_healthlarge 50
-set g_pickup_healthlarge_max 100
-set g_pickup_healthlarge_anyway 0
-set g_pickup_healthmega 100
-set g_pickup_healthmega_max 200
-set g_pickup_healthmega_anyway 0
-set g_pickup_respawntime_short 15
-set g_pickup_respawntime_medium 20
-set g_pickup_respawntime_long 30
-set g_pickup_respawntime_powerup 120
-set g_pickup_respawntime_weapon 10
-set g_pickup_respawntime_superweapon 120
-set g_pickup_respawntime_ammo 15
-set g_pickup_respawntimejitter_short 0
-set g_pickup_respawntimejitter_medium 0
-set g_pickup_respawntimejitter_long 0
-set g_pickup_respawntimejitter_powerup 30
-set g_pickup_respawntimejitter_weapon 0
-set g_pickup_respawntimejitter_superweapon 10
-set g_pickup_respawntimejitter_ammo 0
-// }}}
-
-// {{{ regen/rot
-set g_balance_health_regen 0.08
-set g_balance_health_regenlinear 0.5
-set g_balance_pause_health_regen 5
-set g_balance_pause_health_regen_spawn 0
-set g_balance_health_rot 0.03
-set g_balance_health_rotlinear 0.75
-set g_balance_pause_health_rot 1
-set g_balance_pause_health_rot_spawn 5
-set g_balance_health_regenstable 100
-set g_balance_health_rotstable 100
-set g_balance_health_limit 999
-set g_balance_armor_regen 0
-set g_balance_armor_regenlinear 0
-set g_balance_armor_rot 0.03
-set g_balance_armor_rotlinear 0.75
-set g_balance_pause_armor_rot 1
-set g_balance_pause_armor_rot_spawn 5
-set g_balance_armor_regenstable 100
-set g_balance_armor_rotstable 100
-set g_balance_armor_limit 999
-set g_balance_armor_blockpercent 0.6
-set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
-set g_balance_fuel_regenlinear 0
-set g_balance_pause_fuel_regen 2 // other than this, fuel uses the health regen counter
-set g_balance_fuel_rot 0.05
-set g_balance_fuel_rotlinear 0
-set g_balance_pause_fuel_rot 5
-set g_balance_pause_fuel_rot_spawn 10
-set g_balance_fuel_regenstable 50
-set g_balance_fuel_rotstable 100
-set g_balance_fuel_limit 999
-// }}}
-
-// {{{ misc
-set g_balance_selfdamagepercent 0.65
-set g_weaponspeedfactor 1 "weapon projectile speed multiplier"
-set g_weaponratefactor 1 "weapon fire rate multiplier"
-set g_weapondamagefactor 1 "weapon damage multiplier"
-set g_weaponforcefactor 1 "weapon force multiplier"
-set g_weaponspreadfactor 1 "weapon spread multiplier"
-set g_balance_firetransfer_time 0.9
-set g_balance_firetransfer_damage 0.8
-set g_throughfloor_damage 0.75
-set g_throughfloor_force 0.75
-set g_projectiles_damage 1
-// possible values:
-// -2: absolutely no damage to projectiles (no exceptions)
-// -1: no damage other than the exceptions (electro combo, hagar join explode, ML mines)
-// 0: only damage from contents (lava/slime) or exceptions
-// 1: only self damage or damage from contents or exceptions
-// 2: allow all damage to projectiles normally
-set g_projectiles_keep_owner 0
-set g_projectiles_newton_style 0
-// possible values:
-// 0: absolute velocity projectiles (like Quake)
-// 1: relative velocity projectiles, "Newtonian" (like Tribes 2)
-// 2: relative velocity projectiles, but aim is precorrected so projectiles hit the crosshair (note: strafe rockets then are SLOWER than ones shot while standing, happens in 1 too when aiming correctly which is hard)
-set g_projectiles_newton_style_2_minfactor 0.8
-set g_projectiles_newton_style_2_maxfactor 1.5
-set g_projectiles_spread_style 7
-// possible values:
-// 0: forward + solid sphere (like Quake) - varies velocity
-// 1: forward + flattened solid sphere
-// 2: forward + solid circle
-// 3: forward + normal distribution 3D - varies velocity
-// 4: forward + normal distribution on a plane
-// 5: forward + circle with 1-r falloff
-// 6: forward + circle with 1-r^2 falloff
-// 7: forward + circle with (1-r)(2-r) falloff
-set g_balance_falldamage_deadminspeed 250
-set g_balance_falldamage_minspeed 900
-set g_balance_falldamage_factor 0.20
-set g_balance_falldamage_maxdamage 40
-set g_balance_damagepush_speedfactor 2.5
-set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
-set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
-set g_balance_contents_playerdamage_drowning 20 // damage per second for while player is drowning
-set g_balance_contents_playerdamage_lava 50 // damage per second for while player is inside lava
-set g_balance_contents_playerdamage_slime 30 // damage per second for while player is inside slime
-set g_balance_contents_projectiledamage 10000 // instantly kill projectiles upon touching lava/slime
-set g_maxpushtime 8.0 "timeout for kill credit when your damage knocks someone into a death trap"
-// }}}
-
-// {{{ powerups
-set g_balance_powerup_invincible_takedamage 0.25 // only 1/4th damage is taken
-set g_balance_powerup_invincible_time 30
-set g_balance_powerup_strength_damage 3
-set g_balance_powerup_strength_force 3
-set g_balance_powerup_strength_time 30
-set g_balance_powerup_strength_selfdamage 1.5
-set g_balance_powerup_strength_selfforce 1.5
-set g_balance_superweapons_time 30
-// }}}
-
-// {{{ jetpack/hook
-set g_jetpack_antigravity 0.8 "factor of gravity compensation of the jetpack"
-set g_jetpack_acceleration_side 1200 "acceleration of the jetpack in xy direction"
-set g_jetpack_acceleration_up 600 "acceleration of the jetpack in z direction (note: you have to factor in gravity here, if antigravity is not 1)"
-set g_jetpack_maxspeed_side 1200 "max speed of the jetpack in xy direction"
-set g_jetpack_maxspeed_up 600 "max speed of the jetpack in z direction"
-set g_jetpack_fuel 8 "fuel per second for jetpack"
-set g_jetpack_attenuation 2 "jetpack sound attenuation"
-
-set g_grappling_hook_tarzan 2 // 2: can also pull players
-set g_balance_grapplehook_speed_fly 1800
-set g_balance_grapplehook_speed_pull 2000
-set g_balance_grapplehook_force_rubber 2000
-set g_balance_grapplehook_force_rubber_overstretch 1000
-set g_balance_grapplehook_length_min 50
-set g_balance_grapplehook_stretch 50
-set g_balance_grapplehook_airfriction 0.2
-set g_balance_grapplehook_health 50
-set g_balance_grapplehook_damagedbycontents 1
-set g_balance_grapplehook_refire 0.2
-// }}}
-
-// {{{ weapon properties
-// {{{ laser
-set g_balance_laser_melee_animtime 0.3
-set g_balance_laser_melee_damage 80
-set g_balance_laser_melee_delay 0.25
-set g_balance_laser_melee_force 200
-set g_balance_laser_melee_multihit 1
-set g_balance_laser_melee_no_doubleslap 1
-set g_balance_laser_melee_nonplayerdamage 40
-set g_balance_laser_melee_range 120
-set g_balance_laser_melee_refire 1.25
-set g_balance_laser_melee_swing_side 120
-set g_balance_laser_melee_swing_up 30
-set g_balance_laser_melee_time 0.15
-set g_balance_laser_melee_traces 10
-
-set g_balance_laser_primary 0 // 0 = shockwave attack, 1 = projectile primary
-set g_balance_laser_primary_damage 25
-set g_balance_laser_primary_edgedamage 12.5
-set g_balance_laser_primary_force 300
-set g_balance_laser_primary_radius 70
-set g_balance_laser_primary_speed 6000
-set g_balance_laser_primary_spread 0
-set g_balance_laser_primary_refire 0.7
-set g_balance_laser_primary_animtime 0.2
-set g_balance_laser_primary_lifetime 5
-set g_balance_laser_primary_shotangle 0
-set g_balance_laser_primary_delay 0
-set g_balance_laser_primary_force_zscale 1.2
-set g_balance_laser_primary_force_velocitybias 0
-set g_balance_laser_primary_force_other_scale 1
-
-set g_balance_laser_secondary 2 // 0 = switch away to last used weapon, 1 = projectile secondary, 2 = melee secondary
-set g_balance_laser_secondary_damage 25
-set g_balance_laser_secondary_edgedamage 12.5
-set g_balance_laser_secondary_force 400
-set g_balance_laser_secondary_radius 70
-set g_balance_laser_secondary_speed 12000
-set g_balance_laser_secondary_spread 0
-set g_balance_laser_secondary_refire 0.7
-set g_balance_laser_secondary_animtime 0.2
-set g_balance_laser_secondary_lifetime 5
-set g_balance_laser_secondary_shotangle -90
-set g_balance_laser_secondary_delay 0
-set g_balance_laser_secondary_force_zscale 1.25
-set g_balance_laser_secondary_force_velocitybias 0
-set g_balance_laser_secondary_force_other_scale 1
-
-set g_balance_laser_shockwave_damage 20
-set g_balance_laser_shockwave_distance 2000
-set g_balance_laser_shockwave_edgedamage 0
-set g_balance_laser_shockwave_force 200
-set g_balance_laser_shockwave_force_forwardbias 50
-set g_balance_laser_shockwave_force_zscale 2
-set g_balance_laser_shockwave_jump_damage 20
-set g_balance_laser_shockwave_jump_edgedamage 0
-set g_balance_laser_shockwave_jump_force 300
-set g_balance_laser_shockwave_jump_force_velocitybias 0
-set g_balance_laser_shockwave_jump_force_zscale 1.25
-set g_balance_laser_shockwave_jump_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_jump_multiplier_distance 0.5
-set g_balance_laser_shockwave_jump_multiplier_min 0
-set g_balance_laser_shockwave_jump_radius 150
-set g_balance_laser_shockwave_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_multiplier_distance 0.5
-set g_balance_laser_shockwave_multiplier_min 0
-set g_balance_laser_shockwave_splash_damage 15
-set g_balance_laser_shockwave_splash_edgedamage 0
-set g_balance_laser_shockwave_splash_force 100
-set g_balance_laser_shockwave_splash_force_forwardbias 50
-set g_balance_laser_shockwave_splash_multiplier_accuracy 0.5
-set g_balance_laser_shockwave_splash_multiplier_distance 0.5
-set g_balance_laser_shockwave_splash_multiplier_min 0
-set g_balance_laser_shockwave_splash_radius 70
-set g_balance_laser_shockwave_spread_max 120
-set g_balance_laser_shockwave_spread_min 25
-
-set g_balance_laser_switchdelay_drop 0.15
-set g_balance_laser_switchdelay_raise 0.15
-set g_balance_laser_reload_ammo 0 //default: 6
-set g_balance_laser_reload_time 2
-// }}}
-// {{{ shotgun
-set g_balance_shotgun_primary_bullets 14
-set g_balance_shotgun_primary_damage 4
-set g_balance_shotgun_primary_force 15
-set g_balance_shotgun_primary_spread 0.12
-set g_balance_shotgun_primary_refire 0.75
-set g_balance_shotgun_primary_animtime 0.2
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_solidpenetration 3.8
-set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_melee_delay 0.25 // 0.35 was too slow
-set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing_side 120
-set g_balance_shotgun_secondary_melee_swing_up 30
-set g_balance_shotgun_secondary_melee_time 0.15
-set g_balance_shotgun_secondary_melee_traces 10
-set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_melee_nonplayerdamage 40
-set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_damage 80
-set g_balance_shotgun_secondary_force 200
-set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_secondary_animtime 1
-set g_balance_shotgun_switchdelay_drop 0.2
-set g_balance_shotgun_switchdelay_raise 0.2
-set g_balance_shotgun_reload_ammo 0 //default: 5
-set g_balance_shotgun_reload_time 2
-// }}}
-// {{{ uzi
-set g_balance_uzi_mode 1 				// Activates varible spread for sustained & burst mode secondary
-set g_balance_uzi_spread_min 0.02
-set g_balance_uzi_spread_max 0.05
-set g_balance_uzi_spread_add 0.012
-
-set g_balance_uzi_burst 3				// # of bullets in a burst (if set to 2 or more)
-set g_balance_uzi_burst_animtime 0.3
-set g_balance_uzi_burst_refire 0.06		// refire between burst bullets
-set g_balance_uzi_burst_refire2 0.45	// refire after burst
-set g_balance_uzi_burst_spread 0.02
-set g_balance_uzi_burst_damage 25
-set g_balance_uzi_burst_force 20
-set g_balance_uzi_burst_ammo 3
-
-set g_balance_uzi_first 1
-set g_balance_uzi_first_damage 14
-set g_balance_uzi_first_force 5
-set g_balance_uzi_first_spread 0.03
-set g_balance_uzi_first_refire 0.125
-set g_balance_uzi_first_ammo 1
-
-set g_balance_uzi_sustained_damage 10 // 100 dps
-set g_balance_uzi_sustained_force 5
-set g_balance_uzi_sustained_spread 0.03
-set g_balance_uzi_sustained_refire 0.1
-set g_balance_uzi_sustained_ammo 1
-
-set g_balance_uzi_solidpenetration 13.1
-
-set g_balance_uzi_switchdelay_drop 0.2
-set g_balance_uzi_switchdelay_raise 0.2
-
-set g_balance_uzi_reload_ammo 60 //default: 30
-set g_balance_uzi_reload_time 2
-// }}}
-// {{{ mortar
-set g_balance_grenadelauncher_primary_type 0
-set g_balance_grenadelauncher_primary_damage 50
-set g_balance_grenadelauncher_primary_edgedamage 25
-set g_balance_grenadelauncher_primary_force 250
-set g_balance_grenadelauncher_primary_radius 120
-set g_balance_grenadelauncher_primary_speed 1900
-set g_balance_grenadelauncher_primary_speed_up 225
-set g_balance_grenadelauncher_primary_speed_z 0
-set g_balance_grenadelauncher_primary_spread 0
-set g_balance_grenadelauncher_primary_lifetime 5
-set g_balance_grenadelauncher_primary_lifetime2 1
-set g_balance_grenadelauncher_primary_refire 0.8
-set g_balance_grenadelauncher_primary_animtime 0.3
-set g_balance_grenadelauncher_primary_ammo 2
-set g_balance_grenadelauncher_primary_health 15
-set g_balance_grenadelauncher_primary_damageforcescale 0
-set g_balance_grenadelauncher_primary_remote_minbouncecnt 0
-
-set g_balance_grenadelauncher_secondary_type 1
-set g_balance_grenadelauncher_secondary_damage 60
-set g_balance_grenadelauncher_secondary_edgedamage 30
-set g_balance_grenadelauncher_secondary_force 250
-set g_balance_grenadelauncher_secondary_radius 120
-set g_balance_grenadelauncher_secondary_speed 1400
-set g_balance_grenadelauncher_secondary_speed_up 150
-set g_balance_grenadelauncher_secondary_speed_z 0
-set g_balance_grenadelauncher_secondary_spread 0
-set g_balance_grenadelauncher_secondary_lifetime 5
-set g_balance_grenadelauncher_secondary_lifetime_bounce 0.5
-set g_balance_grenadelauncher_secondary_lifetime_stick 0
-set g_balance_grenadelauncher_secondary_refire 0.7
-set g_balance_grenadelauncher_secondary_animtime 0.3
-set g_balance_grenadelauncher_secondary_ammo 2
-set g_balance_grenadelauncher_secondary_health 30
-set g_balance_grenadelauncher_secondary_damageforcescale 4
-set g_balance_grenadelauncher_secondary_remote_detonateprimary 0
-
-set g_balance_grenadelauncher_bouncefactor 0.5
-set g_balance_grenadelauncher_bouncestop 0.075
-
-set g_balance_grenadelauncher_switchdelay_drop 0.2
-set g_balance_grenadelauncher_switchdelay_raise 0.2
-
-set g_balance_grenadelauncher_reload_ammo 0 //default: 12
-set g_balance_grenadelauncher_reload_time 2
-// }}}
-// {{{ electro
-set g_balance_electro_lightning 0
-set g_balance_electro_primary_damage 40
-set g_balance_electro_primary_edgedamage 20
-set g_balance_electro_primary_force 200
-set g_balance_electro_primary_force_up 0
-set g_balance_electro_primary_radius 100
-set g_balance_electro_primary_comboradius 300
-set g_balance_electro_primary_speed 2500
-set g_balance_electro_primary_spread 0
-set g_balance_electro_primary_lifetime 5
-set g_balance_electro_primary_refire 0.6
-set g_balance_electro_primary_animtime 0.3
-set g_balance_electro_primary_ammo 4
-set g_balance_electro_primary_range 0
-set g_balance_electro_primary_falloff_mindist 255 // 0.3 * radius
-set g_balance_electro_primary_falloff_maxdist 850
-set g_balance_electro_primary_falloff_halflifedist 425
-set g_balance_electro_secondary_damage 40
-set g_balance_electro_secondary_edgedamage 20
-set g_balance_electro_secondary_force 50
-set g_balance_electro_secondary_radius 150
-set g_balance_electro_secondary_speed 1000
-set g_balance_electro_secondary_speed_up 200
-set g_balance_electro_secondary_speed_z 0
-set g_balance_electro_secondary_spread 0.04
-set g_balance_electro_secondary_lifetime 4
-set g_balance_electro_secondary_refire 0.2
-set g_balance_electro_secondary_refire2 1.6
-set g_balance_electro_secondary_animtime 0.2
-set g_balance_electro_secondary_ammo 2
-set g_balance_electro_secondary_health 5
-set g_balance_electro_secondary_damageforcescale 4
-set g_balance_electro_secondary_damagedbycontents 1
-set g_balance_electro_secondary_count 3
-set g_balance_electro_secondary_bouncefactor 0.3
-set g_balance_electro_secondary_bouncestop 0.05
-set g_balance_electro_combo_damage 50
-set g_balance_electro_combo_edgedamage 25
-set g_balance_electro_combo_force 120
-set g_balance_electro_combo_radius 150
-set g_balance_electro_combo_comboradius 300
-set g_balance_electro_combo_speed 2000
-set g_balance_electro_combo_safeammocheck 1
-set g_balance_electro_switchdelay_drop 0.2
-set g_balance_electro_switchdelay_raise 0.2
-set g_balance_electro_reload_ammo 0 //default: 20
-set g_balance_electro_reload_time 2
-// }}}
-// {{{ lightning
-set g_balance_lightning_primary_ammo 5
-set g_balance_lightning_primary_animtime 0.2
-set g_balance_lightning_primary_damage 100
-set g_balance_lightning_primary_edgedamage 0
-set g_balance_lightning_primary_falloff_mindist 0
-set g_balance_lightning_primary_falloff_maxdist 0
-set g_balance_lightning_primary_falloff_halflifedist 0
-set g_balance_lightning_primary_force 425
-set g_balance_lightning_primary_lifetime 0
-set g_balance_lightning_primary_radius 850
-set g_balance_lightning_primary_range 800
-set g_balance_lightning_primary_refire 0.4
-set g_balance_lightning_primary_speed 0
-set g_balance_lightning_primary_spread 0
-set g_balance_lightning_secondary_ammo 5
-set g_balance_lightning_secondary_animtime 0.5
-set g_balance_lightning_secondary_damage 100
-set g_balance_lightning_secondary_damageforcescale 4
-set g_balance_lightning_secondary_edgedamage 80
-set g_balance_lightning_secondary_flyingdamage 1
-set g_balance_lightning_secondary_flyingforce -80
-set g_balance_lightning_secondary_flyingradius 200
-set g_balance_lightning_secondary_force -200
-set g_balance_lightning_secondary_health 1
-set g_balance_lightning_secondary_lifetime 30
-set g_balance_lightning_secondary_radius 300
-set g_balance_lightning_secondary_refire 5
-set g_balance_lightning_secondary_speed 600
-// }}}
-// {{{ crylink 
-set g_balance_crylink_primary_damage 12
-set g_balance_crylink_primary_edgedamage 6
-set g_balance_crylink_primary_force -50
-set g_balance_crylink_primary_radius 80
-set g_balance_crylink_primary_speed 2000
-set g_balance_crylink_primary_spread 0.08
-set g_balance_crylink_primary_shots 6
-set g_balance_crylink_primary_bounces 1
-set g_balance_crylink_primary_refire 0.7
-set g_balance_crylink_primary_animtime 0.3
-set g_balance_crylink_primary_ammo 3
-set g_balance_crylink_primary_bouncedamagefactor 0.5
-set g_balance_crylink_primary_joindelay 0.1
-set g_balance_crylink_primary_joinspread 0.2
-set g_balance_crylink_primary_joinexplode 1
-set g_balance_crylink_primary_joinexplode_damage 0
-set g_balance_crylink_primary_joinexplode_edgedamage 0
-set g_balance_crylink_primary_joinexplode_radius 0
-set g_balance_crylink_primary_joinexplode_force 0
-set g_balance_crylink_primary_linkexplode 1
-
-set g_balance_crylink_primary_middle_lifetime 5 // range: 35000 full, fades to 70000
-set g_balance_crylink_primary_middle_fadetime 5
-set g_balance_crylink_primary_other_lifetime 5
-set g_balance_crylink_primary_other_fadetime 5
-
-set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_damage 10
-set g_balance_crylink_secondary_edgedamage 5
-set g_balance_crylink_secondary_force -250
-set g_balance_crylink_secondary_radius 100
-set g_balance_crylink_secondary_speed 3000
-set g_balance_crylink_secondary_spread 0.01
-set g_balance_crylink_secondary_spreadtype 1
-set g_balance_crylink_secondary_shots 5
-set g_balance_crylink_secondary_bounces 0
-set g_balance_crylink_secondary_refire 0.7
-set g_balance_crylink_secondary_animtime 0.2
-set g_balance_crylink_secondary_ammo 2
-set g_balance_crylink_secondary_bouncedamagefactor 0.5
-set g_balance_crylink_secondary_joindelay 0
-set g_balance_crylink_secondary_joinspread 0
-set g_balance_crylink_secondary_joinexplode 0
-set g_balance_crylink_secondary_joinexplode_damage 0
-set g_balance_crylink_secondary_joinexplode_edgedamage 0
-set g_balance_crylink_secondary_joinexplode_radius 0
-set g_balance_crylink_secondary_joinexplode_force 0
-set g_balance_crylink_secondary_linkexplode 1
-
-set g_balance_crylink_secondary_middle_lifetime 5 // range: 35000 full, fades to 70000
-set g_balance_crylink_secondary_middle_fadetime 5
-set g_balance_crylink_secondary_line_lifetime 5
-set g_balance_crylink_secondary_line_fadetime 5
-
-set g_balance_crylink_switchdelay_drop 0.2
-set g_balance_crylink_switchdelay_raise 0.2
-
-set g_balance_crylink_reload_ammo 0 //default: 10
-set g_balance_crylink_reload_time 2
-// }}}
-// {{{ nex
-set g_balance_nex_primary_damage 80
-set g_balance_nex_primary_force 400
-set g_balance_nex_primary_refire 1.5
-set g_balance_nex_primary_animtime 0.6
-set g_balance_nex_primary_ammo 6
-set g_balance_nex_primary_damagefalloff_mindist 0 // 1000    For tZork ;3
-set g_balance_nex_primary_damagefalloff_maxdist 0 // 3000
-set g_balance_nex_primary_damagefalloff_halflife 0 // 1500
-set g_balance_nex_primary_damagefalloff_forcehalflife 0 // 1500
-
-set g_balance_nex_secondary 0
-set g_balance_nex_secondary_charge 0
-set g_balance_nex_secondary_charge_rate 0.1
-set g_balance_nex_secondary_chargepool 0
-set g_balance_nex_secondary_chargepool_regen 0.15
-set g_balance_nex_secondary_chargepool_pause_regen 1
-set g_balance_nex_secondary_chargepool_pause_health_regen 1
-set g_balance_nex_secondary_damage 0
-set g_balance_nex_secondary_force 0
-set g_balance_nex_secondary_refire 0
-set g_balance_nex_secondary_animtime 0
-set g_balance_nex_secondary_ammo 2
-set g_balance_nex_secondary_damagefalloff_mindist 0
-set g_balance_nex_secondary_damagefalloff_maxdist 0
-set g_balance_nex_secondary_damagefalloff_halflife 0
-set g_balance_nex_secondary_damagefalloff_forcehalflife 0
-
-set g_balance_nex_charge 1
-set g_balance_nex_charge_mindmg 40
-set g_balance_nex_charge_start 0.5
-set g_balance_nex_charge_rate 0.4
-set g_balance_nex_charge_animlimit 0.5
-set g_balance_nex_charge_limit 1
-set g_balance_nex_charge_rot_rate 0
-set g_balance_nex_charge_rot_pause 0 // Dont rot down until this long after release of charge button
-set g_balance_nex_charge_shot_multiplier 0
-set g_balance_nex_charge_velocity_rate 0
-set g_balance_nex_charge_minspeed 400
-set g_balance_nex_charge_maxspeed 800
-
-set g_balance_nex_switchdelay_drop 0.3
-set g_balance_nex_switchdelay_raise 0.25
-
-set g_balance_nex_reload_ammo 0 //default: 25
-set g_balance_nex_reload_time 2
-// }}}
-// {{{ minstanex
-set g_balance_minstanex_refire 1
-set g_balance_minstanex_animtime 0.3
-set g_balance_minstanex_ammo 10
-set g_balance_minstanex_laser_ammo 0
-set g_balance_minstanex_laser_animtime 0.3
-set g_balance_minstanex_laser_refire 0.7
-set g_balance_minstanex_switchdelay_drop 0.2
-set g_balance_minstanex_switchdelay_raise 0.2
-set g_balance_minstanex_reload_ammo 0 //default: 50
-set g_balance_minstanex_reload_time 2
-// }}}
-// {{{ hagar
-set g_balance_hagar_primary_damage 25
-set g_balance_hagar_primary_edgedamage 12.5
-set g_balance_hagar_primary_force 100
-set g_balance_hagar_primary_health 15
-set g_balance_hagar_primary_damageforcescale 0
-set g_balance_hagar_primary_radius 65
-set g_balance_hagar_primary_spread 0.03
-set g_balance_hagar_primary_speed 2500
-set g_balance_hagar_primary_lifetime 5
-set g_balance_hagar_primary_refire 0.16667 // 6 rockets per second
-set g_balance_hagar_primary_ammo 1
-set g_balance_hagar_secondary 1
-set g_balance_hagar_secondary_load 1
-set g_balance_hagar_secondary_load_speed 0.5
-set g_balance_hagar_secondary_load_spread 0.075
-set g_balance_hagar_secondary_load_spread_bias 0.5
-set g_balance_hagar_secondary_load_max 4
-set g_balance_hagar_secondary_load_hold 4
-set g_balance_hagar_secondary_load_releasedeath 0
-set g_balance_hagar_secondary_load_abort 0
-set g_balance_hagar_secondary_load_linkexplode 0
-set g_balance_hagar_secondary_load_animtime 0.2
-set g_balance_hagar_secondary_damage 40
-set g_balance_hagar_secondary_edgedamage 20
-set g_balance_hagar_secondary_force 75
-set g_balance_hagar_secondary_health 15
-set g_balance_hagar_secondary_damageforcescale 0
-set g_balance_hagar_secondary_radius 80
-set g_balance_hagar_secondary_spread 0.05
-set g_balance_hagar_secondary_speed 2000
-set g_balance_hagar_secondary_lifetime_min 10
-set g_balance_hagar_secondary_lifetime_rand 0
-set g_balance_hagar_secondary_refire 0.5
-set g_balance_hagar_secondary_ammo 1
-set g_balance_hagar_switchdelay_drop 0.2
-set g_balance_hagar_switchdelay_raise 0.2
-set g_balance_hagar_reload_ammo 0 //default: 25
-set g_balance_hagar_reload_time 2
-// }}}
-// {{{ rocketlauncher
-set g_balance_rocketlauncher_damage 70
-set g_balance_rocketlauncher_edgedamage 35
-set g_balance_rocketlauncher_force 450
-set g_balance_rocketlauncher_radius 110
-set g_balance_rocketlauncher_speed 1300
-set g_balance_rocketlauncher_speedaccel 1300
-set g_balance_rocketlauncher_speedstart 1000
-set g_balance_rocketlauncher_lifetime 10
-set g_balance_rocketlauncher_refire 1.2
-set g_balance_rocketlauncher_animtime 0.4
-set g_balance_rocketlauncher_ammo 4
-set g_balance_rocketlauncher_health 30 // 30 // 5 hitpoints above maximum laser value -- this way lasers can't blow it up, but grenadelauncher still can most the time.
-set g_balance_rocketlauncher_damageforcescale 1 // low damage force scale so that it can still be affected by other hits, but not so much that it does a 90 degree turn
-set g_balance_rocketlauncher_detonatedelay 0.02 // positive: timer till detonation is allowed, negative: "security device" that prevents ANY remote detonation if it could hurt its owner, zero: detonatable at any time
-set g_balance_rocketlauncher_guiderate 70 // max degrees per second
-set g_balance_rocketlauncher_guideratedelay 0.01 // immediate
-set g_balance_rocketlauncher_guidegoal 512 // goal distance for (non-laser) guiding (higher = less control, lower = erratic)
-set g_balance_rocketlauncher_guidedelay 0.2 // delay before guiding kicks in
-set g_balance_rocketlauncher_guidestop 0 // stop guiding when firing again
-set g_balance_rocketlauncher_remote_damage 70
-set g_balance_rocketlauncher_remote_edgedamage 35
-set g_balance_rocketlauncher_remote_radius 110
-set g_balance_rocketlauncher_remote_force 400
-set g_balance_rocketlauncher_switchdelay_drop 0.3
-set g_balance_rocketlauncher_switchdelay_raise 0.2
-set g_balance_rocketlauncher_reload_ammo 0 //default: 25
-set g_balance_rocketlauncher_reload_time 2
-// }}}
-// {{{ porto
-set g_balance_porto_primary_refire 1.5
-set g_balance_porto_primary_animtime 0.3
-set g_balance_porto_primary_speed 1000
-set g_balance_porto_primary_lifetime 5
-set g_balance_porto_secondary 1
-set g_balance_porto_secondary_refire 1.5
-set g_balance_porto_secondary_animtime 0.3
-set g_balance_porto_secondary_speed 1000
-set g_balance_porto_secondary_lifetime 5
-set g_balance_porto_switchdelay_drop 0.2
-set g_balance_porto_switchdelay_raise 0.2
-set g_balance_portal_health 200 // these get recharged whenever the portal is used
-set g_balance_portal_lifetime 15 // these get recharged whenever the portal is used
-// }}}
-// {{{ hook
-set g_balance_hook_primary_fuel 5 // hook monkeys set 0
-set g_balance_hook_primary_refire 0.2 // hook monkeys set 0
-set g_balance_hook_primary_animtime 0.3 // good shoot anim
-set g_balance_hook_primary_hooked_time_max 0 // infinite
-set g_balance_hook_primary_hooked_time_free 2 // 2s being hooked are free
-set g_balance_hook_primary_hooked_fuel 5 // fuel per second hooked
-set g_balance_hook_secondary_damage 25 // not much
-set g_balance_hook_secondary_edgedamage 5 // not much
-set g_balance_hook_secondary_radius 500 // LOTS
-set g_balance_hook_secondary_force -2000 // LOTS
-set g_balance_hook_secondary_ammo 30 // a whole pack
-set g_balance_hook_secondary_lifetime 5 // infinite
-set g_balance_hook_secondary_speed 0 // not much throwing
-set g_balance_hook_secondary_gravity 5 // fast falling
-set g_balance_hook_secondary_refire 3 // don't drop too many bombs...
-set g_balance_hook_secondary_animtime 0.3 // good shoot anim
-set g_balance_hook_secondary_power 3 // effect behaves like a square function
-set g_balance_hook_secondary_duration 1.5 // effect runs for three seconds
-set g_balance_hook_secondary_health 15
-set g_balance_hook_secondary_damageforcescale 0
-set g_balance_hook_switchdelay_drop 0.2
-set g_balance_hook_switchdelay_raise 0.2
-// }}}
-// {{{ tuba
-set g_balance_tuba_refire 0.05
-set g_balance_tuba_animtime 0.05
-set g_balance_tuba_attenuation 0.5
-set g_balance_tuba_volume 1
-set g_balance_tuba_fadetime 0.25
-set g_balance_tuba_damage 5
-set g_balance_tuba_edgedamage 0
-set g_balance_tuba_radius 200
-set g_balance_tuba_force 40
-set g_balance_tuba_pitchstep 6
-set g_balance_tuba_switchdelay_drop 0.2
-set g_balance_tuba_switchdelay_raise 0.2
-// }}}
-// {{{ fireball // this is a superweapon -- lets make it behave as one.
-set g_balance_fireball_primary_animtime 0.2
-set g_balance_fireball_primary_bfgdamage 100
-set g_balance_fireball_primary_bfgforce 0
-set g_balance_fireball_primary_bfgradius 1000
-set g_balance_fireball_primary_damage 200
-set g_balance_fireball_primary_damageforcescale 0
-set g_balance_fireball_primary_edgedamage 50
-set g_balance_fireball_primary_force 600
-set g_balance_fireball_primary_health 0
-set g_balance_fireball_primary_laserburntime 0.5
-set g_balance_fireball_primary_laserdamage 80
-set g_balance_fireball_primary_laseredgedamage 20
-set g_balance_fireball_primary_laserradius 256
-set g_balance_fireball_primary_lifetime 15
-set g_balance_fireball_primary_radius 200
-set g_balance_fireball_primary_refire 2
-set g_balance_fireball_primary_refire2 0
-set g_balance_fireball_primary_speed 1200
-set g_balance_fireball_primary_spread 0
-set g_balance_fireball_secondary_animtime 0.3
-set g_balance_fireball_secondary_damage 40
-set g_balance_fireball_secondary_damageforcescale 4
-set g_balance_fireball_secondary_damagetime 5
-set g_balance_fireball_secondary_force 100
-set g_balance_fireball_secondary_laserburntime 0.5
-set g_balance_fireball_secondary_laserdamage 50
-set g_balance_fireball_secondary_laseredgedamage 20
-set g_balance_fireball_secondary_laserradius 110
-set g_balance_fireball_secondary_lifetime 7
-set g_balance_fireball_secondary_refire 1.5
-set g_balance_fireball_secondary_speed 900
-set g_balance_fireball_secondary_speed_up 100
-set g_balance_fireball_secondary_speed_z 0
-set g_balance_fireball_secondary_spread 0
-set g_balance_fireball_switchdelay_drop 0.2
-set g_balance_fireball_switchdelay_raise 0.2
-// }}}
diff --git a/qcsrc/client/Defs.qc b/qcsrc/client/Defs.qc
index 24a5fbfc0..b89a177f0 100644
--- a/qcsrc/client/Defs.qc
+++ b/qcsrc/client/Defs.qc
@@ -223,8 +223,8 @@ string shortmapname;
 float tempdb;
 float ClientProgsDB;
 vector hook_shotorigin[4];
-vector lightning_shotorigin[4];
-
+vector electro_shotorigin[4];
+vector gauntlet_shotorigin[4];
 
 #ifdef BLURTEST
 float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power;
@@ -251,7 +251,7 @@ float w_deathtype, w_issilent, w_random;
 vector w_org, w_backoff;
 
 float rifle_scope;
-float vortex_scope;
+float nex_scope;
 
 float minelayer_maxmines;
 
@@ -262,7 +262,7 @@ float bgmtime;
 string weaponorder_byimpulse;
 string weaponorder_bypriority;
 
-float vortex_charge_movingavg;
+float nex_charge_movingavg;
 
 float serverflags;
 
diff --git a/qcsrc/client/Main.qc b/qcsrc/client/Main.qc
index 7d85532ba..c0e37ae62 100644
--- a/qcsrc/client/Main.qc
+++ b/qcsrc/client/Main.qc
@@ -125,6 +125,7 @@ void CSQC_Init(void)
 	Hook_Precache();
 	GibSplash_Precache();
 	Casings_Precache();
+	DamageInfo_Precache();
 	Vehicles_Precache();
 	turrets_precache();
 	Tuba_Precache();
@@ -132,8 +133,8 @@ void CSQC_Init(void)
 
 	if(autocvar_cl_reticle)
 	{
-		precache_pic("gfx/reticle_normal");
-		// weapon reticles are precached in weapon files
+		if(autocvar_cl_reticle_item_normal) { precache_pic("gfx/reticle_normal"); }
+		if(autocvar_cl_reticle_item_nex) { precache_pic("gfx/reticle_nex"); }
 	}
 
 	get_mi_min_max_texcoords(1); // try the CLEVER way first
@@ -822,7 +823,8 @@ void CSQC_Ent_Update(float bIsNewEntity)
 		case ENT_CLIENT_WARPZONE_TELEPORTED: WarpZone_Teleported_Read(bIsNewEntity); break;
 		case ENT_CLIENT_TRIGGER_MUSIC: Ent_ReadTriggerMusic(); break;
 		case ENT_CLIENT_HOOK: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_HOOK); break;
-		case ENT_CLIENT_ARC_BEAM: Ent_ReadArcBeam(bIsNewEntity); break;
+		case ENT_CLIENT_LGBEAM: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_LGBEAM); break;
+		case ENT_CLIENT_GAUNTLET: Ent_ReadHook(bIsNewEntity, ENT_CLIENT_GAUNTLET); break;
 		case ENT_CLIENT_ACCURACY: Ent_ReadAccuracy(); break;
 		case ENT_CLIENT_AUXILIARYXHAIR: Net_AuXair2(bIsNewEntity); break;
 		case ENT_CLIENT_TURRET: ent_turret(); break;
@@ -962,10 +964,14 @@ void Ent_Init()
 	hook_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
 	hook_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
 	hook_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
-	arc_shotorigin[0] = decompressShotOrigin(ReadInt24_t());
-	arc_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
-	arc_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
-	arc_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
+	electro_shotorigin[0] = decompressShotOrigin(ReadInt24_t());
+	electro_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
+	electro_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
+	electro_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
+	gauntlet_shotorigin[0] = decompressShotOrigin(ReadInt24_t());
+	gauntlet_shotorigin[1] = decompressShotOrigin(ReadInt24_t());
+	gauntlet_shotorigin[2] = decompressShotOrigin(ReadInt24_t());
+	gauntlet_shotorigin[3] = decompressShotOrigin(ReadInt24_t());
 
 	if(forcefog)
 		strunzone(forcefog);
@@ -978,7 +984,7 @@ void Ent_Init()
 	g_balance_electro_secondary_bouncefactor = ReadCoord();
 	g_balance_electro_secondary_bouncestop = ReadCoord();
 
-	vortex_scope = !ReadByte();
+	nex_scope = !ReadByte();
 	rifle_scope = !ReadByte();
 
 	serverflags = ReadByte();
@@ -1175,7 +1181,7 @@ void Net_WeaponComplain()
 
 	if(complain_weapon_name)
 		strunzone(complain_weapon_name);
-	complain_weapon_name = strzone(WEP_NAME(complain_weapon));
+	complain_weapon_name = strzone(ReadString());
 
 	complain_weapon_type = ReadByte();
 
@@ -1219,16 +1225,16 @@ float CSQC_Parse_TempEntity()
 			Net_ReadRace();
 			bHandled = true;
 			break;
-		case TE_CSQC_VORTEXBEAMPARTICLE:
-			Net_ReadVortexBeamParticle();
+		case TE_CSQC_NEXGUNBEAMPARTICLE:
+			Net_ReadNexgunBeamParticle();
 			bHandled = true;
 			break;
 		case TE_CSQC_TEAMNAGGER:
 			Net_TeamNagger();
 			bHandled = true;
 			break;
-		case TE_CSQC_ARC:
-			Net_ReadArc();
+		case TE_CSQC_LIGHTNINGARC:
+			Net_ReadLightningarc();
 			bHandled = true;
 			break;
 		case TE_CSQC_PINGPLREPORT:
@@ -1247,10 +1253,6 @@ float CSQC_Parse_TempEntity()
 			cl_notice_read();
 			bHandled = true;
 			break;
-		case TE_CSQC_SHOCKWAVEPARTICLE:
-			Net_ReadShockwaveParticle();
-			bHandled = true;
-			break;
 		default:
 			// No special logic for this temporary entity; return 0 so the engine can handle it
 			bHandled = false;
diff --git a/qcsrc/client/View.qc b/qcsrc/client/View.qc
index f68ea32e5..a069faa46 100644
--- a/qcsrc/client/View.qc
+++ b/qcsrc/client/View.qc
@@ -104,7 +104,7 @@ vector GetCurrentFov(float fov)
 
 	zoomdir = button_zoom;
 	if(hud == HUD_NORMAL)
-	if((activeweapon == WEP_VORTEX && vortex_scope) || (activeweapon == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here
+	if((activeweapon == WEP_NEX && nex_scope) || (activeweapon == WEP_RIFLE && rifle_scope)) // do NOT use switchweapon here
 		zoomdir += button_attack2;
 	if(spectatee_status > 0 || isdemo())
 	{
@@ -269,7 +269,7 @@ float EnemyHitCheck()
 
 float TrueAimCheck()
 {
-	float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
+	float nudge = 1; // added to traceline target and subtracted from result
 	vector vecs, trueaimpoint, w_shotorg;
 	vector mi, ma, dv;
 	float shottype;
@@ -280,15 +280,15 @@ float TrueAimCheck()
 	ta = trueaim;
 	mv = MOVE_NOMONSTERS;
 
-	switch(activeweapon) // WEAPONTODO
+	switch(activeweapon)
 	{
 		case WEP_TUBA: // no aim
 		case WEP_PORTO: // shoots from eye
 		case WEP_HOOK: // no trueaim
-		case WEP_MORTAR: // toss curve
+		case WEP_GRENADE_LAUNCHER: // toss curve
 			return SHOTTYPE_HITWORLD;
-		case WEP_VORTEX:
-		case WEP_VAPORIZER:
+		case WEP_NEX:
+		case WEP_MINSTANEX:
 			mv = MOVE_NORMAL;
 			break;
 		case WEP_RIFLE:
@@ -300,7 +300,7 @@ float TrueAimCheck()
 				return EnemyHitCheck();
 			}
 			break;
-		case WEP_DEVASTATOR: // projectile has a size!
+		case WEP_ROCKET_LAUNCHER: // projectile has a size!
 			mi = '-3 -3 -3';
 			ma = '3 3 3';
 			break;
@@ -365,7 +365,6 @@ float camera_mode;
 const float CAMERA_FREE = 1;
 const float CAMERA_CHASE = 2;
 float reticle_type;
-string reticle_image;
 string NextFrameCommand;
 void CSQC_SPIDER_HUD();
 void CSQC_RAPTOR_HUD();
@@ -378,7 +377,7 @@ float pickup_crosshair_time, pickup_crosshair_size;
 float hit_time, typehit_time;
 float nextsound_hit_time, nextsound_typehit_time;
 float hitindication_crosshair_time, hitindication_crosshair_size;
-float use_vortex_chargepool;
+float use_nex_chargepool;
 
 float myhealth, myhealth_prev;
 float myhealth_flash;
@@ -868,64 +867,50 @@ void CSQC_UpdateView(float w, float h)
 		R_EndPolygon();
 	}
 
-	if(autocvar_cl_reticle)
+	// Draw the aiming reticle for weapons that use it
+	// reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
+	// It must be a persisted float for fading out to work properly (you let go of the zoom button for
+	// the view to go back to normal, so reticle_type would become 0 as we fade out)
+	if(spectatee_status || is_dead || hud != HUD_NORMAL)
+		reticle_type = 0; // prevent reticle from showing during the respawn zoom effect or for spectators
+	else if((activeweapon == WEP_NEX || activeweapon == WEP_RIFLE || activeweapon == WEP_MINSTANEX) && (button_zoom || zoomscript_caught))
+		reticle_type = 2; // nex zoom
+	else if(button_zoom || zoomscript_caught)
+		reticle_type = 1; // normal zoom
+	else if((activeweapon == WEP_NEX) && button_attack2)
+		reticle_type = 2; // nex zoom
+
+	if(reticle_type && autocvar_cl_reticle)
 	{
-		// Draw the aiming reticle for weapons that use it
-		// reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
-		// It must be a persisted float for fading out to work properly (you let go of the zoom button for
-		// the view to go back to normal, so reticle_type would become 0 as we fade out)
-		if(spectatee_status || is_dead || hud != HUD_NORMAL)
+		if(autocvar_cl_reticle_stretch)
 		{
-			// no zoom reticle while dead
-			reticle_type = 0;
+			reticle_size_x = vid_conwidth;
+			reticle_size_y = vid_conheight;
+			reticle_pos_x = 0;
+			reticle_pos_y = 0;
 		}
-		else if(WEP_ACTION(activeweapon, WR_ZOOMRETICLE) && autocvar_cl_reticle_weapon)
+		else
 		{
-			if(reticle_image != "") { reticle_type = 2; }
-			else { reticle_type = 0; }
+			reticle_size_x = max(vid_conwidth, vid_conheight);
+			reticle_size_y = max(vid_conwidth, vid_conheight);
+			reticle_pos_x = (vid_conwidth - reticle_size_x) / 2;
+			reticle_pos_y = (vid_conheight - reticle_size_y) / 2;
 		}
-		else if(button_zoom || zoomscript_caught)
+
+		f = current_zoomfraction;
+		if(zoomscript_caught)
+			f = 1;
+		if(autocvar_cl_reticle_item_normal)
 		{
-			// normal zoom
-			reticle_type = 1;
+			if(reticle_type == 1 && f)
+				drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_normal, DRAWFLAG_NORMAL);
 		}
-
-		if(reticle_type)
+		if(autocvar_cl_reticle_item_nex)
 		{
-			if(autocvar_cl_reticle_stretch)
-			{
-				reticle_size_x = vid_conwidth;
-				reticle_size_y = vid_conheight;
-				reticle_pos_x = 0;
-				reticle_pos_y = 0;
-			}
-			else
-			{
-				reticle_size_x = max(vid_conwidth, vid_conheight);
-				reticle_size_y = max(vid_conwidth, vid_conheight);
-				reticle_pos_x = (vid_conwidth - reticle_size_x) / 2;
-				reticle_pos_y = (vid_conheight - reticle_size_y) / 2;
-			}
-
-			if(zoomscript_caught)
-				f = 1;
-			else 
-				f = current_zoomfraction;
-
-			if(f)
-			{
-				switch(reticle_type)
-				{
-					case 1: drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_normal_alpha, DRAWFLAG_NORMAL); break;
-					case 2: drawpic(reticle_pos, reticle_image, reticle_size, '1 1 1', f * autocvar_cl_reticle_weapon_alpha, DRAWFLAG_NORMAL); break;
-				}
-			}
+			if(reticle_type == 2 && f)
+				drawpic(reticle_pos, "gfx/reticle_nex", reticle_size, '1 1 1', f * autocvar_cl_reticle_item_nex, DRAWFLAG_NORMAL);
 		}
 	}
-	else
-	{
-		if(reticle_type != 0) { reticle_type = 0; }
-	}
 
 
 	// improved polyblend
@@ -1234,39 +1219,42 @@ void CSQC_UpdateView(float w, float h)
 				shottype = SHOTTYPE_HITWORLD;
 
 			vector wcross_color = '0 0 0', wcross_size = '0 0 0';
-			string wcross_name = "";
+			string wcross_wep = "", wcross_name;
 			float wcross_scale, wcross_blur;
 
-			if(autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1))
+			if (autocvar_crosshair_per_weapon || (autocvar_crosshair_color_special == 1))
 			{
 				e = get_weaponinfo(switchingweapon);
-				if(e)
+				if (e && e.netname != "")
 				{
+					wcross_wep = e.netname;
 					if(autocvar_crosshair_per_weapon)
 					{
-						// WEAPONTODO: access these through some general settings (with non-balance config settings)
-						//wcross_resolution *= cvar(strcat("crosshair_", wcross_wep, "_size"));
-						//if (wcross_resolution == 0)
-							//return;
-
-						//wcross_style = cvar_string(strcat("crosshair_", wcross_wep));
-						wcross_resolution *= e.w_crosshair_size;
-						wcross_name = e.w_crosshair;
+						wcross_resolution *= cvar(strcat("crosshair_", wcross_wep, "_size"));
+						if (wcross_resolution == 0)
+							return;
+						wcross_alpha *= cvar(strcat("crosshair_", wcross_wep, "_alpha"));
+						if (wcross_alpha == 0)
+							return;
+
+						wcross_style = cvar_string(strcat("crosshair_", wcross_wep));
+						if(wcross_style == "" || wcross_style == "0")
+							wcross_style = wcross_wep;
 					}
 				}
 			}
 
-			if(wcross_name == "")
-				wcross_name = strcat("gfx/crosshair", wcross_style);
+			//printf("crosshair style: %s\n", wcross_style);
+			wcross_name = strcat("gfx/crosshair", wcross_style);
 
 			// MAIN CROSSHAIR COLOR DECISION
 			switch(autocvar_crosshair_color_special)
 			{
 				case 1: // crosshair_color_per_weapon
 				{
-					if(e)
+					if(wcross_wep != "")
 					{
-						wcross_color = e.wpcolor;
+						wcross_color = stov(cvar_string(sprintf("crosshair_%s_color", wcross_wep)));
 						break;
 					}
 					else { goto normalcolor; }
@@ -1454,32 +1442,32 @@ void CSQC_UpdateView(float w, float h)
 					weapon_clipload = getstati(STAT_WEAPON_CLIPLOAD);
 					weapon_clipsize = getstati(STAT_WEAPON_CLIPSIZE);
 
-					float vortex_charge, vortex_chargepool;
-					vortex_charge = getstatf(STAT_VORTEX_CHARGE);
-					vortex_chargepool = getstatf(STAT_VORTEX_CHARGEPOOL);
+					float nex_charge, nex_chargepool;
+					nex_charge = getstatf(STAT_NEX_CHARGE);
+					nex_chargepool = getstatf(STAT_NEX_CHARGEPOOL);
 
-					if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
-						vortex_charge_movingavg = vortex_charge;
+					if(nex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
+						nex_charge_movingavg = nex_charge;
 
 
 					// handle the values
-					if (autocvar_crosshair_ring && activeweapon == WEP_VORTEX && vortex_charge && autocvar_crosshair_ring_vortex) // ring around crosshair representing velocity-dependent damage for the vortex
+					if (autocvar_crosshair_ring && activeweapon == WEP_NEX && nex_charge && autocvar_crosshair_ring_nex) // ring around crosshair representing velocity-dependent damage for the nex
 					{
-						if (vortex_chargepool || use_vortex_chargepool) {
-							use_vortex_chargepool = 1;
-							ring_inner_value = vortex_chargepool;
+						if (nex_chargepool || use_nex_chargepool) {
+							use_nex_chargepool = 1;
+							ring_inner_value = nex_chargepool;
 						} else {
-							vortex_charge_movingavg = (1 - autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate) * vortex_charge_movingavg + autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate * vortex_charge;
-							ring_inner_value = bound(0, autocvar_crosshair_ring_vortex_currentcharge_scale * (vortex_charge - vortex_charge_movingavg), 1);
+							nex_charge_movingavg = (1 - autocvar_crosshair_ring_nex_currentcharge_movingavg_rate) * nex_charge_movingavg + autocvar_crosshair_ring_nex_currentcharge_movingavg_rate * nex_charge;
+							ring_inner_value = bound(0, autocvar_crosshair_ring_nex_currentcharge_scale * (nex_charge - nex_charge_movingavg), 1);
 						}
 
-						ring_inner_alpha = autocvar_crosshair_ring_vortex_inner_alpha;
-						ring_inner_rgb = eX * autocvar_crosshair_ring_vortex_inner_color_red + eY * autocvar_crosshair_ring_vortex_inner_color_green + eZ * autocvar_crosshair_ring_vortex_inner_color_blue;
+						ring_inner_alpha = autocvar_crosshair_ring_nex_inner_alpha;
+						ring_inner_rgb = eX * autocvar_crosshair_ring_nex_inner_color_red + eY * autocvar_crosshair_ring_nex_inner_color_green + eZ * autocvar_crosshair_ring_nex_inner_color_blue;
 						ring_inner_image = "gfx/crosshair_ring_inner.tga";
 
 						// draw the outer ring to show the current charge of the weapon
-						ring_value = vortex_charge;
-						ring_alpha = autocvar_crosshair_ring_vortex_alpha;
+						ring_value = nex_charge;
+						ring_alpha = autocvar_crosshair_ring_nex_alpha;
 						ring_rgb = wcross_color;
 						ring_image = "gfx/crosshair_ring_nexgun.tga";
 					}
diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh
index e33ea8081..28ef157e5 100644
--- a/qcsrc/client/autocvars.qh
+++ b/qcsrc/client/autocvars.qh
@@ -62,9 +62,8 @@ float autocvar_cl_particles_quality;
 float autocvar_cl_projectiles_sloppy;
 float autocvar_cl_readpicture_force;
 var float autocvar_cl_reticle = 1;
-var float autocvar_cl_reticle_normal_alpha = 1;
-var float autocvar_cl_reticle_weapon = 1;
-var float autocvar_cl_reticle_weapon_alpha = 1;
+float autocvar_cl_reticle_item_nex;
+float autocvar_cl_reticle_item_normal;
 float autocvar_cl_reticle_stretch;
 float autocvar_cl_spawn_event_particles;
 var float autocvar_cl_spawn_event_sound = 1;
@@ -126,14 +125,14 @@ float autocvar_crosshair_ring_minelayer;
 float autocvar_crosshair_ring_minelayer_alpha;
 float autocvar_crosshair_ring_hagar;
 float autocvar_crosshair_ring_hagar_alpha;
-float autocvar_crosshair_ring_vortex;
-float autocvar_crosshair_ring_vortex_alpha;
-float autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate;
-float autocvar_crosshair_ring_vortex_currentcharge_scale;
-float autocvar_crosshair_ring_vortex_inner_alpha;
-float autocvar_crosshair_ring_vortex_inner_color_blue;
-float autocvar_crosshair_ring_vortex_inner_color_green;
-float autocvar_crosshair_ring_vortex_inner_color_red;
+float autocvar_crosshair_ring_nex;
+float autocvar_crosshair_ring_nex_alpha;
+float autocvar_crosshair_ring_nex_currentcharge_movingavg_rate;
+float autocvar_crosshair_ring_nex_currentcharge_scale;
+float autocvar_crosshair_ring_nex_inner_alpha;
+float autocvar_crosshair_ring_nex_inner_color_blue;
+float autocvar_crosshair_ring_nex_inner_color_green;
+float autocvar_crosshair_ring_nex_inner_color_red;
 float autocvar_crosshair_ring_size;
 float autocvar_crosshair_ring_reload;
 float autocvar_crosshair_ring_reload_alpha;
@@ -325,7 +324,6 @@ float autocvar_hud_panel_weapons_ammo;
 float autocvar_hud_panel_weapons_ammo_alpha;
 string autocvar_hud_panel_weapons_ammo_color;
 float autocvar_hud_panel_weapons_ammo_full_cells;
-float autocvar_hud_panel_weapons_ammo_full_plasma;
 float autocvar_hud_panel_weapons_ammo_full_fuel;
 float autocvar_hud_panel_weapons_ammo_full_nails;
 float autocvar_hud_panel_weapons_ammo_full_rockets;
diff --git a/qcsrc/client/csqcmodel_hooks.qc b/qcsrc/client/csqcmodel_hooks.qc
index 077b7d972..120b6658d 100644
--- a/qcsrc/client/csqcmodel_hooks.qc
+++ b/qcsrc/client/csqcmodel_hooks.qc
@@ -470,14 +470,8 @@ void CSQCModel_Effects_PreUpdate(void)
 	self.effects = self.csqcmodel_effects;
 	self.modelflags = self.csqcmodel_modelflags;
 }
-void Reset_ArcBeam(void);
 void CSQCModel_Effects_PostUpdate(void)
 {
-	if (self == csqcplayer) {
-		if (self.csqcmodel_teleported) {
-			Reset_ArcBeam();
-		}
-	}
 	self.csqcmodel_effects = self.effects;
 	self.csqcmodel_modelflags = self.modelflags;
 	self.effects = 0;
diff --git a/qcsrc/client/damage.qc b/qcsrc/client/damage.qc
index 32849c2ac..cc3653db4 100644
--- a/qcsrc/client/damage.qc
+++ b/qcsrc/client/damage.qc
@@ -80,22 +80,27 @@ void DamageEffect(vector hitorg, float dmg, float type, float specnum)
 	}
 
 	life = bound(autocvar_cl_damageeffect_lifetime_min, dmg * autocvar_cl_damageeffect_lifetime, autocvar_cl_damageeffect_lifetime_max);
+	specstr = species_prefix(specnum);
+	type = DEATH_WEAPONOF(type);
+	e = get_weaponinfo(type);
 
-	effectname = get_weaponinfo(DEATH_WEAPONOF(type)).netname;
+	effectname = strcat("damage_", e.netname);
 
-	if(substring(effectname, strlen(effectname) - 5, 5) == "BLOOD")
+	// if damage was dealt with a bullet weapon, our effect is blood
+	// since blood is species dependent, include the species tag
+	if(type == WEP_SHOTGUN || type == WEP_UZI || type == WEP_RIFLE)
 	{
 		if(self.isplayermodel)
 		{
-			specstr = species_prefix(specnum);
-			specstr = substring(specstr, 0, strlen(specstr) - 1);
-			effectname = strreplace("BLOOD", specstr, effectname); 
+			effectname = strcat(effectname, "_", specstr);
+			effectname = substring(effectname, 0, strlen(effectname) - 1); // remove the _ symbol at the end of the species tag
 		}
-		else { return; } // objects don't bleed
+		else
+			return; // objects don't bleed
 	}
 
 	e = spawn();
-	setmodel(e, "null"); // necessary to attach and read origin
+	setmodel(e, "null"); // necessary to attach and read origin // samual: FIXME: this is weird, is there some better way to do this?
 	setattachment(e, self, gettaginfo_name); // attach to the given bone
 	e.classname = "damage";
 	e.owner = self;
@@ -339,12 +344,19 @@ void Ent_DamageInfo(float isNew)
 		w_random = prandom();
 
 		traceline(w_org - normalize(force) * 16, w_org + normalize(force) * 16, MOVE_NOMONSTERS, world);
-		if(trace_fraction < 1 && hitwep != WEP_VORTEX && hitwep != WEP_VAPORIZER)
+		if(trace_fraction < 1 && hitwep != WEP_NEX && hitwep != WEP_MINSTANEX)
 			w_backoff = trace_plane_normal;
 		else
 			w_backoff = -1 * normalize(force);
 		setorigin(self, w_org + w_backoff * 2); // for sound() calls
 
-		WEP_ACTION(hitwep, WR_IMPACTEFFECT);
+		(get_weaponinfo(hitwep)).weapon_func(WR_IMPACTEFFECT);
 	}
 }
+
+void DamageInfo_Precache()
+{
+	float i;
+	for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+		(get_weaponinfo(i)).weapon_func(WR_PRECACHE);
+}
diff --git a/qcsrc/client/effects.qc b/qcsrc/client/effects.qc
index c35a3a94a..8c237aade 100644
--- a/qcsrc/client/effects.qc
+++ b/qcsrc/client/effects.qc
@@ -95,4 +95,3 @@ void Net_ReadLightningarc()
     }
 
 }
-void Net_ReadArc() { Net_ReadLightningarc(); }
diff --git a/qcsrc/client/hook.qc b/qcsrc/client/hook.qc
index 8b2ffca19..889e75d26 100644
--- a/qcsrc/client/hook.qc
+++ b/qcsrc/client/hook.qc
@@ -75,8 +75,11 @@ void Draw_GrapplingHook()
 		case ENT_CLIENT_HOOK:
 			vs = hook_shotorigin[s];
 			break;
-		case ENT_CLIENT_ARC_BEAM:
-			vs = lightning_shotorigin[s];
+		case ENT_CLIENT_LGBEAM:
+			vs = electro_shotorigin[s];
+			break;
+		case ENT_CLIENT_GAUNTLET:
+			vs = gauntlet_shotorigin[s];
 			break;
 	}
 
@@ -89,7 +92,8 @@ void Draw_GrapplingHook()
 				a = view_origin + view_forward * vs_x + view_right * -vs_y + view_up * vs_z;
 				b = self.origin;
 				break;
-			case ENT_CLIENT_ARC_BEAM:
+			case ENT_CLIENT_LGBEAM:
+			case ENT_CLIENT_GAUNTLET:
 				if(self.HookRange)
 					b = view_origin + view_forward * self.HookRange;
 				else
@@ -109,7 +113,8 @@ void Draw_GrapplingHook()
 				a = self.velocity;
 				b = self.origin;
 				break;
-			case ENT_CLIENT_ARC_BEAM:
+			case ENT_CLIENT_LGBEAM:
+			case ENT_CLIENT_GAUNTLET:
 				a = self.origin;
 				b = self.velocity;
 				break;
@@ -133,12 +138,18 @@ void Draw_GrapplingHook()
 				default: tex = "particles/hook_white"; rgb = getcsqcplayercolor(self.sv_entnum); break;
 			}
 			break;
-		case ENT_CLIENT_ARC_BEAM: // todo
+		case ENT_CLIENT_LGBEAM:
 			intensity = bound(0.2, 1 + Noise_Pink(self, frametime) * 1 + Noise_Burst(self, frametime, 0.03) * 0.3, 2);
 			offset = Noise_Brown(self, frametime) * 10;
 			tex = "particles/lgbeam";
 			rgb = '1 1 1';
 			break;
+		case ENT_CLIENT_GAUNTLET:
+			intensity = 1;
+			offset = Noise_White(self, frametime);
+			tex = "particles/gauntletbeam";
+			rgb = '1 1 1';
+			break;
 	}
 
 	Draw_GrapplingHook_trace_callback_tex = tex;
@@ -165,7 +176,8 @@ void Draw_GrapplingHook()
 				self.drawmask = 0;
 			}
 			break;
-		case ENT_CLIENT_ARC_BEAM:
+		case ENT_CLIENT_LGBEAM:
+		case ENT_CLIENT_GAUNTLET:
 			setorigin(self, a); // beam origin!
 			break;
 	}
@@ -175,8 +187,11 @@ void Draw_GrapplingHook()
 		default:
 		case ENT_CLIENT_HOOK:
 			break;
-		case ENT_CLIENT_ARC_BEAM:
-			pointparticles(particleeffectnum("electro_lightning"), trace_endpos, normalize(atrans - trace_endpos), frametime * intensity); // todo: new effect
+		case ENT_CLIENT_LGBEAM:
+			pointparticles(particleeffectnum("electro_lightning"), trace_endpos, normalize(atrans - trace_endpos), frametime * intensity);
+			break;
+		case ENT_CLIENT_GAUNTLET:
+			pointparticles(particleeffectnum("gauntlet_lightning"), b, normalize(a - b), frametime * intensity);
 			break;
 	}
 }
@@ -207,9 +222,10 @@ void Ent_ReadHook(float bIsNew, float type)
 		{
 			default:
 			case ENT_CLIENT_HOOK:
+			case ENT_CLIENT_GAUNTLET:
 				self.HookRange = 0;
 				break;
-			case ENT_CLIENT_ARC_BEAM:
+			case ENT_CLIENT_LGBEAM:
 				self.HookRange = ReadCoord();
 				break;
 		}
@@ -243,9 +259,12 @@ void Ent_ReadHook(float bIsNew, float type)
 				setmodel(self, "models/hook.md3");
 				self.drawmask = MASK_NORMAL;
 				break;
-			case ENT_CLIENT_ARC_BEAM:
+			case ENT_CLIENT_LGBEAM:
 				sound (self, CH_SHOTS_SINGLE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTEN_NORM);
 				break;
+			case ENT_CLIENT_GAUNTLET:
+				sound (self, CH_SHOTS_SINGLE, "weapons/gauntletbeam_fly.wav", VOL_BASE, ATTEN_NORM);
+				break;
 		}
 	}
 
@@ -255,6 +274,7 @@ void Ent_ReadHook(float bIsNew, float type)
 void Hook_Precache()
 {
 	precache_sound("weapons/lgbeam_fly.wav");
+	precache_sound("weapons/gauntletbeam_fly.wav");
 	precache_model("models/hook.md3");
 }
 
diff --git a/qcsrc/client/hud.qc b/qcsrc/client/hud.qc
index 701990d6b..ab61eb3c3 100644
--- a/qcsrc/client/hud.qc
+++ b/qcsrc/client/hud.qc
@@ -408,6 +408,42 @@ float weaponorder_cmp(float i, float j, entity pass)
 	return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string)
 }
 
+float GetAmmoStat(float i)
+{
+	switch(i)
+	{
+		case 0: return STAT_SHELLS;
+		case 1: return STAT_NAILS;
+		case 2: return STAT_ROCKETS;
+		case 3: return STAT_CELLS;
+		case 4: return STAT_FUEL;
+		default: return -1;
+	}
+}
+
+float GetAmmoTypeForWep(float i)
+{
+	switch(i)
+	{
+		case WEP_SHOTGUN: return 0;
+		case WEP_UZI: return 1;
+		case WEP_GRENADE_LAUNCHER: return 2;
+		case WEP_MINE_LAYER: return 2;
+		case WEP_ELECTRO: return 3;
+		case WEP_CRYLINK: return 3;
+		case WEP_HLAC: return 3;
+		case WEP_MINSTANEX: return 3;
+		case WEP_NEX: return 3;
+		case WEP_RIFLE: return 1;
+		case WEP_HAGAR: return 2;
+		case WEP_ROCKET_LAUNCHER: return 2;
+		case WEP_SEEKER: return 2;
+		case WEP_FIREBALL: return 4;
+		case WEP_HOOK: return 3;
+		default: return -1;
+	}
+}
+
 void HUD_Weapons(void)
 {
 	// declarations
@@ -424,7 +460,7 @@ void HUD_Weapons(void)
 	float timein_effect_length = autocvar_hud_panel_weapons_timeout_speed_in; //? 0.375 : 0);
 	float timeout_effect_length = autocvar_hud_panel_weapons_timeout_speed_out; //? 0.75 : 0);
 
-	float ammo_full;
+	float ammo_type, ammo_full;
 	float barsize_x = 0, barsize_y = 0, baroffset_x = 0, baroffset_y = 0;
 	vector ammo_color = '1 0 1';
 	float ammo_alpha = 1;
@@ -728,7 +764,7 @@ void HUD_Weapons(void)
 		if(weapons_stat & WepSet_FromWeapon(self.weapon))
 		{
 			// draw the weapon image
-			drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+			drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 
 			// draw weapon label string
 			switch(autocvar_hud_panel_weapons_label)
@@ -742,7 +778,7 @@ void HUD_Weapons(void)
 					break;
 
 				case 3: // weapon name
-					drawstring(weapon_pos, strtolower(self.message), '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+					drawstring(weapon_pos, self.netname, '1 1 0' * 0.5 * weapon_size_y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 					break;
 
 				default: // nothing
@@ -750,20 +786,21 @@ void HUD_Weapons(void)
 			}
 
 			// draw ammo status bar
-			if(autocvar_hud_panel_weapons_ammo && (self.ammo_field != ammo_none))
+			if(autocvar_hud_panel_weapons_ammo && self.weapon != WEP_TUBA && self.weapon != WEP_LASER && self.weapon != WEP_PORTO)
 			{
-				a = getstati(GetAmmoStat(self.ammo_field)); // how much ammo do we have?
+				a = 0;
+				ammo_type = GetAmmoTypeForWep(self.weapon);
+				if(ammo_type != -1)
+					a = getstati(GetAmmoStat(ammo_type)); // how much ammo do we have?
 
 				if(a > 0)
 				{
-					switch(self.ammo_field)
-					{
-						case ammo_shells:  ammo_full = autocvar_hud_panel_weapons_ammo_full_shells;  break;
-						case ammo_nails:   ammo_full = autocvar_hud_panel_weapons_ammo_full_nails;   break;
-						case ammo_rockets: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break;
-						case ammo_cells:   ammo_full = autocvar_hud_panel_weapons_ammo_full_cells;   break;
-						case ammo_plasma:  ammo_full = autocvar_hud_panel_weapons_ammo_full_plasma;  break;
-						case ammo_fuel:    ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel;    break;
+					switch(ammo_type) {
+						case 0: ammo_full = autocvar_hud_panel_weapons_ammo_full_shells; break;
+						case 1: ammo_full = autocvar_hud_panel_weapons_ammo_full_nails; break;
+						case 2: ammo_full = autocvar_hud_panel_weapons_ammo_full_rockets; break;
+						case 3: ammo_full = autocvar_hud_panel_weapons_ammo_full_cells; break;
+						case 4: ammo_full = autocvar_hud_panel_weapons_ammo_full_fuel; break;
 						default: ammo_full = 60;
 					}
 
@@ -771,25 +808,15 @@ void HUD_Weapons(void)
 						weapon_pos_x + baroffset_x,
 						weapon_pos_y + baroffset_y,
 						barsize_x * bound(0, a/ammo_full, 1),
-						barsize_y
-					);
-
-					drawpic_aspect_skin(
-						weapon_pos,
-						"weapon_ammo",
-						weapon_size,
-						ammo_color,
-						ammo_alpha,
-						DRAWFLAG_NORMAL
-					);
-
+						barsize_y);
+					drawpic_aspect_skin(weapon_pos, "weapon_ammo", weapon_size, ammo_color, ammo_alpha, DRAWFLAG_NORMAL);
 					drawresetcliparea();
 				}
 			}
 		}
 		else // draw a "ghost weapon icon" if you don't have the weapon
 		{
-			drawpic_aspect_skin(weapon_pos, self.model2, weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
+			drawpic_aspect_skin(weapon_pos, strcat("weapon", self.netname), weapon_size, '0 0 0', panel_fg_alpha * 0.5, DRAWFLAG_NORMAL);
 		}
 
 		// draw the complain message
@@ -831,6 +858,34 @@ void HUD_Weapons(void)
 }
 
 // Ammo (#1)
+//
+// TODO: macro
+float GetAmmoItemCode(float i)
+{
+	switch(i)
+	{
+		case 0: return IT_SHELLS;
+		case 1: return IT_NAILS;
+		case 2: return IT_ROCKETS;
+		case 3: return IT_CELLS;
+		case 4: return IT_FUEL;
+		default: return -1;
+	}
+}
+
+string GetAmmoPicture(float i)
+{
+	switch(i)
+	{
+		case 0: return "ammo_shells";
+		case 1: return "ammo_bullets";
+		case 2: return "ammo_rockets";
+		case 3: return "ammo_cells";
+		case 4: return "ammo_fuel";
+		default: return "";
+	}
+}
+
 void DrawNadeScoreBar(vector myPos, vector mySize, vector color)
 {
 	
@@ -879,30 +934,16 @@ void DrawAmmoNades(vector myPos, vector mySize, float draw_expanding, float expa
 	}
 }
 
-void DrawAmmoItem(vector myPos, vector mySize, .float ammotype, float currently_selected, float infinite_ammo)
+void DrawAmmoItem(vector myPos, vector mySize, float itemcode, float currently_selected, float infinite_ammo)
 {
-	float a = 0;
-	if(ammotype != ammo_none)
+	float a;
+	if(autocvar__hud_configure)
 	{
-		if(autocvar__hud_configure)
-		{
-			currently_selected = (ammotype == ammo_rockets); //rockets always selected
-			a = 60;
-		}
-		else
-		{
-			// how much ammo do we have of this ammotype?
-			a = getstati(GetAmmoStat(ammotype));
-		}
+		currently_selected = (itemcode == 2); //rockets always selected
+		a = 31 + mod(itemcode*93, 128);
 	}
 	else
-	{
-		#if 0
-		infinite_ammo = TRUE;
-		#else
-		return; // just don't draw infinite ammo at all.
-		#endif
-	}
+		a = getstati(GetAmmoStat(itemcode)); // how much ammo do we have of type itemcode?
 
 	vector color;
 	if(infinite_ammo)
@@ -930,7 +971,7 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammotype, float currently_
 		picpos = myPos;
 	}
 
-	if(currently_selected)
+	if (currently_selected)
 		drawpic_aspect_skin(myPos, "ammo_current_bg", mySize, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
 
     if(a > 0 && autocvar_hud_panel_ammo_progressbar)
@@ -944,9 +985,9 @@ void DrawAmmoItem(vector myPos, vector mySize, .float ammotype, float currently_
             drawstring_aspect(numpos, ftos(a), eX * (2/3) * mySize_x + eY * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL);
     }
 	if(a > 0 || infinite_ammo)
-		drawpic_aspect_skin(picpos, GetAmmoPicture(ammotype), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
+		drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '1 1 1', panel_fg_alpha * theAlpha, DRAWFLAG_NORMAL);
 	else // "ghost" ammo icon
-		drawpic_aspect_skin(picpos, GetAmmoPicture(ammotype), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL);
+		drawpic_aspect_skin(picpos, GetAmmoPicture(itemcode), '1 1 0' * mySize_y, '0 0 0', panel_fg_alpha * theAlpha * 0.5, DRAWFLAG_NORMAL);
 }
 
 float nade_prevstatus;
@@ -982,6 +1023,7 @@ void HUD_Ammo(void)
 	float total_ammo_count;
 
 	vector ammo_size;
+	float AMMO_COUNT = 4;
 	if (autocvar_hud_panel_ammo_onlycurrent)
 		total_ammo_count = 1;
 	else
@@ -1026,24 +1068,31 @@ void HUD_Ammo(void)
 		ammo_size_y = newSize;
 	}
 
-	float i;
-	float infinite_ammo = (getstati(STAT_ITEMS, 0, 24) & IT_UNLIMITED_WEAPON_AMMO);
+	float i, stat_items, currently_selected, infinite_ammo;
+	infinite_ammo = FALSE;
+
 	row = column = 0;
-	if(autocvar_hud_panel_ammo_onlycurrent)
+
+	if (autocvar_hud_panel_ammo_onlycurrent)
 	{
 		if(autocvar__hud_configure)
 		{
-			DrawAmmoItem(pos, ammo_size, ammo_rockets, TRUE, FALSE);
+			DrawAmmoItem(pos, ammo_size, 2, true, FALSE); //show rockets
 		}
 		else
 		{
-			DrawAmmoItem(
-				pos,
-				ammo_size,
-				(get_weaponinfo(switchweapon)).ammo_field,
-				TRUE,
-				infinite_ammo
-			);
+			stat_items = getstati(STAT_ITEMS, 0, 24);
+			if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
+				infinite_ammo = TRUE;
+			for (i = 0; i < AMMO_COUNT; ++i) {
+				currently_selected = stat_items & GetAmmoItemCode(i);
+				if (currently_selected)
+				{
+					DrawAmmoItem(pos, ammo_size, i, true, infinite_ammo);
+					break;
+				}
+			}
+		}
 
 		++row;
 		if(row >= rows)
@@ -1051,23 +1100,15 @@ void HUD_Ammo(void)
 			row = 0;
 			column = column + 1;
 		}
-		}
 	}
 	else
 	{
-		.float ammotype;
-		row = column = 0;
-		for(i = 0; i < AMMO_COUNT; ++i)
-		{
-			ammotype = GetAmmoFieldFromNum(i);
-			DrawAmmoItem(
-				pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y),
-				ammo_size,
-				ammotype,
-				((get_weaponinfo(switchweapon)).ammo_field == ammotype),
-				infinite_ammo
-			);
-
+		stat_items = getstati(STAT_ITEMS, 0, 24);
+		if (stat_items & IT_UNLIMITED_WEAPON_AMMO)
+			infinite_ammo = TRUE;
+		for (i = 0; i < AMMO_COUNT; ++i) {
+			currently_selected = stat_items & GetAmmoItemCode(i);
+			DrawAmmoItem(pos + eX * column * (ammo_size_x + offset_x) + eY * row * (ammo_size_y + offset_y), ammo_size, i, currently_selected, infinite_ammo);
 			++row;
 			if(row >= rows)
 			{
@@ -1750,7 +1791,7 @@ void HUD_Notify(void)
 		{
 			attacker = sprintf(_("Player %d"), count + 1);
 			victim = sprintf(_("Player %d"), count + 2);
-			icon = get_weaponinfo(min(WEP_FIRST + count * 2, WEP_LAST)).model2;
+			icon = strcat("weapon", get_weaponinfo(min(WEP_FIRST + count * 2, WEP_LAST)).netname);
 			alpha = bound(0, 1.2 - count / entry_count, 1);
 		}
 		else
diff --git a/qcsrc/client/particles.qc b/qcsrc/client/particles.qc
index 6c5ceac7f..8751cc0c5 100644
--- a/qcsrc/client/particles.qc
+++ b/qcsrc/client/particles.qc
@@ -225,7 +225,7 @@ void Ent_RainOrSnow()
 		self.draw = Draw_Snow;
 }
 
-void Net_ReadVortexBeamParticle()
+void Net_ReadNexgunBeamParticle()
 {
 	vector shotorg, endpos;
 	float charge;
diff --git a/qcsrc/client/progs.src b/qcsrc/client/progs.src
index 90f445c51..86a8b4339 100644
--- a/qcsrc/client/progs.src
+++ b/qcsrc/client/progs.src
@@ -21,7 +21,8 @@ Defs.qc
 ../common/buffs.qh
 ../common/test.qh
 ../common/counting.qh
-../common/weapons/weapons.qh // TODO
+../common/items.qh
+../common/explosion_equation.qh
 ../common/mapinfo.qh
 ../common/command/markup.qh
 ../common/command/rpn.qh
@@ -58,12 +59,11 @@ vehicles/vehicles.qh
 ../csqcmodellib/common.qh
 ../csqcmodellib/cl_model.qh
 ../csqcmodellib/cl_player.qh
-weapons/projectile.qh // TODO
+projectile.qh
 player_skeleton.qh
 
 sortlist.qc
 miscfunctions.qc
-../server/t_items.qh
 ../server/t_items.qc
 
 teamradar.qc
@@ -78,7 +78,7 @@ rubble.qc
 hook.qc
 particles.qc
 laser.qc
-weapons/projectile.qc // TODO
+projectile.qc
 gibs.qc
 damage.qc
 casings.qc
@@ -112,7 +112,9 @@ noise.qc
 ../common/command/rpn.qc
 ../common/command/generic.qc
 ../common/mapinfo.qc
-../common/weapons/weapons.qc // TODO
+../common/items.qc
+../server/w_all.qc
+../common/explosion_equation.qc
 ../common/urllib.qc
 command/cl_cmd.qc
 
diff --git a/qcsrc/client/projectile.qc b/qcsrc/client/projectile.qc
new file mode 100644
index 000000000..8ff5e0f91
--- /dev/null
+++ b/qcsrc/client/projectile.qc
@@ -0,0 +1,505 @@
+.vector iorigin1, iorigin2;
+.float spawntime;
+.vector trail_oldorigin;
+.float trail_oldtime;
+.float fade_time, fade_rate;
+
+void SUB_Stop()
+{
+	self.move_velocity = self.move_avelocity = '0 0 0';
+	self.move_movetype = MOVETYPE_NONE;
+}
+
+.float alphamod;
+.float count; // set if clientside projectile
+.float cnt; // sound index
+.float gravity;
+.float snd_looping;
+.float silent;
+
+void Projectile_ResetTrail(vector to)
+{
+	self.trail_oldorigin = to;
+	self.trail_oldtime = time;
+}
+
+void Projectile_DrawTrail(vector to)
+{
+	vector from;
+	float t0;
+
+	from = self.trail_oldorigin;
+	t0 = self.trail_oldtime;
+	self.trail_oldorigin = to;
+	self.trail_oldtime = time;
+
+	// force the effect even for stationary firemine
+	if(self.cnt == PROJECTILE_FIREMINE)
+		if(from == to)
+			from_z += 1;
+
+	if (self.traileffect)
+	{
+		particles_alphamin = particles_alphamax = particles_fade = sqrt(self.alpha);
+		boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE | PARTICLES_DRAWASTRAIL);
+	}
+}
+
+void Projectile_Draw()
+{
+	vector rot;
+	vector trailorigin;
+	float f;
+	float drawn;
+	float t;
+	float a;
+
+	f = self.move_flags;
+
+	if(self.count & 0x80)
+	{
+		//self.move_flags &= ~FL_ONGROUND;
+		if(self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY)
+			Movetype_Physics_NoMatchServer();
+			// the trivial movetypes do not have to match the
+			// server's ticrate as they are ticrate independent
+			// NOTE: this assumption is only true if MOVETYPE_FLY
+			// projectiles detonate on impact. If they continue
+			// moving, we might still be ticrate dependent.
+		else
+			Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
+		if(!(self.move_flags & FL_ONGROUND))
+			if(self.velocity != '0 0 0')
+				self.move_angles = self.angles = vectoangles(self.velocity);
+	}
+	else
+	{
+		InterpolateOrigin_Do();
+	}
+
+	if(self.count & 0x80)
+	{
+		drawn = (time >= self.spawntime - 0.02);
+		t = max(time, self.spawntime);
+	}
+	else
+	{
+		drawn = (self.iflags & IFLAG_VALID);
+		t = time;
+	}
+
+	if(!(f & FL_ONGROUND))
+	{
+		rot = '0 0 0';
+		switch(self.cnt)
+		{
+			/*
+			case PROJECTILE_GRENADE:
+				rot = '-2000 0 0'; // forward
+				break;
+			*/
+			case PROJECTILE_GRENADE_BOUNCING:
+				rot = '0 -1000 0'; // sideways
+				break;
+			case PROJECTILE_HOOKBOMB:
+				rot = '1000 0 0'; // forward
+				break;
+			default:
+				break;
+		}
+
+		if(Nade_IDFromProjectile(self.cnt) != 0)
+			rot = self.avelocity;
+
+		self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime)));
+	}
+
+	vector ang;
+	ang = self.angles;
+	ang_x = -ang_x;
+	makevectors(ang);
+
+	a = 1 - (time - self.fade_time) * self.fade_rate;
+	self.alpha = bound(0, self.alphamod * a, 1);
+	if(self.alpha <= 0)
+		drawn = 0;
+	self.renderflags = 0;
+
+	trailorigin = self.origin;
+	switch(self.cnt)
+	{
+		case PROJECTILE_GRENADE:
+		case PROJECTILE_GRENADE_BOUNCING:
+			trailorigin += v_right * 1 + v_forward * -10;
+			break;
+		default:
+			break;
+	}
+
+	if(Nade_IDFromProjectile(self.cnt) != 0)
+		trailorigin += v_up * 4;
+
+	if(drawn)
+		Projectile_DrawTrail(trailorigin);
+	else
+		Projectile_ResetTrail(trailorigin);
+
+	self.drawmask = 0;
+
+	if(!drawn)
+		return;
+
+	switch(self.cnt)
+	{
+		// Possibly add dlights here.
+		default:
+			break;
+	}
+
+	self.drawmask = MASK_NORMAL;
+}
+
+void loopsound(entity e, float ch, string samp, float vol, float attn)
+{
+	if(self.silent)
+		return;
+
+	sound(e, ch, samp, vol, attn);
+	e.snd_looping = ch;
+}
+
+void Ent_RemoveProjectile()
+{
+	if(self.count & 0x80)
+	{
+		tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self);
+		Projectile_DrawTrail(trace_endpos);
+	}
+}
+
+void Ent_Projectile()
+{
+	float f;
+
+	// projectile properties:
+	//   kind (interpolated, or clientside)
+	//
+	//   modelindex
+	//   origin
+	//   scale
+	//   if clientside:
+	//     velocity
+	//     gravity
+	//   soundindex (hardcoded list)
+	//   effects
+	//
+	// projectiles don't send angles, because they always follow the velocity
+
+	f = ReadByte();
+	self.count = (f & 0x80);
+	self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES | IFLAG_ORIGIN;
+	self.solid = SOLID_TRIGGER;
+	//self.effects = EF_NOMODELFLAGS;
+
+	// this should make collisions with bmodels more exact, but it leads to
+	// projectiles no longer being able to lie on a bmodel
+	self.move_nomonsters = MOVE_WORLDONLY;
+	if(f & 0x40)
+		self.move_flags |= FL_ONGROUND;
+	else
+		self.move_flags &= ~FL_ONGROUND;
+
+	if(!self.move_time)
+	{
+		// for some unknown reason, we don't need to care for
+		// sv_gameplayfix_delayprojectiles here.
+		self.move_time = time;
+		self.spawntime = time;
+	}
+	else
+		self.move_time = max(self.move_time, time);
+
+	if(!(self.count & 0x80))
+		InterpolateOrigin_Undo();
+
+	if(f & 1)
+	{
+		self.origin_x = ReadCoord();
+		self.origin_y = ReadCoord();
+		self.origin_z = ReadCoord();
+		setorigin(self, self.origin);
+		if(self.count & 0x80)
+		{
+			self.velocity_x = ReadCoord();
+			self.velocity_y = ReadCoord();
+			self.velocity_z = ReadCoord();
+			if(f & 0x10)
+				self.gravity = ReadCoord();
+			else
+				self.gravity = 0; // none
+			self.move_origin = self.origin;
+			self.move_velocity = self.velocity;
+		}
+
+		if(time == self.spawntime || (self.count & 0x80) || (f & 0x08))
+		{
+			self.trail_oldorigin = self.origin;
+			if(!(self.count & 0x80))
+				InterpolateOrigin_Reset();
+		}
+
+		if(f & 0x20)
+		{
+			self.fade_time = time + ReadByte() * ticrate;
+			self.fade_rate = 1 / (ReadByte() * ticrate);
+		}
+		else
+		{
+			self.fade_time = 0;
+			self.fade_rate = 0;
+		}
+
+		self.team = ReadByte() - 1;
+	}
+
+	if(f & 2)
+	{
+		self.cnt = ReadByte();
+
+		self.silent = (self.cnt & 0x80);
+		self.cnt = (self.cnt & 0x7F);
+
+		self.scale = 1;
+		self.traileffect = 0;
+		switch(self.cnt)
+		{
+			case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
+			case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break;
+			case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
+			case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
+			case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
+			case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
+			case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
+			case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
+			case PROJECTILE_LASER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break;
+			case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break;
+			case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
+			case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
+			case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); break;
+			case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break;
+			case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break;
+			case PROJECTILE_NAPALM_FOUNTAIN: //self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("torch_small"); break;
+			case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough
+			case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough
+			case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break;
+			case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_SEEKER"); break;
+			case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum("TR_SEEKER"); break;
+
+			case PROJECTILE_MAGE_SPIKE: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum("TR_VORESPIKE"); break;
+			case PROJECTILE_SHAMBLER_LIGHTNING: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
+
+			case PROJECTILE_RAPTORBOMB:    setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break;
+			case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3");     self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break;
+			case PROJECTILE_RAPTORCANNON:  setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
+
+			case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum("spiderbot_rocket_thrust"); break;
+			case PROJECTILE_WAKIROCKET:   setmodel(self, "models/vehicles/rocket01.md3");  self.traileffect = particleeffectnum("wakizashi_rocket_thrust"); break;
+			case PROJECTILE_WAKICANNON:   setmodel(self, "models/laser.mdl");  self.traileffect = particleeffectnum(""); break;
+
+			case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
+			case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
+
+			default:
+				if(Nade_IDFromProjectile(self.cnt) != 0) { setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum(Nade_TrailEffect(self.cnt, self.team)); break; }
+				error("Received invalid CSQC projectile, can't work with this!");
+				break;
+		}
+
+		self.mins = '0 0 0';
+		self.maxs = '0 0 0';
+		self.colormod = '0 0 0';
+		self.move_touch = SUB_Stop;
+		self.move_movetype = MOVETYPE_TOSS;
+		self.alphamod = 1;
+
+		switch(self.cnt)
+		{
+			case PROJECTILE_ELECTRO:
+				// only new engines support sound moving with object
+				loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTEN_NORM);
+				self.mins = '0 0 -4';
+				self.maxs = '0 0 -4';
+				self.move_movetype = MOVETYPE_BOUNCE;
+				self.move_touch = func_null;
+				self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
+				self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
+				break;
+			case PROJECTILE_ROCKET:
+				loopsound(self, CH_SHOTS_SINGLE, "weapons/rocket_fly.wav", VOL_BASE, ATTEN_NORM);
+				self.mins = '-3 -3 -3';
+				self.maxs = '3 3 3';
+				break;
+			case PROJECTILE_GRENADE:
+				self.mins = '-3 -3 -3';
+				self.maxs = '3 3 3';
+				break;
+			case PROJECTILE_GRENADE_BOUNCING:
+				self.mins = '-3 -3 -3';
+				self.maxs = '3 3 3';
+				self.move_movetype = MOVETYPE_BOUNCE;
+				self.move_touch = func_null;
+				self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor;
+				self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop;
+				break;
+			case PROJECTILE_SHAMBLER_LIGHTNING:
+				self.mins = '-8 -8 -8';
+				self.maxs = '8 8 8';
+				self.scale = 2.5;
+				self.avelocity = randomvec() * 720;
+				break;
+			case PROJECTILE_MINE:
+				self.mins = '-4 -4 -4';
+				self.maxs = '4 4 4';
+				break;
+			case PROJECTILE_PORTO_RED:
+				self.colormod = '2 1 1';
+				self.alphamod = 0.5;
+				self.move_movetype = MOVETYPE_BOUNCE;
+				self.move_touch = func_null;
+				break;
+			case PROJECTILE_PORTO_BLUE:
+				self.colormod = '1 1 2';
+				self.alphamod = 0.5;
+				self.move_movetype = MOVETYPE_BOUNCE;
+				self.move_touch = func_null;
+				break;
+			case PROJECTILE_HAGAR_BOUNCING:
+				self.move_movetype = MOVETYPE_BOUNCE;
+				self.move_touch = func_null;
+				break;
+			case PROJECTILE_CRYLINK_BOUNCING:
+				self.move_movetype = MOVETYPE_BOUNCE;
+				self.move_touch = func_null;
+				break;
+			case PROJECTILE_NAPALM_FOUNTAIN:
+			case PROJECTILE_FIREBALL:
+				loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly2.wav", VOL_BASE, ATTEN_NORM);
+				self.mins = '-16 -16 -16';
+				self.maxs = '16 16 16';
+				break;
+			case PROJECTILE_FIREMINE:
+				loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly.wav", VOL_BASE, ATTEN_NORM);
+				self.move_movetype = MOVETYPE_BOUNCE;
+				self.move_touch = func_null;
+				self.mins = '-4 -4 -4';
+				self.maxs = '4 4 4';
+				break;
+			case PROJECTILE_TAG:
+				self.mins = '-2 -2 -2';
+				self.maxs = '2 2 2';
+				break;
+			case PROJECTILE_FLAC:
+				self.mins = '-2 -2 -2';
+				self.maxs = '2 2 2';
+				break;
+			case PROJECTILE_SEEKER:
+				loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM);
+				self.mins = '-4 -4 -4';
+				self.maxs = '4 4 4';
+				break;
+            case PROJECTILE_RAPTORBOMB:
+				self.mins = '-3 -3 -3';
+				self.maxs = '3 3 3';
+				break;
+            case PROJECTILE_RAPTORBOMBLET:
+				break;
+            case PROJECTILE_RAPTORCANNON:
+				break;
+            case PROJECTILE_SPIDERROCKET:
+                loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM);
+				break;
+            case PROJECTILE_WAKIROCKET:
+                loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM);
+				break;
+            /*
+            case PROJECTILE_WAKICANNON:
+				break;
+			case PROJECTILE_BUMBLE_GUN:
+				// only new engines support sound moving with object
+				loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTEN_NORM);
+				self.mins = '0 0 -4';
+				self.maxs = '0 0 -4';
+				self.move_movetype = MOVETYPE_BOUNCE;
+				self.move_touch = func_null;
+				self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
+				self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
+				break;
+			*/
+			default:
+				break;
+		}
+
+		if(Nade_IDFromProjectile(self.cnt) != 0)
+		{
+			self.mins = '-16 -16 -16';
+			self.maxs = '16 16 16';
+			self.colormod = Nade_Color(Nade_IDFromProjectile(self.cnt));
+			self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
+			self.move_movetype = MOVETYPE_BOUNCE;
+			self.move_touch = func_null;
+			self.scale = 1.5;
+			self.avelocity = randomvec() * 720;
+			
+			if(Nade_IDFromProjectile(self.cnt) == NADE_TYPE_TRANSLOCATE)
+				self.solid = SOLID_TRIGGER;
+		}
+
+		setsize(self, self.mins, self.maxs);
+	}
+
+	if(self.gravity)
+	{
+		if(self.move_movetype == MOVETYPE_FLY)
+			self.move_movetype = MOVETYPE_TOSS;
+		if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
+			self.move_movetype = MOVETYPE_BOUNCE;
+	}
+	else
+	{
+		if(self.move_movetype == MOVETYPE_TOSS)
+			self.move_movetype = MOVETYPE_FLY;
+		if(self.move_movetype == MOVETYPE_BOUNCE)
+			self.move_movetype = MOVETYPE_BOUNCEMISSILE;
+	}
+
+	if(!(self.count & 0x80))
+		InterpolateOrigin_Note();
+
+	self.draw = Projectile_Draw;
+	self.entremove = Ent_RemoveProjectile;
+}
+
+void Projectile_Precache()
+{
+	precache_model("models/ebomb.mdl");
+	precache_model("models/elaser.mdl");
+	precache_model("models/grenademodel.md3");
+	precache_model("models/mine.md3");
+	precache_model("models/hagarmissile.mdl");
+	precache_model("models/hlac_bullet.md3");
+	precache_model("models/laser.mdl");
+	precache_model("models/plasmatrail.mdl");
+	precache_model("models/rocket.md3");
+	precache_model("models/tagrocket.md3");
+	precache_model("models/tracer.mdl");
+	precache_model("models/sphere/sphere.md3");
+
+	precache_model("models/weapons/v_ok_grenade.md3");
+
+	precache_sound("weapons/electro_fly.wav");
+	precache_sound("weapons/rocket_fly.wav");
+	precache_sound("weapons/fireball_fly.wav");
+	precache_sound("weapons/fireball_fly2.wav");
+	precache_sound("weapons/tag_rocket_fly.wav");
+
+}
diff --git a/qcsrc/client/projectile.qh b/qcsrc/client/projectile.qh
new file mode 100644
index 000000000..70c8ba0df
--- /dev/null
+++ b/qcsrc/client/projectile.qh
@@ -0,0 +1,3 @@
+.float traileffect;
+void Projectile_ResetTrail(vector to);
+void Projectile_DrawTrail(vector to);
diff --git a/qcsrc/client/scoreboard.qc b/qcsrc/client/scoreboard.qc
index 06e29680f..52bf9190b 100644
--- a/qcsrc/client/scoreboard.qc
+++ b/qcsrc/client/scoreboard.qc
@@ -955,7 +955,7 @@ float average_accuracy;
 vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
 {
 	float i;
-	float weapon_cnt = WEP_COUNT - 3; // either vaporizer/nex are hidden, no port-o-launch, no tuba
+	float weapon_cnt = WEP_COUNT - 3; // either minstanex/nex are hidden, no port-o-launch, no tuba
 	float rows;
 	if(autocvar_scoreboard_accuracy_doublerows)
 		rows = 2;
@@ -998,7 +998,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
 	if(rows == 2)
 		pos_x += weapon_width / 2;
 
-	if(switchweapon == WEP_VAPORIZER)
+	if(switchweapon == WEP_MINSTANEX)
 		g_minstagib = 1; // TODO: real detection for minstagib?
 
 	float weapon_stats;
@@ -1012,7 +1012,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
 		self = get_weaponinfo(i);
 		if (!self.weapon)
 			continue;
-		if ((i == WEP_VORTEX && g_minstagib) || i == WEP_PORTO || (i == WEP_VAPORIZER && !g_minstagib) || i == WEP_TUBA) // skip port-o-launch, vortex || vaporizer and tuba
+		if ((i == WEP_NEX && g_minstagib) || i == WEP_PORTO || (i == WEP_MINSTANEX && !g_minstagib) || i == WEP_TUBA) // skip port-o-launch, nex || minstanex and tuba
 			continue;
 		weapon_stats = weapon_accuracy[i-WEP_FIRST];
 
@@ -1023,7 +1023,7 @@ vector HUD_DrawScoreboardAccuracyStats(vector pos, vector rgb, vector bg_size)
 			weapon_alpha = 0.2 * scoreboard_alpha_fg;
 
 		// weapon icon
-		drawpic_aspect_skin(pos, self.model2, '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
+		drawpic_aspect_skin(pos, strcat("weapon", self.netname), '1 0 0' * weapon_width + '0 1 0' * weapon_height, '1 1 1', weapon_alpha, DRAWFLAG_NORMAL);
 		// the accuracy
 		if(weapon_stats >= 0) {
 			weapons_with_stats += 1;
diff --git a/qcsrc/client/waypointsprites.qc b/qcsrc/client/waypointsprites.qc
index c99fc5d51..7ee34672c 100644
--- a/qcsrc/client/waypointsprites.qc
+++ b/qcsrc/client/waypointsprites.qc
@@ -217,20 +217,31 @@ float spritelookupblinkvalue(string s)
 }
 vector spritelookupcolor(string s, vector def)
 {
-	if(substring(s, 0, 4) == "wpn-")
-		return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).wpcolor);
-
 	switch(s)
 	{
 		case "keycarrier-friend": return '0 1 0';
+		case "wpn-laser":         return '1 0.5 0.5';
+		case "wpn-shotgun":       return '0.5 0.25 0';
+		case "wpn-uzi":           return '1 1 0';
+		case "wpn-gl":            return '1 0 0';
+		case "wpn-electro":       return '0 0.5 1';
+		case "wpn-crylink":       return '1 0.5 1';
+		case "wpn-nex":           return '0.5 1 1';
+		case "wpn-hagar":         return '1 1 0.5';
+		case "wpn-rl":            return '1 1 0';
+		case "wpn-porto":         return '0.5 0.5 0.5';
+		case "wpn-minstanex":     return '0.5 1 1';
+		case "wpn-hookgun":       return '0 0.5 0';
+		case "wpn-fireball":      return '1 0.5 0';
+		case "wpn-hlac":          return '0 1 0';
+		case "wpn-campingrifle":  return '0.5 1 0';
+		case "wpn-minelayer":     return '0.75 1 0';
 		default:                  return def;
 	}
 }
 string spritelookuptext(string s)
 {
-	if(substring(s, 0, 4) == "wpn-") { return (get_weaponinfo(stof(substring(s, 4, strlen(s)))).message); }
 	if(substring(s, 0, 5) == "buff-") { return Buff_PrettyName(Buff_Type_FromSprite(s)); }
-
 	switch(s)
 	{
 		case "as-push": return _("Push");
@@ -271,6 +282,22 @@ string spritelookuptext(string s)
 		case "nb-ball": return _("Ball");
 		case "ka-ball": return _("Ball");
 		case "ka-ballcarrier": return _("Ball carrier");
+		case "wpn-laser": return _("Laser");
+		case "wpn-shotgun": return _("Shotgun");
+		case "wpn-uzi": return _("Machine Gun");
+		case "wpn-gl": return _("Mortar");
+		case "wpn-electro": return _("Electro");
+		case "wpn-crylink": return _("Crylink");
+		case "wpn-nex": return _("Nex");
+		case "wpn-hagar": return _("Hagar");
+		case "wpn-rl": return _("Rocket Launcher");
+		case "wpn-porto": return _("Port-O-Launch");
+		case "wpn-minstanex": return _("Minstanex");
+		case "wpn-hookgun": return _("Hook");
+		case "wpn-fireball": return _("Fireball");
+		case "wpn-hlac": return _("HLAC");
+		case "wpn-campingrifle": return _("Rifle");
+		case "wpn-minelayer": return _("Mine Layer");
 		case "dom-neut": return _("Control point");
 		case "dom-red": return _("Control point");
 		case "dom-blue": return _("Control point");
diff --git a/qcsrc/client/weapons/projectile.qc b/qcsrc/client/weapons/projectile.qc
deleted file mode 100644
index 58bd11ee4..000000000
--- a/qcsrc/client/weapons/projectile.qc
+++ /dev/null
@@ -1,505 +0,0 @@
-.vector iorigin1, iorigin2;
-.float spawntime;
-.vector trail_oldorigin;
-.float trail_oldtime;
-.float fade_time, fade_rate;
-
-void SUB_Stop()
-{
-	self.move_velocity = self.move_avelocity = '0 0 0';
-	self.move_movetype = MOVETYPE_NONE;
-}
-
-.float alphamod;
-.float count; // set if clientside projectile
-.float cnt; // sound index
-.float gravity;
-.float snd_looping;
-.float silent;
-
-void Projectile_ResetTrail(vector to)
-{
-	self.trail_oldorigin = to;
-	self.trail_oldtime = time;
-}
-
-void Projectile_DrawTrail(vector to)
-{
-	vector from;
-	float t0;
-
-	from = self.trail_oldorigin;
-	t0 = self.trail_oldtime;
-	self.trail_oldorigin = to;
-	self.trail_oldtime = time;
-
-	// force the effect even for stationary firemine
-	if(self.cnt == PROJECTILE_FIREMINE)
-		if(from == to)
-			from_z += 1;
-
-	if (self.traileffect)
-	{
-		particles_alphamin = particles_alphamax = particles_fade = sqrt(self.alpha);
-		boxparticles(self.traileffect, self, from, to, self.velocity, self.velocity, 1, PARTICLES_USEALPHA | PARTICLES_USEFADE | PARTICLES_DRAWASTRAIL);
-	}
-}
-
-void Projectile_Draw()
-{
-	vector rot;
-	vector trailorigin;
-	float f;
-	float drawn;
-	float t;
-	float a;
-
-	f = self.move_flags;
-
-	if(self.count & 0x80)
-	{
-		//self.move_flags &= ~FL_ONGROUND;
-		if(self.move_movetype == MOVETYPE_NONE || self.move_movetype == MOVETYPE_FLY)
-			Movetype_Physics_NoMatchServer();
-			// the trivial movetypes do not have to match the
-			// server's ticrate as they are ticrate independent
-			// NOTE: this assumption is only true if MOVETYPE_FLY
-			// projectiles detonate on impact. If they continue
-			// moving, we might still be ticrate dependent.
-		else
-			Movetype_Physics_MatchServer(autocvar_cl_projectiles_sloppy);
-		if(!(self.move_flags & FL_ONGROUND))
-			if(self.velocity != '0 0 0')
-				self.move_angles = self.angles = vectoangles(self.velocity);
-	}
-	else
-	{
-		InterpolateOrigin_Do();
-	}
-
-	if(self.count & 0x80)
-	{
-		drawn = (time >= self.spawntime - 0.02);
-		t = max(time, self.spawntime);
-	}
-	else
-	{
-		drawn = (self.iflags & IFLAG_VALID);
-		t = time;
-	}
-
-	if(!(f & FL_ONGROUND))
-	{
-		rot = '0 0 0';
-		switch(self.cnt)
-		{
-			/*
-			case PROJECTILE_GRENADE:
-				rot = '-2000 0 0'; // forward
-				break;
-			*/
-			case PROJECTILE_GRENADE_BOUNCING:
-				rot = '0 -1000 0'; // sideways
-				break;
-			case PROJECTILE_HOOKBOMB:
-				rot = '1000 0 0'; // forward
-				break;
-			default:
-				break;
-		}
-
-		if(Nade_IDFromProjectile(self.cnt) != 0)
-			rot = self.avelocity;
-
-		self.angles = AnglesTransform_ToAngles(AnglesTransform_Multiply(AnglesTransform_FromAngles(self.angles), rot * (t - self.spawntime)));
-	}
-
-	vector ang;
-	ang = self.angles;
-	ang_x = -ang_x;
-	makevectors(ang);
-
-	a = 1 - (time - self.fade_time) * self.fade_rate;
-	self.alpha = bound(0, self.alphamod * a, 1);
-	if(self.alpha <= 0)
-		drawn = 0;
-	self.renderflags = 0;
-
-	trailorigin = self.origin;
-	switch(self.cnt)
-	{
-		case PROJECTILE_GRENADE:
-		case PROJECTILE_GRENADE_BOUNCING:
-			trailorigin += v_right * 1 + v_forward * -10;
-			break;
-		default:
-			break;
-	}
-
-	if(Nade_IDFromProjectile(self.cnt) != 0)
-		trailorigin += v_up * 4;
-
-	if(drawn)
-		Projectile_DrawTrail(trailorigin);
-	else
-		Projectile_ResetTrail(trailorigin);
-
-	self.drawmask = 0;
-
-	if(!drawn)
-		return;
-
-	switch(self.cnt)
-	{
-		// Possibly add dlights here.
-		default:
-			break;
-	}
-
-	self.drawmask = MASK_NORMAL;
-}
-
-void loopsound(entity e, float ch, string samp, float vol, float attn)
-{
-	if(self.silent)
-		return;
-
-	sound(e, ch, samp, vol, attn);
-	e.snd_looping = ch;
-}
-
-void Ent_RemoveProjectile()
-{
-	if(self.count & 0x80)
-	{
-		tracebox(self.origin, self.mins, self.maxs, self.origin + self.velocity * 0.05, MOVE_NORMAL, self);
-		Projectile_DrawTrail(trace_endpos);
-	}
-}
-
-void Ent_Projectile()
-{
-	float f;
-
-	// projectile properties:
-	//   kind (interpolated, or clientside)
-	//
-	//   modelindex
-	//   origin
-	//   scale
-	//   if clientside:
-	//     velocity
-	//     gravity
-	//   soundindex (hardcoded list)
-	//   effects
-	//
-	// projectiles don't send angles, because they always follow the velocity
-
-	f = ReadByte();
-	self.count = (f & 0x80);
-	self.iflags = (self.iflags & IFLAG_INTERNALMASK) | IFLAG_AUTOANGLES | IFLAG_ANGLES | IFLAG_ORIGIN;
-	self.solid = SOLID_TRIGGER;
-	//self.effects = EF_NOMODELFLAGS;
-
-	// this should make collisions with bmodels more exact, but it leads to
-	// projectiles no longer being able to lie on a bmodel
-	self.move_nomonsters = MOVE_WORLDONLY;
-	if(f & 0x40)
-		self.move_flags |= FL_ONGROUND;
-	else
-		self.move_flags &= ~FL_ONGROUND;
-
-	if(!self.move_time)
-	{
-		// for some unknown reason, we don't need to care for
-		// sv_gameplayfix_delayprojectiles here.
-		self.move_time = time;
-		self.spawntime = time;
-	}
-	else
-		self.move_time = max(self.move_time, time);
-
-	if(!(self.count & 0x80))
-		InterpolateOrigin_Undo();
-
-	if(f & 1)
-	{
-		self.origin_x = ReadCoord();
-		self.origin_y = ReadCoord();
-		self.origin_z = ReadCoord();
-		setorigin(self, self.origin);
-		if(self.count & 0x80)
-		{
-			self.velocity_x = ReadCoord();
-			self.velocity_y = ReadCoord();
-			self.velocity_z = ReadCoord();
-			if(f & 0x10)
-				self.gravity = ReadCoord();
-			else
-				self.gravity = 0; // none
-			self.move_origin = self.origin;
-			self.move_velocity = self.velocity;
-		}
-
-		if(time == self.spawntime || (self.count & 0x80) || (f & 0x08))
-		{
-			self.trail_oldorigin = self.origin;
-			if(!(self.count & 0x80))
-				InterpolateOrigin_Reset();
-		}
-
-		if(f & 0x20)
-		{
-			self.fade_time = time + ReadByte() * ticrate;
-			self.fade_rate = 1 / (ReadByte() * ticrate);
-		}
-		else
-		{
-			self.fade_time = 0;
-			self.fade_rate = 0;
-		}
-
-		self.team = ReadByte() - 1;
-	}
-
-	if(f & 2)
-	{
-		self.cnt = ReadByte();
-
-		self.silent = (self.cnt & 0x80);
-		self.cnt = (self.cnt & 0x7F);
-
-		self.scale = 1;
-		self.traileffect = 0;
-		switch(self.cnt)
-		{
-			case PROJECTILE_ELECTRO: setmodel(self, "models/ebomb.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
-			case PROJECTILE_ROCKET: setmodel(self, "models/rocket.md3");self.traileffect = particleeffectnum("TR_ROCKET"); self.scale = 2; break;
-			case PROJECTILE_CRYLINK: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
-			case PROJECTILE_CRYLINK_BOUNCING: setmodel(self, "models/plasmatrail.mdl");self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
-			case PROJECTILE_ELECTRO_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
-			case PROJECTILE_GRENADE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
-			case PROJECTILE_GRENADE_BOUNCING: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
-			case PROJECTILE_MINE: setmodel(self, "models/mine.md3");self.traileffect = particleeffectnum("TR_GRENADE"); break;
-			case PROJECTILE_BLASTER: setmodel(self, "models/laser.mdl");self.traileffect = particleeffectnum(""); break;
-			case PROJECTILE_HLAC: setmodel(self, "models/hlac_bullet.md3");self.traileffect = particleeffectnum(""); break;
-			case PROJECTILE_PORTO_RED: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
-			case PROJECTILE_PORTO_BLUE: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_WIZSPIKE"); self.scale = 4; break;
-			case PROJECTILE_HOOKBOMB: setmodel(self, "models/grenademodel.md3");self.traileffect = particleeffectnum("TR_KNIGHTSPIKE"); break;
-			case PROJECTILE_HAGAR: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break;
-			case PROJECTILE_HAGAR_BOUNCING: setmodel(self, "models/hagarmissile.mdl");self.traileffect = particleeffectnum("tr_hagar"); self.scale = 0.75; break;
-			case PROJECTILE_NAPALM_FOUNTAIN: //self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("torch_small"); break;
-			case PROJECTILE_FIREBALL: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("fireball"); break; // particle effect is good enough
-			case PROJECTILE_FIREMINE: self.model = ""; self.modelindex = 0; self.traileffect = particleeffectnum("firemine"); break; // particle effect is good enough
-			case PROJECTILE_TAG: setmodel(self, "models/laser.mdl"); self.traileffect = particleeffectnum("TR_ROCKET"); break;
-			case PROJECTILE_FLAC: setmodel(self, "models/hagarmissile.mdl"); self.scale = 0.4; self.traileffect = particleeffectnum("TR_SEEKER"); break;
-			case PROJECTILE_SEEKER: setmodel(self, "models/tagrocket.md3"); self.traileffect = particleeffectnum("TR_SEEKER"); break;
-
-			case PROJECTILE_MAGE_SPIKE: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum("TR_VORESPIKE"); break;
-			case PROJECTILE_SHAMBLER_LIGHTNING: setmodel(self, "models/ebomb.mdl"); self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
-
-			case PROJECTILE_RAPTORBOMB:    setmodel(self, "models/vehicles/clusterbomb.md3"); self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break;
-			case PROJECTILE_RAPTORBOMBLET: setmodel(self, "models/vehicles/bomblet.md3");     self.gravity = 1; self.avelocity = '0 0 180'; self.traileffect = particleeffectnum(""); break;
-			case PROJECTILE_RAPTORCANNON:  setmodel(self, "models/plasmatrail.mdl"); self.traileffect = particleeffectnum("TR_CRYLINKPLASMA"); break;
-
-			case PROJECTILE_SPIDERROCKET: setmodel(self, "models/vehicles/rocket02.md3"); self.traileffect = particleeffectnum("spiderbot_rocket_thrust"); break;
-			case PROJECTILE_WAKIROCKET:   setmodel(self, "models/vehicles/rocket01.md3");  self.traileffect = particleeffectnum("wakizashi_rocket_thrust"); break;
-			case PROJECTILE_WAKICANNON:   setmodel(self, "models/laser.mdl");  self.traileffect = particleeffectnum(""); break;
-
-			case PROJECTILE_BUMBLE_GUN: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
-			case PROJECTILE_BUMBLE_BEAM: setmodel(self, "models/elaser.mdl");self.traileffect = particleeffectnum("TR_NEXUIZPLASMA"); break;
-
-			default:
-				if(Nade_IDFromProjectile(self.cnt) != 0) { setmodel(self, "models/weapons/v_ok_grenade.md3");self.traileffect = particleeffectnum(Nade_TrailEffect(self.cnt, self.team)); break; }
-				error("Received invalid CSQC projectile, can't work with this!");
-				break;
-		}
-
-		self.mins = '0 0 0';
-		self.maxs = '0 0 0';
-		self.colormod = '0 0 0';
-		self.move_touch = SUB_Stop;
-		self.move_movetype = MOVETYPE_TOSS;
-		self.alphamod = 1;
-
-		switch(self.cnt)
-		{
-			case PROJECTILE_ELECTRO:
-				// only new engines support sound moving with object
-				loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTEN_NORM);
-				self.mins = '0 0 -4';
-				self.maxs = '0 0 -4';
-				self.move_movetype = MOVETYPE_BOUNCE;
-				self.move_touch = func_null;
-				self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
-				self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
-				break;
-			case PROJECTILE_ROCKET:
-				loopsound(self, CH_SHOTS_SINGLE, "weapons/rocket_fly.wav", VOL_BASE, ATTEN_NORM);
-				self.mins = '-3 -3 -3';
-				self.maxs = '3 3 3';
-				break;
-			case PROJECTILE_GRENADE:
-				self.mins = '-3 -3 -3';
-				self.maxs = '3 3 3';
-				break;
-			case PROJECTILE_GRENADE_BOUNCING:
-				self.mins = '-3 -3 -3';
-				self.maxs = '3 3 3';
-				self.move_movetype = MOVETYPE_BOUNCE;
-				self.move_touch = func_null;
-				self.move_bounce_factor = g_balance_grenadelauncher_bouncefactor;
-				self.move_bounce_stopspeed = g_balance_grenadelauncher_bouncestop;
-				break;
-			case PROJECTILE_SHAMBLER_LIGHTNING:
-				self.mins = '-8 -8 -8';
-				self.maxs = '8 8 8';
-				self.scale = 2.5;
-				self.avelocity = randomvec() * 720;
-				break;
-			case PROJECTILE_MINE:
-				self.mins = '-4 -4 -4';
-				self.maxs = '4 4 4';
-				break;
-			case PROJECTILE_PORTO_RED:
-				self.colormod = '2 1 1';
-				self.alphamod = 0.5;
-				self.move_movetype = MOVETYPE_BOUNCE;
-				self.move_touch = func_null;
-				break;
-			case PROJECTILE_PORTO_BLUE:
-				self.colormod = '1 1 2';
-				self.alphamod = 0.5;
-				self.move_movetype = MOVETYPE_BOUNCE;
-				self.move_touch = func_null;
-				break;
-			case PROJECTILE_HAGAR_BOUNCING:
-				self.move_movetype = MOVETYPE_BOUNCE;
-				self.move_touch = func_null;
-				break;
-			case PROJECTILE_CRYLINK_BOUNCING:
-				self.move_movetype = MOVETYPE_BOUNCE;
-				self.move_touch = func_null;
-				break;
-			case PROJECTILE_NAPALM_FOUNTAIN:
-			case PROJECTILE_FIREBALL:
-				loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly2.wav", VOL_BASE, ATTEN_NORM);
-				self.mins = '-16 -16 -16';
-				self.maxs = '16 16 16';
-				break;
-			case PROJECTILE_FIREMINE:
-				loopsound(self, CH_SHOTS_SINGLE, "weapons/fireball_fly.wav", VOL_BASE, ATTEN_NORM);
-				self.move_movetype = MOVETYPE_BOUNCE;
-				self.move_touch = func_null;
-				self.mins = '-4 -4 -4';
-				self.maxs = '4 4 4';
-				break;
-			case PROJECTILE_TAG:
-				self.mins = '-2 -2 -2';
-				self.maxs = '2 2 2';
-				break;
-			case PROJECTILE_FLAC:
-				self.mins = '-2 -2 -2';
-				self.maxs = '2 2 2';
-				break;
-			case PROJECTILE_SEEKER:
-				loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM);
-				self.mins = '-4 -4 -4';
-				self.maxs = '4 4 4';
-				break;
-            case PROJECTILE_RAPTORBOMB:
-				self.mins = '-3 -3 -3';
-				self.maxs = '3 3 3';
-				break;
-            case PROJECTILE_RAPTORBOMBLET:
-				break;
-            case PROJECTILE_RAPTORCANNON:
-				break;
-            case PROJECTILE_SPIDERROCKET:
-                loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM);
-				break;
-            case PROJECTILE_WAKIROCKET:
-                loopsound(self, CH_SHOTS_SINGLE, "weapons/tag_rocket_fly.wav", VOL_BASE, ATTEN_NORM);
-				break;
-            /*
-            case PROJECTILE_WAKICANNON:
-				break;
-			case PROJECTILE_BUMBLE_GUN:
-				// only new engines support sound moving with object
-				loopsound(self, CH_SHOTS_SINGLE, "weapons/electro_fly.wav", VOL_BASE, ATTEN_NORM);
-				self.mins = '0 0 -4';
-				self.maxs = '0 0 -4';
-				self.move_movetype = MOVETYPE_BOUNCE;
-				self.move_touch = func_null;
-				self.move_bounce_factor = g_balance_electro_secondary_bouncefactor;
-				self.move_bounce_stopspeed = g_balance_electro_secondary_bouncestop;
-				break;
-			*/
-			default:
-				break;
-		}
-
-		if(Nade_IDFromProjectile(self.cnt) != 0)
-		{
-			self.mins = '-16 -16 -16';
-			self.maxs = '16 16 16';
-			self.colormod = Nade_Color(Nade_IDFromProjectile(self.cnt));
-			self.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
-			self.move_movetype = MOVETYPE_BOUNCE;
-			self.move_touch = func_null;
-			self.scale = 1.5;
-			self.avelocity = randomvec() * 720;
-			
-			if(Nade_IDFromProjectile(self.cnt) == NADE_TYPE_TRANSLOCATE)
-				self.solid = SOLID_TRIGGER;
-		}
-
-		setsize(self, self.mins, self.maxs);
-	}
-
-	if(self.gravity)
-	{
-		if(self.move_movetype == MOVETYPE_FLY)
-			self.move_movetype = MOVETYPE_TOSS;
-		if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
-			self.move_movetype = MOVETYPE_BOUNCE;
-	}
-	else
-	{
-		if(self.move_movetype == MOVETYPE_TOSS)
-			self.move_movetype = MOVETYPE_FLY;
-		if(self.move_movetype == MOVETYPE_BOUNCE)
-			self.move_movetype = MOVETYPE_BOUNCEMISSILE;
-	}
-
-	if(!(self.count & 0x80))
-		InterpolateOrigin_Note();
-
-	self.draw = Projectile_Draw;
-	self.entremove = Ent_RemoveProjectile;
-}
-
-void Projectile_Precache()
-{
-	precache_model("models/ebomb.mdl");
-	precache_model("models/elaser.mdl");
-	precache_model("models/grenademodel.md3");
-	precache_model("models/mine.md3");
-	precache_model("models/hagarmissile.mdl");
-	precache_model("models/hlac_bullet.md3");
-	precache_model("models/laser.mdl");
-	precache_model("models/plasmatrail.mdl");
-	precache_model("models/rocket.md3");
-	precache_model("models/tagrocket.md3");
-	precache_model("models/tracer.mdl");
-	precache_model("models/sphere/sphere.md3");
-
-	precache_model("models/weapons/v_ok_grenade.md3");
-
-	precache_sound("weapons/electro_fly.wav");
-	precache_sound("weapons/rocket_fly.wav");
-	precache_sound("weapons/fireball_fly.wav");
-	precache_sound("weapons/fireball_fly2.wav");
-	precache_sound("weapons/tag_rocket_fly.wav");
-
-}
diff --git a/qcsrc/client/weapons/projectile.qh b/qcsrc/client/weapons/projectile.qh
deleted file mode 100644
index 70c8ba0df..000000000
--- a/qcsrc/client/weapons/projectile.qh
+++ /dev/null
@@ -1,3 +0,0 @@
-.float traileffect;
-void Projectile_ResetTrail(vector to);
-void Projectile_DrawTrail(vector to);
diff --git a/qcsrc/common/command/generic.qc b/qcsrc/common/command/generic.qc
index 3f87609ee..08b0b69dd 100644
--- a/qcsrc/common/command/generic.qc
+++ b/qcsrc/common/command/generic.qc
@@ -239,12 +239,12 @@ void GenericCommand_dumpnotifs(float request)
 
 			if(filename == "")
 			{
-				filename = "notifications_dump.cfg";
+				filename = "notifications.cfg";
 				alsoprint = FALSE;
 			}
 			else if(filename == "-")
 			{
-				filename = "notifications_dump.cfg";
+				filename = "notifications.cfg";
 				alsoprint = TRUE;
 			}
 			fh = fopen(filename, FILE_WRITE);
@@ -269,60 +269,7 @@ void GenericCommand_dumpnotifs(float request)
 		case CMD_REQUEST_USAGE:
 		{
 			print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpnotifs [filename]"));
-			print("  Where 'filename' is the file to write (default is notifications_dump.cfg),\n");
-			print("  if supplied with '-' output to console as well as default,\n");
-			print("  if left blank, it will only write to default.\n");
-			return;
-		}
-	}
-}
-
-void GenericCommand_dumpweapons(float request) // WEAPONTODO: make this work with other progs than just server
-{
-	switch(request)
-	{
-		case CMD_REQUEST_COMMAND:
-		{
-			#ifdef SVQC
-			wep_config_file = -1;
-			wep_config_alsoprint = -1;
-			string filename = argv(1);
-			
-			if(filename == "")
-			{
-				filename = "weapons_dump.cfg";
-				wep_config_alsoprint = FALSE;
-			}
-			else if(filename == "-")
-			{
-				filename = "weapons_dump.cfg";
-				wep_config_alsoprint = TRUE;
-			}
-			wep_config_file = fopen(filename, FILE_WRITE);
-			
-			if(wep_config_file >= 0)
-			{
-				Dump_Weapon_Settings();
-				print(sprintf("Dumping weapons... File located in ^2data/data/%s^7.\n", filename));
-				fclose(wep_config_file);
-				wep_config_file = -1;
-				wep_config_alsoprint = -1;
-			}
-			else
-			{
-				print(sprintf("^1Error: ^7Could not open file '%s'!\n", filename));
-			}
-			#else
-			print(_("Weapons dump command only works with sv_cmd.\n"));
-			#endif
-			return;
-		}
-			
-		default:
-		case CMD_REQUEST_USAGE:
-		{
-			print(strcat("\nUsage:^3 ", GetProgramCommandPrefix(), " dumpweapons [filename]"));
-			print("  Where 'filename' is the file to write (default is weapons_dump.cfg),\n");
+			print("  Where 'filename' is the file to write (default is notifications.cfg),\n");
 			print("  if supplied with '-' output to console as well as default,\n");
 			print("  if left blank, it will only write to default.\n");
 			return;
@@ -638,7 +585,6 @@ void GenericCommand_(float request)
 	GENERIC_COMMAND("addtolist", GenericCommand_addtolist(request, arguments), "Add a string to a cvar") \
 	GENERIC_COMMAND("dumpcommands", GenericCommand_dumpcommands(request), "Dump all commands on the program to *_cmd_dump.txt") \
 	GENERIC_COMMAND("dumpnotifs", GenericCommand_dumpnotifs(request), "Dump all notifications into notifications_dump.txt") \
-	GENERIC_COMMAND("dumpweapons", GenericCommand_dumpweapons(request), "Dump all weapons into weapons_dump.txt") \
 	GENERIC_COMMAND("maplist", GenericCommand_maplist(request, arguments), "Automatic control of maplist") \
 	GENERIC_COMMAND("nextframe", GenericCommand_nextframe(request, arguments, command), "Execute the given command next frame of this VM") \
 	GENERIC_COMMAND("qc_curl", GenericCommand_qc_curl(request, arguments), "Queries a URL") \
diff --git a/qcsrc/common/constants.qh b/qcsrc/common/constants.qh
index 2d0c83a49..fb6d781c0 100644
--- a/qcsrc/common/constants.qh
+++ b/qcsrc/common/constants.qh
@@ -30,18 +30,17 @@ const float AS_FLOAT = 8;
 
 const float TE_CSQC_PICTURE = 100;
 const float TE_CSQC_RACE = 101;
-const float TE_CSQC_VORTEXBEAMPARTICLE = 103;
-const float TE_CSQC_ARC = 104;
+const float TE_CSQC_NEXGUNBEAMPARTICLE = 103;
+const float TE_CSQC_LIGHTNINGARC = 104;
 const float TE_CSQC_TEAMNAGGER = 105;
 const float TE_CSQC_PINGPLREPORT = 106;
 const float TE_CSQC_TARGET_MUSIC = 107;
 const float TE_CSQC_WEAPONCOMPLAIN = 108;
-const float TE_CSQC_VORTEX_SCOPE = 109;
+const float TE_CSQC_NEX_SCOPE = 109;
 const float TE_CSQC_MINELAYER_MAXMINES = 110;
 const float TE_CSQC_HAGAR_MAXROCKETS = 111;
 const float TE_CSQC_VEHICLESETUP = 112;
 const float TE_CSQC_SVNOTICE = 113;
-const float TE_CSQC_SHOCKWAVEPARTICLE = 114;
 
 const float RACE_NET_CHECKPOINT_HIT_QUALIFYING = 0; // byte checkpoint, short time, short recordtime, string recordholder
 const float RACE_NET_CHECKPOINT_CLEAR = 1;
@@ -86,7 +85,8 @@ const float ENT_CLIENT_WARPZONE = 24;
 const float ENT_CLIENT_WARPZONE_CAMERA = 25;
 const float ENT_CLIENT_TRIGGER_MUSIC = 26;
 const float ENT_CLIENT_HOOK = 27;
-const float ENT_CLIENT_ARC_BEAM = 29; // WEAPONTODO: fix numbers
+const float ENT_CLIENT_LGBEAM = 28;
+const float ENT_CLIENT_GAUNTLET = 29;
 const float ENT_CLIENT_ACCURACY = 30;
 const float ENT_CLIENT_SHOWNAMES = 31;
 const float ENT_CLIENT_WARPZONE_TELEPORTED = 32;
@@ -238,7 +238,7 @@ const float ATTEN_MAX = 3.984375;
 #define VOL_BASE 0.7
 #define VOL_BASEVOICE 1.0
 
-// WEAPONTODO: move this into separate/new projectile handling code // this sets sounds and other properties of the projectiles in csqc
+// this sets sounds and other properties of the projectiles in csqc
 const float PROJECTILE_ELECTRO = 1;
 const float PROJECTILE_ROCKET = 2;
 const float PROJECTILE_TAG = 3;
@@ -247,7 +247,7 @@ const float PROJECTILE_ELECTRO_BEAM = 6;
 const float PROJECTILE_GRENADE = 7;
 const float PROJECTILE_GRENADE_BOUNCING = 8;
 const float PROJECTILE_MINE = 9;
-const float PROJECTILE_BLASTER = 10;
+const float PROJECTILE_LASER = 10;
 const float PROJECTILE_HLAC = 11;
 const float PROJECTILE_SEEKER = 12;
 const float PROJECTILE_FLAC = 13;
@@ -292,6 +292,25 @@ const float WATERLEVEL_NONE = 0;
 const float WATERLEVEL_WETFEET = 1;
 const float WATERLEVEL_SWIMMING = 2;
 const float WATERLEVEL_SUBMERGED = 3;
+
+const float MAX_SHOT_DISTANCE = 32768;
+
+// weapon requests
+const float WR_SETUP = 1; // (SVQC) setup weapon data
+const float WR_THINK = 2; // (SVQC) logic to run every frame
+const float WR_CHECKAMMO1 = 3; // (SVQC) checks ammo for weapon
+const float WR_CHECKAMMO2 = 4; // (SVQC) checks ammo for weapon
+const float WR_AIM = 5; // (SVQC) runs bot aiming code for this weapon
+const float WR_PRECACHE = 6; // (CSQC and SVQC) precaches models/sounds used by this weapon
+const float WR_SUICIDEMESSAGE = 7; // (SVQC) notification number for suicide message (may inspect w_deathtype for details)
+const float WR_KILLMESSAGE = 8; // (SVQC) notification number for kill message (may inspect w_deathtype for details)
+const float WR_RELOAD = 9; // (SVQC) does not need to do anything
+const float WR_RESETPLAYER = 10; // (SVQC) does not need to do anything
+const float WR_IMPACTEFFECT = 11; // (CSQC) impact effect
+const float WR_SWITCHABLE = 12; // (CSQC) impact effect
+const float WR_PLAYERDEATH = 13; // (SVQC) does not need to do anything
+const float WR_GONETHINK = 14; // (SVQC) logic to run every frame, also if no longer having the weapon as long as the switch away has not been performed
+
 #define SERVERFLAG_ALLOW_FULLBRIGHT 1
 #define SERVERFLAG_TEAMPLAY 2
 #define SERVERFLAG_PLAYERSTATS 4
diff --git a/qcsrc/common/explosion_equation.qc b/qcsrc/common/explosion_equation.qc
new file mode 100644
index 000000000..3fddd70d2
--- /dev/null
+++ b/qcsrc/common/explosion_equation.qc
@@ -0,0 +1,62 @@
+float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v)
+{
+	float a;
+	a  = explosion_v * (explosion_v - target_v);
+
+	if(a <= 0)
+		// target is too fast to be hittable by this
+		return 0;
+
+	a /= (explosion_v * explosion_v);
+		// we know we can divide by this, or above a would be == 0
+
+	return a;
+}
+
+#if 0
+vector explosion_calcpush(vector explosion_v, float explosion_m, vector target_v, float target_m, float elasticity)
+{
+	// solution of the equations:
+	//    v'                = v + a vp             // central hit
+	//    m*v'   + mp*vp'   = m*v + mp*vp          // conservation of momentum
+	//    m*v'^2 + mp*vp'^2 = m*v^2 + mp*vp^2      // conservation of energy (ELASTIC hit)
+	// -> a = 0                                    // case 1: did not hit
+	// -> a = 2*mp*(vp^2 - vp.v) / ((m+mp) * vp^2) // case 2: did hit
+	//                                             // non-elastic hits are somewhere between these two
+
+	// this would be physically correct, but we don't do that
+	return explosion_v * explosion_calcpush_getmultiplier(explosion_v, target_v) * (
+		(1 + elasticity) * (
+			explosion_m
+		) / (
+			target_m + explosion_m
+		)
+	); // note: this factor is at least 0, at most 2
+}
+#endif
+
+// simplified formula, tuned so that if the target has velocity 0, we get exactly the original force
+vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor)
+{
+	// if below 1, the formulas make no sense (and would cause superjumps)
+	if(speedfactor < 1)
+		return explosion_f;
+
+#if 0
+	float m;
+	// find m so that
+	//   speedfactor * (1 + e) * m / (1 + m) == 1
+	m = 1 / ((1 + 0) * speedfactor - 1);
+	vector v;
+	v = explosion_calcpush(explosion_f * speedfactor, m, target_v, 1, 0);
+	// the factor we then get is:
+	//   1
+	printf("MASS: %f\nv: %v -> %v\nENERGY BEFORE == %f + %f = %f\nENERGY AFTER >= %f\n",
+		m,
+		target_v, target_v + v,
+		target_v * target_v, m * explosion_f * speedfactor * explosion_f * speedfactor, target_v * target_v + m * explosion_f * speedfactor * explosion_f * speedfactor,
+		(target_v + v) * (target_v + v));
+	return v;
+#endif
+	return explosion_f * explosion_calcpush_getmultiplier(explosion_f * speedfactor, target_v);
+}
diff --git a/qcsrc/common/explosion_equation.qh b/qcsrc/common/explosion_equation.qh
new file mode 100644
index 000000000..c8630cdb1
--- /dev/null
+++ b/qcsrc/common/explosion_equation.qh
@@ -0,0 +1 @@
+vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor);
diff --git a/qcsrc/common/items.qc b/qcsrc/common/items.qc
new file mode 100644
index 000000000..19173079f
--- /dev/null
+++ b/qcsrc/common/items.qc
@@ -0,0 +1,251 @@
+// WEAPON PLUGIN SYSTEM
+entity weapon_info[WEP_MAXCOUNT];
+entity dummy_weapon_info;
+
+#if WEP_MAXCOUNT > 72
+# error Kein Weltraum links auf dem Gerät
+#endif
+
+WepSet WepSet_FromWeapon(float a) {
+	a -= WEP_FIRST;
+#if WEP_MAXCOUNT > 24
+	if(a >= 24) {
+		a -= 24;
+#if WEP_MAXCOUNT > 48
+		if(a >= 24) {
+			a -= 24;
+			return '0 0 1' * power2of(a);
+		}
+#endif
+		return '0 1 0' * power2of(a);
+	}
+#endif
+	return '1 0 0' * power2of(a);
+}
+#ifdef SVQC
+void WepSet_AddStat()
+{
+	addstat(STAT_WEAPONS, AS_INT, weapons_x);
+#if WEP_MAXCOUNT > 24
+	addstat(STAT_WEAPONS2, AS_INT, weapons_y);
+#if WEP_MAXCOUNT > 48
+	addstat(STAT_WEAPONS3, AS_INT, weapons_z);
+#endif
+#endif
+}
+void WriteWepSet(float dst, WepSet w)
+{
+#if WEP_MAXCOUNT > 48
+	WriteInt72_t(dst, w);
+#elif WEP_MAXCOUNT > 24
+	WriteInt48_t(dst, w);
+#else
+	WriteInt24_t(dst, w_x);
+#endif
+}
+#endif
+#ifdef CSQC
+WepSet WepSet_GetFromStat()
+{
+	WepSet w = '0 0 0';
+	w_x = getstati(STAT_WEAPONS);
+#if WEP_MAXCOUNT > 24
+	w_y = getstati(STAT_WEAPONS2);
+#if WEP_MAXCOUNT > 48
+	w_z = getstati(STAT_WEAPONS3);
+#endif
+#endif
+	return w;
+}
+WepSet ReadWepSet()
+{
+#if WEP_MAXCOUNT > 48
+	return ReadInt72_t();
+#elif WEP_MAXCOUNT > 24
+	return ReadInt48_t();
+#else
+	return ReadInt24_t() * '1 0 0';
+#endif
+}
+#endif
+
+void register_weapon(float id, WepSet bit, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname)
+{
+	entity e;
+	weapon_info[id - 1] = e = spawn();
+	e.classname = "weapon_info";
+	e.weapon = id;
+	e.weapons = bit;
+	e.netname = shortname;
+	e.message = wname;
+	e.items = ammotype;
+	e.weapon_func = func;
+	e.mdl = modelname;
+	e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
+	e.spawnflags = weapontype;
+	e.model2 = strzone(strcat("wpn-", e.mdl));
+	e.impulse = i;
+	e.bot_pickupbasevalue = pickupbasevalue;
+	if(ammotype & IT_SHELLS)
+		e.ammo_field = ammo_shells;
+	else if(ammotype & IT_NAILS)
+		e.ammo_field = ammo_nails;
+	else if(ammotype & IT_ROCKETS)
+		e.ammo_field = ammo_rockets;
+	else if(ammotype & IT_CELLS)
+		e.ammo_field = ammo_cells;
+	else if(ammotype & IT_FUEL)
+		e.ammo_field = ammo_fuel;
+	else
+		e.ammo_field = ammo_batteries;
+}
+float w_null(float dummy)
+{
+	return 0;
+}
+void register_weapons_done()
+{
+	dummy_weapon_info = spawn();
+	dummy_weapon_info.classname = "weapon_info";
+	dummy_weapon_info.weapon = 0; // you can recognize dummies by this
+	dummy_weapon_info.weapons = '0 0 0';
+	dummy_weapon_info.netname = "";
+	dummy_weapon_info.message = "AOL CD Thrower";
+	dummy_weapon_info.items = 0;
+	dummy_weapon_info.weapon_func = w_null;
+	dummy_weapon_info.mdl = "";
+	dummy_weapon_info.model = "";
+	dummy_weapon_info.spawnflags = 0;
+	dummy_weapon_info.model2 = "";
+	dummy_weapon_info.impulse = -1;
+	dummy_weapon_info.bot_pickupbasevalue = 0;
+
+	float i;
+	weaponorder_byid = "";
+	for(i = WEP_MAXCOUNT; i >= 1; --i)
+		if(weapon_info[i-1])
+			weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
+	weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
+}
+entity get_weaponinfo(float id)
+{
+	entity w;
+	if(id < WEP_FIRST || id > WEP_LAST)
+		return dummy_weapon_info;
+	w = weapon_info[id - 1];
+	if(w)
+		return w;
+	return dummy_weapon_info;
+}
+string W_FixWeaponOrder(string order, float complete)
+{
+	return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
+}
+string W_NameWeaponOrder_MapFunc(string s)
+{
+	entity wi;
+	if(s == "0" || stof(s))
+	{
+		wi = get_weaponinfo(stof(s));
+		if(wi != dummy_weapon_info)
+			return wi.netname;
+	}
+	return s;
+}
+string W_NameWeaponOrder(string order)
+{
+	return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
+}
+string W_NumberWeaponOrder_MapFunc(string s)
+{
+	float i;
+	if(s == "0" || stof(s))
+		return s;
+	for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+		if(s == get_weaponinfo(i).netname)
+			return ftos(i);
+	return s;
+}
+string W_NumberWeaponOrder(string order)
+{
+	return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
+}
+
+float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
+string W_FixWeaponOrder_BuildImpulseList_order;
+void W_FixWeaponOrder_BuildImpulseList_swap(float i, float j, entity pass)
+{
+	float h;
+	h = W_FixWeaponOrder_BuildImpulseList_buf[i];
+	W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
+	W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
+}
+float W_FixWeaponOrder_BuildImpulseList_cmp(float i, float j, entity pass)
+{
+	entity e1, e2;
+	float d;
+	e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
+	e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
+	d = mod(e1.impulse + 9, 10) - mod(e2.impulse + 9, 10);
+	if(d != 0)
+		return -d; // high impulse first!
+	return
+		strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
+		-
+		strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
+		; // low char index first!
+}
+string W_FixWeaponOrder_BuildImpulseList(string o)
+{
+	float i;
+	W_FixWeaponOrder_BuildImpulseList_order = o;
+	for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+		W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
+	heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
+	o = "";
+	for(i = WEP_FIRST; i <= WEP_LAST; ++i)
+		o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
+	W_FixWeaponOrder_BuildImpulseList_order = string_null;
+	return substring(o, 1, -1);
+}
+
+string W_FixWeaponOrder_AllowIncomplete(string order)
+{
+	return W_FixWeaponOrder(order, 0);
+}
+
+string W_FixWeaponOrder_ForceComplete(string order)
+{
+	if(order == "")
+		order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
+	return W_FixWeaponOrder(order, 1);
+}
+
+void W_RandomWeapons(entity e, float n)
+{
+	float i, j;
+	WepSet remaining;
+	WepSet result;
+	remaining = e.weapons;
+	result = '0 0 0';
+	for(i = 0; i < n; ++i)
+	{
+		RandomSelection_Init();
+		for(j = WEP_FIRST; j <= WEP_LAST; ++j)
+			if(remaining & WepSet_FromWeapon(j))
+				RandomSelection_Add(world, j, string_null, 1, 1);
+		result |= WepSet_FromWeapon(RandomSelection_chosen_float);
+		remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
+	}
+	e.weapons = result;
+}
+
+string W_Name(float weaponid)
+{
+	return (get_weaponinfo(weaponid)).message;
+}
+
+float W_AmmoItemCode(float wpn)
+{
+	return (get_weaponinfo(wpn)).items & IT_AMMO;
+}
diff --git a/qcsrc/common/items.qh b/qcsrc/common/items.qh
new file mode 100644
index 000000000..264c9ca73
--- /dev/null
+++ b/qcsrc/common/items.qh
@@ -0,0 +1,151 @@
+const float BOT_PICKUP_RATING_LOW	= 2500;
+const float BOT_PICKUP_RATING_MID	= 5000;
+const float BOT_PICKUP_RATING_HIGH	= 10000;
+
+const float WEP_TYPE_OTHER	      =  0x00; // not for damaging people
+const float WEP_TYPE_SPLASH	      =  0x01; // splash damage
+const float WEP_TYPE_HITSCAN	      =  0x02; // hitscan
+const float WEP_TYPEMASK            =  0x0F;
+const float WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
+const float WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
+const float WEP_FLAG_HIDDEN         =  0x40; // hides from menu
+const float WEP_FLAG_RELOADABLE     =  0x80; // can has reload
+const float WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
+const float WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
+
+const float	IT_UNLIMITED_WEAPON_AMMO     = 1;
+// when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
+const float	IT_UNLIMITED_SUPERWEAPONS    = 2;
+// when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
+const float   IT_CTF_SHIELDED              = 4; // set for the flag shield
+const float   IT_USING_JETPACK             = 8; // confirmation that button is pressed
+const float   IT_JETPACK                   = 16; // actual item
+const float   IT_FUEL_REGEN                = 32; // fuel regeneration trigger
+WANT_CONST float   IT_SHELLS                    = 256;
+WANT_CONST float   IT_NAILS                     = 512;
+WANT_CONST float   IT_ROCKETS                   = 1024;
+WANT_CONST float   IT_CELLS                     = 2048;
+const float   IT_SUPERWEAPON               = 4096;
+const float   IT_FUEL                      = 128;
+const float   IT_STRENGTH                  = 8192;
+const float   IT_INVINCIBLE                = 16384;
+const float   IT_HEALTH                    = 32768;
+// union:
+	// for items:
+	WANT_CONST float	IT_KEY1					= 131072;
+	WANT_CONST float	IT_KEY2					= 262144;
+	// for players:
+	const float	IT_RED_FLAG_TAKEN		= 32768;
+	const float	IT_RED_FLAG_LOST		= 65536;
+	const float	IT_RED_FLAG_CARRYING		= 98304;
+	const float	IT_BLUE_FLAG_TAKEN		= 131072;
+	const float	IT_BLUE_FLAG_LOST		= 262144;
+	const float	IT_BLUE_FLAG_CARRYING	= 393216;
+// end
+const float   IT_5HP                       = 524288;
+const float   IT_25HP                      = 1048576;
+const float   IT_ARMOR_SHARD               = 2097152;
+const float   IT_ARMOR                     = 4194304;
+
+const float   IT_AMMO                      = 3968; // IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_FUEL;
+const float   IT_PICKUPMASK                = 51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately
+const float   IT_UNLIMITED_AMMO            = 3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO;
+
+// variables:
+string weaponorder_byid;
+
+// functions:
+entity get_weaponinfo(float id);
+string W_FixWeaponOrder(string order, float complete);
+string W_NameWeaponOrder(string order);
+string W_NumberWeaponOrder(string order);
+
+// ammo types
+.float ammo_shells;
+.float ammo_nails;
+.float ammo_rockets;
+.float ammo_cells;
+.float ammo_fuel;
+.float ammo_batteries; // dummy
+
+// Weapon sets
+typedef vector WepSet;
+WepSet WepSet_FromWeapon(float a);
+#ifdef SVQC
+void WepSet_AddStat();
+void WriteWepSet(float dest, WepSet w);
+#endif
+#ifdef CSQC
+WepSet WepSet_GetFromStat();
+WepSet ReadWepSet();
+#endif
+
+// Weapon name macros
+#define WEP_FIRST 1
+#define WEP_MAXCOUNT 24 // Increase as needed. Can be up to three times as much.
+float WEP_COUNT;
+float WEP_LAST;
+WepSet WEPSET_ALL;
+WepSet WEPSET_SUPERWEAPONS;
+
+// entity properties of weaponinfo:
+.float weapon; // WEP_...
+.WepSet weapons; // WEPSET_...
+.string netname; // short name
+.string message; // human readable name
+.float items; // IT_...
+.float(float) weapon_func; // w_...
+.string mdl; // modelname without g_, v_, w_
+.string model; // full name of g_ model
+.float spawnflags; // WEPSPAWNFLAG_... combined
+.float impulse; // weapon impulse
+.float bot_pickupbasevalue; // bot weapon priority
+.string model2; // wpn- sprite name
+..float ammo_field; // main ammo field
+
+// dynamic weapon adding
+float w_null(float dummy);
+void register_weapon(float id, WepSet bit, float(float) func, float ammotype, float i, float weapontype, float pickupbasevalue, string modelname, string shortname, string wname);
+void register_weapons_done();
+
+#define REGISTER_WEAPON_2(id,bit,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
+	float id; \
+	WepSet bit; \
+	float func(float); \
+	void RegisterWeapons_##id() \
+	{ \
+		WEP_LAST = (id = WEP_FIRST + WEP_COUNT); \
+		bit = WepSet_FromWeapon(id); \
+		WEPSET_ALL |= bit; \
+		if((weapontype) & WEP_FLAG_SUPERWEAPON) \
+			WEPSET_SUPERWEAPONS |= bit; \
+		++WEP_COUNT; \
+		register_weapon(id,bit,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname); \
+	} \
+	ACCUMULATE_FUNCTION(RegisterWeapons, RegisterWeapons_##id)
+#ifdef MENUQC
+#define REGISTER_WEAPON(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
+	REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,w_null,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname)
+#else
+#define REGISTER_WEAPON(id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname) \
+	REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,func,ammotype,i,weapontype,pickupbasevalue,modelname,shortname,wname)
+#endif
+
+#include "../server/w_all.qc"
+
+#undef REGISTER_WEAPON
+ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done);
+
+
+string W_FixWeaponOrder(string order, float complete);
+string W_NumberWeaponOrder(string order);
+string W_NameWeaponOrder(string order);
+string W_FixWeaponOrder_BuildImpulseList(string o);
+string W_FixWeaponOrder_AllowIncomplete(string order);
+string W_FixWeaponOrder_ForceComplete(string order);
+
+void W_RandomWeapons(entity e, float n);
+
+string W_Name(float weaponid);
+
+float W_AmmoItemCode(float wpn);
diff --git a/qcsrc/common/monsters/monster/mage.qc b/qcsrc/common/monsters/monster/mage.qc
index 3adc59a30..26bb0a9af 100644
--- a/qcsrc/common/monsters/monster/mage.qc
+++ b/qcsrc/common/monsters/monster/mage.qc
@@ -70,7 +70,7 @@ float friend_needshelp(entity e)
 	switch(self.skin)
 	{
 		case 0: return (e.health < autocvar_g_balance_health_regenstable);
-		case 1: return ((e.ammo_cells && e.ammo_cells < g_pickup_cells_max) || (e.ammo_plasma && e.ammo_plasma < g_pickup_plasma_max) || (e.ammo_rockets && e.ammo_rockets < g_pickup_rockets_max) || (e.ammo_nails && e.ammo_nails < g_pickup_nails_max) || (e.ammo_shells && e.ammo_shells < g_pickup_shells_max));
+		case 1: return ((e.ammo_cells && e.ammo_cells < g_pickup_cells_max) || (e.ammo_rockets && e.ammo_rockets < g_pickup_rockets_max) || (e.ammo_nails && e.ammo_nails < g_pickup_nails_max) || (e.ammo_shells && e.ammo_shells < g_pickup_shells_max));
 		case 2: return (e.armorvalue < autocvar_g_balance_armor_regenstable);
 		case 3: return (e.health > 0);
 	}
@@ -87,7 +87,7 @@ void mage_spike_explode()
 	self.realowner.mage_spike = world;
 
 	pointparticles(particleeffectnum("explosion_small"), self.origin, '0 0 0', 1);
-	RadiusDamage (self, self.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius), world, world, 0, DEATH_MONSTER_MAGE, other);
+	RadiusDamage (self, self.realowner, (autocvar_g_monster_mage_attack_spike_damage), (autocvar_g_monster_mage_attack_spike_damage) * 0.5, (autocvar_g_monster_mage_attack_spike_radius), world, 0, DEATH_MONSTER_MAGE, other);
 
 	remove (self);
 }
@@ -209,7 +209,6 @@ void mage_heal()
 					break;
 				case 1:
 					if(head.ammo_cells) head.ammo_cells = bound(head.ammo_cells, head.ammo_cells + 1, g_pickup_cells_max);
-					if(head.ammo_plasma) head.ammo_plasma = bound(head.ammo_plasma, head.ammo_plasma + 1, g_pickup_plasma_max);
 					if(head.ammo_rockets) head.ammo_rockets = bound(head.ammo_rockets, head.ammo_rockets + 1, g_pickup_rockets_max);
 					if(head.ammo_shells) head.ammo_shells = bound(head.ammo_shells, head.ammo_shells + 2, g_pickup_shells_max);
 					if(head.ammo_nails) head.ammo_nails = bound(head.ammo_nails, head.ammo_nails + 5, g_pickup_nails_max);
@@ -249,7 +248,7 @@ void mage_heal()
 void mage_push()
 {
 	sound(self, CH_SHOTS, "weapons/tagexp1.wav", 1, ATTEN_NORM);
-	RadiusDamage (self, self, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius), world, world, (autocvar_g_monster_mage_attack_push_force), DEATH_MONSTER_MAGE, self.enemy);
+	RadiusDamage (self, self, (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_damage), (autocvar_g_monster_mage_attack_push_radius), world, (autocvar_g_monster_mage_attack_push_force), DEATH_MONSTER_MAGE, self.enemy);
 	pointparticles(particleeffectnum("TE_EXPLOSION"), self.origin, '0 0 0', 1);
 
 	self.frame = mage_anim_attack;
diff --git a/qcsrc/common/monsters/monster/shambler.qc b/qcsrc/common/monsters/monster/shambler.qc
index 7c46a1da1..0e82fe8d2 100644
--- a/qcsrc/common/monsters/monster/shambler.qc
+++ b/qcsrc/common/monsters/monster/shambler.qc
@@ -74,7 +74,7 @@ void shambler_lightning_explode()
 	if(self.movetype == MOVETYPE_NONE)
 		self.velocity = self.oldvelocity;
 
-	RadiusDamage (self, self.realowner, (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_radius), world, world, (autocvar_g_monster_shambler_attack_lightning_force), self.projectiledeathtype, other);
+	RadiusDamage (self, self.realowner, (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_damage), (autocvar_g_monster_shambler_attack_lightning_radius), world, (autocvar_g_monster_shambler_attack_lightning_force), self.projectiledeathtype, other);
 
 	for(head = findradius(self.origin, (autocvar_g_monster_shambler_attack_lightning_radius_zap)); head; head = head.chain) if(head != self.realowner) if(head.takedamage)
 	{
@@ -148,7 +148,7 @@ void shambler_lightning()
 	gren.event_damage = shambler_lightning_damage;
 	gren.damagedbycontents = TRUE;
 	gren.missile_flags = MIF_SPLASH | MIF_ARC;
-	W_SetupProjVelocity_Explicit(gren, v_forward, v_up, (autocvar_g_monster_shambler_attack_lightning_speed), (autocvar_g_monster_shambler_attack_lightning_speed_up), 0, 0, FALSE);
+	W_SetupProjectileVelocityEx(gren, v_forward, v_up, (autocvar_g_monster_shambler_attack_lightning_speed), (autocvar_g_monster_shambler_attack_lightning_speed_up), 0, 0, FALSE);
 
 	gren.angles = vectoangles (gren.velocity);
 	gren.flags = FL_PROJECTILE;
@@ -222,7 +222,7 @@ float m_shambler(float req)
 			self.monster_loot = spawnfunc_item_health_mega;
 			self.monster_attackfunc	= shambler_attack;
 			self.frame = shambler_anim_stand;
-			self.weapon = WEP_VORTEX;
+			self.weapon = WEP_NEX;
 
 			return TRUE;
 		}
diff --git a/qcsrc/common/monsters/monster/spider.qc b/qcsrc/common/monsters/monster/spider.qc
index c6c454547..7e35b8b16 100644
--- a/qcsrc/common/monsters/monster/spider.qc
+++ b/qcsrc/common/monsters/monster/spider.qc
@@ -35,7 +35,7 @@ void spider_web_explode()
 	if(self)
 	{
 		pointparticles(particleeffectnum("electro_impact"), self.origin, '0 0 0', 1);
-		RadiusDamage(self, self.realowner, 0, 0, 25, world, world, 25, self.projectiledeathtype, world);
+		RadiusDamage(self, self.realowner, 0, 0, 25, world, 25, self.projectiledeathtype, world);
 
 		for(e = findradius(self.origin, 25); e; e = e.chain) if(e != self) if(e.takedamage && e.deadflag == DEAD_NO) if(e.health > 0) if(e.monsterid != MON_SPIDER)
 			e.spider_slowness = time + (autocvar_g_monster_spider_attack_web_damagetime);
@@ -72,7 +72,7 @@ void spider_shootweb()
 	//proj.glow_size = 50;
 	//proj.glow_color = 45;
 	proj.movetype = MOVETYPE_BOUNCE;
-	W_SetupProjVelocity_Explicit(proj, v_forward, v_up, (autocvar_g_monster_spider_attack_web_speed), (autocvar_g_monster_spider_attack_web_speed_up), 0, 0, FALSE);
+	W_SetupProjectileVelocityEx(proj, v_forward, v_up, (autocvar_g_monster_spider_attack_web_speed), (autocvar_g_monster_spider_attack_web_speed_up), 0, 0, FALSE);
 	proj.touch = spider_web_touch;
 	setsize(proj, '-4 -4 -4', '4 4 4');
 	proj.takedamage = DAMAGE_NO;
diff --git a/qcsrc/common/monsters/monster/wyvern.qc b/qcsrc/common/monsters/monster/wyvern.qc
index a44f6d9c7..ed4962d06 100644
--- a/qcsrc/common/monsters/monster/wyvern.qc
+++ b/qcsrc/common/monsters/monster/wyvern.qc
@@ -35,7 +35,7 @@ void wyvern_fireball_explode()
 	{
 		pointparticles(particleeffectnum("fireball_explode"), self.origin, '0 0 0', 1);
 
-		RadiusDamage(self, self.realowner, (autocvar_g_monster_wyvern_attack_fireball_damage), (autocvar_g_monster_wyvern_attack_fireball_edgedamage), (autocvar_g_monster_wyvern_attack_fireball_force), world, world, (autocvar_g_monster_wyvern_attack_fireball_radius), self.projectiledeathtype, world);
+		RadiusDamage(self, self.realowner, (autocvar_g_monster_wyvern_attack_fireball_damage), (autocvar_g_monster_wyvern_attack_fireball_edgedamage), (autocvar_g_monster_wyvern_attack_fireball_force), world, (autocvar_g_monster_wyvern_attack_fireball_radius), self.projectiledeathtype, world);
 
 		for(e = world; (e = findfloat(e, takedamage, DAMAGE_AIM)); ) if(vlen(e.origin - self.origin) <= (autocvar_g_monster_wyvern_attack_fireball_radius))
 			Fire_AddDamage(e, self, 5 * Monster_SkillModifier(), (autocvar_g_monster_wyvern_attack_fireball_damagetime), self.projectiledeathtype);
diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc
index fd966f5d2..6d06de50e 100644
--- a/qcsrc/common/monsters/sv_monsters.qc
+++ b/qcsrc/common/monsters/sv_monsters.qc
@@ -335,7 +335,7 @@ void Monster_CheckMinibossFlag ()
 		self.health += autocvar_g_monsters_miniboss_healthboost;
 		self.effects |= EF_RED;
 		if(!self.weapon)
-			self.weapon = WEP_VORTEX;
+			self.weapon = WEP_NEX;
 	}
 }
 
diff --git a/qcsrc/common/notifications.qh b/qcsrc/common/notifications.qh
index 27e2f7ede..60cc622fa 100644
--- a/qcsrc/common/notifications.qh
+++ b/qcsrc/common/notifications.qh
@@ -497,19 +497,13 @@ void Send_Notification_WOCOVA(
 	MSG_INFO_NOTIF(1, INFO_WATERMARK,                      1, 0, "s1", "",                          "",                     _("^F3SVQC Build information: ^F4%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_MURDER,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weapontuba",             _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Accordeon%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_ACCORDEON_SUICIDE,             2, 1, "s1 s2loc spree_lost", "s1",                 "weapontuba",             _("^BG%s^K1 hurt their own ears with the @!#%%'n Accordeon%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_ARC_MURDER,                    3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponhlac",             _("^BG%s%s^K1 was electrocuted by ^BG%s^K1's Arc%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_BLASTER_MURDER,                3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponlaser",            _("^BG%s%s^K1 was shot to death by ^BG%s^K1's Blaster%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_BLASTER_SUICIDE,               2, 1, "s1 s2loc spree_lost", "s1",                 "weaponlaser",            _("^BG%s^K1 shot themself to hell with their Blaster%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_MURDER,                3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponcrylink",          _("^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_CRYLINK_SUICIDE,               2, 1, "s1 s2loc spree_lost", "s1",                 "weaponcrylink",          _("^BG%s^K1 felt the strong pull of their Crylink%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_DEVASTATOR_MURDER_DIRECT,      3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponrocketlauncher",   _("^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_DEVASTATOR_MURDER_SPLASH,      3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponrocketlauncher",   _("^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_DEVASTATOR_SUICIDE,            2, 1, "s1 s2loc spree_lost", "s1",                 "weaponrocketlauncher",   _("^BG%s^K1 blew themself up with their Devastator%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_BOLT,           3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponelectro",          _("^BG%s%s^K1 was blasted by ^BG%s^K1's Electro bolt%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_COMBO,          3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponelectro",          _("^BG%s%s^K1 felt the electrifying air of ^BG%s^K1's Electro combo%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_ORBS,           3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponelectro",          _("^BG%s%s^K1 got too close to ^BG%s^K1's Electro orb%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_BOLT,          2, 1, "s1 s2loc spree_lost", "s1",                 "weaponelectro",          _("^BG%s^K1 played with Electro bolts%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_ORBS,          2, 1, "s1 s2loc spree_lost", "s1",                 "weaponelectro",          _("^BG%s^K1 could not remember where they put their Electro orb%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_MURDER_ORBS,           3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponelectro",          _("^BG%s%s^K1 got too close to ^BG%s^K1's Electro plasma%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_BOLT,          2, 1, "s1 s2loc spree_lost", "s1",                 "weaponelectro",          _("^BG%s^K1 played with Electro plasma%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_ELECTRO_SUICIDE_ORBS,          2, 1, "s1 s2loc spree_lost", "s1",                 "weaponelectro",          _("^BG%s^K1 could not remember where they put their Electro plasma%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_BLAST,         3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponfireball",         _("^BG%s%s^K1 got too close to ^BG%s^K1's fireball%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_MURDER_FIREMINE,      3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponfireball",         _("^BG%s%s^K1 got burnt by ^BG%s^K1's firemine%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_FIREBALL_SUICIDE_BLAST,        2, 1, "s1 s2loc spree_lost", "s1",                 "weaponfireball",         _("^BG%s^K1 should have used a smaller gun%s%s"), "") \
@@ -522,30 +516,33 @@ void Send_Notification_WOCOVA(
 	MSG_INFO_NOTIF(1, INFO_WEAPON_HOOK_MURDER,                   3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponhook",             _("^BG%s%s^K1 was caught in ^BG%s^K1's Hook gravity bomb%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_MURDER,            3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weapontuba",             _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Klein Bottle%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_KLEINBOTTLE_SUICIDE,           2, 1, "s1 s2loc spree_lost", "s1",                 "weapontuba",             _("^BG%s^K1 hurt their own ears with the @!#%%'n Klein Bottle%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_MACHINEGUN_MURDER_SNIPE,       3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponuzi",              _("^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_MACHINEGUN_MURDER_SPRAY,       3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponuzi",              _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_MURDER,                  3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponlaser",            _("^BG%s%s^K1 was shot to death by ^BG%s^K1's Laser%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_LASER_SUICIDE,                 2, 1, "s1 s2loc spree_lost", "s1",                 "weaponlaser",            _("^BG%s^K1 shot themself to hell with their Laser%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_MURDER,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponminelayer",        _("^BG%s%s^K1 got too close to ^BG%s^K1's mine%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_MINELAYER_SUICIDE,             2, 1, "s1 s2loc spree_lost", "s1",                 "weaponminelayer",        _("^BG%s^K1 forgot about their mine%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_MINSTANEX_MURDER,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponminstanex",        _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Minstanex%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_BOUNCE,          3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weapongrenadelauncher",  _("^BG%s%s^K1 got too close to ^BG%s^K1's Mortar grenade%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_MURDER_EXPLODE,         3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weapongrenadelauncher",  _("^BG%s%s^K1 ate ^BG%s^K1's Mortar grenade%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_BOUNCE,         2, 1, "s1 s2loc spree_lost", "s1",                 "weapongrenadelauncher",  _("^BG%s^K1 didn't see their own Mortar grenade%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_MORTAR_SUICIDE_EXPLODE,        2, 1, "s1 s2loc spree_lost", "s1",                 "weapongrenadelauncher",  _("^BG%s^K1 blew themself up with their own Mortar%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_NEX_MURDER,                    3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponnex",              _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Nex%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER,                  3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponrifle",            _("^BG%s%s^K1 was sniped with a Rifle by ^BG%s^K1%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL,             3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponrifle",            _("^BG%s%s^K1 died in ^BG%s^K1's Rifle bullet hail%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING,    3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponrifle",            _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle bullet hail%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_RIFLE_MURDER_PIERCING,         3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponrifle",            _("^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT,  3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponrocketlauncher",   _("^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH,  3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponrocketlauncher",   _("^BG%s%s^K1 got too close ^BG%s^K1's rocket%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_ROCKETLAUNCHER_SUICIDE,        2, 1, "s1 s2loc spree_lost", "s1",                 "weaponrocketlauncher",   _("^BG%s^K1 blew themself up with their Rocketlauncher%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_SPRAY,           3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponseeker",           _("^BG%s%s^K1 was pummeled by ^BG%s^K1's Seeker rockets%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_MURDER_TAG,             3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponseeker",           _("^BG%s%s^K1 was tagged by ^BG%s^K1's Seeker%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_SEEKER_SUICIDE,                2, 1, "s1 s2loc spree_lost", "s1",                 "weaponseeker",           _("^BG%s^K1 played with tiny Seeker rockets%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_SHOCKWAVE_MURDER,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponshotgun",          _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shockwave%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_SHOCKWAVE_MURDER_SLAP,         3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1",  "notify_melee_shotgun",   _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shockwave%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER,                3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponshotgun",          _("^BG%s%s^K1 was gunned down by ^BG%s^K1's Shotgun%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_SHOTGUN_MURDER_SLAP,           3, 2, "spree_inf s2 s1 s3loc spree_end", "s2 s1",  "notify_melee_shotgun",   _("^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shotgun%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_THINKING_WITH_PORTALS,         2, 1, "s1 s2loc spree_lost", "s1",                 "notify_selfkill",        _("^BG%s^K1 is now thinking with portals%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_MURDER,                   3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weapontuba",             _("^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Tuba%s%s"), "") \
 	MSG_INFO_NOTIF(1, INFO_WEAPON_TUBA_SUICIDE,                  2, 1, "s1 s2loc spree_lost", "s1",                 "weapontuba",             _("^BG%s^K1 hurt their own ears with the @!#%%'n Tuba%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_VAPORIZER_MURDER,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponminstanex",        _("^BG%s%s^K1 has been sublimated by ^BG%s^K1's Vaporizer%s%s"), "") \
-	MSG_INFO_NOTIF(1, INFO_WEAPON_VORTEX_MURDER,                 3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponnex",              _("^BG%s%s^K1 has been vaporized by ^BG%s^K1's Vortex%s%s"), "")
+	MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SNIPE,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponuzi",              _("^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"), "") \
+	MSG_INFO_NOTIF(1, INFO_WEAPON_UZI_MURDER_SPRAY,              3, 2, "spree_inf s1 s2 s3loc spree_end", "s2 s1",  "weaponuzi",              _("^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"), "")
 
 #define MULTITEAM_CENTER2(default,prefix,strnum,flnum,args,cpid,durcnt,normal,gentle) \
 	MSG_CENTER_NOTIF(default, prefix##RED, strnum, flnum, args, cpid, durcnt, TCR(normal, COL_TEAM_1, strtoupper(NAME_TEAM_1)), TCR(gentle, COL_TEAM_1, strtoupper(NAME_TEAM_1))) \
@@ -812,14 +809,8 @@ void Send_Notification_WOCOVA(
 	MSG_MULTI_NOTIF(1, MULTI_MINSTA_FINDAMMO,                ANNCE_NUM_10,  NO_MSG,                                    CENTER_MINSTA_FINDAMMO_FIRST) \
 	MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_MURDER,              NO_MSG,        INFO_WEAPON_ACCORDEON_MURDER,              NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_ACCORDEON_SUICIDE,             NO_MSG,        INFO_WEAPON_ACCORDEON_SUICIDE,             CENTER_DEATH_SELF_GENERIC) \
-	MSG_MULTI_NOTIF(1, WEAPON_ARC_MURDER,                    NO_MSG,        INFO_WEAPON_ARC_MURDER,                    NO_MSG) \
-	MSG_MULTI_NOTIF(1, WEAPON_BLASTER_MURDER,                NO_MSG,        INFO_WEAPON_BLASTER_MURDER,                NO_MSG) \
-	MSG_MULTI_NOTIF(1, WEAPON_BLASTER_SUICIDE,               NO_MSG,        INFO_WEAPON_BLASTER_SUICIDE,               CENTER_DEATH_SELF_GENERIC) \
 	MSG_MULTI_NOTIF(1, WEAPON_CRYLINK_MURDER,                NO_MSG,        INFO_WEAPON_CRYLINK_MURDER,                NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_CRYLINK_SUICIDE,               NO_MSG,        INFO_WEAPON_CRYLINK_SUICIDE,               CENTER_DEATH_SELF_GENERIC) \
-	MSG_MULTI_NOTIF(1, WEAPON_DEVASTATOR_MURDER_DIRECT,      NO_MSG,        INFO_WEAPON_DEVASTATOR_MURDER_DIRECT,      NO_MSG) \
-	MSG_MULTI_NOTIF(1, WEAPON_DEVASTATOR_MURDER_SPLASH,      NO_MSG,        INFO_WEAPON_DEVASTATOR_MURDER_SPLASH,      NO_MSG) \
-	MSG_MULTI_NOTIF(1, WEAPON_DEVASTATOR_SUICIDE,            NO_MSG,        INFO_WEAPON_DEVASTATOR_SUICIDE,            CENTER_DEATH_SELF_GENERIC) \
 	MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_BOLT,           NO_MSG,        INFO_WEAPON_ELECTRO_MURDER_BOLT,           NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_COMBO,          NO_MSG,        INFO_WEAPON_ELECTRO_MURDER_COMBO,          NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_ELECTRO_MURDER_ORBS,           NO_MSG,        INFO_WEAPON_ELECTRO_MURDER_ORBS,           NO_MSG) \
@@ -837,30 +828,33 @@ void Send_Notification_WOCOVA(
 	MSG_MULTI_NOTIF(1, WEAPON_HOOK_MURDER,                   NO_MSG,        INFO_WEAPON_HOOK_MURDER,                   NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_KLEINBOTTLE_MURDER,            NO_MSG,        INFO_WEAPON_KLEINBOTTLE_MURDER,            NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_KLEINBOTTLE_SUICIDE,           NO_MSG,        INFO_WEAPON_KLEINBOTTLE_SUICIDE,           CENTER_DEATH_SELF_GENERIC) \
-	MSG_MULTI_NOTIF(1, WEAPON_MACHINEGUN_MURDER_SNIPE,       NO_MSG,        INFO_WEAPON_MACHINEGUN_MURDER_SNIPE,       NO_MSG) \
-	MSG_MULTI_NOTIF(1, WEAPON_MACHINEGUN_MURDER_SPRAY,       NO_MSG,        INFO_WEAPON_MACHINEGUN_MURDER_SPRAY,       NO_MSG) \
+	MSG_MULTI_NOTIF(1, WEAPON_LASER_MURDER,                  NO_MSG,        INFO_WEAPON_LASER_MURDER,                  NO_MSG) \
+	MSG_MULTI_NOTIF(1, WEAPON_LASER_SUICIDE,                 NO_MSG,        INFO_WEAPON_LASER_SUICIDE,                 CENTER_DEATH_SELF_GENERIC) \
 	MSG_MULTI_NOTIF(1, WEAPON_MINELAYER_MURDER,              NO_MSG,        INFO_WEAPON_MINELAYER_MURDER,              NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_MINELAYER_SUICIDE,             NO_MSG,        INFO_WEAPON_MINELAYER_SUICIDE,             CENTER_DEATH_SELF_GENERIC) \
+	MSG_MULTI_NOTIF(1, WEAPON_MINSTANEX_MURDER,              NO_MSG,        INFO_WEAPON_MINSTANEX_MURDER,              NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_MORTAR_MURDER_BOUNCE,          NO_MSG,        INFO_WEAPON_MORTAR_MURDER_BOUNCE,          NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_MORTAR_MURDER_EXPLODE,         NO_MSG,        INFO_WEAPON_MORTAR_MURDER_EXPLODE,         NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_MORTAR_SUICIDE_BOUNCE,         NO_MSG,        INFO_WEAPON_MORTAR_SUICIDE_BOUNCE,         CENTER_DEATH_SELF_GENERIC) \
 	MSG_MULTI_NOTIF(1, WEAPON_MORTAR_SUICIDE_EXPLODE,        NO_MSG,        INFO_WEAPON_MORTAR_SUICIDE_EXPLODE,        CENTER_DEATH_SELF_GENERIC) \
+	MSG_MULTI_NOTIF(1, WEAPON_NEX_MURDER,                    NO_MSG,        INFO_WEAPON_NEX_MURDER,                    NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER,                  NO_MSG,        INFO_WEAPON_RIFLE_MURDER,                  NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_HAIL,             NO_MSG,        INFO_WEAPON_RIFLE_MURDER_HAIL,             NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_HAIL_PIERCING,    NO_MSG,        INFO_WEAPON_RIFLE_MURDER_HAIL_PIERCING,    NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_RIFLE_MURDER_PIERCING,         NO_MSG,        INFO_WEAPON_RIFLE_MURDER_PIERCING,         NO_MSG) \
+	MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_MURDER_DIRECT,  NO_MSG,        INFO_WEAPON_ROCKETLAUNCHER_MURDER_DIRECT,  NO_MSG) \
+	MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_MURDER_SPLASH,  NO_MSG,        INFO_WEAPON_ROCKETLAUNCHER_MURDER_SPLASH,  NO_MSG) \
+	MSG_MULTI_NOTIF(1, WEAPON_ROCKETLAUNCHER_SUICIDE,        NO_MSG,        INFO_WEAPON_ROCKETLAUNCHER_SUICIDE,        CENTER_DEATH_SELF_GENERIC) \
 	MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_SPRAY,           NO_MSG,        INFO_WEAPON_SEEKER_MURDER_SPRAY,           NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_SEEKER_MURDER_TAG,             NO_MSG,        INFO_WEAPON_SEEKER_MURDER_TAG,             NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_SEEKER_SUICIDE,                NO_MSG,        INFO_WEAPON_SEEKER_SUICIDE,                CENTER_DEATH_SELF_GENERIC) \
-	MSG_MULTI_NOTIF(1, WEAPON_SHOCKWAVE_MURDER,              NO_MSG,        INFO_WEAPON_SHOCKWAVE_MURDER,              NO_MSG) \
-	MSG_MULTI_NOTIF(1, WEAPON_SHOCKWAVE_MURDER_SLAP,         NO_MSG,        INFO_WEAPON_SHOCKWAVE_MURDER_SLAP,         NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER,                NO_MSG,        INFO_WEAPON_SHOTGUN_MURDER,                NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_SHOTGUN_MURDER_SLAP,           NO_MSG,        INFO_WEAPON_SHOTGUN_MURDER_SLAP,           NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_THINKING_WITH_PORTALS,         NO_MSG,        INFO_WEAPON_THINKING_WITH_PORTALS,         CENTER_DEATH_SELF_GENERIC) \
 	MSG_MULTI_NOTIF(1, WEAPON_TUBA_MURDER,                   NO_MSG,        INFO_WEAPON_TUBA_MURDER,                   NO_MSG) \
 	MSG_MULTI_NOTIF(1, WEAPON_TUBA_SUICIDE,                  NO_MSG,        INFO_WEAPON_TUBA_SUICIDE,                  CENTER_DEATH_SELF_GENERIC) \
-	MSG_MULTI_NOTIF(1, WEAPON_VAPORIZER_MURDER,              NO_MSG,        INFO_WEAPON_VAPORIZER_MURDER,              NO_MSG) \
-	MSG_MULTI_NOTIF(1, WEAPON_VORTEX_MURDER,                 NO_MSG,        INFO_WEAPON_VORTEX_MURDER,                 NO_MSG)
+	MSG_MULTI_NOTIF(1, WEAPON_UZI_MURDER_SNIPE,              NO_MSG,        INFO_WEAPON_UZI_MURDER_SNIPE,              NO_MSG) \
+	MSG_MULTI_NOTIF(1, WEAPON_UZI_MURDER_SPRAY,              NO_MSG,        INFO_WEAPON_UZI_MURDER_SPRAY,              NO_MSG)
 
 #define MULTITEAM_CHOICE2(default,challow,prefix,chtype,optiona,optionb) \
 	MSG_CHOICE_NOTIF(default, challow, prefix##RED, chtype, optiona##RED, optionb##RED) \
@@ -1024,7 +1018,7 @@ string arg_slot[NOTIF_MAX_ARGS];
     ARG_CASE(ARG_CS_SV,     "spree_inf",     (autocvar_notification_show_sprees ? notif_arg_spree_inf(1, input, s2, f2) : "")) \
     ARG_CASE(ARG_CS_SV,     "spree_end",     (autocvar_notification_show_sprees ? notif_arg_spree_inf(-1, "", "", f1) : "")) \
     ARG_CASE(ARG_CS_SV,     "spree_lost",    (autocvar_notification_show_sprees ? notif_arg_spree_inf(-2, "", "", f1) : "")) \
-    ARG_CASE(ARG_CS_SV,     "item_wepname",  WEP_NAME(f1)) \
+    ARG_CASE(ARG_CS_SV,     "item_wepname",  W_Name(f1)) \
     ARG_CASE(ARG_CS_SV,     "item_buffname", sprintf("%s%s", rgb_to_hexcolor(Buff_Color(f1)), Buff_PrettyName(f1))) \
     ARG_CASE(ARG_CS_SV,     "item_wepammo",  (s1 != "" ? sprintf(_(" with %s"), s1) : "")) \
     ARG_CASE(ARG_DC,        "item_centime",  ftos(autocvar_notification_item_centerprinttime)) \
diff --git a/qcsrc/common/stats.qh b/qcsrc/common/stats.qh
index 44a540b65..793582e12 100644
--- a/qcsrc/common/stats.qh
+++ b/qcsrc/common/stats.qh
@@ -52,10 +52,10 @@ const float STAT_SHOTORG                = 46; // compressShotOrigin
 const float STAT_LEADLIMIT              = 47;
 const float STAT_WEAPON_CLIPLOAD        = 48;
 const float STAT_WEAPON_CLIPSIZE        = 49;
-const float STAT_VORTEX_CHARGE          = 50;
+const float STAT_NEX_CHARGE             = 50;
 const float STAT_LAST_PICKUP            = 51;
 const float STAT_HUD                    = 52;
-const float STAT_VORTEX_CHARGEPOOL      = 53;
+const float STAT_NEX_CHARGEPOOL         = 53;
 const float STAT_HIT_TIME               = 54;
 const float STAT_TYPEHIT_TIME           = 55;
 const float STAT_LAYED_MINES            = 56;
@@ -86,7 +86,7 @@ const float STAT_NADE_BONUS_TYPE        = 80;
 const float STAT_NADE_BONUS_SCORE       = 81;
 const float STAT_HEALING_ORB            = 82;
 const float STAT_HEALING_ORB_ALPHA      = 83;
-const float STAT_PLASMA                 = 84;
+// 84 empty?
 // 85 empty?
 // 86 empty?
 // 87 empty?
diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc
index b5c98190e..c50a3ba53 100644
--- a/qcsrc/common/util.qc
+++ b/qcsrc/common/util.qc
@@ -2558,30 +2558,6 @@ void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t
 		queue_start.FindConnectedComponent_processing = 0;
 }
 
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z)
-{
-	vector result; result_x = x; result_y = y; result_z = z;
-	return result;
-}
-
-vector get_corner_position(entity box, float corner)
-{
-	switch(corner)
-	{
-		case 1: return combine_to_vector(box.absmin_x, box.absmin_y, box.absmin_z);
-		case 2: return combine_to_vector(box.absmax_x, box.absmin_y, box.absmin_z);
-		case 3: return combine_to_vector(box.absmin_x, box.absmax_y, box.absmin_z);
-		case 4: return combine_to_vector(box.absmin_x, box.absmin_y, box.absmax_z);
-		case 5: return combine_to_vector(box.absmax_x, box.absmax_y, box.absmin_z);
-		case 6: return combine_to_vector(box.absmin_x, box.absmax_y, box.absmax_z);
-		case 7: return combine_to_vector(box.absmax_x, box.absmin_y, box.absmax_z);
-		case 8: return combine_to_vector(box.absmax_x, box.absmax_y, box.absmax_z);
-		default: return '0 0 0';
-	}
-}
-#endif
-
 // todo: this sucks, lets find a better way to do backtraces?
 #ifndef MENUQC
 void backtrace(string msg)
diff --git a/qcsrc/common/util.qh b/qcsrc/common/util.qh
index a959931c3..9b969134a 100644
--- a/qcsrc/common/util.qh
+++ b/qcsrc/common/util.qh
@@ -1,3 +1,4 @@
+#define WANT_CONST
 // commonly used, but better make them macros
 #define TRUE 1
 #define FALSE 0
@@ -363,11 +364,6 @@ typedef entity(entity cur, entity near, entity pass) findNextEntityNearFunction_
 typedef float(entity a, entity b, entity pass) isConnectedFunction_t;
 void FindConnectedComponent(entity e, .entity fld, findNextEntityNearFunction_t nxt, isConnectedFunction_t iscon, entity pass);
 
-#ifdef SVQC
-vector combine_to_vector(float x, float y, float z);
-vector get_corner_position(entity box, float corner);
-#endif
-
 // expand multiple arguments into one argument by stripping parenthesis
 #define XPD(...) __VA_ARGS__
 
@@ -449,5 +445,3 @@ float Mod_Q1BSP_NativeContentsFromSuperContents(float supercontents);
 // Quadratic splines (bezier)
 vector bezier_quadratic_getpoint(vector a, vector p, vector b, float t);
 vector bezier_quadratic_getderivative(vector a, vector p, vector b, float t);
-
-#define APPEND_TO_STRING(list,sep,add) ((list) = (((list) != "") ? strcat(list, sep, add) : (add)))
diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh
deleted file mode 100644
index a40488f83..000000000
--- a/qcsrc/common/weapons/all.qh
+++ /dev/null
@@ -1,27 +0,0 @@
-// ONLY EVER ADD NEW WEAPONS AT THE END. IF YOU REMOVE ONE, PUT THE LAST ONE ON
-// ITS PLACE. THIS IS TO AVOID UNNECESSARY RENUMBERING OF WEAPON IMPULSES.
-// IF YOU DISREGARD THIS NOTICE, I'LL KILL YOU WITH THE @!#%'N TUBA
-
-// core weapons
-#include "w_blaster.qc"
-#include "w_shotgun.qc"
-#include "w_machinegun.qc"
-#include "w_mortar.qc"
-#include "w_minelayer.qc"
-#include "w_electro.qc"
-#include "w_crylink.qc"
-#include "w_vortex.qc"
-#include "w_hagar.qc"
-#include "w_devastator.qc"
-
-// other weapons
-#include "w_porto.qc"
-#include "w_vaporizer.qc"
-#include "w_hook.qc"
-#include "w_hlac.qc"
-#include "w_tuba.qc"
-#include "w_rifle.qc"
-#include "w_fireball.qc"
-#include "w_seeker.qc"
-#include "w_shockwave.qc"
-#include "w_arc.qc"
diff --git a/qcsrc/common/weapons/calculations.qc b/qcsrc/common/weapons/calculations.qc
deleted file mode 100644
index 7bc64e0b5..000000000
--- a/qcsrc/common/weapons/calculations.qc
+++ /dev/null
@@ -1,261 +0,0 @@
-// =============================
-//  Explosion Force Calculation
-// =============================
-
-float explosion_calcpush_getmultiplier(vector explosion_v, vector target_v)
-{
-	float a;
-	a  = explosion_v * (explosion_v - target_v);
-
-	if(a <= 0)
-		// target is too fast to be hittable by this
-		return 0;
-
-	a /= (explosion_v * explosion_v);
-		// we know we can divide by this, or above a would be == 0
-
-	return a;
-}
-
-#if 0
-vector explosion_calcpush(vector explosion_v, float explosion_m, vector target_v, float target_m, float elasticity)
-{
-	// solution of the equations:
-	//    v'                = v + a vp             // central hit
-	//    m*v'   + mp*vp'   = m*v + mp*vp          // conservation of momentum
-	//    m*v'^2 + mp*vp'^2 = m*v^2 + mp*vp^2      // conservation of energy (ELASTIC hit)
-	// -> a = 0                                    // case 1: did not hit
-	// -> a = 2*mp*(vp^2 - vp.v) / ((m+mp) * vp^2) // case 2: did hit
-	//                                             // non-elastic hits are somewhere between these two
-
-	// this would be physically correct, but we don't do that
-	return explosion_v * explosion_calcpush_getmultiplier(explosion_v, target_v) * (
-		(1 + elasticity) * (
-			explosion_m
-		) / (
-			target_m + explosion_m
-		)
-	); // note: this factor is at least 0, at most 2
-}
-#endif
-
-// simplified formula, tuned so that if the target has velocity 0, we get exactly the original force
-vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor)
-{
-	// if below 1, the formulas make no sense (and would cause superjumps)
-	if(speedfactor < 1)
-		return explosion_f;
-
-#if 0
-	float m;
-	// find m so that
-	//   speedfactor * (1 + e) * m / (1 + m) == 1
-	m = 1 / ((1 + 0) * speedfactor - 1);
-	vector v;
-	v = explosion_calcpush(explosion_f * speedfactor, m, target_v, 1, 0);
-	// the factor we then get is:
-	//   1
-	printf("MASS: %f\nv: %v -> %v\nENERGY BEFORE == %f + %f = %f\nENERGY AFTER >= %f\n",
-		m,
-		target_v, target_v + v,
-		target_v * target_v, m * explosion_f * speedfactor * explosion_f * speedfactor, target_v * target_v + m * explosion_f * speedfactor * explosion_f * speedfactor,
-		(target_v + v) * (target_v + v));
-	return v;
-#endif
-	return explosion_f * explosion_calcpush_getmultiplier(explosion_f * speedfactor, target_v);
-}
-
-
-// =========================
-//  Shot Spread Calculation
-// =========================
-
-vector cliptoplane(vector v, vector p)
-{
-	return v - (v * p) * p;
-}
-
-vector solve_cubic_pq(float p, float q)
-{
-	float D, u, v, a;
-	D = q*q/4.0 + p*p*p/27.0;
-	if(D < 0)
-	{
-		// irreducibilis
-		a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p)));
-		u = sqrt(-4.0/3.0 * p);
-		// a in range 0..pi/3
-		// cos(a)
-		// cos(a + 2pi/3)
-		// cos(a + 4pi/3)
-		return
-			u *
-			(
-				'1 0 0' * cos(a + 2.0/3.0*M_PI)
-				+
-				'0 1 0' * cos(a + 4.0/3.0*M_PI)
-				+
-				'0 0 1' * cos(a)
-			);
-	}
-	else if(D == 0)
-	{
-		// simple
-		if(p == 0)
-			return '0 0 0';
-		u = 3*q/p;
-		v = -u/2;
-		if(u >= v)
-			return '1 1 0' * v + '0 0 1' * u;
-		else
-			return '0 1 1' * v + '1 0 0' * u;
-	}
-	else
-	{
-		// cardano
-		u = cbrt(-q/2.0 + sqrt(D));
-		v = cbrt(-q/2.0 - sqrt(D));
-		return '1 1 1' * (u + v);
-	}
-}
-vector solve_cubic_abcd(float a, float b, float c, float d)
-{
-	// y = 3*a*x + b
-	// x = (y - b) / 3a
-	float p, q;
-	vector v;
-	p = (9*a*c - 3*b*b);
-	q = (27*a*a*d - 9*a*b*c + 2*b*b*b);
-	v = solve_cubic_pq(p, q);
-	v = (v -  b * '1 1 1') * (1.0 / (3.0 * a));
-	if(a < 0)
-		v += '1 0 -1' * (v_z - v_x); // swap x, z
-	return v;
-}
-
-vector findperpendicular(vector v)
-{
-	vector p;
-	p_x = v_z;
-	p_y = -v_x;
-	p_z = v_y;
-	return normalize(cliptoplane(p, v));
-}
-
-vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle)
-{
-	float sigma;
-	vector v1 = '0 0 0', v2;
-	float dx, dy, r;
-	float sstyle;
-	spread *= spreadfactor; //g_weaponspreadfactor;
-	if(spread <= 0)
-		return forward;
-	sstyle = spreadstyle; //autocvar_g_projectiles_spread_style;
-	
-	if(sstyle == 0)
-	{
-		// this is the baseline for the spread value!
-		// standard deviation: sqrt(2/5)
-		// density function: sqrt(1-r^2)
-		return forward + randomvec() * spread;
-	}
-	else if(sstyle == 1)
-	{
-		// same thing, basically
-		return normalize(forward + cliptoplane(randomvec() * spread, forward));
-	}
-	else if(sstyle == 2)
-	{
-		// circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
-		sigma = spread * 0.89442719099991587855; // match baseline stddev
-		v1 = findperpendicular(forward);
-		v2 = cross(forward, v1);
-		// random point on unit circle
-		dx = random() * 2 * M_PI;
-		dy = sin(dx);
-		dx = cos(dx);
-		// radius in our dist function
-		r = random();
-		r = sqrt(r);
-		return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-	}
-	else if(sstyle == 3) // gauss 3d
-	{
-		sigma = spread * 0.44721359549996; // match baseline stddev
-		// note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
-		v1 = forward;
-		v1_x += gsl_ran_gaussian(sigma);
-		v1_y += gsl_ran_gaussian(sigma);
-		v1_z += gsl_ran_gaussian(sigma);
-		return v1;
-	}
-	else if(sstyle == 4) // gauss 2d
-	{
-		sigma = spread * 0.44721359549996; // match baseline stddev
-		// note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
-		v1_x = gsl_ran_gaussian(sigma);
-		v1_y = gsl_ran_gaussian(sigma);
-		v1_z = gsl_ran_gaussian(sigma);
-		return normalize(forward + cliptoplane(v1, forward));
-	}
-	else if(sstyle == 5) // 1-r
-	{
-		sigma = spread * 1.154700538379252; // match baseline stddev
-		v1 = findperpendicular(forward);
-		v2 = cross(forward, v1);
-		// random point on unit circle
-		dx = random() * 2 * M_PI;
-		dy = sin(dx);
-		dx = cos(dx);
-		// radius in our dist function
-		r = random();
-		r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
-		return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-	}
-	else if(sstyle == 6) // 1-r^2
-	{
-		sigma = spread * 1.095445115010332; // match baseline stddev
-		v1 = findperpendicular(forward);
-		v2 = cross(forward, v1);
-		// random point on unit circle
-		dx = random() * 2 * M_PI;
-		dy = sin(dx);
-		dx = cos(dx);
-		// radius in our dist function
-		r = random();
-		r = sqrt(1 - r);
-		r = sqrt(1 - r);
-		return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-	}
-	else if(sstyle == 7) // (1-r) (2-r)
-	{
-		sigma = spread * 1.224744871391589; // match baseline stddev
-		v1 = findperpendicular(forward);
-		v2 = cross(forward, v1);
-		// random point on unit circle
-		dx = random() * 2 * M_PI;
-		dy = sin(dx);
-		dx = cos(dx);
-		// radius in our dist function
-		r = random();
-		r = 1 - sqrt(r);
-		r = 1 - sqrt(r);
-		return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
-	}
-	else
-		error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
-	return '0 0 0';
-	/*
-	 * how to derive falloff functions:
-	 * rho(r) := (2-r) * (1-r);
-	 * a : 0;
-	 * b : 1;
-	 * rhor(r) := r * rho(r);
-	 * cr(t) := integrate(rhor(r), r, a, t);
-	 * scr(t) := integrate(rhor(r) * r^2, r, a, t);
-	 * variance : scr(b) / cr(b);
-	 * solve(cr(r) = rand * cr(b), r), programmmode:false;
-	 * sqrt(0.4 / variance), numer;
-	 */
-}
diff --git a/qcsrc/common/weapons/calculations.qh b/qcsrc/common/weapons/calculations.qh
deleted file mode 100644
index 9a6dd1c54..000000000
--- a/qcsrc/common/weapons/calculations.qh
+++ /dev/null
@@ -1,2 +0,0 @@
-vector damage_explosion_calcpush(vector explosion_f, vector target_v, float speedfactor);
-vector W_CalculateSpread(vector forward, float spread, float spreadfactor, float spreadstyle);
diff --git a/qcsrc/common/weapons/config.qc b/qcsrc/common/weapons/config.qc
deleted file mode 100644
index 2537022f6..000000000
--- a/qcsrc/common/weapons/config.qc
+++ /dev/null
@@ -1,55 +0,0 @@
-// ==========================
-//  Balance Config Generator
-// ==========================
-
-void W_Config_Queue_Swap(float root, float child, entity pass)
-{
-	string oldroot = wep_config_queue[root];
-	wep_config_queue[root] = wep_config_queue[child];
-	wep_config_queue[child] = oldroot;
-}
-
-float W_Config_Queue_Compare(float root, float child, entity pass)
-{
-	return strcmp(wep_config_queue[root], wep_config_queue[child]);
-}
-
-void Dump_Weapon_Settings(void)
-{
-	float i, x, totalsettings = 0;
-	for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-	{
-		// step 1: clear the queue
-		WEP_CONFIG_COUNT = 0;
-		for(x = 0; x <= MAX_WEP_CONFIG; ++x)
-			{ wep_config_queue[x] = string_null; }
-
-		// step 2: build new queue
-		WEP_ACTION(i, WR_CONFIG);
-
-		// step 3: sort queue
-		heapsort(WEP_CONFIG_COUNT, W_Config_Queue_Swap, W_Config_Queue_Compare, world);
-		
-		// step 4: write queue
-		WEP_CONFIG_WRITETOFILE(sprintf(
-			"// {{{ #%d: %s%s\n",
-			i,
-			WEP_NAME(i),
-			(((get_weaponinfo(i)).spawnflags & WEP_FLAG_MUTATORBLOCKED) ? " (MUTATOR WEAPON)" : "")
-		))
-		for(x = 0; x <= WEP_CONFIG_COUNT; ++x) { WEP_CONFIG_WRITETOFILE(wep_config_queue[x]) }
-		WEP_CONFIG_WRITETOFILE("// }}}\n")
-
-		// step 5: debug info
-		print(sprintf("#%d: %s: %d settings...\n", i, WEP_NAME(i), WEP_CONFIG_COUNT));
-		totalsettings += WEP_CONFIG_COUNT;
-	}
-
-	// clear queue now that we're finished
-	WEP_CONFIG_COUNT = 0;
-	for(x = 0; x <= MAX_WEP_CONFIG; ++x)
-		{ wep_config_queue[x] = string_null; }
-
-	// extra information
-	print(sprintf("Totals: %d weapons, %d settings\n", (i - 1), totalsettings));
-}
diff --git a/qcsrc/common/weapons/config.qh b/qcsrc/common/weapons/config.qh
deleted file mode 100644
index 6a0489314..000000000
--- a/qcsrc/common/weapons/config.qh
+++ /dev/null
@@ -1,44 +0,0 @@
-// ==========================
-//  Balance Config Generator
-// ==========================
-
-void Dump_Weapon_Settings(void);
-float wep_config_file;
-float wep_config_alsoprint;
-
-#define MAX_WEP_CONFIG 256
-float WEP_CONFIG_COUNT;
-string wep_config_queue[MAX_WEP_CONFIG];
-
-#define WEP_CONFIG_QUEUE(a) { \
-	wep_config_queue[WEP_CONFIG_COUNT] = a; \
-	++WEP_CONFIG_COUNT; }
-
-#define WEP_CONFIG_WRITETOFILE(a) { \
-	fputs(wep_config_file, a); \
-	if(wep_config_alsoprint) { print(a); } }
-
-#define WEP_CONFIG_WRITE_CVARS_NONE(wepname,name) \
-	{ WEP_CONFIG_QUEUE( \
-		sprintf("set g_balance_%s_%s %g\n", #wepname, #name, \
-		cvar(sprintf("g_balance_%s_%s", #wepname, #name)))) }
-
-#define WEP_CONFIG_WRITE_CVARS_PRI(wepname,name) WEP_CONFIG_WRITE_CVARS_NONE(wepname, primary_##name)
-#define WEP_CONFIG_WRITE_CVARS_SEC(wepname,name) WEP_CONFIG_WRITE_CVARS_NONE(wepname, secondary_##name)
-#define WEP_CONFIG_WRITE_CVARS_BOTH(wepname,name) \
-	WEP_CONFIG_WRITE_CVARS_PRI(wepname, name) \
-	WEP_CONFIG_WRITE_CVARS_SEC(wepname, name)
-	
-#define WEP_CONFIG_WRITE_CVARS(wepid,wepname,mode,name) WEP_CONFIG_WRITE_CVARS_##mode(wepname, name)
-
-#define WEP_CONFIG_WRITE_PROPS_string(wepname,name) \
-	{ WEP_CONFIG_QUEUE( \
-		sprintf("set g_balance_%s_%s \"%s\"\n", #wepname, #name, \
-		cvar_string(sprintf("g_balance_%s_%s", #wepname, #name)))) }
-
-#define WEP_CONFIG_WRITE_PROPS_float(wepname,name) \
-	{ WEP_CONFIG_QUEUE( \
-		sprintf("set g_balance_%s_%s %g\n", #wepname, #name, \
-		cvar(sprintf("g_balance_%s_%s", #wepname, #name)))) }
-
-#define WEP_CONFIG_WRITE_PROPS(wepid,wepname,type,prop,name) WEP_CONFIG_WRITE_PROPS_##type(wepname,name)
diff --git a/qcsrc/common/weapons/w_arc.qc b/qcsrc/common/weapons/w_arc.qc
deleted file mode 100644
index c666619e5..000000000
--- a/qcsrc/common/weapons/w_arc.qc
+++ /dev/null
@@ -1,1427 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ ARC,
-/* function  */ W_Arc,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 3,
-/* flags     */ WEP_FLAG_NORMAL,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '1 1 1',
-/* modelname */ "arc",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhlac 0.7",
-/* wepimg    */ "weaponhlac",
-/* refname   */ "arc",
-/* wepname   */ _("Arc")
-);
-
-#define ARC_SETTINGS(w_cvar,w_prop) ARC_SETTINGS_LIST(w_cvar, w_prop, ARC, arc)
-#define ARC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, NONE, beam_ammo) \
-	w_cvar(id, sn, NONE, beam_animtime) \
-	w_cvar(id, sn, NONE, beam_botaimspeed) \
-	w_cvar(id, sn, NONE, beam_botaimlifetime) \
-	w_cvar(id, sn, NONE, beam_damage) \
-	w_cvar(id, sn, NONE, beam_degreespersegment) \
-	w_cvar(id, sn, NONE, beam_distancepersegment) \
-	w_cvar(id, sn, NONE, beam_falloff_halflifedist) \
-	w_cvar(id, sn, NONE, beam_falloff_maxdist) \
-	w_cvar(id, sn, NONE, beam_falloff_mindist) \
-	w_cvar(id, sn, NONE, beam_force) \
-	w_cvar(id, sn, NONE, beam_healing_amax) \
-	w_cvar(id, sn, NONE, beam_healing_aps) \
-	w_cvar(id, sn, NONE, beam_healing_hmax) \
-	w_cvar(id, sn, NONE, beam_healing_hps) \
-	w_cvar(id, sn, NONE, beam_maxangle) \
-	w_cvar(id, sn, NONE, beam_nonplayerdamage) \
-	w_cvar(id, sn, NONE, beam_range) \
-	w_cvar(id, sn, NONE, beam_refire) \
-	w_cvar(id, sn, NONE, beam_returnspeed) \
-	w_cvar(id, sn, NONE, beam_tightness) \
-	w_cvar(id, sn, NONE, burst_ammo) \
-	w_cvar(id, sn, NONE, burst_damage) \
-	w_cvar(id, sn, NONE, burst_healing_aps) \
-	w_cvar(id, sn, NONE, burst_healing_hps) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifndef MENUQC
-#define ARC_MAX_SEGMENTS 20
-vector arc_shotorigin[4];
-.vector beam_start;
-.vector beam_dir;
-.vector beam_wantdir;
-.float beam_type;
-
-#define ARC_BT_MISS        0
-#define ARC_BT_WALL        1
-#define ARC_BT_HEAL        2
-#define ARC_BT_HIT         3
-#define ARC_BT_BURST_MISS  10
-#define ARC_BT_BURST_WALL  11
-#define ARC_BT_BURST_HEAL  12
-#define ARC_BT_BURST_HIT   13
-#define ARC_BT_BURSTMASK   10
-
-#define ARC_SF_SETTINGS    1
-#define ARC_SF_START       2
-#define ARC_SF_WANTDIR     4
-#define ARC_SF_BEAMDIR     8
-#define ARC_SF_BEAMTYPE    16
-#define ARC_SF_LOCALMASK   14
-#endif
-#ifdef SVQC
-ARC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.entity arc_beam;
-.float BUTTON_ATCK_prev; // for better animation control
-.float beam_prev;
-.float beam_initialized;
-.float beam_bursting;
-.float beam_teleporttime;
-#endif
-#ifdef CSQC
-void Ent_ReadArcBeam(float isnew);
-
-.vector beam_color;
-.float beam_alpha;
-.float beam_thickness;
-.float beam_traileffect;
-.float beam_hiteffect;
-.float beam_hitlight[4]; // 0: radius, 123: rgb
-.float beam_muzzleeffect;
-.float beam_muzzlelight[4]; // 0: radius, 123: rgb
-.string beam_image;
-
-.entity beam_muzzleentity;
-
-.float beam_degreespersegment;
-.float beam_distancepersegment;
-.float beam_usevieworigin;
-.float beam_initialized;
-.float beam_maxangle;
-.float beam_range;
-.float beam_returnspeed;
-.float beam_tightness;
-.vector beam_shotorigin;
-
-entity Draw_ArcBeam_callback_entity;
-float Draw_ArcBeam_callback_last_thickness;
-vector Draw_ArcBeam_callback_last_top; // NOTE: in same coordinate system as player.
-vector Draw_ArcBeam_callback_last_bottom; // NOTE: in same coordinate system as player.
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_arc(void) { weapon_defaultspawnfunc(WEP_ARC); }
-
-float W_Arc_Beam_Send(entity to, float sf)
-{
-	WriteByte(MSG_ENTITY, ENT_CLIENT_ARC_BEAM);
-
-	// Truncate information when this beam is displayed to the owner client
-	// - The owner client has no use for beam start position or directions,
-	//    it always figures this information out for itself with csqc code.
-	// - Spectating the owner also truncates this information.
-	float drawlocal = ((to == self.owner) || ((to.enemy == self.owner) && IS_SPEC(to)));
-	if(drawlocal) { sf &= ~ARC_SF_LOCALMASK; }
-
-	WriteByte(MSG_ENTITY, sf);
-
-	if(sf & ARC_SF_SETTINGS) // settings information
-	{
-		WriteShort(MSG_ENTITY, WEP_CVAR(arc, beam_degreespersegment));
-		WriteShort(MSG_ENTITY, WEP_CVAR(arc, beam_distancepersegment));
-		WriteShort(MSG_ENTITY, WEP_CVAR(arc, beam_maxangle));
-		WriteCoord(MSG_ENTITY, WEP_CVAR(arc, beam_range));
-		WriteShort(MSG_ENTITY, WEP_CVAR(arc, beam_returnspeed));
-		WriteByte(MSG_ENTITY, WEP_CVAR(arc, beam_tightness) * 10);
-
-		WriteByte(MSG_ENTITY, drawlocal);
-	}
-	if(sf & ARC_SF_START) // starting location
-	{
-		WriteCoord(MSG_ENTITY, self.beam_start_x);
-		WriteCoord(MSG_ENTITY, self.beam_start_y);
-		WriteCoord(MSG_ENTITY, self.beam_start_z);
-	}
-	if(sf & ARC_SF_WANTDIR) // want/aim direction
-	{
-		WriteCoord(MSG_ENTITY, self.beam_wantdir_x);
-		WriteCoord(MSG_ENTITY, self.beam_wantdir_y);
-		WriteCoord(MSG_ENTITY, self.beam_wantdir_z);
-	}
-	if(sf & ARC_SF_BEAMDIR) // beam direction
-	{
-		WriteCoord(MSG_ENTITY, self.beam_dir_x);
-		WriteCoord(MSG_ENTITY, self.beam_dir_y);
-		WriteCoord(MSG_ENTITY, self.beam_dir_z);
-	}
-	if(sf & ARC_SF_BEAMTYPE) // beam type
-	{
-		WriteByte(MSG_ENTITY, self.beam_type);
-	}
-
-	return TRUE;
-}
-
-void Reset_ArcBeam(entity player, vector forward)
-{
-	if (!player.arc_beam) {
-		return;
-	}
-	player.arc_beam.beam_dir = forward;
-	player.arc_beam.beam_teleporttime = time;
-}
-
-void W_Arc_Beam_Think(void)
-{
-	if(self != self.owner.arc_beam)
-	{
-		remove(self);
-		return;
-	}
-
-	if(
-		!IS_PLAYER(self.owner)
-		||
-		(self.owner.WEP_AMMO(ARC) <= 0 && !(self.owner.items & IT_UNLIMITED_WEAPON_AMMO))
-		||
-		self.owner.deadflag != DEAD_NO
-		||
-		(!self.owner.BUTTON_ATCK /* FIXME(Samual): && !self.beam_bursting */)
-		||
-		self.owner.frozen
-	)
-	{
-		if(self == self.owner.arc_beam) { self.owner.arc_beam = world; }
-		entity oldself = self;
-		self = self.owner;
-		if(!WEP_ACTION(WEP_ARC, WR_CHECKAMMO1) && !WEP_ACTION(WEP_ARC, WR_CHECKAMMO2))
-		{
-			// note: this doesn't force the switch
-			W_SwitchToOtherWeapon(self);
-		}
-		self = oldself;
-		remove(self);
-		return;
-	}
-
-	float burst = 0;
-	if(/*self.owner.BUTTON_ATCK2 || */self.beam_bursting)
-	{
-		if(!self.beam_bursting)
-			self.beam_bursting = TRUE;
-		burst = ARC_BT_BURSTMASK;
-	}
-
-	// decrease ammo
-	float coefficient = frametime;
-	if(!(self.owner.items & IT_UNLIMITED_WEAPON_AMMO))
-	{
-		float rootammo;
-		if(burst)
-			{ rootammo = WEP_CVAR(arc, burst_ammo); }
-		else
-			{ rootammo = WEP_CVAR(arc, beam_ammo); }
-
-		if(rootammo)
-		{
-			coefficient = min(coefficient, self.owner.WEP_AMMO(ARC) / rootammo);
-			self.owner.WEP_AMMO(ARC) = max(0, self.owner.WEP_AMMO(ARC) - (rootammo * frametime));
-		}
-	}
-
-	makevectors(self.owner.v_angle);
-
-	W_SetupShot_Range(
-		self.owner,
-		TRUE,
-		0,
-		"",
-		0,
-		WEP_CVAR(arc, beam_damage) * coefficient,
-		WEP_CVAR(arc, beam_range)
-	);
-
-	// After teleport, "lock" the beam until the teleport is confirmed.
-	if (time < self.beam_teleporttime + ANTILAG_LATENCY(self.owner)) {
-		w_shotdir = self.beam_dir;
-	}
-
-	// network information: shot origin and want/aim direction
-	if(self.beam_start != w_shotorg)
-	{
-		self.SendFlags |= ARC_SF_START;
-		self.beam_start = w_shotorg;
-	}
-	if(self.beam_wantdir != w_shotdir)
-	{
-		self.SendFlags |= ARC_SF_WANTDIR;
-		self.beam_wantdir = w_shotdir;
-	}
-
-	if(!self.beam_initialized)
-	{
-		self.beam_dir = w_shotdir;
-		self.beam_initialized = TRUE;
-	}
-
-	// WEAPONTODO: Detect player velocity so that the beam curves when moving too
-	// idea: blend together self.beam_dir with the inverted direction the player is moving in
-	// might have to make some special accomodation so that it only uses view_right and view_up
-
-	// note that if we do this, it'll always be corrected to a maximum angle by beam_maxangle handling
-
-	float segments; 
-	if(self.beam_dir != w_shotdir)
-	{
-		// calculate how much we're going to move the end of the beam to the want position
-		// WEAPONTODO (server and client):
-		// blendfactor never actually becomes 0 in this situation, which is a problem
-		// regarding precision... this means that self.beam_dir and w_shotdir approach
-		// eachother, however they never actually become the same value with this method.
-		// Perhaps we should do some form of rounding/snapping?
-		float angle = vlen(w_shotdir - self.beam_dir) * RAD2DEG;
-		if(angle && (angle > WEP_CVAR(arc, beam_maxangle)))
-		{
-			// if the angle is greater than maxangle, force the blendfactor to make this the maximum factor
-			float blendfactor = bound(
-				0,
-				(1 - (WEP_CVAR(arc, beam_returnspeed) * frametime)),
-				min(WEP_CVAR(arc, beam_maxangle) / angle, 1)
-			);
-			self.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (self.beam_dir * blendfactor));
-		}
-		else
-		{
-			// the radius is not too far yet, no worries :D
-			float blendfactor = bound(
-				0,
-				(1 - (WEP_CVAR(arc, beam_returnspeed) * frametime)),
-				1
-			);
-			self.beam_dir = normalize((w_shotdir * (1 - blendfactor)) + (self.beam_dir * blendfactor));
-		}
-
-		// network information: beam direction
-		self.SendFlags |= ARC_SF_BEAMDIR;
-
-		// calculate how many segments are needed
-		float max_allowed_segments;
-
-		if(WEP_CVAR(arc, beam_distancepersegment))
-		{
-			max_allowed_segments = min(
-				ARC_MAX_SEGMENTS,
-				1 + (vlen(w_shotdir / WEP_CVAR(arc, beam_distancepersegment)))
-			);
-		}
-		else { max_allowed_segments = ARC_MAX_SEGMENTS; }
-
-		if(WEP_CVAR(arc, beam_degreespersegment))
-		{
-			segments = bound(
-				1, 
-				(
-					min(
-						angle,
-						WEP_CVAR(arc, beam_maxangle)
-					)
-					/
-					WEP_CVAR(arc, beam_degreespersegment)
-				),
-				max_allowed_segments
-			);
-		}
-		else { segments = 1; }
-	}
-	else { segments = 1; }
-
-	vector beam_endpos = (w_shotorg + (self.beam_dir * WEP_CVAR(arc, beam_range)));
-	vector beam_controlpoint = w_shotorg + w_shotdir * (WEP_CVAR(arc, beam_range) * (1 - WEP_CVAR(arc, beam_tightness)));
-
-	float i;
-	float new_beam_type = 0;
-	vector last_origin = w_shotorg;
-	for(i = 1; i <= segments; ++i)
-	{
-		// WEAPONTODO (client):
-		// In order to do nice fading and pointing on the starting segment, we must always
-		// have that drawn as a separate triangle... However, that is difficult to do when
-		// keeping in mind the above problems and also optimizing the amount of segments
-		// drawn on screen at any given time. (Automatic beam quality scaling, essentially)
-
-		vector new_origin = bezier_quadratic_getpoint(
-			w_shotorg,
-			beam_controlpoint,
-			beam_endpos,
-			i / segments);
-		vector new_dir = normalize(new_origin - last_origin);
-
-		WarpZone_traceline_antilag(
-			self.owner,
-			last_origin,
-			new_origin,
-			MOVE_NORMAL,
-			self.owner,
-			ANTILAG_LATENCY(self.owner)
-		);
-
-		// Do all the transforms for warpzones right now, as we already
-		// "are" in the post-trace system (if we hit a player, that's
-		// always BEHIND the last passed wz).
-		last_origin = trace_endpos;
-		w_shotorg = WarpZone_TransformOrigin(WarpZone_trace_transform, w_shotorg);
-		beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint);
-		beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos);
-		new_dir = WarpZone_TransformVelocity(WarpZone_trace_transform, new_dir);
-
-		float is_player = (
-			trace_ent.classname == "player"
-			||
-			trace_ent.classname == "body"
-			||
-			(trace_ent.flags & FL_MONSTER)
-		);
-
-		if(trace_ent && trace_ent.takedamage && (is_player || WEP_CVAR(arc, beam_nonplayerdamage)))
-		{
-			// calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
-			// NO. trace_endpos should be just fine. If not,
-			// that's an engine bug that needs proper debugging.
-			vector hitorigin = trace_endpos;
-
-			float falloff = ExponentialFalloff(
-				WEP_CVAR(arc, beam_falloff_mindist),
-				WEP_CVAR(arc, beam_falloff_maxdist),
-				WEP_CVAR(arc, beam_falloff_halflifedist),
-				vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, hitorigin) - w_shotorg)
-			);
-
-			if(is_player && SAME_TEAM(self.owner, trace_ent))
-			{
-				float roothealth, rootarmor;
-				if(burst)
-				{
-					roothealth = WEP_CVAR(arc, burst_healing_hps);
-					rootarmor = WEP_CVAR(arc, burst_healing_aps);
-				}
-				else
-				{
-					roothealth = WEP_CVAR(arc, beam_healing_hps);
-					rootarmor = WEP_CVAR(arc, beam_healing_aps);
-				}
-
-				if(trace_ent.health <= WEP_CVAR(arc, beam_healing_hmax) && roothealth)
-				{
-					trace_ent.health = min(
-						trace_ent.health + (roothealth * coefficient),
-						WEP_CVAR(arc, beam_healing_hmax)
-					);
-				}
-				if(trace_ent.armorvalue <= WEP_CVAR(arc, beam_healing_amax) && rootarmor)
-				{
-					trace_ent.armorvalue = min(
-						trace_ent.armorvalue + (rootarmor * coefficient),
-						WEP_CVAR(arc, beam_healing_amax)
-					);
-				}
-
-				// stop rot, set visual effect
-				if(roothealth || rootarmor)
-				{
-					trace_ent.pauserothealth_finished = max(
-						trace_ent.pauserothealth_finished,
-						time + autocvar_g_balance_pause_health_rot
-					);
-					trace_ent.pauserotarmor_finished = max(
-						trace_ent.pauserotarmor_finished,
-						time + autocvar_g_balance_pause_armor_rot
-					);
-					new_beam_type = ARC_BT_HEAL;
-				}
-			}
-			else
-			{
-				float rootdamage;
-				if(is_player)
-				{
-					if(burst)
-						{ rootdamage = WEP_CVAR(arc, burst_damage); }
-					else
-						{ rootdamage = WEP_CVAR(arc, beam_damage); }
-				}
-				else
-					{ rootdamage = WEP_CVAR(arc, beam_nonplayerdamage); }
-
-				if(accuracy_isgooddamage(self.owner, trace_ent))
-				{
-					accuracy_add(
-						self.owner,
-						WEP_ARC,
-						0,
-						rootdamage * coefficient * falloff
-					);
-				}
-
-				Damage(
-					trace_ent,
-					self.owner,
-					self.owner,
-					rootdamage * coefficient * falloff,
-					WEP_ARC,
-					hitorigin,
-					WEP_CVAR(arc, beam_force) * new_dir * coefficient * falloff
-				);
-
-				new_beam_type = ARC_BT_HIT;
-			}
-			break; 
-		}
-		else if(trace_fraction != 1)
-		{
-			// we collided with geometry
-			new_beam_type = ARC_BT_WALL;
-			break;
-		}
-	}
-
-	// te_explosion(trace_endpos);
-
-	// if we're bursting, use burst visual effects
-	new_beam_type += burst;
-
-	// network information: beam type
-	if(new_beam_type != self.beam_type)
-	{
-		self.SendFlags |= ARC_SF_BEAMTYPE;
-		self.beam_type = new_beam_type;
-	}
-
-	self.owner.beam_prev = time;
-	self.nextthink = time;
-}
-
-void W_Arc_Beam(float burst)
-{
-	// FIXME(Samual): remove this when overheat and burst work.
-	if (burst)
-	{
-		centerprint(self, "^4NOTE:^7 Arc burst (secondary) is not implemented yet.");
-	}
-
-	// only play fire sound if 1 sec has passed since player let go the fire button
-	if(time - self.beam_prev > 1)
-	{
-		sound(self, CH_WEAPON_A, "weapons/lgbeam_fire.wav", VOL_BASE, ATTN_NORM);
-	}
-
-	entity beam = self.arc_beam = spawn();
-	beam.classname = "W_Arc_Beam";
-	beam.solid = SOLID_NOT;
-	beam.think = W_Arc_Beam_Think;
-	beam.owner = self;
-	beam.movetype = MOVETYPE_NONE;
-	beam.bot_dodge = TRUE;
-	beam.bot_dodgerating = WEP_CVAR(arc, beam_damage);
-	beam.beam_bursting = burst;
-	Net_LinkEntity(beam, FALSE, 0, W_Arc_Beam_Send);
-
-	entity oldself = self;
-	self = beam;
-	self.think();
-	self = oldself;
-}
-
-float W_Arc(float req)
-{
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			if(WEP_CVAR(arc, beam_botaimspeed))
-			{
-				self.BUTTON_ATCK = bot_aim(
-					WEP_CVAR(arc, beam_botaimspeed),
-					0,
-					WEP_CVAR(arc, beam_botaimlifetime),
-					FALSE
-				);
-			}
-			else
-			{
-				self.BUTTON_ATCK = bot_aim(
-					1000000,
-					0,
-					0.001,
-					FALSE
-				);
-			}
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			#if 0
-			if(self.arc_beam.beam_heat > threshold)
-			{
-				stop the beam somehow
-				play overheat animation
-			}
-			#endif
-
-			if(self.BUTTON_ATCK || self.BUTTON_ATCK2 /* FIXME(Samual): || self.arc_beam.beam_bursting */)
-			{
-				if(self.BUTTON_ATCK_prev)
-				{
-					#if 0
-					if(self.animstate_startframe == self.anim_shoot_x && self.animstate_numframes == self.anim_shoot_y)
-						weapon_thinkf(WFRAME_DONTCHANGE, autocvar_g_balance_arc_primary_animtime, w_ready);
-					else
-					#endif
-						weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
-				}
-
-				if((!self.arc_beam) || wasfreed(self.arc_beam))
-				{
-					if(weapon_prepareattack(!!self.BUTTON_ATCK2, 0))
-					{
-						W_Arc_Beam(!!self.BUTTON_ATCK2);
-						
-						if(!self.BUTTON_ATCK_prev)
-						{
-							weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
-							self.BUTTON_ATCK_prev = 1;
-						}
-					}
-				}
-			} 
-			else // todo
-			{
-				if(self.BUTTON_ATCK_prev != 0)
-				{
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(arc, beam_animtime), w_ready);
-					ATTACK_FINISHED(self) = time + WEP_CVAR(arc, beam_refire) * W_WeaponRateFactor();
-				}
-				self.BUTTON_ATCK_prev = 0;
-			}
-
-			#if 0
-			if(self.BUTTON_ATCK2)
-			if(weapon_prepareattack(1, autocvar_g_balance_arc_secondary_refire))
-			{
-				W_Arc_Attack2();
-				self.arc_count = autocvar_g_balance_arc_secondary_count;
-				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_arc_secondary_animtime, w_arc_checkattack);
-				self.arc_secondarytime = time + autocvar_g_balance_arc_secondary_refire2 * W_WeaponRateFactor();
-			}
-			#endif
-
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_arc.md3");
-			precache_model("models/weapons/v_arc.md3");
-			precache_model("models/weapons/h_arc.iqm");
-			precache_sound("weapons/lgbeam_fire.wav");
-			if(!arc_shotorigin[0])
-			{
-				arc_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 1);
-				arc_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 2);
-				arc_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 3);
-				arc_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_ARC), FALSE, FALSE, 4);
-			}
-			ARC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			return ((!WEP_CVAR(arc, beam_ammo)) || (self.WEP_AMMO(ARC) > 0));
-		}
-		case WR_CHECKAMMO2:
-		{
-			// arc currently has no secondary attack
-			return FALSE;
-			//return ((!WEP_CVAR(arc, burst_ammo)) || (self.WEP_AMMO(ARC) > 0));
-		}
-		case WR_CONFIG:
-		{
-			ARC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			return WEAPON_ARC_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-void Draw_ArcBeam_callback(vector start, vector hit, vector end)
-{
-	entity beam = Draw_ArcBeam_callback_entity;
-	vector transformed_view_org;
-	transformed_view_org = WarpZone_TransformOrigin(WarpZone_trace_transform, view_origin);
-
-	// Thickdir shall be perpendicular to the beam and to the view-to-beam direction (WEAPONTODO: WHY)
-	// WEAPONTODO: Wouldn't it be better to be perpendicular to the beam and to the view FORWARD direction?
-	vector thickdir = normalize(cross(normalize(start - hit), transformed_view_org - start));
-
-	vector hitorigin;
-
-	// draw segment
-	#if 0
-	if(trace_fraction != 1)
-	{
-		// calculate our own hit origin as trace_endpos tends to jump around annoyingly (to player origin?)
-		hitorigin = start + (Draw_ArcBeam_callback_new_dir * Draw_ArcBeam_callback_segmentdist * trace_fraction);
-		hitorigin = WarpZone_TransformOrigin(WarpZone_trace_transform, hitorigin);
-	}
-	else
-	{
-		hitorigin = hit;
-	}
-	#else
-	hitorigin = hit;
-	#endif
-
-	// decide upon thickness
-	float thickness = beam.beam_thickness;
-
-	// draw primary beam render
-	vector top    = hitorigin + (thickdir * thickness);
-	vector bottom = hitorigin - (thickdir * thickness);
-	
-	vector last_top = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_top);
-	vector last_bottom = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_bottom);
-
-	R_BeginPolygon(beam.beam_image, DRAWFLAG_NORMAL); // DRAWFLAG_ADDITIVE
-	R_PolygonVertex(
-		top,
-		'0 0.5 0' + ('0 0.5 0' * (thickness / beam.beam_thickness)),
-		beam.beam_color,
-		beam.beam_alpha
-	);
-	R_PolygonVertex(
-		last_top,
-		'0 0.5 0' + ('0 0.5 0' * (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
-		beam.beam_color,
-		beam.beam_alpha
-	);
-	R_PolygonVertex(
-		last_bottom,
-		'0 0.5 0' * (1 - (Draw_ArcBeam_callback_last_thickness / beam.beam_thickness)),
-		beam.beam_color,
-		beam.beam_alpha
-	);
-	R_PolygonVertex(
-		bottom,
-		'0 0.5 0' * (1 - (thickness / beam.beam_thickness)),
-		beam.beam_color,
-		beam.beam_alpha
-	);
-	R_EndPolygon();
-
-	// draw trailing particles
-	// NOTES:
-	//  - Don't use spammy particle counts here, use a FEW small particles around the beam
-	//  - We're not using WarpZone_TrailParticles here because we will handle warpzones ourselves.
-	if(beam.beam_traileffect)
-	{
-		trailparticles(beam, beam.beam_traileffect, start, hitorigin);
-	}
-
-	// set up for the next 
-	Draw_ArcBeam_callback_last_thickness = thickness;
-	Draw_ArcBeam_callback_last_top = WarpZone_UnTransformOrigin(WarpZone_trace_transform, top);
-	Draw_ArcBeam_callback_last_bottom = WarpZone_UnTransformOrigin(WarpZone_trace_transform, bottom);
-}
-
-void Reset_ArcBeam(void)
-{
-	entity e;
-	for (e = world; (e = findfloat(e, beam_usevieworigin, 1)); ) {
-		e.beam_initialized = FALSE;
-	}
-	for (e = world; (e = findfloat(e, beam_usevieworigin, 2)); ) {
-		e.beam_initialized = FALSE;
-	}
-}
-
-void Draw_ArcBeam(void)
-{
-	if(!self.beam_usevieworigin)
-	{
-		InterpolateOrigin_Do();
-	}
-
-	// origin = beam starting origin
-	// v_angle = wanted/aim direction
-	// angles = current direction of beam
-
-	vector start_pos;
-	vector wantdir; //= view_forward;
-	vector beamdir; //= self.beam_dir;
-
-	float segments;
-	if(self.beam_usevieworigin)
-	{
-		// WEAPONTODO:
-		// Currently we have to replicate nearly the same method of figuring
-		// out the shotdir that the server does... Ideally in the future we
-		// should be able to acquire this from a generalized function built
-		// into a weapon system for client code. 
-
-		// find where we are aiming
-		makevectors(warpzone_save_view_angles);
-		vector forward = v_forward;
-		vector right = v_right;
-		vector up = v_up;
-
-		// decide upon start position
-		if(self.beam_usevieworigin == 2)
-			{ start_pos = warpzone_save_view_origin; }
-		else
-			{ start_pos = self.origin; }
-
-		// trace forward with an estimation
-		WarpZone_TraceLine(
-			start_pos,
-			start_pos + forward * self.beam_range,
-			MOVE_NOMONSTERS,
-			self
-		);
-
-		// untransform in case our trace went through a warpzone
-		vector end_pos = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
-
-		// un-adjust trueaim if shotend is too close
-		if(vlen(end_pos - start_pos) < g_trueaim_minrange)
-			end_pos = start_pos + (forward * g_trueaim_minrange);
-
-		// move shot origin to the actual gun muzzle origin
-		vector origin_offset =
-			  right * -self.beam_shotorigin_y 
-			+ up * self.beam_shotorigin_z;
-
-		start_pos = start_pos + origin_offset;
-
-		// Move it also forward, but only as far as possible without hitting anything. Don't poke into walls!
-		traceline(start_pos, start_pos + forward * self.beam_shotorigin_x, MOVE_NORMAL, self);
-		start_pos = trace_endpos;
-
-		// calculate the aim direction now
-		wantdir = normalize(end_pos - start_pos);
-
-		if(!self.beam_initialized)
-		{
-			self.beam_dir = wantdir;
-			self.beam_initialized = TRUE;
-		}
-
-		if(self.beam_dir != wantdir)
-		{
-			// calculate how much we're going to move the end of the beam to the want position
-			// WEAPONTODO (server and client):
-			// blendfactor never actually becomes 0 in this situation, which is a problem
-			// regarding precision... this means that self.beam_dir and w_shotdir approach
-			// eachother, however they never actually become the same value with this method.
-			// Perhaps we should do some form of rounding/snapping?
-			float angle = vlen(wantdir - self.beam_dir) * RAD2DEG;
-			if(angle && (angle > self.beam_maxangle))
-			{
-				// if the angle is greater than maxangle, force the blendfactor to make this the maximum factor
-				float blendfactor = bound(
-					0,
-					(1 - (self.beam_returnspeed * frametime)),
-					min(self.beam_maxangle / angle, 1)
-				);
-				self.beam_dir = normalize((wantdir * (1 - blendfactor)) + (self.beam_dir * blendfactor));
-			}
-			else
-			{
-				// the radius is not too far yet, no worries :D
-				float blendfactor = bound(
-					0,
-					(1 - (self.beam_returnspeed * frametime)),
-					1
-				);
-				self.beam_dir = normalize((wantdir * (1 - blendfactor)) + (self.beam_dir * blendfactor));
-			}
-
-			// calculate how many segments are needed
-			float max_allowed_segments;
-
-			if(self.beam_distancepersegment)
-			{
-				max_allowed_segments = min(
-					ARC_MAX_SEGMENTS,
-					1 + (vlen(wantdir / self.beam_distancepersegment))
-				);
-			}
-			else { max_allowed_segments = ARC_MAX_SEGMENTS; }
-
-			if(self.beam_degreespersegment)
-			{
-				segments = bound(
-					1, 
-					(
-						min(
-							angle,
-							self.beam_maxangle
-						)
-						/
-						self.beam_degreespersegment
-					),
-					max_allowed_segments
-				);
-			}
-			else { segments = 1; }
-		}
-		else { segments = 1; }
-
-		// set the beam direction which the rest of the code will refer to
-		beamdir = self.beam_dir;
-
-		// finally, set self.angles to the proper direction so that muzzle attachment points in proper direction
-		self.angles = fixedvectoangles2(forward, up); // TODO(Samual): is this == warpzone_save_view_angles?
-	}
-	else
-	{
-		// set the values from the provided info from the networked entity
-		start_pos = self.origin;
-		wantdir = self.v_angle;
-		beamdir = self.angles;
-
-		if(beamdir != wantdir)
-		{
-			float angle = vlen(wantdir - beamdir) * RAD2DEG;
-
-			// calculate how many segments are needed
-			float max_allowed_segments;
-
-			if(self.beam_distancepersegment)
-			{
-				max_allowed_segments = min(
-					ARC_MAX_SEGMENTS,
-					1 + (vlen(wantdir / self.beam_distancepersegment))
-				);
-			}
-			else { max_allowed_segments = ARC_MAX_SEGMENTS; }
-
-			if(self.beam_degreespersegment)
-			{
-				segments = bound(
-					1, 
-					(
-						min(
-							angle,
-							self.beam_maxangle
-						)
-						/
-						self.beam_degreespersegment
-					),
-					max_allowed_segments
-				);
-			}
-			else { segments = 1; }
-		}
-		else { segments = 1; }
-	}
-
-	setorigin(self, start_pos);
-	self.beam_muzzleentity.angles_z = random() * 360; // WEAPONTODO: use avelocity instead?
-
-	vector beam_endpos = (start_pos + (beamdir * self.beam_range));
-	vector beam_controlpoint = start_pos + wantdir * (self.beam_range * (1 - self.beam_tightness));
-
-	Draw_ArcBeam_callback_entity = self;
-	Draw_ArcBeam_callback_last_thickness = 0;
-	Draw_ArcBeam_callback_last_top = start_pos;
-	Draw_ArcBeam_callback_last_bottom = start_pos;
-
-	vector last_origin = start_pos;
-	vector original_start_pos = start_pos;
-
-	float i;
-	for(i = 1; i <= segments; ++i)
-	{
-		// WEAPONTODO (client):
-		// In order to do nice fading and pointing on the starting segment, we must always
-		// have that drawn as a separate triangle... However, that is difficult to do when
-		// keeping in mind the above problems and also optimizing the amount of segments
-		// drawn on screen at any given time. (Automatic beam quality scaling, essentially)
-
-		vector new_origin = bezier_quadratic_getpoint(
-			start_pos,
-			beam_controlpoint,
-			beam_endpos,
-			i / segments);
-
-		WarpZone_TraceBox_ThroughZone(
-			last_origin,
-			'0 0 0',
-			'0 0 0',
-			new_origin,
-			MOVE_NORMAL,
-			world,
-			world,
-			Draw_ArcBeam_callback
-		);
-
-		// Do all the transforms for warpzones right now, as we already "are" in the post-trace
-		// system (if we hit a player, that's always BEHIND the last passed wz).
-		last_origin = trace_endpos;
-		start_pos = WarpZone_TransformOrigin(WarpZone_trace_transform, start_pos);
-		beam_controlpoint = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_controlpoint);
-		beam_endpos = WarpZone_TransformOrigin(WarpZone_trace_transform, beam_endpos);
-		beamdir = WarpZone_TransformVelocity(WarpZone_trace_transform, beamdir);
-		Draw_ArcBeam_callback_last_top = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_top);
-		Draw_ArcBeam_callback_last_bottom = WarpZone_TransformOrigin(WarpZone_trace_transform, Draw_ArcBeam_callback_last_bottom);
-
-		if(trace_fraction < 1) { break; }
-	}
-
-	// visual effects for startpoint and endpoint
-	if(self.beam_hiteffect)
-	{
-		// FIXME we really should do this on the server so it actually
-		// matches gameplay. What this client side stuff is doing is no
-		// more than guesswork.
-		pointparticles(
-			self.beam_hiteffect,
-			last_origin,
-			beamdir * -1,
-			frametime * 2
-		);
-	}
-	if(self.beam_hitlight[0])
-	{
-		adddynamiclight(
-			last_origin,
-			self.beam_hitlight[0],
-			vec3(
-				self.beam_hitlight[1],
-				self.beam_hitlight[2],
-				self.beam_hitlight[3]
-			)
-		);
-	}
-	if(self.beam_muzzleeffect)
-	{
-		pointparticles(
-			self.beam_muzzleeffect,
-			original_start_pos + wantdir * 20,
-			wantdir * 1000,
-			frametime * 0.1
-		);
-	}
-	if(self.beam_muzzlelight[0])
-	{
-		adddynamiclight(
-			original_start_pos + wantdir * 20,
-			self.beam_muzzlelight[0],
-			vec3(
-				self.beam_muzzlelight[1],
-				self.beam_muzzlelight[2],
-				self.beam_muzzlelight[3]
-			)
-		);
-	}
-
-	// cleanup
-	Draw_ArcBeam_callback_entity = world;
-	Draw_ArcBeam_callback_last_thickness = 0;
-	Draw_ArcBeam_callback_last_top = '0 0 0';
-	Draw_ArcBeam_callback_last_bottom = '0 0 0';
-}
-
-void Remove_ArcBeam(void)
-{
-	remove(self.beam_muzzleentity);
-	sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
-}
-
-void Ent_ReadArcBeam(float isnew)
-{
-	float sf = ReadByte();
-	entity flash;
-
-	if(isnew)
-	{
-		// calculate shot origin offset from gun alignment
-		float gunalign = autocvar_cl_gunalign;
-		if(gunalign != 1 && gunalign != 2 && gunalign != 4)
-			gunalign = 3; // default value
-		--gunalign;
-
-		self.beam_shotorigin = arc_shotorigin[gunalign];
-
-		// set other main attributes of the beam
-		self.draw = Draw_ArcBeam;
-		self.entremove = Remove_ArcBeam;
-		sound(self, CH_SHOTS_SINGLE, "weapons/lgbeam_fly.wav", VOL_BASE, ATTEN_NORM);
-
-		flash = spawn();
-		flash.owner = self;
-		flash.effects = EF_ADDITIVE | EF_FULLBRIGHT;
-		flash.drawmask = MASK_NORMAL;
-		flash.solid = SOLID_NOT;
-		flash.avelocity_z = 5000;
-		setattachment(flash, self, "");
-		setorigin(flash, '0 0 0');
-
-		self.beam_muzzleentity = flash;
-	}
-	else
-	{
-		flash = self.beam_muzzleentity;
-	}
-
-	if(sf & ARC_SF_SETTINGS) // settings information
-	{
-		self.beam_degreespersegment = ReadShort();
-		self.beam_distancepersegment = ReadShort();
-		self.beam_maxangle = ReadShort();
-		self.beam_range = ReadCoord();
-		self.beam_returnspeed = ReadShort();
-		self.beam_tightness = (ReadByte() / 10);
-
-		if(ReadByte())
-		{
-			if(autocvar_chase_active)
-				{ self.beam_usevieworigin = 1; }
-			else // use view origin
-				{ self.beam_usevieworigin = 2; }
-		}
-		else
-		{
-			self.beam_usevieworigin = 0;
-		}
-	}
-
-	if(!self.beam_usevieworigin)
-	{
-		// self.iflags = IFLAG_ORIGIN | IFLAG_ANGLES | IFLAG_V_ANGLE; // why doesn't this work?
-		self.iflags = IFLAG_ORIGIN;
-
-		InterpolateOrigin_Undo();
-	}
-
-	if(sf & ARC_SF_START) // starting location
-	{
-		self.origin_x = ReadCoord();
-		self.origin_y = ReadCoord();
-		self.origin_z = ReadCoord();
-	}
-	else if(self.beam_usevieworigin) // infer the location from player location
-	{
-		if(self.beam_usevieworigin == 2)
-		{
-			// use view origin
-			self.origin = view_origin;
-		}
-		else
-		{
-			// use player origin so that third person display still works
-			self.origin = getplayerorigin(player_localnum) + ('0 0 1' * getstati(STAT_VIEWHEIGHT));
-		}
-	}
-
-	setorigin(self, self.origin);
-
-	if(sf & ARC_SF_WANTDIR) // want/aim direction
-	{
-		self.v_angle_x = ReadCoord();
-		self.v_angle_y = ReadCoord();
-		self.v_angle_z = ReadCoord();
-	}
-
-	if(sf & ARC_SF_BEAMDIR) // beam direction
-	{
-		self.angles_x = ReadCoord();
-		self.angles_y = ReadCoord();
-		self.angles_z = ReadCoord();
-	}
-
-	if(sf & ARC_SF_BEAMTYPE) // beam type
-	{
-		self.beam_type = ReadByte();
-		switch(self.beam_type)
-		{
-			case ARC_BT_MISS:
-			{
-				self.beam_color = '-1 -1 1';
-				self.beam_alpha = 0.5;
-				self.beam_thickness = 8;
-				self.beam_traileffect = FALSE;
-				self.beam_hiteffect = particleeffectnum("electro_lightning");
-				self.beam_hitlight[0] = 0;
-				self.beam_hitlight[1] = 1;
-				self.beam_hitlight[2] = 1;
-				self.beam_hitlight[3] = 1;
-				self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash");
-				self.beam_muzzlelight[0] = 0;
-				self.beam_muzzlelight[1] = 1;
-				self.beam_muzzlelight[2] = 1;
-				self.beam_muzzlelight[3] = 1;
-				if(self.beam_muzzleeffect >= 0)
-				{
-					self.beam_image = "particles/lgbeam";
-					setmodel(flash, "models/flash.md3");
-					flash.alpha = self.beam_alpha;
-					flash.colormod = self.beam_color;
-					flash.scale = 0.5;
-				}
-				break;
-			}
-			case ARC_BT_WALL: // grenadelauncher_muzzleflash healray_muzzleflash
-			{
-				self.beam_color = '0.5 0.5 1';
-				self.beam_alpha = 0.5;
-				self.beam_thickness = 8;
-				self.beam_traileffect = FALSE;
-				self.beam_hiteffect = particleeffectnum("electro_lightning");
-				self.beam_hitlight[0] = 0;
-				self.beam_hitlight[1] = 1;
-				self.beam_hitlight[2] = 1;
-				self.beam_hitlight[3] = 1;
-				self.beam_muzzleeffect = -1; // particleeffectnum("grenadelauncher_muzzleflash");
-				self.beam_muzzlelight[0] = 0;
-				self.beam_muzzlelight[1] = 1;
-				self.beam_muzzlelight[2] = 1;
-				self.beam_muzzlelight[3] = 1;
-				self.beam_image = "particles/lgbeam";
-				if(self.beam_muzzleeffect >= 0)
-				{
-					setmodel(flash, "models/flash.md3");
-					flash.alpha = self.beam_alpha;
-					flash.colormod = self.beam_color;
-					flash.scale = 0.5;
-				}
-				break;
-			}
-			case ARC_BT_HEAL:
-			{
-				self.beam_color = '0 1 0';
-				self.beam_alpha = 0.5;
-				self.beam_thickness = 8;
-				self.beam_traileffect = FALSE;
-				self.beam_hiteffect = particleeffectnum("healray_impact"); 
-				self.beam_hitlight[0] = 0;
-				self.beam_hitlight[1] = 1;
-				self.beam_hitlight[2] = 1;
-				self.beam_hitlight[3] = 1;
-				self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash");
-				self.beam_muzzlelight[0] = 0;
-				self.beam_muzzlelight[1] = 1;
-				self.beam_muzzlelight[2] = 1;
-				self.beam_muzzlelight[3] = 1;
-				self.beam_image = "particles/lgbeam";
-				if(self.beam_muzzleeffect >= 0)
-				{
-					self.beam_image = "particles/lgbeam";
-					setmodel(flash, "models/flash.md3");
-					flash.alpha = self.beam_alpha;
-					flash.colormod = self.beam_color;
-					flash.scale = 0.5;
-				}
-				break;
-			}
-			case ARC_BT_HIT:
-			{
-				self.beam_color = '1 0 1';
-				self.beam_alpha = 0.5;
-				self.beam_thickness = 8;
-				self.beam_traileffect = FALSE;
-				self.beam_hiteffect = particleeffectnum("electro_lightning"); 
-				self.beam_hitlight[0] = 20;
-				self.beam_hitlight[1] = 1;
-				self.beam_hitlight[2] = 0;
-				self.beam_hitlight[3] = 0;
-				self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash");
-				self.beam_muzzlelight[0] = 50;
-				self.beam_muzzlelight[1] = 1;
-				self.beam_muzzlelight[2] = 0;
-				self.beam_muzzlelight[3] = 0;
-				self.beam_image = "particles/lgbeam";
-				if(self.beam_muzzleeffect >= 0)
-				{
-					self.beam_image = "particles/lgbeam";
-					setmodel(flash, "models/flash.md3");
-					flash.alpha = self.beam_alpha;
-					flash.colormod = self.beam_color;
-					flash.scale = 0.5;
-				}
-				break;
-			}
-			case ARC_BT_BURST_MISS:
-			{
-				self.beam_color = '-1 -1 1';
-				self.beam_alpha = 0.5;
-				self.beam_thickness = 14;
-				self.beam_traileffect = FALSE;
-				self.beam_hiteffect = particleeffectnum("electro_lightning"); 
-				self.beam_hitlight[0] = 0;
-				self.beam_hitlight[1] = 1;
-				self.beam_hitlight[2] = 1;
-				self.beam_hitlight[3] = 1;
-				self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash");
-				self.beam_muzzlelight[0] = 0;
-				self.beam_muzzlelight[1] = 1;
-				self.beam_muzzlelight[2] = 1;
-				self.beam_muzzlelight[3] = 1;
-				self.beam_image = "particles/lgbeam";
-				setmodel(flash, "models/flash.md3");
-				flash.alpha = self.beam_alpha;
-				flash.colormod = self.beam_color;
-				flash.scale = 0.5;
-				break;
-			}
-			case ARC_BT_BURST_WALL:
-			{
-				self.beam_color = '0.5 0.5 1';
-				self.beam_alpha = 0.5;
-				self.beam_thickness = 14;
-				self.beam_traileffect = FALSE;
-				self.beam_hiteffect = particleeffectnum("electro_lightning"); 
-				self.beam_hitlight[0] = 0;
-				self.beam_hitlight[1] = 1;
-				self.beam_hitlight[2] = 1;
-				self.beam_hitlight[3] = 1;
-				self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash");
-				self.beam_muzzlelight[0] = 0;
-				self.beam_muzzlelight[1] = 1;
-				self.beam_muzzlelight[2] = 1;
-				self.beam_muzzlelight[3] = 1;
-				self.beam_image = "particles/lgbeam";
-				if(self.beam_muzzleeffect >= 0)
-				{
-					self.beam_image = "particles/lgbeam";
-					setmodel(flash, "models/flash.md3");
-					flash.alpha = self.beam_alpha;
-					flash.colormod = self.beam_color;
-					flash.scale = 0.5;
-				}
-				break;
-			}
-			case ARC_BT_BURST_HEAL:
-			{
-				self.beam_color = '0 1 0';
-				self.beam_alpha = 0.5;
-				self.beam_thickness = 14;
-				self.beam_traileffect = FALSE;
-				self.beam_hiteffect = particleeffectnum("electro_lightning"); 
-				self.beam_hitlight[0] = 0;
-				self.beam_hitlight[1] = 1;
-				self.beam_hitlight[2] = 1;
-				self.beam_hitlight[3] = 1;
-				self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash");
-				self.beam_muzzlelight[0] = 0;
-				self.beam_muzzlelight[1] = 1;
-				self.beam_muzzlelight[2] = 1;
-				self.beam_muzzlelight[3] = 1;
-				self.beam_image = "particles/lgbeam";
-				if(self.beam_muzzleeffect >= 0)
-				{
-					self.beam_image = "particles/lgbeam";
-					setmodel(flash, "models/flash.md3");
-					flash.alpha = self.beam_alpha;
-					flash.colormod = self.beam_color;
-					flash.scale = 0.5;
-				}
-				break;
-			}
-			case ARC_BT_BURST_HIT:
-			{
-				self.beam_color = '1 0 1';
-				self.beam_alpha = 0.5;
-				self.beam_thickness = 14;
-				self.beam_traileffect = FALSE;
-				self.beam_hiteffect = particleeffectnum("electro_lightning"); 
-				self.beam_hitlight[0] = 0;
-				self.beam_hitlight[1] = 1;
-				self.beam_hitlight[2] = 1;
-				self.beam_hitlight[3] = 1;
-				self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash");
-				self.beam_muzzlelight[0] = 0;
-				self.beam_muzzlelight[1] = 1;
-				self.beam_muzzlelight[2] = 1;
-				self.beam_muzzlelight[3] = 1;
-				self.beam_image = "particles/lgbeam";
-				if(self.beam_muzzleeffect >= 0)
-				{
-					self.beam_image = "particles/lgbeam";
-					setmodel(flash, "models/flash.md3");
-					flash.alpha = self.beam_alpha;
-					flash.colormod = self.beam_color;
-					flash.scale = 0.5;
-				}
-				break;
-			}
-
-			// shouldn't be possible, but lets make it colorful if it does :D
-			default:
-			{
-				self.beam_color = randomvec();
-				self.beam_alpha = 1;
-				self.beam_thickness = 8;
-				self.beam_traileffect = FALSE;
-				self.beam_hiteffect = FALSE; 
-				self.beam_hitlight[0] = 0;
-				self.beam_hitlight[1] = 1;
-				self.beam_hitlight[2] = 1;
-				self.beam_hitlight[3] = 1;
-				self.beam_muzzleeffect = -1; //particleeffectnum("nex_muzzleflash");
-				self.beam_muzzlelight[0] = 0;
-				self.beam_muzzlelight[1] = 1;
-				self.beam_muzzlelight[2] = 1;
-				self.beam_muzzlelight[3] = 1;
-				self.beam_image = "particles/lgbeam";
-				if(self.beam_muzzleeffect >= 0)
-				{
-					self.beam_image = "particles/lgbeam";
-					setmodel(flash, "models/flash.md3");
-					flash.alpha = self.beam_alpha;
-					flash.colormod = self.beam_color;
-					flash.scale = 0.5;
-				}
-				break;
-			}
-		}
-	}
-
-	if(!self.beam_usevieworigin)
-	{
-		InterpolateOrigin_Note();
-	}
-}
-
-float W_Arc(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			// todo
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/lgbeam_fly.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_blaster.qc b/qcsrc/common/weapons/w_blaster.qc
deleted file mode 100644
index aa8d0a89b..000000000
--- a/qcsrc/common/weapons/w_blaster.qc
+++ /dev/null
@@ -1,296 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ BLASTER,
-/* function  */ W_Blaster,
-/* ammotype  */ ammo_none,
-/* impulse   */ 1,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ 0,
-/* color     */ '1 0.5 0.5',
-/* modelname */ "laser",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairlaser 0.4",
-/* wepimg    */ "weaponlaser",
-/* refname   */ "blaster",
-/* wepname   */ _("Blaster")
-);
-
-#define BLASTER_SETTINGS(w_cvar,w_prop) BLASTER_SETTINGS_LIST(w_cvar, w_prop, BLASTER, blaster)
-#define BLASTER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, delay) \
-	w_cvar(id, sn, BOTH, edgedamage) \
-	w_cvar(id, sn, BOTH, force) \
-	w_cvar(id, sn, BOTH, force_zscale) \
-	w_cvar(id, sn, BOTH, lifetime) \
-	w_cvar(id, sn, BOTH, radius) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, BOTH, shotangle) \
-	w_cvar(id, sn, BOTH, speed) \
-	w_cvar(id, sn, BOTH, spread) \
-	w_cvar(id, sn, NONE, secondary) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-BLASTER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.float blaster_damage;
-.float blaster_edgedamage;
-.float blaster_radius;
-.float blaster_force;
-.float blaster_lifetime;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_blaster(void) { weapon_defaultspawnfunc(WEP_BLASTER); }
-void spawnfunc_weapon_laser(void) { spawnfunc_weapon_blaster(); }
-
-void W_Blaster_Touch(void)
-{
-	PROJECTILE_TOUCH;
-
-	self.event_damage = func_null;
-
-	RadiusDamage(
-		self,
-		self.realowner,
-		self.blaster_damage,
-		self.blaster_edgedamage,
-		self.blaster_radius,
-		world,
-		world,
-		self.blaster_force,
-		self.projectiledeathtype,
-		other
-	);
-	
-	remove(self);
-}
-
-void W_Blaster_Think(void)
-{
-	self.movetype = MOVETYPE_FLY;
-	self.think = SUB_Remove;
-	self.nextthink = time + self.blaster_lifetime;
-	CSQCProjectile(self, TRUE, PROJECTILE_BLASTER, TRUE);
-}
-
-void W_Blaster_Attack(
-	float atk_deathtype,
-	float atk_shotangle,
-	float atk_damage,
-	float atk_edgedamage,
-	float atk_radius,
-	float atk_force,
-	float atk_speed,
-	float atk_spread,
-	float atk_delay,
-	float atk_lifetime)
-{
-	vector s_forward = v_forward * cos(atk_shotangle * DEG2RAD) + v_up * sin(atk_shotangle * DEG2RAD);
-
-	W_SetupShot_Dir(self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, atk_damage);
-	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	entity missile = spawn();
-	missile.owner = missile.realowner = self;
-	missile.classname = "blasterbolt";
-	missile.bot_dodge = TRUE;
-	missile.bot_dodgerating = atk_damage;
-	PROJECTILE_MAKETRIGGER(missile);
-
-	missile.blaster_damage = atk_damage;
-	missile.blaster_edgedamage = atk_edgedamage;
-	missile.blaster_radius = atk_radius;
-	missile.blaster_force = atk_force;
-	missile.blaster_lifetime = atk_lifetime;
-
-	setorigin(missile, w_shotorg);
-	setsize(missile, '0 0 0', '0 0 0');
-	
-	W_SetupProjVelocity_Explicit(
-		missile,
-		w_shotdir,
-		v_up,
-		atk_speed,
-		0,
-		0,
-		atk_spread,
-		FALSE
-	);
-
-	missile.angles = vectoangles(missile.velocity);
-
-	//missile.glow_color = 250; // 244, 250
-	//missile.glow_size = 120;
-
-	missile.touch = W_Blaster_Touch;
-	missile.flags = FL_PROJECTILE;
-	missile.missile_flags = MIF_SPLASH;
-	missile.projectiledeathtype = atk_deathtype; 
-	missile.think = W_Blaster_Think;
-	missile.nextthink = time + atk_delay;
-
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-
-	if(time >= missile.nextthink)
-	{
-		entity oldself;
-		oldself = self;
-		self = missile;
-		self.think();
-		self = oldself;
-	}
-}
-float W_Blaster(float request)
-{
-	switch(request)
-	{
-		case WR_AIM:
-		{
-			if(WEP_CVAR(blaster, secondary))
-			{
-				if((random() * (WEP_CVAR_PRI(blaster, damage) + WEP_CVAR_SEC(blaster, damage))) > WEP_CVAR_PRI(blaster, damage))
-					{ self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(blaster, speed), 0, WEP_CVAR_SEC(blaster, lifetime), FALSE); }
-				else
-					{ self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), FALSE); }
-			}
-			else
-				{ self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(blaster, speed), 0, WEP_CVAR_PRI(blaster, lifetime), FALSE); }
-
-			return TRUE;
-		}
-		
-		case WR_THINK:
-		{
-			if(self.BUTTON_ATCK)
-			{
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(blaster, refire)))
-				{
-					W_Blaster_Attack(
-						WEP_BLASTER,
-						WEP_CVAR_PRI(blaster, shotangle),
-						WEP_CVAR_PRI(blaster, damage),
-						WEP_CVAR_PRI(blaster, edgedamage),
-						WEP_CVAR_PRI(blaster, radius),
-						WEP_CVAR_PRI(blaster, force),
-						WEP_CVAR_PRI(blaster, speed),
-						WEP_CVAR_PRI(blaster, spread),
-						WEP_CVAR_PRI(blaster, delay),
-						WEP_CVAR_PRI(blaster, lifetime)
-					);
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(blaster, animtime), w_ready);
-				}
-			}
-			else if(self.BUTTON_ATCK2)
-			{
-				switch(WEP_CVAR(blaster, secondary))
-				{
-					case 0: // switch to last used weapon
-					{
-						if(self.switchweapon == WEP_BLASTER) // don't do this if already switching
-							W_LastWeapon();
-						break;
-					}
-
-					case 1: // normal projectile secondary
-					{
-						if(weapon_prepareattack(1, WEP_CVAR_SEC(blaster, refire)))
-						{
-							W_Blaster_Attack(
-								WEP_BLASTER | HITTYPE_SECONDARY,
-								WEP_CVAR_SEC(blaster, shotangle),
-								WEP_CVAR_SEC(blaster, damage),
-								WEP_CVAR_SEC(blaster, edgedamage),
-								WEP_CVAR_SEC(blaster, radius),
-								WEP_CVAR_SEC(blaster, force),
-								WEP_CVAR_SEC(blaster, speed),
-								WEP_CVAR_SEC(blaster, spread),
-								WEP_CVAR_SEC(blaster, delay),
-								WEP_CVAR_SEC(blaster, lifetime)
-							);
-							weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(blaster, animtime), w_ready);
-						}
-
-						break;
-					}
-				}
-			}
-			return TRUE;
-		}
-		
-		case WR_INIT: 
-		{
-			precache_model("models/weapons/g_laser.md3");
-			precache_model("models/weapons/v_laser.md3");
-			precache_model("models/weapons/h_laser.iqm");
-			precache_sound("weapons/lasergun_fire.wav");
-			BLASTER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		
-		case WR_SETUP:
-		{
-			self.ammo_field = ammo_none;
-			return TRUE;
-		}
-		
-		case WR_CHECKAMMO1:
-		case WR_CHECKAMMO2:
-		{
-			return TRUE; // laser has infinite ammo
-		}
-		
-		case WR_CONFIG:
-		{
-			BLASTER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_BLASTER_SUICIDE;
-		}
-		
-		case WR_KILLMESSAGE:
-		{
-			return WEAPON_BLASTER_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Blaster(float request)
-{
-	switch(request)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 6;
-			pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1);
-			if(!w_issilent) { sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); }
-			return TRUE;
-		}
-		
-		case WR_INIT:
-		{
-			precache_sound("weapons/laserimpact.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_crylink.qc b/qcsrc/common/weapons/w_crylink.qc
deleted file mode 100644
index d17826a92..000000000
--- a/qcsrc/common/weapons/w_crylink.qc
+++ /dev/null
@@ -1,730 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ CRYLINK,
-/* function  */ W_Crylink,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 6,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 0.5 1',
-/* modelname */ "crylink",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshaircrylink 0.4",
-/* wepimg    */ "weaponcrylink",
-/* refname   */ "crylink",
-/* wepname   */ _("Crylink")
-);
-
-#define CRYLINK_SETTINGS(w_cvar,w_prop) CRYLINK_SETTINGS_LIST(w_cvar, w_prop, CRYLINK, crylink)
-#define CRYLINK_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, ammo) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, edgedamage) \
-	w_cvar(id, sn, BOTH, radius) \
-	w_cvar(id, sn, BOTH, force) \
-	w_cvar(id, sn, BOTH, spread) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, BOTH, speed) \
-	w_cvar(id, sn, BOTH, shots) \
-	w_cvar(id, sn, BOTH, bounces) \
-	w_cvar(id, sn, BOTH, bouncedamagefactor) \
-	w_cvar(id, sn, BOTH, middle_lifetime) \
-	w_cvar(id, sn, BOTH, middle_fadetime) \
-	w_cvar(id, sn, BOTH, other_lifetime) \
-	w_cvar(id, sn, BOTH, other_fadetime) \
-	w_cvar(id, sn, BOTH, linkexplode) \
-	w_cvar(id, sn, BOTH, joindelay) \
-	w_cvar(id, sn, BOTH, joinspread) \
-	w_cvar(id, sn, BOTH, joinexplode) \
-	w_cvar(id, sn, BOTH, joinexplode_damage) \
-	w_cvar(id, sn, BOTH, joinexplode_edgedamage) \
-	w_cvar(id, sn, BOTH, joinexplode_radius) \
-	w_cvar(id, sn, BOTH, joinexplode_force) \
-	w_cvar(id, sn, SEC,  spreadtype) \
-	w_cvar(id, sn, NONE, secondary) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-CRYLINK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.float gravity;
-.float crylink_waitrelease;
-.entity crylink_lastgroup;
-
-.entity queuenext;
-.entity queueprev;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_crylink(void) { weapon_defaultspawnfunc(WEP_CRYLINK); }
-
-void W_Crylink_CheckLinks(entity e)
-{
-	float i;
-	entity p;
-
-	if(e == world)
-		error("W_Crylink_CheckLinks: entity is world");
-	if(e.classname != "spike" || wasfreed(e))
-		error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e)));
-
-	p = e;
-	for(i = 0; i < 1000; ++i)
-	{
-		if(p.queuenext.queueprev != p || p.queueprev.queuenext != p)
-			error("W_Crylink_CheckLinks: queue is inconsistent");
-		p = p.queuenext;
-		if(p == e)
-			break;
-	}
-	if(i >= 1000)
-		error("W_Crylink_CheckLinks: infinite chain");
-}
-
-void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next)
-{
-	W_Crylink_CheckLinks(next);
-	if(me == own.crylink_lastgroup)
-		own.crylink_lastgroup = ((me == next) ? world : next);
-	prev.queuenext = next;
-	next.queueprev = prev;
-	me.classname = "spike_oktoremove";
-	if(me != next)
-		W_Crylink_CheckLinks(next);
-}
-
-void W_Crylink_Dequeue(entity e)
-{
-	W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext);
-}
-
-void W_Crylink_Reset(void)
-{
-	W_Crylink_Dequeue(self);
-	remove(self);
-}
-
-// force projectile to explode
-void W_Crylink_LinkExplode(entity e, entity e2)
-{
-	float a;
-
-	if(e == e2)
-		return;
-
-	a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1);
-
-	if(e == e.realowner.crylink_lastgroup)
-		e.realowner.crylink_lastgroup = world;
-		
-	float isprimary = !(e.projectiledeathtype & HITTYPE_SECONDARY);
-		
-	RadiusDamage(e, e.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * a, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * a, WEP_CVAR_BOTH(crylink, isprimary, radius), world, world, WEP_CVAR_BOTH(crylink, isprimary, force) * a, e.projectiledeathtype, other);
-
-	W_Crylink_LinkExplode(e.queuenext, e2);
-
-	e.classname = "spike_oktoremove";
-	remove(e);
-}
-
-// adjust towards center
-// returns the origin where they will meet... and the time till the meeting is
-// stored in w_crylink_linkjoin_time.
-// could possibly network this origin and time, and display a special particle
-// effect when projectiles meet there :P
-// jspeed: joining speed (calculate this as join spread * initial speed)
-float w_crylink_linkjoin_time;
-vector W_Crylink_LinkJoin(entity e, float jspeed)
-{
-	vector avg_origin, avg_velocity;
-	vector targ_origin;
-	float avg_dist, n;
-	entity p;
-
-	// FIXME remove this debug code
-	W_Crylink_CheckLinks(e);
-
-	w_crylink_linkjoin_time = 0;
-
-	avg_origin = e.origin;
-	avg_velocity = e.velocity;
-	n = 1;
-	for(p = e; (p = p.queuenext) != e; )
-	{
-		avg_origin += WarpZone_RefSys_TransformOrigin(p, e, p.origin);
-		avg_velocity += WarpZone_RefSys_TransformVelocity(p, e, p.velocity);
-		++n;
-	}
-	avg_origin *= (1.0 / n);
-	avg_velocity *= (1.0 / n);
-
-	if(n < 2)
-		return avg_origin; // nothing to do
-
-	// yes, mathematically we can do this in ONE step, but beware of 32bit floats...
-	avg_dist = pow(vlen(e.origin - avg_origin), 2);
-	for(p = e; (p = p.queuenext) != e; )
-		avg_dist += pow(vlen(WarpZone_RefSys_TransformOrigin(p, e, p.origin) - avg_origin), 2);
-	avg_dist *= (1.0 / n);
-	avg_dist = sqrt(avg_dist);
-
-	if(avg_dist == 0)
-		return avg_origin; // no change needed
-
-	if(jspeed == 0)
-	{
-		e.velocity = avg_velocity;
-		UpdateCSQCProjectile(e);
-		for(p = e; (p = p.queuenext) != e; )
-		{
-			p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity);
-			UpdateCSQCProjectile(p);
-		}
-		targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE
-	}
-	else
-	{
-		w_crylink_linkjoin_time = avg_dist / jspeed;
-		targ_origin = avg_origin + w_crylink_linkjoin_time * avg_velocity;
-
-		e.velocity = (targ_origin - e.origin) * (1.0 / w_crylink_linkjoin_time);
-		UpdateCSQCProjectile(e);
-		for(p = e; (p = p.queuenext) != e; )
-		{
-			p.velocity = WarpZone_RefSys_TransformVelocity(e, p, (targ_origin - WarpZone_RefSys_TransformOrigin(p, e, p.origin)) * (1.0 / w_crylink_linkjoin_time));
-			UpdateCSQCProjectile(p);
-		}
-
-		// analysis:
-		//   jspeed -> +infinity:
-		//      w_crylink_linkjoin_time -> +0
-		//      targ_origin -> avg_origin
-		//      p->velocity -> HUEG towards center
-		//   jspeed -> 0:
-		//      w_crylink_linkjoin_time -> +/- infinity
-		//      targ_origin -> avg_velocity * +/- infinity
-		//      p->velocity -> avg_velocity
-		//   jspeed -> -infinity:
-		//      w_crylink_linkjoin_time -> -0
-		//      targ_origin -> avg_origin
-		//      p->velocity -> HUEG away from center
-	}
-
-	W_Crylink_CheckLinks(e);
-
-	return targ_origin;
-}
-
-void W_Crylink_LinkJoinEffect_Think(void)
-{
-	// is there at least 2 projectiles very close?
-	entity e, p;
-	float n;
-	e = self.owner.crylink_lastgroup;
-	n = 0;
-	if(e)
-	{
-		if(vlen(e.origin - self.origin) < vlen(e.velocity) * frametime)
-			++n;
-		for(p = e; (p = p.queuenext) != e; )
-		{
-			if(vlen(p.origin - self.origin) < vlen(p.velocity) * frametime)
-				++n;
-		}
-		if(n >= 2)
-		{
-			float isprimary = !(e.projectiledeathtype & HITTYPE_SECONDARY);
-			
-			if(WEP_CVAR_BOTH(crylink, isprimary, joinexplode))
-			{
-				n /= WEP_CVAR_BOTH(crylink, isprimary, shots);
-				RadiusDamage(
-					e,
-					e.realowner,
-					WEP_CVAR_BOTH(crylink, isprimary, joinexplode_damage) * n,
-					WEP_CVAR_BOTH(crylink, isprimary, joinexplode_edgedamage) * n,
-					WEP_CVAR_BOTH(crylink, isprimary, joinexplode_radius) * n,
-					e.realowner,
-					world,
-					WEP_CVAR_BOTH(crylink, isprimary, joinexplode_force) * n,
-					e.projectiledeathtype,
-					other
-				);
-				pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
-			}
-		}
-	}
-	remove(self);
-}
-
-float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad)
-{
-	entity head = WarpZone_FindRadius((projectile.origin + (projectile.mins + projectile.maxs) * 0.5), rad + MAX_DAMAGEEXTRARADIUS, FALSE);
-	float hit_friendly = 0;
-	float hit_enemy = 0;
-
-	while(head)
-	{
-		if((head.takedamage != DAMAGE_NO) && (head.deadflag == DEAD_NO))
-		{
-			if(SAME_TEAM(head, projectile.realowner))
-				++hit_friendly;
-			else
-				++hit_enemy;
-		}
-			
-		head = head.chain;
-	}
-
-	return (hit_enemy ? FALSE : hit_friendly);
-}
-
-// NO bounce protection, as bounces are limited!
-void W_Crylink_Touch(void)
-{
-	float finalhit;
-	float f;
-	float isprimary = !(self.projectiledeathtype & HITTYPE_SECONDARY);
-	PROJECTILE_TOUCH;
-
-	float a;
-	a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1);
-
-	finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO));
-	if(finalhit)
-		f = 1;
-	else
-		f = WEP_CVAR_BOTH(crylink, isprimary, bouncedamagefactor);
-	if(a)
-		f *= a;
-
-	float totaldamage = RadiusDamage(self, self.realowner, WEP_CVAR_BOTH(crylink, isprimary, damage) * f, WEP_CVAR_BOTH(crylink, isprimary, edgedamage) * f, WEP_CVAR_BOTH(crylink, isprimary, radius), world, world, WEP_CVAR_BOTH(crylink, isprimary, force) * f, self.projectiledeathtype, other);
-		
-	if(totaldamage && ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 2) || ((WEP_CVAR_BOTH(crylink, isprimary, linkexplode) == 1) && !W_Crylink_Touch_WouldHitFriendly(self, WEP_CVAR_BOTH(crylink, isprimary, radius)))))
-	{
-		if(self == self.realowner.crylink_lastgroup)
-			self.realowner.crylink_lastgroup = world;
-		W_Crylink_LinkExplode(self.queuenext, self);
-		self.classname = "spike_oktoremove";
-		remove(self);
-		return;
-	}
-	else if(finalhit)
-	{
-		// just unlink
-		W_Crylink_Dequeue(self);
-		remove(self);
-		return;
-	}
-	self.cnt = self.cnt - 1;
-	self.angles = vectoangles(self.velocity);
-	self.owner = world;
-	self.projectiledeathtype |= HITTYPE_BOUNCE;
-	// commented out as it causes a little hitch...
-	//if(proj.cnt == 0)
-	//	CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE);
-}
-
-void W_Crylink_Fadethink(void)
-{
-	W_Crylink_Dequeue(self);
-	remove(self);
-}
-
-void W_Crylink_Attack(void)
-{
-	float counter, shots;
-	entity proj, prevproj, firstproj;
-	vector s;
-	vector forward, right, up;
-	float maxdmg;
-
-	W_DecreaseAmmo(WEP_CVAR_PRI(crylink, ammo));
-
-	maxdmg = WEP_CVAR_PRI(crylink, damage) * WEP_CVAR_PRI(crylink, shots);
-	maxdmg *= 1 + WEP_CVAR_PRI(crylink, bouncedamagefactor) * WEP_CVAR_PRI(crylink, bounces);
-	if(WEP_CVAR_PRI(crylink, joinexplode))
-		maxdmg += WEP_CVAR_PRI(crylink, joinexplode_damage);
-
-	W_SetupShot(self, FALSE, 2, "weapons/crylink_fire.wav", CH_WEAPON_A, maxdmg);
-	forward = v_forward;
-	right = v_right;
-	up = v_up;
-
-	shots = WEP_CVAR_PRI(crylink, shots);
-	pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
-	proj = prevproj = firstproj = world;
-	for(counter = 0; counter < shots; ++counter)
-	{
-		proj = spawn();
-		proj.reset = W_Crylink_Reset;
-		proj.realowner = proj.owner = self;
-		proj.classname = "spike";
-		proj.bot_dodge = TRUE;
-		proj.bot_dodgerating = WEP_CVAR_PRI(crylink, damage);
-		if(shots == 1) {
-			proj.queuenext = proj;
-			proj.queueprev = proj;
-		}
-		else if(counter == 0) { // first projectile, store in firstproj for now
-			firstproj = proj;
-		}
-		else if(counter == shots - 1) { // last projectile, link up with first projectile
-			prevproj.queuenext = proj;
-			firstproj.queueprev = proj;
-			proj.queuenext = firstproj;
-			proj.queueprev = prevproj;
-		}
-		else { // else link up with previous projectile
-			prevproj.queuenext = proj;
-			proj.queueprev = prevproj;
-		}
-
-		prevproj = proj;
-
-		proj.movetype = MOVETYPE_BOUNCEMISSILE;
-		PROJECTILE_MAKETRIGGER(proj);
-		proj.projectiledeathtype = WEP_CRYLINK;
-		//proj.gravity = 0.001;
-
-		setorigin(proj, w_shotorg);
-		setsize(proj, '0 0 0', '0 0 0');
-
-
-		s = '0 0 0';
-		if(counter == 0)
-			s = '0 0 0';
-		else
-		{
-			makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
-			s_y = v_forward_x;
-			s_z = v_forward_y;
-		}
-		s = s * WEP_CVAR_PRI(crylink, spread) * g_weaponspreadfactor;
-		W_SetupProjVelocity_Explicit(proj, w_shotdir + right * s_y + up * s_z, v_up, WEP_CVAR_PRI(crylink, speed), 0, 0, 0, FALSE);
-		proj.touch = W_Crylink_Touch;
-
-		proj.think = W_Crylink_Fadethink;
-		if(counter == 0)
-		{
-			proj.fade_time = time + WEP_CVAR_PRI(crylink, middle_lifetime);
-			proj.fade_rate = 1 / WEP_CVAR_PRI(crylink, middle_fadetime);
-			proj.nextthink = time + WEP_CVAR_PRI(crylink, middle_lifetime) + WEP_CVAR_PRI(crylink, middle_fadetime);
-		}
-		else
-		{
-			proj.fade_time = time + WEP_CVAR_PRI(crylink, other_lifetime);
-			proj.fade_rate = 1 / WEP_CVAR_PRI(crylink, other_fadetime);
-			proj.nextthink = time + WEP_CVAR_PRI(crylink, other_lifetime) + WEP_CVAR_PRI(crylink, other_fadetime);
-		}
-		proj.teleport_time = time + WEP_CVAR_PRI(crylink, joindelay);
-		proj.cnt = WEP_CVAR_PRI(crylink, bounces);
-		//proj.scale = 1 + 1 * proj.cnt;
-
-		proj.angles = vectoangles(proj.velocity);
-
-		//proj.glow_size = 20;
-
-		proj.flags = FL_PROJECTILE;
-		proj.missile_flags = MIF_SPLASH;
-    
-		CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE);
-
-		other = proj; MUTATOR_CALLHOOK(EditProjectile);
-	}
-	if(WEP_CVAR_PRI(crylink, joinspread) != 0)
-	{
-		self.crylink_lastgroup = proj;
-		W_Crylink_CheckLinks(proj);
-		self.crylink_waitrelease = 1;
-	}
-}
-
-void W_Crylink_Attack2(void)
-{
-	float counter, shots;
-	entity proj, prevproj, firstproj;
-	vector s;
-	vector forward, right, up;
-	float maxdmg;
-
-	W_DecreaseAmmo(WEP_CVAR_SEC(crylink, ammo));
-
-	maxdmg = WEP_CVAR_SEC(crylink, damage) * WEP_CVAR_SEC(crylink, shots);
-	maxdmg *= 1 + WEP_CVAR_SEC(crylink, bouncedamagefactor) * WEP_CVAR_SEC(crylink, bounces);
-	if(WEP_CVAR_SEC(crylink, joinexplode))
-		maxdmg += WEP_CVAR_SEC(crylink, joinexplode_damage);
-
-	W_SetupShot(self, FALSE, 2, "weapons/crylink_fire2.wav", CH_WEAPON_A, maxdmg);
-	forward = v_forward;
-	right = v_right;
-	up = v_up;
-
-	shots = WEP_CVAR_SEC(crylink, shots);
-	pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
-	proj = prevproj = firstproj = world;
-	for(counter = 0; counter < shots; ++counter)
-	{
-		proj = spawn();
-		proj.reset = W_Crylink_Reset;
-		proj.realowner = proj.owner = self;
-		proj.classname = "spike";
-		proj.bot_dodge = TRUE;
-		proj.bot_dodgerating = WEP_CVAR_SEC(crylink, damage);
-		if(shots == 1) {
-			proj.queuenext = proj;
-			proj.queueprev = proj;
-		}
-		else if(counter == 0) { // first projectile, store in firstproj for now
-			firstproj = proj;
-		}
-		else if(counter == shots - 1) { // last projectile, link up with first projectile
-			prevproj.queuenext = proj;
-			firstproj.queueprev = proj;
-			proj.queuenext = firstproj;
-			proj.queueprev = prevproj;
-		}
-		else { // else link up with previous projectile
-			prevproj.queuenext = proj;
-			proj.queueprev = prevproj;
-		}
-
-		prevproj = proj;
-
-		proj.movetype = MOVETYPE_BOUNCEMISSILE;
-		PROJECTILE_MAKETRIGGER(proj);
-		proj.projectiledeathtype = WEP_CRYLINK | HITTYPE_SECONDARY;
-		//proj.gravity = 0.001;
-
-		setorigin(proj, w_shotorg);
-		setsize(proj, '0 0 0', '0 0 0');
-
-		if(WEP_CVAR_SEC(crylink, spreadtype) == 1)
-		{
-			s = '0 0 0';
-			if(counter == 0)
-				s = '0 0 0';
-			else
-			{
-				makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
-				s_y = v_forward_x;
-				s_z = v_forward_y;
-			}
-			s = s * WEP_CVAR_SEC(crylink, spread) * g_weaponspreadfactor;
-			s = w_shotdir + right * s_y + up * s_z;
-		}
-		else
-		{
-			s = (w_shotdir + (((counter + 0.5) / shots) * 2 - 1) * v_right * WEP_CVAR_SEC(crylink, spread) * g_weaponspreadfactor);
-		}
-
-		W_SetupProjVelocity_Explicit(proj, s, v_up, WEP_CVAR_SEC(crylink, speed), 0, 0, 0, FALSE);
-		proj.touch = W_Crylink_Touch;
-		proj.think = W_Crylink_Fadethink;
-		if(counter == (shots - 1) / 2)
-		{
-			proj.fade_time = time + WEP_CVAR_SEC(crylink, middle_lifetime);
-			proj.fade_rate = 1 / WEP_CVAR_SEC(crylink, middle_fadetime);
-			proj.nextthink = time + WEP_CVAR_SEC(crylink, middle_lifetime) + WEP_CVAR_SEC(crylink, middle_fadetime);
-		}
-		else
-		{
-			proj.fade_time = time + WEP_CVAR_SEC(crylink, other_lifetime);
-			proj.fade_rate = 1 / WEP_CVAR_SEC(crylink, other_fadetime);
-			proj.nextthink = time + WEP_CVAR_SEC(crylink, other_lifetime) + WEP_CVAR_SEC(crylink, other_fadetime);
-		}
-		proj.teleport_time = time + WEP_CVAR_SEC(crylink, joindelay);
-		proj.cnt = WEP_CVAR_SEC(crylink, bounces);
-		//proj.scale = 1 + 1 * proj.cnt;
-
-		proj.angles = vectoangles(proj.velocity);
-
-		//proj.glow_size = 20;
-
-		proj.flags = FL_PROJECTILE;
-        proj.missile_flags = MIF_SPLASH;
-        
-		CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE);
-
-		other = proj; MUTATOR_CALLHOOK(EditProjectile);
-	}
-	if(WEP_CVAR_SEC(crylink, joinspread) != 0)
-	{
-		self.crylink_lastgroup = proj;
-		W_Crylink_CheckLinks(proj);
-		self.crylink_waitrelease = 2;
-	}
-}
-
-float W_Crylink(float req)
-{
-	float ammo_amount;
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			if(random() < 0.10)
-				self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(crylink, speed), 0, WEP_CVAR_PRI(crylink, middle_lifetime), FALSE);
-			else
-				self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(crylink, speed), 0, WEP_CVAR_SEC(crylink, middle_lifetime), FALSE);
-				
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo))) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-
-			if(self.BUTTON_ATCK)
-			{
-				if(self.crylink_waitrelease != 1)
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(crylink, refire)))
-				{
-					W_Crylink_Attack();
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(crylink, animtime), w_ready);
-				}
-			}
-
-			if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary)
-			{
-				if(self.crylink_waitrelease != 2)
-				if(weapon_prepareattack(1, WEP_CVAR_SEC(crylink, refire)))
-				{
-					W_Crylink_Attack2();
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(crylink, animtime), w_ready);
-				}
-			}
-
-			if((self.crylink_waitrelease == 1 && !self.BUTTON_ATCK) || (self.crylink_waitrelease == 2 && !self.BUTTON_ATCK2))
-			{
-				if(!self.crylink_lastgroup || time > self.crylink_lastgroup.teleport_time)
-				{
-					// fired and released now!
-					if(self.crylink_lastgroup)
-					{
-						vector pos;
-						entity linkjoineffect;
-						float isprimary = (self.crylink_waitrelease == 1);
-						
-						pos = W_Crylink_LinkJoin(self.crylink_lastgroup, WEP_CVAR_BOTH(crylink, isprimary, joinspread) * WEP_CVAR_BOTH(crylink, isprimary, speed));
-
-						linkjoineffect = spawn();
-						linkjoineffect.think = W_Crylink_LinkJoinEffect_Think;
-						linkjoineffect.classname = "linkjoineffect";
-						linkjoineffect.nextthink = time + w_crylink_linkjoin_time;
-						linkjoineffect.owner = self;
-						setorigin(linkjoineffect, pos);
-					}
-					self.crylink_waitrelease = 0;
-					if(!W_Crylink(WR_CHECKAMMO1) && !W_Crylink(WR_CHECKAMMO2))
-					if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-					{
-						// ran out of ammo!
-						self.cnt = WEP_CRYLINK;
-						self.switchweapon = w_getbestweapon(self);
-					}
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_crylink.md3");
-			precache_model("models/weapons/v_crylink.md3");
-			precache_model("models/weapons/h_crylink.iqm");
-			precache_sound("weapons/crylink_fire.wav");
-			precache_sound("weapons/crylink_fire2.wav");
-			precache_sound("weapons/crylink_linkjoin.wav");
-			CRYLINK_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			// don't "run out of ammo" and switch weapons while waiting for release
-			if(self.crylink_lastgroup && self.crylink_waitrelease)
-				return TRUE;
-
-			ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_PRI(crylink, ammo);
-			ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= WEP_CVAR_PRI(crylink, ammo);
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			// don't "run out of ammo" and switch weapons while waiting for release
-			if(self.crylink_lastgroup && self.crylink_waitrelease)
-				return TRUE;
-
-			ammo_amount = self.WEP_AMMO(CRYLINK) >= WEP_CVAR_SEC(crylink, ammo);
-			ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= WEP_CVAR_SEC(crylink, ammo);
-			return ammo_amount;
-		}
-		case WR_CONFIG:
-		{
-			CRYLINK_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(min(WEP_CVAR_PRI(crylink, ammo), WEP_CVAR_SEC(crylink, ammo)), "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_CRYLINK_SUICIDE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			return WEAPON_CRYLINK_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Crylink(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 2;
-			if(w_deathtype & HITTYPE_SECONDARY)
-			{
-				pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1);
-				if(!w_issilent)
-					sound(self, CH_SHOTS, "weapons/crylink_impact2.wav", VOL_BASE, ATTN_NORM);
-			}
-			else
-			{
-				pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1);
-				if(!w_issilent)
-					sound(self, CH_SHOTS, "weapons/crylink_impact.wav", VOL_BASE, ATTN_NORM);
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/crylink_impact2.wav");
-			precache_sound("weapons/crylink_impact.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_devastator.qc b/qcsrc/common/weapons/w_devastator.qc
deleted file mode 100644
index 2e69c5f53..000000000
--- a/qcsrc/common/weapons/w_devastator.qc
+++ /dev/null
@@ -1,683 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ DEVASTATOR,
-/* function  */ W_Devastator,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 9,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '1 1 0',
-/* modelname */ "rl",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairrocketlauncher 0.5875",
-/* wepimg    */ "weaponrocketlauncher",
-/* refname   */ "devastator",
-/* wepname   */ _("Devastator")
-);
-
-#define DEVASTATOR_SETTINGS(w_cvar,w_prop) DEVASTATOR_SETTINGS_LIST(w_cvar, w_prop, DEVASTATOR, devastator)
-#define DEVASTATOR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, NONE, ammo) \
-	w_cvar(id, sn, NONE, animtime) \
-	w_cvar(id, sn, NONE, damage) \
-	w_cvar(id, sn, NONE, damageforcescale) \
-	w_cvar(id, sn, NONE, detonatedelay) \
-	w_cvar(id, sn, NONE, edgedamage) \
-	w_cvar(id, sn, NONE, force) \
-	w_cvar(id, sn, NONE, guidedelay) \
-	w_cvar(id, sn, NONE, guidegoal) \
-	w_cvar(id, sn, NONE, guiderate) \
-	w_cvar(id, sn, NONE, guideratedelay) \
-	w_cvar(id, sn, NONE, guidestop) \
-	w_cvar(id, sn, NONE, health) \
-	w_cvar(id, sn, NONE, lifetime) \
-	w_cvar(id, sn, NONE, radius) \
-	w_cvar(id, sn, NONE, refire) \
-	w_cvar(id, sn, NONE, remote_damage) \
-	w_cvar(id, sn, NONE, remote_edgedamage) \
-	w_cvar(id, sn, NONE, remote_force) \
-	w_cvar(id, sn, NONE, remote_jump_damage) \
-	w_cvar(id, sn, NONE, remote_jump_radius) \
-	w_cvar(id, sn, NONE, remote_jump_velocity_z_add) \
-	w_cvar(id, sn, NONE, remote_jump_velocity_z_max) \
-	w_cvar(id, sn, NONE, remote_jump_velocity_z_min) \
-	w_cvar(id, sn, NONE, remote_radius) \
-	w_cvar(id, sn, NONE, speed) \
-	w_cvar(id, sn, NONE, speedaccel) \
-	w_cvar(id, sn, NONE, speedstart) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-DEVASTATOR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.float rl_release;
-.float rl_detonate_later;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_devastator(void) { weapon_defaultspawnfunc(WEP_DEVASTATOR); }
-void spawnfunc_weapon_rocketlauncher(void) { spawnfunc_weapon_devastator(); }
-
-void W_Devastator_Unregister(void)
-{
-	if(self.realowner && self.realowner.lastrocket == self)
-	{
-		self.realowner.lastrocket = world;
-		// self.realowner.rl_release = 1;
-	}
-}
-
-void W_Devastator_Explode(void)
-{
-	W_Devastator_Unregister();
-
-	if(other.takedamage == DAMAGE_AIM)
-		if(IS_PLAYER(other))
-			if(DIFF_TEAM(self.realowner, other))
-				if(other.deadflag == DEAD_NO)
-					if(IsFlying(other))
-						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	RadiusDamage(
-		self,
-		self.realowner,
-		WEP_CVAR(devastator, damage),
-		WEP_CVAR(devastator, edgedamage),
-		WEP_CVAR(devastator, radius),
-		world,
-		world,
-		WEP_CVAR(devastator, force),
-		self.projectiledeathtype,
-		other
-	);
-
-	if(self.realowner.weapon == WEP_DEVASTATOR)
-	{
-		if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
-		{
-			self.realowner.cnt = WEP_DEVASTATOR;
-			ATTACK_FINISHED(self.realowner) = time;
-			self.realowner.switchweapon = w_getbestweapon(self.realowner);
-		}
-	}
-	remove(self);
-}
-
-void W_Devastator_DoRemoteExplode(void)
-{
-	W_Devastator_Unregister();
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	float handled_as_rocketjump = FALSE;
-
-	entity head = WarpZone_FindRadius(
-		self.origin,
-		WEP_CVAR(devastator, remote_jump_radius),
-		FALSE
-	);
-	
-	while(head)
-	{
-		if(head.takedamage && (head == self.realowner))
-		{
-			float distance_to_head = vlen(self.origin - head.WarpZone_findradius_nearest);
-			if(distance_to_head <= WEP_CVAR(devastator, remote_jump_radius))
-			{
-				// we handled this as a rocketjump :)
-				handled_as_rocketjump = TRUE;
-
-				// modify velocity 
-				head.velocity_x *= 0.9;
-				head.velocity_y *= 0.9;
-				head.velocity_z = bound(
-					WEP_CVAR(devastator, remote_jump_velocity_z_min),
-					head.velocity_z + WEP_CVAR(devastator, remote_jump_velocity_z_add),
-					WEP_CVAR(devastator, remote_jump_velocity_z_max)
-				);
-
-				// now do the damage
-				RadiusDamage(
-					self,
-					head,
-					WEP_CVAR(devastator, remote_jump_damage),
-					WEP_CVAR(devastator, remote_jump_damage),
-					WEP_CVAR(devastator, remote_jump_radius),
-					world,
-					head,
-					0,
-					self.projectiledeathtype | HITTYPE_BOUNCE,
-					world
-				);
-				break;
-			}
-		}
-		head = head.chain;
-	}
-
-	RadiusDamage(
-		self,
-		self.realowner,
-		WEP_CVAR(devastator, remote_damage),
-		WEP_CVAR(devastator, remote_edgedamage),
-		WEP_CVAR(devastator, remote_radius),
-		(handled_as_rocketjump ? head : world),
-		world,
-		WEP_CVAR(devastator, remote_force),
-		self.projectiledeathtype | HITTYPE_BOUNCE,
-		world
-	);
-
-	if(self.realowner.weapon == WEP_DEVASTATOR)
-	{
-		if(self.realowner.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
-		{
-			self.realowner.cnt = WEP_DEVASTATOR;
-			ATTACK_FINISHED(self.realowner) = time;
-			self.realowner.switchweapon = w_getbestweapon(self.realowner);
-		}
-	}
-	remove(self);
-}
-
-void W_Devastator_RemoteExplode(void)
-{
-	if(self.realowner.deadflag == DEAD_NO)
-	if(self.realowner.lastrocket)
-	{
-		if((self.spawnshieldtime >= 0)
-			? (time >= self.spawnshieldtime) // timer
-			: (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > WEP_CVAR(devastator, remote_radius)) // safety device
-		)
-		{
-			W_Devastator_DoRemoteExplode();
-		}
-	}
-}
-
-vector W_Devastator_SteerTo(vector thisdir, vector goaldir, float maxturn_cos)
-{
-	if(thisdir * goaldir > maxturn_cos)
-		return goaldir;
-	if(thisdir * goaldir < -0.9998) // less than 1 degree and opposite
-		return thisdir; // refuse to guide (better than letting a numerical error happen)
-	float f, m2;
-	vector v;
-	// solve:
-	//   g = normalize(thisdir + goaldir * X)
-	//   thisdir * g = maxturn
-	//
-	//   gg = thisdir + goaldir * X
-	//   (thisdir * gg)^2 = maxturn^2 * (gg * gg)
-	//
-	//   (1 + (thisdir * goaldir) * X)^2 = maxturn^2 * (1 + X*X + 2 * X * thisdir * goaldir)
-	f = thisdir * goaldir;
-	//   (1 + f * X)^2 = maxturn^2 * (1 + X*X + 2 * X * f)
-	//   0 = (m^2 - f^2) * x^2 + (2 * f * (m^2 - 1)) * x + (m^2 - 1)
-	m2 = maxturn_cos * maxturn_cos;
-	v = solve_quadratic(m2 - f * f, 2 * f * (m2 - 1), m2 - 1);
-	return normalize(thisdir + goaldir * v_y); // the larger solution!
-}
-// assume thisdir == -goaldir:
-//   f == -1
-//   v = solve_qadratic(m2 - 1, -2 * (m2 - 1), m2 - 1)
-//   (m2 - 1) x^2 - 2 * (m2 - 1) * x + (m2 - 1) = 0
-//   x^2 - 2 * x + 1 = 0
-//   (x - 1)^2 = 0
-//   x = 1
-//   normalize(thisdir + goaldir)
-//   normalize(0)
-
-void W_Devastator_Think(void)
-{
-	vector desireddir, olddir, newdir, desiredorigin, goal;
-	float velspeed, f;
-	self.nextthink = time;
-	if(time > self.cnt)
-	{
-		other = world;
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		W_Devastator_Explode();
-		return;
-	}
-
-	// accelerate
-	makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0');
-	velspeed = WEP_CVAR(devastator, speed) * g_weaponspeedfactor - (self.velocity * v_forward);
-	if(velspeed > 0)
-		self.velocity = self.velocity + v_forward * min(WEP_CVAR(devastator, speedaccel) * g_weaponspeedfactor * frametime, velspeed);
-
-	// laser guided, or remote detonation
-	if(self.realowner.weapon == WEP_DEVASTATOR)
-	{
-		if(self == self.realowner.lastrocket)
-		if(!self.realowner.rl_release)
-		if(!self.BUTTON_ATCK2)
-		if(WEP_CVAR(devastator, guiderate))
-		if(time > self.pushltime)
-		if(self.realowner.deadflag == DEAD_NO)
-		{
-			f = WEP_CVAR(devastator, guideratedelay);
-			if(f)
-				f = bound(0, (time - self.pushltime) / f, 1);
-			else
-				f = 1;
-
-			velspeed = vlen(self.velocity);
-
-			makevectors(self.realowner.v_angle);
-			desireddir = WarpZone_RefSys_TransformVelocity(self.realowner, self, v_forward);
-			desiredorigin = WarpZone_RefSys_TransformOrigin(self.realowner, self, self.realowner.origin + self.realowner.view_ofs);
-			olddir = normalize(self.velocity);
-
-			// now it gets tricky... we want to move like some curve to approximate the target direction
-			// but we are limiting the rate at which we can turn!
-			goal = desiredorigin + ((self.origin - desiredorigin) * desireddir + WEP_CVAR(devastator, guidegoal)) * desireddir;
-			newdir = W_Devastator_SteerTo(olddir, normalize(goal - self.origin), cos(WEP_CVAR(devastator, guiderate) * f * frametime * DEG2RAD));
-
-			self.velocity = newdir * velspeed;
-			self.angles = vectoangles(self.velocity);
-
-			if(!self.count)
-			{
-				pointparticles(particleeffectnum("rocket_guide"), self.origin, self.velocity, 1);
-				// TODO add a better sound here
-				sound(self.realowner, CH_WEAPON_B, "weapons/rocket_mode.wav", VOL_BASE, ATTN_NORM);
-				self.count = 1;
-			}
-		}
-
-		if(self.rl_detonate_later)
-			W_Devastator_RemoteExplode();
-	}
-
-	if(self.csqcprojectile_clientanimate == 0)
-		UpdateCSQCProjectile(self);
-}
-
-void W_Devastator_Touch(void)
-{
-	if(WarpZone_Projectile_Touch())
-	{
-		if(wasfreed(self))
-			W_Devastator_Unregister();
-		return;
-	}
-	W_Devastator_Unregister();
-	W_Devastator_Explode();
-}
-
-void W_Devastator_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if(self.health <= 0)
-		return;
-	
-	if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
-		return; // g_projectiles_damage says to halt
-		
-	self.health = self.health - damage;
-	self.angles = vectoangles(self.velocity);
-	
-	if(self.health <= 0)
-		W_PrepareExplosionByDamage(attacker, W_Devastator_Explode);
-}
-
-void W_Devastator_Attack(void)
-{
-	entity missile;
-	entity flash;
-
-	W_DecreaseAmmo(WEP_CVAR(devastator, ammo));
-
-	W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, WEP_CVAR(devastator, damage));
-	pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	missile = WarpZone_RefSys_SpawnSameRefSys(self);
-	missile.owner = missile.realowner = self;
-	self.lastrocket = missile;
-	if(WEP_CVAR(devastator, detonatedelay) >= 0)
-		missile.spawnshieldtime = time + WEP_CVAR(devastator, detonatedelay);
-	else
-		missile.spawnshieldtime = -1;
-	missile.pushltime = time + WEP_CVAR(devastator, guidedelay);
-	missile.classname = "rocket";
-	missile.bot_dodge = TRUE;
-	missile.bot_dodgerating = WEP_CVAR(devastator, damage) * 2; // * 2 because it can be detonated inflight which makes it even more dangerous
-
-	missile.takedamage = DAMAGE_YES;
-	missile.damageforcescale = WEP_CVAR(devastator, damageforcescale);
-	missile.health = WEP_CVAR(devastator, health);
-	missile.event_damage = W_Devastator_Damage;
-	missile.damagedbycontents = TRUE;
-
-	missile.movetype = MOVETYPE_FLY;
-	PROJECTILE_MAKETRIGGER(missile);
-	missile.projectiledeathtype = WEP_DEVASTATOR;
-	setsize(missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
-
-	setorigin(missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
-	W_SetupProjVelocity_Basic(missile, WEP_CVAR(devastator, speedstart), 0);
-	missile.angles = vectoangles(missile.velocity);
-
-	missile.touch = W_Devastator_Touch;
-	missile.think = W_Devastator_Think;
-	missile.nextthink = time;
-	missile.cnt = time + WEP_CVAR(devastator, lifetime);
-	missile.flags = FL_PROJECTILE;
-	missile.missile_flags = MIF_SPLASH; 
-
-	CSQCProjectile(missile, WEP_CVAR(devastator, guiderate) == 0 && WEP_CVAR(devastator, speedaccel) == 0, PROJECTILE_ROCKET, FALSE); // because of fly sound
-
-	// muzzle flash for 1st person view
-	flash = spawn();
-	setmodel(flash, "models/flash.md3"); // precision set below
-	SUB_SetFade(flash, time, 0.1);
-	flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-	W_AttachToShotorg(flash, '5 0 0');
-
-	// common properties
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-float W_Devastator(float req)
-{
-	entity rock;
-	float rockfound;
-	float ammo_amount;
-	switch(req)
-	{
-		#if 0
-		case WR_AIM:
-		{
-			// aim and decide to fire if appropriate
-			self.BUTTON_ATCK = bot_aim(WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), FALSE);
-			if(skill >= 2) // skill 0 and 1 bots won't detonate rockets!
-			{
-				// decide whether to detonate rockets
-				entity missile, targetlist, targ;
-				targetlist = findchainfloat(bot_attack, TRUE);
-				for(missile = world; (missile = find(missile, classname, "rocket")); ) if(missile.realowner == self)
-				{
-					targ = targetlist;
-					while(targ)
-					{
-						if(targ != missile.realowner && vlen(targ.origin - missile.origin) < WEP_CVAR(devastator, radius))
-						{
-							self.BUTTON_ATCK2 = TRUE;
-							break;
-						}
-						targ = targ.chain;
-					}
-				}
-				
-				if(self.BUTTON_ATCK2) self.BUTTON_ATCK = FALSE;
-			}
-			
-			return TRUE;
-		}
-		#else
-		case WR_AIM:
-		{
-			// aim and decide to fire if appropriate
-			self.BUTTON_ATCK = bot_aim(WEP_CVAR(devastator, speed), 0, WEP_CVAR(devastator, lifetime), FALSE);
-			if(skill >= 2) // skill 0 and 1 bots won't detonate rockets!
-			{
-				// decide whether to detonate rockets
-				entity missile, targetlist, targ;
-				float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
-				float selfdamage, teamdamage, enemydamage;
-				edgedamage = WEP_CVAR(devastator, edgedamage);
-				coredamage = WEP_CVAR(devastator, damage);
-				edgeradius = WEP_CVAR(devastator, radius);
-				recipricoledgeradius = 1 / edgeradius;
-				selfdamage = 0;
-				teamdamage = 0;
-				enemydamage = 0;
-				targetlist = findchainfloat(bot_attack, TRUE);
-				missile = find(world, classname, "rocket");
-				while(missile)
-				{
-					if(missile.realowner != self)
-					{
-						missile = find(missile, classname, "rocket");
-						continue;
-					}
-					targ = targetlist;
-					while(targ)
-					{
-						d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - missile.origin);
-						d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
-						// count potential damage according to type of target
-						if(targ == self)
-							selfdamage = selfdamage + d;
-						else if(targ.team == self.team && teamplay)
-							teamdamage = teamdamage + d;
-						else if(bot_shouldattack(targ))
-							enemydamage = enemydamage + d;
-						targ = targ.chain;
-					}
-					missile = find(missile, classname, "rocket");
-				}
-				float desirabledamage;
-				desirabledamage = enemydamage;
-				if(time > self.invincible_finished && time > self.spawnshieldtime)
-					desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
-				if(teamplay && self.team)
-					desirabledamage = desirabledamage - teamdamage;
-
-				missile = find(world, classname, "rocket");
-				while(missile)
-				{
-					if(missile.realowner != self)
-					{
-						missile = find(missile, classname, "rocket");
-						continue;
-					}
-					makevectors(missile.v_angle);
-					targ = targetlist;
-					if(skill > 9) // normal players only do this for the target they are tracking
-					{
-						targ = targetlist;
-						while(targ)
-						{
-							if(
-								(v_forward * normalize(missile.origin - targ.origin)< 0.1)
-								&& desirabledamage > 0.1*coredamage
-							)self.BUTTON_ATCK2 = TRUE;
-							targ = targ.chain;
-						}
-					}else{
-						float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
-						//As the distance gets larger, a correct detonation gets near imposible
-						//Bots are assumed to use the rocket spawnfunc_light to see if the rocket gets near a player
-						if(v_forward * normalize(missile.origin - self.enemy.origin)< 0.1)
-							if(IS_PLAYER(self.enemy))
-								if(desirabledamage >= 0.1*coredamage)
-									if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1))
-										self.BUTTON_ATCK2 = TRUE;
-					//	dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n");
-					}
-
-					missile = find(missile, classname, "rocket");
-				}
-				// if we would be doing at X percent of the core damage, detonate it
-				// but don't fire a new shot at the same time!
-				if(desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events
-					self.BUTTON_ATCK2 = TRUE;
-				if((skill > 6.5) && (selfdamage > self.health))
-					self.BUTTON_ATCK2 = FALSE;
-				//if(self.BUTTON_ATCK2 == TRUE)
-				//	dprint(ftos(desirabledamage),"\n");
-				if(self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE;
-			}
-			
-			return TRUE;
-		}
-		#endif
-		case WR_THINK:
-		{
-			if(WEP_CVAR(devastator, reload_ammo) && self.clip_load < WEP_CVAR(devastator, ammo)) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-			else
-			{
-				if(self.BUTTON_ATCK)
-				{
-					if(self.rl_release || WEP_CVAR(devastator, guidestop))
-					if(weapon_prepareattack(0, WEP_CVAR(devastator, refire)))
-					{
-						W_Devastator_Attack();
-						weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(devastator, animtime), w_ready);
-						self.rl_release = 0;
-					}
-				}
-				else
-					self.rl_release = 1;
-
-				if(self.BUTTON_ATCK2)
-				{
-					rockfound = 0;
-					for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self)
-					{
-						if(!rock.rl_detonate_later)
-						{
-							rock.rl_detonate_later = TRUE;
-							rockfound = 1;
-						}
-					}
-					if(rockfound)
-						sound(self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			//if(autocvar_sv_precacheweapons)
-			//{
-				precache_model("models/flash.md3");
-				precache_model("models/weapons/g_rl.md3");
-				precache_model("models/weapons/v_rl.md3");
-				precache_model("models/weapons/h_rl.iqm");
-				precache_sound("weapons/rocket_det.wav");
-				precache_sound("weapons/rocket_fire.wav");
-				precache_sound("weapons/rocket_mode.wav");
-			//}
-			DEVASTATOR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_SETUP:
-		{
-			self.rl_release = 1;
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			#if 0
-			// don't switch while guiding a missile
-			if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_DEVASTATOR)
-			{
-				ammo_amount = FALSE;
-				if(WEP_CVAR(devastator, reload_ammo))
-				{
-					if(self.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo) && self.(weapon_load[WEP_DEVASTATOR]) < WEP_CVAR(devastator, ammo))
-						ammo_amount = TRUE;
-				}
-				else if(self.WEP_AMMO(DEVASTATOR) < WEP_CVAR(devastator, ammo))
-					ammo_amount = TRUE;
-				return !ammo_amount;
-			}
-			#endif
-			#if 0
-			if(self.rl_release == 0)
-			{
-				printf("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: TRUE\n", self.rl_release, self.WEP_AMMO(DEVASTATOR), WEP_CVAR(devastator, ammo));
-				return TRUE;
-			}
-			else
-			{
-				ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo);
-				ammo_amount += self.(weapon_load[WEP_DEVASTATOR]) >= WEP_CVAR(devastator, ammo);
-				printf("W_Devastator(WR_CHECKAMMO1): %d, %.2f, %d: %s\n", self.rl_release, self.WEP_AMMO(DEVASTATOR), WEP_CVAR(devastator, ammo), (ammo_amount ? "TRUE" : "FALSE"));
-				return ammo_amount;
-			}
-			#else
-			ammo_amount = self.WEP_AMMO(DEVASTATOR) >= WEP_CVAR(devastator, ammo);
-			ammo_amount += self.(weapon_load[WEP_DEVASTATOR]) >= WEP_CVAR(devastator, ammo);
-			return ammo_amount;
-			#endif
-		}
-		case WR_CHECKAMMO2:
-		{
-			return FALSE;
-		}
-		case WR_CONFIG:
-		{
-			DEVASTATOR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RESETPLAYER:
-		{
-			self.rl_release = 0;
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(WEP_CVAR(devastator, ammo), "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_DEVASTATOR_SUICIDE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
-				return WEAPON_DEVASTATOR_MURDER_SPLASH;
-			else
-				return WEAPON_DEVASTATOR_MURDER_DIRECT;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Devastator(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 12;
-			pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
-			if(!w_issilent)
-				sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTN_NORM);
-				
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/rocket_impact.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_electro.qc b/qcsrc/common/weapons/w_electro.qc
deleted file mode 100644
index 3847e2d56..000000000
--- a/qcsrc/common/weapons/w_electro.qc
+++ /dev/null
@@ -1,620 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ ELECTRO,
-/* function  */ W_Electro,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 5,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0 0.5 1',
-/* modelname */ "electro",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairelectro 0.5",
-/* wepimg    */ "weaponelectro",
-/* refname   */ "electro",
-/* wepname   */ _("Electro")
-);
-
-#define ELECTRO_SETTINGS(w_cvar,w_prop) ELECTRO_SETTINGS_LIST(w_cvar, w_prop, ELECTRO, electro)
-#define ELECTRO_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, ammo) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, edgedamage) \
-	w_cvar(id, sn, BOTH, force) \
-	w_cvar(id, sn, BOTH, radius) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, BOTH, speed) \
-	w_cvar(id, sn, BOTH, spread) \
-	w_cvar(id, sn, BOTH, lifetime) \
-	w_cvar(id, sn, PRI,  comboradius) \
-	w_cvar(id, sn, PRI,  midaircombo_explode) \
-	w_cvar(id, sn, PRI,  midaircombo_interval) \
-	w_cvar(id, sn, PRI,  midaircombo_radius) \
-	w_cvar(id, sn, SEC,  bouncefactor) \
-	w_cvar(id, sn, SEC,  bouncestop) \
-	w_cvar(id, sn, SEC,  count) \
-	w_cvar(id, sn, SEC,  damageforcescale) \
-	w_cvar(id, sn, SEC,  damagedbycontents) \
-	w_cvar(id, sn, SEC,  health) \
-	w_cvar(id, sn, SEC,  refire2) \
-	w_cvar(id, sn, SEC,  speed_up) \
-	w_cvar(id, sn, SEC,  speed_z) \
-	w_cvar(id, sn, SEC,  touchexplode) \
-	w_cvar(id, sn, NONE, combo_comboradius) \
-	w_cvar(id, sn, NONE, combo_comboradius_thruwall) \
-	w_cvar(id, sn, NONE, combo_damage) \
-	w_cvar(id, sn, NONE, combo_edgedamage) \
-	w_cvar(id, sn, NONE, combo_force) \
-	w_cvar(id, sn, NONE, combo_radius) \
-	w_cvar(id, sn, NONE, combo_speed) \
-	w_cvar(id, sn, NONE, combo_safeammocheck) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-ELECTRO_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.float electro_count;
-.float electro_secondarytime;
-void W_Electro_ExplodeCombo(void);
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_electro(void) { weapon_defaultspawnfunc(WEP_ELECTRO); }
-
-void W_Electro_TriggerCombo(vector org, float rad, entity own)
-{
-	entity e = WarpZone_FindRadius(org, rad, !WEP_CVAR(electro, combo_comboradius_thruwall));
-	while(e)
-	{
-		if(e.classname == "electro_orb")
-		{
-			// do we allow thruwall triggering?
-			if(WEP_CVAR(electro, combo_comboradius_thruwall))
-			{
-				// if distance is greater than thruwall distance, check to make sure it's not through a wall
-				if(vlen(e.WarpZone_findradius_dist) > WEP_CVAR(electro, combo_comboradius_thruwall))
-				{
-					WarpZone_TraceLine(org, e.origin, MOVE_NOMONSTERS, e);
-					if(trace_fraction != 1)
-					{
-						// trigger is through a wall and outside of thruwall range, abort
-						e = e.chain;
-						continue;
-					}
-				}
-			}
-			
-			// change owner to whoever caused the combo explosion
-			e.realowner = own;
-			e.takedamage = DAMAGE_NO;
-			e.classname = "electro_orb_chain";
-			
-			// now set the next one to trigger as well
-			e.think = W_Electro_ExplodeCombo;
-			
-			// delay combo chains, looks cooler
-			e.nextthink =
-				(
-					time
-					+
-					(WEP_CVAR(electro, combo_speed) ?
-						(vlen(e.WarpZone_findradius_dist) / WEP_CVAR(electro, combo_speed))
-						:
-						0
-					)
-				);
-		}
-		e = e.chain;
-	}
-}
-
-void W_Electro_ExplodeCombo(void)
-{
-	W_Electro_TriggerCombo(self.origin, WEP_CVAR(electro, combo_comboradius), self.realowner);
-
-	self.event_damage = func_null;
-	
-	RadiusDamage(
-		self,
-		self.realowner,
-		WEP_CVAR(electro, combo_damage),
-		WEP_CVAR(electro, combo_edgedamage),
-		WEP_CVAR(electro, combo_radius),
-		world,
-		world,
-		WEP_CVAR(electro, combo_force),
-		WEP_ELECTRO | HITTYPE_BOUNCE, // use THIS type for a combo because primary can't bounce
-		world
-	);
-
-	remove(self);
-}
-
-void W_Electro_Explode(void)
-{
-	if(other.takedamage == DAMAGE_AIM)
-		if(IS_PLAYER(other))
-			if(DIFF_TEAM(self.realowner, other))
-				if(other.deadflag == DEAD_NO)
-					if(IsFlying(other))
-						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_ELECTROBITCH);
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-	
-	if(self.movetype == MOVETYPE_BOUNCE)
-	{
-		RadiusDamage(
-			self,
-			self.realowner,
-			WEP_CVAR_SEC(electro, damage),
-			WEP_CVAR_SEC(electro, edgedamage),
-			WEP_CVAR_SEC(electro, radius),
-			world,
-			world,
-			WEP_CVAR_SEC(electro, force),
-			self.projectiledeathtype,
-			other
-		);
-	}
-	else
-	{
-		W_Electro_TriggerCombo(self.origin, WEP_CVAR_PRI(electro, comboradius), self.realowner);
-		RadiusDamage(
-			self,
-			self.realowner,
-			WEP_CVAR_PRI(electro, damage),
-			WEP_CVAR_PRI(electro, edgedamage),
-			WEP_CVAR_PRI(electro, radius),
-			world,
-			world,
-			WEP_CVAR_PRI(electro, force),
-			self.projectiledeathtype,
-			other
-		);
-	}
-
-	remove(self);
-}
-
-void W_Electro_TouchExplode(void)
-{
-	PROJECTILE_TOUCH;
-	W_Electro_Explode();
-}
-
-void W_Electro_Bolt_Think(void)
-{
-	if(time >= self.ltime)
-	{
-		self.use();
-		return;
-	}
-
-	if(WEP_CVAR_PRI(electro, midaircombo_radius))
-	{
-		float found = 0;
-		entity e = WarpZone_FindRadius(self.origin, WEP_CVAR_PRI(electro, midaircombo_radius), TRUE);
-
-		// loop through nearby orbs and trigger them
-		while(e)
-		{
-			if(e.classname == "electro_orb")
-			{
-				// change owner to whoever caused the combo explosion
-				e.realowner = self.realowner;
-				e.takedamage = DAMAGE_NO;
-				e.classname = "electro_orb_chain";
-
-				// now set the next one to trigger as well
-				e.think = W_Electro_ExplodeCombo;
-				
-				// delay combo chains, looks cooler
-				e.nextthink =
-					(
-						time
-						+
-						(WEP_CVAR(electro, combo_speed) ?
-							(vlen(e.WarpZone_findradius_dist) / WEP_CVAR(electro, combo_speed))
-							:
-							0
-						)
-					);
-
-				++found;
-			}
-			e = e.chain;
-		}
-
-		// if we triggered an orb, should we explode? if not, lets try again next time
-		if(found && WEP_CVAR_PRI(electro, midaircombo_explode))
-			{ self.use(); }
-		else
-			{ self.nextthink = min(time + WEP_CVAR_PRI(electro, midaircombo_interval), self.ltime); }
-	}
-	else { self.nextthink = self.ltime; }
-}
-
-void W_Electro_Attack_Bolt(void)
-{
-	entity proj;
-
-	W_DecreaseAmmo(WEP_CVAR_PRI(electro, ammo));
-
-	W_SetupShot_ProjectileSize(
-		self,
-		'0 0 -3',
-		'0 0 -3',
-		FALSE,
-		2,
-		"weapons/electro_fire.wav",
-		CH_WEAPON_A,
-		WEP_CVAR_PRI(electro, damage)
-	);
-
-	pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	proj = spawn();
-	proj.classname = "electro_bolt";
-	proj.owner = proj.realowner = self;
-	proj.bot_dodge = TRUE;
-	proj.bot_dodgerating = WEP_CVAR_PRI(electro, damage);
-	proj.use = W_Electro_Explode;
-	proj.think = W_Electro_Bolt_Think;
-	proj.nextthink = time;
-	proj.ltime = time + WEP_CVAR_PRI(electro, lifetime);
-	PROJECTILE_MAKETRIGGER(proj);
-	proj.projectiledeathtype = WEP_ELECTRO;
-	setorigin(proj, w_shotorg);
-
-	proj.movetype = MOVETYPE_FLY;
-	W_SetupProjVelocity_PRI(proj, electro);
-	proj.angles = vectoangles(proj.velocity);
-	proj.touch = W_Electro_TouchExplode;
-	setsize(proj, '0 0 -3', '0 0 -3');
-	proj.flags = FL_PROJECTILE;
-	proj.missile_flags = MIF_SPLASH;
-
-	CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO_BEAM, TRUE);
-
-	other = proj; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-void W_Electro_Orb_Touch(void)
-{
-	PROJECTILE_TOUCH;
-	if(other.takedamage == DAMAGE_AIM)
-		{ if(WEP_CVAR_SEC(electro, touchexplode)) { W_Electro_Explode(); } }
-	else
-	{
-		//UpdateCSQCProjectile(self);
-		spamsound(self, CH_SHOTS, "weapons/electro_bounce.wav", VOL_BASE, ATTEN_NORM);
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-	}
-}
-
-void W_Electro_Orb_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if(self.health <= 0)
-		return;
-
-	// note: combos are usually triggered by W_Electro_TriggerCombo, not damage
-	float is_combo = (inflictor.classname == "electro_orb_chain" || inflictor.classname == "electro_bolt");
-
-	if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_combo ? 1 : -1)))
-		return; // g_projectiles_damage says to halt
-
-	self.health = self.health - damage;
-	if(self.health <= 0)
-	{
-		self.takedamage = DAMAGE_NO;
-		self.nextthink = time;
-		if(is_combo)
-		{
-			// change owner to whoever caused the combo explosion
-			self.realowner = inflictor.realowner;
-			self.classname = "electro_orb_chain";
-			self.think = W_Electro_ExplodeCombo;
-			self.nextthink = time +
-				(
-					// bound the length, inflictor may be in a galaxy far far away (warpzones)
-					min(
-						WEP_CVAR(electro, combo_radius),
-						vlen(self.origin - inflictor.origin)
-					)
-					/
-					// delay combo chains, looks cooler
-					WEP_CVAR(electro, combo_speed)
-				);
-		}
-		else
-		{
-			self.use = W_Electro_Explode;
-			self.think = adaptor_think2use; // not _hittype_splash, as this runs "immediately"
-		}
-	}
-}
-
-void W_Electro_Attack_Orb(void)
-{
-	W_DecreaseAmmo(WEP_CVAR_SEC(electro, ammo));
-
-	W_SetupShot_ProjectileSize(
-		self,
-		'0 0 -4',
-		'0 0 -4',
-		FALSE,
-		2,
-		"weapons/electro_fire2.wav",
-		CH_WEAPON_A,
-		WEP_CVAR_SEC(electro, damage)
-	);
-
-	w_shotdir = v_forward; // no TrueAim for grenades please
-
-	pointparticles(particleeffectnum("electro_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	entity proj = spawn();
-	proj.classname = "electro_orb";
-	proj.owner = proj.realowner = self;
-	proj.use = W_Electro_Explode;
-	proj.think = adaptor_think2use_hittype_splash;
-	proj.bot_dodge = TRUE;
-	proj.bot_dodgerating = WEP_CVAR_SEC(electro, damage);
-	proj.nextthink = time + WEP_CVAR_SEC(electro, lifetime);
-	PROJECTILE_MAKETRIGGER(proj);
-	proj.projectiledeathtype = WEP_ELECTRO | HITTYPE_SECONDARY;
-	setorigin(proj, w_shotorg);
-
-	//proj.glow_size = 50;
-	//proj.glow_color = 45;
-	proj.movetype = MOVETYPE_BOUNCE;
-	W_SetupProjVelocity_UP_SEC(proj, electro);
-	proj.touch = W_Electro_Orb_Touch;
-	setsize(proj, '0 0 -4', '0 0 -4');
-	proj.takedamage = DAMAGE_YES;
-	proj.damageforcescale = WEP_CVAR_SEC(electro, damageforcescale);
-	proj.health = WEP_CVAR_SEC(electro, health);
-	proj.event_damage = W_Electro_Orb_Damage;
-	proj.flags = FL_PROJECTILE;
-	proj.damagedbycontents = (WEP_CVAR_SEC(electro, damagedbycontents));
-
-	proj.bouncefactor = WEP_CVAR_SEC(electro, bouncefactor);
-	proj.bouncestop = WEP_CVAR_SEC(electro, bouncestop);
-	proj.missile_flags = MIF_SPLASH | MIF_ARC;
-
-#if 0
-	entity p2;
-	p2 = spawn();
-	copyentity(proj, p2);
-	setmodel(p2, "models/ebomb.mdl");
-	setsize(p2, proj.mins, proj.maxs);
-#endif
-
-	CSQCProjectile(proj, TRUE, PROJECTILE_ELECTRO, FALSE); // no culling, it has sound
-
-	other = proj; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-void W_Electro_CheckAttack(void)
-{
-	if(self.electro_count > 1)
-	if(self.BUTTON_ATCK2)
-	if(weapon_prepareattack(1, -1))
-	{
-		W_Electro_Attack_Orb();
-		self.electro_count -= 1;
-		weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
-		return;
-	}
-	// WEAPONTODO: when the player releases the button, cut down the length of refire2? 
-	w_ready();
-}
-
-.float bot_secondary_electromooth;
-float W_Electro(float req)
-{
-	float ammo_amount;
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			self.BUTTON_ATCK = self.BUTTON_ATCK2 = FALSE;
-			if(vlen(self.origin-self.enemy.origin) > 1000) { self.bot_secondary_electromooth = 0; }
-			if(self.bot_secondary_electromooth == 0)
-			{
-				float shoot;
-
-				if(WEP_CVAR_PRI(electro, speed))
-					shoot = bot_aim(WEP_CVAR_PRI(electro, speed), 0, WEP_CVAR_PRI(electro, lifetime), FALSE);
-				else
-					shoot = bot_aim(1000000, 0, 0.001, FALSE);
-
-				if(shoot)
-				{
-					self.BUTTON_ATCK = TRUE;
-					if(random() < 0.01) self.bot_secondary_electromooth = 1;
-				}
-			}
-			else
-			{
-				if(bot_aim(WEP_CVAR_SEC(electro, speed), WEP_CVAR_SEC(electro, speed_up), WEP_CVAR_SEC(electro, lifetime), TRUE))
-				{
-					self.BUTTON_ATCK2 = TRUE;
-					if(random() < 0.03) self.bot_secondary_electromooth = 0;
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(autocvar_g_balance_electro_reload_ammo) // forced reload // WEAPONTODO
-			{
-				ammo_amount = 0;
-				if(self.clip_load >= WEP_CVAR_PRI(electro, ammo))
-					ammo_amount = 1;
-				if(self.clip_load >= WEP_CVAR_SEC(electro, ammo))
-					ammo_amount += 1;
-
-				if(!ammo_amount)
-				{
-					WEP_ACTION(self.weapon, WR_RELOAD);
-					return FALSE;
-				}
-				
-				return TRUE;
-			}
-			
-			if(self.BUTTON_ATCK)
-			{
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(electro, refire)))
-				{
-						W_Electro_Attack_Bolt();
-						weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(electro, animtime), w_ready);
-				}
-			}
-			else if(self.BUTTON_ATCK2)
-			{
-				if(time >= self.electro_secondarytime)
-				if(weapon_prepareattack(1, WEP_CVAR_SEC(electro, refire)))
-				{
-					W_Electro_Attack_Orb();
-					self.electro_count = WEP_CVAR_SEC(electro, count);
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(electro, animtime), W_Electro_CheckAttack);
-					self.electro_secondarytime = time + WEP_CVAR_SEC(electro, refire2) * W_WeaponRateFactor();
-				}
-			}
-
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_electro.md3");
-			precache_model("models/weapons/v_electro.md3");
-			precache_model("models/weapons/h_electro.iqm");
-			precache_sound("weapons/electro_bounce.wav");
-			precache_sound("weapons/electro_fire.wav");
-			precache_sound("weapons/electro_fire2.wav");
-			precache_sound("weapons/electro_impact.wav");
-			precache_sound("weapons/electro_impact_combo.wav");
-			ELECTRO_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_PRI(electro, ammo);
-			ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= WEP_CVAR_PRI(electro, ammo);
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			if(WEP_CVAR(electro, combo_safeammocheck)) // true if you can fire at least one secondary blob AND one primary shot after it, otherwise false.
-			{
-				ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
-				ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= WEP_CVAR_SEC(electro, ammo) + WEP_CVAR_PRI(electro, ammo);
-			}
-			else
-			{
-				ammo_amount = self.WEP_AMMO(ELECTRO) >= WEP_CVAR_SEC(electro, ammo);
-				ammo_amount += self.(weapon_load[WEP_ELECTRO]) >= WEP_CVAR_SEC(electro, ammo);
-			}
-			return ammo_amount;
-		}
-		case WR_CONFIG:
-		{
-			ELECTRO_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RESETPLAYER:
-		{
-			self.electro_secondarytime = time;
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(min(WEP_CVAR_PRI(electro, ammo), WEP_CVAR_SEC(electro, ammo)), "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_ELECTRO_SUICIDE_ORBS;
-			else
-				return WEAPON_ELECTRO_SUICIDE_BOLT;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-			{
-				return WEAPON_ELECTRO_MURDER_ORBS;
-			}
-			else
-			{
-				if(w_deathtype & HITTYPE_BOUNCE)
-					return WEAPON_ELECTRO_MURDER_COMBO;
-				else
-					return WEAPON_ELECTRO_MURDER_BOLT;
-			}
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Electro(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 6;
-			if(w_deathtype & HITTYPE_SECONDARY)
-			{
-				pointparticles(particleeffectnum("electro_ballexplode"), org2, '0 0 0', 1);
-				if(!w_issilent)
-					sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTEN_NORM);
-			}
-			else
-			{
-				if(w_deathtype & HITTYPE_BOUNCE)
-				{
-					// this is sent as "primary (w_deathtype & HITTYPE_BOUNCE)" to distinguish it from (w_deathtype & HITTYPE_SECONDARY) bounced balls
-					pointparticles(particleeffectnum("electro_combo"), org2, '0 0 0', 1);
-					if(!w_issilent)
-						sound(self, CH_SHOTS, "weapons/electro_impact_combo.wav", VOL_BASE, ATTEN_NORM);
-				}
-				else
-				{
-					pointparticles(particleeffectnum("electro_impact"), org2, '0 0 0', 1);
-					if(!w_issilent)
-						sound(self, CH_SHOTS, "weapons/electro_impact.wav", VOL_BASE, ATTEN_NORM);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/electro_impact.wav");
-			precache_sound("weapons/electro_impact_combo.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_fireball.qc b/qcsrc/common/weapons/w_fireball.qc
deleted file mode 100644
index a5bca22cd..000000000
--- a/qcsrc/common/weapons/w_fireball.qc
+++ /dev/null
@@ -1,485 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ FIREBALL,
-/* function  */ W_Fireball,
-/* ammotype  */ ammo_none,
-/* impulse   */ 9,
-/* flags     */ WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 0.5 0',
-/* modelname */ "fireball",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairfireball",
-/* wepimg    */ "weaponfireball",
-/* refname   */ "fireball",
-/* wepname   */ _("Fireball")
-);
-
-#define FIREBALL_SETTINGS(w_cvar,w_prop) FIREBALL_SETTINGS_LIST(w_cvar, w_prop, FIREBALL, fireball)
-#define FIREBALL_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, damageforcescale) \
-	w_cvar(id, sn, BOTH, speed) \
-	w_cvar(id, sn, BOTH, spread) \
-	w_cvar(id, sn, BOTH, lifetime) \
-	w_cvar(id, sn, BOTH, laserburntime) \
-	w_cvar(id, sn, BOTH, laserdamage) \
-	w_cvar(id, sn, BOTH, laseredgedamage) \
-	w_cvar(id, sn, BOTH, laserradius) \
-	w_cvar(id, sn, PRI,  edgedamage) \
-	w_cvar(id, sn, PRI,  force) \
-	w_cvar(id, sn, PRI,  radius) \
-	w_cvar(id, sn, PRI,  health) \
-	w_cvar(id, sn, PRI,  refire2) \
-	w_cvar(id, sn, PRI,  bfgdamage) \
-	w_cvar(id, sn, PRI,  bfgforce) \
-	w_cvar(id, sn, PRI,  bfgradius) \
-	w_cvar(id, sn, SEC,  damagetime) \
-	w_cvar(id, sn, SEC,  speed_up) \
-	w_cvar(id, sn, SEC,  speed_z) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-FIREBALL_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.float bot_primary_fireballmooth; // whatever a mooth is
-.vector fireball_impactvec;
-.float fireball_primarytime;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_fireball(void) { weapon_defaultspawnfunc(WEP_FIREBALL); }
-
-void W_Fireball_Explode(void)
-{
-	entity e;
-	float dist;
-	float points;
-	vector dir;
-	float d;
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	// 1. dist damage
-	d = (self.realowner.health + self.realowner.armorvalue);
-	RadiusDamage(self, self.realowner, WEP_CVAR_PRI(fireball, damage), WEP_CVAR_PRI(fireball, edgedamage), WEP_CVAR_PRI(fireball, radius), world, world, WEP_CVAR_PRI(fireball, force), self.projectiledeathtype, other);
-	if(self.realowner.health + self.realowner.armorvalue >= d)
-	if(!self.cnt)
-	{
-		modeleffect_spawn("models/sphere/sphere.md3", 0, 0, self.origin, '0 0 0', '0 0 0', '0 0 0', 0, WEP_CVAR_PRI(fireball, bfgradius), 0.2, 0.05, 0.25);
-
-		// 2. bfg effect
-		// NOTE: this cannot be made warpzone aware by design. So, better intentionally ignore warpzones here.
-		for(e = findradius(self.origin, WEP_CVAR_PRI(fireball, bfgradius)); e; e = e.chain)
-		if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(!IS_PLAYER(e) || !self.realowner || DIFF_TEAM(e, self))
-		{
-			// can we see fireball?
-			traceline(e.origin + e.view_ofs, self.origin, MOVE_NORMAL, e);
-			if(/* trace_startsolid || */ trace_fraction != 1) // startsolid should be never happening anyway
-				continue;
-			// can we see player who shot fireball?
-			traceline(e.origin + e.view_ofs, self.realowner.origin + self.realowner.view_ofs, MOVE_NORMAL, e);
-			if(trace_ent != self.realowner)
-			if(/* trace_startsolid || */ trace_fraction != 1)
-				continue;
-			dist = vlen(self.origin - e.origin - e.view_ofs);
-			points = (1 - sqrt(dist / WEP_CVAR_PRI(fireball, bfgradius)));
-			if(points <= 0)
-				continue;
-			dir = normalize(e.origin + e.view_ofs - self.origin);
-
-			if(accuracy_isgooddamage(self.realowner, e))
-				accuracy_add(self.realowner, WEP_FIREBALL, 0, WEP_CVAR_PRI(fireball, bfgdamage) * points);
-
-			Damage(e, self, self.realowner, WEP_CVAR_PRI(fireball, bfgdamage) * points, self.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH, e.origin + e.view_ofs, WEP_CVAR_PRI(fireball, bfgforce) * dir);
-			pointparticles(particleeffectnum("fireball_bfgdamage"), e.origin, -1 * dir, 1);
-		}
-	}
-
-	remove(self);
-}
-
-void W_Fireball_TouchExplode(void)
-{
-	PROJECTILE_TOUCH;
-	W_Fireball_Explode();
-}
-
-void W_Fireball_LaserPlay(float dt, float dist, float damage, float edgedamage, float burntime)
-{
-	entity e;
-	float d;
-	vector p;
-
-	if(damage <= 0)
-		return;
-
-	RandomSelection_Init();
-	for(e = WarpZone_FindRadius(self.origin, dist, TRUE); e; e = e.chain)
-	if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(!IS_PLAYER(e) || !self.realowner || DIFF_TEAM(e, self))
-	{
-		p = e.origin;
-		p_x += e.mins_x + random() * (e.maxs_x - e.mins_x);
-		p_y += e.mins_y + random() * (e.maxs_y - e.mins_y);
-		p_z += e.mins_z + random() * (e.maxs_z - e.mins_z);
-		d = vlen(WarpZone_UnTransformOrigin(e, self.origin) - p);
-		if(d < dist)
-		{
-			e.fireball_impactvec = p;
-			RandomSelection_Add(e, 0, string_null, 1 / (1 + d), !Fire_IsBurning(e));
-		}
-	}
-	if(RandomSelection_chosen_ent)
-	{
-		d = vlen(WarpZone_UnTransformOrigin(RandomSelection_chosen_ent, self.origin) - RandomSelection_chosen_ent.fireball_impactvec);
-		d = damage + (edgedamage - damage) * (d / dist);
-		Fire_AddDamage(RandomSelection_chosen_ent, self.realowner, d * burntime, burntime, self.projectiledeathtype | HITTYPE_BOUNCE);
-		//trailparticles(self, particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec);
-		pointparticles(particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec - self.origin, 1);
-	}
-}
-
-void W_Fireball_Think(void)
-{
-	if(time > self.pushltime)
-	{
-		self.cnt = 1;
-		self.projectiledeathtype |= HITTYPE_SPLASH;
-		W_Fireball_Explode();
-		return;
-	}
-
-	W_Fireball_LaserPlay(0.1, WEP_CVAR_PRI(fireball, laserradius), WEP_CVAR_PRI(fireball, laserdamage), WEP_CVAR_PRI(fireball, laseredgedamage), WEP_CVAR_PRI(fireball, laserburntime));
-
-	self.nextthink = time + 0.1;
-}
-
-void W_Fireball_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if(self.health <= 0)
-		return;
-
-	if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
-		return; // g_projectiles_damage says to halt
-
-	self.health = self.health - damage;
-	if(self.health <= 0)
-	{
-		self.cnt = 1;
-		W_PrepareExplosionByDamage(attacker, W_Fireball_Explode);
-	}
-}
-
-void W_Fireball_Attack1(void)
-{
-	entity proj;
-
-	W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', FALSE, 2, "weapons/fireball_fire2.wav", CH_WEAPON_A, WEP_CVAR_PRI(fireball, damage) + WEP_CVAR_PRI(fireball, bfgdamage));
-
-	pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	proj = spawn();
-	proj.classname = "plasma_prim";
-	proj.owner = proj.realowner = self;
-	proj.bot_dodge = TRUE;
-	proj.bot_dodgerating = WEP_CVAR_PRI(fireball, damage);
-	proj.pushltime = time + WEP_CVAR_PRI(fireball, lifetime);
-	proj.use = W_Fireball_Explode;
-	proj.think = W_Fireball_Think;
-	proj.nextthink = time;
-	proj.health = WEP_CVAR_PRI(fireball, health);
-	proj.team = self.team;
-	proj.event_damage = W_Fireball_Damage;
-	proj.takedamage = DAMAGE_YES;
-	proj.damageforcescale = WEP_CVAR_PRI(fireball, damageforcescale);
-	PROJECTILE_MAKETRIGGER(proj);
-	proj.projectiledeathtype = WEP_FIREBALL;
-	setorigin(proj, w_shotorg);
-
-	proj.movetype = MOVETYPE_FLY;
-	W_SetupProjVelocity_PRI(proj, fireball);
-	proj.angles = vectoangles(proj.velocity);
-	proj.touch = W_Fireball_TouchExplode;
-	setsize(proj, '-16 -16 -16', '16 16 16');
-	proj.flags = FL_PROJECTILE;
-    proj.missile_flags = MIF_SPLASH | MIF_PROXY;
-
-	CSQCProjectile(proj, TRUE, PROJECTILE_FIREBALL, TRUE);
-
-	other = proj; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-void W_Fireball_AttackEffect(float i, vector f_diff)
-{
-	W_SetupShot_ProjectileSize(self, '-16 -16 -16', '16 16 16', FALSE, 0, "", 0, 0);
-	w_shotorg += f_diff_x * v_up + f_diff_y * v_right;
-	pointparticles(particleeffectnum("fireball_preattack_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-}
-
-void W_Fireball_Attack1_Frame4(void)
-{
-	W_Fireball_Attack1();
-	weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), w_ready);
-}
-
-void W_Fireball_Attack1_Frame3(void)
-{
-	W_Fireball_AttackEffect(0, '+1.25 +3.75 0');
-	weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame4);
-}
-
-void W_Fireball_Attack1_Frame2(void)
-{
-	W_Fireball_AttackEffect(0, '-1.25 +3.75 0');
-	weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame3);
-}
-
-void W_Fireball_Attack1_Frame1(void)
-{
-	W_Fireball_AttackEffect(1, '+1.25 -3.75 0');
-	weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame2);
-}
-
-void W_Fireball_Attack1_Frame0(void)
-{
-	W_Fireball_AttackEffect(0, '-1.25 -3.75 0');
-	sound(self, CH_WEAPON_SINGLE, "weapons/fireball_prefire2.wav", VOL_BASE, ATTEN_NORM);
-	weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(fireball, animtime), W_Fireball_Attack1_Frame1);
-}
-
-void W_Fireball_Firemine_Think(void)
-{
-	if(time > self.pushltime)
-	{
-		remove(self);
-		return;
-	}
-
-	// make it "hot" once it leaves its owner
-	if(self.owner)
-	{
-		if(vlen(self.origin - self.owner.origin - self.owner.view_ofs) > WEP_CVAR_SEC(fireball, laserradius))
-		{
-			self.cnt += 1;
-			if(self.cnt == 3)
-				self.owner = world;
-		}
-		else
-			self.cnt = 0;
-	}
-
-	W_Fireball_LaserPlay(0.1, WEP_CVAR_SEC(fireball, laserradius), WEP_CVAR_SEC(fireball, laserdamage), WEP_CVAR_SEC(fireball, laseredgedamage), WEP_CVAR_SEC(fireball, laserburntime));
-
-	self.nextthink = time + 0.1;
-}
-
-void W_Fireball_Firemine_Touch(void)
-{
-	PROJECTILE_TOUCH;
-	if(other.takedamage == DAMAGE_AIM)
-	if(Fire_AddDamage(other, self.realowner, WEP_CVAR_SEC(fireball, damage), WEP_CVAR_SEC(fireball, damagetime), self.projectiledeathtype) >= 0)
-	{
-		remove(self);
-		return;
-	}
-	self.projectiledeathtype |= HITTYPE_BOUNCE;
-}
-
-void W_Fireball_Attack2(void)
-{
-	entity proj;
-	vector f_diff;
-	float c;
-
-	c = mod(self.bulletcounter, 4);
-	switch(c)
-	{
-		case 0:
-			f_diff = '-1.25 -3.75 0';
-			break;
-		case 1:
-			f_diff = '+1.25 -3.75 0';
-			break;
-		case 2:
-			f_diff = '-1.25 +3.75 0';
-			break;
-		case 3:
-		default:
-			f_diff = '+1.25 +3.75 0';
-			break;
-	}
-	W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 2, "weapons/fireball_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(fireball, damage));
-	traceline(w_shotorg, w_shotorg + f_diff_x * v_up + f_diff_y * v_right, MOVE_NORMAL, self);
-	w_shotorg = trace_endpos;
-
-	pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	proj = spawn();
-	proj.owner = proj.realowner = self;
-	proj.classname = "grenade";
-	proj.bot_dodge = TRUE;
-	proj.bot_dodgerating = WEP_CVAR_SEC(fireball, damage);
-	proj.movetype = MOVETYPE_BOUNCE;
-	proj.projectiledeathtype = WEP_FIREBALL | HITTYPE_SECONDARY;
-	proj.touch = W_Fireball_Firemine_Touch;
-	PROJECTILE_MAKETRIGGER(proj);
-	setsize(proj, '-4 -4 -4', '4 4 4');
-	setorigin(proj, w_shotorg);
-	proj.think = W_Fireball_Firemine_Think;
-	proj.nextthink = time;
-	proj.damageforcescale = WEP_CVAR_SEC(fireball, damageforcescale);
-	proj.pushltime = time + WEP_CVAR_SEC(fireball, lifetime);
-	W_SetupProjVelocity_UP_SEC(proj, fireball);
-
-	proj.angles = vectoangles(proj.velocity);
-	proj.flags = FL_PROJECTILE;
-    proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC;
-
-	CSQCProjectile(proj, TRUE, PROJECTILE_FIREMINE, TRUE);
-
-	other = proj; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-float W_Fireball(float req)
-{
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			self.BUTTON_ATCK = FALSE;
-			self.BUTTON_ATCK2 = FALSE;
-			if(self.bot_primary_fireballmooth == 0)
-			{
-				if(bot_aim(WEP_CVAR_PRI(fireball, speed), 0, WEP_CVAR_PRI(fireball, lifetime), FALSE))
-				{
-					self.BUTTON_ATCK = TRUE;
-					if(random() < 0.02) self.bot_primary_fireballmooth = 0;
-				}
-			}
-			else
-			{
-				if(bot_aim(WEP_CVAR_SEC(fireball, speed), WEP_CVAR_SEC(fireball, speed_up), WEP_CVAR_SEC(fireball, lifetime), TRUE))
-				{
-					self.BUTTON_ATCK2 = TRUE;
-					if(random() < 0.01) self.bot_primary_fireballmooth = 1;
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(self.BUTTON_ATCK)
-			{
-				if(time >= self.fireball_primarytime)
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(fireball, refire)))
-				{
-					W_Fireball_Attack1_Frame0();
-					self.fireball_primarytime = time + WEP_CVAR_PRI(fireball, refire2) * W_WeaponRateFactor();
-				}
-			}
-			else if(self.BUTTON_ATCK2)
-			{
-				if(weapon_prepareattack(1, WEP_CVAR_SEC(fireball, refire)))
-				{
-					W_Fireball_Attack2();
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(fireball, animtime), w_ready);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_fireball.md3");
-			precache_model("models/weapons/v_fireball.md3");
-			precache_model("models/weapons/h_fireball.iqm");
-			precache_model("models/sphere/sphere.md3");
-			precache_sound("weapons/fireball_fire.wav");
-			precache_sound("weapons/fireball_fire2.wav");
-			precache_sound("weapons/fireball_prefire2.wav");
-			FIREBALL_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_SETUP:
-		{
-			self.ammo_field = ammo_none;
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		case WR_CHECKAMMO2:
-		{
-			return TRUE; // fireball has infinite ammo
-		}
-		case WR_CONFIG:
-		{
-			FIREBALL_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RESETPLAYER:
-		{
-			self.fireball_primarytime = time;
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_FIREBALL_SUICIDE_FIREMINE;
-			else
-				return WEAPON_FIREBALL_SUICIDE_BLAST;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_FIREBALL_MURDER_FIREMINE;
-			else
-				return WEAPON_FIREBALL_MURDER_BLAST;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Fireball(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			if(w_deathtype & HITTYPE_SECONDARY)
-			{
-				// firemine goes out silently
-			}
-			else
-			{
-				org2 = w_org + w_backoff * 16;
-				pointparticles(particleeffectnum("fireball_explode"), org2, '0 0 0', 1);
-				if(!w_issilent)
-					sound(self, CH_SHOTS, "weapons/fireball_impact2.wav", VOL_BASE, ATTEN_NORM * 0.25); // long range boom
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/fireball_impact2.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_hagar.qc b/qcsrc/common/weapons/w_hagar.qc
deleted file mode 100644
index fe3abf0a9..000000000
--- a/qcsrc/common/weapons/w_hagar.qc
+++ /dev/null
@@ -1,559 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ HAGAR,
-/* function  */ W_Hagar,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 8,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 1 0.5',
-/* modelname */ "hagar",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhagar 0.8",
-/* wepimg    */ "weaponhagar",
-/* refname   */ "hagar",
-/* wepname   */ _("Hagar")
-);
-
-#define HAGAR_SETTINGS(w_cvar,w_prop) HAGAR_SETTINGS_LIST(w_cvar, w_prop, HAGAR, hagar)
-#define HAGAR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, ammo) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, edgedamage) \
-	w_cvar(id, sn, BOTH, force) \
-	w_cvar(id, sn, BOTH, radius) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, BOTH, speed) \
-	w_cvar(id, sn, BOTH, spread) \
-	w_cvar(id, sn, BOTH, damageforcescale) \
-	w_cvar(id, sn, BOTH, health) \
-	w_cvar(id, sn, PRI,  lifetime) \
-	w_cvar(id, sn, SEC,  load) \
-	w_cvar(id, sn, SEC,  load_max) \
-	w_cvar(id, sn, SEC,  load_abort) \
-	w_cvar(id, sn, SEC,  load_animtime) \
-	w_cvar(id, sn, SEC,  load_hold) \
-	w_cvar(id, sn, SEC,  load_speed) \
-	w_cvar(id, sn, SEC,  load_releasedeath) \
-	w_cvar(id, sn, SEC,  load_spread) \
-	w_cvar(id, sn, SEC,  load_spread_bias) \
-	w_cvar(id, sn, SEC,  load_linkexplode) \
-	w_cvar(id, sn, SEC,  lifetime_min) \
-	w_cvar(id, sn, SEC,  lifetime_rand) \
-	w_cvar(id, sn, NONE, secondary) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-HAGAR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_hagar(void) { weapon_defaultspawnfunc(WEP_HAGAR); }
-
-// NO bounce protection, as bounces are limited!
-
-void W_Hagar_Explode(void)
-{
-	self.event_damage = func_null;
-	RadiusDamage(self, self.realowner, WEP_CVAR_PRI(hagar, damage), WEP_CVAR_PRI(hagar, edgedamage), WEP_CVAR_PRI(hagar, radius), world, world, WEP_CVAR_PRI(hagar, force), self.projectiledeathtype, other);
-
-	remove(self);
-}
-
-void W_Hagar_Explode2(void)
-{
-	self.event_damage = func_null;
-	RadiusDamage(self, self.realowner, WEP_CVAR_SEC(hagar, damage), WEP_CVAR_SEC(hagar, edgedamage), WEP_CVAR_SEC(hagar, radius), world, world, WEP_CVAR_SEC(hagar, force), self.projectiledeathtype, other);
-
-	remove(self);
-}
-
-void W_Hagar_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if(self.health <= 0)
-		return;
-		
-	float is_linkexplode = ( ((inflictor.owner != world) ? (inflictor.owner == self.owner) : TRUE)
-		&& (inflictor.projectiledeathtype & HITTYPE_SECONDARY) 
-		&& (self.projectiledeathtype & HITTYPE_SECONDARY));
-	
-	if(is_linkexplode)
-		is_linkexplode = (is_linkexplode && WEP_CVAR_SEC(hagar, load_linkexplode));
-	else
-		is_linkexplode = -1; // not secondary load, so continue as normal without exception.
-
-	if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, is_linkexplode))
-		return; // g_projectiles_damage says to halt
-
-	self.health = self.health - damage;
-	self.angles = vectoangles(self.velocity);
-	
-	if(self.health <= 0)
-		W_PrepareExplosionByDamage(attacker, self.think);
-}
-
-void W_Hagar_Touch(void)
-{
-	PROJECTILE_TOUCH;
-	self.use();
-}
-
-void W_Hagar_Touch2(void)
-{
-	PROJECTILE_TOUCH;
-
-	if(self.cnt > 0 || other.takedamage == DAMAGE_AIM) {
-		self.use();
-	} else {
-		self.cnt++;
-		pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1);
-		self.angles = vectoangles(self.velocity);
-		self.owner = world;
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-	}
-}
-
-void W_Hagar_Attack(void)
-{
-	entity missile;
-
-	W_DecreaseAmmo(WEP_CVAR_PRI(hagar, ammo));
-
-	W_SetupShot(self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(hagar, damage));
-
-	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	missile = spawn();
-	missile.owner = missile.realowner = self;
-	missile.classname = "missile";
-	missile.bot_dodge = TRUE;
-	missile.bot_dodgerating = WEP_CVAR_PRI(hagar, damage);
-	
-	missile.takedamage = DAMAGE_YES;
-	missile.health = WEP_CVAR_PRI(hagar, health);
-	missile.damageforcescale = WEP_CVAR_PRI(hagar, damageforcescale);
-	missile.event_damage = W_Hagar_Damage;
-	missile.damagedbycontents = TRUE;
-	
-	missile.touch = W_Hagar_Touch;
-	missile.use = W_Hagar_Explode;
-	missile.think = adaptor_think2use_hittype_splash;
-	missile.nextthink = time + WEP_CVAR_PRI(hagar, lifetime);
-	PROJECTILE_MAKETRIGGER(missile);
-	missile.projectiledeathtype = WEP_HAGAR;
-	setorigin(missile, w_shotorg);
-	setsize(missile, '0 0 0', '0 0 0');
-
-	missile.movetype = MOVETYPE_FLY;
-	W_SetupProjVelocity_PRI(missile, hagar);
-
-	missile.angles = vectoangles(missile.velocity);
-	missile.flags = FL_PROJECTILE;
-	missile.missile_flags = MIF_SPLASH; 
-
-	CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE);
-
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-void W_Hagar_Attack2(void)
-{
-	entity missile;
-
-	W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo));
-
-	W_SetupShot(self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
-
-	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	missile = spawn();
-	missile.owner = missile.realowner = self;
-	missile.classname = "missile";
-	missile.bot_dodge = TRUE;
-	missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage);
-	
-	missile.takedamage = DAMAGE_YES;
-	missile.health = WEP_CVAR_SEC(hagar, health);
-	missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale);
-	missile.event_damage = W_Hagar_Damage;
-	missile.damagedbycontents = TRUE;
-
-	missile.touch = W_Hagar_Touch2;
-	missile.cnt = 0;
-	missile.use = W_Hagar_Explode2;
-	missile.think = adaptor_think2use_hittype_splash;
-	missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand);
-	PROJECTILE_MAKETRIGGER(missile);
-	missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY;
-	setorigin(missile, w_shotorg);
-	setsize(missile, '0 0 0', '0 0 0');
-
-	missile.movetype = MOVETYPE_BOUNCEMISSILE;
-	W_SetupProjVelocity_SEC(missile, hagar);
-
-	missile.angles = vectoangles(missile.velocity);
-	missile.flags = FL_PROJECTILE;
-	missile.missile_flags = MIF_SPLASH; 
-
-	CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR_BOUNCING, TRUE);
-
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-.float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning;
-void W_Hagar_Attack2_Load_Release(void)
-{
-	// time to release the rockets we've loaded
-
-	entity missile;
-	float counter, shots, spread_pershot;
-	vector s;
-	vector forward, right, up;
-
-	if(!self.hagar_load)
-		return;
-
-	weapon_prepareattack_do(1, WEP_CVAR_SEC(hagar, refire));
-
-	W_SetupShot(self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hagar, damage));
-	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	forward = v_forward;
-	right = v_right;
-	up = v_up;
-
-	shots = self.hagar_load;
-	missile = world;
-	for(counter = 0; counter < shots; ++counter)
-	{
-		missile = spawn();
-		missile.owner = missile.realowner = self;
-		missile.classname = "missile";
-		missile.bot_dodge = TRUE;
-		missile.bot_dodgerating = WEP_CVAR_SEC(hagar, damage);
-		
-		missile.takedamage = DAMAGE_YES;
-		missile.health = WEP_CVAR_SEC(hagar, health);
-		missile.damageforcescale = WEP_CVAR_SEC(hagar, damageforcescale);
-		missile.event_damage = W_Hagar_Damage;
-		missile.damagedbycontents = TRUE;
-
-		missile.touch = W_Hagar_Touch; // not bouncy
-		missile.use = W_Hagar_Explode2;
-		missile.think = adaptor_think2use_hittype_splash;
-		missile.nextthink = time + WEP_CVAR_SEC(hagar, lifetime_min) + random() * WEP_CVAR_SEC(hagar, lifetime_rand);
-		PROJECTILE_MAKETRIGGER(missile);
-		missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY;
-		setorigin(missile, w_shotorg);
-		setsize(missile, '0 0 0', '0 0 0');
-		missile.movetype = MOVETYPE_FLY;
-		missile.missile_flags = MIF_SPLASH; 
-		
-		// per-shot spread calculation: the more shots there are, the less spread is applied (based on the bias cvar)
-		spread_pershot = ((shots - 1) / (WEP_CVAR_SEC(hagar, load_max) - 1)); 
-		spread_pershot = (1 - (spread_pershot * WEP_CVAR_SEC(hagar, load_spread_bias)));
-		spread_pershot = (WEP_CVAR_SEC(hagar, spread) * spread_pershot * g_weaponspreadfactor);
-		
-		// pattern spread calculation
-		s = '0 0 0';
-		if(counter == 0)
-			s = '0 0 0';
-		else
-		{
-			makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
-			s_y = v_forward_x;
-			s_z = v_forward_y;
-		}
-		s = s * WEP_CVAR_SEC(hagar, load_spread) * g_weaponspreadfactor;
-		
-		W_SetupProjVelocity_Explicit(missile, w_shotdir + right * s_y + up * s_z, v_up, WEP_CVAR_SEC(hagar, speed), 0, 0, spread_pershot, FALSE);
-
-		missile.angles = vectoangles(missile.velocity);
-		missile.flags = FL_PROJECTILE;
-
-		CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE);
-
-		other = missile; MUTATOR_CALLHOOK(EditProjectile);
-	}
-
-	weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hagar, load_animtime), w_ready);
-	self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, refire) * W_WeaponRateFactor();
-	self.hagar_load = 0;
-}
-
-void W_Hagar_Attack2_Load(void)
-{
-	// loadable hagar secondary attack, must always run each frame
-	
-	if(time < game_starttime)
-		return;
-
-	float loaded, enough_ammo;
-	loaded = self.hagar_load >= WEP_CVAR_SEC(hagar, load_max);
-
-	// this is different than WR_CHECKAMMO when it comes to reloading
-	if(autocvar_g_balance_hagar_reload_ammo)
-		enough_ammo = self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_SEC(hagar, ammo);
-	else
-		enough_ammo = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo);
-
-	if(self.BUTTON_ATCK2)
-	{
-		if(self.BUTTON_ATCK && WEP_CVAR_SEC(hagar, load_abort))
-		{
-			if(self.hagar_load)
-			{
-				// if we pressed primary fire while loading, unload all rockets and abort
-				self.weaponentity.state = WS_READY;
-				W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo
-				self.hagar_load = 0;
-				sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM);
-
-				// pause until we can load rockets again, once we re-press the alt fire button
-				self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor();
-
-				// require letting go of the alt fire button before we can load again
-				self.hagar_loadblock = TRUE;
-			}
-		}
-		else
-		{
-			// check if we can attempt to load another rocket
-			if(!loaded && enough_ammo)
-			{
-				if(!self.hagar_loadblock && self.hagar_loadstep < time)
-				{
-					W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo));
-					self.weaponentity.state = WS_INUSE;
-					self.hagar_load += 1;
-					sound(self, CH_WEAPON_B, "weapons/hagar_load.wav", VOL_BASE * 0.8, ATTN_NORM); // sound is too loud according to most
-
-					if(self.hagar_load >= WEP_CVAR_SEC(hagar, load_max))
-						self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_hold) * W_WeaponRateFactor();
-					else
-						self.hagar_loadstep = time + WEP_CVAR_SEC(hagar, load_speed) * W_WeaponRateFactor();
-				}
-			}
-			else if(!self.hagar_loadbeep && self.hagar_load) // prevents the beep from playing each frame
-			{
-				// if this is the last rocket we can load, play a beep sound to notify the player
-				sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM);
-				self.hagar_loadbeep = TRUE;
-			}
-		}
-	}
-	else if(self.hagar_loadblock)
-	{
-		// the alt fire button has been released, so re-enable loading if blocked
-		self.hagar_loadblock = FALSE;
-	}
-
-	if(self.hagar_load)
-	{
-		// play warning sound if we're about to release
-		if((loaded || !enough_ammo) && self.hagar_loadstep - 0.5 < time && WEP_CVAR_SEC(hagar, load_hold) >= 0)
-		{
-			if(!self.hagar_warning && self.hagar_load) // prevents the beep from playing each frame
-			{
-				// we're about to automatically release after holding time, play a beep sound to notify the player
-				sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTN_NORM);
-				self.hagar_warning = TRUE;
-			}
-		}
-		
-		// release if player let go of button or if they've held it in too long
-		if(!self.BUTTON_ATCK2 || ((loaded || !enough_ammo) && self.hagar_loadstep < time && WEP_CVAR_SEC(hagar, load_hold) >= 0))
-		{
-			self.weaponentity.state = WS_READY;
-			W_Hagar_Attack2_Load_Release();
-		}
-	}
-	else
-	{
-		self.hagar_loadbeep = FALSE;
-		self.hagar_warning = FALSE;
-	}
-
-	// we aren't checking ammo during an attack, so we must do it here
-	if(!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2)))
-	{
-		// note: this doesn't force the switch
-		W_SwitchToOtherWeapon(self);
-		return;
-	}
-}
-
-float W_Hagar(float req)
-{
-	float ammo_amount;
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			if(random()>0.15)
-				self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), FALSE);
-			else // not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
-				self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_PRI(hagar, speed), 0, WEP_CVAR_PRI(hagar, lifetime), FALSE);
-				
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			float loadable_secondary;
-			loadable_secondary = (WEP_CVAR_SEC(hagar, load) && WEP_CVAR(hagar, secondary));
-
-			if(loadable_secondary)
-				W_Hagar_Attack2_Load(); // must always run each frame
-			if(autocvar_g_balance_hagar_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo))) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-			else if(self.BUTTON_ATCK && !self.hagar_load && !self.hagar_loadblock) // not while secondary is loaded or awaiting reset
-			{
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(hagar, refire)))
-				{
-					W_Hagar_Attack();
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hagar, refire), w_ready);
-				}
-			}
-			else if(self.BUTTON_ATCK2 && !loadable_secondary && WEP_CVAR(hagar, secondary))
-			{
-				if(weapon_prepareattack(1, WEP_CVAR_SEC(hagar, refire)))
-				{
-					W_Hagar_Attack2();
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hagar, refire), w_ready);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_GONETHINK:
-		{
-			// we lost the weapon and want to prepare switching away
-			if(self.hagar_load)
-			{
-				self.weaponentity.state = WS_READY;
-				W_Hagar_Attack2_Load_Release();
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_hagar.md3");
-			precache_model("models/weapons/v_hagar.md3");
-			precache_model("models/weapons/h_hagar.iqm");
-			precache_sound("weapons/hagar_fire.wav");
-			precache_sound("weapons/hagar_load.wav");
-			precache_sound("weapons/hagar_beep.wav");
-			HAGAR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_SETUP:
-		{
-			self.hagar_loadblock = FALSE;
-
-			if(self.hagar_load)
-			{
-				W_DecreaseAmmo(WEP_CVAR_SEC(hagar, ammo) * self.hagar_load * -1); // give back ammo if necessary
-				self.hagar_load = 0;
-			}
-			
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_PRI(hagar, ammo);
-			ammo_amount += self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_PRI(hagar, ammo);
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			ammo_amount = self.WEP_AMMO(HAGAR) >= WEP_CVAR_SEC(hagar, ammo);
-			ammo_amount += self.(weapon_load[WEP_HAGAR]) >= WEP_CVAR_SEC(hagar, ammo);
-			return ammo_amount;
-		}
-		case WR_CONFIG:
-		{
-			HAGAR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RESETPLAYER:
-		{
-			self.hagar_load = 0;
-			return TRUE;
-		}
-		case WR_PLAYERDEATH:
-		{
-			// if we have any rockets loaded when we die, release them
-			if(self.hagar_load && WEP_CVAR_SEC(hagar, load_releasedeath))
-				W_Hagar_Attack2_Load_Release();
-				
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			if(!self.hagar_load) // require releasing loaded rockets first
-				W_Reload(min(WEP_CVAR_PRI(hagar, ammo), WEP_CVAR_SEC(hagar, ammo)), "weapons/reload.wav");
-				
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_HAGAR_SUICIDE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_HAGAR_MURDER_BURST;
-			else
-				return WEAPON_HAGAR_MURDER_SPRAY;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Hagar(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 6;
-			pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
-			if(!w_issilent)
-			{
-				if(w_random<0.15)
-					sound(self, CH_SHOTS, "weapons/hagexp1.wav", VOL_BASE, ATTN_NORM);
-				else if(w_random<0.7)
-					sound(self, CH_SHOTS, "weapons/hagexp2.wav", VOL_BASE, ATTN_NORM);
-				else
-					sound(self, CH_SHOTS, "weapons/hagexp3.wav", VOL_BASE, ATTN_NORM);
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/hagexp1.wav");
-			precache_sound("weapons/hagexp2.wav");
-			precache_sound("weapons/hagexp3.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_hlac.qc b/qcsrc/common/weapons/w_hlac.qc
deleted file mode 100644
index d3dbed2f9..000000000
--- a/qcsrc/common/weapons/w_hlac.qc
+++ /dev/null
@@ -1,313 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ HLAC,
-/* function  */ W_HLAC,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 6,
-/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0 1 0',
-/* modelname */ "hlac",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhlac 0.6",
-/* wepimg    */ "weaponhlac",
-/* refname   */ "hlac",
-/* wepname   */ _("Heavy Laser Assault Cannon")
-);
-
-#define HLAC_SETTINGS(w_cvar,w_prop) HLAC_SETTINGS_LIST(w_cvar, w_prop, HLAC, hlac)
-#define HLAC_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, ammo) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, edgedamage) \
-	w_cvar(id, sn, BOTH, force) \
-	w_cvar(id, sn, BOTH, lifetime) \
-	w_cvar(id, sn, BOTH, radius) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, BOTH, speed) \
-	w_cvar(id, sn, BOTH, spread_crouchmod) \
-	w_cvar(id, sn, PRI,  spread_add) \
-	w_cvar(id, sn, PRI,  spread_max) \
-	w_cvar(id, sn, PRI,  spread_min) \
-	w_cvar(id, sn, NONE, secondary) \
-	w_cvar(id, sn, SEC,  shots) \
-	w_cvar(id, sn, SEC,  spread) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-HLAC_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_hlac(void) { weapon_defaultspawnfunc(WEP_HLAC); }
-
-void W_HLAC_Touch(void)
-{
-	float isprimary;
-
-	PROJECTILE_TOUCH;
-
-	self.event_damage = func_null;
-	
-	isprimary = !(self.projectiledeathtype & HITTYPE_SECONDARY);
-	
-	RadiusDamage(self, self.realowner, WEP_CVAR_BOTH(hlac, isprimary, damage), WEP_CVAR_BOTH(hlac, isprimary, edgedamage), WEP_CVAR_BOTH(hlac, isprimary, radius), world, world, WEP_CVAR_BOTH(hlac, isprimary, force), self.projectiledeathtype, other);
-
-	remove(self);
-}
-
-void W_HLAC_Attack(void)
-{
-	entity missile;
-    float spread;
-
-	W_DecreaseAmmo(WEP_CVAR_PRI(hlac, ammo));
-
-    spread = WEP_CVAR_PRI(hlac, spread_min) + (WEP_CVAR_PRI(hlac, spread_add) * self.misc_bulletcounter);
-    spread = min(spread,WEP_CVAR_PRI(hlac, spread_max));
-    if(self.crouch)
-        spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
-
-	W_SetupShot(self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage));
-	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-	if(!autocvar_g_norecoil)
-	{
-		self.punchangle_x = random() - 0.5;
-		self.punchangle_y = random() - 0.5;
-	}
-
-	missile = spawn();
-	missile.owner = missile.realowner = self;
-	missile.classname = "hlacbolt";
-	missile.bot_dodge = TRUE;
-
-    missile.bot_dodgerating = WEP_CVAR_PRI(hlac, damage);
-
-	missile.movetype = MOVETYPE_FLY;
-	PROJECTILE_MAKETRIGGER(missile);
-
-	setorigin(missile, w_shotorg);
-	setsize(missile, '0 0 0', '0 0 0');
-
-	W_SetupProjVelocity_Basic(missile, WEP_CVAR_PRI(hlac, speed), spread);
-	//missile.angles = vectoangles(missile.velocity); // csqc
-
-	missile.touch = W_HLAC_Touch;
-	missile.think = SUB_Remove;
-
-    missile.nextthink = time + WEP_CVAR_PRI(hlac, lifetime);
-
-	missile.flags = FL_PROJECTILE;
-	missile.projectiledeathtype = WEP_HLAC;
-
-	CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE);
-
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-void W_HLAC_Attack2(void)
-{
-	entity missile;
-    float spread;
-
-    spread = WEP_CVAR_SEC(hlac, spread);
-
-
-    if(self.crouch)
-        spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod);
-
-	W_SetupShot(self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage));
-	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	missile = spawn();
-	missile.owner = missile.realowner = self;
-	missile.classname = "hlacbolt";
-	missile.bot_dodge = TRUE;
-
-    missile.bot_dodgerating = WEP_CVAR_SEC(hlac, damage);
-
-	missile.movetype = MOVETYPE_FLY;
-	PROJECTILE_MAKETRIGGER(missile);
-
-	setorigin(missile, w_shotorg);
-	setsize(missile, '0 0 0', '0 0 0');
-
-	W_SetupProjVelocity_Basic(missile, WEP_CVAR_SEC(hlac, speed), spread);
-	//missile.angles = vectoangles(missile.velocity); // csqc
-
-	missile.touch = W_HLAC_Touch;
-	missile.think = SUB_Remove;
-
-    missile.nextthink = time + WEP_CVAR_SEC(hlac, lifetime);
-
-	missile.flags = FL_PROJECTILE;
-	missile.missile_flags = MIF_SPLASH; 
-	missile.projectiledeathtype = WEP_HLAC | HITTYPE_SECONDARY;
-
-	CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE);
-
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-// weapon frames
-void W_HLAC_Attack_Frame(void)
-{
-	if(self.weapon != self.switchweapon) // abort immediately if switching
-	{
-		w_ready();
-		return;
-	}
-
-	if(self.BUTTON_ATCK)
-	{
-		if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1))
-		if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-		{
-			W_SwitchWeapon_Force(self, w_getbestweapon(self));
-			w_ready();
-			return;
-		}
-
-		ATTACK_FINISHED(self) = time + WEP_CVAR_PRI(hlac, refire) * W_WeaponRateFactor();
-		W_HLAC_Attack();
-		self.misc_bulletcounter = self.misc_bulletcounter + 1;
-        weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
-	}
-	else
-	{
-		weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, animtime), w_ready);
-	}
-}
-
-void W_HLAC_Attack2_Frame(void)
-{
-    float i;
-
-	W_DecreaseAmmo(WEP_CVAR_SEC(hlac, ammo));
-
-    for(i=WEP_CVAR_SEC(hlac, shots);i>0;--i)
-        W_HLAC_Attack2();
-
-	if(!autocvar_g_norecoil)
-	{
-		self.punchangle_x = random() - 0.5;
-		self.punchangle_y = random() - 0.5;
-	}
-}
-
-float W_HLAC(float req)
-{
-	float ammo_amount;
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			self.BUTTON_ATCK = bot_aim(WEP_CVAR_PRI(hlac, speed), 0, WEP_CVAR_PRI(hlac, lifetime), FALSE);
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(autocvar_g_balance_hlac_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo))) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-			else if(self.BUTTON_ATCK)
-			{
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(hlac, refire)))
-				{
-					self.misc_bulletcounter = 0;
-					W_HLAC_Attack();
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hlac, refire), W_HLAC_Attack_Frame);
-				}
-			}
-
-			else if(self.BUTTON_ATCK2 && WEP_CVAR(hlac, secondary))
-			{
-				if(weapon_prepareattack(1, WEP_CVAR_SEC(hlac, refire)))
-				{
-					W_HLAC_Attack2_Frame();
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hlac, animtime), w_ready);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_hlac.md3");
-			precache_model("models/weapons/v_hlac.md3");
-			precache_model("models/weapons/h_hlac.iqm");
-			precache_sound("weapons/lasergun_fire.wav");
-			HLAC_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_PRI(hlac, ammo);
-			ammo_amount += self.(weapon_load[WEP_HLAC]) >= WEP_CVAR_PRI(hlac, ammo);
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			ammo_amount = self.WEP_AMMO(HLAC) >= WEP_CVAR_SEC(hlac, ammo);
-			ammo_amount += self.(weapon_load[WEP_HLAC]) >= WEP_CVAR_SEC(hlac, ammo);
-			return ammo_amount;
-		}
-		case WR_CONFIG:
-		{
-			HLAC_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(min(WEP_CVAR_PRI(hlac, ammo), WEP_CVAR_SEC(hlac, ammo)), "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_HLAC_SUICIDE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			return WEAPON_HLAC_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_HLAC(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 6;
-			pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1);
-			if(!w_issilent)
-				sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM);
-				
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/laserimpact.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_hook.qc b/qcsrc/common/weapons/w_hook.qc
deleted file mode 100644
index 931d3e0ad..000000000
--- a/qcsrc/common/weapons/w_hook.qc
+++ /dev/null
@@ -1,367 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ HOOK,
-/* function  */ W_Hook,
-/* ammotype  */ ammo_fuel,
-/* impulse   */ 0,
-/* flags     */ WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ 0,
-/* color     */ '0 0.5 0',
-/* modelname */ "hookgun",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairhook 0.5",
-/* wepimg    */ "weaponhook",
-/* refname   */ "hook",
-/* wepname   */ _("Grappling Hook")
-);
-
-#define HOOK_SETTINGS(w_cvar,w_prop) HOOK_SETTINGS_LIST(w_cvar, w_prop, HOOK, hook)
-#define HOOK_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, PRI,  ammo) \
-	w_cvar(id, sn, PRI,  hooked_ammo) \
-	w_cvar(id, sn, PRI,  hooked_time_free) \
-	w_cvar(id, sn, PRI,  hooked_time_max) \
-	w_cvar(id, sn, SEC,  damage) \
-	w_cvar(id, sn, SEC,  duration) \
-	w_cvar(id, sn, SEC,  edgedamage) \
-	w_cvar(id, sn, SEC,  force) \
-	w_cvar(id, sn, SEC,  gravity) \
-	w_cvar(id, sn, SEC,  lifetime) \
-	w_cvar(id, sn, SEC,  power) \
-	w_cvar(id, sn, SEC,  radius) \
-	w_cvar(id, sn, SEC,  speed) \
-	w_cvar(id, sn, SEC,  health) \
-	w_cvar(id, sn, SEC,  damageforcescale) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-HOOK_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-
-.float dmg;
-.float dmg_edge;
-.float dmg_radius;
-.float dmg_force;
-.float dmg_power;
-.float dmg_duration;
-.float dmg_last;
-.float hook_refire;
-.float hook_time_hooked;
-.float hook_time_fueldecrease;
-#endif
-#else
-#ifdef SVQC
-
-void spawnfunc_weapon_hook(void)
-{
-	if(g_grappling_hook) // offhand hook
-	{
-		startitem_failed = TRUE;
-		remove(self);
-		return;
-	}
-	weapon_defaultspawnfunc(WEP_HOOK);
-}
-
-void W_Hook_ExplodeThink(void)
-{
-	float dt, dmg_remaining_next, f;
-
-	dt = time - self.teleport_time;
-	dmg_remaining_next = pow(bound(0, 1 - dt / self.dmg_duration, 1), self.dmg_power);
-
-	f = self.dmg_last - dmg_remaining_next;
-	self.dmg_last = dmg_remaining_next;
-
-	RadiusDamage(self, self.realowner, self.dmg * f, self.dmg_edge * f, self.dmg_radius, self.realowner, world, self.dmg_force * f, self.projectiledeathtype, world);
-	self.projectiledeathtype |= HITTYPE_BOUNCE;
-	//RadiusDamage(self, world, self.dmg * f, self.dmg_edge * f, self.dmg_radius, world, world, self.dmg_force * f, self.projectiledeathtype, world);
-
-	if(dt < self.dmg_duration)
-		self.nextthink = time + 0.05; // soon
-	else
-		remove(self);
-}
-
-void W_Hook_Explode2(void)
-{
-	self.event_damage = func_null;
-	self.touch = func_null;
-	self.effects |= EF_NODRAW;
-
-	self.think = W_Hook_ExplodeThink;
-	self.nextthink = time;
-	self.dmg = WEP_CVAR_SEC(hook, damage);
-	self.dmg_edge = WEP_CVAR_SEC(hook, edgedamage);
-	self.dmg_radius = WEP_CVAR_SEC(hook, radius);
-	self.dmg_force = WEP_CVAR_SEC(hook, force);
-	self.dmg_power = WEP_CVAR_SEC(hook, power);
-	self.dmg_duration = WEP_CVAR_SEC(hook, duration);
-	self.teleport_time = time;
-	self.dmg_last = 1;
-	self.movetype = MOVETYPE_NONE;
-}
-
-void W_Hook_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if(self.health <= 0)
-		return;
-		
-	if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
-		return; // g_projectiles_damage says to halt	
-	
-	self.health = self.health - damage;
-	
-	if(self.health <= 0)
-		W_PrepareExplosionByDamage(self.realowner, W_Hook_Explode2);
-}
-
-void W_Hook_Touch2(void)
-{
-	PROJECTILE_TOUCH;
-	self.use();
-}
-
-void W_Hook_Attack2(void)
-{
-	entity gren;
-
-	//W_DecreaseAmmo(WEP_CVAR_SEC(hook, ammo)); // WEAPONTODO: Figure out how to handle ammo with hook secondary (gravitybomb)
-	W_SetupShot(self, FALSE, 4, "weapons/hookbomb_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(hook, damage));
-
-	gren = spawn();
-	gren.owner = gren.realowner = self;
-	gren.classname = "hookbomb";
-	gren.bot_dodge = TRUE;
-	gren.bot_dodgerating = WEP_CVAR_SEC(hook, damage);
-	gren.movetype = MOVETYPE_TOSS;
-	PROJECTILE_MAKETRIGGER(gren);
-	gren.projectiledeathtype = WEP_HOOK | HITTYPE_SECONDARY;
-	setorigin(gren, w_shotorg);
-	setsize(gren, '0 0 0', '0 0 0');
-
-	gren.nextthink = time + WEP_CVAR_SEC(hook, lifetime);
-	gren.think = adaptor_think2use_hittype_splash;
-	gren.use = W_Hook_Explode2;
-	gren.touch = W_Hook_Touch2;
-	
-	gren.takedamage = DAMAGE_YES;
-	gren.health = WEP_CVAR_SEC(hook, health);
-	gren.damageforcescale = WEP_CVAR_SEC(hook, damageforcescale);
-	gren.event_damage = W_Hook_Damage;
-	gren.damagedbycontents = TRUE;
-	gren.missile_flags = MIF_SPLASH | MIF_ARC;
-
-	gren.velocity = '0 0 1' * WEP_CVAR_SEC(hook, speed);
-	if(autocvar_g_projectiles_newton_style)
-		gren.velocity = gren.velocity + self.velocity;
-
-	gren.gravity = WEP_CVAR_SEC(hook, gravity);
-	//W_SetupProjVelocity_Basic(gren); // just falling down!
-
-	gren.angles = '0 0 0';
-	gren.flags = FL_PROJECTILE;
-
-	CSQCProjectile(gren, TRUE, PROJECTILE_HOOKBOMB, TRUE);
-
-	other = gren; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-float W_Hook(float req)
-{
-	float hooked_time_max, hooked_fuel;
-		
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			// no bot AI for hook (yet?)
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK))
-			{
-				if(!self.hook)
-				if(!(self.hook_state & HOOK_WAITING_FOR_RELEASE))
-				if(!(self.hook_state & HOOK_FIRING))
-				if(time > self.hook_refire)
-				if(weapon_prepareattack(0, -1))
-				{
-					W_DecreaseAmmo(WEP_CVAR_PRI(hook, ammo));
-					self.hook_state |= HOOK_FIRING;
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(hook, animtime), w_ready);				
-				}
-			}
-
-			if(self.BUTTON_ATCK2)
-			{
-				if(weapon_prepareattack(1, WEP_CVAR_SEC(hook, refire)))
-				{
-					W_Hook_Attack2();
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(hook, animtime), w_ready);
-				}
-			}
-
-			if(self.hook)
-			{
-				// if hooked, no bombs, and increase the timer
-				self.hook_refire = max(self.hook_refire, time + WEP_CVAR_PRI(hook, refire) * W_WeaponRateFactor());
-
-				// hook also inhibits health regeneration, but only for 1 second
-				if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-					self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
-			}
-
-			if(self.hook && self.hook.state == 1)
-			{
-				hooked_time_max = WEP_CVAR_PRI(hook, hooked_time_max);			
-				if(hooked_time_max > 0)
-				{
-					if( time > self.hook_time_hooked + hooked_time_max )
-						self.hook_state |= HOOK_REMOVING;
-				}
-				
-				hooked_fuel = WEP_CVAR_PRI(hook, hooked_ammo);
-				if(hooked_fuel > 0)
-				{
-					if( time > self.hook_time_fueldecrease )
-					{
-						if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-						{
-							if( self.ammo_fuel >= (time - self.hook_time_fueldecrease) * hooked_fuel )
-							{
-								W_DecreaseAmmo((time - self.hook_time_fueldecrease) * hooked_fuel);
-								self.hook_time_fueldecrease = time;
-								// decrease next frame again
-							}
-							else
-							{
-								self.ammo_fuel = 0;
-								self.hook_state |= HOOK_REMOVING;
-								W_SwitchWeapon_Force(self, w_getbestweapon(self));
-							}
-						}
-					}
-				}
-			}
-			else
-			{
-				self.hook_time_hooked = time;				
-				self.hook_time_fueldecrease = time + WEP_CVAR_PRI(hook, hooked_time_free);
-			}
-
-			if(self.BUTTON_CROUCH)
-			{
-				self.hook_state &= ~HOOK_PULLING;
-				if(self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK))
-					self.hook_state &= ~HOOK_RELEASING;
-				else
-					self.hook_state |= HOOK_RELEASING;
-			}
-			else
-			{
-				self.hook_state |= HOOK_PULLING;
-				self.hook_state &= ~HOOK_RELEASING;
-
-				if(self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK))
-				{
-					// already fired
-					if(self.hook)
-						self.hook_state |= HOOK_WAITING_FOR_RELEASE;
-				}
-				else
-				{
-					self.hook_state |= HOOK_REMOVING;
-					self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_hookgun.md3");
-			precache_model("models/weapons/v_hookgun.md3");
-			precache_model("models/weapons/h_hookgun.iqm");
-			precache_sound("weapons/hook_impact.wav"); // done by g_hook.qc
-			precache_sound("weapons/hook_fire.wav");
-			precache_sound("weapons/hookbomb_fire.wav");
-			HOOK_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_SETUP:
-		{
-			self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			if(self.hook)
-				return self.ammo_fuel > 0;
-			else
-				return self.ammo_fuel >= WEP_CVAR_PRI(hook, ammo);
-		}
-		case WR_CHECKAMMO2:
-		{
-			// infinite ammo for now
-			return TRUE; // self.ammo_cells >= WEP_CVAR_SEC(hook, ammo); // WEAPONTODO: see above
-		}
-		case WR_CONFIG:
-		{
-			HOOK_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RESETPLAYER:
-		{
-			self.hook_refire = time;
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return FALSE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			return WEAPON_HOOK_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Hook(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 2;
-			pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1);
-			if(!w_issilent)
-				sound(self, CH_SHOTS, "weapons/hookbomb_impact.wav", VOL_BASE, ATTN_NORM);
-				
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/hookbomb_impact.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_machinegun.qc b/qcsrc/common/weapons/w_machinegun.qc
deleted file mode 100644
index 9c69c8d82..000000000
--- a/qcsrc/common/weapons/w_machinegun.qc
+++ /dev/null
@@ -1,407 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ MACHINEGUN,
-/* function  */ W_MachineGun,
-/* ammotype  */ ammo_nails,
-/* impulse   */ 3,
-/* flags     */ WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 1 0',
-/* modelname */ "uzi",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairuzi 0.6",
-/* wepimg    */ "weaponuzi",
-/* refname   */ "machinegun",
-/* wepname   */ _("Machine Gun")
-);
-
-#define MACHINEGUN_SETTINGS(w_cvar,w_prop) MACHINEGUN_SETTINGS_LIST(w_cvar, w_prop, MACHINEGUN, machinegun)
-#define MACHINEGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, NONE, spread_min) \
-	w_cvar(id, sn, NONE, spread_max) \
-	w_cvar(id, sn, NONE, spread_add) \
-	w_cvar(id, sn, NONE, mode) \
-	w_cvar(id, sn, NONE, first) \
-	w_cvar(id, sn, NONE, first_damage) \
-	w_cvar(id, sn, NONE, first_force) \
-	w_cvar(id, sn, NONE, first_refire) \
-	w_cvar(id, sn, NONE, first_spread) \
-	w_cvar(id, sn, NONE, first_ammo) \
-	w_cvar(id, sn, NONE, solidpenetration) \
-	w_cvar(id, sn, NONE, sustained_damage) \
-	w_cvar(id, sn, NONE, sustained_force) \
-	w_cvar(id, sn, NONE, sustained_refire) \
-	w_cvar(id, sn, NONE, sustained_spread) \
-	w_cvar(id, sn, NONE, sustained_ammo) \
-	w_cvar(id, sn, NONE, burst) \
-	w_cvar(id, sn, NONE, burst_refire) \
-	w_cvar(id, sn, NONE, burst_refire2) \
-	w_cvar(id, sn, NONE, burst_animtime) \
-	w_cvar(id, sn, NONE, burst_speed) \
-	w_cvar(id, sn, NONE, burst_ammo) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-MACHINEGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-#endif
-#else
-#ifdef SVQC
-
-void spawnfunc_weapon_machinegun(void)
-{
-	if(autocvar_sv_q3acompat_machineshotgunswap)
-	if(self.classname != "droppedweapon")
-	{
-		weapon_defaultspawnfunc(WEP_SHOCKWAVE);
-		return;
-	}
-	weapon_defaultspawnfunc(WEP_MACHINEGUN);
-}
-void spawnfunc_weapon_uzi(void) { spawnfunc_weapon_machinegun(); }
-
-void W_MachineGun_MuzzleFlash_Think(void)
-{
-	self.frame = self.frame + 2;
-	self.scale = self.scale * 0.5;
-	self.alpha = self.alpha - 0.25;
-	self.nextthink = time + 0.05;
-
-	if(self.alpha <= 0)
-	{
-		self.think = SUB_Remove;
-		self.nextthink = time;
-		self.realowner.muzzle_flash = world;
-		return;
-	}
-
-}
-
-void W_MachineGun_MuzzleFlash(void)
-{
-	if(self.muzzle_flash == world)
-		self.muzzle_flash = spawn();
-
-	// muzzle flash for 1st person view
-	setmodel(self.muzzle_flash, "models/uziflash.md3"); // precision set below
-
-	self.muzzle_flash.scale = 0.75;
-	self.muzzle_flash.think = W_MachineGun_MuzzleFlash_Think;
-	self.muzzle_flash.nextthink = time + 0.02;
-	self.muzzle_flash.frame = 2;
-	self.muzzle_flash.alpha = 0.75;
-	self.muzzle_flash.angles_z = random() * 180;
-	self.muzzle_flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-	self.muzzle_flash.owner = self.muzzle_flash.realowner = self;
-}
-
-void W_MachineGun_Attack(float deathtype)
-{
-	W_SetupShot(self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? WEP_CVAR(machinegun, first_damage) : WEP_CVAR(machinegun, sustained_damage)));
-	if(!autocvar_g_norecoil)
-	{
-		self.punchangle_x = random() - 0.5;
-		self.punchangle_y = random() - 0.5;
-	}
-
-	// this attack_finished just enforces a cooldown at the end of a burst
-	ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor();
-
-	if(self.misc_bulletcounter == 1)
-		fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, first_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, first_damage), WEP_CVAR(machinegun, first_force), deathtype, 0);
-	else
-		fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, sustained_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), deathtype, 0);
-
-	pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	W_MachineGun_MuzzleFlash();
-	W_AttachToShotorg(self.muzzle_flash, '5 0 0');
-
-	// casing code
-	if(autocvar_g_casings >= 2)
-		SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
-
-	if(self.misc_bulletcounter == 1)
-		W_DecreaseAmmo(WEP_CVAR(machinegun, first_ammo));
-	else
-		W_DecreaseAmmo(WEP_CVAR(machinegun, sustained_ammo));
-}
-
-// weapon frames
-void W_MachineGun_Attack_Frame(void)
-{
-	if(self.weapon != self.switchweapon) // abort immediately if switching
-	{
-		w_ready();
-		return;
-	}
-	if(self.BUTTON_ATCK)
-	{
-		if(!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
-		if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-		{
-			W_SwitchWeapon_Force(self, w_getbestweapon(self));
-			w_ready();
-			return;
-		}
-		self.misc_bulletcounter = self.misc_bulletcounter + 1;
-		W_MachineGun_Attack(WEP_MACHINEGUN);
-		weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
-	}
-	else
-		weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), w_ready);
-}
-
-
-void W_MachineGun_Attack_Auto(void)
-{
-	float machinegun_spread;
-
-	if(!self.BUTTON_ATCK)
-	{
-		w_ready();
-		return;
-	}
-
-	if(!WEP_ACTION(self.weapon, WR_CHECKAMMO1))
-	if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-	{
-		W_SwitchWeapon_Force(self, w_getbestweapon(self));
-		w_ready();
-		return;
-	}
-
-	W_DecreaseAmmo(WEP_CVAR(machinegun, sustained_ammo));
-
-	W_SetupShot(self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
-	if(!autocvar_g_norecoil)
-	{
-		self.punchangle_x = random() - 0.5;
-		self.punchangle_y = random() - 0.5;
-	}
-
-	machinegun_spread = bound(WEP_CVAR(machinegun, spread_min), WEP_CVAR(machinegun, spread_min) + (WEP_CVAR(machinegun, spread_add) * self.misc_bulletcounter), WEP_CVAR(machinegun, spread_max));
-	fireBullet(w_shotorg, w_shotdir, machinegun_spread, WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN, 0);
-
-	self.misc_bulletcounter = self.misc_bulletcounter + 1;
-
-	pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	W_MachineGun_MuzzleFlash();
-	W_AttachToShotorg(self.muzzle_flash, '5 0 0');
-
-	if(autocvar_g_casings >= 2) // casing code
-		SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
-
-	ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, first_refire) * W_WeaponRateFactor();
-	weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Auto);
-}
-
-void W_MachineGun_Attack_Burst(void)
-{
-	W_SetupShot(self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, WEP_CVAR(machinegun, sustained_damage));
-	if(!autocvar_g_norecoil)
-	{
-		self.punchangle_x = random() - 0.5;
-		self.punchangle_y = random() - 0.5;
-	}
-
-	fireBullet(w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), WEP_MACHINEGUN, 0);
-
-	pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	W_MachineGun_MuzzleFlash();
-	W_AttachToShotorg(self.muzzle_flash, '5 0 0');
-
-	if(autocvar_g_casings >= 2) // casing code
-		SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
-
-	self.misc_bulletcounter = self.misc_bulletcounter + 1;
-	if(self.misc_bulletcounter == 0)
-	{
-		ATTACK_FINISHED(self) = time + WEP_CVAR(machinegun, burst_refire2) * W_WeaponRateFactor();
-		weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, burst_animtime), w_ready);
-	}
-	else
-	{
-		weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, burst_refire), W_MachineGun_Attack_Burst);
-	}
-
-}
-
-float W_MachineGun(float req)
-{
-	float ammo_amount;
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200)
-				self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
-			else
-				self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE);
-			
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(WEP_CVAR(machinegun, reload_ammo) && self.clip_load < min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo))) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-			else if(WEP_CVAR(machinegun, mode) == 1)
-			{
-				if(self.BUTTON_ATCK)
-				if(weapon_prepareattack(0, 0))
-				{
-					self.misc_bulletcounter = 0;
-					W_MachineGun_Attack_Auto();
-				}
-
-				if(self.BUTTON_ATCK2)
-				if(weapon_prepareattack(1, 0))
-				{
-					if(!WEP_ACTION(self.weapon, WR_CHECKAMMO2))
-					if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-					{
-						W_SwitchWeapon_Force(self, w_getbestweapon(self));
-						w_ready();
-						return FALSE;
-					}
-
-					W_DecreaseAmmo(WEP_CVAR(machinegun, burst_ammo));
-
-					self.misc_bulletcounter = WEP_CVAR(machinegun, burst) * -1;
-					W_MachineGun_Attack_Burst();
-				}
-			}
-			else
-			{
-
-				if(self.BUTTON_ATCK)
-				if(weapon_prepareattack(0, 0))
-				{
-					self.misc_bulletcounter = 1;
-					W_MachineGun_Attack(WEP_MACHINEGUN); // sets attack_finished
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(machinegun, sustained_refire), W_MachineGun_Attack_Frame);
-				}
-
-				if(self.BUTTON_ATCK2 && WEP_CVAR(machinegun, first))
-				if(weapon_prepareattack(1, 0))
-				{
-					self.misc_bulletcounter = 1;
-					W_MachineGun_Attack(WEP_MACHINEGUN | HITTYPE_SECONDARY); // sets attack_finished
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(machinegun, first_refire), w_ready);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/uziflash.md3");
-			precache_model("models/weapons/g_uzi.md3");
-			precache_model("models/weapons/v_uzi.md3");
-			precache_model("models/weapons/h_uzi.iqm");
-			precache_sound("weapons/uzi_fire.wav");
-			MACHINEGUN_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			if(WEP_CVAR(machinegun, mode) == 1)
-				ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, sustained_ammo);
-			else
-				ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, first_ammo);
-
-			if(WEP_CVAR(machinegun, reload_ammo))
-			{
-				if(WEP_CVAR(machinegun, mode) == 1)
-					ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, sustained_ammo);
-				else
-					ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, first_ammo);
-			}
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			if(WEP_CVAR(machinegun, mode) == 1)
-				ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, burst_ammo);
-			else
-				ammo_amount = self.WEP_AMMO(MACHINEGUN) >= WEP_CVAR(machinegun, first_ammo);
-
-			if(WEP_CVAR(machinegun, reload_ammo))
-			{
-				if(WEP_CVAR(machinegun, mode) == 1)
-					ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, burst_ammo);
-				else
-					ammo_amount += self.(weapon_load[WEP_MACHINEGUN]) >= WEP_CVAR(machinegun, first_ammo);
-			}
-			return ammo_amount;
-		}
-		case WR_CONFIG:
-		{
-			MACHINEGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(min(max(WEP_CVAR(machinegun, sustained_ammo), WEP_CVAR(machinegun, first_ammo)), WEP_CVAR(machinegun, burst_ammo)), "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_THINKING_WITH_PORTALS;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_MACHINEGUN_MURDER_SNIPE;
-			else
-				return WEAPON_MACHINEGUN_MURDER_SPRAY;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_MachineGun(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 2;
-			pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1);
-			if(!w_issilent)
-				if(w_random < 0.05)
-					sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_NORM);
-				else if(w_random < 0.1)
-					sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTN_NORM);
-				else if(w_random < 0.2)
-					sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTN_NORM);
-					
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/ric1.wav");
-			precache_sound("weapons/ric2.wav");
-			precache_sound("weapons/ric3.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_minelayer.qc b/qcsrc/common/weapons/w_minelayer.qc
deleted file mode 100644
index e0e9c6256..000000000
--- a/qcsrc/common/weapons/w_minelayer.qc
+++ /dev/null
@@ -1,620 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ MINE_LAYER,
-/* function  */ W_MineLayer,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 4,
-/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '0.75 1 0',
-/* modelname */ "minelayer",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairminelayer 0.9",
-/* wepimg    */ "weaponminelayer",
-/* refname   */ "minelayer",
-/* wepname   */ _("Mine Layer")
-);
-
-#define MINELAYER_SETTINGS(w_cvar,w_prop) MINELAYER_SETTINGS_LIST(w_cvar, w_prop, MINE_LAYER, minelayer)
-#define MINELAYER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, NONE, ammo) \
-	w_cvar(id, sn, NONE, animtime) \
-	w_cvar(id, sn, NONE, damage) \
-	w_cvar(id, sn, NONE, damageforcescale) \
-	w_cvar(id, sn, NONE, detonatedelay) \
-	w_cvar(id, sn, NONE, edgedamage) \
-	w_cvar(id, sn, NONE, force) \
-	w_cvar(id, sn, NONE, health) \
-	w_cvar(id, sn, NONE, lifetime) \
-	w_cvar(id, sn, NONE, lifetime_countdown) \
-	w_cvar(id, sn, NONE, limit) \
-	w_cvar(id, sn, NONE, protection) \
-	w_cvar(id, sn, NONE, proximityradius) \
-	w_cvar(id, sn, NONE, radius) \
-	w_cvar(id, sn, NONE, refire) \
-	w_cvar(id, sn, NONE, remote_damage) \
-	w_cvar(id, sn, NONE, remote_edgedamage) \
-	w_cvar(id, sn, NONE, remote_force) \
-	w_cvar(id, sn, NONE, remote_radius) \
-	w_cvar(id, sn, NONE, speed) \
-	w_cvar(id, sn, NONE, time) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-MINELAYER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-void W_MineLayer_Think(void);
-.float minelayer_detonate, mine_explodeanyway;
-.float mine_time;
-.vector mine_orientation;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_minelayer(void) { weapon_defaultspawnfunc(WEP_MINE_LAYER); }
-
-void W_MineLayer_Stick(entity to)
-{
-	spamsound(self, CH_SHOTS, "weapons/mine_stick.wav", VOL_BASE, ATTN_NORM);
-
-	// in order for mines to face properly when sticking to the ground, they must be a server side entity rather than a csqc projectile
-
-	entity newmine;
-	newmine = spawn();
-	newmine.classname = self.classname;
-
-	newmine.bot_dodge = self.bot_dodge;
-	newmine.bot_dodgerating = self.bot_dodgerating;
-
-	newmine.owner = self.owner;
-	newmine.realowner = self.realowner;
-	setsize(newmine, '-4 -4 -4', '4 4 4');
-	setorigin(newmine, self.origin);
-	setmodel(newmine, "models/mine.md3");
-	newmine.angles = vectoangles(-trace_plane_normal); // face against the surface
-
-	newmine.mine_orientation = -trace_plane_normal;
-
-	newmine.takedamage = self.takedamage;
-	newmine.damageforcescale = self.damageforcescale;
-	newmine.health = self.health;
-	newmine.event_damage = self.event_damage;
-	newmine.spawnshieldtime = self.spawnshieldtime;
-	newmine.damagedbycontents = TRUE;
-
-	newmine.movetype = MOVETYPE_NONE; // lock the mine in place
-	newmine.projectiledeathtype = self.projectiledeathtype;
-
-	newmine.mine_time = self.mine_time;
-
-	newmine.touch = func_null;
-	newmine.think = W_MineLayer_Think;
-	newmine.nextthink = time;
-	newmine.cnt = self.cnt;
-	newmine.flags = self.flags;
-
-	remove(self);
-	self = newmine;
-
-	if(to)
-		SetMovetypeFollow(self, to);
-}
-
-void W_MineLayer_Explode(void)
-{
-	if(other.takedamage == DAMAGE_AIM)
-		if(IS_PLAYER(other))
-			if(DIFF_TEAM(self.realowner, other))
-				if(other.deadflag == DEAD_NO)
-					if(IsFlying(other))
-						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	RadiusDamage(self, self.realowner, WEP_CVAR(minelayer, damage), WEP_CVAR(minelayer, edgedamage), WEP_CVAR(minelayer, radius), world, world, WEP_CVAR(minelayer, force), self.projectiledeathtype, other);
-
-	if(self.realowner.weapon == WEP_MINE_LAYER)
-	{
-		entity oldself;
-		oldself = self;
-		self = self.realowner;
-		if(!WEP_ACTION(WEP_MINE_LAYER, WR_CHECKAMMO1))
-		{
-			self.cnt = WEP_MINE_LAYER;
-			ATTACK_FINISHED(self) = time;
-			self.switchweapon = w_getbestweapon(self);
-		}
-		self = oldself;
-	}
-	self.realowner.minelayer_mines -= 1;
-	remove(self);
-}
-
-void W_MineLayer_DoRemoteExplode(void)
-{
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
-		self.velocity = self.mine_orientation; // particle fx and decals need .velocity
-
-	RadiusDamage(self, self.realowner, WEP_CVAR(minelayer, remote_damage), WEP_CVAR(minelayer, remote_edgedamage), WEP_CVAR(minelayer, remote_radius), world, world, WEP_CVAR(minelayer, remote_force), self.projectiledeathtype | HITTYPE_BOUNCE, world);
-
-	if(self.realowner.weapon == WEP_MINE_LAYER)
-	{
-		entity oldself;
-		oldself = self;
-		self = self.realowner;
-		if(!WEP_ACTION(WEP_MINE_LAYER, WR_CHECKAMMO1))
-		{
-			self.cnt = WEP_MINE_LAYER;
-			ATTACK_FINISHED(self) = time;
-			self.switchweapon = w_getbestweapon(self);
-		}
-		self = oldself;
-	}
-	self.realowner.minelayer_mines -= 1;
-	remove(self);
-}
-
-void W_MineLayer_RemoteExplode(void)
-{
-	if(self.realowner.deadflag == DEAD_NO)
-		if((self.spawnshieldtime >= 0)
-			? (time >= self.spawnshieldtime) // timer
-			: (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > WEP_CVAR(minelayer, remote_radius)) // safety device
-		)
-		{
-			W_MineLayer_DoRemoteExplode();
-		}
-}
-
-void W_MineLayer_ProximityExplode(void)
-{
-	// make sure no friend is in the mine's radius. If there is any, explosion is delayed until he's at a safe distance
-	if(WEP_CVAR(minelayer, protection) && self.mine_explodeanyway == 0)
-	{
-		entity head;
-		head = findradius(self.origin, WEP_CVAR(minelayer, radius));
-		while(head)
-		{
-			if(head == self.realowner || SAME_TEAM(head, self.realowner))
-				return;
-			head = head.chain;
-		}
-	}
-
-	self.mine_time = 0;
-	W_MineLayer_Explode();
-}
-
-float W_MineLayer_Count(entity e)
-{
-	float minecount = 0;
-	entity mine;
-	for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == e)
-		minecount += 1;
-
-	return minecount;
-}
-
-void W_MineLayer_Think(void)
-{
-	entity head;
-
-	self.nextthink = time;
-
-	if(self.movetype == MOVETYPE_FOLLOW)
-	{
-		if(LostMovetypeFollow(self))
-		{
-			UnsetMovetypeFollow(self);
-			self.movetype = MOVETYPE_NONE;
-		}
-	}
-	
-	// our lifetime has expired, it's time to die - mine_time just allows us to play a sound for this
-	// TODO: replace this mine_trigger.wav sound with a real countdown
-	if((time > self.cnt) && (!self.mine_time))
-	{
-		if(WEP_CVAR(minelayer, lifetime_countdown) > 0)
-			spamsound(self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTN_NORM);
-		self.mine_time = time + WEP_CVAR(minelayer, lifetime_countdown);
-		self.mine_explodeanyway = 1; // make the mine super aggressive -- Samual: Rather, make it not care if a team mate is near.
-	}
-
-	// a player's mines shall explode if he disconnects or dies
-	// TODO: Do this on team change too -- Samual: But isn't a player killed when they switch teams?
-	if(!IS_PLAYER(self.realowner) || self.realowner.deadflag != DEAD_NO || self.realowner.frozen)
-	{
-		other = world;
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		W_MineLayer_Explode();
-		return;
-	}
-
-	// set the mine for detonation when a foe gets close enough
-	head = findradius(self.origin, WEP_CVAR(minelayer, proximityradius));
-	while(head)
-	{
-		if(IS_PLAYER(head) && head.deadflag == DEAD_NO && !head.frozen)
-		if(head != self.realowner && DIFF_TEAM(head, self.realowner)) // don't trigger for team mates
-		if(!self.mine_time)
-		{
-			spamsound(self, CH_SHOTS, "weapons/mine_trigger.wav", VOL_BASE, ATTN_NORM);
-			self.mine_time = time + WEP_CVAR(minelayer, time);
-		}
-		head = head.chain;
-	}
-
-	// explode if it's time to
-	if(self.mine_time && time >= self.mine_time)
-	{
-		W_MineLayer_ProximityExplode();
-		return;
-	}
-
-	// remote detonation
-	if(self.realowner.weapon == WEP_MINE_LAYER)
-	if(self.realowner.deadflag == DEAD_NO)
-	if(self.minelayer_detonate)
-		W_MineLayer_RemoteExplode();
-}
-
-void W_MineLayer_Touch(void)
-{
-	if(self.movetype == MOVETYPE_NONE || self.movetype == MOVETYPE_FOLLOW)
-		return; // we're already a stuck mine, why do we get called? TODO does this even happen?
-
-	if(WarpZone_Projectile_Touch())
-	{
-		if(wasfreed(self))
-			self.realowner.minelayer_mines -= 1;
-		return;
-	}
-
-	if(other && IS_PLAYER(other) && other.deadflag == DEAD_NO)
-	{
-		// hit a player
-		// don't stick
-	}
-	else
-	{
-		W_MineLayer_Stick(other);
-	}
-}
-
-void W_MineLayer_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if(self.health <= 0)
-		return;
-		
-	float is_from_enemy = (inflictor.realowner != self.realowner);
-		
-	if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, (is_from_enemy ? 1 : -1)))
-		return; // g_projectiles_damage says to halt
-		
-	self.health = self.health - damage;
-	self.angles = vectoangles(self.velocity);
-	
-	if(self.health <= 0)
-		W_PrepareExplosionByDamage(attacker, W_MineLayer_Explode);
-}
-
-void W_MineLayer_Attack(void)
-{
-	entity mine;
-	entity flash;
-
-	// scan how many mines we placed, and return if we reached our limit
-	if(WEP_CVAR(minelayer, limit))
-	{
-		if(self.minelayer_mines >= WEP_CVAR(minelayer, limit))
-		{
-			// the refire delay keeps this message from being spammed
-			sprint(self, strcat("minelayer: You cannot place more than ^2", ftos(WEP_CVAR(minelayer, limit)), " ^7mines at a time\n") );
-			play2(self, "weapons/unavailable.wav");
-			return;
-		}
-	}
-
-	W_DecreaseAmmo(WEP_CVAR(minelayer, ammo));
-
-	W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 5, "weapons/mine_fire.wav", CH_WEAPON_A, WEP_CVAR(minelayer, damage));
-	pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	mine = WarpZone_RefSys_SpawnSameRefSys(self);
-	mine.owner = mine.realowner = self;
-	if(WEP_CVAR(minelayer, detonatedelay) >= 0)
-		mine.spawnshieldtime = time + WEP_CVAR(minelayer, detonatedelay);
-	else
-		mine.spawnshieldtime = -1;
-	mine.classname = "mine";
-	mine.bot_dodge = TRUE;
-	mine.bot_dodgerating = WEP_CVAR(minelayer, damage) * 2; // * 2 because it can detonate inflight which makes it even more dangerous
-
-	mine.takedamage = DAMAGE_YES;
-	mine.damageforcescale = WEP_CVAR(minelayer, damageforcescale);
-	mine.health = WEP_CVAR(minelayer, health);
-	mine.event_damage = W_MineLayer_Damage;
-	mine.damagedbycontents = TRUE;
-
-	mine.movetype = MOVETYPE_TOSS;
-	PROJECTILE_MAKETRIGGER(mine);
-	mine.projectiledeathtype = WEP_MINE_LAYER;
-	setsize(mine, '-4 -4 -4', '4 4 4'); // give it some size so it can be shot
-
-	setorigin(mine, w_shotorg - v_forward * 4); // move it back so it hits the wall at the right point
-	W_SetupProjVelocity_Basic(mine, WEP_CVAR(minelayer, speed), 0);
-	mine.angles = vectoangles(mine.velocity);
-
-	mine.touch = W_MineLayer_Touch;
-	mine.think = W_MineLayer_Think;
-	mine.nextthink = time;
-	mine.cnt = time + (WEP_CVAR(minelayer, lifetime) - WEP_CVAR(minelayer, lifetime_countdown));
-	mine.flags = FL_PROJECTILE;
-	mine.missile_flags = MIF_SPLASH | MIF_ARC | MIF_PROXY;
-
-	CSQCProjectile(mine, TRUE, PROJECTILE_MINE, TRUE);
-
-	// muzzle flash for 1st person view
-	flash = spawn();
-	setmodel(flash, "models/flash.md3"); // precision set below
-	SUB_SetFade(flash, time, 0.1);
-	flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-	W_AttachToShotorg(flash, '5 0 0');
-
-	// common properties
-
-	other = mine; MUTATOR_CALLHOOK(EditProjectile);
-	
-	self.minelayer_mines = W_MineLayer_Count(self);
-}
-
-float W_MineLayer_PlacedMines(float detonate)
-{
-	entity mine;
-	float minfound = 0;
-
-	for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.realowner == self)
-	{
-		if(detonate)
-		{
-			if(!mine.minelayer_detonate)
-			{
-				mine.minelayer_detonate = TRUE;
-				minfound = 1;
-			}
-		}
-		else
-			minfound = 1;
-	}
-	return minfound;
-}
-
-float W_MineLayer(float req)
-{
-	entity mine;
-	float ammo_amount;
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			// aim and decide to fire if appropriate
-			if(self.minelayer_mines >= WEP_CVAR(minelayer, limit))
-				self.BUTTON_ATCK = FALSE;
-			else
-				self.BUTTON_ATCK = bot_aim(WEP_CVAR(minelayer, speed), 0, WEP_CVAR(minelayer, lifetime), FALSE);
-			if(skill >= 2) // skill 0 and 1 bots won't detonate mines!
-			{
-				// decide whether to detonate mines
-				entity targetlist, targ;
-				float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
-				float selfdamage, teamdamage, enemydamage;
-				edgedamage = WEP_CVAR(minelayer, edgedamage);
-				coredamage = WEP_CVAR(minelayer, damage);
-				edgeradius = WEP_CVAR(minelayer, radius);
-				recipricoledgeradius = 1 / edgeradius;
-				selfdamage = 0;
-				teamdamage = 0;
-				enemydamage = 0;
-				targetlist = findchainfloat(bot_attack, TRUE);
-				mine = find(world, classname, "mine");
-				while(mine)
-				{
-					if(mine.realowner != self)
-					{
-						mine = find(mine, classname, "mine");
-						continue;
-					}
-					targ = targetlist;
-					while(targ)
-					{
-						d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - mine.origin);
-						d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
-						// count potential damage according to type of target
-						if(targ == self)
-							selfdamage = selfdamage + d;
-						else if(targ.team == self.team && teamplay)
-							teamdamage = teamdamage + d;
-						else if(bot_shouldattack(targ))
-							enemydamage = enemydamage + d;
-						targ = targ.chain;
-					}
-					mine = find(mine, classname, "mine");
-				}
-				float desirabledamage;
-				desirabledamage = enemydamage;
-				if(time > self.invincible_finished && time > self.spawnshieldtime)
-					desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
-				if(teamplay && self.team)
-					desirabledamage = desirabledamage - teamdamage;
-
-				mine = find(world, classname, "mine");
-				while(mine)
-				{
-					if(mine.realowner != self)
-					{
-						mine = find(mine, classname, "mine");
-						continue;
-					}
-					makevectors(mine.v_angle);
-					targ = targetlist;
-					if(skill > 9) // normal players only do this for the target they are tracking
-					{
-						targ = targetlist;
-						while(targ)
-						{
-							if(
-								(v_forward * normalize(mine.origin - targ.origin)< 0.1)
-								&& desirabledamage > 0.1*coredamage
-							)self.BUTTON_ATCK2 = TRUE;
-							targ = targ.chain;
-						}
-					}else{
-						float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
-						//As the distance gets larger, a correct detonation gets near imposible
-						//Bots are assumed to use the mine spawnfunc_light to see if the mine gets near a player
-						if(v_forward * normalize(mine.origin - self.enemy.origin)< 0.1)
-							if(IS_PLAYER(self.enemy))
-								if(desirabledamage >= 0.1*coredamage)
-									if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1))
-										self.BUTTON_ATCK2 = TRUE;
-					//	dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n");
-					}
-
-					mine = find(mine, classname, "mine");
-				}
-				// if we would be doing at X percent of the core damage, detonate it
-				// but don't fire a new shot at the same time!
-				if(desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events
-					self.BUTTON_ATCK2 = TRUE;
-				if((skill > 6.5) && (selfdamage > self.health))
-					self.BUTTON_ATCK2 = FALSE;
-				//if(self.BUTTON_ATCK2 == TRUE)
-				//	dprint(ftos(desirabledamage),"\n");
-				if(self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE;
-			}
-			
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(autocvar_g_balance_minelayer_reload_ammo && self.clip_load < WEP_CVAR(minelayer, ammo)) // forced reload
-			{
-				// not if we're holding the minelayer without enough ammo, but can detonate existing mines
-				if(!(W_MineLayer_PlacedMines(FALSE) && self.WEP_AMMO(MINE_LAYER) < WEP_CVAR(minelayer, ammo)))
-					WEP_ACTION(self.weapon, WR_RELOAD);
-			}
-			else if(self.BUTTON_ATCK)
-			{
-				if(weapon_prepareattack(0, WEP_CVAR(minelayer, refire)))
-				{
-					W_MineLayer_Attack();
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(minelayer, animtime), w_ready);
-				}
-			}
-
-			if(self.BUTTON_ATCK2)
-			{
-				if(W_MineLayer_PlacedMines(TRUE))
-					sound(self, CH_WEAPON_B, "weapons/mine_det.wav", VOL_BASE, ATTN_NORM);
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/flash.md3");
-			precache_model("models/mine.md3");
-			precache_model("models/weapons/g_minelayer.md3");
-			precache_model("models/weapons/v_minelayer.md3");
-			precache_model("models/weapons/h_minelayer.iqm");
-			precache_sound("weapons/mine_det.wav");
-			precache_sound("weapons/mine_fire.wav");
-			precache_sound("weapons/mine_stick.wav");
-			precache_sound("weapons/mine_trigger.wav");
-			MINELAYER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			// don't switch while placing a mine
-			if(ATTACK_FINISHED(self) <= time || self.weapon != WEP_MINE_LAYER)
-			{
-				ammo_amount = self.WEP_AMMO(MINE_LAYER) >= WEP_CVAR(minelayer, ammo);
-				ammo_amount += self.(weapon_load[WEP_MINE_LAYER]) >= WEP_CVAR(minelayer, ammo);
-				return ammo_amount;
-			}
-			return TRUE;
-		}
-		case WR_CHECKAMMO2:
-		{
-			if(W_MineLayer_PlacedMines(FALSE))
-				return TRUE;
-			else
-				return FALSE;
-		}
-		case WR_CONFIG:
-		{
-			MINELAYER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RESETPLAYER:
-		{
-			self.minelayer_mines = 0;
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(WEP_CVAR(minelayer, ammo), "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_MINELAYER_SUICIDE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			return WEAPON_MINELAYER_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_MineLayer(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 12;
-			pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
-			if(!w_issilent)
-				sound(self, CH_SHOTS, "weapons/mine_exp.wav", VOL_BASE, ATTN_NORM);
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/mine_exp.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_mortar.qc b/qcsrc/common/weapons/w_mortar.qc
deleted file mode 100644
index de40fcb39..000000000
--- a/qcsrc/common/weapons/w_mortar.qc
+++ /dev/null
@@ -1,490 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ MORTAR,
-/* function  */ W_Mortar,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 4,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '1 0 0',
-/* modelname */ "gl",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairgrenadelauncher 0.7",
-/* wepimg    */ "weapongrenadelauncher",
-/* refname   */ "mortar",
-/* wepname   */ _("Mortar")
-);
-
-#define MORTAR_SETTINGS(w_cvar,w_prop) MORTAR_SETTINGS_LIST(w_cvar, w_prop, MORTAR, mortar)
-#define MORTAR_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, ammo) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, NONE, bouncefactor) \
-	w_cvar(id, sn, NONE, bouncestop) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, damageforcescale) \
-	w_cvar(id, sn, BOTH, edgedamage) \
-	w_cvar(id, sn, BOTH, force) \
-	w_cvar(id, sn, BOTH, health) \
-	w_cvar(id, sn, BOTH, lifetime) \
-	w_cvar(id, sn, SEC,  lifetime_bounce) \
-	w_cvar(id, sn, BOTH, lifetime_stick) \
-	w_cvar(id, sn, BOTH, radius) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, SEC,  remote_detonateprimary) \
-	w_cvar(id, sn, PRI,  remote_minbouncecnt) \
-	w_cvar(id, sn, BOTH, speed) \
-	w_cvar(id, sn, BOTH, speed_up) \
-	w_cvar(id, sn, BOTH, speed_z) \
-	w_cvar(id, sn, BOTH, spread) \
-	w_cvar(id, sn, BOTH, type) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-MORTAR_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.float gl_detonate_later;
-.float gl_bouncecnt;
-#endif
-#else
-#ifdef SVQC
-
-void spawnfunc_weapon_mortar(void) { weapon_defaultspawnfunc(WEP_MORTAR); }
-void spawnfunc_weapon_grenadelauncher(void) { spawnfunc_weapon_mortar(); }
-
-void W_Mortar_Grenade_Explode(void)
-{
-	if(other.takedamage == DAMAGE_AIM)
-		if(IS_PLAYER(other))
-			if(DIFF_TEAM(self.realowner, other))
-				if(other.deadflag == DEAD_NO)
-					if(IsFlying(other))
-						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	if(self.movetype == MOVETYPE_NONE)
-		self.velocity = self.oldvelocity;
-
-	RadiusDamage(self, self.realowner, WEP_CVAR_PRI(mortar, damage), WEP_CVAR_PRI(mortar, edgedamage), WEP_CVAR_PRI(mortar, radius), world, world, WEP_CVAR_PRI(mortar, force), self.projectiledeathtype, other);
-
-	remove(self);
-}
-
-void W_Mortar_Grenade_Explode2(void)
-{
-	if(other.takedamage == DAMAGE_AIM)
-		if(IS_PLAYER(other))
-			if(DIFF_TEAM(self.realowner, other))
-				if(other.deadflag == DEAD_NO)
-					if(IsFlying(other))
-						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
-
-	self.event_damage = func_null;
-	self.takedamage = DAMAGE_NO;
-
-	if(self.movetype == MOVETYPE_NONE)
-		self.velocity = self.oldvelocity;
-
-	RadiusDamage(self, self.realowner, WEP_CVAR_SEC(mortar, damage), WEP_CVAR_SEC(mortar, edgedamage), WEP_CVAR_SEC(mortar, radius), world, world, WEP_CVAR_SEC(mortar, force), self.projectiledeathtype, other);
-
-	remove(self);
-}
-
-
-void W_Mortar_Grenade_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if(self.health <= 0)
-		return;
-		
-	if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
-		return; // g_projectiles_damage says to halt
-		
-	self.health = self.health - damage;
-	
-	if(self.health <= 0)
-		W_PrepareExplosionByDamage(attacker, self.use);
-}
-
-void W_Mortar_Grenade_Think1(void)
-{
-	self.nextthink = time;
-	if(time > self.cnt)
-	{
-		other = world;
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		W_Mortar_Grenade_Explode();
-		return;
-	}
-	if(self.gl_detonate_later && self.gl_bouncecnt >= WEP_CVAR_PRI(mortar, remote_minbouncecnt))
-		W_Mortar_Grenade_Explode();
-}
-
-void W_Mortar_Grenade_Touch1(void)
-{
-	PROJECTILE_TOUCH;
-	if(other.takedamage == DAMAGE_AIM || WEP_CVAR_PRI(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
-	{
-		self.use();
-	}
-	else if(WEP_CVAR_PRI(mortar, type) == 1) // bounce
-	{
-		float r;
-		r = random() * 6;
-		if(r < 1)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM);
-		else if(r < 2)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM);
-		else if(r < 3)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM);
-		else if(r < 4)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM);
-		else if(r < 5)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
-		else
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
-		pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1);
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		self.gl_bouncecnt += 1;
-	}
-	else if(WEP_CVAR_PRI(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
-	{
-		spamsound(self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM);
-
-		// let it stick whereever it is
-		self.oldvelocity = self.velocity;
-		self.velocity = '0 0 0';
-		self.movetype = MOVETYPE_NONE; // also disables gravity
-		self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
-		UpdateCSQCProjectile(self);
-
-		// do not respond to any more touches
-		self.solid = SOLID_NOT;
-
-		self.nextthink = min(self.nextthink, time + WEP_CVAR_PRI(mortar, lifetime_stick));
-	}
-}
-
-void W_Mortar_Grenade_Touch2(void)
-{
-	PROJECTILE_TOUCH;
-	if(other.takedamage == DAMAGE_AIM || WEP_CVAR_SEC(mortar, type) == 0) // always explode when hitting a player, or if normal mortar projectile
-	{
-		self.use();
-	}
-	else if(WEP_CVAR_SEC(mortar, type) == 1) // bounce
-	{
-		float r;
-		r = random() * 6;
-		if(r < 1)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTN_NORM);
-		else if(r < 2)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTN_NORM);
-		else if(r < 3)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTN_NORM);
-		else if(r < 4)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTN_NORM);
-		else if(r < 5)
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTN_NORM);
-		else
-			spamsound(self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTN_NORM);
-		pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1);
-		self.projectiledeathtype |= HITTYPE_BOUNCE;
-		self.gl_bouncecnt += 1;
-		
-		if(WEP_CVAR_SEC(mortar, lifetime_bounce) && self.gl_bouncecnt == 1)
-			self.nextthink = time + WEP_CVAR_SEC(mortar, lifetime_bounce);
-			
-	}
-	else if(WEP_CVAR_SEC(mortar, type) == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
-	{
-		spamsound(self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTN_NORM);
-
-		// let it stick whereever it is
-		self.oldvelocity = self.velocity;
-		self.velocity = '0 0 0';
-		self.movetype = MOVETYPE_NONE; // also disables gravity
-		self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
-		UpdateCSQCProjectile(self);
-
-		// do not respond to any more touches
-		self.solid = SOLID_NOT;
-
-		self.nextthink = min(self.nextthink, time + WEP_CVAR_SEC(mortar, lifetime_stick));
-	}
-}
-
-void W_Mortar_Attack(void)
-{
-	entity gren;
-
-	W_DecreaseAmmo(WEP_CVAR_PRI(mortar, ammo));
-
-	W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(mortar, damage));
-	w_shotdir = v_forward; // no TrueAim for grenades please
-
-	pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	gren = spawn();
-	gren.owner = gren.realowner = self;
-	gren.classname = "grenade";
-	gren.bot_dodge = TRUE;
-	gren.bot_dodgerating = WEP_CVAR_PRI(mortar, damage);
-	gren.movetype = MOVETYPE_BOUNCE;
-	gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
-	gren.bouncestop = WEP_CVAR(mortar, bouncestop);
-	PROJECTILE_MAKETRIGGER(gren);
-	gren.projectiledeathtype = WEP_MORTAR;
-	setorigin(gren, w_shotorg);
-	setsize(gren, '-3 -3 -3', '3 3 3');
-
-	gren.cnt = time + WEP_CVAR_PRI(mortar, lifetime);
-	gren.nextthink = time;
-	gren.think = W_Mortar_Grenade_Think1;
-	gren.use = W_Mortar_Grenade_Explode;
-	gren.touch = W_Mortar_Grenade_Touch1;
-
-	gren.takedamage = DAMAGE_YES;
-	gren.health = WEP_CVAR_PRI(mortar, health);
-	gren.damageforcescale = WEP_CVAR_PRI(mortar, damageforcescale);
-	gren.event_damage = W_Mortar_Grenade_Damage;
-	gren.damagedbycontents = TRUE;
-	gren.missile_flags = MIF_SPLASH | MIF_ARC;
-	W_SetupProjVelocity_UP_PRI(gren, mortar);
-
-	gren.angles = vectoangles(gren.velocity);
-	gren.flags = FL_PROJECTILE;
-
-	if(WEP_CVAR_PRI(mortar, type) == 0 || WEP_CVAR_PRI(mortar, type) == 2)
-		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
-	else
-		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
-
-	other = gren; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-void W_Mortar_Attack2(void)
-{
-	entity gren;
-
-	W_DecreaseAmmo(WEP_CVAR_SEC(mortar, ammo));
-
-	W_SetupShot_ProjectileSize(self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, WEP_CVAR_SEC(mortar, damage));
-	w_shotdir = v_forward; // no TrueAim for grenades please
-
-	pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	gren = spawn();
-	gren.owner = gren.realowner = self;
-	gren.classname = "grenade";
-	gren.bot_dodge = TRUE;
-	gren.bot_dodgerating = WEP_CVAR_SEC(mortar, damage);
-	gren.movetype = MOVETYPE_BOUNCE;
-	gren.bouncefactor = WEP_CVAR(mortar, bouncefactor);
-	gren.bouncestop = WEP_CVAR(mortar, bouncestop);
-	PROJECTILE_MAKETRIGGER(gren);
-	gren.projectiledeathtype = WEP_MORTAR | HITTYPE_SECONDARY;
-	setorigin(gren, w_shotorg);
-	setsize(gren, '-3 -3 -3', '3 3 3');
-
-	gren.nextthink = time + WEP_CVAR_SEC(mortar, lifetime);
-	gren.think = adaptor_think2use_hittype_splash;
-	gren.use = W_Mortar_Grenade_Explode2;
-	gren.touch = W_Mortar_Grenade_Touch2;
-
-	gren.takedamage = DAMAGE_YES;
-	gren.health = WEP_CVAR_SEC(mortar, health);
-	gren.damageforcescale = WEP_CVAR_SEC(mortar, damageforcescale);
-	gren.event_damage = W_Mortar_Grenade_Damage;
-	gren.damagedbycontents = TRUE;
-	gren.missile_flags = MIF_SPLASH | MIF_ARC;
-	W_SetupProjVelocity_UP_SEC(gren, mortar);
-
-	gren.angles = vectoangles(gren.velocity);
-	gren.flags = FL_PROJECTILE;
-
-	if(WEP_CVAR_SEC(mortar, type) == 0 || WEP_CVAR_SEC(mortar, type) == 2)
-		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
-	else
-		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
-
-	other = gren; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-.float bot_secondary_grenademooth;
-float W_Mortar(float req)
-{
-	entity nade;
-	float nadefound;
-	float ammo_amount;
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			self.BUTTON_ATCK = FALSE;
-			self.BUTTON_ATCK2 = FALSE;
-			if(self.bot_secondary_grenademooth == 0) // WEAPONTODO: merge this into using WEP_CVAR_BOTH
-			{
-				if(bot_aim(WEP_CVAR_PRI(mortar, speed), WEP_CVAR_PRI(mortar, speed_up), WEP_CVAR_PRI(mortar, lifetime), TRUE))
-				{
-					self.BUTTON_ATCK = TRUE;
-					if(random() < 0.01) self.bot_secondary_grenademooth = 1;
-				}
-			}
-			else
-			{
-				if(bot_aim(WEP_CVAR_SEC(mortar, speed), WEP_CVAR_SEC(mortar, speed_up), WEP_CVAR_SEC(mortar, lifetime), TRUE))
-				{
-					self.BUTTON_ATCK2 = TRUE;
-					if(random() < 0.02) self.bot_secondary_grenademooth = 0;
-				}
-			}
-			
-			return TRUE;
-		}
-		/*case WR_CALCINFO:
-		{
-			wepinfo_pri_refire = max3(sys_frametime, WEP_CVAR_PRI(mortar, refire), WEP_CVAR_PRI(mortar, animtime));
-			wepinfo_pri_dps = (WEP_CVAR_PRI(mortar, damage) * (1 / wepinfo_pri_refire));
-			wepinfo_pri_speed = (1 / max(1, (10000 / max(1, WEP_CVAR_PRI(mortar, speed)))));
-
-			// for the range calculation, closer to 1 is better
-			wepinfo_pri_range_max = 2000 * wepinfo_pri_speed;
-			wepinfo_pri_range = wepinfo_pri_speed * WEP_CVAR_PRI(mortar, 
-			
-			wepinfo_sec_refire = max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime));
-			wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / wepinfo_sec_refire));
-			
-			wepinfo_sec_dps = (WEP_CVAR_SEC(mortar, damage) * (1 / max3(sys_frametime, WEP_CVAR_SEC(mortar, refire), WEP_CVAR_SEC(mortar, animtime))));
-			wepinfo_ter_dps = 0;
-			*/
-		case WR_THINK:
-		{
-			if(autocvar_g_balance_mortar_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo))) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-			else if(self.BUTTON_ATCK)
-			{
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(mortar, refire)))
-				{
-					W_Mortar_Attack();
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(mortar, animtime), w_ready);
-				}
-			}
-			else if(self.BUTTON_ATCK2)
-			{
-				if(WEP_CVAR_SEC(mortar, remote_detonateprimary))
-				{
-					nadefound = 0;
-					for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self)
-					{
-						if(!nade.gl_detonate_later)
-						{
-							nade.gl_detonate_later = TRUE;
-							nadefound = 1;
-						}
-					}
-					if(nadefound)
-						sound(self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTN_NORM);
-				}
-				else if(weapon_prepareattack(1, WEP_CVAR_SEC(mortar, refire)))
-				{
-					W_Mortar_Attack2();
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(mortar, animtime), w_ready);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_gl.md3");
-			precache_model("models/weapons/v_gl.md3");
-			precache_model("models/weapons/h_gl.iqm");
-			precache_sound("weapons/grenade_bounce1.wav");
-			precache_sound("weapons/grenade_bounce2.wav");
-			precache_sound("weapons/grenade_bounce3.wav");
-			precache_sound("weapons/grenade_bounce4.wav");
-			precache_sound("weapons/grenade_bounce5.wav");
-			precache_sound("weapons/grenade_bounce6.wav");
-			precache_sound("weapons/grenade_stick.wav");
-			precache_sound("weapons/grenade_fire.wav");
-			MORTAR_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_PRI(mortar, ammo);
-			ammo_amount += self.(weapon_load[WEP_MORTAR]) >= WEP_CVAR_PRI(mortar, ammo);
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			ammo_amount = self.WEP_AMMO(MORTAR) >= WEP_CVAR_SEC(mortar, ammo);
-			ammo_amount += self.(weapon_load[WEP_MORTAR]) >= WEP_CVAR_SEC(mortar, ammo);
-			return ammo_amount;
-		}
-		case WR_CONFIG:
-		{
-			MORTAR_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(min(WEP_CVAR_PRI(mortar, ammo), WEP_CVAR_SEC(mortar, ammo)), "weapons/reload.wav"); // WEAPONTODO
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_MORTAR_SUICIDE_BOUNCE;
-			else
-				return WEAPON_MORTAR_SUICIDE_EXPLODE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_MORTAR_MURDER_BOUNCE;
-			else
-				return WEAPON_MORTAR_MURDER_EXPLODE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Mortar(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 12;
-			pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1);
-			if(!w_issilent)
-				sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTN_NORM);
-				
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/grenade_impact.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_porto.qc b/qcsrc/common/weapons/w_porto.qc
deleted file mode 100644
index 49fb47e43..000000000
--- a/qcsrc/common/weapons/w_porto.qc
+++ /dev/null
@@ -1,422 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ PORTO,
-/* function  */ W_Porto,
-/* ammotype  */ ammo_none,
-/* impulse   */ 0,
-/* flags     */ WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON,
-/* rating    */ 0,
-/* color     */ '0.5 0.5 0.5',
-/* modelname */ "porto",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairporto 0.6",
-/* wepimg    */ "weaponporto",
-/* refname   */ "porto",
-/* wepname   */ _("Port-O-Launch")
-);
-
-#define PORTO_SETTINGS(w_cvar,w_prop) PORTO_SETTINGS_LIST(w_cvar, w_prop, PORTO, porto)
-#define PORTO_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, lifetime) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, BOTH, speed) \
-	w_cvar(id, sn, NONE, secondary) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-PORTO_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.entity porto_current;
-.vector porto_v_angle; // holds "held" view angles
-.float porto_v_angle_held;
-.vector right_vector;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_porto(void) { weapon_defaultspawnfunc(WEP_PORTO); }
-
-void W_Porto_Success(void)
-{
-	if(self.realowner == world)
-	{
-		objerror("Cannot succeed successfully: no owner\n");
-		return;
-	}
-
-	self.realowner.porto_current = world;
-	remove(self);
-}
-
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
-void W_Porto_Fail(float failhard)
-{
-	if(self.realowner == world)
-	{
-		objerror("Cannot fail successfully: no owner\n");
-		return;
-	}
-
-	// no portals here!
-	if(self.cnt < 0)
-	{
-		Portal_ClearWithID(self.realowner, self.portal_id);
-	}
-
-	self.realowner.porto_current = world;
-
-	if(self.cnt < 0 && !failhard && self.realowner.playerid == self.playerid && self.realowner.deadflag == DEAD_NO && !(self.realowner.weapons & WEPSET_PORTO))
-	{
-		setsize(self, '-16 -16 0', '16 16 32');
-		setorigin(self, self.origin + trace_plane_normal);
-		if(move_out_of_solid(self))
-		{
-			self.flags = FL_ITEM;
-			self.velocity = trigger_push_calculatevelocity(self.origin, self.realowner, 128);
-			tracetoss(self, self);
-			if(vlen(trace_endpos - self.realowner.origin) < 128)
-			{
-				W_ThrowNewWeapon(self.realowner, WEP_PORTO, 0, self.origin, self.velocity);
-				centerprint(self.realowner, "^1Portal deployment failed.\n\n^2Catch it to try again!");
-			}
-		}
-	}
-	remove(self);
-}
-
-void W_Porto_Remove(entity p)
-{
-	if(p.porto_current.realowner == p && p.porto_current.classname == "porto")
-	{
-		entity oldself;
-		oldself = self;
-		self = p.porto_current;
-		W_Porto_Fail(1);
-		self = oldself;
-	}
-}
-
-void W_Porto_Think(void)
-{
-	trace_plane_normal = '0 0 0';
-	if(self.realowner.playerid != self.playerid)
-		remove(self);
-	else
-		W_Porto_Fail(0);
-}
-
-void W_Porto_Touch(void)
-{
-	vector norm;
-
-	// do not use PROJECTILE_TOUCH here
-	// FIXME but DO handle warpzones!
-
-	if(other.classname == "portal")
-		return; // handled by the portal
-
-	norm = trace_plane_normal;
-	if(trace_ent.iscreature)
-	{
-		traceline(trace_ent.origin, trace_ent.origin + '0 0 2' * PL_MIN_z, MOVE_WORLDONLY, self);
-		if(trace_fraction >= 1)
-			return;
-		if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
-			return;
-		if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-			return;
-	}
-
-	if(self.realowner.playerid != self.playerid)
-	{
-		sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
-		remove(self);
-	}
-	else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
-	{
-		spamsound(self, CH_SHOTS, "porto/bounce.wav", VOL_BASE, ATTEN_NORM);
-		// just reflect
-		self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * trace_plane_normal);
-		self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * trace_plane_normal));
-	}
-	else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-	{
-		sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
-		W_Porto_Fail(0);
-		if(self.cnt < 0)
-			Portal_ClearAll_PortalsOnly(self.realowner);
-	}
-	else if(self.cnt == 0)
-	{
-		// in-portal only
-		if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
-		{
-			sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
-			trace_plane_normal = norm;
-			centerprint(self.realowner, "^1In^7-portal created.");
-			W_Porto_Success();
-		}
-		else
-		{
-			sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
-			trace_plane_normal = norm;
-			W_Porto_Fail(0);
-		}
-	}
-	else if(self.cnt == 1)
-	{
-		// out-portal only
-		if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
-		{
-			sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
-			trace_plane_normal = norm;
-			centerprint(self.realowner, "^4Out^7-portal created.");
-			W_Porto_Success();
-		}
-		else
-		{
-			sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
-			trace_plane_normal = norm;
-			W_Porto_Fail(0);
-		}
-	}
-	else if(self.effects & EF_RED)
-	{
-		self.effects += EF_BLUE - EF_RED;
-		if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
-		{
-			sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
-			trace_plane_normal = norm;
-			centerprint(self.realowner, "^1In^7-portal created.");
-			self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * norm);
-			self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * norm));
-			CSQCProjectile(self, TRUE, PROJECTILE_PORTO_BLUE, TRUE); // change type
-		}
-		else
-		{
-			sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
-			trace_plane_normal = norm;
-			Portal_ClearAll_PortalsOnly(self.realowner);
-			W_Porto_Fail(0);
-		}
-	}
-	else
-	{
-		if(self.realowner.portal_in.portal_id == self.portal_id)
-		{
-			if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
-			{
-				sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
-				trace_plane_normal = norm;
-				centerprint(self.realowner, "^4Out^7-portal created.");
-				W_Porto_Success();
-			}
-			else
-			{
-				sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
-				Portal_ClearAll_PortalsOnly(self.realowner);
-				W_Porto_Fail(0);
-			}
-		}
-		else
-		{
-			sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
-			Portal_ClearAll_PortalsOnly(self.realowner);
-			W_Porto_Fail(0);
-		}
-	}
-}
-
-void W_Porto_Attack(float type)
-{
-	entity gren;
-
-	W_SetupShot(self, FALSE, 4, "porto/fire.wav", CH_WEAPON_A, 0);
-	// always shoot from the eye
-	w_shotdir = v_forward;
-	w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
-
-	//pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	gren = spawn();
-	gren.cnt = type;
-	gren.owner = gren.realowner = self;
-	gren.playerid = self.playerid;
-	gren.classname = "porto";
-	gren.bot_dodge = TRUE;
-	gren.bot_dodgerating = 200;
-	gren.movetype = MOVETYPE_BOUNCEMISSILE;
-	PROJECTILE_MAKETRIGGER(gren);
-	gren.effects = EF_RED;
-	gren.scale = 4;
-	setorigin(gren, w_shotorg);
-	setsize(gren, '0 0 0', '0 0 0');
-	
-	gren.nextthink = time + WEP_CVAR_BOTH(porto, (type <= 0), lifetime);
-	gren.think = W_Porto_Think;
-	gren.touch = W_Porto_Touch;
-	
-	if(self.items & IT_STRENGTH)
-		W_SetupProjVelocity_Basic(gren, WEP_CVAR_BOTH(porto, (type <= 0), speed) * autocvar_g_balance_powerup_strength_force, 0);
-	else
-		W_SetupProjVelocity_Basic(gren, WEP_CVAR_BOTH(porto, (type <= 0), speed), 0);
-
-	gren.angles = vectoangles(gren.velocity);
-	gren.flags = FL_PROJECTILE;
-
-	gren.portal_id = time;
-	self.porto_current = gren;
-	gren.playerid = self.playerid;
-	fixedmakevectors(fixedvectoangles(gren.velocity));
-	gren.right_vector = v_right;
-
-	gren.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
-
-	if(type > 0)
-		CSQCProjectile(gren, TRUE, PROJECTILE_PORTO_BLUE, TRUE);
-	else
-		CSQCProjectile(gren, TRUE, PROJECTILE_PORTO_RED, TRUE);
-
-	other = gren; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-float w_nexball_weapon(float req); // WEAPONTODO
-float W_Porto(float req)
-{
-	//vector v_angle_save;
-
-	if(g_nexball) { return w_nexball_weapon(req); }
-	
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			self.BUTTON_ATCK = FALSE;
-			self.BUTTON_ATCK2 = FALSE;
-			if(!WEP_CVAR(porto, secondary))
-				if(bot_aim(WEP_CVAR_PRI(porto, speed), 0, WEP_CVAR_PRI(porto, lifetime), FALSE))
-					self.BUTTON_ATCK = TRUE;
-					
-			return TRUE;
-		}
-		case WR_CONFIG:
-		{
-			PORTO_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(WEP_CVAR(porto, secondary))
-			{
-				if(self.BUTTON_ATCK)
-				if(!self.porto_current)
-				if(!self.porto_forbidden)
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(porto, refire)))
-				{
-					W_Porto_Attack(0);
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
-				}
-
-				if(self.BUTTON_ATCK2)
-				if(!self.porto_current)
-				if(!self.porto_forbidden)
-				if(weapon_prepareattack(1, WEP_CVAR_SEC(porto, refire)))
-				{
-					W_Porto_Attack(1);
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(porto, animtime), w_ready);
-				}
-			}
-			else
-			{
-				if(self.porto_v_angle_held)
-				{
-					if(!self.BUTTON_ATCK2)
-					{
-						self.porto_v_angle_held = 0;
-
-						ClientData_Touch(self);
-					}
-				}
-				else
-				{
-					if(self.BUTTON_ATCK2)
-					{
-						self.porto_v_angle = self.v_angle;
-						self.porto_v_angle_held = 1;
-
-						ClientData_Touch(self);
-					}
-				}
-				if(self.porto_v_angle_held)
-					makevectors(self.porto_v_angle); // override the previously set angles
-
-				if(self.BUTTON_ATCK)
-				if(!self.porto_current)
-				if(!self.porto_forbidden)
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(porto, refire)))
-				{
-					W_Porto_Attack(-1);
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(porto, animtime), w_ready);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_porto.md3");
-			precache_model("models/weapons/v_porto.md3");
-			precache_model("models/weapons/h_porto.iqm");
-			precache_model("models/portal.md3");
-			precache_sound("porto/bounce.wav");
-			precache_sound("porto/create.wav");
-			precache_sound("porto/expire.wav");
-			precache_sound("porto/explode.wav");
-			precache_sound("porto/fire.wav");
-			precache_sound("porto/unsupported.wav");
-			PORTO_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_SETUP:
-		{
-			self.ammo_field = ammo_none;
-			return TRUE;
-		}
-		case WR_RESETPLAYER:
-		{
-			self.porto_current = world;
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Porto(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			print("Since when does Porto send DamageInfo?\n");
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			// nothing to do
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_rifle.qc b/qcsrc/common/weapons/w_rifle.qc
deleted file mode 100644
index 03c396ceb..000000000
--- a/qcsrc/common/weapons/w_rifle.qc
+++ /dev/null
@@ -1,316 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ RIFLE,
-/* function  */ W_Rifle,
-/* ammotype  */ ammo_nails,
-/* impulse   */ 7,
-/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0.5 1 0',
-/* modelname */ "campingrifle",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairrifle 0.5",
-/* wepimg    */ "weaponrifle",
-/* refname   */ "rifle",
-/* wepname   */ _("Rifle")
-);
-
-#define RIFLE_SETTINGS(w_cvar,w_prop) RIFLE_SETTINGS_LIST(w_cvar, w_prop, RIFLE, rifle)
-#define RIFLE_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, ammo) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, bullethail) \
-	w_cvar(id, sn, BOTH, burstcost) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, force) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, BOTH, shots) \
-	w_cvar(id, sn, BOTH, solidpenetration) \
-	w_cvar(id, sn, BOTH, spread) \
-	w_cvar(id, sn, BOTH, tracer) \
-	w_cvar(id, sn, NONE, bursttime) \
-	w_cvar(id, sn, NONE, secondary) \
-	w_cvar(id, sn, SEC,  reload) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-RIFLE_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.float rifle_accumulator;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_rifle(void) { weapon_defaultspawnfunc(WEP_RIFLE); }
-void spawnfunc_weapon_campingrifle(void) { spawnfunc_weapon_rifle(); }
-void spawnfunc_weapon_sniperrifle(void) { spawnfunc_weapon_rifle(); }
-
-void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, float deathtype, float pTracer, float pShots, string pSound)
-{
-	float i;
-
-	W_DecreaseAmmo(pAmmo);
-
-	W_SetupShot(self, TRUE, 2, pSound, CH_WEAPON_A, pDamage * pShots);
-
-	pointparticles(particleeffectnum("rifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
-
-	if(self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) // if zoomed, shoot from the eye
-	{
-		w_shotdir = v_forward;
-		w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
-	}
-
-	for(i = 0; i < pShots; ++i)
-		fireBullet(w_shotorg, w_shotdir, pSpread, pSolidPenetration, pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE));
-
-	if(autocvar_g_casings >= 2)
-		SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
-}
-
-void W_Rifle_Attack(void)
-{
-	W_Rifle_FireBullet(WEP_CVAR_PRI(rifle, spread), WEP_CVAR_PRI(rifle, damage), WEP_CVAR_PRI(rifle, force), WEP_CVAR_PRI(rifle, solidpenetration), WEP_CVAR_PRI(rifle, ammo), WEP_RIFLE, WEP_CVAR_PRI(rifle, tracer), WEP_CVAR_PRI(rifle, shots), "weapons/campingrifle_fire.wav");
-}
-
-void W_Rifle_Attack2(void)
-{
-	W_Rifle_FireBullet(WEP_CVAR_SEC(rifle, spread), WEP_CVAR_SEC(rifle, damage), WEP_CVAR_SEC(rifle, force), WEP_CVAR_SEC(rifle, solidpenetration), WEP_CVAR_SEC(rifle, ammo), WEP_RIFLE | HITTYPE_SECONDARY, WEP_CVAR_SEC(rifle, tracer), WEP_CVAR_SEC(rifle, shots), "weapons/campingrifle_fire2.wav");
-}
-
-.void(void) rifle_bullethail_attackfunc;
-.float rifle_bullethail_frame;
-.float rifle_bullethail_animtime;
-.float rifle_bullethail_refire;
-void W_Rifle_BulletHail_Continue(void)
-{
-	float r, sw, af;
-
-	sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing
-	af = ATTACK_FINISHED(self);
-	self.switchweapon = self.weapon;
-	ATTACK_FINISHED(self) = time;
-	print(ftos(self.WEP_AMMO(RIFLE)), "\n");
-	r = weapon_prepareattack(self.rifle_bullethail_frame == WFRAME_FIRE2, self.rifle_bullethail_refire);
-	if(self.switchweapon == self.weapon)
-		self.switchweapon = sw;
-	if(r)
-	{
-		self.rifle_bullethail_attackfunc();
-		weapon_thinkf(self.rifle_bullethail_frame, self.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue);
-		print("thinkf set\n");
-	}
-	else
-	{
-		ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
-		print("out of ammo... ", ftos(self.weaponentity.state), "\n");
-	}
-}
-
-void W_Rifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire)
-{
-	// if we get here, we have at least one bullet to fire
-	AttackFunc();
-	if(mode)
-	{
-		// continue hail
-		self.rifle_bullethail_attackfunc = AttackFunc;
-		self.rifle_bullethail_frame = fr;
-		self.rifle_bullethail_animtime = animtime;
-		self.rifle_bullethail_refire = refire;
-		weapon_thinkf(fr, animtime, W_Rifle_BulletHail_Continue);
-	}
-	else
-	{
-		// just one shot
-		weapon_thinkf(fr, animtime, w_ready);
-	}
-}
-
-.float bot_secondary_riflemooth;
-float W_Rifle(float req)
-{
-	float ammo_amount;
-	
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			self.BUTTON_ATCK=FALSE;
-			self.BUTTON_ATCK2=FALSE;
-			if(vlen(self.origin-self.enemy.origin) > 1000)
-				self.bot_secondary_riflemooth = 0;
-			if(self.bot_secondary_riflemooth == 0)
-			{
-				if(bot_aim(1000000, 0, 0.001, FALSE))
-				{
-					self.BUTTON_ATCK = TRUE;
-					if(random() < 0.01) self.bot_secondary_riflemooth = 1;
-				}
-			}
-			else
-			{
-				if(bot_aim(1000000, 0, 0.001, FALSE))
-				{
-					self.BUTTON_ATCK2 = TRUE;
-					if(random() < 0.03) self.bot_secondary_riflemooth = 0;
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(autocvar_g_balance_rifle_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo))) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-			else
-			{
-				self.rifle_accumulator = bound(time - WEP_CVAR(rifle, bursttime), self.rifle_accumulator, time);
-				if(self.BUTTON_ATCK)
-				if(weapon_prepareattack_check(0, WEP_CVAR_PRI(rifle, refire)))
-				if(time >= self.rifle_accumulator + WEP_CVAR_PRI(rifle, burstcost))
-				{
-					weapon_prepareattack_do(0, WEP_CVAR_PRI(rifle, refire));
-					W_Rifle_BulletHail(WEP_CVAR_PRI(rifle, bullethail), W_Rifle_Attack, WFRAME_FIRE1, WEP_CVAR_PRI(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
-					self.rifle_accumulator += WEP_CVAR_PRI(rifle, burstcost);
-				}
-				if(self.BUTTON_ATCK2)
-				{
-					if(WEP_CVAR(rifle, secondary))
-					{
-						if(WEP_CVAR_SEC(rifle, reload))
-							WEP_ACTION(self.weapon, WR_RELOAD);
-						else
-						{
-							if(weapon_prepareattack_check(1, WEP_CVAR_SEC(rifle, refire)))
-							if(time >= self.rifle_accumulator + WEP_CVAR_SEC(rifle, burstcost))
-							{
-								weapon_prepareattack_do(1, WEP_CVAR_SEC(rifle, refire));
-								W_Rifle_BulletHail(WEP_CVAR_SEC(rifle, bullethail), W_Rifle_Attack2, WFRAME_FIRE2, WEP_CVAR_SEC(rifle, animtime), WEP_CVAR_PRI(rifle, refire));
-								self.rifle_accumulator += WEP_CVAR_SEC(rifle, burstcost);
-							}
-						}
-					}
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_campingrifle.md3");
-			precache_model("models/weapons/v_campingrifle.md3");
-			precache_model("models/weapons/h_campingrifle.iqm");
-			precache_sound("weapons/campingrifle_fire.wav");
-			precache_sound("weapons/campingrifle_fire2.wav");
-			RIFLE_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_PRI(rifle, ammo);
-			ammo_amount += self.(weapon_load[WEP_RIFLE]) >= WEP_CVAR_PRI(rifle, ammo);
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			ammo_amount = self.WEP_AMMO(RIFLE) >= WEP_CVAR_SEC(rifle, ammo);
-			ammo_amount += self.(weapon_load[WEP_RIFLE]) >= WEP_CVAR_SEC(rifle, ammo);
-			return ammo_amount;
-		}
-		case WR_CONFIG:
-		{
-			RIFLE_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RESETPLAYER:
-		{
-			self.rifle_accumulator = time - WEP_CVAR(rifle, bursttime);
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(min(WEP_CVAR_PRI(rifle, ammo), WEP_CVAR_SEC(rifle, ammo)), "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_THINKING_WITH_PORTALS;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-			{
-				if(w_deathtype & HITTYPE_BOUNCE)
-					return WEAPON_RIFLE_MURDER_HAIL_PIERCING;
-				else
-					return WEAPON_RIFLE_MURDER_HAIL;
-			}
-			else
-			{
-				if(w_deathtype & HITTYPE_BOUNCE)
-					return WEAPON_RIFLE_MURDER_PIERCING;
-				else
-					return WEAPON_RIFLE_MURDER;
-			}
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Rifle(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 2;
-			pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1);
-			if(!w_issilent)
-			{
-				if(w_random < 0.2)
-					sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTN_NORM);
-				else if(w_random < 0.4)
-					sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTN_NORM);
-				else if(w_random < 0.5)
-					sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTN_NORM);
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/ric1.wav");
-			precache_sound("weapons/ric2.wav");
-			precache_sound("weapons/ric3.wav");
-			if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
-			{
-				precache_pic("gfx/reticle_nex");
-			}
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			if(button_zoom || zoomscript_caught)
-			{
-				reticle_image = "gfx/reticle_nex";
-				return TRUE;
-			}
-			else
-			{
-				// no weapon specific image for this weapon
-				return FALSE;
-			}
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_seeker.qc b/qcsrc/common/weapons/w_seeker.qc
deleted file mode 100644
index 7d933d5ca..000000000
--- a/qcsrc/common/weapons/w_seeker.qc
+++ /dev/null
@@ -1,792 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ SEEKER,
-/* function  */ W_Seeker,
-/* ammotype  */ ammo_rockets,
-/* impulse   */ 8,
-/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0.5 1 0',
-/* modelname */ "seeker",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairseeker 0.8",
-/* wepimg    */ "weaponseeker",
-/* refname   */ "seeker",
-/* wepname   */ _("T.A.G. Seeker")
-);
-
-#define SEEKER_SETTINGS(w_cvar,w_prop) SEEKER_SETTINGS_LIST(w_cvar, w_prop, SEEKER, seeker)
-#define SEEKER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, NONE, type) \
-	w_cvar(id, sn, NONE, flac_ammo) \
-	w_cvar(id, sn, NONE, flac_animtime) \
-	w_cvar(id, sn, NONE, flac_damage) \
-	w_cvar(id, sn, NONE, flac_edgedamage) \
-	w_cvar(id, sn, NONE, flac_force) \
-	w_cvar(id, sn, NONE, flac_lifetime) \
-	w_cvar(id, sn, NONE, flac_lifetime_rand) \
-	w_cvar(id, sn, NONE, flac_radius) \
-	w_cvar(id, sn, NONE, flac_refire) \
-	w_cvar(id, sn, NONE, flac_speed) \
-	w_cvar(id, sn, NONE, flac_speed_up) \
-	w_cvar(id, sn, NONE, flac_speed_z) \
-	w_cvar(id, sn, NONE, flac_spread) \
-	w_cvar(id, sn, NONE, missile_accel) \
-	w_cvar(id, sn, NONE, missile_ammo) \
-	w_cvar(id, sn, NONE, missile_animtime) \
-	w_cvar(id, sn, NONE, missile_count) \
-	w_cvar(id, sn, NONE, missile_damage) \
-	w_cvar(id, sn, NONE, missile_damageforcescale) \
-	w_cvar(id, sn, NONE, missile_decel) \
-	w_cvar(id, sn, NONE, missile_delay) \
-	w_cvar(id, sn, NONE, missile_edgedamage) \
-	w_cvar(id, sn, NONE, missile_force) \
-	w_cvar(id, sn, NONE, missile_health) \
-	w_cvar(id, sn, NONE, missile_lifetime) \
-	w_cvar(id, sn, NONE, missile_proxy) \
-	w_cvar(id, sn, NONE, missile_proxy_delay) \
-	w_cvar(id, sn, NONE, missile_proxy_maxrange) \
-	w_cvar(id, sn, NONE, missile_radius) \
-	w_cvar(id, sn, NONE, missile_refire) \
-	w_cvar(id, sn, NONE, missile_smart) \
-	w_cvar(id, sn, NONE, missile_smart_mindist) \
-	w_cvar(id, sn, NONE, missile_smart_trace_max) \
-	w_cvar(id, sn, NONE, missile_smart_trace_min) \
-	w_cvar(id, sn, NONE, missile_speed) \
-	w_cvar(id, sn, NONE, missile_speed_max) \
-	w_cvar(id, sn, NONE, missile_speed_up) \
-	w_cvar(id, sn, NONE, missile_speed_z) \
-	w_cvar(id, sn, NONE, missile_spread) \
-	w_cvar(id, sn, NONE, missile_turnrate) \
-	w_cvar(id, sn, NONE, tag_ammo) \
-	w_cvar(id, sn, NONE, tag_animtime) \
-	w_cvar(id, sn, NONE, tag_damageforcescale) \
-	w_cvar(id, sn, NONE, tag_health) \
-	w_cvar(id, sn, NONE, tag_lifetime) \
-	w_cvar(id, sn, NONE, tag_refire) \
-	w_cvar(id, sn, NONE, tag_speed) \
-	w_cvar(id, sn, NONE, tag_spread) \
-	w_cvar(id, sn, NONE, tag_tracker_lifetime) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-SEEKER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.entity tag_target, wps_tag_tracker;
-.float tag_time;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_seeker(void) { weapon_defaultspawnfunc(WEP_SEEKER); }
-
-// ============================
-// Begin: Missile functions, these are general functions to be manipulated by other code
-// ============================
-void W_Seeker_Missile_Explode(void)
-{
-	self.event_damage = func_null;
-	RadiusDamage(self, self.realowner, WEP_CVAR(seeker, missile_damage), WEP_CVAR(seeker, missile_edgedamage), WEP_CVAR(seeker, missile_radius), world, world, WEP_CVAR(seeker, missile_force), self.projectiledeathtype, other);
-
-	remove(self);
-}
-
-void W_Seeker_Missile_Touch(void)
-{
-	PROJECTILE_TOUCH;
-
-	W_Seeker_Missile_Explode();
-}
-
-void W_Seeker_Missile_Think(void)
-{
-	entity e;
-	vector desireddir, olddir, newdir, eorg;
-	float turnrate;
-	float dist;
-	float spd;
-
-	if(time > self.cnt)
-	{
-		self.projectiledeathtype |= HITTYPE_SPLASH;
-		W_Seeker_Missile_Explode();
-	}
-
-	spd = vlen(self.velocity);
-	spd = bound(
-		spd - WEP_CVAR(seeker, missile_decel) * frametime,
-		WEP_CVAR(seeker, missile_speed_max),
-		spd + WEP_CVAR(seeker, missile_accel) * frametime
-	);
-
-	if(self.enemy != world)
-		if(self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
-			self.enemy = world;
-
-	if(self.enemy != world)
-	{
-		e               = self.enemy;
-		eorg            = 0.5 * (e.absmin + e.absmax);
-		turnrate        = WEP_CVAR(seeker, missile_turnrate); // how fast to turn
-		desireddir      = normalize(eorg - self.origin);
-		olddir          = normalize(self.velocity); // get my current direction
-		dist            = vlen(eorg - self.origin);
-
-		// Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
-		if(WEP_CVAR(seeker, missile_smart) && (dist > WEP_CVAR(seeker, missile_smart_mindist)))
-		{
-			// Is it a better idea (shorter distance) to trace to the target itself?
-			if( vlen(self.origin + olddir * self.wait) < dist)
-				traceline(self.origin, self.origin + olddir * self.wait, FALSE, self);
-			else
-				traceline(self.origin, eorg, FALSE, self);
-
-			// Setup adaptive tracelength
-			self.wait = bound(WEP_CVAR(seeker, missile_smart_trace_min), vlen(self.origin - trace_endpos), self.wait = WEP_CVAR(seeker, missile_smart_trace_max));
-
-			// Calc how important it is that we turn and add this to the desierd (enemy) dir.
-			desireddir  = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
-		}
-
-		newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy
-		self.velocity = newdir * spd; // make me fly in the new direction at my flight speed
-	}
-	else
-		dist = 0;
-
-	// Proxy
-	if(WEP_CVAR(seeker, missile_proxy))
-	{
-		if(dist <= WEP_CVAR(seeker, missile_proxy_maxrange))
-		{
-			if(self.autoswitch == 0)
-			{
-				self.autoswitch = time + WEP_CVAR(seeker, missile_proxy_delay);
-			}
-			else
-			{
-				if(self.autoswitch <= time)
-				{
-					W_Seeker_Missile_Explode();
-					self.autoswitch = 0;
-				}
-			}
-		}
-		else
-		{
-			if(self.autoswitch != 0)
-				self.autoswitch = 0;
-		}
-	}
-	///////////////
-
-	if(self.enemy.deadflag != DEAD_NO)
-	{
-		self.enemy = world;
-		self.cnt = time + 1 + (random() * 4);
-		self.nextthink = self.cnt;
-		return;
-	}
-
-	//self.angles = vectoangles(self.velocity);			// turn model in the new flight direction
-	self.nextthink = time;// + 0.05; // csqc projectiles
-	UpdateCSQCProjectile(self);
-}
-
-
-
-void W_Seeker_Missile_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if(self.health <= 0)
-		return;
-
-	if(!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
-		return; // g_projectiles_damage says to halt
-
-	if(self.realowner == attacker)
-		self.health = self.health - (damage * 0.25);
-	else
-		self.health = self.health - damage;
-
-	if(self.health <= 0)
-		W_PrepareExplosionByDamage(attacker, W_Seeker_Missile_Explode);
-}
-
-/*
-void W_Seeker_Missile_Animate(void)
-{
-	self.frame = self.frame +1;
-	self.nextthink = time + 0.05;
-
-	if(self.enemy != world)
-		if(self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
-			self.enemy = world;
-
-	if(self.frame == 5)
-	{
-		self.think           = W_Seeker_Missile_Think;
-		self.nextthink       = time;// + cvar("g_balance_seeker_missile_activate_delay"); // cant dealy with csqc projectiles
-
-		if(autocvar_g_balance_seeker_missile_proxy)
-			self.movetype    = MOVETYPE_BOUNCEMISSILE;
-		else
-			self.movetype    = MOVETYPE_FLYMISSILE;
-	}
-
-	UpdateCSQCProjectile(self);
-}
-*/
-
-void W_Seeker_Fire_Missile(vector f_diff, entity m_target)
-{
-	entity missile;
-
-	W_DecreaseAmmo(WEP_CVAR(seeker, missile_ammo));
-
-	makevectors(self.v_angle);
-	W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/seeker_fire.wav", CH_WEAPON_A, 0);
-	w_shotorg += f_diff;
-	pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	//self.detornator         = FALSE;
-
-	missile                 = spawn();
-	missile.owner           = missile.realowner = self;
-	missile.classname       = "seeker_missile";
-	missile.bot_dodge       = TRUE;
-	missile.bot_dodgerating = WEP_CVAR(seeker, missile_damage);
-
-	missile.think           = W_Seeker_Missile_Think;
-	missile.touch           = W_Seeker_Missile_Touch;
-	missile.event_damage    = W_Seeker_Missile_Damage;
-	missile.nextthink       = time;// + 0.2;// + cvar("g_balance_seeker_missile_activate_delay");
-	missile.cnt             = time + WEP_CVAR(seeker, missile_lifetime);
-	missile.enemy           = m_target;
-	missile.solid           = SOLID_BBOX;
-	missile.scale           = 2;
-	missile.takedamage      = DAMAGE_YES;
-	missile.health          = WEP_CVAR(seeker, missile_health);
-	missile.damageforcescale = WEP_CVAR(seeker, missile_damageforcescale);
-	missile.damagedbycontents = TRUE;
-	//missile.think           = W_Seeker_Missile_Animate; // csqc projectiles.
-
-	if(missile.enemy != world)
-		missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
-	else
-		missile.projectiledeathtype = WEP_SEEKER;
-
-
-	setorigin(missile, w_shotorg);
-	setsize(missile, '-4 -4 -4', '4 4 4');
-	missile.movetype    = MOVETYPE_FLYMISSILE;
-	missile.flags       = FL_PROJECTILE;
-	missile.missile_flags = MIF_SPLASH | MIF_GUIDED_TAG;
-
-	W_SetupProjVelocity_UP_PRE(missile, seeker, missile_);
-
-	missile.angles = vectoangles(missile.velocity);
-
-	CSQCProjectile(missile, FALSE, PROJECTILE_SEEKER, TRUE);
-
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-// ============================
-// Begin: FLAC, close range attack meant for defeating rockets which are coming at you.
-// ============================
-void W_Seeker_Flac_Explode(void)
-{
-	self.event_damage = func_null;
-
-	RadiusDamage(self, self.realowner, WEP_CVAR(seeker, flac_damage), WEP_CVAR(seeker, flac_edgedamage), WEP_CVAR(seeker, flac_radius), world, world, WEP_CVAR(seeker, flac_force), self.projectiledeathtype, other);
-
-	remove(self);
-}
-
-void W_Seeker_Flac_Touch(void)
-{
-	PROJECTILE_TOUCH;
-
-	W_Seeker_Flac_Explode();
-}
-
-void W_Seeker_Fire_Flac(void)
-{
-	entity missile;
-	vector f_diff;
-	float c;
-
-	W_DecreaseAmmo(WEP_CVAR(seeker, flac_ammo));
-
-	c = mod(self.bulletcounter, 4);
-	switch(c)
-	{
-		case 0:
-			f_diff = '-1.25 -3.75 0';
-			break;
-		case 1:
-			f_diff = '+1.25 -3.75 0';
-			break;
-		case 2:
-			f_diff = '-1.25 +3.75 0';
-			break;
-		case 3:
-		default:
-			f_diff = '+1.25 +3.75 0';
-			break;
-	}
-	W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/flac_fire.wav", CH_WEAPON_A, WEP_CVAR(seeker, flac_damage));
-	w_shotorg += f_diff;
-
-	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	missile 				= spawn();
-	missile.owner 			= missile.realowner = self;
-	missile.classname 		= "missile";
-	missile.bot_dodge 		= TRUE;
-	missile.bot_dodgerating = WEP_CVAR(seeker, flac_damage);
-	missile.touch 			= W_Seeker_Flac_Explode;
-	missile.use 			= W_Seeker_Flac_Explode;
-	missile.think 			= adaptor_think2use_hittype_splash;
-	missile.nextthink 		= time + WEP_CVAR(seeker, flac_lifetime) + WEP_CVAR(seeker, flac_lifetime_rand);
-	missile.solid 			= SOLID_BBOX;
-	missile.movetype 		= MOVETYPE_FLY;
-	missile.projectiledeathtype = WEP_SEEKER;
-	missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
-	missile.flags 				= FL_PROJECTILE;
-	missile.missile_flags       = MIF_SPLASH;
-
-	// csqc projectiles
-	//missile.angles 				= vectoangles(missile.velocity);
-	//missile.scale = 0.4; // BUG: the model is too big
-
-	setorigin(missile, w_shotorg);
-	setsize(missile, '-2 -2 -2', '2 2 2');
-
-	W_SetupProjVelocity_UP_PRE(missile, seeker, flac_);
-	CSQCProjectile(missile, TRUE, PROJECTILE_FLAC, TRUE);
-
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-// ============================
-// Begin: Tag and rocket controllers
-// ============================
-entity W_Seeker_Tagged_Info(entity isowner, entity istarget)
-{
-	entity tag;
-	for(tag = world; (tag = find(tag, classname, "tag_tracker")); )
-		if((tag.realowner == isowner) && (tag.tag_target == istarget))
-			return tag;
-
-	return world;
-}
-
-void W_Seeker_Attack(void)
-{
-	entity tracker, closest_target;
-
-	closest_target = world;
-	for(tracker = world; (tracker = find(tracker, classname, "tag_tracker")); ) if (tracker.realowner == self)
-	{
-		if(closest_target)
-		{
-			if(vlen(self.origin - tracker.tag_target.origin) < vlen(self.origin - closest_target.origin))
-				closest_target = tracker.tag_target;
-		}
-		else
-			closest_target = tracker.tag_target;
-	}
-
-	traceline(self.origin + self.view_ofs, closest_target.origin, MOVE_NOMONSTERS, self);
-	if((!closest_target) || ((trace_fraction < 1) && (trace_ent != closest_target)))
-		closest_target = world;
-
-	W_Seeker_Fire_Missile('0 0 0', closest_target);
-}
-
-void W_Seeker_Vollycontroller_Think(void) // TODO: Merge this with W_Seeker_Attack
-{
-	float c;
-	entity oldself,oldenemy;
-	self.cnt = self.cnt - 1;
-
-	if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.WEP_AMMO(SEEKER) < WEP_CVAR(seeker, missile_ammo)) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER))
-	{
-		remove(self);
-		return;
-	}
-
-	self.nextthink = time + WEP_CVAR(seeker, missile_delay) * W_WeaponRateFactor();
-
-	oldself = self;
-	self = self.realowner;
-
-	oldenemy = self.enemy;
-	self.enemy = oldself.enemy;
-
-	c = mod(self.cnt, 4);
-	switch(c)
-	{
-		case 0:
-			W_Seeker_Fire_Missile('-1.25 -3.75 0', self.enemy);
-			break;
-		case 1:
-			W_Seeker_Fire_Missile('+1.25 -3.75 0', self.enemy);
-			break;
-		case 2:
-			W_Seeker_Fire_Missile('-1.25 +3.75 0', self.enemy);
-			break;
-		case 3:
-		default:
-			W_Seeker_Fire_Missile('+1.25 +3.75 0', self.enemy);
-			break;
-	}
-
-	self.enemy = oldenemy;
-	self = oldself;
-}
-
-void W_Seeker_Tracker_Think(void)
-{
-	// commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up
-	if((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER)
-	|| (time > self.tag_time + WEP_CVAR(seeker, tag_tracker_lifetime)))
-	{
-		if(self)
-		{
-			WaypointSprite_Kill(self.tag_target.wps_tag_tracker);
-			remove(self);
-		}
-		return;
-	}
-
-	// Update the think method information
-	self.nextthink = time;
-}
-
-// ============================
-// Begin: Tag projectile
-// ============================
-void W_Seeker_Tag_Explode(void)
-{
-	//if(other==self.realowner)
-	//    return;
-	Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE, other.species, self);
-
-	remove(self);
-}
-
-void W_Seeker_Tag_Damage(entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
-{
-	if(self.health <= 0)
-		return;
-	self.health = self.health - damage;
-	if(self.health <= 0)
-		W_Seeker_Tag_Explode();
-}
-
-void W_Seeker_Tag_Touch(void)
-{
-	vector dir;
-	vector org2;
-	entity e;
-
-	PROJECTILE_TOUCH;
-
-	dir     = normalize(self.realowner.origin - self.origin);
-	org2    = findbetterlocation(self.origin, 8);
-
-	te_knightspike(org2);
-
-	self.event_damage = func_null;
-	Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE | HITTYPE_SECONDARY, other.species, self);
-
-	if(other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO)
-	{
-		// check to see if this person is already tagged by me
-		entity tag = W_Seeker_Tagged_Info(self.realowner, other);
-
-		if(tag != world)
-		{
-			if(other.wps_tag_tracker && (WEP_CVAR(seeker, type) == 1)) // don't attach another waypointsprite without killing the old one first
-				WaypointSprite_Kill(other.wps_tag_tracker);
-
-			tag.tag_time = time;
-		}
-		else
-		{
-			//sprint(self.realowner, strcat("You just tagged ^2", other.netname, "^7 with a tracking device!\n"));
-			e             = spawn();
-			e.cnt         = WEP_CVAR(seeker, missile_count);
-			e.classname   = "tag_tracker";
-			e.owner       = self.owner;
-			e.realowner   = self.realowner;
-
-			if(WEP_CVAR(seeker, type) == 1)
-			{
-				e.tag_target  = other;
-				e.tag_time    = time;
-				e.think       = W_Seeker_Tracker_Think;
-			}
-			else
-			{
-				e.enemy     = other;
-				e.think     = W_Seeker_Vollycontroller_Think;
-			}
-
-			e.nextthink   = time;
-		}
-
-		if(WEP_CVAR(seeker, type) == 1)
-		{
-			WaypointSprite_Spawn("tagged-target", WEP_CVAR(seeker, tag_tracker_lifetime), 0, other, '0 0 64', self.realowner, 0, other, wps_tag_tracker, TRUE, RADARICON_TAGGED, '0.5 1 0');
-			WaypointSprite_UpdateRule(other.wps_tag_tracker, 0, SPRITERULE_DEFAULT);
-		}
-	}
-
-	remove(self);
-	return;
-}
-
-void W_Seeker_Fire_Tag(void)
-{
-	entity missile;
-	W_DecreaseAmmo(WEP_CVAR(seeker, tag_ammo));
-
-	W_SetupShot_ProjectileSize(self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/tag_fire.wav", CH_WEAPON_A, WEP_CVAR(seeker, missile_damage) * WEP_CVAR(seeker, missile_count));
-
-	missile                 = spawn();
-	missile.owner           = missile.realowner = self;
-	missile.classname       = "seeker_tag";
-	missile.bot_dodge       = TRUE;
-	missile.bot_dodgerating = 50;
-	missile.touch           = W_Seeker_Tag_Touch;
-	missile.think           = SUB_Remove;
-	missile.nextthink       = time + WEP_CVAR(seeker, tag_lifetime);
-	missile.movetype        = MOVETYPE_FLY;
-	missile.solid           = SOLID_BBOX;
-
-	missile.takedamage       = DAMAGE_YES;
-	missile.event_damage     = W_Seeker_Tag_Damage;
-	missile.health           = WEP_CVAR(seeker, tag_health);
-	missile.damageforcescale = WEP_CVAR(seeker, tag_damageforcescale);
-
-	setorigin(missile, w_shotorg);
-	setsize(missile, '-2 -2 -2', '2 2 2');
-
-	missile.flags       = FL_PROJECTILE;
-	//missile.missile_flags = MIF_..?;
-
-	missile.movetype    = MOVETYPE_FLY;
-	W_SetupProjVelocity_PRE(missile, seeker, tag_);
-	missile.angles = vectoangles(missile.velocity);
-
-	CSQCProjectile(missile, TRUE, PROJECTILE_TAG, FALSE); // has sound
-
-	other = missile; MUTATOR_CALLHOOK(EditProjectile);
-}
-
-// ============================
-// Begin: Genereal weapon functions
-// ============================
-
-float W_Seeker(float req)
-{
-	float ammo_amount;
-
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			if(WEP_CVAR(seeker, type) == 1)
-				if(W_Seeker_Tagged_Info(self, self.enemy) != world)
-					self.BUTTON_ATCK = bot_aim(WEP_CVAR(seeker, missile_speed_max), 0, WEP_CVAR(seeker, missile_lifetime), FALSE);
-				else
-					self.BUTTON_ATCK2 = bot_aim(WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), FALSE);
-			else
-				self.BUTTON_ATCK = bot_aim(WEP_CVAR(seeker, tag_speed), 0, WEP_CVAR(seeker, tag_lifetime), FALSE);
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(autocvar_g_balance_seeker_reload_ammo && self.clip_load < min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo))) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-
-			else if(self.BUTTON_ATCK)
-			{
-				if(WEP_CVAR(seeker, type) == 1)
-				{
-					if(weapon_prepareattack(0, WEP_CVAR(seeker, missile_refire)))
-					{
-						W_Seeker_Attack();
-						weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, missile_animtime), w_ready);
-					}
-				}
-				else
-				{
-					if(weapon_prepareattack(0, WEP_CVAR(seeker, tag_refire)))
-					{
-						W_Seeker_Fire_Tag();
-						weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
-					}
-				}
-			}
-
-			else if(self.BUTTON_ATCK2)
-			{
-				if(WEP_CVAR(seeker, type) == 1)
-				{
-					if(weapon_prepareattack(0, WEP_CVAR(seeker, tag_refire)))
-					{
-						W_Seeker_Fire_Tag();
-						weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, tag_animtime), w_ready);
-					}
-				}
-				else
-				{
-					if(weapon_prepareattack(0, WEP_CVAR(seeker, flac_refire)))
-					{
-						W_Seeker_Fire_Flac();
-						weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(seeker, flac_animtime), w_ready);
-					}
-				}
-			}
-
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_seeker.md3");
-			precache_model("models/weapons/v_seeker.md3");
-			precache_model("models/weapons/h_seeker.iqm");
-			precache_sound("weapons/tag_fire.wav");
-			precache_sound("weapons/flac_fire.wav");
-			precache_sound("weapons/seeker_fire.wav");
-			SEEKER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			if(WEP_CVAR(seeker, type) == 1)
-			{
-				ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, missile_ammo);
-				ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, missile_ammo);
-			}
-			else
-			{
-				ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, tag_ammo);
-				ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, tag_ammo);
-			}
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			if(WEP_CVAR(seeker, type) == 1)
-			{
-				ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, tag_ammo);
-				ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, tag_ammo);
-			}
-			else
-			{
-				ammo_amount = self.WEP_AMMO(SEEKER) >= WEP_CVAR(seeker, flac_ammo);
-				ammo_amount += self.(weapon_load[WEP_SEEKER]) >= WEP_CVAR(seeker, flac_ammo);
-			}
-			return ammo_amount;
-		}
-		case WR_CONFIG:
-		{
-			SEEKER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(min(WEP_CVAR(seeker, missile_ammo), WEP_CVAR(seeker, tag_ammo)), "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_SEEKER_SUICIDE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_SEEKER_MURDER_TAG;
-			else
-				return WEAPON_SEEKER_MURDER_SPRAY;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Seeker(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 6;
-			if(w_deathtype & HITTYPE_BOUNCE)
-			{
-				if(w_deathtype & HITTYPE_SECONDARY)
-				{
-					if(!w_issilent)
-						sound(self, CH_SHOTS, "weapons/tag_impact.wav", 1, ATTEN_NORM);
-				}
-				else
-				{
-					pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
-					if(!w_issilent)
-					{
-						if(w_random<0.15)
-							sound(self, CH_SHOTS, "weapons/tagexp1.wav", 1, ATTEN_NORM);
-						else if(w_random<0.7)
-							sound(self, CH_SHOTS, "weapons/tagexp2.wav", 1, ATTEN_NORM);
-						else
-							sound(self, CH_SHOTS, "weapons/tagexp3.wav", 1, ATTEN_NORM);
-					}
-				}
-			}
-			else
-			{
-				pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
-				if(!w_issilent)
-				{
-					if(w_random<0.15)
-						sound(self, CH_SHOTS, "weapons/seekerexp1.wav", 1, ATTEN_NORM);
-					else if(w_random<0.7)
-						sound(self, CH_SHOTS, "weapons/seekerexp2.wav", 1, ATTEN_NORM);
-					else
-						sound(self, CH_SHOTS, "weapons/seekerexp3.wav", 1, ATTEN_NORM);
-				}
-			}
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/seekerexp1.wav");
-			precache_sound("weapons/seekerexp2.wav");
-			precache_sound("weapons/seekerexp3.wav");
-			precache_sound("weapons/tagexp1.wav");
-			precache_sound("weapons/tagexp2.wav");
-			precache_sound("weapons/tagexp3.wav");
-			precache_sound("weapons/tag_impact.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_shockwave.qc b/qcsrc/common/weapons/w_shockwave.qc
deleted file mode 100644
index 759dc35ea..000000000
--- a/qcsrc/common/weapons/w_shockwave.qc
+++ /dev/null
@@ -1,897 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ SHOCKWAVE,
-/* function  */ W_Shockwave,
-/* ammotype  */ ammo_none,
-/* impulse   */ 2,
-/* flags     */ WEP_FLAG_NORMAL | WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_FLAG_MUTATORBLOCKED,
-/* rating    */ BOT_PICKUP_RATING_LOW,
-/* color     */ '0.5 0.25 0',
-/* modelname */ "shotgun",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairshotgun 0.7",
-/* wepimg    */ "weaponshotgun",
-/* refname   */ "shockwave",
-/* wepname   */ _("Shockwave")
-);
-
-#define SHOCKWAVE_SETTINGS(w_cvar,w_prop) SHOCKWAVE_SETTINGS_LIST(w_cvar, w_prop, SHOCKWAVE, shockwave)
-#define SHOCKWAVE_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, NONE, blast_animtime) \
-	w_cvar(id, sn, NONE, blast_damage) \
-	w_cvar(id, sn, NONE, blast_distance) \
-	w_cvar(id, sn, NONE, blast_edgedamage) \
-	w_cvar(id, sn, NONE, blast_force) \
-	w_cvar(id, sn, NONE, blast_force_forwardbias) \
-	w_cvar(id, sn, NONE, blast_force_zscale) \
-	w_cvar(id, sn, NONE, blast_jump_damage) \
-	w_cvar(id, sn, NONE, blast_jump_edgedamage) \
-	w_cvar(id, sn, NONE, blast_jump_force) \
-	w_cvar(id, sn, NONE, blast_jump_force_velocitybias) \
-	w_cvar(id, sn, NONE, blast_jump_force_zscale) \
-	w_cvar(id, sn, NONE, blast_jump_multiplier_accuracy) \
-	w_cvar(id, sn, NONE, blast_jump_multiplier_distance) \
-	w_cvar(id, sn, NONE, blast_jump_multiplier_min) \
-	w_cvar(id, sn, NONE, blast_jump_radius) \
-	w_cvar(id, sn, NONE, blast_multiplier_accuracy) \
-	w_cvar(id, sn, NONE, blast_multiplier_distance) \
-	w_cvar(id, sn, NONE, blast_multiplier_min) \
-	w_cvar(id, sn, NONE, blast_refire) \
-	w_cvar(id, sn, NONE, blast_splash_damage) \
-	w_cvar(id, sn, NONE, blast_splash_edgedamage) \
-	w_cvar(id, sn, NONE, blast_splash_force) \
-	w_cvar(id, sn, NONE, blast_splash_force_forwardbias) \
-	w_cvar(id, sn, NONE, blast_splash_multiplier_accuracy) \
-	w_cvar(id, sn, NONE, blast_splash_multiplier_distance) \
-	w_cvar(id, sn, NONE, blast_splash_multiplier_min) \
-	w_cvar(id, sn, NONE, blast_splash_radius) \
-	w_cvar(id, sn, NONE, blast_spread_max) \
-	w_cvar(id, sn, NONE, blast_spread_min) \
-	w_cvar(id, sn, NONE, melee_animtime) \
-	w_cvar(id, sn, NONE, melee_damage) \
-	w_cvar(id, sn, NONE, melee_delay) \
-	w_cvar(id, sn, NONE, melee_force) \
-	w_cvar(id, sn, NONE, melee_multihit) \
-	w_cvar(id, sn, NONE, melee_no_doubleslap) \
-	w_cvar(id, sn, NONE, melee_nonplayerdamage) \
-	w_cvar(id, sn, NONE, melee_range) \
-	w_cvar(id, sn, NONE, melee_refire) \
-	w_cvar(id, sn, NONE, melee_swing_side) \
-	w_cvar(id, sn, NONE, melee_swing_up) \
-	w_cvar(id, sn, NONE, melee_time) \
-	w_cvar(id, sn, NONE, melee_traces) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-SHOCKWAVE_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-#endif
-#ifdef CSQC
-void Net_ReadShockwaveParticle(void);
-.vector sw_shotorg;
-.vector sw_shotdir;
-.float sw_distance;
-.float sw_spread_max;
-.float sw_spread_min;
-.float sw_time;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_shockwave(void)
-{
-	//if(autocvar_sv_q3acompat_machineshockwaveswap) // WEAPONTODO
-	if(autocvar_sv_q3acompat_machineshotgunswap)
-	if(self.classname != "droppedweapon")
-	{
-		weapon_defaultspawnfunc(WEP_MACHINEGUN);
-		return;
-	}
-	weapon_defaultspawnfunc(WEP_SHOCKWAVE);
-}
-
-#define MAX_SHOCKWAVE_HITS 10
-//#define DEBUG_SHOCKWAVE
-
-.float swing_prev;
-.entity swing_alreadyhit;
-.float shockwave_blasttime;
-entity shockwave_hit[MAX_SHOCKWAVE_HITS];
-float shockwave_hit_damage[MAX_SHOCKWAVE_HITS];
-vector shockwave_hit_force[MAX_SHOCKWAVE_HITS];
-
-// MELEE ATTACK MODE
-void W_Shockwave_Melee_Think(void)
-{
-	// declarations
-	float i, f, swing, swing_factor, swing_damage, meleetime, is_player;
-	entity target_victim;
-	vector targpos;
-
-	// check to see if we can still continue, otherwise give up now
-	if((self.realowner.deadflag != DEAD_NO) && WEP_CVAR(shockwave, melee_no_doubleslap))
-	{
-		remove(self);
-		return;
-	}
-
-	// set start time of melee
-	if(!self.cnt)
-	{
-		self.cnt = time; 
-		W_PlayStrengthSound(self.realowner);
-	}
-
-	// update values for v_* vectors
-	makevectors(self.realowner.v_angle);
-	
-	// calculate swing percentage based on time
-	meleetime = WEP_CVAR(shockwave, melee_time) * W_WeaponRateFactor();
-	swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10);
-	f = ((1 - swing) * WEP_CVAR(shockwave, melee_traces));
-	
-	// perform the traces needed for this frame 
-	for(i=self.swing_prev; i < f; ++i)
-	{
-		swing_factor = ((1 - (i / WEP_CVAR(shockwave, melee_traces))) * 2 - 1);
-		
-		targpos = (self.realowner.origin + self.realowner.view_ofs 
-			+ (v_forward * WEP_CVAR(shockwave, melee_range))
-			+ (v_up * swing_factor * WEP_CVAR(shockwave, melee_swing_up))
-			+ (v_right * swing_factor * WEP_CVAR(shockwave, melee_swing_side)));
-
-		WarpZone_traceline_antilag(
-			self.realowner,
-			(self.realowner.origin + self.realowner.view_ofs),
-			targpos,
-			FALSE,
-			self.realowner,
-			ANTILAG_LATENCY(self.realowner)
-		);
-		
-		// draw lightning beams for debugging
-#ifdef DEBUG_SHOCKWAVE
-		te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5); 
-		te_customflash(targpos, 40,  2, '1 1 1');
-#endif
-		
-		is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || (trace_ent.flags & FL_MONSTER));
-
-		if((trace_fraction < 1) // if trace is good, apply the damage and remove self if necessary
-			&& (trace_ent.takedamage == DAMAGE_AIM)  
-			&& (trace_ent != self.swing_alreadyhit)
-			&& (is_player || WEP_CVAR(shockwave, melee_nonplayerdamage)))
-		{
-			target_victim = trace_ent; // so it persists through other calls
-			
-			if(is_player) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught
-				swing_damage = (WEP_CVAR(shockwave, melee_damage) * min(1, swing_factor + 1));
-			else
-				swing_damage = (WEP_CVAR(shockwave, melee_nonplayerdamage) * min(1, swing_factor + 1));
-
-			// trigger damage with this calculated info
-			Damage(
-				target_victim,
-				self.realowner,
-				self.realowner, 
-				swing_damage,
-				(WEP_SHOCKWAVE | HITTYPE_SECONDARY), 
-				(self.realowner.origin + self.realowner.view_ofs), 
-				(v_forward * WEP_CVAR(shockwave, melee_force))
-			);
-
-			// handle accuracy
-			if(accuracy_isgooddamage(self.realowner, target_victim))
-				{ accuracy_add(self.realowner, WEP_SHOCKWAVE, 0, swing_damage); }
-
-			#ifdef DEBUG_SHOCKWAVE
-			print(sprintf(
-				"MELEE: %s hitting %s with %f damage (factor: %f) at %f time.\n",
-				self.realowner.netname,
-				target_victim.netname,
-				swing_damage,
-				swing_factor,
-				time
-			));
-			#endif
-
-			// allow multiple hits with one swing, but not against the same player twice
-			if(WEP_CVAR(shockwave, melee_multihit))
-			{
-				self.swing_alreadyhit = target_victim;
-				continue; // move along to next trace
-			}
-			else
-			{
-				remove(self);
-				return;
-			}
-		}
-	}
-	
-	if(time >= self.cnt + meleetime)
-	{
-		// melee is finished
-		remove(self);
-		return;
-	}
-	else
-	{
-		// set up next frame 
-		self.swing_prev = i;
-		self.nextthink = time;
-	}
-}
-
-void W_Shockwave_Melee(void)
-{
-	sound(self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTN_NORM);
-	weapon_thinkf(WFRAME_FIRE2, WEP_CVAR(shockwave, melee_animtime), w_ready);
-
-	entity meleetemp;
-	meleetemp = spawn();
-	meleetemp.owner = meleetemp.realowner = self;
-	meleetemp.think = W_Shockwave_Melee_Think;
-	meleetemp.nextthink = time + WEP_CVAR(shockwave, melee_delay) * W_WeaponRateFactor();
-	W_SetupShot_Range(self, TRUE, 0, "", 0, WEP_CVAR(shockwave, melee_damage), WEP_CVAR(shockwave, melee_range));
-}
-
-// SHOCKWAVE ATTACK MODE
-float W_Shockwave_Attack_CheckSpread(
-	vector targetorg,
-	vector nearest_on_line,
-	vector sw_shotorg,
-	vector attack_endpos)
-{
-	float spreadlimit;
-	float distance_of_attack = vlen(sw_shotorg - attack_endpos);
-	float distance_from_line = vlen(targetorg - nearest_on_line);
-	
-	spreadlimit = (distance_of_attack ? min(1, (vlen(sw_shotorg - nearest_on_line) / distance_of_attack)) : 1);
-	spreadlimit =
-		(
-			(WEP_CVAR(shockwave, blast_spread_min) * (1 - spreadlimit))
-			+
-			(WEP_CVAR(shockwave, blast_spread_max) * spreadlimit)
-		);
-
-	if(
-		(spreadlimit && (distance_from_line <= spreadlimit))
-		&&
-		((vlen(normalize(targetorg - sw_shotorg) - normalize(attack_endpos - sw_shotorg)) * RAD2DEG) <= 90)
-	)
-		{ return bound(0, (distance_from_line / spreadlimit), 1); }
-	else
-		{ return FALSE; }
-}
-
-float W_Shockwave_Attack_IsVisible(
-	entity head,
-	vector nearest_on_line,
-	vector sw_shotorg,
-	vector attack_endpos)
-{
-	vector nearest_to_attacker = head.WarpZone_findradius_nearest;
-	vector center = (head.origin + (head.mins + head.maxs) * 0.5);
-	vector corner;
-	float i;
-
-	// STEP ONE: Check if the nearest point is clear
-	if(W_Shockwave_Attack_CheckSpread(nearest_to_attacker, nearest_on_line, sw_shotorg, attack_endpos))
-	{
-		WarpZone_TraceLine(sw_shotorg, nearest_to_attacker, MOVE_NOMONSTERS, self);
-		if(trace_fraction == 1) { return TRUE; } // yes, the nearest point is clear and we can allow the damage
-	}
-
-	// STEP TWO: Check if shotorg to center point is clear
-	if(W_Shockwave_Attack_CheckSpread(center, nearest_on_line, sw_shotorg, attack_endpos))
-	{
-		WarpZone_TraceLine(sw_shotorg, center, MOVE_NOMONSTERS, self);
-		if(trace_fraction == 1) { return TRUE; } // yes, the center point is clear and we can allow the damage
-	}
-
-	// STEP THREE: Check each corner to see if they are clear
-	for(i=1; i<=8; ++i)
-	{
-		corner = get_corner_position(head, i);
-		if(W_Shockwave_Attack_CheckSpread(corner, nearest_on_line, sw_shotorg, attack_endpos))
-		{
-			WarpZone_TraceLine(sw_shotorg, corner, MOVE_NOMONSTERS, self);
-			if(trace_fraction == 1) { return TRUE; } // yes, this corner is clear and we can allow the damage
-		}
-	}
-
-	return FALSE;
-}
-
-float W_Shockwave_Attack_CheckHit(
-	float queue,
-	entity head,
-	vector final_force,
-	float final_damage)
-{
-	if(!head) { return FALSE; }
-	float i;
-	
-	for(i = 0; i <= queue; ++i)
-	{
-		if(shockwave_hit[i] == head)
-		{
-			if(vlen(final_force) > vlen(shockwave_hit_force[i])) { shockwave_hit_force[i] = final_force; }
-			if(final_damage > shockwave_hit_damage[i]) { shockwave_hit_damage[i] = final_damage; }
-			return FALSE;
-		}
-	}
-
-	shockwave_hit[queue] = head;
-	shockwave_hit_force[queue] = final_force;
-	shockwave_hit_damage[queue] = final_damage;
-	return TRUE;
-}
-
-void W_Shockwave_Send(void)
-{
-	WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
-	WriteByte(MSG_BROADCAST, TE_CSQC_SHOCKWAVEPARTICLE);
-	WriteCoord(MSG_BROADCAST, w_shotorg_x);
-	WriteCoord(MSG_BROADCAST, w_shotorg_y);
-	WriteCoord(MSG_BROADCAST, w_shotorg_z);
-	WriteCoord(MSG_BROADCAST, w_shotdir_x);
-	WriteCoord(MSG_BROADCAST, w_shotdir_y);
-	WriteCoord(MSG_BROADCAST, w_shotdir_z);
-	WriteShort(MSG_BROADCAST, WEP_CVAR(shockwave, blast_distance));
-	WriteByte(MSG_BROADCAST, bound(0, WEP_CVAR(shockwave, blast_spread_max), 255));
-	WriteByte(MSG_BROADCAST, bound(0, WEP_CVAR(shockwave, blast_spread_min), 255));
-	WriteByte(MSG_BROADCAST, num_for_edict(self));
-}
-
-void W_Shockwave_Attack(void)
-{
-	// declarations
-	float multiplier, multiplier_from_accuracy, multiplier_from_distance;
-	float final_damage;
-	vector final_force, center, vel;
-	entity head;
-
-	float i, queue = 0;
-	
-	// set up the shot direction
-	W_SetupShot(self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, WEP_CVAR(shockwave, blast_damage));
-	vector attack_endpos = (w_shotorg + (w_shotdir * WEP_CVAR(shockwave, blast_distance)));
-	WarpZone_TraceLine(w_shotorg, attack_endpos, MOVE_NOMONSTERS, self);
-	vector attack_hitpos = trace_endpos;
-	float distance_to_end = vlen(w_shotorg - attack_endpos);
-	float distance_to_hit = vlen(w_shotorg - attack_hitpos);
-	//entity transform = WarpZone_trace_transform;
-
-	// do the firing effect now
-	W_Shockwave_Send();
-	Damage_DamageInfo(
-		attack_hitpos,
-		WEP_CVAR(shockwave, blast_splash_damage),
-		WEP_CVAR(shockwave, blast_splash_edgedamage),
-		WEP_CVAR(shockwave, blast_splash_radius),
-		w_shotdir * WEP_CVAR(shockwave, blast_splash_force),
-		WEP_SHOCKWAVE,
-		0,
-		self
-	);
-
-	// splash damage/jumping trace
-	head = WarpZone_FindRadius(
-		attack_hitpos,
-		max(
-			WEP_CVAR(shockwave, blast_splash_radius),
-			WEP_CVAR(shockwave, blast_jump_radius)
-		),
-		FALSE
-	);
-	
-	while(head)
-	{
-		if(head.takedamage)
-		{
-			float distance_to_head = vlen(attack_hitpos - head.WarpZone_findradius_nearest);
-			
-			if((head == self) && (distance_to_head <= WEP_CVAR(shockwave, blast_jump_radius)))
-			{
-				// ========================
-				//  BLAST JUMP CALCULATION
-				// ========================
-				
-				// calculate importance of distance and accuracy for this attack
-				multiplier_from_accuracy = (1 -
-					(distance_to_head ?
-						min(1, (distance_to_head / WEP_CVAR(shockwave, blast_jump_radius)))
-						:
-						0
-					)
-				);
-				multiplier_from_distance = (1 -
-					(distance_to_hit ?
-						min(1, (distance_to_hit / distance_to_end))
-						:
-						0
-					)
-				);
-				multiplier =
-					max(
-						WEP_CVAR(shockwave, blast_jump_multiplier_min),
-						(
-							(multiplier_from_accuracy * WEP_CVAR(shockwave, blast_jump_multiplier_accuracy))
-							+
-							(multiplier_from_distance * WEP_CVAR(shockwave, blast_jump_multiplier_distance))
-						)
-					);
-
-				// calculate damage from multiplier: 1 = "highest" damage, 0 = "lowest" edgedamage
-				final_damage =
-					(
-						(WEP_CVAR(shockwave, blast_jump_damage) * multiplier)
-						+
-						(WEP_CVAR(shockwave, blast_jump_edgedamage) * (1 - multiplier))
-					);
-
-				// figure out the direction of force
-				vel = normalize(combine_to_vector(head.velocity_x, head.velocity_y, 0));
-				vel *=
-					(
-						bound(0, (vlen(vel) / autocvar_sv_maxspeed), 1)
-						*
-						WEP_CVAR(shockwave, blast_jump_force_velocitybias)
-					);
-				final_force = normalize((CENTER_OR_VIEWOFS(head) - attack_hitpos) + vel);
-
-				// now multiply the direction by force units
-				final_force *= (WEP_CVAR(shockwave, blast_jump_force) * multiplier);
-				final_force_z *= WEP_CVAR(shockwave, blast_jump_force_zscale);
-
-				// trigger damage with this calculated info
-				Damage(
-					head,
-					self,
-					self,
-					final_damage,
-					WEP_SHOCKWAVE,
-					head.origin,
-					final_force
-				);
-
-				#ifdef DEBUG_SHOCKWAVE
-				print(sprintf(
-					"SELF HIT: multiplier = %f, damage = %f, force = %f... "
-					"multiplier_from_accuracy = %f, multiplier_from_distance = %f.\n",
-					multiplier,
-					final_damage,
-					vlen(final_force),
-					multiplier_from_accuracy,
-					multiplier_from_distance
-				));
-				#endif
-			}
-			else if(distance_to_head <= WEP_CVAR(shockwave, blast_splash_radius))
-			{
-				// ==========================
-				//  BLAST SPLASH CALCULATION
-				// ==========================
-				
-				// calculate importance of distance and accuracy for this attack
-				multiplier_from_accuracy = (1 -
-					(distance_to_head ?
-						min(1, (distance_to_head / WEP_CVAR(shockwave, blast_splash_radius)))
-						:
-						0
-					)
-				);
-				multiplier_from_distance = (1 -
-					(distance_to_hit ?
-						min(1, (distance_to_hit / distance_to_end))
-						:
-						0
-					)
-				);
-				multiplier =
-					max(
-						WEP_CVAR(shockwave, blast_splash_multiplier_min),
-						(
-							(multiplier_from_accuracy * WEP_CVAR(shockwave, blast_splash_multiplier_accuracy))
-							+
-							(multiplier_from_distance * WEP_CVAR(shockwave, blast_splash_multiplier_distance))
-						)
-					);
-
-				// calculate damage from multiplier: 1 = "highest" damage, 0 = "lowest" edgedamage
-				final_damage =
-					(
-						(WEP_CVAR(shockwave, blast_splash_damage) * multiplier)
-						+
-						(WEP_CVAR(shockwave, blast_splash_edgedamage) * (1 - multiplier))
-					);
-
-				// figure out the direction of force
-				final_force = (w_shotdir * WEP_CVAR(shockwave, blast_splash_force_forwardbias));
-				final_force = normalize(CENTER_OR_VIEWOFS(head) - (attack_hitpos - final_force));
-				//te_lightning2(world, attack_hitpos, (attack_hitpos + (final_force * 200)));
-
-				// now multiply the direction by force units
-				final_force *= (WEP_CVAR(shockwave, blast_splash_force) * multiplier);
-				final_force_z *= WEP_CVAR(shockwave, blast_force_zscale);
-
-				// queue damage with this calculated info
-				if(W_Shockwave_Attack_CheckHit(queue, head, final_force, final_damage)) { queue = min(queue + 1, MAX_SHOCKWAVE_HITS); }
-
-				#ifdef DEBUG_SHOCKWAVE
-				print(sprintf(
-					"SPLASH HIT: multiplier = %f, damage = %f, force = %f... "
-					"multiplier_from_accuracy = %f, multiplier_from_distance = %f.\n",
-					multiplier,
-					final_damage,
-					vlen(final_force),
-					multiplier_from_accuracy,
-					multiplier_from_distance
-				));
-				#endif
-			}
-		}
-		head = head.chain;
-	}
-
-	// cone damage trace
-	head = WarpZone_FindRadius(w_shotorg, WEP_CVAR(shockwave, blast_distance), FALSE);
-	while(head)
-	{
-		if((head != self) && head.takedamage)
-		{
-			// ========================
-			//  BLAST CONE CALCULATION
-			// ========================
-
-			// if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc) 
-			center = CENTER_OR_VIEWOFS(head);
-
-			// find the closest point on the enemy to the center of the attack
-			float ang; // angle between shotdir and h
-			float h; // hypotenuse, which is the distance between attacker to head
-			float a; // adjacent side, which is the distance between attacker and the point on w_shotdir that is closest to head.origin
-			
-			h = vlen(center - self.origin);
-			ang = acos(dotproduct(normalize(center - self.origin), w_shotdir));
-			a = h * cos(ang);
-			// WEAPONTODO: replace with simpler method
-
-			vector nearest_on_line = (w_shotorg + a * w_shotdir);
-			vector nearest_to_attacker = WarpZoneLib_NearestPointOnBox(center + head.mins, center + head.maxs, nearest_on_line);
-
-			if((vlen(head.WarpZone_findradius_dist) <= WEP_CVAR(shockwave, blast_distance)) 
-				&& (W_Shockwave_Attack_IsVisible(head, nearest_on_line, w_shotorg, attack_endpos)))
-			{
-				// calculate importance of distance and accuracy for this attack
-				multiplier_from_accuracy = (1 -
-					W_Shockwave_Attack_CheckSpread(
-						nearest_to_attacker,
-						nearest_on_line,
-						w_shotorg,
-						attack_endpos
-					)
-				);
-				multiplier_from_distance = (1 -
-					(distance_to_hit ?
-						min(1, (vlen(head.WarpZone_findradius_dist) / distance_to_end))
-						:
-						0
-					)
-				);
-				multiplier =
-					max(
-						WEP_CVAR(shockwave, blast_multiplier_min),
-						(
-							(multiplier_from_accuracy * WEP_CVAR(shockwave, blast_multiplier_accuracy))
-							+
-							(multiplier_from_distance * WEP_CVAR(shockwave, blast_multiplier_distance))
-						)
-					);
-
-				// calculate damage from multiplier: 1 = "highest" damage, 0 = "lowest" edgedamage
-				final_damage =
-					(
-						(WEP_CVAR(shockwave, blast_damage) * multiplier)
-						+
-						(WEP_CVAR(shockwave, blast_edgedamage) * (1 - multiplier))
-					);
-
-				// figure out the direction of force
-				final_force = (w_shotdir * WEP_CVAR(shockwave, blast_force_forwardbias));
-				final_force = normalize(center - (nearest_on_line - final_force));
-				//te_lightning2(world, nearest_on_line, (attack_hitpos + (final_force * 200)));
-
-				// now multiply the direction by force units
-				final_force *= (WEP_CVAR(shockwave, blast_force) * multiplier);
-				final_force_z *= WEP_CVAR(shockwave, blast_force_zscale);
-
-				// queue damage with this calculated info
-				if(W_Shockwave_Attack_CheckHit(queue, head, final_force, final_damage)) { queue = min(queue + 1, MAX_SHOCKWAVE_HITS); }
-
-				#ifdef DEBUG_SHOCKWAVE
-				print(sprintf(
-					"BLAST HIT: multiplier = %f, damage = %f, force = %f... "
-					"multiplier_from_accuracy = %f, multiplier_from_distance = %f.\n",
-					multiplier,
-					final_damage,
-					vlen(final_force),
-					multiplier_from_accuracy,
-					multiplier_from_distance
-				));
-				#endif
-			}
-		}
-		head = head.chain;
-	}
-
-	for(i = 1; i <= queue; ++i)
-	{
-		head = shockwave_hit[i-1];
-		final_force = shockwave_hit_force[i-1];
-		final_damage = shockwave_hit_damage[i-1];
-		
-		Damage(
-			head,
-			self,
-			self,
-			final_damage,
-			WEP_SHOCKWAVE,
-			head.origin,
-			final_force
-		);
-
-		if(accuracy_isgooddamage(self.realowner, head))
-		{
-			print("wtf\n");
-			accuracy_add(self.realowner, WEP_SHOCKWAVE, 0, final_damage);
-		}
-
-		#ifdef DEBUG_SHOCKWAVE
-		print(sprintf(
-			"SHOCKWAVE by %s: damage = %f, force = %f.\n",
-			self.netname,
-			final_damage,
-			vlen(final_force)
-		));
-		#endif
-		
-		shockwave_hit[i-1] = world;
-		shockwave_hit_force[i-1] = '0 0 0';
-		shockwave_hit_damage[i-1] = 0;
-	}
-}
-
-float W_Shockwave(float req)
-{
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			if(vlen(self.origin - self.enemy.origin) <= WEP_CVAR(shockwave, melee_range))
-				{ self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE); }
-			else
-				{ self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE); }
-			
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(self.BUTTON_ATCK)
-			{
-				if(time >= self.shockwave_blasttime) // handle refire separately so the secondary can be fired straight after a primary
-				{
-					if(weapon_prepareattack(0, WEP_CVAR(shockwave, blast_animtime)))
-					{
-						W_Shockwave_Attack();
-						self.shockwave_blasttime = time + WEP_CVAR(shockwave, blast_refire) * W_WeaponRateFactor();
-						weapon_thinkf(WFRAME_FIRE1, WEP_CVAR(shockwave, blast_animtime), w_ready);
-					}
-				}
-			}
-			else if(self.BUTTON_ATCK2)
-			{
-				//if(self.clip_load >= 0) // we are not currently reloading
-				if(!self.crouch) // no crouchmelee please
-				if(weapon_prepareattack(1, WEP_CVAR(shockwave, melee_refire)))
-				{
-					// attempt forcing playback of the anim by switching to another anim (that we never play) here...
-					weapon_thinkf(WFRAME_FIRE1, 0, W_Shockwave_Melee);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/uziflash.md3");
-			precache_model("models/weapons/g_shotgun.md3");
-			precache_model("models/weapons/v_shotgun.md3");
-			precache_model("models/weapons/h_shotgun.iqm");
-			precache_sound("misc/itempickup.wav");
-			precache_sound("weapons/lasergun_fire.wav");
-			precache_sound("weapons/shotgun_melee.wav");
-			SHOCKWAVE_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		case WR_CHECKAMMO2:
-		{
-			// shockwave has infinite ammo
-			return TRUE;
-		}
-		case WR_CONFIG:
-		{
-			SHOCKWAVE_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_THINKING_WITH_PORTALS;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_SHOCKWAVE_MURDER_SLAP;
-			else
-				return WEAPON_SHOCKWAVE_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-// WEAPONTODO: add client side settings for these
-#define SW_MAXALPHA 0.5
-#define SW_FADETIME 0.4
-#define SW_DISTTOMIN 200
-void Draw_Shockwave()
-{
-	// fading/removal control
-	float a = bound(0, (SW_MAXALPHA - ((time - self.sw_time) / SW_FADETIME)), SW_MAXALPHA);
-	if(a < ALPHA_MIN_VISIBLE) { remove(self); }
-
-	// WEAPONTODO: save this only once when creating the entity
-	vector sw_color = getcsqcplayercolor(self.sv_entnum); // GetTeamRGB(GetPlayerColor(self.sv_entnum));
-
-	// WEAPONTODO: trace to find what we actually hit
-	vector endpos = (self.sw_shotorg + (self.sw_shotdir * self.sw_distance));
-
-	vectorvectors(self.sw_shotdir);
-	vector right = v_right; // save this for when we do makevectors later
-	vector up = v_up; // save this for when we do makevectors later
-
-	// WEAPONTODO: combine and simplify these calculations
-	vector min_end = ((self.sw_shotorg + (self.sw_shotdir * SW_DISTTOMIN)) + (up * self.sw_spread_min));
-	vector max_end = (endpos + (up * self.sw_spread_max));
-	float spread_to_min = vlen(normalize(min_end - self.sw_shotorg) - self.sw_shotdir);
-	float spread_to_max = vlen(normalize(max_end - min_end) - self.sw_shotdir);
-
-	vector first_min_end = '0 0 0', prev_min_end = '0 0 0', new_min_end = '0 0 0';
-	vector first_max_end = '0 0 0', prev_max_end = '0 0 0', new_max_end = '0 0 0';
-	float new_max_dist, new_min_dist;
-
-	vector deviation, angle = '0 0 0';
-	float counter, divisions = 20;
-	for(counter = 0; counter < divisions; ++counter)
-	{
-		// perfect circle effect lines
-		makevectors('0 360 0' * (0.75 + (counter - 0.5) / divisions));
-		angle_y = v_forward_x;
-		angle_z = v_forward_y;
-
-		// first do the spread_to_min effect
-		deviation = angle * spread_to_min;
-		deviation = ((self.sw_shotdir + (right * deviation_y) + (up * deviation_z)));
-		new_min_dist = SW_DISTTOMIN;
-		new_min_end = (self.sw_shotorg + (deviation * new_min_dist));
-		//te_lightning2(world, new_min_end, self.sw_shotorg);
-
-		// then calculate spread_to_max effect
-		deviation = angle * spread_to_max;
-		deviation = ((self.sw_shotdir + (right * deviation_y) + (up * deviation_z)));
-		new_max_dist = vlen(new_min_end - endpos);
-		new_max_end = (new_min_end + (deviation * new_max_dist));
-		//te_lightning2(world, new_end, prev_min_end);
-		
-
-		if(counter == 0)
-		{
-			first_min_end = new_min_end;
-			first_max_end = new_max_end;
-		}
-
-		if(counter >= 1)
-		{
-			// draw from shot origin to min spread radius
-			R_BeginPolygon("", DRAWFLAG_NORMAL);
-			R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(new_min_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(self.sw_shotorg, '0 0 0', sw_color, a);
-			R_EndPolygon();
-
-			// draw from min spread radius to max spread radius
-			R_BeginPolygon("", DRAWFLAG_NORMAL);
-			R_PolygonVertex(new_min_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(prev_max_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(new_max_end, '0 0 0', sw_color, a);
-			R_EndPolygon();
-		}
-
-		prev_min_end = new_min_end;
-		prev_max_end = new_max_end;
-
-		// last division only
-		if((counter + 1) == divisions)
-		{
-			// draw from shot origin to min spread radius
-			R_BeginPolygon("", DRAWFLAG_NORMAL);
-			R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(first_min_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(self.sw_shotorg, '0 0 0', sw_color, a);
-			R_EndPolygon();
-
-			// draw from min spread radius to max spread radius
-			R_BeginPolygon("", DRAWFLAG_NORMAL);
-			R_PolygonVertex(first_min_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(prev_max_end, '0 0 0', sw_color, a);
-			R_PolygonVertex(first_max_end, '0 0 0', sw_color, a);
-			R_EndPolygon();
-		}
-	}
-}
-
-void Net_ReadShockwaveParticle(void)
-{
-	entity shockwave;
-	shockwave = spawn();
-	shockwave.draw = Draw_Shockwave;
-	
-	shockwave.sw_shotorg_x = ReadCoord(); shockwave.sw_shotorg_y = ReadCoord(); shockwave.sw_shotorg_z = ReadCoord();
-	shockwave.sw_shotdir_x  = ReadCoord(); shockwave.sw_shotdir_y  = ReadCoord(); shockwave.sw_shotdir_z  = ReadCoord();
-
-	shockwave.sw_distance = ReadShort();
-	shockwave.sw_spread_max = ReadByte();
-	shockwave.sw_spread_min = ReadByte();
-
-	shockwave.sv_entnum = ReadByte();
-
-	shockwave.sw_time = time;
-}
-
-float W_Shockwave(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			// handled by Net_ReadShockwaveParticle
-			//vector org2;
-			//org2 = w_org + w_backoff * 2;
-			//pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1);
-			return FALSE;
-		}
-		case WR_INIT:
-		{
-			//precache_sound("weapons/ric1.wav");
-			//precache_sound("weapons/ric2.wav");
-			//precache_sound("weapons/ric3.wav");
-			return FALSE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_shotgun.qc b/qcsrc/common/weapons/w_shotgun.qc
deleted file mode 100644
index 6e500dff2..000000000
--- a/qcsrc/common/weapons/w_shotgun.qc
+++ /dev/null
@@ -1,329 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ SHOTGUN,
-/* function  */ W_Shotgun,
-/* ammotype  */ ammo_none,
-/* impulse   */ 2,
-/* flags     */ WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_LOW,
-/* color     */ '0.5 0.25 0',
-/* modelname */ "shotgun",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairshotgun 0.65",
-/* wepimg    */ "weaponshotgun",
-/* refname   */ "shotgun",
-/* wepname   */ _("Shotgun")
-);
-
-#define SHOTGUN_SETTINGS(w_cvar,w_prop) SHOTGUN_SETTINGS_LIST(w_cvar, w_prop, SHOTGUN, shotgun)
-#define SHOTGUN_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, PRI,  ammo) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, PRI,  bullets) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, force) \
-	w_cvar(id, sn, PRI,  solidpenetration) \
-	w_cvar(id, sn, PRI,  spread) \
-	w_cvar(id, sn, NONE, secondary) \
-	w_cvar(id, sn, SEC,  melee_time) \
-	w_cvar(id, sn, SEC,  melee_no_doubleslap) \
-	w_cvar(id, sn, SEC,  melee_traces) \
-	w_cvar(id, sn, SEC,  melee_swing_up) \
-	w_cvar(id, sn, SEC,  melee_swing_side) \
-	w_cvar(id, sn, SEC,  melee_nonplayerdamage) \
-	w_cvar(id, sn, SEC,  melee_multihit) \
-	w_cvar(id, sn, SEC,  melee_delay) \
-	w_cvar(id, sn, SEC,  melee_range) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-SHOTGUN_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_shotgun(void) { weapon_defaultspawnfunc(WEP_SHOTGUN); }
-
-void W_Shotgun_Attack(void)
-{
-	float	sc;
-	entity flash;
-
-	W_DecreaseAmmo(WEP_CVAR_PRI(shotgun, ammo));
-
-	W_SetupShot(self, TRUE, 5, "weapons/shotgun_fire.wav", CH_WEAPON_A, WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
-	for(sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1)
-		fireBullet(w_shotorg, w_shotdir, WEP_CVAR_PRI(shotgun, spread), WEP_CVAR_PRI(shotgun, solidpenetration), WEP_CVAR_PRI(shotgun, damage), WEP_CVAR_PRI(shotgun, force), WEP_SHOTGUN, 0);
-
-	pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, WEP_CVAR_PRI(shotgun, ammo));
-
-	// casing code
-	if(autocvar_g_casings >= 1)
-		for(sc = 0;sc < WEP_CVAR_PRI(shotgun, ammo);sc = sc + 1)
-			SpawnCasing(((random() * 50 + 50) * v_right) - (v_forward * (random() * 25 + 25)) - ((random() * 5 - 30) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 1, self);
-
-	// muzzle flash for 1st person view
-	flash = spawn();
-	setmodel(flash, "models/uziflash.md3"); // precision set below
-	flash.think = SUB_Remove;
-	flash.nextthink = time + 0.06;
-	flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
-	W_AttachToShotorg(flash, '5 0 0');
-}
-
-.float swing_prev;
-.entity swing_alreadyhit;
-void W_Shotgun_Melee_Think(void)
-{
-	// declarations
-	float i, f, swing, swing_factor, swing_damage, meleetime, is_player;
-	entity target_victim;
-	vector targpos;
-
-	if(!self.cnt) // set start time of melee
-	{
-		self.cnt = time;
-		W_PlayStrengthSound(self.realowner);
-	}
-
-	makevectors(self.realowner.v_angle); // update values for v_* vectors
-
-	// calculate swing percentage based on time
-	meleetime = WEP_CVAR_SEC(shotgun, melee_time) * W_WeaponRateFactor();
-	swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10);
-	f = ((1 - swing) * WEP_CVAR_SEC(shotgun, melee_traces));
-
-	// check to see if we can still continue, otherwise give up now
-	if((self.realowner.deadflag != DEAD_NO) && WEP_CVAR_SEC(shotgun, melee_no_doubleslap))
-	{
-		remove(self);
-		return;
-	}
-
-	// if okay, perform the traces needed for this frame
-	for(i=self.swing_prev; i < f; ++i)
-	{
-		swing_factor = ((1 - (i / WEP_CVAR_SEC(shotgun, melee_traces))) * 2 - 1);
-
-		targpos = (self.realowner.origin + self.realowner.view_ofs
-			+ (v_forward * WEP_CVAR_SEC(shotgun, melee_range))
-			+ (v_up * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_up))
-			+ (v_right * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_side)));
-
-		WarpZone_traceline_antilag(self, self.realowner.origin + self.realowner.view_ofs, targpos, FALSE, self, ANTILAG_LATENCY(self.realowner));
-
-		// draw lightning beams for debugging
-		//te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5);
-		//te_customflash(targpos, 40,  2, '1 1 1');
-
-		is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || (trace_ent.flags & FL_MONSTER));
-
-		if((trace_fraction < 1) // if trace is good, apply the damage and remove self
-			&& (trace_ent.takedamage == DAMAGE_AIM)
-			&& (trace_ent != self.swing_alreadyhit)
-			&& (is_player || WEP_CVAR_SEC(shotgun, melee_nonplayerdamage)))
-		{
-			target_victim = trace_ent; // so it persists through other calls
-
-			if(is_player) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught.
-				swing_damage = (WEP_CVAR_SEC(shotgun, damage) * min(1, swing_factor + 1));
-			else
-				swing_damage = (WEP_CVAR_SEC(shotgun, melee_nonplayerdamage) * min(1, swing_factor + 1));
-
-			//print(strcat(self.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n"));
-
-			Damage(target_victim, self.realowner, self.realowner,
-				swing_damage, WEP_SHOTGUN | HITTYPE_SECONDARY,
-				self.realowner.origin + self.realowner.view_ofs,
-				v_forward * WEP_CVAR_SEC(shotgun, force));
-
-			if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_SHOTGUN, 0, swing_damage); }
-
-			// draw large red flash for debugging
-			//te_customflash(targpos, 200, 2, '15 0 0');
-
-			if(WEP_CVAR_SEC(shotgun, melee_multihit)) // allow multiple hits with one swing, but not against the same player twice.
-			{
-				self.swing_alreadyhit = target_victim;
-				continue; // move along to next trace
-			}
-			else
-			{
-				remove(self);
-				return;
-			}
-		}
-	}
-
-	if(time >= self.cnt + meleetime)
-	{
-		// melee is finished
-		remove(self);
-		return;
-	}
-	else
-	{
-		// set up next frame
-		self.swing_prev = i;
-		self.nextthink = time;
-	}
-}
-
-void W_Shotgun_Attack2(void)
-{
-	sound(self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTEN_NORM);
-	weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(shotgun, animtime), w_ready);
-
-	entity meleetemp;
-	meleetemp = spawn();
-	meleetemp.realowner = self;
-	meleetemp.think = W_Shotgun_Melee_Think;
-	meleetemp.nextthink = time + WEP_CVAR_SEC(shotgun, melee_delay) * W_WeaponRateFactor();
-	W_SetupShot_Range(self, TRUE, 0, "", 0, WEP_CVAR_SEC(shotgun, damage), WEP_CVAR_SEC(shotgun, melee_range));
-}
-
-.float shotgun_primarytime;
-
-float W_Shotgun(float req)
-{
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			if(vlen(self.origin-self.enemy.origin) <= WEP_CVAR_SEC(shotgun, melee_range))
-				self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE);
-			else
-				self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
-
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(WEP_CVAR(shotgun, reload_ammo) && self.clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
-			{
-				// don't force reload an empty shotgun if its melee attack is active
-				if(!WEP_CVAR(shotgun, secondary))
-					WEP_ACTION(self.weapon, WR_RELOAD);
-			}
-			else
-			{
-				if(self.BUTTON_ATCK)
-				{
-					if(time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
-					{
-						if(weapon_prepareattack(0, WEP_CVAR_PRI(shotgun, animtime)))
-						{
-							W_Shotgun_Attack();
-							self.shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor();
-							weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
-						}
-					}
-				}
-			}
-			if(self.clip_load >= 0) // we are not currently reloading
-			if(!self.crouch) // no crouchmelee please
-			if(self.BUTTON_ATCK2 && WEP_CVAR(shotgun, secondary))
-			if(weapon_prepareattack(1, WEP_CVAR_SEC(shotgun, refire)))
-			{
-				// attempt forcing playback of the anim by switching to another anim (that we never play) here...
-				weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2);
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/uziflash.md3");
-			precache_model("models/weapons/g_shotgun.md3");
-			precache_model("models/weapons/v_shotgun.md3");
-			precache_model("models/weapons/h_shotgun.iqm");
-			precache_sound("misc/itempickup.wav");
-			precache_sound("weapons/shotgun_fire.wav");
-			precache_sound("weapons/shotgun_melee.wav");
-			SHOTGUN_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_SETUP:
-		{
-			self.ammo_field = ammo_none;
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		case WR_CHECKAMMO2:
-		{
-			// shotgun has infinite ammo
-			return TRUE;
-		}
-		case WR_CONFIG:
-		{
-			SHOTGUN_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(WEP_CVAR_PRI(shotgun, ammo), "weapons/reload.wav"); // WEAPONTODO
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_THINKING_WITH_PORTALS;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_SHOTGUN_MURDER_SLAP;
-			else
-				return WEAPON_SHOTGUN_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-.float prevric;
-float W_Shotgun(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 2;
-			pointparticles(particleeffectnum("shotgun_impact"), org2, w_backoff * 1000, 1);
-			if(!w_issilent && time - self.prevric > 0.25)
-			{
-				if(w_random < 0.0165)
-					sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_NORM);
-				else if(w_random < 0.033)
-					sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTEN_NORM);
-				else if(w_random < 0.05)
-					sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTEN_NORM);
-				self.prevric = time;
-			}
-
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/ric1.wav");
-			precache_sound("weapons/ric2.wav");
-			precache_sound("weapons/ric3.wav");
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_tuba.qc b/qcsrc/common/weapons/w_tuba.qc
deleted file mode 100644
index e450c5bd0..000000000
--- a/qcsrc/common/weapons/w_tuba.qc
+++ /dev/null
@@ -1,508 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ TUBA,
-/* function  */ W_Tuba,
-/* ammotype  */ ammo_none,
-/* impulse   */ 1,
-/* flags     */ WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH,
-/* rating    */ BOT_PICKUP_RATING_MID,
-/* color     */ '0 1 0',
-/* modelname */ "tuba",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairtuba",
-/* wepimg    */ "weapontuba",
-/* refname   */ "tuba",
-/* xgettext:no-c-format */
-/* wepname   */ _("@!#%'n Tuba")
-);
-
-#define TUBA_SETTINGS(w_cvar,w_prop) TUBA_SETTINGS_LIST(w_cvar, w_prop, TUBA, tuba)
-#define TUBA_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, NONE, animtime) \
-	w_cvar(id, sn, NONE, attenuation) \
-	w_cvar(id, sn, NONE, damage) \
-	w_cvar(id, sn, NONE, edgedamage) \
-	w_cvar(id, sn, NONE, force) \
-	w_cvar(id, sn, NONE, radius) \
-	w_cvar(id, sn, NONE, refire) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-TUBA_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.entity tuba_note;
-.float tuba_smoketime;
-.float tuba_instrument;
-
-#define MAX_TUBANOTES 32
-.float tuba_lastnotes_last;
-.float tuba_lastnotes_cnt; // over
-.vector tuba_lastnotes[MAX_TUBANOTES];
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_tuba(void) { weapon_defaultspawnfunc(WEP_TUBA); }
-
-float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo)
-{
-	float i, j, mmin, mmax, nolength;
-	float n = tokenize_console(melody);
-	if(n > pl.tuba_lastnotes_cnt)
-		return FALSE;
-	float pitchshift = 0;
-
-	if(instrument >= 0)
-		if(pl.tuba_instrument != instrument)
-			return FALSE;
-
-	// verify notes...
-	nolength = FALSE;
-	for(i = 0; i < n; ++i)
-	{
-		vector v = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]);
-		float ai = stof(argv(n - i - 1));
-		float np = floor(ai);
-		if(ai == np)
-			nolength = TRUE;
-		// n counts the last played notes BACKWARDS
-		// _x is start
-		// _y is end
-		// _z is note pitch
-		if(ignorepitch && i == 0)
-		{
-			pitchshift = np - v_z;
-		}
-		else
-		{
-			if(v_z + pitchshift != np)
-				return FALSE;
-		}
-	}
-
-	// now we know the right NOTES were played
-	if(!nolength)
-	{
-		// verify rhythm...
-		float ti = 0;
-		if(maxtempo > 0)
-			mmin = 240 / maxtempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec
-		else
-			mmin = 0;
-		if(mintempo > 0)
-			mmax = 240 / mintempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec
-		else
-			mmax = 240; // you won't try THAT hard... (tempo 1)
-		//printf("initial tempo rules: %f %f\n", mmin, mmax);
-
-		for(i = 0; i < n; ++i)
-		{
-			vector vi = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]);
-			float ai = stof(argv(n - i - 1));
-			ti -= 1 / (ai - floor(ai));
-			float tj = ti;
-			for(j = i+1; j < n; ++j)
-			{
-				vector vj = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - j + MAX_TUBANOTES, MAX_TUBANOTES)]);
-				float aj = stof(argv(n - j - 1));
-				tj -= (aj - floor(aj));
-
-				// note i should be at m*ti+b
-				// note j should be at m*tj+b
-				// so:
-				// we have a LINE l, so that
-				// vi_x <= l(ti) <= vi_y
-				// vj_x <= l(tj) <= vj_y
-				// what is m?
-
-				// vi_x <= vi_y <= vj_x <= vj_y
-				// ti <= tj
-				//printf("first note: %f to %f, should be %f\n", vi_x, vi_y, ti);
-				//printf("second note: %f to %f, should be %f\n", vj_x, vj_y, tj);
-				//printf("m1 = %f\n", (vi_x - vj_y) / (ti - tj));
-				//printf("m2 = %f\n", (vi_y - vj_x) / (ti - tj));
-				mmin = max(mmin, (vi_x - vj_y) / (ti - tj)); // lower bound
-				mmax = min(mmax, (vi_y - vj_x) / (ti - tj)); // upper bound
-			}
-		}
-
-		if(mmin > mmax) // rhythm fail
-			return FALSE;
-	}
-
-	pl.tuba_lastnotes_cnt = 0;
-
-	return TRUE;
-}
-
-void W_Tuba_NoteOff(void)
-{
-	// we have a note:
-	//   on: self.spawnshieldtime
-	//   off: time
-	//   note: self.cnt
-	if(self.owner.tuba_note == self)
-	{
-		self.owner.tuba_lastnotes_last = mod(self.owner.tuba_lastnotes_last + 1, MAX_TUBANOTES);
-		self.owner.(tuba_lastnotes[self.owner.tuba_lastnotes_last]) = eX * self.spawnshieldtime + eY * time + eZ * self.cnt;
-		self.owner.tuba_note = world;
-		self.owner.tuba_lastnotes_cnt = bound(0, self.owner.tuba_lastnotes_cnt + 1, MAX_TUBANOTES);
-
-		string s;
-		s = trigger_magicear_processmessage_forallears(self.owner, 0, world, string_null);
-		if(s != "")
-		{
-			// simulate a server message
-			switch(self.tuba_instrument)
-			{
-				default:
-				case 0: // Tuba
-					bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Tuba: ^7", s, "\n"));
-					break;
-				case 1:
-					bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Accordeon: ^7", s, "\n"));
-					break;
-				case 2:
-					bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Klein Bottle: ^7", s, "\n"));
-					break;
-			}
-		}
-	}
-	remove(self);
-}
-
-float W_Tuba_GetNote(entity pl, float hittype)
-{
-	float note;
-	float movestate;
-	movestate = 5;
-	if(pl.movement_x < 0) movestate -= 3;
-	if(pl.movement_x > 0) movestate += 3;
-	if(pl.movement_y < 0) movestate -= 1;
-	if(pl.movement_y > 0) movestate += 1;
-#ifdef GMQCC
-	note = 0;
-#endif
-	switch(movestate)
-	{
-	// layout: originally I wanted
-	//   eb e  e#=f
-	//   B  c  d
-	//   Gb G  G#
-	// but then you only use forward and right key. So to make things more
-	// interesting, I swapped B with e#. Har har har...
-	//   eb e  B
-	// f=e# c  d
-	//   Gb G  G#
-		case 1: note = -6; break; // Gb
-		case 2: note = -5; break; // G
-		case 3: note = -4; break; // G#
-		case 4: note = +5; break; // e#
-		default:
-		case 5: note =  0; break; // c
-		case 6: note = +2; break; // d
-		case 7: note = +3; break; // eb
-		case 8: note = +4; break; // e
-		case 9: note = -1; break; // B
-	}
-	if(pl.BUTTON_CROUCH)
-		note -= 12;
-	if(pl.BUTTON_JUMP)
-		note += 12;
-	if(hittype & HITTYPE_SECONDARY)
-		note += 7;
-
-	// we support two kinds of tubas, those tuned in Eb and those tuned in C
-	// kind of tuba currently is player slot number, or team number if in
-	// teamplay
-	// that way, holes in the range of notes are "plugged"
-	if(teamplay)
-	{
-		if(pl.team == NUM_TEAM_2 || pl.team == NUM_TEAM_4)
-			note += 3;
-	}
-	else
-	{
-		if(pl.clientcolors & 1)
-			note += 3;
-	}
-
-	// total range of notes:
-	//                       0
-	//                 ***  ** ****
-	//                        ***  ** ****
-	//     ***  ** ****
-	//            ***  ** ****
-	//     ***  ********************* ****
-	//     -18.........................+12
-	//        ***  ********************* ****
-	//     -18............................+15
-	//     with jump: ... +24
-	//     ... +27
-	return note;
-}
-
-float W_Tuba_NoteSendEntity(entity to, float sf)
-{
-	float f;
-
-	msg_entity = to;
-	if(!sound_allowed(MSG_ONE, self.realowner))
-		return FALSE;
-
-	WriteByte(MSG_ENTITY, ENT_CLIENT_TUBANOTE);
-	WriteByte(MSG_ENTITY, sf);
-	if(sf & 1)
-	{
-		WriteChar(MSG_ENTITY, self.cnt);
-		f = 0;
-		if(self.realowner != to)
-			f |= 1;
-		f |= 2 * self.tuba_instrument;
-		WriteByte(MSG_ENTITY, f);
-	}
-	if(sf & 2)
-	{
-		WriteCoord(MSG_ENTITY, self.origin_x);
-		WriteCoord(MSG_ENTITY, self.origin_y);
-		WriteCoord(MSG_ENTITY, self.origin_z);
-	}
-	return TRUE;
-}
-
-void W_Tuba_NoteThink(void)
-{
-	float dist_mult;
-	float vol0, vol1;
-	vector dir0, dir1;
-	vector v;
-	entity e;
-	if(time > self.teleport_time)
-	{
-		W_Tuba_NoteOff();
-		return;
-	}
-	self.nextthink = time;
-	dist_mult = WEP_CVAR(tuba, attenuation) / autocvar_snd_soundradius;
-	FOR_EACH_REALCLIENT(e)
-	if(e != self.realowner)
-	{
-		v = self.origin - (e.origin + e.view_ofs);
-		vol0 = max(0, 1 - vlen(v) * dist_mult);
-		dir0 = normalize(v);
-		v = self.realowner.origin - (e.origin + e.view_ofs);
-		vol1 = max(0, 1 - vlen(v) * dist_mult);
-		dir1 = normalize(v);
-		if(fabs(vol0 - vol1) > 0.005) // 0.5 percent change in volume
-		{
-			setorigin(self, self.realowner.origin);
-			self.SendFlags |= 2;
-			break;
-		}
-		if(dir0 * dir1 < 0.9994) // 2 degrees change in angle
-		{
-			setorigin(self, self.realowner.origin);
-			self.SendFlags |= 2;
-			break;
-		}
-	}
-}
-
-void W_Tuba_NoteOn(float hittype)
-{
-	vector o;
-	float n;
-
-	W_SetupShot(self, FALSE, 2, "", 0, WEP_CVAR(tuba, damage));
-
-	n = W_Tuba_GetNote(self, hittype);
-
-	hittype = 0;
-	if(self.tuba_instrument & 1)
-		hittype |= HITTYPE_SECONDARY;
-	if(self.tuba_instrument & 2)
-		hittype |= HITTYPE_BOUNCE;
-
-	if(self.tuba_note)
-	{
-		if(self.tuba_note.cnt != n || self.tuba_note.tuba_instrument != self.tuba_instrument)
-		{
-			entity oldself = self;
-			self = self.tuba_note;
-			W_Tuba_NoteOff();
-			self = oldself;
-		}
-	}
-
-	if(!self.tuba_note)
-	{
-		self.tuba_note = spawn();
-		self.tuba_note.owner = self.tuba_note.realowner = self;
-		self.tuba_note.cnt = n;
-		self.tuba_note.tuba_instrument = self.tuba_instrument;
-		self.tuba_note.think = W_Tuba_NoteThink;
-		self.tuba_note.nextthink = time;
-		self.tuba_note.spawnshieldtime = time;
-		Net_LinkEntity(self.tuba_note, FALSE, 0, W_Tuba_NoteSendEntity);
-	}
-
-	self.tuba_note.teleport_time = time + WEP_CVAR(tuba, refire) * 2 * W_WeaponRateFactor(); // so it can get prolonged safely
-
-	//sound(self, c, TUBA_NOTE(n), bound(0, VOL_BASE * cvar("g_balance_tuba_volume"), 1), autocvar_g_balance_tuba_attenuation);
-	RadiusDamage(self, self, WEP_CVAR(tuba, damage), WEP_CVAR(tuba, edgedamage), WEP_CVAR(tuba, radius), world, world, WEP_CVAR(tuba, force), hittype | WEP_TUBA, world);
-
-	o = gettaginfo(self.exteriorweaponentity, 0);
-	if(time > self.tuba_smoketime)
-	{
-		pointparticles(particleeffectnum("smoke_ring"), o + v_up * 45 + v_right * -6 + v_forward * 8, v_up * 100, 1);
-		self.tuba_smoketime = time + 0.25;
-	}
-}
-
-float W_Tuba(float req)
-{
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			// bots cannot play the Tuba well yet
-			// I think they should start with the recorder first
-			if(vlen(self.origin - self.enemy.origin) < WEP_CVAR(tuba, radius))
-			{
-				if(random() > 0.5)
-					self.BUTTON_ATCK = 1;
-				else
-					self.BUTTON_ATCK2 = 1;
-			}
-			
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(self.BUTTON_ATCK)
-			if(weapon_prepareattack(0, WEP_CVAR(tuba, refire)))
-			{
-				W_Tuba_NoteOn(0);
-				//weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_tuba_animtime, w_ready);
-				weapon_thinkf(WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
-			}
-			if(self.BUTTON_ATCK2)
-			if(weapon_prepareattack(1, WEP_CVAR(tuba, refire)))
-			{
-				W_Tuba_NoteOn(HITTYPE_SECONDARY);
-				//weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_tuba_animtime, w_ready);
-				weapon_thinkf(WFRAME_IDLE, WEP_CVAR(tuba, animtime), w_ready);
-			}
-			if(self.tuba_note)
-			{
-				if(!self.BUTTON_ATCK && !self.BUTTON_ATCK2)
-				{
-					entity oldself = self;
-					self = self.tuba_note;
-					W_Tuba_NoteOff();
-					self = oldself;
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/weapons/g_tuba.md3");
-			precache_model("models/weapons/v_tuba.md3");
-			precache_model("models/weapons/h_tuba.iqm");
-			precache_model("models/weapons/v_akordeon.md3");
-			precache_model("models/weapons/h_akordeon.iqm");
-			precache_model("models/weapons/v_kleinbottle.md3");
-			precache_model("models/weapons/h_kleinbottle.iqm");
-			TUBA_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_SETUP:
-		{
-			self.ammo_field = ammo_none;
-			self.tuba_instrument = 0;
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			// switch to alternate instruments :)
-			if(self.weaponentity.state == WS_READY)
-			{
-				switch(self.tuba_instrument)
-				{
-					case 0:
-						self.tuba_instrument = 1;
-						self.weaponname = "akordeon";
-						break;
-					case 1:
-						self.tuba_instrument = 2;
-						self.weaponname = "kleinbottle";
-						break;
-					case 2:
-						self.tuba_instrument = 0;
-						self.weaponname = "tuba";
-						break;
-				}
-				W_SetupShot(self, FALSE, 0, "", 0, 0);
-				pointparticles(particleeffectnum("teleport"), w_shotorg, '0 0 0', 1);
-				self.weaponentity.state = WS_INUSE;
-				weapon_thinkf(WFRAME_RELOAD, 0.5, w_ready);
-			}
-			
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		case WR_CHECKAMMO2:
-		{
-			return TRUE; // tuba has infinite ammo
-		}
-		case WR_CONFIG:
-		{
-			TUBA_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_BOUNCE)
-				return WEAPON_KLEINBOTTLE_SUICIDE;
-			else if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_ACCORDEON_SUICIDE;
-			else
-				return WEAPON_TUBA_SUICIDE;
-		}
-		case WR_KILLMESSAGE:
-		{
-			if(w_deathtype & HITTYPE_BOUNCE)
-				return WEAPON_KLEINBOTTLE_MURDER;
-			else if(w_deathtype & HITTYPE_SECONDARY)
-				return WEAPON_ACCORDEON_MURDER;
-			else
-				return WEAPON_TUBA_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Tuba(float req)
-{
-	// nothing to do here; particles of tuba are handled differently
-	// WEAPONTODO
-
-	switch(req)
-	{
-		case WR_ZOOMRETICLE:
-		{
-			// no weapon specific image for this weapon
-			return FALSE;
-		}
-	}
-
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_vaporizer.qc b/qcsrc/common/weapons/w_vaporizer.qc
deleted file mode 100644
index 7ad1e1dd8..000000000
--- a/qcsrc/common/weapons/w_vaporizer.qc
+++ /dev/null
@@ -1,299 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ VAPORIZER,
-/* function  */ W_Vaporizer,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 7,
-/* flags     */ WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_FLAG_SUPERWEAPON | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '0.5 1 1',
-/* modelname */ "minstanex",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairminstanex 0.4",
-/* wepimg    */ "weaponminstanex",
-/* refname   */ "vaporizer",
-/* wepname   */ _("Vaporizer")
-);
-
-#define VAPORIZER_SETTINGS(w_cvar,w_prop) VAPORIZER_SETTINGS_LIST(w_cvar, w_prop, VAPORIZER, vaporizer)
-#define VAPORIZER_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, PRI, ammo) \
-	w_cvar(id, sn, PRI, animtime) \
-	w_cvar(id, sn, PRI, refire) \
-	w_cvar(id, sn, SEC, ammo) \
-	w_cvar(id, sn, SEC, animtime) \
-	w_cvar(id, sn, SEC, damage) \
-	w_cvar(id, sn, SEC, delay) \
-	w_cvar(id, sn, SEC, edgedamage) \
-	w_cvar(id, sn, SEC, force) \
-	w_cvar(id, sn, SEC, lifetime) \
-	w_cvar(id, sn, SEC, radius) \
-	w_cvar(id, sn, SEC, refire) \
-	w_cvar(id, sn, SEC, shotangle) \
-	w_cvar(id, sn, SEC, speed) \
-	w_cvar(id, sn, SEC, spread) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-VAPORIZER_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-.float vaporizer_lasthit;
-.float jump_interval;
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_vaporizer(void) { weapon_defaultspawnfunc(WEP_VAPORIZER); }
-void spawnfunc_weapon_minstanex(void) { spawnfunc_weapon_vaporizer(); }
-
-void W_Vaporizer_Attack(void)
-{
-	float flying;
-	flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
-
-	W_SetupShot(self, TRUE, 0, "weapons/minstanexfire.wav", CH_WEAPON_A, 10000);
-
-	yoda = 0;
-	damage_goodhits = 0;
-	FireRailgunBullet(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, 10000, 800, 0, 0, 0, 0, WEP_VAPORIZER);
-
-	if(yoda && flying)
-		Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
-	if(damage_goodhits && self.vaporizer_lasthit)
-	{
-		Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
-		damage_goodhits = 0; // only every second time
-	}
-
-	self.vaporizer_lasthit = damage_goodhits;
-
-	pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
-
-	// teamcolor / hit beam effect
-	vector v;
-	v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
-	switch(self.team)
-	{
-		case NUM_TEAM_1:   // Red
-			if(damage_goodhits)
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, v);
-			else
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, v);
-			break;
-		case NUM_TEAM_2:   // Blue
-			if(damage_goodhits)
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, v);
-			else
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, v);
-			break;
-		case NUM_TEAM_3:   // Yellow
-			if(damage_goodhits)
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, v);
-			else
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, v);
-			break;
-		case NUM_TEAM_4:   // Pink
-			if(damage_goodhits)
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, v);
-			else
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, v);
-			break;
-		default:
-			if(damage_goodhits)
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3_HIT"), w_shotorg, v);
-			else
-				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, v);
-			break;
-	}
-	
-	W_DecreaseAmmo(((g_minstagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)));
-}
-
-float W_Vaporizer(float req)
-{
-	float ammo_amount;
-	float vaporizer_ammo;
-
-	// now multiple WR_s use this
-	vaporizer_ammo = ((g_minstagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
-
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			if(self.WEP_AMMO(VAPORIZER) > 0)
-				self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE);
-			else
-				self.BUTTON_ATCK2 = bot_aim(WEP_CVAR_SEC(vaporizer, speed), 0, WEP_CVAR_SEC(vaporizer, lifetime), FALSE); // WEAPONTODO: replace with proper vaporizer cvars
-				
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			// if the laser uses load, we also consider its ammo for reloading
-			if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && self.clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-			else if(WEP_CVAR(vaporizer, reload_ammo) && self.clip_load < vaporizer_ammo) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-			else if(self.BUTTON_ATCK)
-			{
-				if(weapon_prepareattack(0, WEP_CVAR_PRI(vaporizer, refire)))
-				{
-					W_Vaporizer_Attack();
-					weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(vaporizer, animtime), w_ready);
-				}
-			}
-			else if(self.BUTTON_ATCK2)
-			{
-				if(self.jump_interval <= time)
-				if(weapon_prepareattack(1, -1))
-				{
-					// handle refire manually, so that primary and secondary can be fired without conflictions (important for minstagib)
-					self.jump_interval = time + WEP_CVAR_SEC(vaporizer, refire) * W_WeaponRateFactor();
-					
-					// decrease ammo for the laser?
-					if(WEP_CVAR_SEC(vaporizer, ammo))
-						W_DecreaseAmmo(WEP_CVAR_SEC(vaporizer, ammo));
-
-					// ugly minstagib hack to reuse the fire mode of the laser
-					W_Blaster_Attack(
-						WEP_VAPORIZER | HITTYPE_SECONDARY,
-						WEP_CVAR_SEC(vaporizer, shotangle),
-						WEP_CVAR_SEC(vaporizer, damage),
-						WEP_CVAR_SEC(vaporizer, edgedamage),
-						WEP_CVAR_SEC(vaporizer, radius),
-						WEP_CVAR_SEC(vaporizer, force),
-						WEP_CVAR_SEC(vaporizer, speed),
-						WEP_CVAR_SEC(vaporizer, spread),
-						WEP_CVAR_SEC(vaporizer, delay),
-						WEP_CVAR_SEC(vaporizer, lifetime)
-					);
-					
-					// now do normal refire
-					weapon_thinkf(WFRAME_FIRE2, WEP_CVAR_SEC(vaporizer, animtime), w_ready);
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/nexflash.md3");
-			precache_model("models/weapons/g_minstanex.md3");
-			precache_model("models/weapons/v_minstanex.md3");
-			precache_model("models/weapons/h_minstanex.iqm");
-			precache_sound("weapons/minstanexfire.wav");
-			precache_sound("weapons/nexwhoosh1.wav");
-			precache_sound("weapons/nexwhoosh2.wav");
-			precache_sound("weapons/nexwhoosh3.wav");
-			//W_Blaster(WR_INIT); // Samual: Is this really the proper thing to do? Didn't we already run this previously?
-			VAPORIZER_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_SETUP:
-		{
-			self.ammo_field = WEP_AMMO(VAPORIZER);
-			self.vaporizer_lasthit = 0;
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			ammo_amount = self.WEP_AMMO(VAPORIZER) >= vaporizer_ammo;
-			ammo_amount += self.(weapon_load[WEP_VAPORIZER]) >= vaporizer_ammo;
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			if(!WEP_CVAR_SEC(vaporizer, ammo))
-				return TRUE;
-			ammo_amount = self.WEP_AMMO(VAPORIZER) >= WEP_CVAR_SEC(vaporizer, ammo);
-			ammo_amount += self.(weapon_load[WEP_VAPORIZER]) >= WEP_CVAR_SEC(vaporizer, ammo);
-			return ammo_amount;
-		}
-		case WR_CONFIG:
-		{
-			VAPORIZER_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RESETPLAYER:
-		{
-			self.vaporizer_lasthit = 0;
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			float used_ammo;
-			if(WEP_CVAR_SEC(vaporizer, ammo))
-				used_ammo = min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo));
-			else
-				used_ammo = vaporizer_ammo;
-
-			W_Reload(used_ammo, "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_THINKING_WITH_PORTALS;
-		}
-		case WR_KILLMESSAGE:
-		{
-			return WEAPON_VAPORIZER_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-float W_Vaporizer(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 6;
-			if(w_deathtype & HITTYPE_SECONDARY)
-			{
-				pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1);
-				if(!w_issilent) { sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTN_NORM); }
-			}
-			else
-			{
-				pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1);
-				if(!w_issilent) { sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM); }
-			}
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/laserimpact.wav");
-			precache_sound("weapons/neximpact.wav");
-			if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
-			{
-				precache_pic("gfx/reticle_nex");
-			}
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			if(button_zoom || zoomscript_caught)
-			{
-				reticle_image = "gfx/reticle_nex";
-				return TRUE;
-			}
-			else
-			{
-				// no weapon specific image for this weapon
-				return FALSE;
-			}
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/w_vortex.qc b/qcsrc/common/weapons/w_vortex.qc
deleted file mode 100644
index 6512d0430..000000000
--- a/qcsrc/common/weapons/w_vortex.qc
+++ /dev/null
@@ -1,341 +0,0 @@
-#ifdef REGISTER_WEAPON
-REGISTER_WEAPON(
-/* WEP_##id  */ VORTEX,
-/* function  */ W_Vortex,
-/* ammotype  */ ammo_cells,
-/* impulse   */ 7,
-/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
-/* rating    */ BOT_PICKUP_RATING_HIGH,
-/* color     */ '0.5 1 1',
-/* modelname */ "nex",
-/* simplemdl */ "foobar",
-/* crosshair */ "gfx/crosshairnex 0.65",
-/* wepimg    */ "weaponnex",
-/* refname   */ "vortex",
-/* wepname   */ _("Vortex")
-);
-
-#define VORTEX_SETTINGS(w_cvar,w_prop) VORTEX_SETTINGS_LIST(w_cvar, w_prop, VORTEX, vortex)
-#define VORTEX_SETTINGS_LIST(w_cvar,w_prop,id,sn) \
-	w_cvar(id, sn, BOTH, ammo) \
-	w_cvar(id, sn, BOTH, animtime) \
-	w_cvar(id, sn, BOTH, damage) \
-	w_cvar(id, sn, BOTH, force) \
-	w_cvar(id, sn, BOTH, damagefalloff_mindist) \
-	w_cvar(id, sn, BOTH, damagefalloff_maxdist) \
-	w_cvar(id, sn, BOTH, damagefalloff_halflife) \
-	w_cvar(id, sn, BOTH, damagefalloff_forcehalflife) \
-	w_cvar(id, sn, BOTH, refire) \
-	w_cvar(id, sn, NONE, charge) \
-	w_cvar(id, sn, NONE, charge_mindmg) \
-	w_cvar(id, sn, NONE, charge_shot_multiplier) \
-	w_cvar(id, sn, NONE, charge_animlimit) \
-	w_cvar(id, sn, NONE, charge_limit) \
-	w_cvar(id, sn, NONE, charge_rate) \
-	w_cvar(id, sn, NONE, charge_rot_rate) \
-	w_cvar(id, sn, NONE, charge_rot_pause) \
-	w_cvar(id, sn, NONE, charge_start) \
-	w_cvar(id, sn, NONE, charge_minspeed) \
-	w_cvar(id, sn, NONE, charge_maxspeed) \
-	w_cvar(id, sn, NONE, charge_velocity_rate) \
-	w_cvar(id, sn, NONE, secondary) \
-	w_cvar(id, sn, SEC,  chargepool) \
-	w_cvar(id, sn, SEC,  chargepool_regen) \
-	w_cvar(id, sn, SEC,  chargepool_pause_regen) \
-	w_prop(id, sn, float,  reloading_ammo, reload_ammo) \
-	w_prop(id, sn, float,  reloading_time, reload_time) \
-	w_prop(id, sn, float,  switchdelay_raise, switchdelay_raise) \
-	w_prop(id, sn, float,  switchdelay_drop, switchdelay_drop) \
-	w_prop(id, sn, string, weaponreplace, weaponreplace) \
-	w_prop(id, sn, float,  weaponstart, weaponstart) \
-	w_prop(id, sn, float,  weaponstartoverride, weaponstartoverride) \
-	w_prop(id, sn, float,  weaponthrowable, weaponthrowable)
-
-#ifdef SVQC
-VORTEX_SETTINGS(WEP_ADD_CVAR, WEP_ADD_PROP)
-#endif
-#else
-#ifdef SVQC
-void spawnfunc_weapon_vortex(void) { weapon_defaultspawnfunc(WEP_VORTEX); }
-void spawnfunc_weapon_nex(void) { spawnfunc_weapon_vortex(); }
-
-void SendCSQCVortexBeamParticle(float charge) {
-	vector v;
-	v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
-	WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
-	WriteByte(MSG_BROADCAST, TE_CSQC_VORTEXBEAMPARTICLE);
-	WriteCoord(MSG_BROADCAST, w_shotorg_x);
-	WriteCoord(MSG_BROADCAST, w_shotorg_y);
-	WriteCoord(MSG_BROADCAST, w_shotorg_z);
-	WriteCoord(MSG_BROADCAST, v_x);
-	WriteCoord(MSG_BROADCAST, v_y);
-	WriteCoord(MSG_BROADCAST, v_z);
-	WriteByte(MSG_BROADCAST, bound(0, 255 * charge, 255));
-}
-
-void W_Vortex_Attack(float issecondary)
-{
-	float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
-	
-	mydmg = WEP_CVAR_BOTH(vortex, !issecondary, damage);
-	myforce = WEP_CVAR_BOTH(vortex, !issecondary, force);
-	mymindist = WEP_CVAR_BOTH(vortex, !issecondary, damagefalloff_mindist);
-	mymaxdist = WEP_CVAR_BOTH(vortex, !issecondary, damagefalloff_maxdist);
-	myhalflife = WEP_CVAR_BOTH(vortex, !issecondary, damagefalloff_halflife);
-	myforcehalflife = WEP_CVAR_BOTH(vortex, !issecondary, damagefalloff_forcehalflife);
-	myammo = WEP_CVAR_BOTH(vortex, !issecondary, ammo);
-
-	float flying;
-	flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
-
-	if(WEP_CVAR(vortex, charge))
-	{
-		charge = WEP_CVAR(vortex, charge_mindmg) / mydmg + (1 - WEP_CVAR(vortex, charge_mindmg) / mydmg) * self.vortex_charge;
-		self.vortex_charge *= WEP_CVAR(vortex, charge_shot_multiplier); // do this AFTER setting mydmg/myforce
-		// O RLY? -- divVerent
-		// YA RLY -- FruitieX
-	}
-	else
-		charge = 1;
-	mydmg *= charge;
-	myforce *= charge;
-
-	W_SetupShot(self, TRUE, 5, "weapons/nexfire.wav", CH_WEAPON_A, mydmg);
-	if(charge > WEP_CVAR(vortex, charge_animlimit) && WEP_CVAR(vortex, charge_animlimit)) // if the Vortex is overcharged, we play an extra sound
-	{
-		sound(self, CH_WEAPON_B, "weapons/nexcharge.wav", VOL_BASE * (charge - 0.5 * WEP_CVAR(vortex, charge_animlimit)) / (1 - 0.5 * WEP_CVAR(vortex, charge_animlimit)), ATTN_NORM);
-	}
-
-	yoda = 0;
-	FireRailgunBullet(w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_VORTEX);
-
-	if(yoda && flying)
-		Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA); 
-
-	//beam and muzzle flash done on client
-	SendCSQCVortexBeamParticle(charge);
-
-	W_DecreaseAmmo(myammo);
-}
-
-void spawnfunc_weapon_vortex(void); // defined in t_items.qc
-
-.float vortex_chargepool_pauseregen_finished;
-float W_Vortex(float req)
-{
-	float dt;
-	float ammo_amount;
-	switch(req)
-	{
-		case WR_AIM:
-		{
-			if(bot_aim(1000000, 0, 1, FALSE))
-				self.BUTTON_ATCK = TRUE;
-			else
-			{
-				if(WEP_CVAR(vortex, charge))
-					self.BUTTON_ATCK2 = TRUE;
-			}
-			return TRUE;
-		}
-		case WR_THINK:
-		{
-			if(WEP_CVAR(vortex, charge) && self.vortex_charge < WEP_CVAR(vortex, charge_limit))
-				self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME);
-				
-			if(WEP_CVAR_SEC(vortex, chargepool))
-				if(self.vortex_chargepool_ammo < 1)
-				{
-					if(self.vortex_chargepool_pauseregen_finished < time)
-						self.vortex_chargepool_ammo = min(1, self.vortex_chargepool_ammo + WEP_CVAR_SEC(vortex, chargepool_regen) * frametime / W_TICSPERFRAME);
-					self.pauseregen_finished = max(self.pauseregen_finished, time + WEP_CVAR_SEC(vortex, chargepool_pause_regen));
-				}
-
-			if(autocvar_g_balance_vortex_reload_ammo && self.clip_load < min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo))) // forced reload
-				WEP_ACTION(self.weapon, WR_RELOAD);
-			else
-			{
-				if(self.BUTTON_ATCK)
-				{
-					if(weapon_prepareattack(0, WEP_CVAR_PRI(vortex, refire)))
-					{
-						W_Vortex_Attack(0);
-						weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_PRI(vortex, animtime), w_ready);
-					}
-				}
-				if((WEP_CVAR(vortex, charge) && !WEP_CVAR(vortex, secondary)) ? (self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) : self.BUTTON_ATCK2)
-				{
-					if(WEP_CVAR(vortex, charge))
-					{
-						self.vortex_charge_rottime = time + WEP_CVAR(vortex, charge_rot_pause);
-						dt = frametime / W_TICSPERFRAME;
-
-						if(self.vortex_charge < 1)
-						{
-							if(WEP_CVAR_SEC(vortex, chargepool))
-							{
-								if(WEP_CVAR_SEC(vortex, ammo))
-								{
-									// always deplete if secondary is held
-									self.vortex_chargepool_ammo = max(0, self.vortex_chargepool_ammo - WEP_CVAR_SEC(vortex, ammo) * dt);
-
-									dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate));
-									self.vortex_chargepool_pauseregen_finished = time + WEP_CVAR_SEC(vortex, chargepool_pause_regen);
-									dt = min(dt, self.vortex_chargepool_ammo);
-									dt = max(0, dt);
-
-									self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
-								}
-							}
-
-							else if(WEP_CVAR_SEC(vortex, ammo))
-							{
-								if(self.BUTTON_ATCK2) // only eat ammo when the button is pressed
-								{
-									dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate));
-									if(!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-									{
-										// if this weapon is reloadable, decrease its load. Else decrease the player's ammo
-										if(autocvar_g_balance_vortex_reload_ammo)
-										{
-											dt = min(dt, (self.clip_load - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
-											dt = max(0, dt);
-											if(dt > 0)
-											{
-												self.clip_load = max(WEP_CVAR_SEC(vortex, ammo), self.clip_load - WEP_CVAR_SEC(vortex, ammo) * dt);
-											}
-											self.(weapon_load[WEP_VORTEX]) = self.clip_load;
-										}
-										else
-										{
-											dt = min(dt, (self.WEP_AMMO(VORTEX) - WEP_CVAR_PRI(vortex, ammo)) / WEP_CVAR_SEC(vortex, ammo));
-											dt = max(0, dt);
-											if(dt > 0)
-											{
-												self.WEP_AMMO(VORTEX) = max(WEP_CVAR_SEC(vortex, ammo), self.WEP_AMMO(VORTEX) - WEP_CVAR_SEC(vortex, ammo) * dt);
-											}
-										}
-									}
-									self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
-								}
-							}
-
-							else
-							{
-								dt = min(dt, (1 - self.vortex_charge) / WEP_CVAR(vortex, charge_rate));
-								self.vortex_charge += dt * WEP_CVAR(vortex, charge_rate);
-							}
-						}
-					}
-					else if(WEP_CVAR(vortex, secondary))
-					{
-						if(weapon_prepareattack(0, WEP_CVAR_SEC(vortex, refire)))
-						{
-							W_Vortex_Attack(1);
-							weapon_thinkf(WFRAME_FIRE1, WEP_CVAR_SEC(vortex, animtime), w_ready);
-						}
-					}
-				}
-			}
-			
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_model("models/nexflash.md3");
-			precache_model("models/weapons/g_nex.md3");
-			precache_model("models/weapons/v_nex.md3");
-			precache_model("models/weapons/h_nex.iqm");
-			precache_sound("weapons/nexfire.wav");
-			precache_sound("weapons/nexcharge.wav");
-			precache_sound("weapons/nexwhoosh1.wav");
-			precache_sound("weapons/nexwhoosh2.wav");
-			precache_sound("weapons/nexwhoosh3.wav");
-			VORTEX_SETTINGS(WEP_SKIP_CVAR, WEP_SET_PROP)
-			return TRUE;
-		}
-		case WR_CHECKAMMO1:
-		{
-			ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_PRI(vortex, ammo);
-			ammo_amount += (autocvar_g_balance_vortex_reload_ammo && self.(weapon_load[WEP_VORTEX]) >= WEP_CVAR_PRI(vortex, ammo));
-			return ammo_amount;
-		}
-		case WR_CHECKAMMO2:
-		{
-			if(WEP_CVAR(vortex, secondary))
-			{
-				// don't allow charging if we don't have enough ammo
-				ammo_amount = self.WEP_AMMO(VORTEX) >= WEP_CVAR_SEC(vortex, ammo);
-				ammo_amount += self.(weapon_load[WEP_VORTEX]) >= WEP_CVAR_SEC(vortex, ammo);
-				return ammo_amount;
-			}
-			else
-			{
-				return FALSE; // zoom is not a fire mode
-			}
-		}
-		case WR_CONFIG:
-		{
-			VORTEX_SETTINGS(WEP_CONFIG_WRITE_CVARS, WEP_CONFIG_WRITE_PROPS)
-			return TRUE;
-		}
-		case WR_RELOAD:
-		{
-			W_Reload(min(WEP_CVAR_PRI(vortex, ammo), WEP_CVAR_SEC(vortex, ammo)), "weapons/reload.wav");
-			return TRUE;
-		}
-		case WR_SUICIDEMESSAGE:
-		{
-			return WEAPON_THINKING_WITH_PORTALS;
-		}
-		case WR_KILLMESSAGE:
-		{
-			return WEAPON_VORTEX_MURDER;
-		}
-	}
-	return FALSE;
-}
-#endif
-#ifdef CSQC
-var float autocvar_g_balance_vortex_secondary = 0; // WEAPONTODO
-float W_Vortex(float req)
-{
-	switch(req)
-	{
-		case WR_IMPACTEFFECT:
-		{
-			vector org2;
-			org2 = w_org + w_backoff * 6;
-			pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1);
-			if(!w_issilent)
-				sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTN_NORM);
-				
-			return TRUE;
-		}
-		case WR_INIT:
-		{
-			precache_sound("weapons/neximpact.wav");
-			if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
-			{
-				precache_pic("gfx/reticle_nex");
-			}
-			return TRUE;
-		}
-		case WR_ZOOMRETICLE:
-		{
-			if(button_zoom || zoomscript_caught || (!WEP_CVAR(vortex, secondary) && button_attack2))
-			{
-				reticle_image = "gfx/reticle_nex";
-				return TRUE;
-			}
-			else
-			{
-				// no weapon specific image for this weapon
-				return FALSE;
-			}
-		}
-	}
-	return FALSE;
-}
-#endif
-#endif
diff --git a/qcsrc/common/weapons/weapons.qc b/qcsrc/common/weapons/weapons.qc
deleted file mode 100644
index e45a901c3..000000000
--- a/qcsrc/common/weapons/weapons.qc
+++ /dev/null
@@ -1,321 +0,0 @@
-#ifndef MENUQC
-#include "calculations.qc"
-#endif
-#include "all.qh"
-
-// WEAPON PLUGIN SYSTEM
-entity weapon_info[WEP_MAXCOUNT];
-entity dummy_weapon_info;
-
-#if WEP_MAXCOUNT > 72
-# error Kein Weltraum links auf dem Gerät
-#endif
-
-WepSet WepSet_FromWeapon(float a) {
-	a -= WEP_FIRST;
-#if WEP_MAXCOUNT > 24
-	if(a >= 24) {
-		a -= 24;
-#if WEP_MAXCOUNT > 48
-		if(a >= 24) {
-			a -= 24;
-			return '0 0 1' * power2of(a);
-		}
-#endif
-		return '0 1 0' * power2of(a);
-	}
-#endif
-	return '1 0 0' * power2of(a);
-}
-#ifdef SVQC
-void WepSet_AddStat()
-{
-	addstat(STAT_WEAPONS, AS_INT, weapons_x);
-#if WEP_MAXCOUNT > 24
-	addstat(STAT_WEAPONS2, AS_INT, weapons_y);
-#if WEP_MAXCOUNT > 48
-	addstat(STAT_WEAPONS3, AS_INT, weapons_z);
-#endif
-#endif
-}
-void WriteWepSet(float dst, WepSet w)
-{
-#if WEP_MAXCOUNT > 48
-	WriteInt72_t(dst, w);
-#elif WEP_MAXCOUNT > 24
-	WriteInt48_t(dst, w);
-#else
-	WriteInt24_t(dst, w_x);
-#endif
-}
-#endif
-#ifdef CSQC
-WepSet WepSet_GetFromStat()
-{
-	WepSet w = '0 0 0';
-	w_x = getstati(STAT_WEAPONS);
-#if WEP_MAXCOUNT > 24
-	w_y = getstati(STAT_WEAPONS2);
-#if WEP_MAXCOUNT > 48
-	w_z = getstati(STAT_WEAPONS3);
-#endif
-#endif
-	return w;
-}
-WepSet ReadWepSet()
-{
-#if WEP_MAXCOUNT > 48
-	return ReadInt72_t();
-#elif WEP_MAXCOUNT > 24
-	return ReadInt48_t();
-#else
-	return ReadInt24_t() * '1 0 0';
-#endif
-}
-#endif
-
-void register_weapon(
-	float id,
-	WepSet bit,
-	float(float) func,
-	.float ammotype,
-	float i,
-	float weapontype,
-	float pickupbasevalue,
-	vector clr,
-	string modelname,
-	string simplemdl,
-	string crosshair,
-	string wepimg,
-	string refname,
-	string wepname)
-{
-	entity e;
-	weapon_info[id - 1] = e = spawn();
-	e.classname = "weapon_info";
-	e.weapon = id;
-	e.weapons = bit;
-	e.weapon_func = func;
-	e.ammo_field = ammotype;
-	e.impulse = i;
-	e.spawnflags = weapontype;
-	e.bot_pickupbasevalue = pickupbasevalue;
-	e.wpcolor = clr;
-	e.wpmodel = strzone(strcat("wpn-", ftos(id)));
-	e.mdl = modelname;
-	e.model = strzone(strcat("models/weapons/g_", modelname, ".md3"));
-	e.w_simplemdl = strzone(simplemdl); // simpleitems weapon model/image
-	e.w_crosshair = strzone(car(crosshair));
-	string s = cdr(crosshair);
-	e.w_crosshair_size = ((s != "") ? stof(s) : 1); // so that we can scale the crosshair from code (for compat)
-	e.model2 = strzone(wepimg);
-	e.netname = refname;
-	e.message = wepname;
-
-	#ifndef MENUQC
-	func(WR_INIT);
-	#endif
-}
-float w_null(float dummy)
-{
-	return 0;
-}
-void register_weapons_done()
-{
-	dummy_weapon_info = spawn();
-	dummy_weapon_info.classname = "weapon_info";
-	dummy_weapon_info.weapon = 0; // you can recognize dummies by this
-	dummy_weapon_info.weapons = '0 0 0';
-	dummy_weapon_info.netname = "";
-	dummy_weapon_info.message = "AOL CD Thrower";
-	dummy_weapon_info.weapon_func = w_null;
-	dummy_weapon_info.wpmodel = "";
-	dummy_weapon_info.mdl = "";
-	dummy_weapon_info.model = "";
-	dummy_weapon_info.spawnflags = 0;
-	dummy_weapon_info.impulse = -1;
-	dummy_weapon_info.bot_pickupbasevalue = 0;
-	dummy_weapon_info.ammo_field = ammo_none;
-
-	dummy_weapon_info.w_crosshair = "gfx/crosshair1";
-	dummy_weapon_info.w_crosshair_size = 1;
-	dummy_weapon_info.model2 = "";
-
-	float i;
-	weaponorder_byid = "";
-	for(i = WEP_MAXCOUNT; i >= 1; --i)
-		if(weapon_info[i-1])
-			weaponorder_byid = strcat(weaponorder_byid, " ", ftos(i));
-	weaponorder_byid = strzone(substring(weaponorder_byid, 1, strlen(weaponorder_byid) - 1));
-}
-entity get_weaponinfo(float id)
-{
-	entity w;
-	if(id < WEP_FIRST || id > WEP_LAST)
-		return dummy_weapon_info;
-	w = weapon_info[id - 1];
-	if(w)
-		return w;
-	return dummy_weapon_info;
-}
-string W_FixWeaponOrder(string order, float complete)
-{
-	return fixPriorityList(order, WEP_FIRST, WEP_LAST, 230 - WEP_FIRST, complete);
-}
-string W_NameWeaponOrder_MapFunc(string s)
-{
-	entity wi;
-	if(s == "0" || stof(s))
-	{
-		wi = get_weaponinfo(stof(s));
-		if(wi != dummy_weapon_info)
-			return wi.netname;
-	}
-	return s;
-}
-
-string W_UndeprecateName(string s)
-{
-	switch ( s )
-	{
-		case "nex"            : return "vortex";
-		case "rocketlauncher" : return "devastator"; 
-		case "laser"          : return "blaster";
-		case "minstanex"      : return "vaporizer";
-		case "grenadelauncher": return "mortar";
-		case "uzi"            : return "machinegun";
-		default               : return s;
-	}
-}
-string W_NameWeaponOrder(string order)
-{
-	return mapPriorityList(order, W_NameWeaponOrder_MapFunc);
-}
-string W_NumberWeaponOrder_MapFunc(string s)
-{
-	float i;
-	if(s == "0" || stof(s))
-		return s;
-	s = W_UndeprecateName(s);
-	for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-		if(s == get_weaponinfo(i).netname)
-			return ftos(i);
-	return s;
-}
-string W_NumberWeaponOrder(string order)
-{
-	return mapPriorityList(order, W_NumberWeaponOrder_MapFunc);
-}
-
-float W_FixWeaponOrder_BuildImpulseList_buf[WEP_MAXCOUNT];
-string W_FixWeaponOrder_BuildImpulseList_order;
-void W_FixWeaponOrder_BuildImpulseList_swap(float i, float j, entity pass)
-{
-	float h;
-	h = W_FixWeaponOrder_BuildImpulseList_buf[i];
-	W_FixWeaponOrder_BuildImpulseList_buf[i] = W_FixWeaponOrder_BuildImpulseList_buf[j];
-	W_FixWeaponOrder_BuildImpulseList_buf[j] = h;
-}
-float W_FixWeaponOrder_BuildImpulseList_cmp(float i, float j, entity pass)
-{
-	entity e1, e2;
-	float d;
-	e1 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[i]);
-	e2 = get_weaponinfo(W_FixWeaponOrder_BuildImpulseList_buf[j]);
-	d = mod(e1.impulse + 9, 10) - mod(e2.impulse + 9, 10);
-	if(d != 0)
-		return -d; // high impulse first!
-	return
-		strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[i]), 0)
-		-
-		strstrofs(strcat(" ", W_FixWeaponOrder_BuildImpulseList_order, " "), sprintf(" %d ", W_FixWeaponOrder_BuildImpulseList_buf[j]), 0)
-		; // low char index first!
-}
-string W_FixWeaponOrder_BuildImpulseList(string o)
-{
-	float i;
-	W_FixWeaponOrder_BuildImpulseList_order = o;
-	for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-		W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST] = i;
-	heapsort(WEP_LAST - WEP_FIRST + 1, W_FixWeaponOrder_BuildImpulseList_swap, W_FixWeaponOrder_BuildImpulseList_cmp, world);
-	o = "";
-	for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-		o = strcat(o, " ", ftos(W_FixWeaponOrder_BuildImpulseList_buf[i - WEP_FIRST]));
-	W_FixWeaponOrder_BuildImpulseList_order = string_null;
-	return substring(o, 1, -1);
-}
-
-string W_FixWeaponOrder_AllowIncomplete(string order)
-{
-	return W_FixWeaponOrder(order, 0);
-}
-
-string W_FixWeaponOrder_ForceComplete(string order)
-{
-	if(order == "")
-		order = W_NumberWeaponOrder(cvar_defstring("cl_weaponpriority"));
-	return W_FixWeaponOrder(order, 1);
-}
-
-void W_RandomWeapons(entity e, float n)
-{
-	float i, j;
-	WepSet remaining;
-	WepSet result;
-	remaining = e.weapons;
-	result = '0 0 0';
-	for(i = 0; i < n; ++i)
-	{
-		RandomSelection_Init();
-		for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-			if(remaining & WepSet_FromWeapon(j))
-				RandomSelection_Add(world, j, string_null, 1, 1);
-		result |= WepSet_FromWeapon(RandomSelection_chosen_float);
-		remaining &= ~WepSet_FromWeapon(RandomSelection_chosen_float);
-	}
-	e.weapons = result;
-}
-
-string GetAmmoPicture(.float ammotype)
-{
-	switch(ammotype)
-	{
-		case ammo_shells:  return "ammo_shells";
-		case ammo_nails:   return "ammo_bullets";
-		case ammo_rockets: return "ammo_rockets";
-		case ammo_cells:   return "ammo_cells";
-		case ammo_plasma:  return "ammo_cells";
-		case ammo_fuel:    return "ammo_fuel";
-		default: return ""; // wtf, no ammo type?
-	}
-}
-
-#ifdef CSQC
-.float GetAmmoFieldFromNum(float i)
-{
-	switch(i)
-	{
-		case 0: return ammo_shells;
-		case 1: return ammo_nails;
-		case 2: return ammo_rockets;
-		case 3: return ammo_cells;
-		case 4: return ammo_plasma;
-		case 5: return ammo_fuel;
-		default: return ammo_none;
-	}
-}
-
-float GetAmmoStat(.float ammotype)
-{
-	switch(ammotype)
-	{
-		case ammo_shells: return STAT_SHELLS;
-		case ammo_nails: return STAT_NAILS;
-		case ammo_rockets: return STAT_ROCKETS;
-		case ammo_cells: return STAT_CELLS;
-		case ammo_plasma: return STAT_PLASMA;
-		case ammo_fuel: return STAT_FUEL;
-		default: return -1;
-	}
-}
-#endif
diff --git a/qcsrc/common/weapons/weapons.qh b/qcsrc/common/weapons/weapons.qh
deleted file mode 100644
index af031086a..000000000
--- a/qcsrc/common/weapons/weapons.qh
+++ /dev/null
@@ -1,206 +0,0 @@
-#ifndef MENUQC
-#include "calculations.qh"
-#endif
-
-const float MAX_SHOT_DISTANCE = 32768;
-
-// weapon pickup ratings for bot logic
-const float BOT_PICKUP_RATING_LOW  =  2500;
-const float BOT_PICKUP_RATING_MID  =  5000;
-const float BOT_PICKUP_RATING_HIGH = 10000;
-
-// weapon flags
-const float WEP_TYPE_OTHER          =  0x00; // not for damaging people
-const float WEP_TYPE_SPLASH         =  0x01; // splash damage
-const float WEP_TYPE_HITSCAN        =  0x02; // hitscan
-const float WEP_TYPEMASK            =  0x0F;
-const float WEP_FLAG_CANCLIMB       =  0x10; // can be used for movement
-const float WEP_FLAG_NORMAL         =  0x20; // in "most weapons" set
-const float WEP_FLAG_HIDDEN         =  0x40; // hides from menu
-const float WEP_FLAG_RELOADABLE     =  0x80; // can has reload
-const float WEP_FLAG_SUPERWEAPON    = 0x100; // powerup timer
-const float WEP_FLAG_MUTATORBLOCKED = 0x200; // hides from impulse 99 etc. (mutators are allowed to clear this flag)
-
-// weapon requests
-const float WR_SETUP          =  1; // (SERVER) setup weapon data
-const float WR_THINK          =  2; // (SERVER) logic to run every frame
-const float WR_CHECKAMMO1     =  3; // (SERVER) checks ammo for weapon primary
-const float WR_CHECKAMMO2     =  4; // (SERVER) checks ammo for weapon second
-const float WR_AIM            =  5; // (SERVER) runs bot aiming code for this weapon
-const float WR_INIT           =  6; // (BOTH)   precaches models/sounds used by this weapon, also sets up weapon properties
-const float WR_SUICIDEMESSAGE =  7; // (SERVER) notification number for suicide message (may inspect w_deathtype for details)
-const float WR_KILLMESSAGE    =  8; // (SERVER) notification number for kill message (may inspect w_deathtype for details)
-const float WR_RELOAD         =  9; // (SERVER) handles reloading for weapon
-const float WR_RESETPLAYER    = 10; // (SERVER) clears fields that the weapon may use
-const float WR_IMPACTEFFECT   = 11; // (CLIENT) impact effect for weapon explosion
-const float WR_PLAYERDEATH    = 12; // (SERVER) called whenever a player dies
-const float WR_GONETHINK      = 13; // (SERVER) logic to run when weapon is lost
-const float WR_CONFIG         = 14; // (ALL)    dump weapon cvars to config in data directory (see: sv_cmd dumpweapons)
-const float WR_ZOOMRETICLE    = 15; // (CLIENT) weapon specific zoom reticle
-
-// variables:
-string weaponorder_byid;
-
-// weapon sets
-typedef vector WepSet;
-WepSet WepSet_FromWeapon(float a);
-#ifdef SVQC
-void WepSet_AddStat();
-void WriteWepSet(float dest, WepSet w);
-#endif
-#ifdef CSQC
-WepSet WepSet_GetFromStat();
-WepSet ReadWepSet();
-#endif
-
-// weapon name macros
-#define WEP_FIRST 1
-#define WEP_MAXCOUNT 24 // Increase as needed. Can be up to three times as much.
-float WEP_COUNT;
-float WEP_LAST;
-WepSet WEPSET_ALL;
-WepSet WEPSET_SUPERWEAPONS;
-
-// functions:
-entity get_weaponinfo(float id);
-string W_FixWeaponOrder(string order, float complete);
-string W_NameWeaponOrder(string order);
-string W_NumberWeaponOrder(string order);
-string W_FixWeaponOrder_BuildImpulseList(string o);
-string W_FixWeaponOrder_AllowIncomplete(string order);
-string W_FixWeaponOrder_ForceComplete(string order);
-void W_RandomWeapons(entity e, float n);
-
-string GetAmmoPicture(.float ammotype);
-
-#ifdef CSQC
-.float GetAmmoFieldFromNum(float i);
-float GetAmmoStat(.float ammotype);
-#endif
-
-// ammo types
-.float ammo_shells;
-.float ammo_nails;
-.float ammo_rockets;
-.float ammo_cells;
-.float ammo_plasma;
-.float ammo_fuel;
-.float ammo_none;
-
-// other useful macros
-#define WEP_ACTION(wpn,wrequest) (get_weaponinfo(wpn)).weapon_func(wrequest)
-#define WEP_AMMO(wpn) ((get_weaponinfo(WEP_##wpn)).ammo_field) // only used inside weapon files/with direct name, don't duplicate prefix
-#define WEP_NAME(wpn) ((get_weaponinfo(wpn)).message)
-
-
-// ======================
-//  Configuration Macros
-// ======================
-
-// create cvars for weapon settings
-#define WEP_ADD_CVAR_NONE(wepname,name) [[last]] float autocvar_g_balance_##wepname##_##name;
-
-#define WEP_ADD_CVAR_PRI(wepname,name) WEP_ADD_CVAR_NONE(wepname, primary_##name)
-#define WEP_ADD_CVAR_SEC(wepname,name) WEP_ADD_CVAR_NONE(wepname, secondary_##name)
-#define WEP_ADD_CVAR_BOTH(wepname,name) \
-	WEP_ADD_CVAR_PRI(wepname, name) \
-	WEP_ADD_CVAR_SEC(wepname, name)
-
-#define WEP_ADD_CVAR(wepid,wepname,mode,name) WEP_ADD_CVAR_##mode(wepname, name)
-
-// create properties for weapon settings
-#define WEP_ADD_PROP(wepid,wepname,type,prop,name) \
-	.type prop; \
-	[[last]] type autocvar_g_balance_##wepname##_##name;
-
-// read cvars from weapon settings
-#define WEP_CVAR(wepname,name) autocvar_g_balance_##wepname##_##name
-#define WEP_CVAR_PRI(wepname,name) WEP_CVAR(wepname, primary_##name)
-#define WEP_CVAR_SEC(wepname,name) WEP_CVAR(wepname, secondary_##name)
-#define WEP_CVAR_BOTH(wepname,isprimary,name) ((isprimary) ? WEP_CVAR_PRI(wepname, name) : WEP_CVAR_SEC(wepname, name))
-
-// set initialization values for weapon settings
-#define WEP_SKIP_CVAR(unuseda,unusedb,unusedc,unusedd) /* skip cvars */
-#define WEP_SET_PROP(wepid,wepname,type,prop,name) get_weaponinfo(WEP_##wepid).##prop = autocvar_g_balance_##wepname##_##name;
-
-
-// =====================
-//  Weapon Registration
-// =====================
-
-float w_null(float dummy);
-
-void register_weapon(
-	float id,
-	WepSet bit,
-	float(float) func,
-	.float ammotype,
-	float i,
-	float weapontype,
-	float pickupbasevalue,
-	vector clr,
-	string modelname,
-	string simplemdl,
-	string crosshair,
-	string wepimg,
-	string refname,
-	string wepname);
-
-void register_weapons_done();
-
-// entity properties of weaponinfo:
-// fields which are explicitly/manually set are marked with "M", fields set automatically are marked with "A"
-.float weapon;              // M: WEP_id    // WEP_...
-.WepSet weapons;            // A: WEPSET_id // WEPSET_...
-.float(float) weapon_func;  // M: function  // w_...
-..float ammo_field;         // M: ammotype  // main ammo field
-.float impulse;             // M: impulse   // weapon impulse
-.float spawnflags;          // M: flags     // WEPSPAWNFLAG_... combined
-.float bot_pickupbasevalue; // M: rating    // bot weapon priority
-.vector wpcolor;            // M: color     // waypointsprite color
-.string wpmodel;            // A: wpn-id    // wpn- sprite name
-.string mdl;                // M: modelname // name of model (without g_ v_ or h_ prefixes)
-.string model;              // A: modelname // full path to g_ model
-.string w_simplemdl;        // M: simplemdl // simpleitems weapon model/image
-.string w_crosshair;        // M: crosshair // per-weapon crosshair: "CrosshairImage Size"
-.float w_crosshair_size;    // A: crosshair // per-weapon crosshair size (argument two of "crosshair" field)
-.string model2;             // M: wepimg    // "weaponfoobar" side view image file of weapon // WEAPONTODO: Move out of skin files, move to common files
-.string netname;            // M: refname   // reference name name
-.string message;            // M: wepname   // human readable name
-
-
-// note: the fabs call is just there to hide "if result is constant" warning
-#define REGISTER_WEAPON_2(id,bit,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \
-	float id; \
-	WepSet bit; \
-	float function(float); \
-	void RegisterWeapons_##id() \
-	{ \
-		WEP_LAST = (id = WEP_FIRST + WEP_COUNT); \
-		bit = WepSet_FromWeapon(id); \
-		WEPSET_ALL |= bit; \
-		if((flags) & WEP_FLAG_SUPERWEAPON) \
-			WEPSET_SUPERWEAPONS |= bit; \
-		++WEP_COUNT; \
-		register_weapon(id,bit,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname); \
-	} \
-	ACCUMULATE_FUNCTION(RegisterWeapons, RegisterWeapons_##id)
-#ifdef MENUQC
-#define REGISTER_WEAPON(id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \
-	REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,w_null,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname)
-#else
-#define REGISTER_WEAPON(id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname) \
-	REGISTER_WEAPON_2(WEP_##id,WEPSET_##id,function,ammotype,impulse,flags,rating,color,modelname,simplemdl,crosshair,wepimg,refname,wepname)
-#endif
-
-#include "all.qh"
-
-#undef WEP_ADD_CVAR_MO_PRI
-#undef WEP_ADD_CVAR_MO_SEC
-#undef WEP_ADD_CVAR_MO_BOTH
-#undef WEP_ADD_CVAR_MO_NONE
-#undef WEP_ADD_CVAR
-#undef WEP_ADD_PROP
-#undef REGISTER_WEAPON
-
-ACCUMULATE_FUNCTION(RegisterWeapons, register_weapons_done);
diff --git a/qcsrc/menu/progs.src b/qcsrc/menu/progs.src
index 9d2f69333..86cb9621c 100644
--- a/qcsrc/menu/progs.src
+++ b/qcsrc/menu/progs.src
@@ -18,7 +18,7 @@ oo/base.h
 ../common/constants.qh
 ../common/mapinfo.qh
 ../common/campaign_common.qh
-../common/weapons/weapons.qh // TODO
+../common/items.qh
 ../common/counting.qh
 ../common/command/markup.qh
 ../common/command/rpn.qh
@@ -51,7 +51,7 @@ xonotic/util.qc
 ../common/campaign_file.qc
 ../common/campaign_setup.qc
 ../common/mapinfo.qc
-../common/weapons/weapons.qc // TODO
+../common/items.qc
 ../common/urllib.qc
 ../common/monsters/monsters.qc
 
diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c
index 2b4bb6b58..055f5449f 100644
--- a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c
+++ b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.c
@@ -146,7 +146,7 @@ float checkCompatibility_weaponarena_weapon(entity me)
 		return 0;
 	if(cvar_string("g_weaponarena") == "0")
 		return 0;
-	if(cvar_string("g_balance_blaster_weaponstart") == "0")
+	if(cvar_string("g_start_weapon_laser") == "0")
 		return 0;
 	return 1;
 }
@@ -263,9 +263,9 @@ void XonoticMutatorsDialog_fill(entity me)
 			setDependent(e, "g_nix", 1, 1);
 	me.TR(me);
 		me.TDempty(me, 0.2);
-		me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, "g_balance_blaster_weaponstart", "0", _("No start weapons")));
+		me.TD(me, 1, 1.8, e = makeXonoticRadioButton(1, "g_start_weapon_laser", "0", _("No start weapons")));
 			e.cvarOffValue = "-1";
-			makeMulti(e, "g_balance_shotgun_weaponstart g_balance_machinegun_weaponstart g_balance_devastator_weaponstart g_balance_minelayer_weaponstart g_balance_electro_weaponstart g_balance_crylink_weaponstart g_balance_hagar_weaponstart g_balance_porto_weaponstart g_balance_vaporizer_weaponstart g_balance_hook_weaponstart g_balance_rifle_weaponstart g_balance_fireball_weaponstart g_balance_seeker_weaponstart g_balance_tuba_weaponstart g_balance_shockwave_weaponstart g_balance_arc_weaponstart g_balance_vortex_weaponstart g_balance_mortar_weaponstart");
+			makeMulti(e, "g_start_weapon_shotgun g_start_weapon_uzi g_start_weapon_grenadelauncher g_start_weapon_minelayer g_start_weapon_electro g_start_weapon_crylink g_start_weapon_nex g_start_weapon_hagar g_start_weapon_rocketlauncher g_start_weapon_porto g_start_weapon_minstanex g_start_weapon_hook g_start_weapon_hlac g_start_weapon_rifle g_start_weapon_fireball g_start_weapon_seeker g_start_weapon_tuba");
 
 	me.gotoRC(me, me.rows - 1, 0);
 		me.TD(me, 1, me.columns, e = makeXonoticButton(_("OK"), '0 0 0'));
diff --git a/qcsrc/menu/xonotic/util.qc b/qcsrc/menu/xonotic/util.qc
index 8b78a0f0a..74b60d30a 100644
--- a/qcsrc/menu/xonotic/util.qc
+++ b/qcsrc/menu/xonotic/util.qc
@@ -343,6 +343,7 @@ void UpdateNotification_URI_Get_Callback(float id, float status, string data)
 		
 		switch(substring(argv(i), 0, 1))
 		{
+			#define APPEND_TO_STRING(list,sep,add) ((list) = (((list) != "") ? strcat(list, sep, add) : (add)))
 			case "V":
 			{
 				un_version = s;
diff --git a/qcsrc/server/accuracy.qc b/qcsrc/server/accuracy.qc
new file mode 100644
index 000000000..ca837e7d3
--- /dev/null
+++ b/qcsrc/server/accuracy.qc
@@ -0,0 +1,129 @@
+.float accuracy_hit[WEP_MAXCOUNT];
+.float accuracy_fired[WEP_MAXCOUNT];
+.float accuracy_cnt_hit[WEP_MAXCOUNT];
+.float accuracy_cnt_fired[WEP_MAXCOUNT];
+
+float accuracy_byte(float n, float d)
+{
+	//printf("accuracy: %d / %d\n", n, d);
+	if(n <= 0)
+		return 0;
+	if(n > d)
+		return 255;
+	return 1 + rint(n * 100.0 / d);
+}
+
+float accuracy_send(entity to, float sf)
+{
+	float w, f;
+	entity a;
+	WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY);
+
+	a = self.owner;
+	if(IS_SPEC(a))
+		a = a.enemy;
+	a = a.accuracy;
+
+	if(to != a.owner)
+		if (!(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share))
+			sf = 0;
+	// note: zero sendflags can never be sent... so we can use that to say that we send no accuracy!
+	WriteInt24_t(MSG_ENTITY, sf);
+	if(sf == 0)
+		return TRUE;
+	// note: we know that client and server agree about SendFlags...
+	for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w)
+	{
+		if(sf & f)
+			WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w])));
+		if(f == 0x800000)
+			f = 1;
+		else
+			f *= 2;
+	}
+	return TRUE;
+}
+
+// init/free
+void accuracy_init(entity e)
+{
+	e.accuracy = spawn();
+	e.accuracy.owner = e;
+	e.accuracy.classname = "accuracy";
+	e.accuracy.drawonlytoclient = e;
+	Net_LinkEntity(e.accuracy, FALSE, 0, accuracy_send);
+}
+
+void accuracy_free(entity e)
+{
+	remove(e.accuracy);
+}
+
+// force a resend of a player's accuracy stats
+void accuracy_resend(entity e)
+{
+	e.accuracy.SendFlags = 0xFFFFFF;
+}
+
+// update accuracy stats
+.float hit_time;
+.float fired_time;
+
+void accuracy_add(entity e, float w, float fired, float hit)
+{
+	entity a;
+	float b;
+	if(IS_INDEPENDENT_PLAYER(e))
+		return;
+	a = e.accuracy;
+	if(!a || !(hit || fired))
+		return;
+	w -= WEP_FIRST;
+	b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]));
+	if(hit)
+		a.(accuracy_hit[w]) += hit;
+	if(fired)
+		a.(accuracy_fired[w]) += fired;
+
+    if(hit && a.hit_time != time) // only run this once per frame
+    {
+        a.(accuracy_cnt_hit[w]) += 1;
+        a.hit_time = time;
+    }
+
+    if(fired && a.fired_time != time) // only run this once per frame
+    {
+        a.(accuracy_cnt_fired[w]) += 1;
+        a.fired_time = time;
+    }
+
+	if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])))
+		return;
+	w = pow(2, mod(w, 24));
+	a.SendFlags |= w;
+	FOR_EACH_CLIENT(a)
+		if(IS_SPEC(a))
+			if(a.enemy == e)
+				a.SendFlags |= w;
+}
+
+float accuracy_isgooddamage(entity attacker, entity targ)
+{
+	frag_attacker = attacker;
+	frag_target = targ;
+	float mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid);
+
+	if(!warmup_stage)
+	if(targ.deadflag == DEAD_NO)
+	if(mutator_check == MUT_ACCADD_INVALID || (mutator_check == MUT_ACCADD_VALID && IS_CLIENT(targ)))
+	if(DIFF_TEAM(attacker, targ))
+		return TRUE;
+	return FALSE;
+}
+
+float accuracy_canbegooddamage(entity attacker)
+{
+	if(!warmup_stage)
+		return TRUE;
+	return FALSE;
+}
diff --git a/qcsrc/server/accuracy.qh b/qcsrc/server/accuracy.qh
new file mode 100644
index 000000000..90dbb663d
--- /dev/null
+++ b/qcsrc/server/accuracy.qh
@@ -0,0 +1,15 @@
+.float cvar_cl_accuracy_data_share;
+
+// init/free
+void accuracy_init(entity e);
+void accuracy_free(entity e);
+
+// force a resend of a player's accuracy stats
+void accuracy_resend(entity e);
+
+// update accuracy stats
+void accuracy_add(entity e, float w, float fired, float hit);
+
+// helper
+float accuracy_isgooddamage(entity attacker, entity targ);
+float accuracy_canbegooddamage(entity attacker);
diff --git a/qcsrc/server/antilag.qh b/qcsrc/server/antilag.qh
index b89f12bb1..cadb45a14 100644
--- a/qcsrc/server/antilag.qh
+++ b/qcsrc/server/antilag.qh
@@ -5,7 +5,5 @@ void antilag_takeback(entity e, float t);
 void antilag_restore(entity e);
 void antilag_clear(entity e);
 
-.float antilag_debug;
-
 #define ANTILAG_LATENCY(e) min(0.4, e.ping * 0.001)
 // add one ticrate?
diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh
index 92ff35897..11cf993df 100644
--- a/qcsrc/server/autocvars.qh
+++ b/qcsrc/server/autocvars.qh
@@ -80,6 +80,33 @@ float autocvar_g_balance_armor_rot;
 float autocvar_g_balance_armor_rotlinear;
 float autocvar_g_balance_armor_rotstable;
 float autocvar_g_balance_armor_start;
+float autocvar_g_balance_rifle_bursttime;
+float autocvar_g_balance_rifle_primary_ammo;
+float autocvar_g_balance_rifle_primary_animtime;
+float autocvar_g_balance_rifle_primary_bullethail;
+float autocvar_g_balance_rifle_primary_burstcost;
+float autocvar_g_balance_rifle_primary_damage;
+float autocvar_g_balance_rifle_primary_force;
+float autocvar_g_balance_rifle_primary_refire;
+float autocvar_g_balance_rifle_primary_shots;
+float autocvar_g_balance_rifle_primary_solidpenetration;
+float autocvar_g_balance_rifle_primary_spread;
+float autocvar_g_balance_rifle_primary_tracer;
+float autocvar_g_balance_rifle_secondary;
+float autocvar_g_balance_rifle_secondary_ammo;
+float autocvar_g_balance_rifle_secondary_animtime;
+float autocvar_g_balance_rifle_secondary_bullethail;
+float autocvar_g_balance_rifle_secondary_burstcost;
+float autocvar_g_balance_rifle_secondary_damage;
+float autocvar_g_balance_rifle_secondary_force;
+float autocvar_g_balance_rifle_secondary_reload;
+float autocvar_g_balance_rifle_secondary_refire;
+float autocvar_g_balance_rifle_secondary_shots;
+float autocvar_g_balance_rifle_secondary_solidpenetration;
+float autocvar_g_balance_rifle_secondary_spread;
+float autocvar_g_balance_rifle_secondary_tracer;
+float autocvar_g_balance_rifle_reload_ammo;
+float autocvar_g_balance_rifle_reload_time;
 float autocvar_g_balance_cloaked_alpha;
 float autocvar_g_balance_contents_damagerate;
 float autocvar_g_balance_contents_drowndelay;
@@ -87,11 +114,134 @@ float autocvar_g_balance_contents_playerdamage_drowning;
 float autocvar_g_balance_contents_playerdamage_lava;
 float autocvar_g_balance_contents_playerdamage_slime;
 float autocvar_g_balance_contents_projectiledamage;
+float autocvar_g_balance_crylink_primary_ammo;
+float autocvar_g_balance_crylink_primary_animtime;
+float autocvar_g_balance_crylink_primary_bouncedamagefactor;
+float autocvar_g_balance_crylink_primary_bounces;
+float autocvar_g_balance_crylink_primary_damage;
+float autocvar_g_balance_crylink_primary_edgedamage;
+float autocvar_g_balance_crylink_primary_force;
+float autocvar_g_balance_crylink_primary_joindelay;
+float autocvar_g_balance_crylink_primary_joinexplode;
+float autocvar_g_balance_crylink_primary_joinexplode_damage;
+float autocvar_g_balance_crylink_primary_joinexplode_edgedamage;
+float autocvar_g_balance_crylink_primary_joinexplode_force;
+float autocvar_g_balance_crylink_primary_joinexplode_radius;
+float autocvar_g_balance_crylink_primary_joinspread;
+float autocvar_g_balance_crylink_primary_linkexplode;
+float autocvar_g_balance_crylink_primary_middle_fadetime;
+float autocvar_g_balance_crylink_primary_middle_lifetime;
+float autocvar_g_balance_crylink_primary_other_fadetime;
+float autocvar_g_balance_crylink_primary_other_lifetime;
+float autocvar_g_balance_crylink_primary_radius;
+float autocvar_g_balance_crylink_primary_refire;
+float autocvar_g_balance_crylink_primary_shots;
+float autocvar_g_balance_crylink_primary_speed;
+float autocvar_g_balance_crylink_primary_spread;
+float autocvar_g_balance_crylink_secondary;
+float autocvar_g_balance_crylink_secondary_ammo;
+float autocvar_g_balance_crylink_secondary_animtime;
+float autocvar_g_balance_crylink_secondary_bouncedamagefactor;
+float autocvar_g_balance_crylink_secondary_bounces;
+float autocvar_g_balance_crylink_secondary_damage;
+float autocvar_g_balance_crylink_secondary_edgedamage;
+float autocvar_g_balance_crylink_secondary_force;
+float autocvar_g_balance_crylink_secondary_joindelay;
+float autocvar_g_balance_crylink_secondary_joinexplode;
+float autocvar_g_balance_crylink_secondary_joinexplode_damage;
+float autocvar_g_balance_crylink_secondary_joinexplode_edgedamage;
+float autocvar_g_balance_crylink_secondary_joinexplode_force;
+float autocvar_g_balance_crylink_secondary_joinexplode_radius;
+float autocvar_g_balance_crylink_secondary_joinspread;
+float autocvar_g_balance_crylink_secondary_line_fadetime;
+float autocvar_g_balance_crylink_secondary_line_lifetime;
+float autocvar_g_balance_crylink_secondary_linkexplode;
+float autocvar_g_balance_crylink_secondary_middle_fadetime;
+float autocvar_g_balance_crylink_secondary_middle_lifetime;
+float autocvar_g_balance_crylink_secondary_radius;
+float autocvar_g_balance_crylink_secondary_refire;
+float autocvar_g_balance_crylink_secondary_shots;
+float autocvar_g_balance_crylink_secondary_speed;
+float autocvar_g_balance_crylink_secondary_spread;
+float autocvar_g_balance_crylink_secondary_spreadtype;
+float autocvar_g_balance_crylink_reload_ammo;
+float autocvar_g_balance_crylink_reload_time;
 float autocvar_g_balance_damagepush_speedfactor;
+float autocvar_g_balance_electro_combo_comboradius;
+float autocvar_g_balance_electro_combo_damage;
+float autocvar_g_balance_electro_combo_edgedamage;
+float autocvar_g_balance_electro_combo_force;
+float autocvar_g_balance_electro_combo_radius;
+float autocvar_g_balance_electro_combo_speed;
+float autocvar_g_balance_electro_combo_safeammocheck;
+float autocvar_g_balance_electro_lightning;
+float autocvar_g_balance_electro_primary_ammo;
+float autocvar_g_balance_electro_primary_animtime;
+float autocvar_g_balance_electro_primary_comboradius;
+float autocvar_g_balance_electro_primary_damage;
+float autocvar_g_balance_electro_primary_edgedamage;
+float autocvar_g_balance_electro_primary_falloff_halflifedist;
+float autocvar_g_balance_electro_primary_falloff_maxdist;
+float autocvar_g_balance_electro_primary_falloff_mindist;
+float autocvar_g_balance_electro_primary_force;
+float autocvar_g_balance_electro_primary_force_up;
+float autocvar_g_balance_electro_primary_lifetime;
+float autocvar_g_balance_electro_primary_radius;
+float autocvar_g_balance_electro_primary_range;
+float autocvar_g_balance_electro_primary_refire;
+float autocvar_g_balance_electro_primary_speed;
+float autocvar_g_balance_electro_secondary_ammo;
+float autocvar_g_balance_electro_secondary_animtime;
+float autocvar_g_balance_electro_secondary_bouncefactor;
+float autocvar_g_balance_electro_secondary_bouncestop;
+float autocvar_g_balance_electro_secondary_count;
+float autocvar_g_balance_electro_secondary_damage;
+float autocvar_g_balance_electro_secondary_damageforcescale;
+float autocvar_g_balance_electro_secondary_damagedbycontents;
+float autocvar_g_balance_electro_secondary_edgedamage;
+float autocvar_g_balance_electro_secondary_force;
+float autocvar_g_balance_electro_secondary_health;
+float autocvar_g_balance_electro_secondary_lifetime;
+float autocvar_g_balance_electro_secondary_radius;
+float autocvar_g_balance_electro_secondary_refire;
+float autocvar_g_balance_electro_secondary_refire2;
+float autocvar_g_balance_electro_secondary_speed;
+float autocvar_g_balance_electro_reload_ammo;
+float autocvar_g_balance_electro_reload_time;
 float autocvar_g_balance_falldamage_deadminspeed;
 float autocvar_g_balance_falldamage_factor;
 float autocvar_g_balance_falldamage_maxdamage;
 float autocvar_g_balance_falldamage_minspeed;
+float autocvar_g_balance_fireball_primary_animtime;
+float autocvar_g_balance_fireball_primary_bfgdamage;
+float autocvar_g_balance_fireball_primary_bfgforce;
+float autocvar_g_balance_fireball_primary_bfgradius;
+float autocvar_g_balance_fireball_primary_damage;
+float autocvar_g_balance_fireball_primary_damageforcescale;
+float autocvar_g_balance_fireball_primary_edgedamage;
+float autocvar_g_balance_fireball_primary_force;
+float autocvar_g_balance_fireball_primary_health;
+float autocvar_g_balance_fireball_primary_laserburntime;
+float autocvar_g_balance_fireball_primary_laserdamage;
+float autocvar_g_balance_fireball_primary_laseredgedamage;
+float autocvar_g_balance_fireball_primary_laserradius;
+float autocvar_g_balance_fireball_primary_lifetime;
+float autocvar_g_balance_fireball_primary_radius;
+float autocvar_g_balance_fireball_primary_refire;
+float autocvar_g_balance_fireball_primary_refire2;
+float autocvar_g_balance_fireball_primary_speed;
+float autocvar_g_balance_fireball_secondary_animtime;
+float autocvar_g_balance_fireball_secondary_damage;
+float autocvar_g_balance_fireball_secondary_damageforcescale;
+float autocvar_g_balance_fireball_secondary_damagetime;
+float autocvar_g_balance_fireball_secondary_laserburntime;
+float autocvar_g_balance_fireball_secondary_laserdamage;
+float autocvar_g_balance_fireball_secondary_laseredgedamage;
+float autocvar_g_balance_fireball_secondary_laserradius;
+float autocvar_g_balance_fireball_secondary_lifetime;
+float autocvar_g_balance_fireball_secondary_refire;
+float autocvar_g_balance_fireball_secondary_speed;
+float autocvar_g_balance_fireball_secondary_speed_up;
 float autocvar_g_balance_firetransfer_damage;
 float autocvar_g_balance_firetransfer_time;
 float autocvar_g_balance_fuel_limit;
@@ -111,6 +261,75 @@ float autocvar_g_balance_grapplehook_speed_pull;
 float autocvar_g_balance_grapplehook_stretch;
 float autocvar_g_balance_grapplehook_damagedbycontents;
 float autocvar_g_balance_grapplehook_refire;
+float autocvar_g_balance_grenadelauncher_bouncefactor;
+float autocvar_g_balance_grenadelauncher_bouncestop;
+float autocvar_g_balance_grenadelauncher_primary_ammo;
+float autocvar_g_balance_grenadelauncher_primary_animtime;
+float autocvar_g_balance_grenadelauncher_primary_damage;
+float autocvar_g_balance_grenadelauncher_primary_damageforcescale;
+float autocvar_g_balance_grenadelauncher_primary_edgedamage;
+float autocvar_g_balance_grenadelauncher_primary_force;
+float autocvar_g_balance_grenadelauncher_primary_health;
+float autocvar_g_balance_grenadelauncher_primary_lifetime;
+float autocvar_g_balance_grenadelauncher_primary_lifetime_stick;
+float autocvar_g_balance_grenadelauncher_primary_radius;
+float autocvar_g_balance_grenadelauncher_primary_refire;
+float autocvar_g_balance_grenadelauncher_primary_remote_minbouncecnt;
+float autocvar_g_balance_grenadelauncher_primary_speed;
+float autocvar_g_balance_grenadelauncher_primary_speed_up;
+float autocvar_g_balance_grenadelauncher_primary_type;
+float autocvar_g_balance_grenadelauncher_secondary_ammo;
+float autocvar_g_balance_grenadelauncher_secondary_animtime;
+float autocvar_g_balance_grenadelauncher_secondary_damage;
+float autocvar_g_balance_grenadelauncher_secondary_damageforcescale;
+float autocvar_g_balance_grenadelauncher_secondary_edgedamage;
+float autocvar_g_balance_grenadelauncher_secondary_force;
+float autocvar_g_balance_grenadelauncher_secondary_health;
+float autocvar_g_balance_grenadelauncher_secondary_lifetime;
+float autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce;
+float autocvar_g_balance_grenadelauncher_secondary_lifetime_stick;
+float autocvar_g_balance_grenadelauncher_secondary_radius;
+float autocvar_g_balance_grenadelauncher_secondary_refire;
+float autocvar_g_balance_grenadelauncher_secondary_speed;
+float autocvar_g_balance_grenadelauncher_secondary_speed_up;
+float autocvar_g_balance_grenadelauncher_secondary_type;
+float autocvar_g_balance_grenadelauncher_reload_ammo;
+float autocvar_g_balance_grenadelauncher_reload_time;
+float autocvar_g_balance_hagar_primary_ammo;
+float autocvar_g_balance_hagar_primary_damage;
+float autocvar_g_balance_hagar_primary_edgedamage;
+float autocvar_g_balance_hagar_primary_force;
+float autocvar_g_balance_hagar_primary_health;
+float autocvar_g_balance_hagar_primary_damageforcescale;
+float autocvar_g_balance_hagar_primary_lifetime;
+float autocvar_g_balance_hagar_primary_radius;
+float autocvar_g_balance_hagar_primary_refire;
+float autocvar_g_balance_hagar_primary_speed;
+float autocvar_g_balance_hagar_secondary;
+float autocvar_g_balance_hagar_secondary_load;
+float autocvar_g_balance_hagar_secondary_load_speed;
+float autocvar_g_balance_hagar_secondary_load_spread;
+float autocvar_g_balance_hagar_secondary_load_spread_bias;
+float autocvar_g_balance_hagar_secondary_load_max;
+float autocvar_g_balance_hagar_secondary_load_hold;
+float autocvar_g_balance_hagar_secondary_load_releasedeath;
+float autocvar_g_balance_hagar_secondary_load_abort;
+float autocvar_g_balance_hagar_secondary_load_linkexplode;
+float autocvar_g_balance_hagar_secondary_load_animtime;
+float autocvar_g_balance_hagar_secondary_ammo;
+float autocvar_g_balance_hagar_secondary_damage;
+float autocvar_g_balance_hagar_secondary_edgedamage;
+float autocvar_g_balance_hagar_secondary_force;
+float autocvar_g_balance_hagar_secondary_health;
+float autocvar_g_balance_hagar_secondary_damageforcescale;
+float autocvar_g_balance_hagar_secondary_lifetime_min;
+float autocvar_g_balance_hagar_secondary_lifetime_rand;
+float autocvar_g_balance_hagar_secondary_radius;
+float autocvar_g_balance_hagar_secondary_refire;
+float autocvar_g_balance_hagar_secondary_speed;
+float autocvar_g_balance_hagar_secondary_spread;
+float autocvar_g_balance_hagar_reload_ammo;
+float autocvar_g_balance_hagar_reload_time;
 float autocvar_g_balance_health_limit;
 float autocvar_g_balance_health_regen;
 float autocvar_g_balance_health_regenlinear;
@@ -118,6 +337,54 @@ float autocvar_g_balance_health_regenstable;
 float autocvar_g_balance_health_rot;
 float autocvar_g_balance_health_rotlinear;
 float autocvar_g_balance_health_rotstable;
+float autocvar_g_balance_hlac_primary_ammo;
+float autocvar_g_balance_hlac_primary_animtime;
+float autocvar_g_balance_hlac_primary_damage;
+float autocvar_g_balance_hlac_primary_edgedamage;
+float autocvar_g_balance_hlac_primary_force;
+float autocvar_g_balance_hlac_primary_lifetime;
+float autocvar_g_balance_hlac_primary_radius;
+float autocvar_g_balance_hlac_primary_refire;
+float autocvar_g_balance_hlac_primary_speed;
+float autocvar_g_balance_hlac_primary_spread_add;
+float autocvar_g_balance_hlac_primary_spread_crouchmod;
+float autocvar_g_balance_hlac_primary_spread_max;
+float autocvar_g_balance_hlac_primary_spread_min;
+float autocvar_g_balance_hlac_secondary;
+float autocvar_g_balance_hlac_secondary_ammo;
+float autocvar_g_balance_hlac_secondary_animtime;
+float autocvar_g_balance_hlac_secondary_damage;
+float autocvar_g_balance_hlac_secondary_edgedamage;
+float autocvar_g_balance_hlac_secondary_force;
+float autocvar_g_balance_hlac_secondary_lifetime;
+float autocvar_g_balance_hlac_secondary_radius;
+float autocvar_g_balance_hlac_secondary_refire;
+float autocvar_g_balance_hlac_secondary_shots;
+float autocvar_g_balance_hlac_secondary_speed;
+float autocvar_g_balance_hlac_secondary_spread;
+float autocvar_g_balance_hlac_secondary_spread_crouchmod;
+float autocvar_g_balance_hlac_reload_ammo;
+float autocvar_g_balance_hlac_reload_time;
+float autocvar_g_balance_hook_primary_animtime;
+float autocvar_g_balance_hook_primary_fuel;
+float autocvar_g_balance_hook_primary_hooked_fuel;
+float autocvar_g_balance_hook_primary_hooked_time_free;
+float autocvar_g_balance_hook_primary_hooked_time_max;
+float autocvar_g_balance_hook_primary_refire;
+float autocvar_g_balance_hook_secondary_ammo;
+float autocvar_g_balance_hook_secondary_animtime;
+float autocvar_g_balance_hook_secondary_damage;
+float autocvar_g_balance_hook_secondary_duration;
+float autocvar_g_balance_hook_secondary_edgedamage;
+float autocvar_g_balance_hook_secondary_force;
+float autocvar_g_balance_hook_secondary_gravity;
+float autocvar_g_balance_hook_secondary_lifetime;
+float autocvar_g_balance_hook_secondary_power;
+float autocvar_g_balance_hook_secondary_radius;
+float autocvar_g_balance_hook_secondary_refire;
+float autocvar_g_balance_hook_secondary_speed;
+float autocvar_g_balance_hook_secondary_health;
+float autocvar_g_balance_hook_secondary_damageforcescale;
 float autocvar_g_balance_keyhunt_damageforcescale;
 float autocvar_g_balance_keyhunt_delay_collect;
 float autocvar_g_balance_keyhunt_delay_return;
@@ -135,6 +402,102 @@ float autocvar_g_balance_keyhunt_score_push;
 float autocvar_g_balance_keyhunt_throwvelocity;
 float autocvar_g_balance_kill_delay;
 float autocvar_g_balance_kill_antispam;
+float autocvar_g_balance_laser_primary_animtime;
+float autocvar_g_balance_laser_primary_damage;
+float autocvar_g_balance_laser_primary_delay;
+float autocvar_g_balance_laser_primary_edgedamage;
+float autocvar_g_balance_laser_primary_force;
+float autocvar_g_balance_laser_primary_force_other_scale;
+float autocvar_g_balance_laser_primary_force_velocitybias;
+float autocvar_g_balance_laser_primary_force_zscale;
+float autocvar_g_balance_laser_primary_lifetime;
+float autocvar_g_balance_laser_primary_radius;
+float autocvar_g_balance_laser_primary_refire;
+float autocvar_g_balance_laser_primary_shotangle;
+float autocvar_g_balance_laser_primary_speed;
+float autocvar_g_balance_laser_secondary;
+float autocvar_g_balance_laser_secondary_animtime;
+float autocvar_g_balance_laser_secondary_damage;
+float autocvar_g_balance_laser_secondary_edgedamage;
+float autocvar_g_balance_laser_secondary_force;
+float autocvar_g_balance_laser_secondary_force_other_scale;
+float autocvar_g_balance_laser_secondary_force_velocitybias;
+float autocvar_g_balance_laser_secondary_force_zscale;
+float autocvar_g_balance_laser_secondary_lifetime;
+float autocvar_g_balance_laser_secondary_radius;
+float autocvar_g_balance_laser_secondary_speed;
+float autocvar_g_balance_laser_reload_ammo;
+float autocvar_g_balance_laser_reload_time;
+float autocvar_g_balance_minelayer_ammo;
+float autocvar_g_balance_minelayer_animtime;
+float autocvar_g_balance_minelayer_damage;
+float autocvar_g_balance_minelayer_damageforcescale;
+float autocvar_g_balance_minelayer_detonatedelay;
+float autocvar_g_balance_minelayer_edgedamage;
+float autocvar_g_balance_minelayer_force;
+float autocvar_g_balance_minelayer_health;
+float autocvar_g_balance_minelayer_lifetime;
+float autocvar_g_balance_minelayer_lifetime_countdown;
+float autocvar_g_balance_minelayer_limit;
+float autocvar_g_balance_minelayer_protection;
+float autocvar_g_balance_minelayer_proximityradius;
+float autocvar_g_balance_minelayer_radius;
+float autocvar_g_balance_minelayer_refire;
+float autocvar_g_balance_minelayer_remote_damage;
+float autocvar_g_balance_minelayer_remote_edgedamage;
+float autocvar_g_balance_minelayer_remote_force;
+float autocvar_g_balance_minelayer_remote_radius;
+float autocvar_g_balance_minelayer_speed;
+float autocvar_g_balance_minelayer_time;
+float autocvar_g_balance_minelayer_reload_ammo;
+float autocvar_g_balance_minelayer_reload_time;
+float autocvar_g_balance_minstanex_ammo;
+float autocvar_g_balance_minstanex_laser_ammo;
+float autocvar_g_balance_minstanex_laser_animtime;
+float autocvar_g_balance_minstanex_laser_refire;
+float autocvar_g_balance_minstanex_animtime;
+float autocvar_g_balance_minstanex_refire;
+float autocvar_g_balance_minstanex_reload_ammo;
+float autocvar_g_balance_minstanex_reload_time;
+float autocvar_g_balance_nex_charge;
+float autocvar_g_balance_nex_charge_animlimit;
+float autocvar_g_balance_nex_charge_limit;
+float autocvar_g_balance_nex_charge_maxspeed;
+float autocvar_g_balance_nex_charge_mindmg;
+float autocvar_g_balance_nex_charge_minspeed;
+float autocvar_g_balance_nex_charge_rate;
+float autocvar_g_balance_nex_charge_rot_pause;
+float autocvar_g_balance_nex_charge_rot_rate;
+float autocvar_g_balance_nex_charge_shot_multiplier;
+float autocvar_g_balance_nex_charge_start;
+float autocvar_g_balance_nex_charge_velocity_rate;
+float autocvar_g_balance_nex_primary_ammo;
+float autocvar_g_balance_nex_primary_animtime;
+float autocvar_g_balance_nex_primary_damage;
+float autocvar_g_balance_nex_primary_damagefalloff_forcehalflife;
+float autocvar_g_balance_nex_primary_damagefalloff_halflife;
+float autocvar_g_balance_nex_primary_damagefalloff_maxdist;
+float autocvar_g_balance_nex_primary_damagefalloff_mindist;
+float autocvar_g_balance_nex_primary_force;
+float autocvar_g_balance_nex_primary_refire;
+float autocvar_g_balance_nex_secondary;
+float autocvar_g_balance_nex_secondary_ammo;
+float autocvar_g_balance_nex_secondary_animtime;
+float autocvar_g_balance_nex_secondary_charge;
+float autocvar_g_balance_nex_secondary_charge_rate;
+float autocvar_g_balance_nex_secondary_chargepool;
+float autocvar_g_balance_nex_secondary_chargepool_pause_health_regen;
+float autocvar_g_balance_nex_secondary_chargepool_pause_regen;
+float autocvar_g_balance_nex_secondary_chargepool_regen;
+float autocvar_g_balance_nex_secondary_damage;
+float autocvar_g_balance_nex_secondary_damagefalloff_forcehalflife;
+float autocvar_g_balance_nex_secondary_damagefalloff_halflife;
+float autocvar_g_balance_nex_secondary_damagefalloff_maxdist;
+float autocvar_g_balance_nex_secondary_damagefalloff_mindist;
+float autocvar_g_balance_nex_secondary_force;
+float autocvar_g_balance_nex_secondary_refire;
+float autocvar_g_balance_nex_reload_ammo;
+float autocvar_g_balance_nex_reload_time;
 float autocvar_g_balance_nexball_primary_animtime;
 float autocvar_g_balance_nexball_primary_refire;
 float autocvar_g_balance_nexball_primary_speed;
@@ -144,13 +507,11 @@ float autocvar_g_balance_nexball_secondary_lifetime;
 float autocvar_g_balance_nexball_secondary_refire;
 float autocvar_g_balance_nexball_secondary_speed;
 float autocvar_g_balance_nix_ammo_cells;
-float autocvar_g_balance_nix_ammo_plasma;
 float autocvar_g_balance_nix_ammo_fuel;
 float autocvar_g_balance_nix_ammo_nails;
 float autocvar_g_balance_nix_ammo_rockets;
 float autocvar_g_balance_nix_ammo_shells;
 float autocvar_g_balance_nix_ammoincr_cells;
-float autocvar_g_balance_nix_ammoincr_plasma;
 float autocvar_g_balance_nix_ammoincr_fuel;
 float autocvar_g_balance_nix_ammoincr_nails;
 float autocvar_g_balance_nix_ammoincr_rockets;
@@ -168,6 +529,15 @@ float autocvar_g_balance_pause_health_rot;
 float autocvar_g_balance_pause_health_rot_spawn;
 float autocvar_g_balance_portal_health;
 float autocvar_g_balance_portal_lifetime;
+float autocvar_g_balance_porto_primary_animtime;
+float autocvar_g_balance_porto_primary_lifetime;
+float autocvar_g_balance_porto_primary_refire;
+float autocvar_g_balance_porto_primary_speed;
+float autocvar_g_balance_porto_secondary;
+float autocvar_g_balance_porto_secondary_animtime;
+float autocvar_g_balance_porto_secondary_lifetime;
+float autocvar_g_balance_porto_secondary_refire;
+float autocvar_g_balance_porto_secondary_speed;
 float autocvar_g_balance_powerup_invincible_takedamage;
 float autocvar_g_balance_powerup_invincible_time;
 float autocvar_g_balance_powerup_strength_damage;
@@ -176,10 +546,133 @@ float autocvar_g_balance_powerup_strength_selfdamage;
 float autocvar_g_balance_powerup_strength_selfforce;
 float autocvar_g_balance_powerup_strength_time;
 float autocvar_g_balance_superweapons_time;
+float autocvar_g_balance_rocketlauncher_ammo;
+float autocvar_g_balance_rocketlauncher_animtime;
+float autocvar_g_balance_rocketlauncher_damage;
+float autocvar_g_balance_rocketlauncher_damageforcescale;
+float autocvar_g_balance_rocketlauncher_detonatedelay;
+float autocvar_g_balance_rocketlauncher_edgedamage;
+float autocvar_g_balance_rocketlauncher_force;
+float autocvar_g_balance_rocketlauncher_guidedelay;
+float autocvar_g_balance_rocketlauncher_guidegoal;
+float autocvar_g_balance_rocketlauncher_guiderate;
+float autocvar_g_balance_rocketlauncher_guideratedelay;
+float autocvar_g_balance_rocketlauncher_guidestop;
+float autocvar_g_balance_rocketlauncher_health;
+float autocvar_g_balance_rocketlauncher_lifetime;
+float autocvar_g_balance_rocketlauncher_radius;
+float autocvar_g_balance_rocketlauncher_refire;
+float autocvar_g_balance_rocketlauncher_remote_damage;
+float autocvar_g_balance_rocketlauncher_remote_edgedamage;
+float autocvar_g_balance_rocketlauncher_remote_force;
+float autocvar_g_balance_rocketlauncher_remote_radius;
+float autocvar_g_balance_rocketlauncher_speed;
+float autocvar_g_balance_rocketlauncher_speedaccel;
+float autocvar_g_balance_rocketlauncher_speedstart;
+float autocvar_g_balance_rocketlauncher_reload_ammo;
+float autocvar_g_balance_rocketlauncher_reload_time;
+float autocvar_g_balance_seeker_type;
+float autocvar_g_balance_seeker_flac_ammo;
+float autocvar_g_balance_seeker_flac_animtime;
+float autocvar_g_balance_seeker_flac_damage;
+float autocvar_g_balance_seeker_flac_edgedamage;
+float autocvar_g_balance_seeker_flac_force;
+float autocvar_g_balance_seeker_flac_lifetime;
+float autocvar_g_balance_seeker_flac_lifetime_rand;
+float autocvar_g_balance_seeker_flac_radius;
+float autocvar_g_balance_seeker_flac_refire;
+float autocvar_g_balance_seeker_missile_accel;
+float autocvar_g_balance_seeker_missile_ammo;
+float autocvar_g_balance_seeker_missile_animtime;
+float autocvar_g_balance_seeker_missile_count;
+float autocvar_g_balance_seeker_missile_damage;
+float autocvar_g_balance_seeker_missile_damageforcescale;
+float autocvar_g_balance_seeker_missile_decel;
+float autocvar_g_balance_seeker_missile_delay;
+float autocvar_g_balance_seeker_missile_edgedamage;
+float autocvar_g_balance_seeker_missile_force;
+float autocvar_g_balance_seeker_missile_health;
+float autocvar_g_balance_seeker_missile_lifetime;
+float autocvar_g_balance_seeker_missile_proxy;
+float autocvar_g_balance_seeker_missile_proxy_delay;
+float autocvar_g_balance_seeker_missile_proxy_maxrange;
+float autocvar_g_balance_seeker_missile_radius;
+float autocvar_g_balance_seeker_missile_refire;
+float autocvar_g_balance_seeker_missile_smart;
+float autocvar_g_balance_seeker_missile_smart_mindist;
+float autocvar_g_balance_seeker_missile_smart_trace_max;
+float autocvar_g_balance_seeker_missile_smart_trace_min;
+float autocvar_g_balance_seeker_missile_speed_max;
+float autocvar_g_balance_seeker_missile_turnrate;
+float autocvar_g_balance_seeker_tag_ammo;
+float autocvar_g_balance_seeker_tag_animtime;
+float autocvar_g_balance_seeker_tag_damageforcescale;
+float autocvar_g_balance_seeker_tag_health;
+float autocvar_g_balance_seeker_tag_lifetime;
+float autocvar_g_balance_seeker_tag_refire;
+float autocvar_g_balance_seeker_tag_speed;
+float autocvar_g_balance_seeker_tag_tracker_lifetime;
+float autocvar_g_balance_seeker_reload_ammo;
+float autocvar_g_balance_seeker_reload_time;
 float autocvar_g_balance_selfdamagepercent;
+float autocvar_g_balance_shotgun_primary_ammo;
+float autocvar_g_balance_shotgun_primary_animtime;
+float autocvar_g_balance_shotgun_primary_bullets;
+float autocvar_g_balance_shotgun_primary_damage;
+float autocvar_g_balance_shotgun_primary_force;
+float autocvar_g_balance_shotgun_primary_refire;
+float autocvar_g_balance_shotgun_primary_solidpenetration;
+float autocvar_g_balance_shotgun_primary_spread;
+float autocvar_g_balance_shotgun_secondary;
+float autocvar_g_balance_shotgun_secondary_animtime;
+float autocvar_g_balance_shotgun_secondary_damage;
+float autocvar_g_balance_shotgun_secondary_force;
+float autocvar_g_balance_shotgun_secondary_melee_delay;
+float autocvar_g_balance_shotgun_secondary_melee_range;
+float autocvar_g_balance_shotgun_secondary_melee_swing_side;
+float autocvar_g_balance_shotgun_secondary_melee_swing_up;
+float autocvar_g_balance_shotgun_secondary_melee_time;
+float autocvar_g_balance_shotgun_secondary_melee_traces;
+float autocvar_g_balance_shotgun_secondary_melee_no_doubleslap;
+float autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage;
+float autocvar_g_balance_shotgun_secondary_melee_multihit;
+float autocvar_g_balance_shotgun_secondary_refire;
+float autocvar_g_balance_shotgun_reload_ammo;
+float autocvar_g_balance_shotgun_reload_time;
 float autocvar_g_balance_teams;
 float autocvar_g_balance_teams_prevent_imbalance;
 float autocvar_g_balance_teams_scorefactor;
+float autocvar_g_balance_tuba_animtime;
+float autocvar_g_balance_tuba_attenuation;
+float autocvar_g_balance_tuba_damage;
+float autocvar_g_balance_tuba_edgedamage;
+float autocvar_g_balance_tuba_force;
+float autocvar_g_balance_tuba_radius;
+float autocvar_g_balance_tuba_refire;
+float autocvar_g_balance_uzi_burst;
+float autocvar_g_balance_uzi_burst_ammo;
+float autocvar_g_balance_uzi_burst_animtime;
+float autocvar_g_balance_uzi_burst_refire;
+float autocvar_g_balance_uzi_burst_refire2;
+float autocvar_g_balance_uzi_burst_spread;
+float autocvar_g_balance_uzi_first;
+float autocvar_g_balance_uzi_first_ammo;
+float autocvar_g_balance_uzi_first_damage;
+float autocvar_g_balance_uzi_first_force;
+float autocvar_g_balance_uzi_first_refire;
+float autocvar_g_balance_uzi_first_spread;
+float autocvar_g_balance_uzi_mode;
+float autocvar_g_balance_uzi_solidpenetration;
+float autocvar_g_balance_uzi_spread_add;
+float autocvar_g_balance_uzi_spread_max;
+float autocvar_g_balance_uzi_spread_min;
+float autocvar_g_balance_uzi_sustained_ammo;
+float autocvar_g_balance_uzi_sustained_damage;
+float autocvar_g_balance_uzi_sustained_force;
+float autocvar_g_balance_uzi_sustained_refire;
+float autocvar_g_balance_uzi_sustained_spread;
+float autocvar_g_balance_uzi_reload_ammo;
+float autocvar_g_balance_uzi_reload_time;
 float autocvar_g_ballistics_density_corpse;
 float autocvar_g_ballistics_density_player;
 float autocvar_g_ballistics_mindistance;
@@ -438,7 +931,6 @@ float autocvar_g_onslaught_cp_health;
 float autocvar_g_onslaught_cp_regen;
 float autocvar_g_onslaught_gen_health;
 float autocvar_g_pickup_cells_max;
-float autocvar_g_pickup_plasma_max;
 float autocvar_g_pickup_fuel_max;
 float autocvar_g_pickup_items;
 float autocvar_g_pickup_nails_max;
@@ -479,6 +971,7 @@ float autocvar_g_spawn_furthest;
 float autocvar_g_spawn_useallspawns;
 float autocvar_g_spawnpoints_auto_move_out_of_solid;
 #define autocvar_g_spawnshieldtime cvar("g_spawnshieldtime")
+#define autocvar_g_start_weapon_laser cvar("g_start_weapon_laser")
 float autocvar_g_tdm_team_spawns;
 float autocvar_g_tdm_point_limit;
 float autocvar_g_tdm_point_leadlimit;
@@ -651,7 +1144,7 @@ float autocvar_sv_maxairstrafespeed;
 float autocvar_sv_maxspeed;
 string autocvar_sv_motd;
 float autocvar_sv_precacheplayermodels;
-//float autocvar_sv_precacheweapons; // WEAPONTODO?
+float autocvar_sv_precacheweapons;
 float autocvar_sv_q3acompat_machineshotgunswap;
 float autocvar_sv_ready_restart;
 float autocvar_sv_ready_restart_after_countdown;
diff --git a/qcsrc/server/bot/aim.qc b/qcsrc/server/bot/aim.qc
index 0ae331247..61f4ab5e8 100644
--- a/qcsrc/server/bot/aim.qc
+++ b/qcsrc/server/bot/aim.qc
@@ -339,12 +339,12 @@ float bot_aim(float shotspeed, float shotspeedupward, float maxshottime, float a
 	shotspeedupward *= g_weaponspeedfactor;
 	if (!shotspeed)
 	{
-		dprint("bot_aim: WARNING: weapon ", WEP_NAME(self.weapon), " shotspeed is zero!\n");
+		dprint("bot_aim: WARNING: weapon ", W_Name(self.weapon), " shotspeed is zero!\n");
 		shotspeed = 1000000;
 	}
 	if (!maxshottime)
 	{
-		dprint("bot_aim: WARNING: weapon ", WEP_NAME(self.weapon), " maxshottime is zero!\n");
+		dprint("bot_aim: WARNING: weapon ", W_Name(self.weapon), " maxshottime is zero!\n");
 		maxshottime = 1;
 	}
 	makevectors(self.v_angle);
diff --git a/qcsrc/server/bot/havocbot/havocbot.qc b/qcsrc/server/bot/havocbot/havocbot.qc
index 2ce9706a2..2e57eecb3 100644
--- a/qcsrc/server/bot/havocbot/havocbot.qc
+++ b/qcsrc/server/bot/havocbot/havocbot.qc
@@ -92,7 +92,7 @@ void havocbot_ai()
 
 		if(self.weapons)
 		{
-			WEP_ACTION(self.weapon, WR_AIM);
+			weapon_action(self.weapon, WR_AIM);
 			if (autocvar_bot_nofire || IS_INDEPENDENT_PLAYER(self))
 			{
 				self.BUTTON_ATCK = FALSE;
@@ -164,7 +164,7 @@ void havocbot_ai()
 			for(i = WEP_FIRST; i <= WEP_LAST; ++i)
 			{
 				e = get_weaponinfo(i);
-				if ((self.weapons & WepSet_FromWeapon(i)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < e.reloading_ammo))
+				if ((self.weapons & WepSet_FromWeapon(i)) && (e.spawnflags & WEP_FLAG_RELOADABLE) && (self.weapon_load[i] < cvar(strcat("g_balance_", e.netname, "_reload_ammo"))))
 					self.switchweapon = i;
 			}
 		}
@@ -590,10 +590,10 @@ void havocbot_movetogoal()
 
 			return;
 		}
-		else if(self.health>WEP_CVAR(devastator, damage)*0.5)
+		else if(self.health>autocvar_g_balance_rocketlauncher_damage*0.5)
 		{
 			if(self.velocity_z < 0)
-			if(client_hasweapon(self, WEP_DEVASTATOR, TRUE, FALSE))
+			if(client_hasweapon(self, WEP_ROCKET_LAUNCHER, TRUE, FALSE))
 			{
 				self.movement_x = maxspeed;
 
@@ -607,10 +607,10 @@ void havocbot_movetogoal()
 					return;
 				}
 
-				self.switchweapon = WEP_DEVASTATOR;
+				self.switchweapon = WEP_ROCKET_LAUNCHER;
 				self.v_angle_x = 90;
 				self.BUTTON_ATCK = TRUE;
-				self.rocketjumptime = time + WEP_CVAR(devastator, detonatedelay);
+				self.rocketjumptime = time + autocvar_g_balance_rocketlauncher_detonatedelay;
 				return;
 			}
 		}
@@ -956,7 +956,7 @@ float havocbot_chooseweapon_checkreload(float new_weapon)
 		for(i = WEP_FIRST; i <= WEP_LAST; ++i)
 		{
 			// if we are out of ammo for all other weapons, it's an emergency to switch to anything else
-			if (WEP_ACTION(i, WR_CHECKAMMO1) + WEP_ACTION(i, WR_CHECKAMMO2))
+			if (weapon_action(i, WR_CHECKAMMO1) + weapon_action(i, WR_CHECKAMMO2))
 				other_weapon_available = TRUE;
 		}
 		if(other_weapon_available)
@@ -982,7 +982,7 @@ void havocbot_chooseweapon()
 	{
 		// If no weapon was chosen get the first available weapon
 		if(self.weapon==0)
-		for(i=WEP_BLASTER + 1; i < WEP_COUNT ; ++i) // Samual: This seems strange compared to other weapon loops...
+		for(i=WEP_LASER + 1; i < WEP_COUNT ; ++i)
 		{
 			if(client_hasweapon(self, i, TRUE, FALSE))
 			{
diff --git a/qcsrc/server/bot/havocbot/roles.qc b/qcsrc/server/bot/havocbot/roles.qc
index 7e3ddbb43..2104c3443 100644
--- a/qcsrc/server/bot/havocbot/roles.qc
+++ b/qcsrc/server/bot/havocbot/roles.qc
@@ -98,10 +98,7 @@ void havocbot_goalrating_items(float ratingscale, vector org, float sradius)
 					if (head.ammo_rockets && player.ammo_rockets > self.ammo_rockets)
 						continue;
 
-					if (head.ammo_cells && player.ammo_cells > self.ammo_cells)
-						continue;
-
-					if (head.ammo_plasma && player.ammo_plasma > self.ammo_plasma)
+					if (head.ammo_cells && player.ammo_cells > self.ammo_cells )
 						continue;
 
 					discard = FALSE;
diff --git a/qcsrc/server/cheats.qc b/qcsrc/server/cheats.qc
index 22b793d39..c4b3fe67d 100644
--- a/qcsrc/server/cheats.qc
+++ b/qcsrc/server/cheats.qc
@@ -140,7 +140,6 @@ float CheatImpulse(float i)
 			self.personal.ammo_rockets = self.ammo_rockets;
 			self.personal.ammo_nails = self.ammo_nails;
 			self.personal.ammo_cells = self.ammo_cells;
-			self.personal.ammo_plasma = self.ammo_plasma;
 			self.personal.ammo_shells = self.ammo_shells;
 			self.personal.ammo_fuel = self.ammo_fuel;
 			self.personal.health = self.health;
@@ -198,7 +197,6 @@ float CheatImpulse(float i)
 				self.ammo_rockets = self.personal.ammo_rockets;
 				self.ammo_nails = self.personal.ammo_nails;
 				self.ammo_cells = self.personal.ammo_cells;
-				self.ammo_plasma = self.personal.ammo_plasma;
 				self.ammo_shells = self.personal.ammo_shells;
 				self.ammo_fuel = self.personal.ammo_fuel;
 				self.health = self.personal.health;
@@ -266,7 +264,7 @@ float CheatImpulse(float i)
 
 			e2 = spawn();
 			setorigin(e2, e.origin);
-			RadiusDamage(e2, self, 1000, 0, 128, world, world, 500, DEATH_CHEAT, e);
+			RadiusDamage(e2, self, 1000, 0, 128, world, 500, DEATH_CHEAT, e);
 			remove(e2);
 
 			print("404 Sportsmanship not found.\n");
diff --git a/qcsrc/server/cl_client.qc b/qcsrc/server/cl_client.qc
index 2167bdb55..b3c6b6577 100644
--- a/qcsrc/server/cl_client.qc
+++ b/qcsrc/server/cl_client.qc
@@ -417,11 +417,11 @@ void PutClientInServer (void)
 		self.effects |= EF_TELEPORT_BIT | EF_RESTARTANIM_BIT;
 		self.air_finished = time + 12;
 		self.dmg = 2;
-		if(WEP_CVAR(vortex, charge))
+		if(autocvar_g_balance_nex_charge)
 		{
-			if(WEP_CVAR_SEC(vortex, chargepool))
-				self.vortex_chargepool_ammo = 1;
-			self.vortex_charge = WEP_CVAR(vortex, charge_start);
+			if(autocvar_g_balance_nex_secondary_chargepool)
+				self.nex_chargepool_ammo = 1;
+			self.nex_charge = autocvar_g_balance_nex_charge_start;
 		}
 
 		if(warmup_stage)
@@ -430,7 +430,6 @@ void PutClientInServer (void)
 			self.ammo_nails = warmup_start_ammo_nails;
 			self.ammo_rockets = warmup_start_ammo_rockets;
 			self.ammo_cells = warmup_start_ammo_cells;
-			self.ammo_plasma = warmup_start_ammo_plasma;
 			self.ammo_fuel = warmup_start_ammo_fuel;
 			self.health = warmup_start_health;
 			self.armorvalue = warmup_start_armorvalue;
@@ -442,7 +441,6 @@ void PutClientInServer (void)
 			self.ammo_nails = start_ammo_nails;
 			self.ammo_rockets = start_ammo_rockets;
 			self.ammo_cells = start_ammo_cells;
-			self.ammo_plasma = start_ammo_plasma;
 			self.ammo_fuel = start_ammo_fuel;
 			self.health = start_health;
 			self.armorvalue = start_armorvalue;
@@ -454,13 +452,13 @@ void PutClientInServer (void)
 		else
 			self.superweapons_finished = 0;
 
-		if(g_weaponarena_random) // WEAPONTODO: more stuff that should be in a mutator. also: rename those cvars
+		if(g_weaponarena_random)
 		{
 			if(g_weaponarena_random_with_laser)
-				self.weapons &= ~WEPSET_BLASTER;
+				self.weapons &= ~WEPSET_LASER;
 			W_RandomWeapons(self, g_weaponarena_random);
 			if(g_weaponarena_random_with_laser)
-				self.weapons |= WEPSET_BLASTER;
+				self.weapons |= WEPSET_LASER;
 		}
 
 		self.items = start_items;
@@ -565,13 +563,13 @@ void PutClientInServer (void)
 		// reset fields the weapons may use
 		for (j = WEP_FIRST; j <= WEP_LAST; ++j)
 		{
-			WEP_ACTION(j, WR_RESETPLAYER);
+			weapon_action(j, WR_RESETPLAYER);
 
 			// all weapons must be fully loaded when we spawn
 			entity e;
 			e = get_weaponinfo(j);
 			if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
-				self.(weapon_load[j]) = e.reloading_ammo;
+				self.(weapon_load[j]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
 		}
 
 		oldself = self;
@@ -625,27 +623,30 @@ float ClientInit_SendEntity(entity to, float sf)
 	WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[1]));
 	WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[2]));
 	WriteInt24_t(MSG_ENTITY, compressShotOrigin(hook_shotorigin[3]));
-	WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[0]));
-	WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[1]));
-	WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[2]));
-	WriteInt24_t(MSG_ENTITY, compressShotOrigin(arc_shotorigin[3]));
-
+	WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[0]));
+	WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[1]));
+	WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[2]));
+	WriteInt24_t(MSG_ENTITY, compressShotOrigin(electro_shotorigin[3]));
+	WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[0]));
+	WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[1]));
+	WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[2]));
+	WriteInt24_t(MSG_ENTITY, compressShotOrigin(gauntlet_shotorigin[3]));
 	if(sv_foginterval && world.fog != "")
 		WriteString(MSG_ENTITY, world.fog);
 	else
 		WriteString(MSG_ENTITY, "");
 	WriteByte(MSG_ENTITY, self.count * 255.0); // g_balance_armor_blockpercent
-	WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_mortar_bouncefactor // WEAPONTODO
-	WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_mortar_bouncestop
-	WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_mortar_bouncefactor
-	WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_mortar_bouncestop
-	WriteByte(MSG_ENTITY, WEP_CVAR(vortex, secondary)); // client has to know if it should zoom or not // WEAPONTODO
-	WriteByte(MSG_ENTITY, WEP_CVAR(rifle, secondary)); // client has to know if it should zoom or not // WEAPONTODO
+	WriteCoord(MSG_ENTITY, self.bouncefactor); // g_balance_grenadelauncher_bouncefactor
+	WriteCoord(MSG_ENTITY, self.bouncestop); // g_balance_grenadelauncher_bouncestop
+	WriteCoord(MSG_ENTITY, self.ebouncefactor); // g_balance_grenadelauncher_bouncefactor
+	WriteCoord(MSG_ENTITY, self.ebouncestop); // g_balance_grenadelauncher_bouncestop
+	WriteByte(MSG_ENTITY, autocvar_g_balance_nex_secondary); // client has to know if it should zoom or not
+	WriteByte(MSG_ENTITY, autocvar_g_balance_rifle_secondary); // client has to know if it should zoom or not
 	WriteByte(MSG_ENTITY, serverflags); // client has to know if it should zoom or not
-	WriteByte(MSG_ENTITY, WEP_CVAR(minelayer, limit)); // minelayer max mines // WEAPONTODO
-	WriteByte(MSG_ENTITY, WEP_CVAR_SEC(hagar, load_max)); // hagar max loadable rockets // WEAPONTODO
+	WriteByte(MSG_ENTITY, autocvar_g_balance_minelayer_limit); // minelayer max mines
+	WriteByte(MSG_ENTITY, autocvar_g_balance_hagar_secondary_load_max); // hagar max loadable rockets
 	WriteCoord(MSG_ENTITY, autocvar_g_trueaim_minrange);
-	WriteByte(MSG_ENTITY, WEP_CVAR(porto, secondary)); // WEAPONTODO
+	WriteByte(MSG_ENTITY, autocvar_g_balance_porto_secondary);
 	return TRUE;
 }
 
@@ -657,14 +658,14 @@ void ClientInit_CheckUpdate()
 		self.count = autocvar_g_balance_armor_blockpercent;
 		self.SendFlags |= 1;
 	}
-	if(self.bouncefactor != autocvar_g_balance_mortar_bouncefactor) // WEAPONTODO
+	if(self.bouncefactor != autocvar_g_balance_grenadelauncher_bouncefactor)
 	{
-		self.bouncefactor = autocvar_g_balance_mortar_bouncefactor;
+		self.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor;
 		self.SendFlags |= 1;
 	}
-	if(self.bouncestop != autocvar_g_balance_mortar_bouncestop)
+	if(self.bouncestop != autocvar_g_balance_grenadelauncher_bouncestop)
 	{
-		self.bouncestop = autocvar_g_balance_mortar_bouncestop;
+		self.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop;
 		self.SendFlags |= 1;
 	}
 	if(self.ebouncefactor != autocvar_g_balance_electro_secondary_bouncefactor)
@@ -1191,7 +1192,13 @@ void ClientConnect (void)
 	if(!sv_foginterval && world.fog != "")
 		stuffcmd(self, strcat("\nfog ", world.fog, "\nr_fog_exp2 0\nr_drawfog 1\n"));
 
-	W_HitPlotOpen(self);
+	if(autocvar_g_hitplots || strstrofs(strcat(" ", autocvar_g_hitplots_individuals, " "), strcat(" ", self.netaddress, " "), 0) >= 0)
+	{
+		self.hitplotfh = fopen(strcat("hits-", matchid, "-", self.netaddress, "-", ftos(self.playerid), ".plot"), FILE_WRITE);
+		fputs(self.hitplotfh, strcat("#name ", self.netname, "\n"));
+	}
+	else
+		self.hitplotfh = -1;
 
 	if(autocvar_sv_teamnagger && !(autocvar_bot_vs_human && (c3==-1 && c4==-1)) && !g_ca && !g_cts && !g_race) // teamnagger is currently bad for ca, race & cts
 		send_CSQC_teamnagger();
@@ -1231,7 +1238,11 @@ void ClientDisconnect (void)
 
 	CheatShutdownClient();
 
-	W_HitPlotClose(self);
+	if(self.hitplotfh >= 0)
+	{
+		fclose(self.hitplotfh);
+		self.hitplotfh = -1;
+	}
 
 	anticheat_report();
 	anticheat_shutdown();
@@ -1671,7 +1682,6 @@ void SpectateCopy(entity spectatee) {
 	self.armortype = spectatee.armortype;
 	self.armorvalue = spectatee.armorvalue;
 	self.ammo_cells = spectatee.ammo_cells;
-	self.ammo_plasma = spectatee.ammo_plasma;
 	self.ammo_shells = spectatee.ammo_shells;
 	self.ammo_nails = spectatee.ammo_nails;
 	self.ammo_rockets = spectatee.ammo_rockets;
@@ -1692,8 +1702,8 @@ void SpectateCopy(entity spectatee) {
 	self.switchweapon = spectatee.switchweapon;
 	self.switchingweapon = spectatee.switchingweapon;
 	self.weapon = spectatee.weapon;
-	self.vortex_charge = spectatee.vortex_charge;
-	self.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo;
+	self.nex_charge = spectatee.nex_charge;
+	self.nex_chargepool_ammo = spectatee.nex_chargepool_ammo;
 	self.hagar_load = spectatee.hagar_load;
 	self.minelayer_mines = spectatee.minelayer_mines;
 	self.punchangle = spectatee.punchangle;
@@ -2274,17 +2284,17 @@ void PlayerPreThink (void)
 
 		if(frametime)
 		{
-			if(self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge))
+			if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge)
 			{
-				self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
-				self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
-				self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.vortex_charge / WEP_CVAR(vortex, charge_animlimit));
+				self.weaponentity_glowmod_x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
+				self.weaponentity_glowmod_y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
+				self.weaponentity_glowmod_z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, self.nex_charge / autocvar_g_balance_nex_charge_animlimit);
 
-				if(self.vortex_charge > WEP_CVAR(vortex, charge_animlimit))
+				if(self.nex_charge > autocvar_g_balance_nex_charge_animlimit)
 				{
-					self.weaponentity_glowmod_x = self.weaponentity_glowmod_x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
-					self.weaponentity_glowmod_y = self.weaponentity_glowmod_y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
-					self.weaponentity_glowmod_z = self.weaponentity_glowmod_z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.vortex_charge - WEP_CVAR(vortex, charge_animlimit)) / (1 - WEP_CVAR(vortex, charge_animlimit));
+					self.weaponentity_glowmod_x = self.weaponentity_glowmod_x + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
+					self.weaponentity_glowmod_y = self.weaponentity_glowmod_y + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
+					self.weaponentity_glowmod_z = self.weaponentity_glowmod_z + autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (self.nex_charge - autocvar_g_balance_nex_charge_animlimit) / (1 - autocvar_g_balance_nex_charge_animlimit);
 				}
 			}
 			else
@@ -2367,10 +2377,7 @@ void PlayerPreThink (void)
 			do_crouch = 0;
 		if(self.frozen)
 			do_crouch = 0;
-
-		// WEAPONTODO: THIS SHIT NEEDS TO GO EVENTUALLY
-		// It cannot be predicted by the engine! 
-		if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
+		if(self.weapon == WEP_SHOTGUN && self.weaponentity.wframe == WFRAME_FIRE2 && time < self.weapon_nextthink)
 			do_crouch = 0;
 
 		if (do_crouch)
@@ -2418,10 +2425,9 @@ void PlayerPreThink (void)
 
 		player_regen();
 
-		// WEAPONTODO: Add a weapon request for this 
 		// rot nex charge to the charge limit
-		if(WEP_CVAR(vortex, charge_rot_rate) && self.vortex_charge > WEP_CVAR(vortex, charge_limit) && self.vortex_charge_rottime < time)
-			self.vortex_charge = bound(WEP_CVAR(vortex, charge_limit), self.vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1);
+		if(autocvar_g_balance_nex_charge_rot_rate && self.nex_charge > autocvar_g_balance_nex_charge_limit && self.nex_charge_rottime < time)
+			self.nex_charge = bound(autocvar_g_balance_nex_charge_limit, self.nex_charge - autocvar_g_balance_nex_charge_rot_rate * frametime / W_TICSPERFRAME, 1);
 
 		if(frametime)
 			player_anim();
@@ -2445,9 +2451,8 @@ void PlayerPreThink (void)
 		SpectatorThink();
 	}
 
-	// WEAPONTODO: Add weapon request for this
 	if(!zoomstate_set)
-		SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_VORTEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && WEP_CVAR(rifle, secondary) == 0)); // WEAPONTODO
+		SetZoomState(self.BUTTON_ZOOM || self.BUTTON_ZOOMSCRIPT || (self.BUTTON_ATCK2 && self.weapon == WEP_NEX) || (self.BUTTON_ATCK2 && self.weapon == WEP_RIFLE && autocvar_g_balance_rifle_secondary == 0));
 
 	float oldspectatee_status;
 	oldspectatee_status = self.spectatee_status;
@@ -2487,7 +2492,6 @@ void PlayerPreThink (void)
 
 	target_voicescript_next(self);
 
-	// WEAPONTODO: Move into weaponsystem somehow
 	// if a player goes unarmed after holding a loaded weapon, empty his clip size and remove the crosshair ammo ring
 	if(!self.weapon)
 		self.clip_load = self.clip_size = 0;
diff --git a/qcsrc/server/cl_impulse.qc b/qcsrc/server/cl_impulse.qc
index c6ede7f98..c9896bc74 100644
--- a/qcsrc/server/cl_impulse.qc
+++ b/qcsrc/server/cl_impulse.qc
@@ -68,8 +68,8 @@ void ImpulseCommands (void)
 		// weapon switching impulses
 		if(self.deadflag == DEAD_NO)
 			W_NextWeaponOnImpulse(imp);
-		//else
-		//	self.impulse = imp; // retry in next frame
+		else
+			self.impulse = imp; // retry in next frame
 	}
 	else if(imp >= 10 && imp <= 20)
 	{
@@ -78,37 +78,37 @@ void ImpulseCommands (void)
 			switch(imp)
 			{
 				case 10:
-					W_NextWeapon(0);
+					W_NextWeapon (0);
 					break;
 				case 11:
 					W_LastWeapon();
 					break;
 				case 12:
-					W_PreviousWeapon(0);
+					W_PreviousWeapon (0);
 					break;
 				case 13:
-					W_SwitchWeapon(w_getbestweapon(self));
+					W_SwitchWeapon (w_getbestweapon(self));
 					break;
 				case 14:
 					W_NextWeaponOnImpulse(0);
 					break;
 				case 15:
-					W_NextWeapon(2);
+					W_NextWeapon (2);
 					break;
 				case 16:
-					W_PreviousWeapon(2);
+					W_PreviousWeapon (2);
 					break;
 				case 17:
 					W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750, FALSE), '0 0 0', TRUE);
 					break;
 				case 18:
-					W_NextWeapon(1);
+					W_NextWeapon (1);
 					break;
 				case 19:
-					W_PreviousWeapon(1);
+					W_PreviousWeapon (1);
 					break;
 				case 20:
-					WEP_ACTION(self.weapon, WR_RELOAD);
+					W_TriggerReload ();
 					break;
 			}
 		}
diff --git a/qcsrc/server/cl_physics.qc b/qcsrc/server/cl_physics.qc
index 0cae2a261..14747fa99 100644
--- a/qcsrc/server/cl_physics.qc
+++ b/qcsrc/server/cl_physics.qc
@@ -1301,16 +1301,15 @@ void SV_PlayerPhysics()
 		}
 	}
 
-	// WEAPONTODO
 	float xyspeed;
 	xyspeed = vlen('1 0 0' * self.velocity_x + '0 1 0' * self.velocity_y);
-	if(self.weapon == WEP_VORTEX && WEP_CVAR(vortex, charge) && WEP_CVAR(vortex, charge_velocity_rate) && xyspeed > WEP_CVAR(vortex, charge_minspeed))
+	if(self.weapon == WEP_NEX && autocvar_g_balance_nex_charge && autocvar_g_balance_nex_charge_velocity_rate && xyspeed > autocvar_g_balance_nex_charge_minspeed)
 	{
 		// add a maximum of charge_velocity_rate when going fast (f = 1), gradually increasing from minspeed (f = 0) to maxspeed
-	        xyspeed = min(xyspeed, WEP_CVAR(vortex, charge_maxspeed));
-		f = (xyspeed - WEP_CVAR(vortex, charge_minspeed)) / (WEP_CVAR(vortex, charge_maxspeed) - WEP_CVAR(vortex, charge_minspeed));
+	        xyspeed = min(xyspeed, autocvar_g_balance_nex_charge_maxspeed);
+		f = (xyspeed - autocvar_g_balance_nex_charge_minspeed) / (autocvar_g_balance_nex_charge_maxspeed - autocvar_g_balance_nex_charge_minspeed);
 		// add the extra charge
-		self.vortex_charge = min(1, self.vortex_charge + WEP_CVAR(vortex, charge_velocity_rate) * f * frametime);
+		self.nex_charge = min(1, self.nex_charge + autocvar_g_balance_nex_charge_velocity_rate * f * frametime);
 	}
 :end
 	if(self.flags & FL_ONGROUND)
diff --git a/qcsrc/server/cl_player.qc b/qcsrc/server/cl_player.qc
index 7d7ba087a..c11e92051 100644
--- a/qcsrc/server/cl_player.qc
+++ b/qcsrc/server/cl_player.qc
@@ -1,3 +1,126 @@
+.entity accuracy;
+.float accuracy_frags[WEP_MAXCOUNT];
+
+float weaponstats_buffer;
+
+void WeaponStats_Init()
+{
+	if(autocvar_sv_weaponstats_file != "")
+		weaponstats_buffer = buf_create();
+	else
+		weaponstats_buffer = -1;
+}
+
+#define WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot) (((vwep) + (awep) * (WEP_LAST - WEP_FIRST + 1) - (WEP_FIRST + WEP_FIRST * (WEP_LAST - WEP_FIRST + 1))) * 4 + (abot) * 2 + (vbot))
+
+void WeaponStats_ready(entity fh, entity pass, float status)
+{
+	float i, j, n, ibot, jbot, idx;
+	vector v;
+	string prefix, s;
+	switch(status)
+	{
+		case URL_READY_CANWRITE:
+			// we can write
+			prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t");
+			url_fputs(fh, "#begin statsfile\n");
+			url_fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n"));
+#ifdef WATERMARK
+			url_fputs(fh, strcat("#version ", WATERMARK, "\n"));
+#endif
+			url_fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_purechanges)), "\n"));
+			url_fputs(fh, strcat("#cvar_purechanges ", ftos(cvar_purechanges_count), "\n"));
+			n = tokenizebyseparator(cvar_purechanges, "\n");
+			for(i = 0; i < n; ++i)
+				url_fputs(fh, strcat("#cvar_purechange ", argv(i), "\n"));
+			for(i = WEP_FIRST; i <= WEP_LAST; ++i) for(ibot = 0; ibot <= 1; ++ibot)
+				for(j = WEP_FIRST; j <= WEP_LAST; ++j) for(jbot = 0; jbot <= 1; ++jbot)
+				{
+					idx = WEAPONSTATS_GETINDEX(i, ibot, j, jbot);
+					v = stov(bufstr_get(weaponstats_buffer, idx));
+					if(v != '0 0 0')
+					{
+						//vector is: kills hits damage
+						url_fputs(fh, sprintf("%s%d %d\t%d %d\t", prefix, i, ibot, j, jbot));
+						url_fputs(fh, sprintf("%d %d %g\n", v_x, v_y, v_z));
+					}
+				}
+			url_fputs(fh, "#end\n\n");
+			url_fclose(fh);
+			break;
+		case URL_READY_CANREAD:
+			// url_fclose is processing, we got a response for writing the data
+			// this must come from HTTP
+			print("Got response from weapon stats server:\n");
+			while((s = url_fgets(fh)))
+				print("  ", s, "\n");
+			print("End of response.\n");
+			url_fclose(fh);
+			break;
+		case URL_READY_CLOSED:
+			// url_fclose has finished
+			print("Weapon stats written\n");
+			buf_del(weaponstats_buffer);
+			weaponstats_buffer = -1;
+			break;
+		case URL_READY_ERROR:
+		default:
+			print("Weapon stats writing failed: ", ftos(status), "\n");
+			buf_del(weaponstats_buffer);
+			weaponstats_buffer = -1;
+			break;
+	}
+}
+
+void WeaponStats_Shutdown()
+{
+	if(weaponstats_buffer < 0)
+		return;
+	if(autocvar_sv_weaponstats_file != "")
+	{
+		url_multi_fopen(autocvar_sv_weaponstats_file, FILE_APPEND, WeaponStats_ready, world);
+	}
+	else
+	{
+		buf_del(weaponstats_buffer);
+		weaponstats_buffer = -1;
+	}
+}
+
+void WeaponStats_LogItem(float awep, float abot, float vwep, float vbot, vector item)
+{
+	float idx;
+	if(weaponstats_buffer < 0)
+		return;
+	if(awep < WEP_FIRST || vwep < WEP_FIRST)
+		return;
+	if(awep > WEP_LAST || vwep > WEP_LAST)
+		return;
+	idx = WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot);
+	bufstr_set(weaponstats_buffer, idx, vtos(stov(bufstr_get(weaponstats_buffer, idx)) + item));
+}
+void WeaponStats_LogDamage(float awep, float abot, float vwep, float vbot, float damage)
+{
+	if(damage < 0)
+		error("negative damage?");
+	WeaponStats_LogItem(awep, abot, vwep, vbot, '0 0 1' * damage + '0 1 0');
+}
+void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot)
+{
+	WeaponStats_LogItem(awep, abot, vwep, vbot, '1 0 0');
+}
+
+// changes by LordHavoc on 03/29/04 and 03/30/04 at Vermeulen's request
+// merged player_run and player_stand to player_anim
+// added death animations to player_anim
+// can now spawn thrown weapons from anywhere, not just from players
+// thrown weapons now fade out after 20 seconds
+// created PlayerGib function
+// PlayerDie no longer uses hitloc or damage
+// PlayerDie now supports dying animations as well as gibbing
+// cleaned up PlayerDie a lot
+// added CopyBody
+
 .entity pusher;
 .float pushltime;
 .float istypefrag;
@@ -138,6 +261,13 @@ void player_anim (void)
 	}
 }
 
+void SpawnThrownWeapon (vector org, float w)
+{
+	if(self.weapons & WepSet_FromWeapon(self.weapon))
+		if(W_IsWeaponThrowable(self.weapon))
+			W_ThrowNewWeapon(self, self.weapon, FALSE, org, randomvec() * 125 + '0 0 200');
+}
+
 void PlayerCorpseDamage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
 {
 	float take, save;
@@ -424,7 +554,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
 					}
 
 					if(sound_allowed(MSG_BROADCAST, attacker))
-					if(!DEATH_ISWEAPON(deathtype, WEP_BLASTER) || attacker != self || self.health < 2 * WEP_CVAR_PRI(blaster, damage) * autocvar_g_balance_selfdamagepercent + 1) // WEAPONTODO: create separate limit for pain notification with laser
+					if(!DEATH_ISWEAPON(deathtype, WEP_LASER) || attacker != self || self.health < 2 * autocvar_g_balance_laser_primary_damage * autocvar_g_balance_selfdamagepercent + 1)
 					if(self.health > 1)
 					// exclude pain sounds for laserjumps as long as you aren't REALLY low on health and would die of the next two
 					{
@@ -536,7 +666,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
 		frag_deathtype = deathtype;
 		MUTATOR_CALLHOOK(PlayerDies);
 
-		WEP_ACTION(self.weapon, WR_PLAYERDEATH);
+		weapon_action(self.weapon, WR_PLAYERDEATH);
 
 		RemoveGrapplingHook(self);
 
@@ -608,7 +738,7 @@ void PlayerDamage (entity inflictor, entity attacker, float damage, float deatht
 		// reset fields the weapons may use just in case
 		for (j = WEP_FIRST; j <= WEP_LAST; ++j)
 		{
-			WEP_ACTION(j, WR_RESETPLAYER);
+			weapon_action(j, WR_RESETPLAYER);
 			ATTACK_FINISHED_FOR(self, j) = 0;
 		}
 	}
diff --git a/qcsrc/server/cl_weaponsystem.qc b/qcsrc/server/cl_weaponsystem.qc
new file mode 100644
index 000000000..dac383633
--- /dev/null
+++ b/qcsrc/server/cl_weaponsystem.qc
@@ -0,0 +1,1407 @@
+/*
+===========================================================================
+
+  CLIENT WEAPONSYSTEM CODE
+  Bring back W_Weaponframe
+
+===========================================================================
+*/
+
+.float weapon_frametime;
+
+float W_WeaponRateFactor()
+{
+	float t;
+	t = 1.0 / g_weaponratefactor;
+
+	weapon_rate = t;
+	MUTATOR_CALLHOOK(WeaponRateFactor);
+	t = weapon_rate;
+
+	return t;
+}
+
+void W_SwitchWeapon_Force(entity e, float w)
+{
+	e.cnt = e.switchweapon;
+	e.switchweapon = w;
+	e.selectweapon = w;
+}
+
+.float antilag_debug;
+
+// VorteX: static frame globals
+const float WFRAME_DONTCHANGE = -1;
+const float WFRAME_FIRE1 = 0;
+const float WFRAME_FIRE2 = 1;
+const float WFRAME_IDLE = 2;
+const float WFRAME_RELOAD = 3;
+.float wframe;
+
+void(float fr, float t, void() func) weapon_thinkf;
+
+vector W_HitPlotUnnormalizedUntransform(vector screenforward, vector screenright, vector screenup, vector v)
+{
+	vector ret;
+	ret_x = screenright * v;
+	ret_y = screenup * v;
+	ret_z = screenforward * v;
+	return ret;
+}
+
+vector W_HitPlotNormalizedUntransform(vector org, entity targ, vector screenforward, vector screenright, vector screenup, vector v)
+{
+	float i, j, k;
+	vector mi, ma, thisv, myv, ret;
+
+	myv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, org);
+
+	// x = 0..1 relative to hitbox; y = 0..1 relative to hitbox; z = distance
+
+	mi = ma = targ.origin + 0.5 * (targ.mins + targ.maxs);
+	for(i = 0; i < 2; ++i) for(j = 0; j < 2; ++j) for(k = 0; k < 2; ++k)
+	{
+		thisv = targ.origin;
+		if(i) thisv_x += targ.maxs_x; else thisv_x += targ.mins_x;
+		if(j) thisv_y += targ.maxs_y; else thisv_y += targ.mins_y;
+		if(k) thisv_z += targ.maxs_z; else thisv_z += targ.mins_z;
+		thisv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, thisv);
+		if(i || j || k)
+		{
+			if(mi_x > thisv_x) mi_x = thisv_x; if(ma_x < thisv_x) ma_x = thisv_x;
+			if(mi_y > thisv_y) mi_y = thisv_y; if(ma_y < thisv_y) ma_y = thisv_y;
+			//if(mi_z > thisv_z) mi_z = thisv_z; if(ma_z < thisv_z) ma_y = thisv_z;
+		}
+		else
+		{
+			// first run
+			mi = ma = thisv;
+		}
+	}
+
+	thisv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, v);
+	ret_x = (thisv_x - mi_x) / (ma_x - mi_x);
+	ret_y = (thisv_y - mi_y) / (ma_y - mi_y);
+	ret_z = thisv_z - myv_z;
+	return ret;
+}
+
+void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright, vector screenup)
+{
+	vector hitplot;
+	vector org;
+	float lag;
+
+	if(player.hitplotfh >= 0)
+	{
+		lag = ANTILAG_LATENCY(player);
+		if(lag < 0.001)
+			lag = 0;
+		if (!IS_REAL_CLIENT(player))
+			lag = 0; // only antilag for clients
+
+		org = player.origin + player.view_ofs;
+		traceline_antilag_force(player, org, org + screenforward * MAX_SHOT_DISTANCE, MOVE_NORMAL, player, lag);
+		if(IS_CLIENT(trace_ent) || (trace_ent.flags & FL_MONSTER))
+		{
+			antilag_takeback(trace_ent, time - lag);
+			hitplot = W_HitPlotNormalizedUntransform(org, trace_ent, screenforward, screenright, screenup, trace_endpos);
+			antilag_restore(trace_ent);
+			fputs(player.hitplotfh, strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), " ", ftos(player.switchweapon), "\n"));
+			//print(strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), "\n"));
+		}
+	}
+}
+
+vector w_shotorg;
+vector w_shotdir;
+vector w_shotend;
+
+.float prevstrengthsound;
+.float prevstrengthsoundattempt;
+void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound
+{
+	if((player.items & IT_STRENGTH)
+		&& ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam
+		|| (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold)))
+		{
+			sound(player, CH_TRIGGER, "weapons/strength_fire.wav", VOL_BASE, ATTEN_NORM);
+			player.prevstrengthsound = time;
+		}
+		player.prevstrengthsoundattempt = time;
+}
+
+// this function calculates w_shotorg and w_shotdir based on the weapon model
+// offset, trueaim and antilag, and won't put w_shotorg inside a wall.
+// make sure you call makevectors first (FIXME?)
+void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float chan, float maxdamage, float range)
+{
+	float nudge = 1; // added to traceline target and subtracted from result
+	float oldsolid;
+	vector vecs, dv;
+	oldsolid = ent.dphitcontentsmask;
+	if(ent.weapon == WEP_RIFLE)
+		ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+	else
+		ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+	if(antilag)
+		WarpZone_traceline_antilag(world, ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
+		// passing world, because we do NOT want it to touch dphitcontentsmask
+	else
+		WarpZone_TraceLine(ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NOMONSTERS, ent);
+	ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
+
+	vector vf, vr, vu;
+	vf = v_forward;
+	vr = v_right;
+	vu = v_up;
+	w_shotend = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); // warpzone support
+	v_forward = vf;
+	v_right = vr;
+	v_up = vu;
+
+	// un-adjust trueaim if shotend is too close
+	if(vlen(w_shotend - (ent.origin + ent.view_ofs)) < autocvar_g_trueaim_minrange)
+		w_shotend = ent.origin + ent.view_ofs + s_forward * autocvar_g_trueaim_minrange;
+
+	// track max damage
+	if(accuracy_canbegooddamage(ent))
+		accuracy_add(ent, ent.weapon, maxdamage, 0);
+
+	W_HitPlotAnalysis(ent, v_forward, v_right, v_up);
+
+	if(ent.weaponentity.movedir_x > 0)
+		vecs = ent.weaponentity.movedir;
+	else
+		vecs = '0 0 0';
+
+	dv = v_right * -vecs_y + v_up * vecs_z;
+	w_shotorg = ent.origin + ent.view_ofs + dv;
+
+	// now move the shotorg forward as much as requested if possible
+	if(antilag)
+	{
+		if(ent.antilag_debug)
+			tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ent.antilag_debug);
+		else
+			tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
+	}
+	else
+		tracebox(w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent);
+	w_shotorg = trace_endpos - v_forward * nudge;
+	// calculate the shotdir from the chosen shotorg
+	w_shotdir = normalize(w_shotend - w_shotorg);
+
+	if (antilag)
+	if (!ent.cvar_cl_noantilag)
+	{
+		if (autocvar_g_antilag == 1) // switch to "ghost" if not hitting original
+		{
+			traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent);
+			if (!trace_ent.takedamage)
+			{
+				traceline_antilag_force (ent, w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
+				if (trace_ent.takedamage && IS_PLAYER(trace_ent))
+				{
+					entity e;
+					e = trace_ent;
+					traceline(w_shotorg, e.origin, MOVE_NORMAL, ent);
+					if(trace_ent == e)
+						w_shotdir = normalize(trace_ent.origin - w_shotorg);
+				}
+			}
+		}
+		else if(autocvar_g_antilag == 3) // client side hitscan
+		{
+			// this part MUST use prydon cursor
+			if (ent.cursor_trace_ent)                 // client was aiming at someone
+			if (ent.cursor_trace_ent != ent)         // just to make sure
+			if (ent.cursor_trace_ent.takedamage)      // and that person is killable
+			if (IS_PLAYER(ent.cursor_trace_ent)) // and actually a player
+			{
+				// verify that the shot would miss without antilag
+				// (avoids an issue where guns would always shoot at their origin)
+				traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent);
+				if (!trace_ent.takedamage)
+				{
+					// verify that the shot would hit if altered
+					traceline(w_shotorg, ent.cursor_trace_ent.origin, MOVE_NORMAL, ent);
+					if (trace_ent == ent.cursor_trace_ent)
+						w_shotdir = normalize(ent.cursor_trace_ent.origin - w_shotorg);
+					else
+						print("antilag fail\n");
+				}
+			}
+		}
+	}
+
+	ent.dphitcontentsmask = oldsolid; // restore solid type (generally SOLID_SLIDEBOX)
+
+	if (!autocvar_g_norecoil)
+		ent.punchangle_x = recoil * -1;
+
+	if (snd != "")
+	{
+		sound (ent, chan, snd, VOL_BASE, ATTEN_NORM);
+		W_PlayStrengthSound(ent);
+	}
+
+	// nudge w_shotend so a trace to w_shotend hits
+	w_shotend = w_shotend + normalize(w_shotend - w_shotorg) * nudge;
+}
+
+#define W_SetupShot_Dir_ProjectileSize(ent,s_forward,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize_Range(ent, s_forward, mi, ma, antilag, recoil, snd, chan, maxdamage, MAX_SHOT_DISTANCE)
+#define W_SetupShot_ProjectileSize(ent,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, v_forward, mi, ma, antilag, recoil, snd, chan, maxdamage)
+#define W_SetupShot_Dir(ent,s_forward,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, s_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
+#define W_SetupShot(ent,antilag,recoil,snd,chan,maxdamage) W_SetupShot_ProjectileSize(ent, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
+#define W_SetupShot_Range(ent,antilag,recoil,snd,chan,maxdamage,range) W_SetupShot_Dir_ProjectileSize_Range(ent, v_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage, range)
+
+float CL_Weaponentity_CustomizeEntityForClient()
+{
+	self.viewmodelforclient = self.owner;
+	if(IS_SPEC(other))
+		if(other.enemy == self.owner)
+			self.viewmodelforclient = other;
+	return TRUE;
+}
+
+/*
+ * supported formats:
+ *
+ * 1. simple animated model, muzzle flash handling on h_ model:
+ *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
+ *      tags:
+ *        shot = muzzle end (shot origin, also used for muzzle flashes)
+ *        shell = casings ejection point (must be on the right hand side of the gun)
+ *        weapon = attachment for v_tuba.md3
+ *    v_tuba.md3 - first and third person model
+ *    g_tuba.md3 - pickup model
+ *
+ * 2. simple animated model, muzzle flash handling on v_ model:
+ *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
+ *      tags:
+ *        weapon = attachment for v_tuba.md3
+ *    v_tuba.md3 - first and third person model
+ *      tags:
+ *        shot = muzzle end (shot origin, also used for muzzle flashes)
+ *        shell = casings ejection point (must be on the right hand side of the gun)
+ *    g_tuba.md3 - pickup model
+ *
+ * 3. fully animated model, muzzle flash handling on h_ model:
+ *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
+ *      tags:
+ *        shot = muzzle end (shot origin, also used for muzzle flashes)
+ *        shell = casings ejection point (must be on the right hand side of the gun)
+ *        handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes)
+ *    v_tuba.md3 - third person model
+ *    g_tuba.md3 - pickup model
+ *
+ * 4. fully animated model, muzzle flash handling on v_ model:
+ *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
+ *      tags:
+ *        shot = muzzle end (shot origin)
+ *        shell = casings ejection point (must be on the right hand side of the gun)
+ *    v_tuba.md3 - third person model
+ *      tags:
+ *        shot = muzzle end (for muzzle flashes)
+ *    g_tuba.md3 - pickup model
+ */
+
+// writes:
+//   self.origin, self.angles
+//   self.weaponentity
+//   self.movedir, self.view_ofs
+//   attachment stuff
+//   anim stuff
+// to free:
+//   call again with ""
+//   remove the ent
+void CL_WeaponEntity_SetModel(string name)
+{
+	float v_shot_idx;
+	if (name != "")
+	{
+		// if there is a child entity, hide it until we're sure we use it
+		if (self.weaponentity)
+			self.weaponentity.model = "";
+		setmodel(self, strcat("models/weapons/v_", name, ".md3")); // precision set below
+		v_shot_idx = gettagindex(self, "shot"); // used later
+		if(!v_shot_idx)
+			v_shot_idx = gettagindex(self, "tag_shot");
+
+		setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below
+		// preset some defaults that work great for renamed zym files (which don't need an animinfo)
+		self.anim_fire1  = animfixfps(self, '0 1 0.01', '0 0 0');
+		self.anim_fire2  = animfixfps(self, '1 1 0.01', '0 0 0');
+		self.anim_idle   = animfixfps(self, '2 1 0.01', '0 0 0');
+		self.anim_reload = animfixfps(self, '3 1 0.01', '0 0 0');
+
+		// if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
+		// if we don't, this is a "real" animated model
+		if(gettagindex(self, "weapon"))
+		{
+			if (!self.weaponentity)
+				self.weaponentity = spawn();
+			setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter
+			setattachment(self.weaponentity, self, "weapon");
+		}
+		else if(gettagindex(self, "tag_weapon"))
+		{
+			if (!self.weaponentity)
+				self.weaponentity = spawn();
+			setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter
+			setattachment(self.weaponentity, self, "tag_weapon");
+		}
+		else
+		{
+			if(self.weaponentity)
+				remove(self.weaponentity);
+			self.weaponentity = world;
+		}
+
+		setorigin(self,'0 0 0');
+		self.angles = '0 0 0';
+		self.frame = 0;
+		self.viewmodelforclient = world;
+
+		float idx;
+
+		if(v_shot_idx) // v_ model attached to invisible h_ model
+		{
+			self.movedir = gettaginfo(self.weaponentity, v_shot_idx);
+		}
+		else
+		{
+			idx = gettagindex(self, "shot");
+			if(!idx)
+				idx = gettagindex(self, "tag_shot");
+			if(idx)
+				self.movedir = gettaginfo(self, idx);
+			else
+			{
+				print("WARNING: weapon model ", self.model, " does not support the 'shot' tag, will display shots TOTALLY wrong\n");
+				self.movedir = '0 0 0';
+			}
+		}
+
+		if(self.weaponentity) // v_ model attached to invisible h_ model
+		{
+			idx = gettagindex(self.weaponentity, "shell");
+			if(!idx)
+				idx = gettagindex(self.weaponentity, "tag_shell");
+			if(idx)
+				self.spawnorigin = gettaginfo(self.weaponentity, idx);
+		}
+		else
+			idx = 0;
+		if(!idx)
+		{
+			idx = gettagindex(self, "shell");
+			if(!idx)
+				idx = gettagindex(self, "tag_shell");
+			if(idx)
+				self.spawnorigin = gettaginfo(self, idx);
+			else
+			{
+				print("WARNING: weapon model ", self.model, " does not support the 'shell' tag, will display casings wrong\n");
+				self.spawnorigin = self.movedir;
+			}
+		}
+
+		if(v_shot_idx)
+		{
+			self.oldorigin = '0 0 0'; // use regular attachment
+		}
+		else
+		{
+			if(self.weaponentity)
+			{
+				idx = gettagindex(self, "weapon");
+				if(!idx)
+					idx = gettagindex(self, "tag_weapon");
+			}
+			else
+			{
+				idx = gettagindex(self, "handle");
+				if(!idx)
+					idx = gettagindex(self, "tag_handle");
+			}
+			if(idx)
+			{
+				self.oldorigin = self.movedir - gettaginfo(self, idx);
+			}
+			else
+			{
+				print("WARNING: weapon model ", self.model, " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n");
+				self.oldorigin = '0 0 0'; // there is no way to recover from this
+			}
+		}
+
+		self.viewmodelforclient = self.owner;
+	}
+	else
+	{
+		self.model = "";
+		if(self.weaponentity)
+			remove(self.weaponentity);
+		self.weaponentity = world;
+		self.movedir = '0 0 0';
+		self.spawnorigin = '0 0 0';
+		self.oldorigin = '0 0 0';
+		self.anim_fire1  = '0 1 0.01';
+		self.anim_fire2  = '0 1 0.01';
+		self.anim_idle   = '0 1 0.01';
+		self.anim_reload = '0 1 0.01';
+	}
+
+	self.view_ofs = '0 0 0';
+
+	if(self.movedir_x >= 0)
+	{
+		vector v0;
+		v0 = self.movedir;
+		self.movedir = shotorg_adjust(v0, FALSE, FALSE);
+		self.view_ofs = shotorg_adjust(v0, FALSE, TRUE) - v0;
+	}
+	self.owner.stat_shotorg = compressShotOrigin(self.movedir);
+	self.movedir = decompressShotOrigin(self.owner.stat_shotorg); // make them match perfectly
+
+	self.spawnorigin += self.view_ofs; // offset the casings origin by the same amount
+
+	// check if an instant weapon switch occurred
+	setorigin(self, self.view_ofs);
+	// reset animstate now
+	self.wframe = WFRAME_IDLE;
+	setanim(self, self.anim_idle, TRUE, FALSE, TRUE);
+}
+
+vector CL_Weapon_GetShotOrg(float wpn)
+{
+	entity wi, oldself;
+	vector ret;
+	wi = get_weaponinfo(wpn);
+	oldself = self;
+	self = spawn();
+	CL_WeaponEntity_SetModel(wi.mdl);
+	ret = self.movedir;
+	CL_WeaponEntity_SetModel("");
+	remove(self);
+	self = oldself;
+	return ret;
+}
+
+void CL_Weaponentity_Think()
+{
+	float tb;
+	self.nextthink = time;
+	if (intermission_running)
+		self.frame = self.anim_idle_x;
+	if (self.owner.weaponentity != self)
+	{
+		if (self.weaponentity)
+			remove(self.weaponentity);
+		remove(self);
+		return;
+	}
+	if (self.owner.deadflag != DEAD_NO)
+	{
+		self.model = "";
+		if (self.weaponentity)
+			self.weaponentity.model = "";
+		return;
+	}
+	if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
+	{
+		self.weaponname = self.owner.weaponname;
+		self.dmg = self.owner.modelindex;
+		self.deadflag = self.owner.deadflag;
+
+		CL_WeaponEntity_SetModel(self.owner.weaponname);
+	}
+
+	tb = (self.effects & (EF_TELEPORT_BIT | EF_RESTARTANIM_BIT));
+	self.effects = self.owner.effects & EFMASK_CHEAP;
+	self.effects &= ~EF_LOWPRECISION;
+	self.effects &= ~EF_FULLBRIGHT; // can mask team color, so get rid of it
+	self.effects &= ~EF_TELEPORT_BIT;
+	self.effects &= ~EF_RESTARTANIM_BIT;
+	self.effects |= tb;
+
+	if(self.owner.alpha == default_player_alpha)
+		self.alpha = default_weapon_alpha;
+	else if(self.owner.alpha != 0)
+		self.alpha = self.owner.alpha;
+	else
+		self.alpha = 1;
+
+	self.glowmod = self.owner.weaponentity_glowmod;
+	self.colormap = self.owner.colormap;
+	if (self.weaponentity)
+	{
+		self.weaponentity.effects = self.effects;
+		self.weaponentity.alpha = self.alpha;
+		self.weaponentity.colormap = self.colormap;
+		self.weaponentity.glowmod = self.glowmod;
+	}
+
+	self.angles = '0 0 0';
+
+	float f = (self.owner.weapon_nextthink - time);
+	if (self.state == WS_RAISE && !intermission_running)
+	{
+		entity newwep = get_weaponinfo(self.owner.switchweapon);
+		f = f * g_weaponratefactor / max(f, cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname)));
+		//printf("CL_Weaponentity_Think(): cvar: %s, value: %f, nextthink: %f\n", sprintf("g_balance_%s_switchdelay_raise", newwep.netname), cvar(sprintf("g_balance_%s_switchdelay_raise", newwep.netname)), (self.owner.weapon_nextthink - time));
+		self.angles_x = -90 * f * f;
+	}
+	else if (self.state == WS_DROP && !intermission_running)
+	{
+		entity oldwep = get_weaponinfo(self.owner.weapon);
+		f = 1 - f * g_weaponratefactor / max(f, cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname)));
+		//printf("CL_Weaponentity_Think(): cvar: %s, value: %f, nextthink: %f\n", sprintf("g_balance_%s_switchdelay_drop", oldwep.netname), cvar(sprintf("g_balance_%s_switchdelay_drop", oldwep.netname)), (self.owner.weapon_nextthink - time));
+		self.angles_x = -90 * f * f;
+	}
+	else if (self.state == WS_CLEAR)
+	{
+		f = 1;
+		self.angles_x = -90 * f * f;
+	}
+}
+
+void CL_ExteriorWeaponentity_Think()
+{
+	float tag_found;
+	self.nextthink = time;
+	if (self.owner.exteriorweaponentity != self)
+	{
+		remove(self);
+		return;
+	}
+	if (self.owner.deadflag != DEAD_NO)
+	{
+		self.model = "";
+		return;
+	}
+	if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
+	{
+		self.weaponname = self.owner.weaponname;
+		self.dmg = self.owner.modelindex;
+		self.deadflag = self.owner.deadflag;
+		if (self.owner.weaponname != "")
+			setmodel(self, strcat("models/weapons/v_", self.owner.weaponname, ".md3")); // precision set below
+		else
+			self.model = "";
+
+		if((tag_found = gettagindex(self.owner, "tag_weapon")))
+		{
+			self.tag_index = tag_found;
+			self.tag_entity = self.owner;
+		}
+		else
+			setattachment(self, self.owner, "bip01 r hand");
+	}
+	self.effects = self.owner.effects;
+	self.effects |= EF_LOWPRECISION;
+	self.effects = self.effects & EFMASK_CHEAP; // eat performance
+	if(self.owner.alpha == default_player_alpha)
+		self.alpha = default_weapon_alpha;
+	else if(self.owner.alpha != 0)
+		self.alpha = self.owner.alpha;
+	else
+		self.alpha = 1;
+
+	self.glowmod = self.owner.weaponentity_glowmod;
+	self.colormap = self.owner.colormap;
+
+	CSQCMODEL_AUTOUPDATE();
+}
+
+// spawning weaponentity for client
+void CL_SpawnWeaponentity()
+{
+	self.weaponentity = spawn();
+	self.weaponentity.classname = "weaponentity";
+	self.weaponentity.solid = SOLID_NOT;
+	self.weaponentity.owner = self;
+	setmodel(self.weaponentity, ""); // precision set when changed
+	setorigin(self.weaponentity, '0 0 0');
+	self.weaponentity.angles = '0 0 0';
+	self.weaponentity.viewmodelforclient = self;
+	self.weaponentity.flags = 0;
+	self.weaponentity.think = CL_Weaponentity_Think;
+	self.weaponentity.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
+	self.weaponentity.nextthink = time;
+
+	self.exteriorweaponentity = spawn();
+	self.exteriorweaponentity.classname = "exteriorweaponentity";
+	self.exteriorweaponentity.solid = SOLID_NOT;
+	self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity;
+	self.exteriorweaponentity.owner = self;
+	setorigin(self.exteriorweaponentity, '0 0 0');
+	self.exteriorweaponentity.angles = '0 0 0';
+	self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;
+	self.exteriorweaponentity.nextthink = time;
+
+	{
+		entity oldself = self;
+		self = self.exteriorweaponentity;
+		CSQCMODEL_AUTOINIT();
+		self = oldself;
+	}
+}
+
+void Send_WeaponComplain (entity e, float wpn, string wpnname, float type)
+{
+	msg_entity = e;
+	WriteByte(MSG_ONE, SVC_TEMPENTITY);
+	WriteByte(MSG_ONE, TE_CSQC_WEAPONCOMPLAIN);
+	WriteByte(MSG_ONE, wpn);
+	WriteString(MSG_ONE, wpnname);
+	WriteByte(MSG_ONE, type);
+}
+
+.float hasweapon_complain_spam;
+
+float client_hasweapon(entity cl, float wpn, float andammo, float complain)
+{
+	float f;
+	entity oldself;
+
+	if(time < self.hasweapon_complain_spam)
+		complain = 0;
+	if(complain)
+		self.hasweapon_complain_spam = time + 0.2;
+
+	if(wpn == WEP_HOOK && !g_grappling_hook && autocvar_g_nades && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn)))
+		complain = 0;
+
+	if (wpn < WEP_FIRST || wpn > WEP_LAST)
+	{
+		if (complain)
+			sprint(self, "Invalid weapon\n");
+		return FALSE;
+	}
+	if (cl.weapons & WepSet_FromWeapon(wpn))
+	{
+		if (andammo)
+		{
+			if(cl.items & IT_UNLIMITED_WEAPON_AMMO)
+			{
+				f = 1;
+			}
+			else
+			{
+				oldself = self;
+				self = cl;
+				f = weapon_action(wpn, WR_CHECKAMMO1);
+				f = f + weapon_action(wpn, WR_CHECKAMMO2);
+
+				// always allow selecting the Mine Layer if we placed mines, so that we can detonate them
+				entity mine;
+				if(wpn == WEP_MINE_LAYER)
+				for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+					f = 1;
+
+				self = oldself;
+			}
+			if (!f)
+			{
+				if (complain)
+				if(IS_REAL_CLIENT(cl))
+				{
+					play2(cl, "weapons/unavailable.wav");
+					Send_WeaponComplain (cl, wpn, W_Name(wpn), 0);
+				}
+				return FALSE;
+			}
+		}
+		return TRUE;
+	}
+	if (complain)
+	{
+		// DRESK - 3/16/07
+		// Report Proper Weapon Status / Modified Weapon Ownership Message
+		if (weaponsInMap & WepSet_FromWeapon(wpn))
+		{
+			Send_WeaponComplain(cl, wpn, W_Name(wpn), 1);
+
+			if(autocvar_g_showweaponspawns)
+			{
+				entity e;
+				string s;
+
+				e = get_weaponinfo(wpn);
+				s = e.model2;
+
+				for(e = world; (e = findfloat(e, weapon, wpn)); )
+				{
+					if(e.classname == "droppedweapon")
+						continue;
+					if (!(e.flags & FL_ITEM))
+						continue;
+					WaypointSprite_Spawn(
+						s,
+						1, 0,
+						world, e.origin,
+						self, 0,
+						world, enemy,
+						0,
+						RADARICON_NONE, '0 0 0'
+					);
+				}
+			}
+		}
+		else
+		{
+			Send_WeaponComplain (cl, wpn, W_Name(wpn), 2);
+		}
+
+		play2(cl, "weapons/unavailable.wav");
+	}
+	return FALSE;
+}
+
+// Weapon subs
+void w_clear()
+{
+	if (self.weapon != -1)
+	{
+		self.weapon = 0;
+		self.switchingweapon = 0;
+	}
+	if (self.weaponentity)
+	{
+		self.weaponentity.state = WS_CLEAR;
+		self.weaponentity.effects = 0;
+	}
+}
+
+void w_ready()
+{
+	if (self.weaponentity)
+		self.weaponentity.state = WS_READY;
+	weapon_thinkf(WFRAME_IDLE, 1000000, w_ready);
+}
+
+// Setup weapon for client (after this raise frame will be launched)
+void weapon_setup(float windex)
+{
+	entity e;
+	e = get_weaponinfo(windex);
+	self.items &= ~IT_AMMO;
+	self.items = self.items | (e.items & IT_AMMO);
+
+	// the two weapon entities will notice this has changed and update their models
+	self.weapon = windex;
+	self.switchingweapon = windex; // to make sure
+	self.weaponname = e.mdl;
+	self.bulletcounter = 0;
+}
+
+// perform weapon to attack (weaponstate and attack_finished check is here)
+void W_SwitchToOtherWeapon(entity pl)
+{
+	// hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
+	float w, ww;
+	w = pl.weapon;
+	if(pl.weapons & WepSet_FromWeapon(w))
+	{
+		pl.weapons &= ~WepSet_FromWeapon(w);
+		ww = w_getbestweapon(pl);
+		pl.weapons |= WepSet_FromWeapon(w);
+	}
+	else
+		ww = w_getbestweapon(pl);
+	if(ww)
+		W_SwitchWeapon_Force(pl, ww);
+}
+
+.float prevdryfire;
+.float prevwarntime;
+float weapon_prepareattack_checkammo(float secondary)
+{
+	if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+	if (!weapon_action(self.weapon, WR_CHECKAMMO1 + secondary))
+	{
+		// always keep the Mine Layer if we placed mines, so that we can detonate them
+		entity mine;
+		if(self.weapon == WEP_MINE_LAYER)
+		for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
+			return FALSE;
+
+		if(self.weapon == self.switchweapon && time - self.prevdryfire > 1) // only play once BEFORE starting to switch weapons
+		{
+			sound (self, CH_WEAPON_A, "weapons/dryfire.wav", VOL_BASE, ATTEN_NORM);
+			self.prevdryfire = time;
+		}
+
+		if(weapon_action(self.weapon, WR_CHECKAMMO2 - secondary)) // check if the other firing mode has enough ammo
+		{
+			if(time - self.prevwarntime > 1)
+			{
+				Send_Notification(
+					NOTIF_ONE,
+					self,
+					MSG_MULTI,
+					ITEM_WEAPON_PRIMORSEC,
+					self.weapon,
+					secondary,
+					(1 - secondary)
+				);
+			}
+			self.prevwarntime = time;
+		}
+		else // this weapon is totally unable to fire, switch to another one
+		{
+			W_SwitchToOtherWeapon(self);
+		}
+
+		return FALSE;
+	}
+	return TRUE;
+}
+.float race_penalty;
+float weapon_prepareattack_check(float secondary, float attacktime)
+{
+	if(!weapon_prepareattack_checkammo(secondary))
+		return FALSE;
+
+	//if sv_ready_restart_after_countdown is set, don't allow the player to shoot
+	//if all players readied up and the countdown is running
+	if(time < game_starttime || time < self.race_penalty) {
+		return FALSE;
+	}
+
+	if (timeout_status == TIMEOUT_ACTIVE) //don't allow the player to shoot while game is paused
+		return FALSE;
+
+	// do not even think about shooting if switching
+	if(self.switchweapon != self.weapon)
+		return FALSE;
+
+	if(attacktime >= 0)
+	{
+		// don't fire if previous attack is not finished
+		if (ATTACK_FINISHED(self) > time + self.weapon_frametime * 0.5)
+			return FALSE;
+		// don't fire while changing weapon
+		if (self.weaponentity.state != WS_READY)
+			return FALSE;
+	}
+
+	return TRUE;
+}
+float weapon_prepareattack_do(float secondary, float attacktime)
+{
+	self.weaponentity.state = WS_INUSE;
+
+	self.spawnshieldtime = min(self.spawnshieldtime, time); // kill spawn shield when you fire
+
+	// if the weapon hasn't been firing continuously, reset the timer
+	if(attacktime >= 0)
+	{
+		if (ATTACK_FINISHED(self) < time - self.weapon_frametime * 1.5)
+		{
+			ATTACK_FINISHED(self) = time;
+			//dprint("resetting attack finished to ", ftos(time), "\n");
+		}
+		ATTACK_FINISHED(self) = ATTACK_FINISHED(self) + attacktime * W_WeaponRateFactor();
+	}
+	self.bulletcounter += 1;
+	//dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n");
+	return TRUE;
+}
+float weapon_prepareattack(float secondary, float attacktime)
+{
+	if(weapon_prepareattack_check(secondary, attacktime))
+	{
+		weapon_prepareattack_do(secondary, attacktime);
+		return TRUE;
+	}
+	else
+		return FALSE;
+}
+
+void weapon_thinkf(float fr, float t, void() func)
+{
+	vector a;
+	vector of, or, ou;
+	float restartanim;
+
+	if(fr == WFRAME_DONTCHANGE)
+	{
+		fr = self.weaponentity.wframe;
+		restartanim = FALSE;
+	}
+	else if (fr == WFRAME_IDLE)
+		restartanim = FALSE;
+	else
+		restartanim = TRUE;
+
+	of = v_forward;
+	or = v_right;
+	ou = v_up;
+
+	if (self.weaponentity)
+	{
+		self.weaponentity.wframe = fr;
+		a = '0 0 0';
+		if (fr == WFRAME_IDLE)
+			a = self.weaponentity.anim_idle;
+		else if (fr == WFRAME_FIRE1)
+			a = self.weaponentity.anim_fire1;
+		else if (fr == WFRAME_FIRE2)
+			a = self.weaponentity.anim_fire2;
+		else // if (fr == WFRAME_RELOAD)
+			a = self.weaponentity.anim_reload;
+		a_z *= g_weaponratefactor;
+		setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim);
+	}
+
+	v_forward = of;
+	v_right = or;
+	v_up = ou;
+
+	if(self.weapon_think == w_ready && func != w_ready && self.weaponentity.state == WS_RAISE)
+	{
+		backtrace("Tried to override initial weapon think function - should this really happen?");
+	}
+
+	t *= W_WeaponRateFactor();
+
+	// VorteX: haste can be added here
+	if (self.weapon_think == w_ready)
+	{
+		self.weapon_nextthink = time;
+		//dprint("started firing at ", ftos(time), "\n");
+	}
+	if (self.weapon_nextthink < time - self.weapon_frametime * 1.5 || self.weapon_nextthink > time + self.weapon_frametime * 1.5)
+	{
+		self.weapon_nextthink = time;
+		//dprint("reset weapon animation timer at ", ftos(time), "\n");
+	}
+	self.weapon_nextthink = self.weapon_nextthink + t;
+	self.weapon_think = func;
+	//dprint("next ", ftos(self.weapon_nextthink), "\n");
+
+	if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
+	{
+		if(self.weapon == WEP_SHOTGUN && fr == WFRAME_FIRE2)
+			animdecide_setaction(self, ANIMACTION_MELEE, restartanim);
+		else
+			animdecide_setaction(self, ANIMACTION_SHOOT, restartanim);
+	}
+	else
+	{
+		if(self.anim_upper_action == ANIMACTION_SHOOT || self.anim_upper_action == ANIMACTION_MELEE)
+			self.anim_upper_action = 0;
+	}
+}
+
+void weapon_boblayer1(float spd, vector org)
+{
+	// VorteX: haste can be added here
+}
+
+vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float forceAbsolute)
+{
+	vector mdirection;
+	float mspeed;
+	vector outvelocity;
+
+	mvelocity = mvelocity * g_weaponspeedfactor;
+
+	mdirection = normalize(mvelocity);
+	mspeed = vlen(mvelocity);
+
+	outvelocity = get_shotvelocity(pvelocity, mdirection, mspeed, (forceAbsolute ? 0 : autocvar_g_projectiles_newton_style), autocvar_g_projectiles_newton_style_2_minfactor, autocvar_g_projectiles_newton_style_2_maxfactor);
+
+	return outvelocity;
+}
+
+void W_AttachToShotorg(entity flash, vector offset)
+{
+	entity xflash;
+	flash.owner = self;
+	flash.angles_z = random() * 360;
+
+	if(gettagindex(self.weaponentity, "shot"))
+		setattachment(flash, self.weaponentity, "shot");
+	else
+		setattachment(flash, self.weaponentity, "tag_shot");
+	setorigin(flash, offset);
+
+	xflash = spawn();
+	copyentity(flash, xflash);
+
+	flash.viewmodelforclient = self;
+
+	if(self.weaponentity.oldorigin_x > 0)
+	{
+		setattachment(xflash, self.exteriorweaponentity, "");
+		setorigin(xflash, self.weaponentity.oldorigin + offset);
+	}
+	else
+	{
+		if(gettagindex(self.exteriorweaponentity, "shot"))
+			setattachment(xflash, self.exteriorweaponentity, "shot");
+		else
+			setattachment(xflash, self.exteriorweaponentity, "tag_shot");
+		setorigin(xflash, offset);
+	}
+}
+
+vector cliptoplane(vector v, vector p)
+{
+	return v - (v * p) * p;
+}
+
+vector solve_cubic_pq(float p, float q)
+{
+	float D, u, v, a;
+	D = q*q/4.0 + p*p*p/27.0;
+	if(D < 0)
+	{
+		// irreducibilis
+		a = 1.0/3.0 * acos(-q/2.0 * sqrt(-27.0/(p*p*p)));
+		u = sqrt(-4.0/3.0 * p);
+		// a in range 0..pi/3
+		// cos(a)
+		// cos(a + 2pi/3)
+		// cos(a + 4pi/3)
+		return
+			u *
+			(
+				'1 0 0' * cos(a + 2.0/3.0*M_PI)
+				+
+				'0 1 0' * cos(a + 4.0/3.0*M_PI)
+				+
+				'0 0 1' * cos(a)
+			);
+	}
+	else if(D == 0)
+	{
+		// simple
+		if(p == 0)
+			return '0 0 0';
+		u = 3*q/p;
+		v = -u/2;
+		if(u >= v)
+			return '1 1 0' * v + '0 0 1' * u;
+		else
+			return '0 1 1' * v + '1 0 0' * u;
+	}
+	else
+	{
+		// cardano
+		u = cbrt(-q/2.0 + sqrt(D));
+		v = cbrt(-q/2.0 - sqrt(D));
+		return '1 1 1' * (u + v);
+	}
+}
+vector solve_cubic_abcd(float a, float b, float c, float d)
+{
+	// y = 3*a*x + b
+	// x = (y - b) / 3a
+	float p, q;
+	vector v;
+	p = (9*a*c - 3*b*b);
+	q = (27*a*a*d - 9*a*b*c + 2*b*b*b);
+	v = solve_cubic_pq(p, q);
+	v = (v -  b * '1 1 1') * (1.0 / (3.0 * a));
+	if(a < 0)
+		v += '1 0 -1' * (v_z - v_x); // swap x, z
+	return v;
+}
+
+vector findperpendicular(vector v)
+{
+	vector p;
+	p_x = v_z;
+	p_y = -v_x;
+	p_z = v_y;
+	return normalize(cliptoplane(p, v));
+}
+
+vector W_CalculateProjectileSpread(vector forward, float spread)
+{
+	float sigma;
+	vector v1 = '0 0 0', v2;
+	float dx, dy, r;
+	float sstyle;
+	spread *= g_weaponspreadfactor;
+	if(spread <= 0)
+		return forward;
+	sstyle = autocvar_g_projectiles_spread_style;
+
+	if(sstyle == 0)
+	{
+		// this is the baseline for the spread value!
+		// standard deviation: sqrt(2/5)
+		// density function: sqrt(1-r^2)
+		return forward + randomvec() * spread;
+	}
+	else if(sstyle == 1)
+	{
+		// same thing, basically
+		return normalize(forward + cliptoplane(randomvec() * spread, forward));
+	}
+	else if(sstyle == 2)
+	{
+		// circle spread... has at sigma=1 a standard deviation of sqrt(1/2)
+		sigma = spread * 0.89442719099991587855; // match baseline stddev
+		v1 = findperpendicular(forward);
+		v2 = cross(forward, v1);
+		// random point on unit circle
+		dx = random() * 2 * M_PI;
+		dy = sin(dx);
+		dx = cos(dx);
+		// radius in our dist function
+		r = random();
+		r = sqrt(r);
+		return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+	}
+	else if(sstyle == 3) // gauss 3d
+	{
+		sigma = spread * 0.44721359549996; // match baseline stddev
+		// note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
+		v1 = forward;
+		v1_x += gsl_ran_gaussian(sigma);
+		v1_y += gsl_ran_gaussian(sigma);
+		v1_z += gsl_ran_gaussian(sigma);
+		return v1;
+	}
+	else if(sstyle == 4) // gauss 2d
+	{
+		sigma = spread * 0.44721359549996; // match baseline stddev
+		// note: 2D gaussian has sqrt(2) times the stddev of 1D, so this factor is right
+		v1_x = gsl_ran_gaussian(sigma);
+		v1_y = gsl_ran_gaussian(sigma);
+		v1_z = gsl_ran_gaussian(sigma);
+		return normalize(forward + cliptoplane(v1, forward));
+	}
+	else if(sstyle == 5) // 1-r
+	{
+		sigma = spread * 1.154700538379252; // match baseline stddev
+		v1 = findperpendicular(forward);
+		v2 = cross(forward, v1);
+		// random point on unit circle
+		dx = random() * 2 * M_PI;
+		dy = sin(dx);
+		dx = cos(dx);
+		// radius in our dist function
+		r = random();
+		r = solve_cubic_abcd(-2, 3, 0, -r) * '0 1 0';
+		return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+	}
+	else if(sstyle == 6) // 1-r^2
+	{
+		sigma = spread * 1.095445115010332; // match baseline stddev
+		v1 = findperpendicular(forward);
+		v2 = cross(forward, v1);
+		// random point on unit circle
+		dx = random() * 2 * M_PI;
+		dy = sin(dx);
+		dx = cos(dx);
+		// radius in our dist function
+		r = random();
+		r = sqrt(1 - r);
+		r = sqrt(1 - r);
+		return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+	}
+	else if(sstyle == 7) // (1-r) (2-r)
+	{
+		sigma = spread * 1.224744871391589; // match baseline stddev
+		v1 = findperpendicular(forward);
+		v2 = cross(forward, v1);
+		// random point on unit circle
+		dx = random() * 2 * M_PI;
+		dy = sin(dx);
+		dx = cos(dx);
+		// radius in our dist function
+		r = random();
+		r = 1 - sqrt(r);
+		r = 1 - sqrt(r);
+		return normalize(forward + (v1 * dx + v2 * dy) * r * sigma);
+	}
+	else
+		error("g_projectiles_spread_style must be 0 (sphere), 1 (flattened sphere), 2 (circle), 3 (gauss 3D), 4 (gauss plane), 5 (linear falloff), 6 (quadratic falloff), 7 (stronger falloff)!");
+	return '0 0 0';
+	/*
+	 * how to derive falloff functions:
+	 * rho(r) := (2-r) * (1-r);
+	 * a : 0;
+	 * b : 1;
+	 * rhor(r) := r * rho(r);
+	 * cr(t) := integrate(rhor(r), r, a, t);
+	 * scr(t) := integrate(rhor(r) * r^2, r, a, t);
+	 * variance : scr(b) / cr(b);
+	 * solve(cr(r) = rand * cr(b), r), programmmode:false;
+	 * sqrt(0.4 / variance), numer;
+	 */
+}
+
+#if 0
+float mspercallsum;
+float mspercallsstyle;
+float mspercallcount;
+#endif
+void W_SetupProjectileVelocityEx(entity missile, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute)
+{
+	if(missile.owner == world)
+		error("Unowned missile");
+
+	dir = dir + upDir * (pUpSpeed / pSpeed);
+	dir_z += pZSpeed / pSpeed;
+	pSpeed *= vlen(dir);
+	dir = normalize(dir);
+
+#if 0
+	if(autocvar_g_projectiles_spread_style != mspercallsstyle)
+	{
+		mspercallsum = mspercallcount = 0;
+		mspercallsstyle = autocvar_g_projectiles_spread_style;
+	}
+	mspercallsum -= gettime(GETTIME_HIRES);
+#endif
+	dir = W_CalculateProjectileSpread(dir, spread);
+#if 0
+	mspercallsum += gettime(GETTIME_HIRES);
+	mspercallcount += 1;
+	print("avg: ", ftos(mspercallcount / mspercallsum), " per sec\n");
+#endif
+
+	missile.velocity = W_CalculateProjectileVelocity(missile.owner.velocity, pSpeed * dir, forceAbsolute);
+}
+
+void W_SetupProjectileVelocity(entity missile, float pSpeed, float spread)
+{
+	W_SetupProjectileVelocityEx(missile, w_shotdir, v_up, pSpeed, 0, 0, spread, FALSE);
+}
+
+#define W_SETUPPROJECTILEVELOCITY_UP(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), cvar(#s "_speed_up"), cvar(#s "_speed_z"), cvar(#s "_spread"), FALSE)
+#define W_SETUPPROJECTILEVELOCITY(m,s) W_SetupProjectileVelocityEx(m, w_shotdir, v_up, cvar(#s "_speed"), 0, 0, cvar(#s "_spread"), FALSE)
+
+void W_DecreaseAmmo(.float ammo_type, float ammo_use, float ammo_reload)
+{
+	if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !ammo_reload)
+		return;
+
+	// if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+	if(ammo_reload)
+	{
+		self.clip_load -= ammo_use;
+		self.(weapon_load[self.weapon]) = self.clip_load;
+	}
+	else
+		self.(self.current_ammo) -= ammo_use;
+}
+
+// weapon reloading code
+
+.float reload_ammo_amount, reload_ammo_min, reload_time;
+.float reload_complain;
+.string reload_sound;
+
+void W_ReloadedAndReady()
+{
+	// finish the reloading process, and do the ammo transfer
+
+	self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
+
+	// if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
+	if(!self.reload_ammo_min || self.items & IT_UNLIMITED_WEAPON_AMMO)
+		self.clip_load = self.reload_ammo_amount;
+	else
+	{
+		while(self.clip_load < self.reload_ammo_amount && self.(self.current_ammo)) // make sure we don't add more ammo than we have
+		{
+			self.clip_load += 1;
+			self.(self.current_ammo) -= 1;
+		}
+	}
+	self.(weapon_load[self.weapon]) = self.clip_load;
+
+	// do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
+	// then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
+	// so your weapon is disabled for a few seconds without reason
+
+	//ATTACK_FINISHED(self) -= self.reload_time - 1;
+
+	w_ready();
+}
+
+void W_Reload(float sent_ammo_min, float sent_ammo_amount, float sent_time, string sent_sound)
+{
+	// set global values to work with
+
+	self.reload_ammo_min = sent_ammo_min;
+	self.reload_ammo_amount = sent_ammo_amount;
+	self.reload_time = sent_time;
+	self.reload_sound = sent_sound;
+
+	// check if we meet the necessary conditions to reload
+
+	entity e;
+	e = get_weaponinfo(self.weapon);
+
+	// don't reload weapons that don't have the RELOADABLE flag
+	if (!(e.spawnflags & WEP_FLAG_RELOADABLE))
+	{
+		dprint("Warning: Attempted to reload a weapon that does not have the WEP_FLAG_RELOADABLE flag. Fix your code!\n");
+		return;
+	}
+
+	// return if reloading is disabled for this weapon
+	if(!self.reload_ammo_amount)
+		return;
+
+	// our weapon is fully loaded, no need to reload
+	if (self.clip_load >= self.reload_ammo_amount)
+		return;
+
+	// no ammo, so nothing to load
+	if(!self.(self.current_ammo) && self.reload_ammo_min)
+	if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+	{
+		if(IS_REAL_CLIENT(self) && self.reload_complain < time)
+		{
+			play2(self, "weapons/unavailable.wav");
+			sprint(self, strcat("You don't have enough ammo to reload the ^2", W_Name(self.weapon), "\n"));
+			self.reload_complain = time + 1;
+		}
+		// switch away if the amount of ammo is not enough to keep using this weapon
+		if (!(weapon_action(self.weapon, WR_CHECKAMMO1) + weapon_action(self.weapon, WR_CHECKAMMO2)))
+		{
+			self.clip_load = -1; // reload later
+			W_SwitchToOtherWeapon(self);
+		}
+		return;
+	}
+
+	if (self.weaponentity)
+	{
+		if (self.weaponentity.wframe == WFRAME_RELOAD)
+			return;
+
+		// allow switching away while reloading, but this will cause a new reload!
+		self.weaponentity.state = WS_READY;
+	}
+
+	// now begin the reloading process
+
+	sound (self, CH_WEAPON_SINGLE, self.reload_sound, VOL_BASE, ATTEN_NORM);
+
+	// do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
+	// then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
+	// so your weapon is disabled for a few seconds without reason
+
+	//ATTACK_FINISHED(self) = max(time, ATTACK_FINISHED(self)) + self.reload_time + 1;
+
+	weapon_thinkf(WFRAME_RELOAD, self.reload_time, W_ReloadedAndReady);
+
+	if(self.clip_load < 0)
+		self.clip_load = 0;
+	self.old_clip_load = self.clip_load;
+	self.clip_load = self.(weapon_load[self.weapon]) = -1;
+}
diff --git a/qcsrc/server/csqceffects.qc b/qcsrc/server/csqceffects.qc
index ea13aedd5..4b626546d 100644
--- a/qcsrc/server/csqceffects.qc
+++ b/qcsrc/server/csqceffects.qc
@@ -1,7 +1,7 @@
 void te_csqc_lightningarc(vector from,vector to)
 {
 	WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
-	WriteByte(MSG_BROADCAST, TE_CSQC_ARC);
+	WriteByte(MSG_BROADCAST, TE_CSQC_LIGHTNINGARC);
 
 	WriteCoord(MSG_BROADCAST, from_x);
 	WriteCoord(MSG_BROADCAST, from_y);
diff --git a/qcsrc/server/csqcprojectile.qc b/qcsrc/server/csqcprojectile.qc
new file mode 100644
index 000000000..3c747bdbb
--- /dev/null
+++ b/qcsrc/server/csqcprojectile.qc
@@ -0,0 +1,118 @@
+.float csqcprojectile_type;
+
+float CSQCProjectile_SendEntity(entity to, float sf)
+{
+	float ft, fr;
+
+	// note: flag 0x08 = no trail please (teleport bit)
+	sf = sf & 0x0F;
+
+	if(self.csqcprojectile_clientanimate)
+		sf |= 0x80; // client animated, not interpolated
+
+	if(self.flags & FL_ONGROUND)
+		sf |= 0x40;
+
+	ft = fr = 0;
+	if(self.fade_time != 0 || self.fade_rate != 0)
+	{
+		ft = (self.fade_time - time) / sys_frametime;
+		fr = (1 / self.fade_rate) / sys_frametime;
+		if(ft <= 255 && fr <= 255 && fr >= 1)
+			sf |= 0x20;
+	}
+
+	if(self.gravity != 0)
+		sf |= 0x10;
+
+	WriteByte(MSG_ENTITY, ENT_CLIENT_PROJECTILE);
+	WriteByte(MSG_ENTITY, sf);
+
+	if(sf & 1)
+	{
+		WriteCoord(MSG_ENTITY, self.origin_x);
+		WriteCoord(MSG_ENTITY, self.origin_y);
+		WriteCoord(MSG_ENTITY, self.origin_z);
+
+		if(sf & 0x80)
+		{
+			WriteCoord(MSG_ENTITY, self.velocity_x);
+			WriteCoord(MSG_ENTITY, self.velocity_y);
+			WriteCoord(MSG_ENTITY, self.velocity_z);
+			if(sf & 0x10)
+				WriteCoord(MSG_ENTITY, self.gravity);
+		}
+
+		if(sf & 0x20)
+		{
+			WriteByte(MSG_ENTITY, ft);
+			WriteByte(MSG_ENTITY, fr);
+		}
+
+		WriteByte(MSG_ENTITY, self.realowner.team);
+	}
+
+	if(sf & 2)
+		WriteByte(MSG_ENTITY, self.csqcprojectile_type); // TODO maybe put this into sf?
+
+	return 1;
+}
+
+.vector csqcprojectile_oldorigin;
+void CSQCProjectile_Check(entity e)
+{
+	if(e.csqcprojectile_clientanimate)
+	if(e.flags & FL_ONGROUND)
+	if(e.origin != e.csqcprojectile_oldorigin)
+		UpdateCSQCProjectile(e);
+	e.csqcprojectile_oldorigin = e.origin;
+}
+
+void CSQCProjectile(entity e, float clientanimate, float type, float docull)
+{
+	Net_LinkEntity(e, docull, 0, CSQCProjectile_SendEntity);
+
+	e.csqcprojectile_clientanimate = clientanimate;
+
+	if(e.movetype == MOVETYPE_TOSS || e.movetype == MOVETYPE_BOUNCE)
+	{
+		if(e.gravity == 0)
+			e.gravity = 1;
+	}
+	else
+		e.gravity = 0;
+
+	if(!sound_allowed(MSG_BROADCAST, e))
+		type |= 0x80;
+	e.csqcprojectile_type = type;
+}
+
+// FIXME HACK
+float ItemSend(entity to, float sf);
+void ItemUpdate(entity item);
+// END HACK
+void UpdateCSQCProjectile(entity e)
+{
+	if(e.SendEntity == CSQCProjectile_SendEntity)
+	{
+		// send new origin data
+		e.SendFlags |= 0x01;
+	}
+// FIXME HACK
+	else if(e.SendEntity == ItemSend)
+	{
+		ItemUpdate(e);
+	}
+// END HACK
+}
+
+void UpdateCSQCProjectileAfterTeleport(entity e)
+{
+	if(e.SendEntity == CSQCProjectile_SendEntity)
+	{
+		// send new origin data
+		e.SendFlags |= 0x01;
+		// mark as teleported
+		e.SendFlags |= 0x08;
+	}
+}
diff --git a/qcsrc/server/csqcprojectile.qh b/qcsrc/server/csqcprojectile.qh
new file mode 100644
index 000000000..e00c0988b
--- /dev/null
+++ b/qcsrc/server/csqcprojectile.qh
@@ -0,0 +1,6 @@
+.float csqcprojectile_clientanimate;
+
+void CSQCProjectile(entity e, float clientanimate, float type, float docull);
+void UpdateCSQCProjectile(entity e);
+void UpdateCSQCProjectileAfterTeleport(entity e);
+void CSQCProjectile_Check(entity e);
diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh
index 0d03d52cc..dd0b5c22b 100644
--- a/qcsrc/server/defs.qh
+++ b/qcsrc/server/defs.qh
@@ -172,7 +172,7 @@ void setanim(entity e, vector anim, float looping, float override, float restart
 .string item_pickupsound;
 
 // definitions for weaponsystem
-// more WEAPONTODO: move these to their proper files
+
 .entity weaponentity;
 .entity exteriorweaponentity;
 .vector weaponentity_glowmod;
@@ -182,9 +182,8 @@ void setanim(entity e, vector anim, float looping, float override, float restart
 .float switchingweapon; // weapon currently being switched to (is copied from switchweapon once switch is possible)
 .string weaponname; // name of .weapon
 
-// WEAPONTODO
 .float autoswitch;
-//float WEP_ACTION(float wpn, float wrequest);
+float weapon_action(float wpn, float wrequest);
 float client_hasweapon(entity cl, float wpn, float andammo, float complain);
 void w_clear();
 void w_ready();
@@ -192,6 +191,9 @@ void w_ready();
 .float weapon_nextthink;
 .void() weapon_think;
 
+//float	PLAYER_WEAPONSELECTION_DELAY = );
+const float	PLAYER_WEAPONSELECTION_SPEED = 18;
+const vector	PLAYER_WEAPONSELECTION_RANGE = '0 20 -40';
 
 // weapon states (self.weaponentity.state)
 const float WS_CLEAR			= 0; // no weapon selected
@@ -286,12 +288,16 @@ string gamemode_name;
 
 float startitem_failed;
 
+typedef .float floatfield;
+floatfield Item_CounterField(float it);
+
+float W_AmmoItemCode(float wpn);
+string W_Name(float weaponid);
 string W_Apply_Weaponreplace(string in);
 
 void FixIntermissionClient(entity e);
 void FixClientCvars(entity e);
 
-// WEAPONTODO: remove this
 WepSet weaponsInMap;
 
 .float respawn_countdown; // next number to count
@@ -506,6 +512,7 @@ float servertime, serverprevtime, serverframetime;
 .float stat_shotorg; // networked stat for trueaim HUD
 
 string matchid;
+.float hitplotfh;
 
 .float last_pickup;
 
@@ -521,6 +528,8 @@ float client_cefc_accumulator;
 float client_cefc_accumulatortime;
 #endif
 
+..float current_ammo;
+
 .float weapon_load[WEP_MAXCOUNT];
 .float ammo_none; // used by the reloading system, must always be 0
 .float clip_load;
@@ -529,9 +538,9 @@ float client_cefc_accumulatortime;
 
 .entity lastrocket;
 .float minelayer_mines;
-.float vortex_charge;
-.float vortex_charge_rottime;
-.float vortex_chargepool_ammo;
+.float nex_charge;
+.float nex_charge_rottime;
+.float nex_chargepool_ammo;
 .float hagar_load;
 
 .float grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
@@ -551,6 +560,9 @@ string deathmessage;
 
 .float just_joined;
 
+.float cvar_cl_accuracy_data_share;
+.float cvar_cl_accuracy_data_receive;
+
 .float cvar_cl_weaponimpulsemode;
 .float selectweapon; // last selected weapon of the player
 
diff --git a/qcsrc/server/func_breakable.qc b/qcsrc/server/func_breakable.qc
index 0bf71059e..d67e79cd4 100644
--- a/qcsrc/server/func_breakable.qc
+++ b/qcsrc/server/func_breakable.qc
@@ -173,7 +173,7 @@ void func_breakable_destroy() {
 		sound (self, CH_TRIGGER, self.noise, VOL_BASE, ATTEN_NORM);
 
 	if(self.dmg)
-		RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, world, self.dmg_force, DEATH_HURTTRIGGER, world);
+		RadiusDamage(self, activator, self.dmg, self.dmg_edge, self.dmg_radius, self, self.dmg_force, DEATH_HURTTRIGGER, world);
 
 	if(self.cnt)
 		pointparticles(self.cnt, self.absmin * 0.5 + self.absmax * 0.5, '0 0 0', self.count);
diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc
index ec8333070..47443e6d7 100644
--- a/qcsrc/server/g_damage.qc
+++ b/qcsrc/server/g_damage.qc
@@ -115,7 +115,7 @@ void GiveFrags (entity attacker, entity targ, float f, float deathtype)
 		else if(!(attacker.weapons & WepSet_FromWeapon(culprit)))
 			culprit = attacker.weapon;
 
-		if(g_weaponarena_random_with_laser && culprit == WEP_BLASTER) // WEAPONTODO: Shouldn't this be in a mutator?
+		if(g_weaponarena_random_with_laser && culprit == WEP_LASER)
 		{
 			// no exchange
 		}
@@ -287,7 +287,7 @@ float Obituary_WeaponDeath(
 	if(death_weapon)
 	{
 		w_deathtype = deathtype;
-		float death_message = WEP_ACTION(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
+		float death_message = weapon_action(death_weapon, ((murder) ? WR_KILLMESSAGE : WR_SUICIDEMESSAGE));
 		w_deathtype = FALSE;
 
 		if(death_message)
@@ -948,10 +948,11 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, float
 }
 
 float RadiusDamage_running;
-float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float deathtype, entity directhitentity)
+float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity ignore, float forceintensity, float deathtype, entity directhitentity)
 	// Returns total damage applies to creatures
 {
 	entity	targ;
+	vector	blastorigin;
 	vector	force;
 	float   total_damage_to_creatures;
 	entity  next;
@@ -971,161 +972,202 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
 	tfloordmg = autocvar_g_throughfloor_damage;
 	tfloorforce = autocvar_g_throughfloor_force;
 
+	blastorigin = (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5);
 	total_damage_to_creatures = 0;
 
 	if(deathtype != (WEP_HOOK | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once
 		if(DEATH_WEAPONOF(deathtype) != WEP_TUBA) // do not send tuba damage (bandwidth hog)
 		{
-			force = inflictorvelocity;
+			force = inflictor.velocity;
 			if(vlen(force) == 0)
 				force = '0 0 -1';
 			else
 				force = normalize(force);
 			if(forceintensity >= 0)
-				Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
+				Damage_DamageInfo(blastorigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
 			else
-				Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
+				Damage_DamageInfo(blastorigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
 		}
 
 	stat_damagedone = 0;
 
-	targ = WarpZone_FindRadius (inflictororigin, rad + MAX_DAMAGEEXTRARADIUS, FALSE);
+	targ = WarpZone_FindRadius (blastorigin, rad + MAX_DAMAGEEXTRARADIUS, FALSE);
 	while (targ)
 	{
 		next = targ.chain;
-		if ((targ != inflictor) || inflictorselfdamage)
-		if (((cantbe != targ) && !mustbe) || (mustbe == targ))
-		if (targ.takedamage)
-		{
-			vector nearest;
-			vector diff;
-			float power;
-
-			// LordHavoc: measure distance to nearest point on target (not origin)
-			// (this guarentees 100% damage on a touch impact)
-			nearest = targ.WarpZone_findradius_nearest;
-			diff = targ.WarpZone_findradius_dist;
-			// round up a little on the damage to ensure full damage on impacts
-			// and turn the distance into a fraction of the radius
-			power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad);
-			//bprint(" ");
-			//bprint(ftos(power));
-			//if (targ == attacker)
-			//	print(ftos(power), "\n");
-			if (power > 0)
+		if (targ != inflictor)
+			if (ignore != targ) if(targ.takedamage)
 			{
-				float finaldmg;
-				if (power > 1)
-					power = 1;
-				finaldmg = coredamage * power + edgedamage * (1 - power);
-				if (finaldmg > 0)
+				vector nearest;
+				vector diff;
+				float power;
+
+				// LordHavoc: measure distance to nearest point on target (not origin)
+				// (this guarentees 100% damage on a touch impact)
+				nearest = targ.WarpZone_findradius_nearest;
+				diff = targ.WarpZone_findradius_dist;
+				// round up a little on the damage to ensure full damage on impacts
+				// and turn the distance into a fraction of the radius
+				power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad);
+				//bprint(" ");
+				//bprint(ftos(power));
+				//if (targ == attacker)
+				//	print(ftos(power), "\n");
+				if (power > 0)
 				{
-					float a;
-					float c;
-					vector hitloc;
-					vector myblastorigin;
-					vector center;
+					float finaldmg;
+					if (power > 1)
+						power = 1;
+					finaldmg = coredamage * power + edgedamage * (1 - power);
+					if (finaldmg > 0)
+					{
+						float a;
+						float c;
+						vector hitloc;
+						vector myblastorigin;
+						vector center;
 
-					myblastorigin = WarpZone_TransformOrigin(targ, inflictororigin);
+						myblastorigin = WarpZone_TransformOrigin(targ, blastorigin);
 
-					// if it's a player, use the view origin as reference
-					center = CENTER_OR_VIEWOFS(targ);
+						// if it's a player, use the view origin as reference
+						center = CENTER_OR_VIEWOFS(targ);
 
-					force = normalize(center - myblastorigin);
-					force = force * (finaldmg / coredamage) * forceintensity;
-					hitloc = nearest;
+						force = normalize(center - myblastorigin);
+						force = force * (finaldmg / coredamage) * forceintensity;
+						hitloc = nearest;
 
-					if(deathtype & WEP_BLASTER)
-						force *= WEP_CVAR_BOTH(blaster, !(deathtype & HITTYPE_SECONDARY), force_zscale);
+						if(targ != directhitentity)
+						{
+							float hits;
+							float total;
+							float hitratio;
+							float mininv_f, mininv_d;
 
-					if(targ != directhitentity)
-					{
-						float hits;
-						float total;
-						float hitratio;
-						float mininv_f, mininv_d;
+							// test line of sight to multiple positions on box,
+							// and do damage if any of them hit
+							hits = 0;
 
-						// test line of sight to multiple positions on box,
-						// and do damage if any of them hit
-						hits = 0;
+							// we know: max stddev of hitratio = 1 / (2 * sqrt(n))
+							// so for a given max stddev:
+							// n = (1 / (2 * max stddev of hitratio))^2
 
-						// we know: max stddev of hitratio = 1 / (2 * sqrt(n))
-						// so for a given max stddev:
-						// n = (1 / (2 * max stddev of hitratio))^2
+							mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev;
+							mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
 
-						mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev;
-						mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
+							if(autocvar_g_throughfloor_debug)
+								printf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f);
 
-						if(autocvar_g_throughfloor_debug)
-							printf("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f);
+							total = 0.25 * pow(max(mininv_f, mininv_d), 2);
 
+							if(autocvar_g_throughfloor_debug)
+								printf(" steps=%f", total);
 
-						total = 0.25 * pow(max(mininv_f, mininv_d), 2);
+							if (IS_PLAYER(targ))
+								total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player));
+							else
+								total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other));
 
-						if(autocvar_g_throughfloor_debug)
-							printf(" steps=%f", total);
+							if(autocvar_g_throughfloor_debug)
+								printf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)));
 
+							for(c = 0; c < total; ++c)
+							{
+								//traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
+								WarpZone_TraceLine(blastorigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
+								if (trace_fraction == 1 || trace_ent == targ)
+								{
+									++hits;
+									if (hits > 1)
+										hitloc = hitloc + nearest;
+									else
+										hitloc = nearest;
+								}
+								nearest_x = targ.origin_x + targ.mins_x + random() * targ.size_x;
+								nearest_y = targ.origin_y + targ.mins_y + random() * targ.size_y;
+								nearest_z = targ.origin_z + targ.mins_z + random() * targ.size_z;
+							}
 
-						if (IS_PLAYER(targ))
-							total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player));
-						else
-							total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other));
+							nearest = hitloc * (1 / max(1, hits));
+							hitratio = (hits / total);
+							a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1);
+							finaldmg = finaldmg * a;
+							a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1);
+							force = force * a;
 
-						if(autocvar_g_throughfloor_debug)
-							printf(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)));
+							if(autocvar_g_throughfloor_debug)
+								printf(" D=%f F=%f\n", finaldmg, vlen(force));
+						}
 
-						for(c = 0; c < total; ++c)
+						// laser force adjustments :P
+						if(DEATH_WEAPONOF(deathtype) == WEP_LASER)
 						{
-							//traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
-							WarpZone_TraceLine(inflictororigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
-							if (trace_fraction == 1 || trace_ent == targ)
+							if (targ == attacker)
 							{
-								++hits;
-								if (hits > 1)
-									hitloc = hitloc + nearest;
+								vector vel;
+
+								float force_zscale;
+								float force_velocitybiasramp;
+								float force_velocitybias;
+
+								force_velocitybiasramp = autocvar_sv_maxspeed;
+								if(deathtype & HITTYPE_SECONDARY)
+								{
+									force_zscale = autocvar_g_balance_laser_secondary_force_zscale;
+									force_velocitybias = autocvar_g_balance_laser_secondary_force_velocitybias;
+								}
 								else
-									hitloc = nearest;
+								{
+									force_zscale = autocvar_g_balance_laser_primary_force_zscale;
+									force_velocitybias = autocvar_g_balance_laser_primary_force_velocitybias;
+								}
+
+								vel = targ.velocity;
+								vel_z = 0;
+								vel = normalize(vel) * bound(0, vlen(vel) / force_velocitybiasramp, 1) * force_velocitybias;
+								force =
+									vlen(force)
+									*
+									normalize(normalize(force) + vel);
+
+								force_z *= force_zscale;
+							}
+							else
+							{
+								if(deathtype & HITTYPE_SECONDARY)
+								{
+									force *= autocvar_g_balance_laser_secondary_force_other_scale;
+								}
+								else
+								{
+									force *= autocvar_g_balance_laser_primary_force_other_scale;
+								}
 							}
-							nearest_x = targ.origin_x + targ.mins_x + random() * targ.size_x;
-							nearest_y = targ.origin_y + targ.mins_y + random() * targ.size_y;
-							nearest_z = targ.origin_z + targ.mins_z + random() * targ.size_z;
 						}
 
-						nearest = hitloc * (1 / max(1, hits));
-						hitratio = (hits / total);
-						a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1);
-						finaldmg = finaldmg * a;
-						a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1);
-						force = force * a;
-
-						if(autocvar_g_throughfloor_debug)
-							printf(" D=%f F=%f\n", finaldmg, vlen(force));
-					}
-
-					//if (targ == attacker)
-					//{
-					//	print("hits ", ftos(hits), " / ", ftos(total));
-					//	print(" finaldmg ", ftos(finaldmg), " force ", vtos(force));
-					//	print(" (", ftos(a), ")\n");
-					//}
-					if(finaldmg || vlen(force))
-					{
-						if(targ.iscreature)
+						//if (targ == attacker)
+						//{
+						//	print("hits ", ftos(hits), " / ", ftos(total));
+						//	print(" finaldmg ", ftos(finaldmg), " force ", vtos(force));
+						//	print(" (", ftos(a), ")\n");
+						//}
+						if(finaldmg || vlen(force))
 						{
-							total_damage_to_creatures += finaldmg;
+							if(targ.iscreature)
+							{
+								total_damage_to_creatures += finaldmg;
 
-							if(accuracy_isgooddamage(attacker, targ))
-								stat_damagedone += finaldmg;
-						}
+								if(accuracy_isgooddamage(attacker, targ))
+									stat_damagedone += finaldmg;
+							}
 
-						if(targ == directhitentity || DEATH_ISSPECIAL(deathtype))
-							Damage (targ, inflictor, attacker, finaldmg, deathtype, nearest, force);
-						else
-							Damage (targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, nearest, force);
+							if(targ == directhitentity || DEATH_ISSPECIAL(deathtype))
+								Damage (targ, inflictor, attacker, finaldmg, deathtype, nearest, force);
+							else
+								Damage (targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, nearest, force);
+						}
 					}
 				}
 			}
-		}
 		targ = next;
 	}
 
@@ -1137,11 +1179,6 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
 	return total_damage_to_creatures;
 }
 
-float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, float deathtype, entity directhitentity)
-{
-	return RadiusDamageForSource (inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, FALSE, forceintensity, deathtype, directhitentity);
-}
-
 .float fire_damagepersec;
 .float fire_endtime;
 .float fire_deathtype;
diff --git a/qcsrc/server/g_hook.qc b/qcsrc/server/g_hook.qc
index 90b91ad3d..4e1b63400 100644
--- a/qcsrc/server/g_hook.qc
+++ b/qcsrc/server/g_hook.qc
@@ -335,7 +335,7 @@ void FireGrapplingHook (void)
 
 	missile.state = 0; // not latched onto anything
 
-	W_SetupProjVelocity_Explicit(missile, v_forward, v_up, autocvar_g_balance_grapplehook_speed_fly, 0, 0, 0, FALSE);
+	W_SetupProjectileVelocityEx(missile, v_forward, v_up, autocvar_g_balance_grapplehook_speed_fly, 0, 0, 0, FALSE);
 
 	missile.angles = vectoangles (missile.velocity);
 	//missile.glow_color = 250; // 244, 250
@@ -476,7 +476,7 @@ void GrappleHookInit()
 	}
 	else
 	{
-		WEP_ACTION(WEP_HOOK, WR_INIT);
+		weapon_action(WEP_HOOK, WR_PRECACHE);
 		hook_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), FALSE, FALSE, 1);
 		hook_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), FALSE, FALSE, 2);
 		hook_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK), FALSE, FALSE, 3);
diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc
index bd685ba1f..a1460ded8 100644
--- a/qcsrc/server/g_world.qc
+++ b/qcsrc/server/g_world.qc
@@ -653,6 +653,8 @@ void spawnfunc_worldspawn (void)
 	InitGameplayMode();
 	readlevelcvars();
 	GrappleHookInit();
+	ElectroInit();
+	LaserInit();
 
 	player_count = 0;
 	bot_waypoints_for_items = autocvar_g_waypoints_for_items;
@@ -779,7 +781,6 @@ void spawnfunc_worldspawn (void)
 	addstat(STAT_SUPERWEAPONS_FINISHED, AS_FLOAT, superweapons_finished);
 	addstat(STAT_PRESSED_KEYS, AS_FLOAT, pressedkeys);
 	addstat(STAT_FUEL, AS_INT, ammo_fuel);
-	addstat(STAT_PLASMA, AS_INT, ammo_plasma);
 	addstat(STAT_SHOTORG, AS_INT, stat_shotorg);
 	addstat(STAT_LEADLIMIT, AS_FLOAT, stat_leadlimit);
 	addstat(STAT_WEAPON_CLIPLOAD, AS_INT, clip_load);
@@ -789,8 +790,8 @@ void spawnfunc_worldspawn (void)
 	addstat(STAT_TYPEHIT_TIME, AS_FLOAT, typehit_time);
 	addstat(STAT_LAYED_MINES, AS_INT, minelayer_mines);
 
-	addstat(STAT_VORTEX_CHARGE, AS_FLOAT, vortex_charge);
-	addstat(STAT_VORTEX_CHARGEPOOL, AS_FLOAT, vortex_chargepool_ammo);
+	addstat(STAT_NEX_CHARGE, AS_FLOAT, nex_charge);
+	addstat(STAT_NEX_CHARGEPOOL, AS_FLOAT, nex_chargepool_ammo);
 
 	addstat(STAT_HAGAR_LOAD, AS_INT, hagar_load);
 
diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc
index 368c27076..40421bbc0 100644
--- a/qcsrc/server/miscfunctions.qc
+++ b/qcsrc/server/miscfunctions.qc
@@ -355,13 +355,12 @@ string formatmessage(string msg)
 				wep = self.switchweapon;
 			if (!wep)
 				wep = self.cnt;
-			replacement = WEP_NAME(wep);
+			replacement = W_Name(wep);
 		} else if (escape == "W") {
 			if (self.items & IT_SHELLS) replacement = "shells";
 			else if (self.items & IT_NAILS) replacement = "bullets";
 			else if (self.items & IT_ROCKETS) replacement = "rockets";
 			else if (self.items & IT_CELLS) replacement = "cells";
-			else if (self.items & IT_PLASMA) replacement = "plasma";
 			else replacement = "batteries"; // ;)
 		} else if (escape == "x") {
 			replacement = cursor_ent.netname;
@@ -461,6 +460,7 @@ void GetCvars_handleFloatOnce(string thisname, float f, .float field, string nam
 			stuffcmd(self, strcat("cl_cmd sendcvar ", name, "\n"));
 	}
 }
+float w_getbestweapon(entity e);
 string W_FixWeaponOrder_ForceComplete_AndBuildImpulseList(string wo)
 {
 	string o;
@@ -563,8 +563,6 @@ float g_pickup_rockets;
 float g_pickup_rockets_max;
 float g_pickup_cells;
 float g_pickup_cells_max;
-float g_pickup_plasma;
-float g_pickup_plasma_max;
 float g_pickup_fuel;
 float g_pickup_fuel_jetpack;
 float g_pickup_fuel_max;
@@ -613,7 +611,6 @@ float start_ammo_shells;
 float start_ammo_nails;
 float start_ammo_rockets;
 float start_ammo_cells;
-float start_ammo_plasma;
 float start_ammo_fuel;
 float start_health;
 float start_armorvalue;
@@ -625,13 +622,14 @@ float warmup_start_ammo_shells;
 float warmup_start_ammo_nails;
 float warmup_start_ammo_rockets;
 float warmup_start_ammo_cells;
-float warmup_start_ammo_plasma;
 float warmup_start_ammo_fuel;
 float warmup_start_health;
 float warmup_start_armorvalue;
 float g_weapon_stay;
 
-float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still needs done? 
+entity get_weaponinfo(float w);
+
+float want_weapon(string cvarprefix, entity weaponinfo, float allguns)
 {
 	var float i = weaponinfo.weapon;
 	var float d = 0;
@@ -651,14 +649,14 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still ne
 	else if (g_nexball)
 		d = 0; // weapon is set a few lines later
 	else
-		d = !(!weaponinfo.weaponstart);
+		d = (i == WEP_LASER || i == WEP_SHOTGUN);
 
 	if(g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
 		d |= (i == WEP_HOOK);
-	if(!g_cts && (weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED)) // never default mutator blocked guns
+	if(weaponinfo.spawnflags & WEP_FLAG_MUTATORBLOCKED) // never default mutator blocked guns
 		d = 0;
 
-	var float t = weaponinfo.weaponstartoverride;
+	var float t = cvar(strcat(cvarprefix, weaponinfo.netname));
 
 	//print(strcat("want_weapon: ", weaponinfo.netname, " - d: ", ftos(d), ", t: ", ftos(t), ". \n"));
 
@@ -689,7 +687,6 @@ void readplayerstartcvars()
 	start_ammo_nails = 0;
 	start_ammo_rockets = 0;
 	start_ammo_cells = 0;
-	start_ammo_plasma = 0;
 	start_health = cvar("g_balance_health_start");
 	start_armorvalue = cvar("g_balance_armor_start");
 
@@ -782,7 +779,7 @@ void readplayerstartcvars()
 		for (i = WEP_FIRST; i <= WEP_LAST; ++i)
 		{
 			e = get_weaponinfo(i);
-			float w = want_weapon(e, FALSE);
+			float w = want_weapon("g_start_weapon_", e, FALSE);
 			if(w & 1)
 				start_weapons |= WepSet_FromWeapon(i);
 			if(w & 2)
@@ -800,7 +797,6 @@ void readplayerstartcvars()
 		start_ammo_rockets = 999;
 		start_ammo_shells = 999;
 		start_ammo_cells = 999;
-		start_ammo_plasma = 999;
 		start_ammo_nails = 999;
 		start_ammo_fuel = 999;
 	}
@@ -810,7 +806,6 @@ void readplayerstartcvars()
 		start_ammo_nails = cvar("g_start_ammo_nails");
 		start_ammo_rockets = cvar("g_start_ammo_rockets");
 		start_ammo_cells = cvar("g_start_ammo_cells");
-		start_ammo_plasma = cvar("g_start_ammo_plasma");
 		start_ammo_fuel = cvar("g_start_ammo_fuel");
 	}
 
@@ -842,7 +837,7 @@ void readplayerstartcvars()
 			for (i = WEP_FIRST; i <= WEP_LAST; ++i)
 			{
 				e = get_weaponinfo(i);
-				float w = want_weapon(e, g_warmup_allguns);
+				float w = want_weapon("g_start_weapon_", e, g_warmup_allguns);
 				if(w & 1)
 					warmup_start_weapons |= WepSet_FromWeapon(i);
 				if(w & 2)
@@ -873,20 +868,18 @@ void readplayerstartcvars()
 	{
 		e = get_weaponinfo(i);
 		if(precache_weapons & WepSet_FromWeapon(i))
-			WEP_ACTION(i, WR_INIT);
+			weapon_action(i, WR_PRECACHE);
 	}
 
 	start_ammo_shells = max(0, start_ammo_shells);
 	start_ammo_nails = max(0, start_ammo_nails);
 	start_ammo_cells = max(0, start_ammo_cells);
-	start_ammo_plasma = max(0, start_ammo_plasma);
 	start_ammo_rockets = max(0, start_ammo_rockets);
 	start_ammo_fuel = max(0, start_ammo_fuel);
 
 	warmup_start_ammo_shells = max(0, warmup_start_ammo_shells);
 	warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);
 	warmup_start_ammo_cells = max(0, warmup_start_ammo_cells);
-	warmup_start_ammo_plasma = max(0, warmup_start_ammo_plasma);
 	warmup_start_ammo_rockets = max(0, warmup_start_ammo_rockets);
 	warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
 }
@@ -986,8 +979,6 @@ void readlevelcvars(void)
 	g_pickup_rockets_max = cvar("g_pickup_rockets_max");
 	g_pickup_cells = cvar("g_pickup_cells");
 	g_pickup_cells_max = cvar("g_pickup_cells_max");
-	g_pickup_plasma = cvar("g_pickup_plasma");
-	g_pickup_plasma_max = cvar("g_pickup_plasma_max");
 	g_pickup_fuel = cvar("g_pickup_fuel");
 	g_pickup_fuel_jetpack = cvar("g_pickup_fuel_jetpack");
 	g_pickup_fuel_max = cvar("g_pickup_fuel_max");
@@ -1366,6 +1357,18 @@ void precache()
         precache_sound ("weapons/hook_impact.wav"); // hook
     }
 
+    if(autocvar_sv_precacheweapons)
+    {
+        //precache weapon models/sounds
+        float wep;
+        wep = WEP_FIRST;
+        while (wep <= WEP_LAST)
+        {
+            weapon_action(wep, WR_PRECACHE);
+            wep = wep + 1;
+        }
+    }
+
     precache_model("models/elaser.mdl");
     precache_model("models/laser.mdl");
     precache_model("models/ebomb.mdl");
diff --git a/qcsrc/server/mutators/base.qh b/qcsrc/server/mutators/base.qh
index 95d85d793..f4021eb4c 100644
--- a/qcsrc/server/mutators/base.qh
+++ b/qcsrc/server/mutators/base.qh
@@ -109,7 +109,7 @@ MUTATOR_HOOKABLE(WeaponRateFactor);
 		float weapon_rate;
 
 MUTATOR_HOOKABLE(SetStartItems);
-	// adjusts {warmup_}start_{items,weapons,ammo_{cells,plasma,rockets,nails,shells,fuel}}
+	// adjusts {warmup_}start_{items,weapons,ammo_{cells,rockets,nails,shells,fuel}}
 
 MUTATOR_HOOKABLE(BuildMutatorsString);
 	// appends ":mutatorname" to ret_string for logging
diff --git a/qcsrc/server/mutators/gamemode_ca.qc b/qcsrc/server/mutators/gamemode_ca.qc
index 0c5e01a6a..8b38ceb09 100644
--- a/qcsrc/server/mutators/gamemode_ca.qc
+++ b/qcsrc/server/mutators/gamemode_ca.qc
@@ -236,7 +236,6 @@ MUTATOR_HOOKFUNCTION(ca_SetStartItems)
 	start_ammo_nails   = warmup_start_ammo_nails   = cvar("g_lms_start_ammo_nails");
 	start_ammo_rockets = warmup_start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
 	start_ammo_cells   = warmup_start_ammo_cells   = cvar("g_lms_start_ammo_cells");
-	start_ammo_plasma  = warmup_start_ammo_plasma  = cvar("g_lms_start_ammo_plasma");
 	start_ammo_fuel    = warmup_start_ammo_fuel    = cvar("g_lms_start_ammo_fuel");
 
 	return 0;
diff --git a/qcsrc/server/mutators/gamemode_lms.qc b/qcsrc/server/mutators/gamemode_lms.qc
index 0684ac8ed..fb0bb2e86 100644
--- a/qcsrc/server/mutators/gamemode_lms.qc
+++ b/qcsrc/server/mutators/gamemode_lms.qc
@@ -135,7 +135,6 @@ MUTATOR_HOOKFUNCTION(lms_SetStartItems)
 	start_ammo_nails   = warmup_start_ammo_nails   = cvar("g_lms_start_ammo_nails");
 	start_ammo_rockets = warmup_start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
 	start_ammo_cells   = warmup_start_ammo_cells   = cvar("g_lms_start_ammo_cells");
-	start_ammo_plasma  = warmup_start_ammo_plasma  = cvar("g_lms_start_ammo_plasma");
 	start_ammo_fuel    = warmup_start_ammo_fuel    = cvar("g_lms_start_ammo_fuel");
 
 	return FALSE;
diff --git a/qcsrc/server/mutators/gamemode_nexball.qc b/qcsrc/server/mutators/gamemode_nexball.qc
index 85377836d..8695ca31b 100644
--- a/qcsrc/server/mutators/gamemode_nexball.qc
+++ b/qcsrc/server/mutators/gamemode_nexball.qc
@@ -142,7 +142,7 @@ void GiveBall(entity plyr, entity ball)
 	self.weaponentity.weapons = self.weapons;
 	self.weaponentity.switchweapon = self.weapon;
 	self.weapons = WEPSET_PORTO;
-	WEP_ACTION(WEP_PORTO, WR_RESETPLAYER);
+	weapon_action(WEP_PORTO, WR_RESETPLAYER);
 	self.switchweapon = WEP_PORTO;
 	W_SwitchWeapon(WEP_PORTO);
 	self = ownr;
@@ -784,7 +784,7 @@ void W_Nexball_Attack2(void)
 	setsize(missile, '0 0 0', '0 0 0');
 	setorigin(missile, w_shotorg);
 
-	W_SetupProjVelocity_Basic(missile, autocvar_g_balance_nexball_secondary_speed, 0);
+	W_SetupProjectileVelocity(missile, autocvar_g_balance_nexball_secondary_speed, 0);
 	missile.angles = vectoangles(missile.velocity);
 	missile.touch = W_Nexball_Touch;
 	missile.think = SUB_Remove;
@@ -855,7 +855,7 @@ float w_nexball_weapon(float req)
 			weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nexball_primary_animtime, w_ready);
 		}
 	}
-	else if(req == WR_INIT)
+	else if(req == WR_PRECACHE)
 	{
 		precache_model("models/weapons/g_porto.md3");
 		precache_model("models/weapons/v_porto.md3");
@@ -867,7 +867,7 @@ float w_nexball_weapon(float req)
 	}
 	else if(req == WR_SETUP)
 	{
-		//weapon_setup(WEP_PORTO);
+		weapon_setup(WEP_PORTO);
 	}
 	// No need to check WR_CHECKAMMO* or WR_AIM, it should always return TRUE
 	return TRUE;
@@ -930,7 +930,7 @@ MUTATOR_HOOKFUNCTION(nexball_PlayerPreThink)
 			if(self.weaponentity.weapons)
 			{
 				self.weapons = self.weaponentity.weapons;
-				WEP_ACTION(WEP_PORTO, WR_RESETPLAYER);
+				weapon_action(WEP_PORTO, WR_RESETPLAYER);
 				self.switchweapon = self.weaponentity.switchweapon;
 				W_SwitchWeapon(self.switchweapon);
 
@@ -976,7 +976,7 @@ MUTATOR_HOOKFUNCTION(nexball_SetStartItems)
 
 MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing)
 {
-	if(self.weapon == WEP_MORTAR)
+	if(self.weapon == WEP_GRENADE_LAUNCHER)
 		return TRUE;
 
 	return FALSE;
@@ -985,7 +985,7 @@ MUTATOR_HOOKFUNCTION(nexball_ForbidThrowing)
 MUTATOR_HOOKFUNCTION(nexball_FilterItem)
 {
 	if(self.classname == "droppedweapon")
-	if(self.weapon == WEP_MORTAR)
+	if(self.weapon == WEP_GRENADE_LAUNCHER)
 		return TRUE;
 
 	return FALSE;
@@ -1011,7 +1011,7 @@ MUTATOR_DEFINITION(gamemode_nexball)
 		g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
 		addstat(STAT_NB_METERSTART, AS_FLOAT, metertime);
 
-		W_Porto(WR_INIT); // abuse
+		w_porto(WR_PRECACHE); // abuse
 
 		// General settings
 		/*
diff --git a/qcsrc/server/mutators/mutator_minstagib.qc b/qcsrc/server/mutators/mutator_minstagib.qc
index d05e7e9c4..20811ad50 100644
--- a/qcsrc/server/mutators/mutator_minstagib.qc
+++ b/qcsrc/server/mutators/mutator_minstagib.qc
@@ -6,7 +6,7 @@ void spawnfunc_item_minst_cells (void)
 
 	StartItem ("models/items/a_cells.md3",
 			   "misc/itempickup.wav", 45, 0,
-			   "Vaporizer Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100);
+			   "MinstaNex Ammo", IT_CELLS, 0, 0, generic_pickupevalfunc, 100);
 }
 
 void minstagib_health_mega()
@@ -245,7 +245,7 @@ MUTATOR_HOOKFUNCTION(minstagib_PlayerDamage)
 		}
 
 		if(IS_PLAYER(frag_attacker))
-		if(DEATH_ISWEAPON(frag_deathtype, WEP_VAPORIZER))
+		if(DEATH_ISWEAPON(frag_deathtype, WEP_MINSTANEX))
 		if(frag_target.armorvalue)
 		{
 			frag_target.armorvalue -= 1;
@@ -256,7 +256,7 @@ MUTATOR_HOOKFUNCTION(minstagib_PlayerDamage)
 		}
 
 		if(IS_PLAYER(frag_attacker))
-		if(DEATH_ISWEAPON(frag_deathtype, WEP_BLASTER))
+		if (DEATH_ISWEAPON(frag_deathtype, WEP_LASER))
 		{
 			frag_damage = 0;
 			frag_mirrordamage = 0;
@@ -296,8 +296,8 @@ MUTATOR_HOOKFUNCTION(minstagib_SetStartItems)
 
 	start_health = 100;
 	start_armorvalue = 0;
-	start_weapons = WEPSET_VAPORIZER;
-	warmup_start_weapons = WEPSET_VAPORIZER;
+	start_weapons = WEPSET_MINSTANEX;
+	warmup_start_weapons = WEPSET_MINSTANEX;
 	start_items |= IT_UNLIMITED_SUPERWEAPONS;
 
 	return FALSE;
@@ -308,13 +308,13 @@ MUTATOR_HOOKFUNCTION(minstagib_FilterItem)
 	if(self.classname == "item_cells")
 		return TRUE; // no normal cells?
 
-	if(self.weapon == WEP_VAPORIZER && self.classname == "droppedweapon")
+	if(self.weapon == WEP_MINSTANEX && self.classname == "droppedweapon")
 	{
 		self.ammo_cells = autocvar_g_minstagib_ammo_drop;
 		return FALSE;
 	}
 
-	if(self.weapon == WEP_DEVASTATOR || self.weapon == WEP_VORTEX)
+	if(self.weapon == WEP_ROCKET_LAUNCHER || self.weapon == WEP_NEX)
 	{
 		entity e = spawn();
 		setorigin(e, self.origin);
diff --git a/qcsrc/server/mutators/mutator_nades.qc b/qcsrc/server/mutators/mutator_nades.qc
index 70c4578bd..da75e25ac 100644
--- a/qcsrc/server/mutators/mutator_nades.qc
+++ b/qcsrc/server/mutators/mutator_nades.qc
@@ -250,7 +250,7 @@ void nade_ice_think()
 			sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
 
 			RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
-				autocvar_g_nades_nade_radius, self, world, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy);
+				autocvar_g_nades_nade_radius, self, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy);
 			Damage_DamageInfo(self.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
 				autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, self.projectiledeathtype, 0, self);
 		}
@@ -525,10 +525,12 @@ void nade_boom()
 	sound(self, CH_SHOTS_SINGLE, "misc/null.wav", VOL_BASE, ATTEN_NORM);
 	sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
 
+	self.takedamage = DAMAGE_NO;
+
 	if(nade_blast)
 	{
 		RadiusDamage(self, self.realowner, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage,
-				 autocvar_g_nades_nade_radius, self, world, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy);
+				 autocvar_g_nades_nade_radius, self, autocvar_g_nades_nade_force, self.projectiledeathtype, self.enemy);
 		Damage_DamageInfo(self.origin, autocvar_g_nades_nade_damage, autocvar_g_nades_nade_edgedamage, autocvar_g_nades_nade_radius, '1 1 1' * autocvar_g_nades_nade_force, self.projectiledeathtype, 0, self);
 	}
 
@@ -573,19 +575,20 @@ void nade_damage(entity inflictor, entity attacker, float damage, float deathtyp
 	if(self.nade_type == NADE_TYPE_TRANSLOCATE || self.nade_type == NADE_TYPE_SPAWN)
 		return;
 
-	if(DEATH_ISWEAPON(deathtype, WEP_BLASTER))
+	if(DEATH_ISWEAPON(deathtype, WEP_LASER))
 		return;
 
-	if(DEATH_ISWEAPON(deathtype, WEP_VORTEX) || DEATH_ISWEAPON(deathtype, WEP_VAPORIZER))
+	if(DEATH_ISWEAPON(deathtype, WEP_NEX) || DEATH_ISWEAPON(deathtype, WEP_MINSTANEX))
 	{
 		force *= 6;
 		damage = self.max_health * 0.55;
 	}
 
-	if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN))
+	if(DEATH_ISWEAPON(deathtype, WEP_UZI))
 		damage = self.max_health * 0.1;
 
-	if((DEATH_ISWEAPON(deathtype, WEP_SHOCKWAVE) || DEATH_ISWEAPON(deathtype, WEP_SHOTGUN)) && (deathtype & HITTYPE_SECONDARY)) // WEAPONTODO
+	if(DEATH_ISWEAPON(deathtype, WEP_SHOTGUN))
+	if(deathtype & HITTYPE_SECONDARY)
 	{
 		damage = self.max_health * 0.1;
 		force *= 10;
diff --git a/qcsrc/server/mutators/mutator_new_toys.qc b/qcsrc/server/mutators/mutator_new_toys.qc
index d540adee6..f11298451 100644
--- a/qcsrc/server/mutators/mutator_new_toys.qc
+++ b/qcsrc/server/mutators/mutator_new_toys.qc
@@ -1,7 +1,7 @@
 /*
 
-CORE    laser   vortex     lg      rl      cry     gl      elec    hagar   fireb   hook
-									vaporizer  porto
+CORE    laser   nex     lg      rl      cry     gl      elec    hagar   fireb   hook
+									minsta  porto
 									tuba
 
 NEW             rifle   hlac    minel                           seeker
@@ -18,28 +18,28 @@ weaponreplace lists.
 Entity:
 
 {
-"classname" "weapon_vortex"
+"classname" "weapon_nex"
 "new_toys" "rifle"
 }
--> This will spawn as Rifle in this mutator ONLY, and as Vortex otherwise.
+-> This will spawn as Rifle in this mutator ONLY, and as Nex otherwise.
 
 {
-"classname" "weapon_vortext"
-"new_toys" "vortex rifle"
+"classname" "weapon_nex"
+"new_toys" "nex rifle"
 }
--> This will spawn as either Vortex or Rifle in this mutator ONLY, and as Vortex otherwise.
+-> This will spawn as either Nex or Rifle in this mutator ONLY, and as Nex otherwise.
 
 {
-"classname" "weapon_vortex"
-"new_toys" "vortex"
+"classname" "weapon_nex"
+"new_toys" "nex"
 }
--> This is always a Vortex.
+-> This is always a Nex.
 
 If the map specifies no "new_toys" argument
 
 There will be two default replacements selectable: "replace all" and "replace random".
-In "replace all" mode, e.g. Vortex will have the default replacement "rifle".
-In "replace random" mode, Vortex will have the default replacement "vortex rifle".
+In "replace all" mode, e.g. Nex will have the default replacement "rifle".
+In "replace random" mode, Nex will have the default replacement "nex rifle".
 
 This mutator's replacements run BEFORE regular weaponreplace!
 
@@ -87,7 +87,6 @@ float nt_IsNewToy(float w)
 		case WEP_MINE_LAYER:
 		case WEP_HLAC:
 		case WEP_RIFLE:
-		case WEP_SHOTGUN:
 			return TRUE;
 		default:
 			return FALSE;
@@ -101,8 +100,7 @@ string nt_GetFullReplacement(string w)
 		case "hagar": return "seeker";
 		case "rocketlauncher": return "minelayer";
 		case "uzi": return "hlac";
-		case "vortex": return "rifle";
-		case "shockwave": return "shotgun";
+		case "nex": return "rifle";
 		default: return string_null;
 	}
 }
diff --git a/qcsrc/server/mutators/mutator_nix.qc b/qcsrc/server/mutators/mutator_nix.qc
index 5ea5f1ad6..dc12b0520 100644
--- a/qcsrc/server/mutators/mutator_nix.qc
+++ b/qcsrc/server/mutators/mutator_nix.qc
@@ -1,8 +1,10 @@
 float g_nix_with_laser;
-// WEAPONTODO
+
 float nix_weapon;
+float nix_weapon_ammo;
 float nix_nextchange;
 float nix_nextweapon;
+float nix_nextweapon_ammo;
 .float nix_lastchange_id;
 .float nix_lastinfotime;
 .float nix_nextincr;
@@ -20,7 +22,7 @@ float NIX_CanChooseWeapon(float wpn)
 	}
 	else
 	{
-		if(wpn == WEP_BLASTER && g_nix_with_laser) // WEAPONTODO: rename to g_nix_with_blaster
+		if(wpn == WEP_LASER && g_nix_with_laser)
 			return FALSE;
 		if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
 			return FALSE;
@@ -37,6 +39,7 @@ void NIX_ChooseNextWeapon()
 		if(NIX_CanChooseWeapon(j))
 			RandomSelection_Add(world, j, string_null, 1, (j != nix_weapon));
 	nix_nextweapon = RandomSelection_chosen_float;
+	nix_nextweapon_ammo = W_AmmoItemCode(nix_nextweapon);
 }
 
 void NIX_GiveCurrentWeapon()
@@ -51,68 +54,65 @@ void NIX_GiveCurrentWeapon()
 	if(dt <= 0)
 	{
 		nix_weapon = nix_nextweapon;
+		nix_weapon_ammo = nix_nextweapon_ammo;
 		nix_nextweapon = 0;
 		if (!nix_nextchange) // no round played yet?
 			nix_nextchange = time; // start the first round now!
 		else
 			nix_nextchange = time + autocvar_g_balance_nix_roundtime;
-		//WEP_ACTION(nix_weapon, WR_INIT); // forget it, too slow
+		//weapon_action(nix_weapon, WR_PRECACHE); // forget it, too slow
 	}
 
-	// get weapon info
-	entity e = get_weaponinfo(nix_weapon);
-
 	if(nix_nextchange != self.nix_lastchange_id) // this shall only be called once per round!
 	{
-		self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = self.ammo_plasma = self.ammo_fuel = 0;
-		
-		if(self.items & IT_UNLIMITED_WEAPON_AMMO)
+		self.nix_lastchange_id = nix_nextchange;
+		if (self.items & IT_UNLIMITED_WEAPON_AMMO)
 		{
-			switch(e.ammo_field)
-			{
-				case ammo_shells:  self.ammo_shells  = autocvar_g_pickup_shells_max;  break;
-				case ammo_nails:   self.ammo_nails   = autocvar_g_pickup_nails_max;   break;
-				case ammo_rockets: self.ammo_rockets = autocvar_g_pickup_rockets_max; break;
-				case ammo_cells:   self.ammo_cells   = autocvar_g_pickup_cells_max;   break;
-				case ammo_plasma:  self.ammo_plasma  = autocvar_g_pickup_plasma_max;   break;
-				case ammo_fuel:    self.ammo_fuel    = autocvar_g_pickup_fuel_max;    break;
-			}
+			self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
+				autocvar_g_pickup_shells_max : 0;
+			self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
+				autocvar_g_pickup_nails_max : 0;
+			self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
+				autocvar_g_pickup_rockets_max : 0;
+			self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
+				autocvar_g_pickup_cells_max : 0;
+			self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
+				autocvar_g_pickup_fuel_max : 0;
 		}
 		else
 		{
-			switch(e.ammo_field)
-			{
-				case ammo_shells:  self.ammo_shells  = autocvar_g_balance_nix_ammo_shells;  break;
-				case ammo_nails:   self.ammo_nails   = autocvar_g_balance_nix_ammo_nails;   break;
-				case ammo_rockets: self.ammo_rockets = autocvar_g_balance_nix_ammo_rockets; break;
-				case ammo_cells:   self.ammo_cells   = autocvar_g_balance_nix_ammo_cells;   break;
-				case ammo_plasma:  self.ammo_plasma  = autocvar_g_balance_nix_ammo_plasma;   break;
-				case ammo_fuel:    self.ammo_fuel    = autocvar_g_balance_nix_ammo_fuel;    break;
-			}
+			self.ammo_shells = (nix_weapon_ammo & IT_SHELLS) ?
+				autocvar_g_balance_nix_ammo_shells : 0;
+			self.ammo_nails = (nix_weapon_ammo & IT_NAILS) ?
+				autocvar_g_balance_nix_ammo_nails : 0;
+			self.ammo_rockets = (nix_weapon_ammo & IT_ROCKETS) ?
+				autocvar_g_balance_nix_ammo_rockets : 0;
+			self.ammo_cells = (nix_weapon_ammo & IT_CELLS) ?
+				autocvar_g_balance_nix_ammo_cells : 0;
+			self.ammo_fuel = (nix_weapon_ammo & IT_FUEL) ?
+				autocvar_g_balance_nix_ammo_fuel : 0;
 		}
-
 		self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
 		if(dt >= 1 && dt <= 5)
 			self.nix_lastinfotime = -42;
 		else
 			Send_Notification(NOTIF_ONE_ONLY, self, MSG_CENTER, CENTER_NIX_NEWWEAPON, nix_weapon);
 
-		WEP_ACTION(nix_weapon, WR_RESETPLAYER);
+		weapon_action(nix_weapon, WR_RESETPLAYER);
 
 		// all weapons must be fully loaded when we spawn
+		entity e;
+		e = get_weaponinfo(nix_weapon);
 		if(e.spawnflags & WEP_FLAG_RELOADABLE) // prevent accessing undefined cvars
-			self.(weapon_load[nix_weapon]) = e.reloading_ammo;
+			self.(weapon_load[nix_weapon]) = cvar(strcat("g_balance_", e.netname, "_reload_ammo"));
 
 		// nex too
-		if(WEP_CVAR(vortex, charge))
+		if(autocvar_g_balance_nex_charge)
 		{
-			if(WEP_CVAR_SEC(vortex, chargepool))
-				self.vortex_chargepool_ammo = 1;
-			self.vortex_charge = WEP_CVAR(vortex, charge_start);
+			if(autocvar_g_balance_nex_secondary_chargepool)
+				self.nex_chargepool_ammo = 1;
+			self.nex_charge = autocvar_g_balance_nex_charge_start;
 		}
-
-		// set last change info
-		self.nix_lastchange_id = nix_nextchange;
 	}
 	if(self.nix_lastinfotime != dt)
 	{
@@ -123,22 +123,22 @@ void NIX_GiveCurrentWeapon()
 
 	if(!(self.items & IT_UNLIMITED_WEAPON_AMMO) && time > self.nix_nextincr)
 	{
-		switch(e.ammo_field)
-		{
-			case ammo_shells:  self.ammo_shells  += autocvar_g_balance_nix_ammoincr_shells;  break;
-			case ammo_nails:   self.ammo_nails   += autocvar_g_balance_nix_ammoincr_nails;   break;
-			case ammo_rockets: self.ammo_rockets += autocvar_g_balance_nix_ammoincr_rockets; break;
-			case ammo_cells:   self.ammo_cells   += autocvar_g_balance_nix_ammoincr_cells;   break;
-			case ammo_plasma:  self.ammo_plasma  += autocvar_g_balance_nix_ammoincr_plasma;   break;
-			case ammo_fuel:    self.ammo_fuel    += autocvar_g_balance_nix_ammoincr_fuel;    break;
-		}
-
+		if (nix_weapon_ammo & IT_SHELLS)
+			self.ammo_shells = self.ammo_shells + autocvar_g_balance_nix_ammoincr_shells;
+		else if (nix_weapon_ammo & IT_NAILS)
+			self.ammo_nails = self.ammo_nails + autocvar_g_balance_nix_ammoincr_nails;
+		else if (nix_weapon_ammo & IT_ROCKETS)
+			self.ammo_rockets = self.ammo_rockets + autocvar_g_balance_nix_ammoincr_rockets;
+		else if (nix_weapon_ammo & IT_CELLS)
+			self.ammo_cells = self.ammo_cells + autocvar_g_balance_nix_ammoincr_cells;
+		if (nix_weapon_ammo & IT_FUEL) // hook uses cells and fuel
+			self.ammo_fuel = self.ammo_fuel + autocvar_g_balance_nix_ammoincr_fuel;
 		self.nix_nextincr = time + autocvar_g_balance_nix_incrtime;
 	}
 
 	self.weapons = '0 0 0';
 	if(g_nix_with_laser)
-		self.weapons &= ~WEPSET_BLASTER;
+		self.weapons &= ~WEPSET_LASER;
 	self.weapons |= WepSet_FromWeapon(nix_weapon);
 
 	if(self.switchweapon != nix_weapon)
@@ -152,7 +152,7 @@ void NIX_precache()
 	float i;
 	for (i = WEP_FIRST; i <= WEP_LAST; ++i)
 		if (NIX_CanChooseWeapon(i))
-			WEP_ACTION(i, WR_INIT);
+			weapon_action(i, WR_PRECACHE);
 }
 
 MUTATOR_HOOKFUNCTION(nix_ForbidThrowCurrentWeapon)
@@ -259,7 +259,6 @@ MUTATOR_DEFINITION(mutator_nix)
 		FOR_EACH_PLAYER(e) if(e.deadflag == DEAD_NO)
 		{
 			e.ammo_cells = start_ammo_cells;
-			e.ammo_plasma = start_ammo_plasma;
 			e.ammo_shells = start_ammo_shells;
 			e.ammo_nails = start_ammo_nails;
 			e.ammo_rockets = start_ammo_rockets;
diff --git a/qcsrc/server/mutators/mutator_touchexplode.qc b/qcsrc/server/mutators/mutator_touchexplode.qc
index 5f02a8aba..30b01b0da 100644
--- a/qcsrc/server/mutators/mutator_touchexplode.qc
+++ b/qcsrc/server/mutators/mutator_touchexplode.qc
@@ -12,7 +12,7 @@ void PlayerTouchExplode(entity p1, entity p2)
 	entity e;
 	e = spawn();
 	setorigin(e, org);
-	RadiusDamage(e, world, autocvar_g_touchexplode_damage, autocvar_g_touchexplode_edgedamage, autocvar_g_touchexplode_radius, world, world, autocvar_g_touchexplode_force, DEATH_TOUCHEXPLODE, world);
+	RadiusDamage(e, world, autocvar_g_touchexplode_damage, autocvar_g_touchexplode_edgedamage, autocvar_g_touchexplode_radius, world, autocvar_g_touchexplode_force, DEATH_TOUCHEXPLODE, world);
 	remove(e);
 }
 
diff --git a/qcsrc/server/progs.src b/qcsrc/server/progs.src
index 9cc8c9954..288b24775 100644
--- a/qcsrc/server/progs.src
+++ b/qcsrc/server/progs.src
@@ -11,6 +11,7 @@ sys-post.qh
 ../warpzonelib/common.qh
 ../warpzonelib/util_server.qh
 ../warpzonelib/server.qh
+
 ../common/constants.qh
 ../common/stats.qh
 ../common/teams.qh
@@ -19,6 +20,8 @@ sys-post.qh
 ../common/buffs.qh
 ../common/test.qh
 ../common/counting.qh
+../common/items.qh
+../common/explosion_equation.qh
 ../common/urllib.qh
 ../common/command/markup.qh
 ../common/command/rpn.qh
@@ -30,21 +33,6 @@ sys-post.qh
 ../common/monsters/sv_monsters.qh
 ../common/monsters/spawn.qh
 
-../common/weapons/config.qh
-../common/weapons/weapons.qh // TODO
-weapons/accuracy.qh
-weapons/common.qh
-weapons/csqcprojectile.qh // TODO
-weapons/hitplot.qh
-weapons/selection.qh
-weapons/spawning.qh
-weapons/throwing.qh
-weapons/tracing.qh
-weapons/weaponstats.qh
-weapons/weaponsystem.qh
-
-t_items.qh
-
 autocvars.qh
 constants.qh
 defs.qh		// Should rename this, it has fields and globals
@@ -70,7 +58,8 @@ command/getreplies.qh
 command/cmd.qh
 command/sv_cmd.qh
 
-
+accuracy.qh
+csqcprojectile.qh
 ../common/csqcmodel_settings.qh
 ../csqcmodellib/common.qh
 ../csqcmodellib/sv_model.qh
@@ -82,7 +71,9 @@ playerstats.qh
 
 portals.qh
 
-g_hook.qh // TODO
+g_hook.qh
+w_electro.qh
+w_laser.qh
 
 scores.qh
 
@@ -149,20 +140,13 @@ g_models.qc
 item_key.qc
 secret.qc
 
-weapons/accuracy.qc
-weapons/common.qc
-weapons/csqcprojectile.qc // TODO
-weapons/hitplot.qc
-weapons/selection.qc
-weapons/spawning.qc
-weapons/throwing.qc
-weapons/tracing.qc
-weapons/weaponstats.qc
-weapons/weaponsystem.qc
-../common/weapons/config.qc
-../common/weapons/weapons.qc // TODO
+cl_weaponsystem.qc
+w_common.qc
+
+w_all.qc
 
 t_items.qc
+cl_weapons.qc
 cl_impulse.qc
 
 ent_cs.qc
@@ -225,10 +209,15 @@ target_spawn.qc
 func_breakable.qc
 target_music.qc
 
+../common/items.qc
+
 ../common/nades.qc
 ../common/buffs.qc
 
+
+accuracy.qc
 ../csqcmodellib/sv_model.qc
+csqcprojectile.qc
 
 playerdemo.qc
 
@@ -238,6 +227,8 @@ playerstats.qc
 
 round_handler.qc
 
+../common/explosion_equation.qc
+
 ../common/monsters/sv_monsters.qc
 ../common/monsters/monsters.qc
 
diff --git a/qcsrc/server/t_items.qc b/qcsrc/server/t_items.qc
index cc0cb773a..238c6cec5 100644
--- a/qcsrc/server/t_items.qc
+++ b/qcsrc/server/t_items.qc
@@ -1,4 +1,32 @@
+#define ISF_LOCATION 2
+#define ISF_MODEL    4
+#define ISF_STATUS   8
+    #define ITS_STAYWEP   1
+    #define ITS_ANIMATE1  2
+    #define ITS_ANIMATE2  4
+    #define ITS_AVAILABLE 8
+    #define ITS_ALLOWFB   16
+    #define ITS_ALLOWSI   32
+    #define ITS_POWERUP   64
+#define ISF_COLORMAP 16
+#define ISF_DROP 32
+#define ISF_ANGLES 64
+
+.float ItemStatus;
+
 #ifdef CSQC
+
+var float  autocvar_cl_animate_items = 1;
+var float  autocvar_cl_ghost_items = 0.45;
+var vector autocvar_cl_ghost_items_color = '-1 -1 -1';
+var float  autocvar_cl_fullbright_items = 0;
+var vector autocvar_cl_weapon_stay_color = '2 0.5 0.5';
+var float  autocvar_cl_weapon_stay_alpha = 0.75;
+var float  autocvar_cl_simple_items = 0;
+var string autocvar_cl_simpleitems_postfix = "_simple";
+.float  spawntime;
+.float  gravity;
+.vector colormod;
 void ItemDraw()
 {
     if(self.gravity)
@@ -67,17 +95,6 @@ void ItemRead(float _IsNew)
         self.move_angles = self.angles;
     }
 
-    if(sf & ISF_SIZE)
-    {
-        self.mins_x = ReadCoord();
-        self.mins_y = ReadCoord();
-        self.mins_z = ReadCoord();
-        self.maxs_x = ReadCoord();
-        self.maxs_y = ReadCoord();
-        self.maxs_z = ReadCoord();
-        setsize(self, self.mins, self.maxs);
-    }
-
     if(sf & ISF_STATUS) // need to read/write status frist so model can handle simple, fb etc.
     {
         self.ItemStatus = ReadByte();
@@ -121,7 +138,7 @@ void ItemRead(float _IsNew)
     if(sf & ISF_MODEL)
     {
         self.drawmask  = MASK_NORMAL;
-        self.movetype  = MOVETYPE_TOSS;
+        self.movetype  = MOVETYPE_NOCLIP;
         self.draw       = ItemDraw;
 
         if(self.mdl)
@@ -169,7 +186,7 @@ void ItemRead(float _IsNew)
     if(sf & ISF_DROP)
     {
         self.gravity = 1;
-        //self.move_angles = '0 0 0';
+        self.move_angles = '0 0 0';
         self.move_movetype = MOVETYPE_TOSS;
         self.move_velocity_x = ReadCoord();
         self.move_velocity_y = ReadCoord();
@@ -199,6 +216,7 @@ void ItemRead(float _IsNew)
 #endif
 
 #ifdef SVQC
+float autocvar_sv_simple_items;
 float ItemSend(entity to, float sf)
 {
     if(self.gravity)
@@ -224,16 +242,6 @@ float ItemSend(entity to, float sf)
         WriteCoord(MSG_ENTITY, self.angles_z);
     }
 
-    if(sf & ISF_SIZE)
-    {
-        WriteCoord(MSG_ENTITY, self.mins_x);
-        WriteCoord(MSG_ENTITY, self.mins_y);
-        WriteCoord(MSG_ENTITY, self.mins_z);
-        WriteCoord(MSG_ENTITY, self.maxs_x);
-        WriteCoord(MSG_ENTITY, self.maxs_y);
-        WriteCoord(MSG_ENTITY, self.maxs_z);
-    }
-
     if(sf & ISF_STATUS)
         WriteByte(MSG_ENTITY, self.ItemStatus);
 
@@ -281,12 +289,63 @@ float have_pickup_item(void)
 		if(autocvar_g_pickup_items == 0)
 			return FALSE;
 		if(g_weaponarena)
-			if(self.weapons || (self.items & IT_AMMO)) // no item or ammo pickups in weaponarena
+			if(self.weapons || (self.items & IT_AMMO))
 				return FALSE;
 	}
 	return TRUE;
 }
 
+#define ITEM_RESPAWN_TICKS 10
+
+#define ITEM_RESPAWNTIME(i)         ((i).respawntime + crandom() * (i).respawntimejitter)
+	// range: respawntime - respawntimejitter .. respawntime + respawntimejitter
+#define ITEM_RESPAWNTIME_INITIAL(i) (ITEM_RESPAWN_TICKS + random() * ((i).respawntime + (i).respawntimejitter - ITEM_RESPAWN_TICKS))
+	// range: 10 .. respawntime + respawntimejitter
+
+floatfield Item_CounterField(float it)
+{
+	switch(it)
+	{
+		case IT_SHELLS:      return ammo_shells;
+		case IT_NAILS:       return ammo_nails;
+		case IT_ROCKETS:     return ammo_rockets;
+		case IT_CELLS:       return ammo_cells;
+		case IT_FUEL:        return ammo_fuel;
+		case IT_5HP:         return health;
+		case IT_25HP:        return health;
+		case IT_HEALTH:      return health;
+		case IT_ARMOR_SHARD: return armorvalue;
+		case IT_ARMOR:       return armorvalue;
+		// add more things here (health, armor)
+		default:             error("requested item has no counter field");
+	}
+#ifdef GMQCC
+	// should never happen
+	return health;
+#endif
+}
+
+string Item_CounterFieldName(float it)
+{
+	switch(it)
+	{
+		case IT_SHELLS:      return "shells";
+		case IT_NAILS:       return "nails";
+		case IT_ROCKETS:     return "rockets";
+		case IT_CELLS:       return "cells";
+		case IT_FUEL:        return "fuel";
+
+		// add more things here (health, armor)
+		default:             error("requested item has no counter field name");
+	}
+#ifdef GMQCC
+	// should never happen
+	return string_null;
+#endif
+}
+
+.float max_armorvalue;
+.float pickup_anyway;
 /*
 float Item_Customize()
 {
@@ -371,16 +430,6 @@ void Item_Show (entity e, float mode)
     e.SendFlags |= ISF_STATUS;
 }
 
-void Item_Think()
-{
-	self.nextthink = time;
-	if(self.origin != self.oldorigin)
-	{
-		self.oldorigin = self.origin;
-		ItemUpdate(self);
-	}
-}
-
 void Item_Respawn (void)
 {
 	Item_Show(self, 1);
@@ -393,9 +442,6 @@ void Item_Respawn (void)
 		sound (self, CH_TRIGGER, "misc/itemrespawn.wav", VOL_BASE, ATTEN_NORM);	// play respawn sound
 	setorigin (self, self.origin);
 
-	self.think = Item_Think;
-	self.nextthink = time;
-	
 	//pointparticles(particleeffectnum("item_respawn"), self.origin + self.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1);
 	pointparticles(particleeffectnum("item_respawn"), self.origin + 0.5 * (self.mins + self.maxs), '0 0 0', 1);
 }
@@ -434,7 +480,7 @@ void Item_RespawnCountdown (void)
 				entity wi = get_weaponinfo(self.weapon);
 				if(wi)
 				{
-					name = wi.wpmodel;
+					name = wi.model2;
 					rgb = '1 0 0';
 				}
 			}
@@ -459,19 +505,6 @@ void Item_RespawnCountdown (void)
 	}
 }
 
-void Item_RespawnThink()
-{
-	self.nextthink = time;
-	if(self.origin != self.oldorigin)
-	{
-		self.oldorigin = self.origin;
-		ItemUpdate(self);
-	}
-
-	if(time >= self.wait)
-		Item_Respawn();
-}
-
 void Item_ScheduleRespawnIn(entity e, float t)
 {
 	if((e.flags & FL_POWERUP) || (e.weapons & WEPSET_SUPERWEAPONS))
@@ -482,9 +515,8 @@ void Item_ScheduleRespawnIn(entity e, float t)
 	}
 	else
 	{
-		e.think = Item_RespawnThink;
-		e.nextthink = time;
-		e.wait = time + t;
+		e.think = Item_Respawn;
+		e.nextthink = time + t;
 	}
 }
 
@@ -505,25 +537,29 @@ void Item_ScheduleInitialRespawn(entity e)
 	Item_ScheduleRespawnIn(e, game_starttime - time + ITEM_RESPAWNTIME_INITIAL(e));
 }
 
-float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax, float mode)
+const float ITEM_MODE_NONE = 0;
+const float ITEM_MODE_HEALTH = 1;
+const float ITEM_MODE_ARMOR = 2;
+const float ITEM_MODE_FUEL = 3;
+float Item_GiveAmmoTo(entity item, entity player, .float ammofield, float ammomax, float mode)
 {
-	if (!item.ammotype)
+	if (!item.ammofield)
 		return FALSE;
 
 	if (item.spawnshieldtime)
 	{
-		if ((player.ammotype < ammomax) || item.pickup_anyway)
+		if ((player.ammofield < ammomax) || item.pickup_anyway)
 		{
-			player.ammotype = bound(player.ammotype, ammomax, player.ammotype + item.ammotype);
+			player.ammofield = bound(player.ammofield, ammomax, player.ammofield + item.ammofield);
 			goto YEAH;
 		}
 	}
 	else if(g_weapon_stay == 2)
 	{
-		float mi = min(item.ammotype, ammomax);
-		if (player.ammotype < mi)
+		float mi = min(item.ammofield, ammomax);
+		if (player.ammofield < mi)
 		{
-			player.ammotype = mi;
+			player.ammofield = mi;
 			goto YEAH;
 		}
 	}
@@ -573,7 +609,6 @@ float Item_GiveTo(entity item, entity player)
 	pickedup |= Item_GiveAmmoTo(item, player, ammo_nails, g_pickup_nails_max, ITEM_MODE_NONE);
 	pickedup |= Item_GiveAmmoTo(item, player, ammo_rockets, g_pickup_rockets_max, ITEM_MODE_NONE);
 	pickedup |= Item_GiveAmmoTo(item, player, ammo_cells, g_pickup_cells_max, ITEM_MODE_NONE);
-	pickedup |= Item_GiveAmmoTo(item, player, ammo_plasma, g_pickup_plasma_max, ITEM_MODE_NONE);
 	pickedup |= Item_GiveAmmoTo(item, player, health, item.max_health, ITEM_MODE_HEALTH);
 	pickedup |= Item_GiveAmmoTo(item, player, armorvalue, item.max_armorvalue, ITEM_MODE_ARMOR);
 
@@ -721,8 +756,8 @@ void Item_Reset()
 
 	if(self.classname != "droppedweapon")
 	{
-		self.think = Item_Think;
-		self.nextthink = time;
+		self.think = func_null;
+		self.nextthink = 0;
 
 		if(self.waypointsprite_attached)
 			WaypointSprite_Kill(self.waypointsprite_attached);
@@ -784,7 +819,7 @@ float weapon_pickupevalfunc(entity player, entity item)
 		// If I can pick it up
 		if(!item.spawnshieldtime)
 			c = 0;
-		else if(player.ammo_cells || player.ammo_shells || player.ammo_plasma || player.ammo_nails || player.ammo_rockets)
+		else if(player.ammo_cells || player.ammo_shells || player.ammo_nails || player.ammo_rockets)
 		{
 			// Skilled bots will grab more
 			c = bound(0, skill / 10, 1) * 0.5;
@@ -827,7 +862,7 @@ float weapon_pickupevalfunc(entity player, entity item)
 float commodity_pickupevalfunc(entity player, entity item)
 {
 	float c, i;
-	float need_shells = FALSE, need_nails = FALSE, need_rockets = FALSE, need_cells = FALSE, need_plasma = FALSE, need_fuel = FALSE;
+	float need_shells = FALSE, need_nails = FALSE, need_rockets = FALSE, need_cells = FALSE, need_fuel = FALSE;
 	entity wi;
 	c = 0;
 
@@ -847,8 +882,6 @@ float commodity_pickupevalfunc(entity player, entity item)
 			need_rockets = TRUE;
 		else if(wi.items & IT_CELLS)
 			need_cells = TRUE;
-		else if(wi.items & IT_PLASMA)
-			need_plasma = TRUE;
 		else if(wi.items & IT_FUEL)
 			need_cells = TRUE;
 	}
@@ -872,10 +905,6 @@ float commodity_pickupevalfunc(entity player, entity item)
 	if (item.ammo_cells)
 	if (player.ammo_cells < g_pickup_cells_max)
 		c = c + max(0, 1 - player.ammo_cells / g_pickup_cells_max);
-	if (need_plasma)
-	if (item.ammo_plasma)
-	if (player.ammo_plasma < g_pickup_plasma_max)
-		c = c + max(0, 1 - player.ammo_plasma / g_pickup_plasma_max);
 	if (need_fuel)
 	if (item.ammo_fuel)
 	if (player.ammo_fuel < g_pickup_fuel_max)
@@ -896,6 +925,7 @@ void Item_Damage(entity inflictor, entity attacker, float damage, float deathtyp
 		RemoveItem();
 }
 
+.float is_item;
 void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, float defaultrespawntimejitter, string itemname, float itemid, float weaponid, float itemflags, float(entity player, entity item) pickupevalfunc, float pickupbasevalue)
 {
 	startitem_failed = FALSE;
@@ -982,6 +1012,9 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
 			return;
 		}
 
+		if(self.angles != '0 0 0')
+            self.SendFlags |= ISF_ANGLES;
+
 		self.reset = Item_Reset;
 		// it's a level item
 		if(self.spawnflags & 1)
@@ -1000,7 +1033,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
 				setsize (self, '-16 -16 0', '16 16 48');
 			else
 				setsize (self, '-16 -16 0', '16 16 32');
-
 			// note droptofloor returns FALSE if stuck/or would fall too far
 			droptofloor();
 			waypoint_spawnforitem(self);
@@ -1104,10 +1136,6 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
 		Item_Reset();
 
     Net_LinkEntity(self, FALSE, 0, ItemSend);
-	
-	self.SendFlags |= ISF_SIZE;
-	if(self.angles)
-		self.SendFlags |= ISF_ANGLES;
 
 	// call this hook after everything else has been done
 	if(MUTATOR_CALLHOOK(Item_Spawn))
@@ -1117,6 +1145,183 @@ void StartItem (string itemmodel, string pickupsound, float defaultrespawntime,
 		return;
 	}
 }
+
+float weaponswapping;
+float internalteam;
+
+void weapon_defaultspawnfunc(float wpn)
+{
+	entity e;
+	float t;
+	var .float ammofield;
+	string s;
+	entity oldself;
+	float i, j;
+	float f;
+
+	if(self.classname != "droppedweapon" && self.classname != "replacedweapon")
+	{
+		e = get_weaponinfo(wpn);
+
+		if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
+		{
+			objerror("Attempted to spawn a mutator-blocked weapon rejected");
+			startitem_failed = TRUE;
+			return;
+		}
+
+		s = W_Apply_Weaponreplace(e.netname);
+		ret_string = s;
+		other = e;
+		MUTATOR_CALLHOOK(SetWeaponreplace);
+		s = ret_string;
+		if(s == "")
+		{
+			remove(self);
+			startitem_failed = TRUE;
+			return;
+		}
+		t = tokenize_console(s);
+		if(t >= 2)
+		{
+			self.team = --internalteam;
+			oldself = self;
+			for(i = 1; i < t; ++i)
+			{
+				s = argv(i);
+				for(j = WEP_FIRST; j <= WEP_LAST; ++j)
+				{
+					e = get_weaponinfo(j);
+					if(e.netname == s)
+					{
+						self = spawn();
+						copyentity(oldself, self);
+						self.classname = "replacedweapon";
+						weapon_defaultspawnfunc(j);
+						break;
+					}
+				}
+				if(j > WEP_LAST)
+				{
+					print("The weapon replace list for ", oldself.classname, " contains an unknown weapon ", s, ". Skipped.\n");
+				}
+			}
+			self = oldself;
+		}
+		if(t >= 1) // always the case!
+		{
+			s = argv(0);
+			wpn = 0;
+			for(j = WEP_FIRST; j <= WEP_LAST; ++j)
+			{
+				e = get_weaponinfo(j);
+				if(e.netname == s)
+				{
+					wpn = j;
+					break;
+				}
+			}
+			if(j > WEP_LAST)
+			{
+				print("The weapon replace list for ", self.classname, " contains an unknown weapon ", s, ". Skipped.\n");
+			}
+		}
+		if(wpn == 0)
+		{
+			remove(self);
+			startitem_failed = TRUE;
+			return;
+		}
+	}
+
+	e = get_weaponinfo(wpn);
+
+	if(!self.respawntime)
+	{
+		if(e.weapons & WEPSET_SUPERWEAPONS)
+		{
+			self.respawntime = g_pickup_respawntime_superweapon;
+			self.respawntimejitter = g_pickup_respawntimejitter_superweapon;
+		}
+		else
+		{
+			self.respawntime = g_pickup_respawntime_weapon;
+			self.respawntimejitter = g_pickup_respawntimejitter_weapon;
+		}
+	}
+
+	if(e.weapons & WEPSET_SUPERWEAPONS)
+		if(!self.superweapons_finished)
+			self.superweapons_finished = autocvar_g_balance_superweapons_time;
+
+	if(e.items)
+	{
+		for(i = 0, j = 1; i < 24; ++i, j *= 2)
+		{
+			if(e.items & j)
+			{
+				ammofield = Item_CounterField(j);
+				if(!self.ammofield)
+					self.ammofield = cvar(strcat("g_pickup_", Item_CounterFieldName(j), "_weapon"));
+			}
+		}
+	}
+
+	// pickup anyway
+	if(g_pickup_weapons_anyway)
+		self.pickup_anyway = TRUE;
+
+	f = FL_WEAPON;
+
+	// no weapon-stay on superweapons
+	if(e.weapons & WEPSET_SUPERWEAPONS)
+		f |= FL_NO_WEAPON_STAY;
+
+	// weapon stay isn't supported for teamed weapons
+	if(self.team)
+		f |= FL_NO_WEAPON_STAY;
+
+	StartItem(e.model, "weapons/weaponpickup.wav", self.respawntime, self.respawntimejitter, e.message, 0, e.weapon, f, weapon_pickupevalfunc, e.bot_pickupbasevalue);
+	if (self.modelindex) // don't precache if self was removed
+		weapon_action(e.weapon, WR_PRECACHE);
+}
+
+void spawnfunc_weapon_shotgun (void);
+void spawnfunc_weapon_uzi (void) {
+	if(autocvar_sv_q3acompat_machineshotgunswap)
+	if(self.classname != "droppedweapon")
+	{
+		weapon_defaultspawnfunc(WEP_SHOTGUN);
+		return;
+	}
+	weapon_defaultspawnfunc(WEP_UZI);
+}
+
+void spawnfunc_weapon_shotgun (void) {
+	if(autocvar_sv_q3acompat_machineshotgunswap)
+	if(self.classname != "droppedweapon")
+	{
+		weapon_defaultspawnfunc(WEP_UZI);
+		return;
+	}
+	weapon_defaultspawnfunc(WEP_SHOTGUN);
+}
+
+void spawnfunc_weapon_nex (void)
+{
+	weapon_defaultspawnfunc(WEP_NEX);
+}
+
+void spawnfunc_weapon_minstanex (void)
+{
+	weapon_defaultspawnfunc(WEP_MINSTANEX);
+}
+
+void spawnfunc_weapon_rocketlauncher (void)
+{
+	weapon_defaultspawnfunc(WEP_ROCKET_LAUNCHER);
+}
+
 void spawnfunc_item_rockets (void) {
 	if(!self.ammo_rockets)
 		self.ammo_rockets = g_pickup_rockets;
@@ -1152,15 +1357,6 @@ void spawnfunc_item_cells (void) {
 	StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "cells", IT_CELLS, 0, 0, commodity_pickupevalfunc, 2000);
 }
 
-void spawnfunc_item_plasma()
-{
-	if(!self.ammo_plasma)
-		self.ammo_plasma = g_pickup_plasma;
-	if(!self.pickup_anyway)
-		self.pickup_anyway = g_pickup_ammo_anyway;
-	StartItem ("models/items/a_cells.md3", "misc/itempickup.wav", g_pickup_respawntime_ammo, g_pickup_respawntimejitter_ammo, "plasma", IT_PLASMA, 0, 0, commodity_pickupevalfunc, 2000);
-}
-
 void spawnfunc_item_shells (void) {
 	if(!weaponswapping)
 	if(autocvar_sv_q3acompat_machineshotgunswap)
@@ -1282,6 +1478,7 @@ void spawnfunc_item_invincible (void) {
 // compatibility:
 void spawnfunc_item_quad (void) {self.classname = "item_strength";spawnfunc_item_strength();}
 
+float GiveItems(entity e, float beginarg, float endarg);
 void target_items_use (void)
 {
 	if(activator.classname == "droppedweapon")
@@ -1352,7 +1549,7 @@ void spawnfunc_target_items (void)
 					{
 						self.weapons |= WepSet_FromWeapon(j);
 						if(self.spawnflags == 0 || self.spawnflags == 2)
-							WEP_ACTION(e.weapon, WR_INIT);
+							weapon_action(e.weapon, WR_PRECACHE);
 						break;
 					}
 				}
@@ -1403,7 +1600,6 @@ void spawnfunc_target_items (void)
 		if(self.ammo_nails != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_nails), "nails");
 		if(self.ammo_rockets != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_rockets), "rockets");
 		if(self.ammo_cells != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_cells), "cells");
-		if(self.ammo_plasma != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_plasma), "plasma");
 		if(self.ammo_fuel != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.ammo_fuel), "fuel");
 		if(self.health != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.health), "health");
 		if(self.armorvalue != 0) self.netname = sprintf("%s %s%d %s", self.netname, valueprefix, max(0, self.health), "armor");
@@ -1425,7 +1621,7 @@ void spawnfunc_target_items (void)
 			e = get_weaponinfo(j);
 			if(argv(i) == e.netname)
 			{
-				WEP_ACTION(e.weapon, WR_INIT);
+				weapon_action(e.weapon, WR_PRECACHE);
 				break;
 			}
 		}
@@ -1465,6 +1661,13 @@ void spawnfunc_item_jetpack(void)
 	StartItem ("models/items/g_jetpack.md3", "misc/itempickup.wav", g_pickup_respawntime_powerup, g_pickup_respawntimejitter_powerup, "Jet pack", IT_JETPACK, 0, FL_POWERUP, commodity_pickupevalfunc, BOT_PICKUP_RATING_LOW);
 }
 
+
+#define OP_SET 0
+#define OP_MIN 1
+#define OP_MAX 2
+#define OP_PLUS 3
+#define OP_MINUS 4
+
 float GiveWeapon(entity e, float wpn, float op, float val)
 {
 	WepSet v0, v1;
@@ -1574,6 +1777,14 @@ void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .floa
 	else if(v0 > v1)
 		e.regenfield = max(e.regenfield, time + regentime);
 }
+
+#define PREGIVE_WEAPONS(e) WepSet save_weapons; save_weapons = e.weapons
+#define PREGIVE(e,f) float save_##f; save_##f = (e).f
+#define POSTGIVE_WEAPON(e,b,snd_incr,snd_decr) GiveSound((e), !!(save_weapons & WepSet_FromWeapon(b)), !!(e.weapons & WepSet_FromWeapon(b)), 0, snd_incr, snd_decr)
+#define POSTGIVE_BIT(e,f,b,snd_incr,snd_decr) GiveSound((e), save_##f & (b), (e).f & (b), 0, snd_incr, snd_decr)
+#define POSTGIVE_VALUE(e,f,t,snd_incr,snd_decr) GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr)
+#define POSTGIVE_VALUE_ROT(e,f,t,rotfield,rottime,regenfield,regentime,snd_incr,snd_decr) GiveRot((e), save_##f, (e).f, rotfield, rottime, regenfield, regentime); GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr)
+
 float GiveItems(entity e, float beginarg, float endarg)
 {
 	float got, i, j, val, op;
@@ -1602,7 +1813,6 @@ float GiveItems(entity e, float beginarg, float endarg)
 	PREGIVE(e, superweapons_finished);
 	PREGIVE(e, ammo_nails);
 	PREGIVE(e, ammo_cells);
-	PREGIVE(e, ammo_plasma);
 	PREGIVE(e, ammo_shells);
 	PREGIVE(e, ammo_rockets);
 	PREGIVE(e, ammo_fuel);
@@ -1656,7 +1866,6 @@ float GiveItems(entity e, float beginarg, float endarg)
 				}
 			case "allammo":
 				got += GiveValue(e, ammo_cells, op, val);
-				got += GiveValue(e, ammo_plasma, op, val);
 				got += GiveValue(e, ammo_shells, op, val);
 				got += GiveValue(e, ammo_nails, op, val);
 				got += GiveValue(e, ammo_rockets, op, val);
@@ -1689,9 +1898,6 @@ float GiveItems(entity e, float beginarg, float endarg)
 			case "cells":
 				got += GiveValue(e, ammo_cells, op, val);
 				break;
-			case "plasma":
-				got += GiveValue(e, ammo_plasma, op, val);
-				break;
 			case "shells":
 				got += GiveValue(e, ammo_shells, op, val);
 				break;
@@ -1741,14 +1947,13 @@ float GiveItems(entity e, float beginarg, float endarg)
 			POSTGIVE_WEAPON(e, j, "weapons/weaponpickup.wav", string_null);
 			if (!(save_weapons & WepSet_FromWeapon(j)))
 				if(e.weapons & WepSet_FromWeapon(j))
-					WEP_ACTION(wi.weapon, WR_INIT);
+					weapon_action(wi.weapon, WR_PRECACHE);
 		}
 	}
 	POSTGIVE_VALUE(e, strength_finished, 1, "misc/powerup.wav", "misc/poweroff.wav");
 	POSTGIVE_VALUE(e, invincible_finished, 1, "misc/powerup_shield.wav", "misc/poweroff.wav");
 	POSTGIVE_VALUE(e, ammo_nails, 0, "misc/itempickup.wav", string_null);
 	POSTGIVE_VALUE(e, ammo_cells, 0, "misc/itempickup.wav", string_null);
-	POSTGIVE_VALUE(e, ammo_plasma, 0, "misc/itempickup.wav", string_null);
 	POSTGIVE_VALUE(e, ammo_shells, 0, "misc/itempickup.wav", string_null);
 	POSTGIVE_VALUE(e, ammo_rockets, 0, "misc/itempickup.wav", string_null);
 	POSTGIVE_VALUE_ROT(e, ammo_fuel, 1, pauserotfuel_finished, autocvar_g_balance_pause_fuel_rot, pauseregen_finished, autocvar_g_balance_pause_fuel_regen, "misc/itempickup.wav", string_null);
diff --git a/qcsrc/server/t_items.qh b/qcsrc/server/t_items.qh
deleted file mode 100644
index 13cc3796f..000000000
--- a/qcsrc/server/t_items.qh
+++ /dev/null
@@ -1,169 +0,0 @@
-// constants
-#define WANT_CONST /* we WANT these to be constant, but it conflicts with the declaration in dpdefs/progsdefs.qc */
-const      float IT_UNLIMITED_WEAPON_AMMO     =       1; // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
-const      float IT_UNLIMITED_SUPERWEAPONS    =       2; // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
-const      float IT_CTF_SHIELDED              =       4; // set for the flag shield
-const      float IT_USING_JETPACK             =       8; // confirmation that button is pressed
-const      float IT_JETPACK                   =      16; // actual item
-const      float IT_FUEL_REGEN                =      32; // fuel regeneration trigger
-// where is 64... ?
-const      float IT_FUEL                      =     128;
-WANT_CONST float IT_SHELLS                    =     256;
-WANT_CONST float IT_NAILS                     =     512;
-WANT_CONST float IT_ROCKETS                   =    1024;
-WANT_CONST float IT_CELLS                     =    2048;
-const      float IT_SUPERWEAPON               =    4096;
-const      float IT_STRENGTH                  =    8192;
-const      float IT_INVINCIBLE                =   16384;
-const      float IT_HEALTH                    =   32768;
-const      float IT_PLASMA                    =   65536;
-
-// shared value space (union):
-	// for items:
-	WANT_CONST float IT_KEY1                  =  131072;
-	WANT_CONST float IT_KEY2                  =  262144;
-	// for players:
-	const      float IT_RED_FLAG_TAKEN        =   32768;
-	const      float IT_RED_FLAG_LOST         =   65536;
-	const      float IT_RED_FLAG_CARRYING     =   98304;
-	const      float IT_BLUE_FLAG_TAKEN       =  131072;
-	const      float IT_BLUE_FLAG_LOST        =  262144;
-	const      float IT_BLUE_FLAG_CARRYING    =  393216;
-// end
-
-const      float IT_5HP                       =  524288;
-const      float IT_25HP                      = 1048576;
-const      float IT_ARMOR_SHARD               = 2097152;
-const      float IT_ARMOR                     = 4194304;
-
-// item masks
-const      float IT_AMMO                      =    3968; // IT_FUEL | IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS | IT_PLASMA;
-const      float IT_PICKUPMASK                =      51; // IT_FUEL_REGEN | IT_JETPACK | IT_UNLIMITED_AMMO; // strength and invincible are handled separately
-const      float IT_UNLIMITED_AMMO            =       3; // IT_UNLIMITED_SUPERWEAPONS | IT_UNLIMITED_WEAPON_AMMO;
-
-const float AMMO_COUNT = 4; // amount of ammo types to show in the inventory panel
-
-// item networking
-#define ISF_LOCATION 2
-#define ISF_MODEL    4
-#define ISF_STATUS   8
-    #define ITS_STAYWEP   1
-    #define ITS_ANIMATE1  2
-    #define ITS_ANIMATE2  4
-    #define ITS_AVAILABLE 8
-    #define ITS_ALLOWFB   16
-    #define ITS_ALLOWSI   32
-    #define ITS_POWERUP   64
-#define ISF_COLORMAP 16
-#define ISF_DROP 32
-#define ISF_ANGLES 64
-#define ISF_SIZE 128
-
-.float ItemStatus;
-
-#ifdef CSQC
-
-var float  autocvar_cl_animate_items = 1;
-var float  autocvar_cl_ghost_items = 0.45;
-var vector autocvar_cl_ghost_items_color = '-1 -1 -1';
-var float  autocvar_cl_fullbright_items = 0;
-var vector autocvar_cl_weapon_stay_color = '2 0.5 0.5';
-var float  autocvar_cl_weapon_stay_alpha = 0.75;
-var float  autocvar_cl_simple_items = 0;
-var string autocvar_cl_simpleitems_postfix = "_simple";
-.float  spawntime;
-.float  gravity;
-.vector colormod;
-void ItemDraw();
-
-void ItemDrawSimple();
-
-void ItemRead(float _IsNew);
-
-#endif
-#ifdef SVQC
-float autocvar_sv_simple_items;
-float ItemSend(entity to, float sf);
-
-
-float have_pickup_item(void);
-
-#define ITEM_RESPAWN_TICKS 10
-
-#define ITEM_RESPAWNTIME(i)         ((i).respawntime + crandom() * (i).respawntimejitter)
-	// range: respawntime - respawntimejitter .. respawntime + respawntimejitter
-#define ITEM_RESPAWNTIME_INITIAL(i) (ITEM_RESPAWN_TICKS + random() * ((i).respawntime + (i).respawntimejitter - ITEM_RESPAWN_TICKS))
-	// range: 10 .. respawntime + respawntimejitter
-
-.float max_armorvalue;
-.float pickup_anyway;
-
-void Item_Show (entity e, float mode);
-
-void Item_Respawn (void);
-
-void Item_RespawnCountdown (void);
-void Item_ScheduleRespawnIn(entity e, float t);
-
-void Item_ScheduleRespawn(entity e);
-
-void Item_ScheduleInitialRespawn(entity e);
-float ITEM_MODE_NONE = 0;
-float ITEM_MODE_HEALTH = 1;
-float ITEM_MODE_ARMOR = 2;
-float ITEM_MODE_FUEL = 3;
-float Item_GiveAmmoTo(entity item, entity player, .float ammotype, float ammomax, float mode);
-
-float Item_GiveTo(entity item, entity player);
-
-void Item_Touch (void);
-
-void Item_Reset();
-
-void Item_FindTeam();
-// Savage: used for item garbage-collection
-// TODO: perhaps nice special effect?
-
-float ItemSend(entity to, float sf);
-void ItemUpdate(entity item);
-
-// pickup evaluation functions
-// these functions decide how desirable an item is to the bots
-
-float generic_pickupevalfunc(entity player, entity item);// {return item.bot_pickupbasevalue;} // WEAPONTODO
-
-float weapon_pickupevalfunc(entity player, entity item);
-
-float commodity_pickupevalfunc(entity player, entity item);
-
-.float is_item;
-void StartItem (string itemmodel, string pickupsound, float defaultrespawntime, float defaultrespawntimejitter, string itemname, float itemid, float weaponid, float itemflags, float(entity player, entity item) pickupevalfunc, float pickupbasevalue);
-
-
-void target_items_use (void);
-
-#define OP_SET 0
-#define OP_MIN 1
-#define OP_MAX 2
-#define OP_PLUS 3
-#define OP_MINUS 4
-
-float GiveWeapon(entity e, float wpn, float op, float val);
-
-float GiveBit(entity e, .float fld, float bit, float op, float val);
-
-float GiveValue(entity e, .float fld, float op, float val);
-
-void GiveSound(entity e, float v0, float v1, float t, string snd_incr, string snd_decr);
-
-void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .float regenfield, float regentime);
-
-#define PREGIVE_WEAPONS(e) WepSet save_weapons; save_weapons = e.weapons
-#define PREGIVE(e,f) float save_##f; save_##f = (e).f
-#define POSTGIVE_WEAPON(e,b,snd_incr,snd_decr) GiveSound((e), !!(save_weapons & WepSet_FromWeapon(b)), !!(e.weapons & WepSet_FromWeapon(b)), 0, snd_incr, snd_decr)
-#define POSTGIVE_BIT(e,f,b,snd_incr,snd_decr) GiveSound((e), save_##f & (b), (e).f & (b), 0, snd_incr, snd_decr)
-#define POSTGIVE_VALUE(e,f,t,snd_incr,snd_decr) GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr)
-#define POSTGIVE_VALUE_ROT(e,f,t,rotfield,rottime,regenfield,regentime,snd_incr,snd_decr) GiveRot((e), save_##f, (e).f, rotfield, rottime, regenfield, regentime); GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr)
-
-float GiveItems(entity e, float beginarg, float endarg);
-#endif
diff --git a/qcsrc/server/t_quake.qc b/qcsrc/server/t_quake.qc
index 219a6ae23..ab49c6db5 100644
--- a/qcsrc/server/t_quake.qc
+++ b/qcsrc/server/t_quake.qc
@@ -3,7 +3,7 @@
 //***********************
 void spawnfunc_weapon_nailgun (void) {spawnfunc_weapon_electro();}
 void spawnfunc_weapon_supernailgun (void) {spawnfunc_weapon_hagar();}
-void spawnfunc_weapon_supershotgun (void) {spawnfunc_weapon_machinegun();}
+void spawnfunc_weapon_supershotgun (void) {spawnfunc_weapon_uzi();}
 
 void spawnfunc_item_spikes (void) {spawnfunc_item_bullets();}
 //void spawnfunc_item_armor1 (void) {spawnfunc_item_armor_medium;}  // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
diff --git a/qcsrc/server/t_quake3.qc b/qcsrc/server/t_quake3.qc
index 30f1e8f8d..86a87c043 100644
--- a/qcsrc/server/t_quake3.qc
+++ b/qcsrc/server/t_quake3.qc
@@ -8,12 +8,13 @@
 void spawnfunc_ammo_shells()         { spawnfunc_item_shells();         }
 
 // MG -> MG
+void spawnfunc_weapon_machinegun()   { spawnfunc_weapon_uzi();          }
 void spawnfunc_ammo_bullets()        { spawnfunc_item_bullets();        }
 
 // GL -> Mortar
 void spawnfunc_ammo_grenades()       { spawnfunc_item_rockets();        }
 
-// LG -> Lightning
+// LG -> Electro
 void spawnfunc_weapon_lightning()    { spawnfunc_weapon_electro();      }
 void spawnfunc_ammo_lightning()      { spawnfunc_item_cells();          }
 
@@ -21,13 +22,13 @@ void spawnfunc_ammo_lightning()      { spawnfunc_item_cells();          }
 void spawnfunc_weapon_plasmagun()    { spawnfunc_weapon_hagar();        }
 void spawnfunc_ammo_cells()          { spawnfunc_item_rockets();        }
 
-// Rail -> Vortex
-void spawnfunc_weapon_railgun()      { spawnfunc_weapon_vortex();          }
-void spawnfunc_ammo_slugs()          { spawnfunc_item_plasma();          }
+// Rail -> Nex
+void spawnfunc_weapon_railgun()      { spawnfunc_weapon_nex();          }
+void spawnfunc_ammo_slugs()          { spawnfunc_item_cells();          }
 
 // BFG -> Crylink
 void spawnfunc_weapon_bfg()          { spawnfunc_weapon_crylink();      }
-void spawnfunc_ammo_bfg()            { spawnfunc_item_plasma();          }
+void spawnfunc_ammo_bfg()            { spawnfunc_item_cells();          }
 
 // RL -> RL
 void spawnfunc_ammo_rockets()        { spawnfunc_item_rockets();        }
@@ -71,11 +72,11 @@ void target_give_init()
 	entity targ;
 	for (targ = world; (targ = find(targ, targetname, self.target)); ) {
 		if (targ.classname == "weapon_rocketlauncher") {
-			self.ammo_rockets += targ.count * WEP_CVAR(devastator, ammo);
+			self.ammo_rockets += targ.count * autocvar_g_balance_rocketlauncher_ammo;
 			self.netname = "rocketlauncher";
 		}
 		else if (targ.classname == "weapon_plasmagun") {
-			self.ammo_rockets += targ.count * WEP_CVAR_PRI(hagar, ammo); // WEAPONTODO
+			self.ammo_rockets += targ.count * autocvar_g_balance_hagar_primary_ammo;
 			if(self.netname == "")
 				self.netname = "hagar";
 			else
@@ -89,7 +90,7 @@ void target_give_init()
 				self.netname = strcat(self.netname, " crylink");
 		}
 		else if (targ.classname == "weapon_grenadelauncher") {
-			self.ammo_rockets += targ.count * autocvar_g_balance_mortar_primary_ammo; // WEAPONTODO
+			self.ammo_rockets += targ.count * autocvar_g_balance_grenadelauncher_primary_ammo;
 			if(self.netname == "")
 				self.netname = "grenadelauncher";
 			else
diff --git a/qcsrc/server/t_teleporters.qc b/qcsrc/server/t_teleporters.qc
index 543c1cf0b..6e7c35b6a 100644
--- a/qcsrc/server/t_teleporters.qc
+++ b/qcsrc/server/t_teleporters.qc
@@ -80,7 +80,6 @@ void spawn_tdeath(vector v0, entity e, vector v)
 #define TELEPORT_NORMAL 1 // play sounds/effects etc
 #define TELEPORT_SIMPLE 2 // only do teleport, nothing special
 
-void Reset_ArcBeam(entity player, vector forward);
 void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angles, vector to_velocity, vector telefragmin, vector telefragmax, float tflags)
 {
 	entity telefragger;
@@ -118,8 +117,6 @@ void TeleportPlayer(entity teleporter, entity player, vector to, vector to_angle
 	player.velocity = to_velocity;
 	BITXOR_ASSIGN(player.effects, EF_TELEPORT_BIT);
 
-	makevectors(player.angles);
-	Reset_ArcBeam(player, v_forward);
 	UpdateCSQCProjectileAfterTeleport(player);
 
 	if(IS_PLAYER(player))
@@ -340,8 +337,6 @@ void spawnfunc_trigger_teleport (void)
 
 void WarpZone_PostTeleportPlayer_Callback(entity pl)
 {
-	makevectors(pl.angles);
-	Reset_ArcBeam(pl, v_forward);
 	UpdateCSQCProjectileAfterTeleport(pl);
 	{
 		entity oldself = self;
diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc
index d7d833a64..ee91a9dcc 100644
--- a/qcsrc/server/teamplay.qc
+++ b/qcsrc/server/teamplay.qc
@@ -291,7 +291,7 @@ string getwelcomemessage(void)
 		else
 			modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena");
 	}
-	if(cvar("g_balance_blaster_weaponstart") == 0)
+	if(autocvar_g_start_weapon_laser == 0)
 		modifications = strcat(modifications, ", No start weapons");
 	if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
 		modifications = strcat(modifications, ", Low gravity");
diff --git a/qcsrc/server/tturrets/system/system_main.qc b/qcsrc/server/tturrets/system/system_main.qc
index d56a81bbf..d35573b54 100644
--- a/qcsrc/server/tturrets/system/system_main.qc
+++ b/qcsrc/server/tturrets/system/system_main.qc
@@ -148,11 +148,11 @@ void turret_projectile_explode()
     self.event_damage = func_null;
 #ifdef TURRET_DEBUG
     float d;
-    d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+    d = RadiusDamage (self, self.owner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
     self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
     self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
 #else
-    RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+    RadiusDamage (self, self.realowner, self.owner.shot_dmg, 0, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
 #endif
     remove(self);
 }
diff --git a/qcsrc/server/tturrets/units/unit_ewheel.qc b/qcsrc/server/tturrets/units/unit_ewheel.qc
index e8e677ac8..b98388984 100644
--- a/qcsrc/server/tturrets/units/unit_ewheel.qc
+++ b/qcsrc/server/tturrets/units/unit_ewheel.qc
@@ -13,7 +13,7 @@ void ewheel_attack()
     {
         turret_do_updates(self);
 
-        _mis = turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_BLASTER, TRUE, TRUE); // WEAPONTODO: this is not a projectile made by the blaster, add separate effect for it
+        _mis = turret_projectile("weapons/lasergun_fire.wav", 1, 0, DEATH_TURRET_EWHEEL, PROJECTILE_LASER, TRUE, TRUE);
         _mis.missile_flags = MIF_SPLASH;
 
         pointparticles(particleeffectnum("laser_muzzleflash"), self.tur_shotorg, self.tur_shotdir_updated * 1000, 1);
diff --git a/qcsrc/server/tturrets/units/unit_flac.qc b/qcsrc/server/tturrets/units/unit_flac.qc
index 3c9e55863..8a01a9752 100644
--- a/qcsrc/server/tturrets/units/unit_flac.qc
+++ b/qcsrc/server/tturrets/units/unit_flac.qc
@@ -10,11 +10,11 @@ void turret_flac_projectile_think_explode()
 
 #ifdef TURRET_DEBUG
     float d;
-    d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+    d = RadiusDamage (self, self.owner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
     self.owner.tur_dbg_dmg_t_h = self.owner.tur_dbg_dmg_t_h + d;
     self.owner.tur_dbg_dmg_t_f = self.owner.tur_dbg_dmg_t_f + self.owner.shot_dmg;
 #else
-    RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, world, self.owner.shot_force, self.totalfrags, world);
+    RadiusDamage (self, self.realowner, self.owner.shot_dmg, self.owner.shot_dmg, self.owner.shot_radius, self, self.owner.shot_force, self.totalfrags, world);
 #endif
     remove(self);
 }
diff --git a/qcsrc/server/tturrets/units/unit_machinegun.qc b/qcsrc/server/tturrets/units/unit_machinegun.qc
index d235dfb32..eccc37f03 100644
--- a/qcsrc/server/tturrets/units/unit_machinegun.qc
+++ b/qcsrc/server/tturrets/units/unit_machinegun.qc
@@ -7,7 +7,7 @@ void turret_machinegun_attack()
 {
     fireBullet (self.tur_shotorg, self.tur_shotdir_updated,self.shot_spread, 0, self.shot_dmg, self.shot_force, DEATH_TURRET_MACHINEGUN, 0);
 
-    W_MachineGun_MuzzleFlash(); // WEAPONTODO
+    UziFlash();
     setattachment(self.muzzle_flash, self.tur_head, "tag_fire");
 }
 
diff --git a/qcsrc/server/tturrets/units/unit_walker.qc b/qcsrc/server/tturrets/units/unit_walker.qc
index a91daa190..2eeb08b8f 100644
--- a/qcsrc/server/tturrets/units/unit_walker.qc
+++ b/qcsrc/server/tturrets/units/unit_walker.qc
@@ -51,8 +51,7 @@ void walker_setnoanim()
 }
 void walker_rocket_explode()
 {
-    RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, world, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALK_ROCKET, world);
-
+    RadiusDamage (self, self.owner, autocvar_g_turrets_unit_walker_std_rocket_dmg, 0, autocvar_g_turrets_unit_walker_std_rocket_radius, self, autocvar_g_turrets_unit_walker_std_rocket_force, DEATH_TURRET_WALK_ROCKET, world);
     remove (self);
 }
 
diff --git a/qcsrc/server/vehicles/bumblebee.qc b/qcsrc/server/vehicles/bumblebee.qc
index 8b8d308f9..657d22705 100644
--- a/qcsrc/server/vehicles/bumblebee.qc
+++ b/qcsrc/server/vehicles/bumblebee.qc
@@ -702,7 +702,7 @@ void bumb_blowup()
 {
 	RadiusDamage(self, self.enemy, autocvar_g_vehicle_bumblebee_blowup_coredamage,
 				 autocvar_g_vehicle_bumblebee_blowup_edgedamage,
-				 autocvar_g_vehicle_bumblebee_blowup_radius, self, world,
+				 autocvar_g_vehicle_bumblebee_blowup_radius, self,
 				 autocvar_g_vehicle_bumblebee_blowup_forceintensity,
 				 DEATH_VH_BUMB_DEATH, world);
 
@@ -787,6 +787,7 @@ void bumb_die()
 	self.nextthink 		= 0;
 
 	setorigin(self, self.pos1);
+
 }
 
 void bumb_impact()
diff --git a/qcsrc/server/vehicles/racer.qc b/qcsrc/server/vehicles/racer.qc
index fc9cee865..f009723b7 100644
--- a/qcsrc/server/vehicles/racer.qc
+++ b/qcsrc/server/vehicles/racer.qc
@@ -539,7 +539,7 @@ void racer_blowup()
 
     RadiusDamage (self, self.enemy, autocvar_g_vehicle_racer_blowup_coredamage,
 					autocvar_g_vehicle_racer_blowup_edgedamage,
-					autocvar_g_vehicle_racer_blowup_radius, world, world,
+					autocvar_g_vehicle_racer_blowup_radius, world,
 					autocvar_g_vehicle_racer_blowup_forceintensity,
 					DEATH_VH_WAKI_DEATH, world);
 
diff --git a/qcsrc/server/vehicles/raptor.qc b/qcsrc/server/vehicles/raptor.qc
index 53e4d35f7..a6ef52649 100644
--- a/qcsrc/server/vehicles/raptor.qc
+++ b/qcsrc/server/vehicles/raptor.qc
@@ -97,7 +97,7 @@ void raptor_bomblet_boom()
 {
     RadiusDamage (self, self.realowner, autocvar_g_vehicle_raptor_bomblet_damage,
                                     autocvar_g_vehicle_raptor_bomblet_edgedamage,
-                                    autocvar_g_vehicle_raptor_bomblet_radius, world, world,
+                                    autocvar_g_vehicle_raptor_bomblet_radius, world,
                                     autocvar_g_vehicle_raptor_bomblet_force, DEATH_VH_RAPT_BOMB, world);
     remove(self);
 }
@@ -695,10 +695,9 @@ void raptor_blowup()
 {
     self.deadflag    = DEAD_DEAD;
     self.vehicle_exit(VHEF_NORMAL);
-
 	RadiusDamage(self, self.enemy, autocvar_g_vehicle_raptor_blowup_coredamage,
 				autocvar_g_vehicle_raptor_blowup_edgedamage,
-				autocvar_g_vehicle_raptor_blowup_radius, world, world,
+				autocvar_g_vehicle_raptor_blowup_radius, world,
 				autocvar_g_vehicle_raptor_blowup_forceintensity, DEATH_VH_RAPT_DEATH, world);
 
     self.alpha          = -1;
diff --git a/qcsrc/server/vehicles/spiderbot.qc b/qcsrc/server/vehicles/spiderbot.qc
index d78ae30a2..1085a904e 100644
--- a/qcsrc/server/vehicles/spiderbot.qc
+++ b/qcsrc/server/vehicles/spiderbot.qc
@@ -725,7 +725,7 @@ void spiderbot_blowup()
 
 	RadiusDamage(self, self.enemy, autocvar_g_vehicle_spiderbot_blowup_coredamage,
 				autocvar_g_vehicle_spiderbot_blowup_edgedamage,
-				autocvar_g_vehicle_spiderbot_blowup_radius, world, world,
+				autocvar_g_vehicle_spiderbot_blowup_radius, world,
 				autocvar_g_vehicle_spiderbot_blowup_forceintensity, DEATH_VH_SPID_DEATH, world);
 
     self.alpha = self.tur_head.alpha = self.gun1.alpha = self.gun2.alpha = -1;
diff --git a/qcsrc/server/vehicles/vehicles.qc b/qcsrc/server/vehicles/vehicles.qc
index 898274f09..2ee34b928 100644
--- a/qcsrc/server/vehicles/vehicles.qc
+++ b/qcsrc/server/vehicles/vehicles.qc
@@ -3,10 +3,10 @@ float autocvar_g_vehicles_crush_force;
 float autocvar_g_vehicles_delayspawn;
 float autocvar_g_vehicles_delayspawn_jitter;
 
-var float autocvar_g_vehicles_vortex_damagerate = 0.5;
-var float autocvar_g_vehicles_machinegun_damagerate = 0.5;
+var float autocvar_g_vehicles_nex_damagerate = 0.5;
+var float autocvar_g_vehicles_uzi_damagerate = 0.5;
 var float autocvar_g_vehicles_rifle_damagerate = 0.75;
-var float autocvar_g_vehicles_vaporizer_damagerate = 0.001;
+var float autocvar_g_vehicles_minstanex_damagerate = 0.001;
 var float autocvar_g_vehicles_tag_damagerate = 5;
 
 float autocvar_g_vehicles;
@@ -397,7 +397,7 @@ void vehicles_projectile_explode()
 	PROJECTILE_TOUCH;
 
 	self.event_damage = func_null;
-    RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, world, self.shot_force, self.totalfrags, other);
+    RadiusDamage (self, self.realowner, self.shot_dmg, 0, self.shot_radius, self, self.shot_force, self.totalfrags, other);
 
     remove (self);
 }
@@ -908,18 +908,17 @@ void vehicles_damage(entity inflictor, entity attacker, float damage, float deat
 {
     self.dmg_time = time;
 
-	// WEAPONTODO
-    if(DEATH_ISWEAPON(deathtype, WEP_VORTEX))
-        damage *= autocvar_g_vehicles_vortex_damagerate;
+    if(DEATH_ISWEAPON(deathtype, WEP_NEX))
+        damage *= autocvar_g_vehicles_nex_damagerate;
 
-    if(DEATH_ISWEAPON(deathtype, WEP_MACHINEGUN))
-        damage *= autocvar_g_vehicles_machinegun_damagerate;
+    if(DEATH_ISWEAPON(deathtype, WEP_UZI))
+        damage *= autocvar_g_vehicles_uzi_damagerate;
 
     if(DEATH_ISWEAPON(deathtype, WEP_RIFLE))
         damage *= autocvar_g_vehicles_rifle_damagerate;
 
-    if(DEATH_ISWEAPON(deathtype, WEP_VAPORIZER))
-        damage *= autocvar_g_vehicles_vaporizer_damagerate;
+    if(DEATH_ISWEAPON(deathtype, WEP_MINSTANEX))
+        damage *= autocvar_g_vehicles_minstanex_damagerate;
 
     if(DEATH_ISWEAPON(deathtype, WEP_SEEKER))
         damage *= autocvar_g_vehicles_tag_damagerate;
diff --git a/qcsrc/server/w_all.qc b/qcsrc/server/w_all.qc
new file mode 100644
index 000000000..ac4ef47ed
--- /dev/null
+++ b/qcsrc/server/w_all.qc
@@ -0,0 +1,21 @@
+// ONLY EVER ADD NEW WEAPONS AT THE END. IF YOU REMOVE ONE, PUT THE LAST ONE ON
+// ITS PLACE. THIS IS TO AVOID UNNECESSARY RENUMBERING OF WEAPON IMPULSES.
+// IF YOU DISREGARD THIS NOTICE, I'LL KILL YOU WITH THE @!#%'N TUBA
+#include "w_laser.qc"
+#include "w_shotgun.qc"
+#include "w_uzi.qc"
+#include "w_grenadelauncher.qc"
+#include "w_minelayer.qc"
+#include "w_electro.qc"
+#include "w_crylink.qc"
+#include "w_nex.qc"
+#include "w_hagar.qc"
+#include "w_rocketlauncher.qc"
+#include "w_porto.qc"
+#include "w_minstanex.qc"
+#include "w_hook.qc"
+#include "w_hlac.qc"
+#include "w_tuba.qc"
+#include "w_rifle.qc"
+#include "w_fireball.qc"
+#include "w_seeker.qc"
diff --git a/qcsrc/server/w_common.qc b/qcsrc/server/w_common.qc
new file mode 100644
index 000000000..a7ae4d326
--- /dev/null
+++ b/qcsrc/server/w_common.qc
@@ -0,0 +1,376 @@
+
+void W_GiveWeapon (entity e, float wep)
+{
+	entity oldself;
+
+	if (!wep)
+		return;
+
+	e.weapons |= WepSet_FromWeapon(wep);
+
+	oldself = self;
+	self = e;
+
+	if(IS_PLAYER(other))
+		{ Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_WEAPON_GOT, wep); }
+
+	self = oldself;
+}
+
+.float railgundistance;
+.vector railgunforce;
+void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype)
+{
+	vector hitloc, force, endpoint, dir;
+	entity ent, endent;
+	float endq3surfaceflags;
+	float totaldmg;
+	entity o;
+
+	float length;
+	vector beampos;
+	string snd;
+	entity pseudoprojectile;
+	float f, ffs;
+
+	pseudoprojectile = world;
+
+	dir = normalize(end - start);
+	length = vlen(end - start);
+	force = dir * bforce;
+
+	// go a little bit into the wall because we need to hit this wall later
+	end = end + dir;
+
+	totaldmg = 0;
+
+	// trace multiple times until we hit a wall, each obstacle will be made
+	// non-solid so we can hit the next, while doing this we spawn effects and
+	// note down which entities were hit so we can damage them later
+	o = self;
+	while (1)
+	{
+		if(self.antilag_debug)
+			WarpZone_traceline_antilag (self, start, end, FALSE, o, self.antilag_debug);
+		else
+			WarpZone_traceline_antilag (self, start, end, FALSE, o, ANTILAG_LATENCY(self));
+		if(o && WarpZone_trace_firstzone)
+		{
+			o = world;
+			continue;
+		}
+
+		if(trace_ent.solid == SOLID_BSP || trace_ent.solid == SOLID_SLIDEBOX)
+			Damage_DamageInfo(trace_endpos, bdamage, 0, 0, force, deathtype, trace_ent.species, self);
+
+		// if it is world we can't hurt it so stop now
+		if (trace_ent == world || trace_fraction == 1)
+			break;
+
+		// make the entity non-solid so we can hit the next one
+		trace_ent.railgunhit = TRUE;
+		trace_ent.railgunhitloc = end;
+		trace_ent.railgunhitsolidbackup = trace_ent.solid;
+		trace_ent.railgundistance = vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - start);
+		trace_ent.railgunforce = WarpZone_TransformVelocity(WarpZone_trace_transform, force);
+
+		// stop if this is a wall
+		if (trace_ent.solid == SOLID_BSP)
+			break;
+
+		// make the entity non-solid
+		trace_ent.solid = SOLID_NOT;
+	}
+
+	endpoint = trace_endpos;
+	endent = trace_ent;
+	endq3surfaceflags = trace_dphitq3surfaceflags;
+
+	// find all the entities the railgun hit and restore their solid state
+	ent = findfloat(world, railgunhit, TRUE);
+	while (ent)
+	{
+		// restore their solid type
+		ent.solid = ent.railgunhitsolidbackup;
+		ent = findfloat(ent, railgunhit, TRUE);
+	}
+
+	// spawn a temporary explosion entity for RadiusDamage calls
+	//explosion = spawn();
+
+	// Find all non-hit players the beam passed close by
+	if(deathtype == WEP_MINSTANEX || deathtype == WEP_NEX)
+	{
+		FOR_EACH_REALCLIENT(msg_entity)
+		if(msg_entity != self)
+		if(!msg_entity.railgunhit)
+		if(!(IS_SPEC(msg_entity) && msg_entity.enemy == self)) // we use realclient, so spectators can hear the whoosh too
+		{
+			// nearest point on the beam
+			beampos = start + dir * bound(0, (msg_entity.origin - start) * dir, length);
+
+			f = bound(0, 1 - vlen(beampos - msg_entity.origin) / 512, 1);
+			if(f <= 0)
+				continue;
+
+			snd = strcat("weapons/nexwhoosh", ftos(floor(random() * 3) + 1), ".wav");
+
+			if(!pseudoprojectile)
+				pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume
+			soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, snd, VOL_BASE * f, ATTEN_NONE);
+		}
+
+		if(pseudoprojectile)
+			remove(pseudoprojectile);
+	}
+
+	// find all the entities the railgun hit and hurt them
+	ent = findfloat(world, railgunhit, TRUE);
+	while (ent)
+	{
+		// get the details we need to call the damage function
+		hitloc = ent.railgunhitloc;
+
+		f = ExponentialFalloff(mindist, maxdist, halflifedist, ent.railgundistance);
+		ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, ent.railgundistance);
+
+		if(accuracy_isgooddamage(self.realowner, ent))
+			totaldmg += bdamage * f;
+
+		// apply the damage
+		if (ent.takedamage)
+			Damage (ent, self, self, bdamage * f, deathtype, hitloc, ent.railgunforce * ffs);
+
+		// create a small explosion to throw gibs around (if applicable)
+		//setorigin (explosion, hitloc);
+		//RadiusDamage (explosion, self, 10, 0, 50, world, 300, deathtype);
+
+		ent.railgunhitloc = '0 0 0';
+		ent.railgunhitsolidbackup = SOLID_NOT;
+		ent.railgunhit = FALSE;
+		ent.railgundistance = 0;
+
+		// advance to the next entity
+		ent = findfloat(ent, railgunhit, TRUE);
+	}
+
+	// calculate hits and fired shots for hitscan
+	accuracy_add(self, self.weapon, 0, min(bdamage, totaldmg));
+
+	trace_endpos = endpoint;
+	trace_ent = endent;
+	trace_dphitq3surfaceflags = endq3surfaceflags;
+}
+
+float fireBullet_trace_callback_eff;
+entity fireBullet_last_hit;
+void fireBullet_trace_callback(vector start, vector hit, vector end)
+{
+	if(vlen(hit - start) > 16)
+		trailparticles(world, fireBullet_trace_callback_eff, start, hit);
+	WarpZone_trace_forent = world;
+	fireBullet_last_hit = world;
+}
+
+void fireBullet(vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, float tracereffects)
+{
+	// TODO antilag takeback
+	vector  end;
+
+	dir = normalize(dir + randomvec() * spread);
+	end = start + dir * MAX_SHOT_DISTANCE;
+
+	entity pl;
+	fireBullet_last_hit = world;
+	float solid_penetration_left = 1;
+	float total_damage = 0;
+
+	if(tracereffects & EF_RED)
+		fireBullet_trace_callback_eff = particleeffectnum("tr_rifle");
+	else if(tracereffects & EF_BLUE)
+		fireBullet_trace_callback_eff = particleeffectnum("tr_rifle_weak");
+	else
+		fireBullet_trace_callback_eff = particleeffectnum("tr_bullet");
+
+	float lag = ANTILAG_LATENCY(self);
+	if(lag < 0.001)
+		lag = 0;
+	if (!IS_REAL_CLIENT(self))
+		lag = 0;
+	if(autocvar_g_antilag == 0 || self.cvar_cl_noantilag)
+		lag = 0; // only do hitscan, but no antilag
+	if(lag)
+	{
+		FOR_EACH_PLAYER(pl)
+			if(pl != self)
+				antilag_takeback(pl, time - lag);
+		FOR_EACH_MONSTER(pl)
+			antilag_takeback(pl, time - lag);
+	}
+
+	WarpZone_trace_forent = self;
+
+	for (;;)
+	{
+		// TODO also show effect while tracing
+		WarpZone_TraceBox_ThroughZone(start, '0 0 0', '0 0 0', end, FALSE, WarpZone_trace_forent, world, fireBullet_trace_callback);
+		dir = WarpZone_TransformVelocity(WarpZone_trace_transform, dir);
+		end = WarpZone_TransformOrigin(WarpZone_trace_transform, end);
+		start = trace_endpos;
+		entity hit = trace_ent;
+
+		// When hitting sky, stop.
+		if (pointcontents(start) == CONTENT_SKY)
+			break;
+
+		if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+			break;
+
+		// if we hit "weapclip", bail out
+		//
+		// rationale of this check:
+		//
+		// any shader that is solid, nodraw AND trans is meant to clip weapon
+		// shots and players, but has no other effect!
+		//
+		// if it is not trans, it is caulk and should not have this side effect
+		//
+		// matching shaders:
+		//   common/weapclip (intended)
+		//   common/noimpact (is supposed to eat projectiles, but is erased anyway)
+		float is_weapclip = 0;
+		if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODRAW)
+		if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NONSOLID))
+		if (!(trace_dphitcontents & DPCONTENTS_OPAQUE))
+			is_weapclip = 1;
+
+		if(!hit || hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX)
+			Damage_DamageInfo(start, damage * solid_penetration_left, 0, 0, max(1, force) * dir * solid_penetration_left, dtype, hit.species, self);
+
+		if (hit && hit != WarpZone_trace_forent && hit != fireBullet_last_hit)  // Avoid self-damage (except after going through a warp); avoid hitting the same entity twice (engine bug).
+		{
+			fireBullet_last_hit = hit;
+			yoda = 0;
+			float g = accuracy_isgooddamage(self, hit);
+			Damage(hit, self, self, damage * solid_penetration_left, dtype, start, force * dir * solid_penetration_left);
+			// calculate hits for ballistic weapons
+			if(g)
+			{
+				// do not exceed 100%
+				float added_damage = min(damage - total_damage, damage * solid_penetration_left);
+				total_damage += damage * solid_penetration_left;
+				accuracy_add(self, self.weapon, 0, added_damage);
+			}
+		}
+
+		if (is_weapclip)
+			break;
+
+		// go through solid!
+		// outside the world? forget it
+		if(start_x > world.maxs_x || start_y > world.maxs_y || start_z > world.maxs_z || start_x < world.mins_x || start_y < world.mins_y || start_z < world.mins_z)
+			break;
+
+		float maxdist;
+		if(max_solid_penetration < 0)
+			break;
+		else if(hit.ballistics_density < -1)
+			break; // -2: no solid penetration, ever
+		else if(hit.ballistics_density < 0)
+			maxdist = vlen(hit.maxs - hit.mins) + 1; // -1: infinite travel distance
+		else if(hit.ballistics_density == 0)
+			maxdist = max_solid_penetration * solid_penetration_left;
+		else
+			maxdist = max_solid_penetration * solid_penetration_left * hit.ballistics_density;
+
+		if(maxdist <= autocvar_g_ballistics_mindistance)
+			break;
+
+		// move the entity along its velocity until it's out of solid, then let it resume
+		// The previously hit entity is ignored here!
+		traceline_inverted (start, start + dir * maxdist, MOVE_NORMAL, WarpZone_trace_forent, TRUE, hit);
+		if(trace_fraction == 1) // 1: we never got out of solid
+			break;
+
+		float dist_taken = max(autocvar_g_ballistics_mindistance, vlen(trace_endpos - start));
+		solid_penetration_left *= (dist_taken / maxdist);
+
+		// Only show effect when going through a player (invisible otherwise)
+		if (hit && (hit.solid != SOLID_BSP))
+			if(vlen(trace_endpos - start) > 4)
+				trailparticles(self, fireBullet_trace_callback_eff, start, trace_endpos);
+
+		start = trace_endpos;
+
+		if(hit.solid == SOLID_BSP)
+			Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -solid_penetration_left, dtype, 0, self);
+	}
+
+	if(lag)
+	{
+		FOR_EACH_PLAYER(pl)
+			if(pl != self)
+				antilag_restore(pl);
+		FOR_EACH_MONSTER(pl)
+			antilag_restore(pl);
+	}
+}
+
+float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception)
+{
+	float is_from_contents = (deathtype == DEATH_SLIME || deathtype == DEATH_LAVA);
+	float is_from_owner = (inflictor == projowner);
+	float is_from_exception = (exception != -1);
+
+	//dprint(strcat("W_CheckProjectileDamage: from_contents ", ftos(is_from_contents), " : from_owner ", ftos(is_from_owner), " : exception ", strcat(ftos(is_from_exception), " (", ftos(exception), "). \n")));
+
+	if(autocvar_g_projectiles_damage <= -2)
+	{
+		return FALSE; // no damage to projectiles at all, not even with the exceptions
+	}
+	else if(autocvar_g_projectiles_damage == -1)
+	{
+		if(is_from_exception)
+			return (exception); // if exception is detected, allow it to override
+		else
+			return FALSE; // otherwise, no other damage is allowed
+	}
+	else if(autocvar_g_projectiles_damage == 0)
+	{
+		if(is_from_exception)
+			return (exception); // if exception is detected, allow it to override
+		else if (!is_from_contents)
+			return FALSE; // otherwise, only allow damage from contents
+	}
+	else if(autocvar_g_projectiles_damage == 1)
+	{
+		if(is_from_exception)
+			return (exception); // if exception is detected, allow it to override
+		else if (!(is_from_contents || is_from_owner))
+			return FALSE; // otherwise, only allow self damage and damage from contents
+	}
+	else if(autocvar_g_projectiles_damage == 2) // allow any damage, but override for exceptions
+	{
+		if(is_from_exception)
+			return (exception); // if exception is detected, allow it to override
+	}
+
+	return TRUE; // if none of these return, then allow damage anyway.
+}
+
+void W_PrepareExplosionByDamage(entity attacker, void() explode)
+{
+	self.takedamage = DAMAGE_NO;
+	self.event_damage = func_null;
+
+	if(IS_CLIENT(attacker) && !autocvar_g_projectiles_keep_owner)
+	{
+		self.owner = attacker;
+		self.realowner = attacker;
+	}
+
+	// do not explode NOW but in the NEXT FRAME!
+	// because recursive calls to RadiusDamage are not allowed
+	self.nextthink = time;
+	self.think = explode;
+}
diff --git a/qcsrc/server/w_crylink.qc b/qcsrc/server/w_crylink.qc
new file mode 100644
index 000000000..f7ad7583d
--- /dev/null
+++ b/qcsrc/server/w_crylink.qc
@@ -0,0 +1,727 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ CRYLINK,
+/* function  */ w_crylink,
+/* ammotype  */ IT_CELLS,
+/* impulse   */ 6,
+/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
+/* rating    */ BOT_PICKUP_RATING_MID,
+/* model     */ "crylink",
+/* shortname */ "crylink",
+/* fullname  */ _("Crylink")
+);
+#else
+#ifdef SVQC
+.float gravity;
+.float crylink_waitrelease;
+.entity crylink_lastgroup;
+
+.entity queuenext;
+.entity queueprev;
+
+void W_Crylink_CheckLinks(entity e)
+{
+	float i;
+	entity p;
+
+	if(e == world)
+		error("W_Crylink_CheckLinks: entity is world");
+	if(e.classname != "spike" || wasfreed(e))
+		error(sprintf("W_Crylink_CheckLinks: entity is not a spike but a %s (freed: %d)", e.classname, wasfreed(e)));
+
+	p = e;
+	for(i = 0; i < 1000; ++i)
+	{
+		if(p.queuenext.queueprev != p || p.queueprev.queuenext != p)
+			error("W_Crylink_CheckLinks: queue is inconsistent");
+		p = p.queuenext;
+		if(p == e)
+			break;
+	}
+	if(i >= 1000)
+		error("W_Crylink_CheckLinks: infinite chain");
+}
+
+void W_Crylink_Dequeue_Raw(entity own, entity prev, entity me, entity next)
+{
+	W_Crylink_CheckLinks(next);
+	if(me == own.crylink_lastgroup)
+		own.crylink_lastgroup = ((me == next) ? world : next);
+	prev.queuenext = next;
+	next.queueprev = prev;
+	me.classname = "spike_oktoremove";
+	if(me != next)
+		W_Crylink_CheckLinks(next);
+}
+
+void W_Crylink_Dequeue(entity e)
+{
+	W_Crylink_Dequeue_Raw(e.realowner, e.queueprev, e, e.queuenext);
+}
+
+void W_Crylink_Reset(void)
+{
+	W_Crylink_Dequeue(self);
+	remove(self);
+}
+
+// force projectile to explode
+void W_Crylink_LinkExplode (entity e, entity e2)
+{
+	float a;
+
+	if(e == e2)
+		return;
+
+	a = bound(0, 1 - (time - e.fade_time) * e.fade_rate, 1);
+
+	if(e == e.realowner.crylink_lastgroup)
+		e.realowner.crylink_lastgroup = world;
+
+	if(e.projectiledeathtype & HITTYPE_SECONDARY)
+		RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_damage * a, autocvar_g_balance_crylink_secondary_edgedamage * a, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * a, e.projectiledeathtype, other);
+	else
+		RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_damage * a, autocvar_g_balance_crylink_primary_edgedamage * a, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * a, e.projectiledeathtype, other);
+
+	W_Crylink_LinkExplode(e.queuenext, e2);
+
+	e.classname = "spike_oktoremove";
+	remove (e);
+}
+
+// adjust towards center
+// returns the origin where they will meet... and the time till the meeting is
+// stored in w_crylink_linkjoin_time.
+// could possibly network this origin and time, and display a special particle
+// effect when projectiles meet there :P
+// jspeed: joining speed (calculate this as join spread * initial speed)
+float w_crylink_linkjoin_time;
+vector W_Crylink_LinkJoin(entity e, float jspeed)
+{
+	vector avg_origin, avg_velocity;
+	vector targ_origin;
+	float avg_dist, n;
+	entity p;
+
+	// FIXME remove this debug code
+	W_Crylink_CheckLinks(e);
+
+	w_crylink_linkjoin_time = 0;
+
+	avg_origin = e.origin;
+	avg_velocity = e.velocity;
+	n = 1;
+	for(p = e; (p = p.queuenext) != e; )
+	{
+		avg_origin += WarpZone_RefSys_TransformOrigin(p, e, p.origin);
+		avg_velocity += WarpZone_RefSys_TransformVelocity(p, e, p.velocity);
+		++n;
+	}
+	avg_origin *= (1.0 / n);
+	avg_velocity *= (1.0 / n);
+
+	if(n < 2)
+		return avg_origin; // nothing to do
+
+	// yes, mathematically we can do this in ONE step, but beware of 32bit floats...
+	avg_dist = pow(vlen(e.origin - avg_origin), 2);
+	for(p = e; (p = p.queuenext) != e; )
+		avg_dist += pow(vlen(WarpZone_RefSys_TransformOrigin(p, e, p.origin) - avg_origin), 2);
+	avg_dist *= (1.0 / n);
+	avg_dist = sqrt(avg_dist);
+
+	if(avg_dist == 0)
+		return avg_origin; // no change needed
+
+	if(jspeed == 0)
+	{
+		e.velocity = avg_velocity;
+		UpdateCSQCProjectile(e);
+		for(p = e; (p = p.queuenext) != e; )
+		{
+			p.velocity = WarpZone_RefSys_TransformVelocity(e, p, avg_velocity);
+			UpdateCSQCProjectile(p);
+		}
+		targ_origin = avg_origin + 1000000000 * normalize(avg_velocity); // HUUUUUUGE
+	}
+	else
+	{
+			w_crylink_linkjoin_time = avg_dist / jspeed;
+		targ_origin = avg_origin + w_crylink_linkjoin_time * avg_velocity;
+
+		e.velocity = (targ_origin - e.origin) * (1.0 / w_crylink_linkjoin_time);
+		UpdateCSQCProjectile(e);
+		for(p = e; (p = p.queuenext) != e; )
+		{
+			p.velocity = WarpZone_RefSys_TransformVelocity(e, p, (targ_origin - WarpZone_RefSys_TransformOrigin(p, e, p.origin)) * (1.0 / w_crylink_linkjoin_time));
+			UpdateCSQCProjectile(p);
+		}
+
+		// analysis:
+		//   jspeed -> +infinity:
+		//      w_crylink_linkjoin_time -> +0
+		//      targ_origin -> avg_origin
+		//      p->velocity -> HUEG towards center
+		//   jspeed -> 0:
+		//      w_crylink_linkjoin_time -> +/- infinity
+		//      targ_origin -> avg_velocity * +/- infinity
+		//      p->velocity -> avg_velocity
+		//   jspeed -> -infinity:
+		//      w_crylink_linkjoin_time -> -0
+		//      targ_origin -> avg_origin
+		//      p->velocity -> HUEG away from center
+	}
+
+	W_Crylink_CheckLinks(e);
+
+	return targ_origin;
+}
+
+void W_Crylink_LinkJoinEffect_Think()
+{
+	// is there at least 2 projectiles very close?
+	entity e, p;
+	float n;
+	e = self.owner.crylink_lastgroup;
+	n = 0;
+	if(e)
+	{
+		if(vlen(e.origin - self.origin) < vlen(e.velocity) * frametime)
+			++n;
+		for(p = e; (p = p.queuenext) != e; )
+		{
+			if(vlen(p.origin - self.origin) < vlen(p.velocity) * frametime)
+				++n;
+		}
+		if(n >= 2)
+		{
+			if(e.projectiledeathtype & HITTYPE_SECONDARY)
+			{
+				if(autocvar_g_balance_crylink_secondary_joinexplode)
+				{
+					n = n / autocvar_g_balance_crylink_secondary_shots;
+					RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_secondary_joinexplode_damage * n,
+									autocvar_g_balance_crylink_secondary_joinexplode_edgedamage * n,
+									autocvar_g_balance_crylink_secondary_joinexplode_radius * n, e.realowner,
+									autocvar_g_balance_crylink_secondary_joinexplode_force * n, e.projectiledeathtype, other);
+
+					pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
+				}
+			}
+			else
+			{
+				if(autocvar_g_balance_crylink_primary_joinexplode)
+				{
+					n = n / autocvar_g_balance_crylink_primary_shots;
+					RadiusDamage (e, e.realowner, autocvar_g_balance_crylink_primary_joinexplode_damage * n,
+									autocvar_g_balance_crylink_primary_joinexplode_edgedamage * n,
+									autocvar_g_balance_crylink_primary_joinexplode_radius * n, e.realowner,
+									autocvar_g_balance_crylink_primary_joinexplode_force * n, e.projectiledeathtype, other);
+
+					pointparticles(particleeffectnum("crylink_joinexplode"), self.origin, '0 0 0', n);
+				}
+			}
+		}
+	}
+	remove(self);
+}
+
+float W_Crylink_Touch_WouldHitFriendly(entity projectile, float rad)
+{
+	entity head = WarpZone_FindRadius((projectile.origin + (projectile.mins + projectile.maxs) * 0.5), rad + MAX_DAMAGEEXTRARADIUS, FALSE);
+	float hit_friendly = 0;
+	float hit_enemy = 0;
+
+	while(head)
+	{
+		if((head.takedamage != DAMAGE_NO) && (head.deadflag == DEAD_NO))
+		{
+			if(SAME_TEAM(head, projectile.realowner))
+				++hit_friendly;
+			else
+				++hit_enemy;
+		}
+
+		head = head.chain;
+	}
+
+	return (hit_enemy ? FALSE : hit_friendly);
+}
+
+// NO bounce protection, as bounces are limited!
+void W_Crylink_Touch (void)
+{
+	float finalhit;
+	float f;
+	PROJECTILE_TOUCH;
+
+	float a;
+	a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1);
+
+	finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO));
+	if(finalhit)
+		f = 1;
+	else
+		f = autocvar_g_balance_crylink_primary_bouncedamagefactor;
+	if(a)
+		f *= a;
+
+	float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_primary_damage * f, autocvar_g_balance_crylink_primary_edgedamage * f, autocvar_g_balance_crylink_primary_radius, world, autocvar_g_balance_crylink_primary_force * f, self.projectiledeathtype, other);
+
+	if(totaldamage && ((autocvar_g_balance_crylink_primary_linkexplode == 2) || ((autocvar_g_balance_crylink_primary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_primary_radius))))
+	{
+		if(self == self.realowner.crylink_lastgroup)
+			self.realowner.crylink_lastgroup = world;
+		W_Crylink_LinkExplode(self.queuenext, self);
+		self.classname = "spike_oktoremove";
+		remove (self);
+		return;
+	}
+	else if(finalhit)
+	{
+		// just unlink
+		W_Crylink_Dequeue(self);
+		remove(self);
+		return;
+	}
+	self.cnt = self.cnt - 1;
+	self.angles = vectoangles(self.velocity);
+	self.owner = world;
+	self.projectiledeathtype |= HITTYPE_BOUNCE;
+	// commented out as it causes a little hitch...
+	//if(proj.cnt == 0)
+	//	CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE);
+}
+
+void W_Crylink_Touch2 (void)
+{
+	float finalhit;
+	float f;
+	PROJECTILE_TOUCH;
+
+	float a;
+	a = bound(0, 1 - (time - self.fade_time) * self.fade_rate, 1);
+
+	finalhit = ((self.cnt <= 0) || (other.takedamage != DAMAGE_NO));
+	if(finalhit)
+		f = 1;
+	else
+		f = autocvar_g_balance_crylink_secondary_bouncedamagefactor;
+	if(a)
+		f *= a;
+
+	float totaldamage = RadiusDamage(self, self.realowner, autocvar_g_balance_crylink_secondary_damage * f, autocvar_g_balance_crylink_secondary_edgedamage * f, autocvar_g_balance_crylink_secondary_radius, world, autocvar_g_balance_crylink_secondary_force * f, self.projectiledeathtype, other);
+
+	if(totaldamage && ((autocvar_g_balance_crylink_secondary_linkexplode == 2) || ((autocvar_g_balance_crylink_secondary_linkexplode == 1) && !W_Crylink_Touch_WouldHitFriendly(self, autocvar_g_balance_crylink_secondary_radius))))
+	{
+		if(self == self.realowner.crylink_lastgroup)
+			self.realowner.crylink_lastgroup = world;
+		W_Crylink_LinkExplode(self.queuenext, self);
+		self.classname = "spike_oktoremove";
+		remove (self);
+		return;
+	}
+	else if(finalhit)
+	{
+		// just unlink
+		W_Crylink_Dequeue(self);
+		remove(self);
+		return;
+	}
+	self.cnt = self.cnt - 1;
+	self.angles = vectoangles(self.velocity);
+	self.owner = world;
+	self.projectiledeathtype |= HITTYPE_BOUNCE;
+	// commented out as it causes a little hitch...
+	//if(proj.cnt == 0)
+	//	CSQCProjectile(proj, TRUE, PROJECTILE_CRYLINK, TRUE);
+}
+
+void W_Crylink_Fadethink (void)
+{
+	W_Crylink_Dequeue(self);
+	remove(self);
+}
+
+void W_Crylink_Attack (void)
+{
+	float counter, shots;
+	entity proj, prevproj, firstproj;
+	vector s;
+	vector forward, right, up;
+	float maxdmg;
+
+	W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_reload_ammo);
+
+	maxdmg = autocvar_g_balance_crylink_primary_damage*autocvar_g_balance_crylink_primary_shots;
+	maxdmg *= 1 + autocvar_g_balance_crylink_primary_bouncedamagefactor * autocvar_g_balance_crylink_primary_bounces;
+	if(autocvar_g_balance_crylink_primary_joinexplode)
+		maxdmg += autocvar_g_balance_crylink_primary_joinexplode_damage;
+
+	W_SetupShot (self, FALSE, 2, "weapons/crylink_fire.wav", CH_WEAPON_A, maxdmg);
+	forward = v_forward;
+	right = v_right;
+	up = v_up;
+
+	shots = autocvar_g_balance_crylink_primary_shots;
+	pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
+	proj = prevproj = firstproj = world;
+	for(counter = 0; counter < shots; ++counter)
+	{
+		proj = spawn ();
+		proj.reset = W_Crylink_Reset;
+		proj.realowner = proj.owner = self;
+		proj.classname = "spike";
+		proj.bot_dodge = TRUE;
+		proj.bot_dodgerating = autocvar_g_balance_crylink_primary_damage;
+		if(shots == 1) {
+			proj.queuenext = proj;
+			proj.queueprev = proj;
+		}
+		else if(counter == 0) { // first projectile, store in firstproj for now
+			firstproj = proj;
+		}
+		else if(counter == shots - 1) { // last projectile, link up with first projectile
+			prevproj.queuenext = proj;
+			firstproj.queueprev = proj;
+			proj.queuenext = firstproj;
+			proj.queueprev = prevproj;
+		}
+		else { // else link up with previous projectile
+			prevproj.queuenext = proj;
+			proj.queueprev = prevproj;
+		}
+
+		prevproj = proj;
+
+		proj.movetype = MOVETYPE_BOUNCEMISSILE;
+		PROJECTILE_MAKETRIGGER(proj);
+		proj.projectiledeathtype = WEP_CRYLINK;
+		//proj.gravity = 0.001;
+
+		setorigin (proj, w_shotorg);
+		setsize(proj, '0 0 0', '0 0 0');
+
+
+		s = '0 0 0';
+		if (counter == 0)
+			s = '0 0 0';
+		else
+		{
+			makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
+			s_y = v_forward_x;
+			s_z = v_forward_y;
+		}
+		s = s * autocvar_g_balance_crylink_primary_spread * g_weaponspreadfactor;
+		W_SetupProjectileVelocityEx(proj, w_shotdir + right * s_y + up * s_z, v_up, autocvar_g_balance_crylink_primary_speed, 0, 0, 0, FALSE);
+		proj.touch = W_Crylink_Touch;
+
+		proj.think = W_Crylink_Fadethink;
+		if(counter == 0)
+		{
+			proj.fade_time = time + autocvar_g_balance_crylink_primary_middle_lifetime;
+			proj.fade_rate = 1 / autocvar_g_balance_crylink_primary_middle_fadetime;
+			proj.nextthink = time + autocvar_g_balance_crylink_primary_middle_lifetime + autocvar_g_balance_crylink_primary_middle_fadetime;
+		}
+		else
+		{
+			proj.fade_time = time + autocvar_g_balance_crylink_primary_other_lifetime;
+			proj.fade_rate = 1 / autocvar_g_balance_crylink_primary_other_fadetime;
+			proj.nextthink = time + autocvar_g_balance_crylink_primary_other_lifetime + autocvar_g_balance_crylink_primary_other_fadetime;
+		}
+		proj.teleport_time = time + autocvar_g_balance_crylink_primary_joindelay;
+		proj.cnt = autocvar_g_balance_crylink_primary_bounces;
+		//proj.scale = 1 + 1 * proj.cnt;
+
+		proj.angles = vectoangles (proj.velocity);
+
+		//proj.glow_size = 20;
+
+		proj.flags = FL_PROJECTILE;
+    proj.missile_flags = MIF_SPLASH;
+
+		CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE);
+
+		other = proj; MUTATOR_CALLHOOK(EditProjectile);
+	}
+	if(autocvar_g_balance_crylink_primary_joinspread != 0)
+	{
+		self.crylink_lastgroup = proj;
+		W_Crylink_CheckLinks(proj);
+		self.crylink_waitrelease = 1;
+	}
+}
+
+void W_Crylink_Attack2 (void)
+{
+	float counter, shots;
+	entity proj, prevproj, firstproj;
+	vector s;
+	vector forward, right, up;
+	float maxdmg;
+
+	W_DecreaseAmmo(ammo_cells, autocvar_g_balance_crylink_secondary_ammo, autocvar_g_balance_crylink_reload_ammo);
+
+	maxdmg = autocvar_g_balance_crylink_secondary_damage*autocvar_g_balance_crylink_secondary_shots;
+	maxdmg *= 1 + autocvar_g_balance_crylink_secondary_bouncedamagefactor * autocvar_g_balance_crylink_secondary_bounces;
+	if(autocvar_g_balance_crylink_secondary_joinexplode)
+		maxdmg += autocvar_g_balance_crylink_secondary_joinexplode_damage;
+
+	W_SetupShot (self, FALSE, 2, "weapons/crylink_fire2.wav", CH_WEAPON_A, maxdmg);
+	forward = v_forward;
+	right = v_right;
+	up = v_up;
+
+	shots = autocvar_g_balance_crylink_secondary_shots;
+	pointparticles(particleeffectnum("crylink_muzzleflash"), w_shotorg, w_shotdir * 1000, shots);
+	proj = prevproj = firstproj = world;
+	for(counter = 0; counter < shots; ++counter)
+	{
+		proj = spawn ();
+		proj.reset = W_Crylink_Reset;
+		proj.realowner = proj.owner = self;
+		proj.classname = "spike";
+		proj.bot_dodge = TRUE;
+		proj.bot_dodgerating = autocvar_g_balance_crylink_secondary_damage;
+		if(shots == 1) {
+			proj.queuenext = proj;
+			proj.queueprev = proj;
+		}
+		else if(counter == 0) { // first projectile, store in firstproj for now
+			firstproj = proj;
+		}
+		else if(counter == shots - 1) { // last projectile, link up with first projectile
+			prevproj.queuenext = proj;
+			firstproj.queueprev = proj;
+			proj.queuenext = firstproj;
+			proj.queueprev = prevproj;
+		}
+		else { // else link up with previous projectile
+			prevproj.queuenext = proj;
+			proj.queueprev = prevproj;
+		}
+
+		prevproj = proj;
+
+		proj.movetype = MOVETYPE_BOUNCEMISSILE;
+		PROJECTILE_MAKETRIGGER(proj);
+		proj.projectiledeathtype = WEP_CRYLINK | HITTYPE_SECONDARY;
+		//proj.gravity = 0.001;
+
+		setorigin (proj, w_shotorg);
+		setsize(proj, '0 0 0', '0 0 0');
+
+		if(autocvar_g_balance_crylink_secondary_spreadtype == 1)
+		{
+			s = '0 0 0';
+			if (counter == 0)
+				s = '0 0 0';
+			else
+			{
+				makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
+				s_y = v_forward_x;
+				s_z = v_forward_y;
+			}
+			s = s * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor;
+			s = w_shotdir + right * s_y + up * s_z;
+		}
+		else
+		{
+			s = (w_shotdir + (((counter + 0.5) / shots) * 2 - 1) * v_right * autocvar_g_balance_crylink_secondary_spread * g_weaponspreadfactor);
+		}
+
+		W_SetupProjectileVelocityEx(proj, s, v_up, autocvar_g_balance_crylink_secondary_speed, 0, 0, 0, FALSE);
+		proj.touch = W_Crylink_Touch2;
+		proj.think = W_Crylink_Fadethink;
+		if(counter == (shots - 1) / 2)
+		{
+			proj.fade_time = time + autocvar_g_balance_crylink_secondary_middle_lifetime;
+			proj.fade_rate = 1 / autocvar_g_balance_crylink_secondary_middle_fadetime;
+			proj.nextthink = time + autocvar_g_balance_crylink_secondary_middle_lifetime + autocvar_g_balance_crylink_secondary_middle_fadetime;
+		}
+		else
+		{
+			proj.fade_time = time + autocvar_g_balance_crylink_secondary_line_lifetime;
+			proj.fade_rate = 1 / autocvar_g_balance_crylink_secondary_line_fadetime;
+			proj.nextthink = time + autocvar_g_balance_crylink_secondary_line_lifetime + autocvar_g_balance_crylink_secondary_line_fadetime;
+		}
+		proj.teleport_time = time + autocvar_g_balance_crylink_secondary_joindelay;
+		proj.cnt = autocvar_g_balance_crylink_secondary_bounces;
+		//proj.scale = 1 + 1 * proj.cnt;
+
+		proj.angles = vectoangles (proj.velocity);
+
+		//proj.glow_size = 20;
+
+		proj.flags = FL_PROJECTILE;
+        proj.missile_flags = MIF_SPLASH;
+
+		CSQCProjectile(proj, TRUE, (proj.cnt ? PROJECTILE_CRYLINK_BOUNCING : PROJECTILE_CRYLINK), TRUE);
+
+		other = proj; MUTATOR_CALLHOOK(EditProjectile);
+	}
+	if(autocvar_g_balance_crylink_secondary_joinspread != 0)
+	{
+		self.crylink_lastgroup = proj;
+		W_Crylink_CheckLinks(proj);
+		self.crylink_waitrelease = 2;
+	}
+}
+
+void spawnfunc_weapon_crylink (void)
+{
+	weapon_defaultspawnfunc(WEP_CRYLINK);
+}
+
+float w_crylink(float req)
+{
+	float ammo_amount;
+	if (req == WR_AIM)
+	{
+		if (random() < 0.10)
+			self.BUTTON_ATCK = bot_aim(autocvar_g_balance_crylink_primary_speed, 0, autocvar_g_balance_crylink_primary_middle_lifetime, FALSE);
+		else
+			self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_crylink_secondary_speed, 0, autocvar_g_balance_crylink_secondary_middle_lifetime, FALSE);
+	}
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_crylink_reload_ammo && self.clip_load < min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo)) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+
+		if (self.BUTTON_ATCK)
+		{
+			if (self.crylink_waitrelease != 1)
+			if (weapon_prepareattack(0, autocvar_g_balance_crylink_primary_refire))
+			{
+				W_Crylink_Attack();
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_crylink_primary_animtime, w_ready);
+			}
+		}
+
+		if(self.BUTTON_ATCK2 && autocvar_g_balance_crylink_secondary)
+		{
+			if (self.crylink_waitrelease != 2)
+			if (weapon_prepareattack(1, autocvar_g_balance_crylink_secondary_refire))
+			{
+				W_Crylink_Attack2();
+				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_crylink_secondary_animtime, w_ready);
+			}
+		}
+
+		if ((self.crylink_waitrelease == 1 && !self.BUTTON_ATCK) || (self.crylink_waitrelease == 2 && !self.BUTTON_ATCK2))
+		{
+			if (!self.crylink_lastgroup || time > self.crylink_lastgroup.teleport_time)
+			{
+				// fired and released now!
+				if(self.crylink_lastgroup)
+				{
+					vector pos;
+					entity linkjoineffect;
+
+					if(self.crylink_waitrelease == 1)
+					{
+						pos = W_Crylink_LinkJoin(self.crylink_lastgroup, autocvar_g_balance_crylink_primary_joinspread * autocvar_g_balance_crylink_primary_speed);
+
+					}
+					else
+					{
+						pos = W_Crylink_LinkJoin(self.crylink_lastgroup, autocvar_g_balance_crylink_secondary_joinspread * autocvar_g_balance_crylink_secondary_speed);
+					}
+
+					linkjoineffect = spawn();
+					linkjoineffect.think = W_Crylink_LinkJoinEffect_Think;
+					linkjoineffect.classname = "linkjoineffect";
+					linkjoineffect.nextthink = time + w_crylink_linkjoin_time;
+					linkjoineffect.owner = self;
+					setorigin(linkjoineffect, pos);
+				}
+				self.crylink_waitrelease = 0;
+				if(!w_crylink(WR_CHECKAMMO1) && !w_crylink(WR_CHECKAMMO2))
+				if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+				{
+					// ran out of ammo!
+					self.cnt = WEP_CRYLINK;
+					self.switchweapon = w_getbestweapon(self);
+				}
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_crylink.md3");
+		precache_model ("models/weapons/v_crylink.md3");
+		precache_model ("models/weapons/h_crylink.iqm");
+		precache_sound ("weapons/crylink_fire.wav");
+		precache_sound ("weapons/crylink_fire2.wav");
+		precache_sound ("weapons/crylink_linkjoin.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_CRYLINK);
+		self.current_ammo = ammo_cells;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		// don't "run out of ammo" and switch weapons while waiting for release
+		if(self.crylink_lastgroup && self.crylink_waitrelease)
+			return TRUE;
+
+		ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_primary_ammo;
+		ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_primary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		// don't "run out of ammo" and switch weapons while waiting for release
+		if(self.crylink_lastgroup && self.crylink_waitrelease)
+			return TRUE;
+
+		ammo_amount = self.ammo_cells >= autocvar_g_balance_crylink_secondary_ammo;
+		ammo_amount += self.(weapon_load[WEP_CRYLINK]) >= autocvar_g_balance_crylink_secondary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(min(autocvar_g_balance_crylink_primary_ammo, autocvar_g_balance_crylink_secondary_ammo), autocvar_g_balance_crylink_reload_ammo, autocvar_g_balance_crylink_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_CRYLINK_SUICIDE;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		return WEAPON_CRYLINK_MURDER;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_crylink(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 2;
+		if(w_deathtype & HITTYPE_SECONDARY)
+		{
+			pointparticles(particleeffectnum("crylink_impact"), org2, '0 0 0', 1);
+			if(!w_issilent)
+				sound(self, CH_SHOTS, "weapons/crylink_impact2.wav", VOL_BASE, ATTEN_NORM);
+		}
+		else
+		{
+			pointparticles(particleeffectnum("crylink_impactbig"), org2, '0 0 0', 1);
+			if(!w_issilent)
+				sound(self, CH_SHOTS, "weapons/crylink_impact.wav", VOL_BASE, ATTEN_NORM);
+		}
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/crylink_impact2.wav");
+		precache_sound("weapons/crylink_impact.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_electro.qh b/qcsrc/server/w_electro.qh
new file mode 100644
index 000000000..98c0be13e
--- /dev/null
+++ b/qcsrc/server/w_electro.qh
@@ -0,0 +1,2 @@
+void ElectroInit();
+vector electro_shotorigin[4];
diff --git a/qcsrc/server/w_fireball.qc b/qcsrc/server/w_fireball.qc
new file mode 100644
index 000000000..88e9d770f
--- /dev/null
+++ b/qcsrc/server/w_fireball.qc
@@ -0,0 +1,434 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ FIREBALL,
+/* function  */ w_fireball,
+/* ammotype  */ 0,
+/* impulse   */ 9,
+/* flags     */ WEP_FLAG_SUPERWEAPON | WEP_TYPE_SPLASH,
+/* rating    */ BOT_PICKUP_RATING_MID,
+/* model     */ "fireball",
+/* shortname */ "fireball",
+/* fullname  */ _("Fireball")
+);
+#else
+#ifdef SVQC
+.float bot_primary_fireballmooth; // whatever a mooth is
+.vector fireball_impactvec;
+.float fireball_primarytime;
+
+void W_Fireball_Explode (void)
+{
+	entity e;
+	float dist;
+	float points;
+	vector dir;
+	float d;
+
+	self.event_damage = func_null;
+	self.takedamage = DAMAGE_NO;
+
+	// 1. dist damage
+	d = (self.realowner.health + self.realowner.armorvalue);
+	RadiusDamage (self, self.realowner, autocvar_g_balance_fireball_primary_damage, autocvar_g_balance_fireball_primary_edgedamage, autocvar_g_balance_fireball_primary_radius, world, autocvar_g_balance_fireball_primary_force, self.projectiledeathtype, other);
+	if(self.realowner.health + self.realowner.armorvalue >= d)
+	if(!self.cnt)
+	{
+		modeleffect_spawn("models/sphere/sphere.md3", 0, 0, self.origin, '0 0 0', '0 0 0', '0 0 0', 0, autocvar_g_balance_fireball_primary_bfgradius, 0.2, 0.05, 0.25);
+
+		// 2. bfg effect
+		// NOTE: this cannot be made warpzone aware by design. So, better intentionally ignore warpzones here.
+		for(e = findradius(self.origin, autocvar_g_balance_fireball_primary_bfgradius); e; e = e.chain)
+		if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(!IS_PLAYER(e) || !self.realowner || DIFF_TEAM(e, self))
+		{
+			// can we see fireball?
+			traceline(e.origin + e.view_ofs, self.origin, MOVE_NORMAL, e);
+			if(/* trace_startsolid || */ trace_fraction != 1) // startsolid should be never happening anyway
+				continue;
+			// can we see player who shot fireball?
+			traceline(e.origin + e.view_ofs, self.realowner.origin + self.realowner.view_ofs, MOVE_NORMAL, e);
+			if(trace_ent != self.realowner)
+			if(/* trace_startsolid || */ trace_fraction != 1)
+				continue;
+			dist = vlen(self.origin - e.origin - e.view_ofs);
+			points = (1 - sqrt(dist / autocvar_g_balance_fireball_primary_bfgradius));
+			if(points <= 0)
+				continue;
+			dir = normalize(e.origin + e.view_ofs - self.origin);
+
+			if(accuracy_isgooddamage(self.realowner, e))
+				accuracy_add(self.realowner, WEP_FIREBALL, 0, autocvar_g_balance_fireball_primary_bfgdamage * points);
+
+			Damage(e, self, self.realowner, autocvar_g_balance_fireball_primary_bfgdamage * points, self.projectiledeathtype | HITTYPE_BOUNCE | HITTYPE_SPLASH, e.origin + e.view_ofs, autocvar_g_balance_fireball_primary_bfgforce * dir);
+			pointparticles(particleeffectnum("fireball_bfgdamage"), e.origin, -1 * dir, 1);
+		}
+	}
+
+	remove (self);
+}
+
+void W_Fireball_TouchExplode (void)
+{
+	PROJECTILE_TOUCH;
+	W_Fireball_Explode ();
+}
+
+void W_Fireball_LaserPlay(float dt, float dist, float damage, float edgedamage, float burntime)
+{
+	entity e;
+	float d;
+	vector p;
+
+	if(damage <= 0)
+		return;
+
+	RandomSelection_Init();
+	for(e = WarpZone_FindRadius(self.origin, dist, TRUE); e; e = e.chain)
+	if(e != self.realowner) if(e.takedamage == DAMAGE_AIM) if(!IS_PLAYER(e) || !self.realowner || DIFF_TEAM(e, self))
+	{
+		p = e.origin;
+		p_x += e.mins_x + random() * (e.maxs_x - e.mins_x);
+		p_y += e.mins_y + random() * (e.maxs_y - e.mins_y);
+		p_z += e.mins_z + random() * (e.maxs_z - e.mins_z);
+		d = vlen(WarpZone_UnTransformOrigin(e, self.origin) - p);
+		if(d < dist)
+		{
+			e.fireball_impactvec = p;
+			RandomSelection_Add(e, 0, string_null, 1 / (1 + d), !Fire_IsBurning(e));
+		}
+	}
+	if(RandomSelection_chosen_ent)
+	{
+		d = vlen(WarpZone_UnTransformOrigin(RandomSelection_chosen_ent, self.origin) - RandomSelection_chosen_ent.fireball_impactvec);
+		d = damage + (edgedamage - damage) * (d / dist);
+		Fire_AddDamage(RandomSelection_chosen_ent, self.realowner, d * burntime, burntime, self.projectiledeathtype | HITTYPE_BOUNCE);
+		//trailparticles(self, particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec);
+		pointparticles(particleeffectnum("fireball_laser"), self.origin, RandomSelection_chosen_ent.fireball_impactvec - self.origin, 1);
+	}
+}
+
+void W_Fireball_Think()
+{
+	if(time > self.pushltime)
+	{
+		self.cnt = 1;
+		self.projectiledeathtype |= HITTYPE_SPLASH;
+		W_Fireball_Explode();
+		return;
+	}
+
+	W_Fireball_LaserPlay(0.1, autocvar_g_balance_fireball_primary_laserradius, autocvar_g_balance_fireball_primary_laserdamage, autocvar_g_balance_fireball_primary_laseredgedamage, autocvar_g_balance_fireball_primary_laserburntime);
+
+	self.nextthink = time + 0.1;
+}
+
+void W_Fireball_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	if(self.health <= 0)
+		return;
+
+	if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+		return; // g_projectiles_damage says to halt
+
+	self.health = self.health - damage;
+	if (self.health <= 0)
+	{
+		self.cnt = 1;
+		W_PrepareExplosionByDamage(attacker, W_Fireball_Explode);
+	}
+}
+
+void W_Fireball_Attack1()
+{
+	entity proj;
+
+	W_SetupShot_ProjectileSize (self, '-16 -16 -16', '16 16 16', FALSE, 2, "weapons/fireball_fire2.wav", CH_WEAPON_A, autocvar_g_balance_fireball_primary_damage + autocvar_g_balance_fireball_primary_bfgdamage);
+
+	pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	proj = spawn ();
+	proj.classname = "plasma_prim";
+	proj.owner = proj.realowner = self;
+	proj.bot_dodge = TRUE;
+	proj.bot_dodgerating = autocvar_g_balance_fireball_primary_damage;
+	proj.pushltime = time + autocvar_g_balance_fireball_primary_lifetime;
+	proj.use = W_Fireball_Explode;
+	proj.think = W_Fireball_Think;
+	proj.nextthink = time;
+	proj.health = autocvar_g_balance_fireball_primary_health;
+	proj.team = self.team;
+	proj.event_damage = W_Fireball_Damage;
+	proj.takedamage = DAMAGE_YES;
+	proj.damageforcescale = autocvar_g_balance_fireball_primary_damageforcescale;
+	PROJECTILE_MAKETRIGGER(proj);
+	proj.projectiledeathtype = WEP_FIREBALL;
+	setorigin(proj, w_shotorg);
+
+	proj.movetype = MOVETYPE_FLY;
+	W_SETUPPROJECTILEVELOCITY(proj, g_balance_fireball_primary);
+	proj.angles = vectoangles(proj.velocity);
+	proj.touch = W_Fireball_TouchExplode;
+	setsize(proj, '-16 -16 -16', '16 16 16');
+	proj.flags = FL_PROJECTILE;
+    proj.missile_flags = MIF_SPLASH | MIF_PROXY;
+
+	CSQCProjectile(proj, TRUE, PROJECTILE_FIREBALL, TRUE);
+
+	other = proj; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void W_Fireball_AttackEffect(float i, vector f_diff)
+{
+	W_SetupShot_ProjectileSize (self, '-16 -16 -16', '16 16 16', FALSE, 0, "", 0, 0);
+	w_shotorg += f_diff_x * v_up + f_diff_y * v_right;
+	pointparticles(particleeffectnum("fireball_preattack_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+}
+
+void W_Fireball_Attack1_Frame4()
+{
+	W_Fireball_Attack1();
+	weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, w_ready);
+}
+
+void W_Fireball_Attack1_Frame3()
+{
+	W_Fireball_AttackEffect(0, '+1.25 +3.75 0');
+	weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, W_Fireball_Attack1_Frame4);
+}
+
+void W_Fireball_Attack1_Frame2()
+{
+	W_Fireball_AttackEffect(0, '-1.25 +3.75 0');
+	weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, W_Fireball_Attack1_Frame3);
+}
+
+void W_Fireball_Attack1_Frame1()
+{
+	W_Fireball_AttackEffect(1, '+1.25 -3.75 0');
+	weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, W_Fireball_Attack1_Frame2);
+}
+
+void W_Fireball_Attack1_Frame0()
+{
+	W_Fireball_AttackEffect(0, '-1.25 -3.75 0');
+	sound (self, CH_WEAPON_SINGLE, "weapons/fireball_prefire2.wav", VOL_BASE, ATTEN_NORM);
+	weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_fireball_primary_animtime, W_Fireball_Attack1_Frame1);
+}
+
+void W_Firemine_Think()
+{
+	if(time > self.pushltime)
+	{
+		remove(self);
+		return;
+	}
+
+	// make it "hot" once it leaves its owner
+	if(self.owner)
+	{
+		if(vlen(self.origin - self.owner.origin - self.owner.view_ofs) > autocvar_g_balance_fireball_secondary_laserradius)
+		{
+			self.cnt += 1;
+			if(self.cnt == 3)
+				self.owner = world;
+		}
+		else
+			self.cnt = 0;
+	}
+
+	W_Fireball_LaserPlay(0.1, autocvar_g_balance_fireball_secondary_laserradius, autocvar_g_balance_fireball_secondary_laserdamage, autocvar_g_balance_fireball_secondary_laseredgedamage, autocvar_g_balance_fireball_secondary_laserburntime);
+
+	self.nextthink = time + 0.1;
+}
+
+void W_Firemine_Touch (void)
+{
+	PROJECTILE_TOUCH;
+	if (other.takedamage == DAMAGE_AIM)
+	if(Fire_AddDamage(other, self.realowner, autocvar_g_balance_fireball_secondary_damage, autocvar_g_balance_fireball_secondary_damagetime, self.projectiledeathtype) >= 0)
+	{
+		remove(self);
+		return;
+	}
+	self.projectiledeathtype |= HITTYPE_BOUNCE;
+}
+
+void W_Fireball_Attack2()
+{
+	entity proj;
+	vector f_diff;
+	float c;
+
+	c = mod(self.bulletcounter, 4);
+	switch(c)
+	{
+		case 0:
+			f_diff = '-1.25 -3.75 0';
+			break;
+		case 1:
+			f_diff = '+1.25 -3.75 0';
+			break;
+		case 2:
+			f_diff = '-1.25 +3.75 0';
+			break;
+		case 3:
+		default:
+			f_diff = '+1.25 +3.75 0';
+			break;
+	}
+	W_SetupShot_ProjectileSize(self, '-4 -4 -4', '4 4 4', FALSE, 2, "weapons/fireball_fire.wav", CH_WEAPON_A, autocvar_g_balance_fireball_secondary_damage);
+	traceline(w_shotorg, w_shotorg + f_diff_x * v_up + f_diff_y * v_right, MOVE_NORMAL, self);
+	w_shotorg = trace_endpos;
+
+	pointparticles(particleeffectnum("fireball_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	proj = spawn ();
+	proj.owner = proj.realowner = self;
+	proj.classname = "grenade";
+	proj.bot_dodge = TRUE;
+	proj.bot_dodgerating = autocvar_g_balance_fireball_secondary_damage;
+	proj.movetype = MOVETYPE_BOUNCE;
+	proj.projectiledeathtype = WEP_FIREBALL | HITTYPE_SECONDARY;
+	proj.touch = W_Firemine_Touch;
+	PROJECTILE_MAKETRIGGER(proj);
+	setsize(proj, '-4 -4 -4', '4 4 4');
+	setorigin(proj, w_shotorg);
+	proj.think = W_Firemine_Think;
+	proj.nextthink = time;
+	proj.damageforcescale = autocvar_g_balance_fireball_secondary_damageforcescale;
+	proj.pushltime = time + autocvar_g_balance_fireball_secondary_lifetime;
+	W_SETUPPROJECTILEVELOCITY_UP(proj, g_balance_fireball_secondary);
+
+	proj.angles = vectoangles(proj.velocity);
+	proj.flags = FL_PROJECTILE;
+    proj.missile_flags = MIF_SPLASH | MIF_PROXY | MIF_ARC;
+
+	CSQCProjectile(proj, TRUE, PROJECTILE_FIREMINE, TRUE);
+
+	other = proj; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void spawnfunc_weapon_fireball (void)
+{
+	weapon_defaultspawnfunc(WEP_FIREBALL);
+}
+
+float w_fireball(float req)
+{
+	//float ammo_amount;
+	if (req == WR_AIM)
+	{
+		self.BUTTON_ATCK = FALSE;
+		self.BUTTON_ATCK2 = FALSE;
+		if (self.bot_primary_fireballmooth == 0)
+		{
+			if(bot_aim(autocvar_g_balance_fireball_primary_speed, 0, autocvar_g_balance_fireball_primary_lifetime, FALSE))
+			{
+				self.BUTTON_ATCK = TRUE;
+				if(random() < 0.02) self.bot_primary_fireballmooth = 0;
+			}
+		}
+		else
+		{
+			if(bot_aim(autocvar_g_balance_fireball_secondary_speed, autocvar_g_balance_fireball_secondary_speed_up, autocvar_g_balance_fireball_secondary_lifetime, TRUE))
+			{
+				self.BUTTON_ATCK2 = TRUE;
+				if(random() < 0.01) self.bot_primary_fireballmooth = 1;
+			}
+		}
+	}
+	else if (req == WR_THINK)
+	{
+		if (self.BUTTON_ATCK)
+		{
+			if (time >= self.fireball_primarytime)
+			if (weapon_prepareattack(0, autocvar_g_balance_fireball_primary_refire))
+			{
+				W_Fireball_Attack1_Frame0();
+				self.fireball_primarytime = time + autocvar_g_balance_fireball_primary_refire2 * W_WeaponRateFactor();
+			}
+		}
+		else if (self.BUTTON_ATCK2)
+		{
+			if (weapon_prepareattack(1, autocvar_g_balance_fireball_secondary_refire))
+			{
+				W_Fireball_Attack2();
+				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_fireball_secondary_animtime, w_ready);
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_fireball.md3");
+		precache_model ("models/weapons/v_fireball.md3");
+		precache_model ("models/weapons/h_fireball.iqm");
+		precache_model ("models/sphere/sphere.md3");
+		precache_sound ("weapons/fireball_fire.wav");
+		precache_sound ("weapons/fireball_fire2.wav");
+		precache_sound ("weapons/fireball_prefire2.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_FIREBALL);
+		self.current_ammo = ammo_none;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		return 1;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		return 1;
+	}
+	else if (req == WR_RESETPLAYER)
+	{
+		self.fireball_primarytime = time;
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+			return WEAPON_FIREBALL_SUICIDE_FIREMINE;
+		else
+			return WEAPON_FIREBALL_SUICIDE_BLAST;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+		{
+			return WEAPON_FIREBALL_MURDER_FIREMINE;
+		}
+		else
+		{
+			return WEAPON_FIREBALL_MURDER_BLAST;
+		}
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_fireball(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		if(w_deathtype & HITTYPE_SECONDARY)
+		{
+			// firemine goes out silently
+		}
+		else
+		{
+			org2 = w_org + w_backoff * 16;
+			pointparticles(particleeffectnum("fireball_explode"), org2, '0 0 0', 1);
+			if(!w_issilent)
+				sound(self, CH_SHOTS, "weapons/fireball_impact2.wav", VOL_BASE, ATTEN_NORM * 0.25); // long range boom
+		}
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/fireball_impact2.wav");
+	}
+
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_grenadelauncher.qc b/qcsrc/server/w_grenadelauncher.qc
new file mode 100644
index 000000000..17144d3a5
--- /dev/null
+++ b/qcsrc/server/w_grenadelauncher.qc
@@ -0,0 +1,414 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ GRENADE_LAUNCHER,
+/* function  */ w_glauncher,
+/* ammotype  */ IT_ROCKETS,
+/* impulse   */ 4,
+/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
+/* rating    */ BOT_PICKUP_RATING_MID,
+/* model     */ "gl",
+/* shortname */ "grenadelauncher",
+/* fullname  */ _("Mortar")
+);
+#else
+#ifdef SVQC
+.float gl_detonate_later;
+.float gl_bouncecnt;
+
+void W_Grenade_Explode (void)
+{
+	if(other.takedamage == DAMAGE_AIM)
+		if(IS_PLAYER(other))
+			if(DIFF_TEAM(self.realowner, other))
+				if(other.deadflag == DEAD_NO)
+					if(IsFlying(other))
+						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+
+	self.event_damage = func_null;
+	self.takedamage = DAMAGE_NO;
+
+	if(self.movetype == MOVETYPE_NONE)
+		self.velocity = self.oldvelocity;
+
+	RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_primary_damage, autocvar_g_balance_grenadelauncher_primary_edgedamage, autocvar_g_balance_grenadelauncher_primary_radius, world, autocvar_g_balance_grenadelauncher_primary_force, self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void W_Grenade_Explode2 (void)
+{
+	if(other.takedamage == DAMAGE_AIM)
+		if(IS_PLAYER(other))
+			if(DIFF_TEAM(self.realowner, other))
+				if(other.deadflag == DEAD_NO)
+					if(IsFlying(other))
+						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+
+	self.event_damage = func_null;
+	self.takedamage = DAMAGE_NO;
+
+	if(self.movetype == MOVETYPE_NONE)
+		self.velocity = self.oldvelocity;
+
+	RadiusDamage (self, self.realowner, autocvar_g_balance_grenadelauncher_secondary_damage, autocvar_g_balance_grenadelauncher_secondary_edgedamage, autocvar_g_balance_grenadelauncher_secondary_radius, world, autocvar_g_balance_grenadelauncher_secondary_force, self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void W_Grenade_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	if (self.health <= 0)
+		return;
+
+	if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+		return; // g_projectiles_damage says to halt
+
+	self.health = self.health - damage;
+
+	if (self.health <= 0)
+		W_PrepareExplosionByDamage(attacker, self.use);
+}
+
+void W_Grenade_Think1 (void)
+{
+	self.nextthink = time;
+	if (time > self.cnt)
+	{
+		other = world;
+		self.projectiledeathtype |= HITTYPE_BOUNCE;
+		W_Grenade_Explode ();
+		return;
+	}
+	if(self.gl_detonate_later && self.gl_bouncecnt >= autocvar_g_balance_grenadelauncher_primary_remote_minbouncecnt)
+		W_Grenade_Explode();
+}
+
+void W_Grenade_Touch1 (void)
+{
+	PROJECTILE_TOUCH;
+	if (other.takedamage == DAMAGE_AIM || autocvar_g_balance_grenadelauncher_primary_type == 0) // always explode when hitting a player, or if normal mortar projectile
+	{
+		self.use ();
+	}
+	else if (autocvar_g_balance_grenadelauncher_primary_type == 1) // bounce
+	{
+		float r;
+		r = random() * 6;
+		if(r < 1)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTEN_NORM);
+		else if(r < 2)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTEN_NORM);
+		else if(r < 3)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTEN_NORM);
+		else if(r < 4)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTEN_NORM);
+		else if(r < 5)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTEN_NORM);
+		else
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTEN_NORM);
+		self.projectiledeathtype |= HITTYPE_BOUNCE;
+		self.gl_bouncecnt += 1;
+	}
+	else if(autocvar_g_balance_grenadelauncher_primary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
+	{
+		spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTEN_NORM);
+
+		// let it stick whereever it is
+		self.oldvelocity = self.velocity;
+		self.velocity = '0 0 0';
+		self.movetype = MOVETYPE_NONE; // also disables gravity
+		self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
+		UpdateCSQCProjectile(self);
+
+		// do not respond to any more touches
+		self.solid = SOLID_NOT;
+
+		self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_primary_lifetime_stick);
+	}
+}
+
+void W_Grenade_Touch2 (void)
+{
+	PROJECTILE_TOUCH;
+	if (other.takedamage == DAMAGE_AIM || autocvar_g_balance_grenadelauncher_secondary_type == 0) // always explode when hitting a player, or if normal mortar projectile
+	{
+		self.use ();
+	}
+	else if (autocvar_g_balance_grenadelauncher_secondary_type == 1) // bounce
+	{
+		float r;
+		r = random() * 6;
+		if(r < 1)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce1.wav", VOL_BASE, ATTEN_NORM);
+		else if(r < 2)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce2.wav", VOL_BASE, ATTEN_NORM);
+		else if(r < 3)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce3.wav", VOL_BASE, ATTEN_NORM);
+		else if(r < 4)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce4.wav", VOL_BASE, ATTEN_NORM);
+		else if(r < 5)
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce5.wav", VOL_BASE, ATTEN_NORM);
+		else
+			spamsound (self, CH_SHOTS, "weapons/grenade_bounce6.wav", VOL_BASE, ATTEN_NORM);
+		self.projectiledeathtype |= HITTYPE_BOUNCE;
+		self.gl_bouncecnt += 1;
+
+		if (autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce && self.gl_bouncecnt == 1)
+			self.nextthink = time + autocvar_g_balance_grenadelauncher_secondary_lifetime_bounce;
+
+	}
+	else if(autocvar_g_balance_grenadelauncher_secondary_type == 2 && (!other || (other.takedamage != DAMAGE_AIM && other.movetype == MOVETYPE_NONE))) // stick
+	{
+		spamsound (self, CH_SHOTS, "weapons/grenade_stick.wav", VOL_BASE, ATTEN_NORM);
+
+		// let it stick whereever it is
+		self.oldvelocity = self.velocity;
+		self.velocity = '0 0 0';
+		self.movetype = MOVETYPE_NONE; // also disables gravity
+		self.gravity = 0; // nope, it does NOT! maybe a bug in CSQC code? TODO
+		UpdateCSQCProjectile(self);
+
+		// do not respond to any more touches
+		self.solid = SOLID_NOT;
+
+		self.nextthink = min(self.nextthink, time + autocvar_g_balance_grenadelauncher_secondary_lifetime_stick);
+	}
+}
+
+void W_Grenade_Attack (void)
+{
+	entity gren;
+
+	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo);
+
+	W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_primary_damage);
+	w_shotdir = v_forward; // no TrueAim for grenades please
+
+	pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	gren = spawn ();
+	gren.owner = gren.realowner = self;
+	gren.classname = "grenade";
+	gren.bot_dodge = TRUE;
+	gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_primary_damage;
+	gren.movetype = MOVETYPE_BOUNCE;
+	gren.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor;
+	gren.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop;
+	PROJECTILE_MAKETRIGGER(gren);
+	gren.projectiledeathtype = WEP_GRENADE_LAUNCHER;
+	setorigin(gren, w_shotorg);
+	setsize(gren, '-3 -3 -3', '3 3 3');
+
+	gren.cnt = time + autocvar_g_balance_grenadelauncher_primary_lifetime;
+	gren.nextthink = time;
+	gren.think = W_Grenade_Think1;
+	gren.use = W_Grenade_Explode;
+	gren.touch = W_Grenade_Touch1;
+
+	gren.takedamage = DAMAGE_YES;
+	gren.health = autocvar_g_balance_grenadelauncher_primary_health;
+	gren.damageforcescale = autocvar_g_balance_grenadelauncher_primary_damageforcescale;
+	gren.event_damage = W_Grenade_Damage;
+	gren.damagedbycontents = TRUE;
+	gren.missile_flags = MIF_SPLASH | MIF_ARC;
+	W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_primary);
+
+	gren.angles = vectoangles (gren.velocity);
+	gren.flags = FL_PROJECTILE;
+
+	if(autocvar_g_balance_grenadelauncher_primary_type == 0 || autocvar_g_balance_grenadelauncher_primary_type == 2)
+		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
+	else
+		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
+
+	other = gren; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void W_Grenade_Attack2 (void)
+{
+	entity gren;
+
+	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_grenadelauncher_secondary_ammo, autocvar_g_balance_grenadelauncher_reload_ammo);
+
+	W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 4, "weapons/grenade_fire.wav", CH_WEAPON_A, autocvar_g_balance_grenadelauncher_secondary_damage);
+	w_shotdir = v_forward; // no TrueAim for grenades please
+
+	pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	gren = spawn ();
+	gren.owner = gren.realowner = self;
+	gren.classname = "grenade";
+	gren.bot_dodge = TRUE;
+	gren.bot_dodgerating = autocvar_g_balance_grenadelauncher_secondary_damage;
+	gren.movetype = MOVETYPE_BOUNCE;
+	gren.bouncefactor = autocvar_g_balance_grenadelauncher_bouncefactor;
+	gren.bouncestop = autocvar_g_balance_grenadelauncher_bouncestop;
+	PROJECTILE_MAKETRIGGER(gren);
+	gren.projectiledeathtype = WEP_GRENADE_LAUNCHER | HITTYPE_SECONDARY;
+	setorigin(gren, w_shotorg);
+	setsize(gren, '-3 -3 -3', '3 3 3');
+
+	gren.nextthink = time + autocvar_g_balance_grenadelauncher_secondary_lifetime;
+	gren.think = adaptor_think2use_hittype_splash;
+	gren.use = W_Grenade_Explode2;
+	gren.touch = W_Grenade_Touch2;
+
+	gren.takedamage = DAMAGE_YES;
+	gren.health = autocvar_g_balance_grenadelauncher_secondary_health;
+	gren.damageforcescale = autocvar_g_balance_grenadelauncher_secondary_damageforcescale;
+	gren.event_damage = W_Grenade_Damage;
+	gren.damagedbycontents = TRUE;
+	gren.missile_flags = MIF_SPLASH | MIF_ARC;
+	W_SETUPPROJECTILEVELOCITY_UP(gren, g_balance_grenadelauncher_secondary);
+
+	gren.angles = vectoangles (gren.velocity);
+	gren.flags = FL_PROJECTILE;
+
+	if(autocvar_g_balance_grenadelauncher_secondary_type == 0 || autocvar_g_balance_grenadelauncher_secondary_type == 2)
+		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE, TRUE);
+	else
+		CSQCProjectile(gren, TRUE, PROJECTILE_GRENADE_BOUNCING, TRUE);
+
+	other = gren; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void spawnfunc_weapon_grenadelauncher (void)
+{
+	weapon_defaultspawnfunc(WEP_GRENADE_LAUNCHER);
+}
+
+.float bot_secondary_grenademooth;
+float w_glauncher(float req)
+{
+	entity nade;
+	float nadefound;
+	float ammo_amount;
+
+	if (req == WR_AIM)
+	{
+		self.BUTTON_ATCK = FALSE;
+		self.BUTTON_ATCK2 = FALSE;
+		if (self.bot_secondary_grenademooth == 0)
+		{
+			if(bot_aim(autocvar_g_balance_grenadelauncher_primary_speed, autocvar_g_balance_grenadelauncher_primary_speed_up, autocvar_g_balance_grenadelauncher_primary_lifetime, TRUE))
+			{
+				self.BUTTON_ATCK = TRUE;
+				if(random() < 0.01) self.bot_secondary_grenademooth = 1;
+			}
+		}
+		else
+		{
+			if(bot_aim(autocvar_g_balance_grenadelauncher_secondary_speed, autocvar_g_balance_grenadelauncher_secondary_speed_up, autocvar_g_balance_grenadelauncher_secondary_lifetime, TRUE))
+			{
+				self.BUTTON_ATCK2 = TRUE;
+				if(random() < 0.02) self.bot_secondary_grenademooth = 0;
+			}
+		}
+	}
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_grenadelauncher_reload_ammo && self.clip_load < min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo)) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+		else if (self.BUTTON_ATCK)
+		{
+			if (weapon_prepareattack(0, autocvar_g_balance_grenadelauncher_primary_refire))
+			{
+				W_Grenade_Attack();
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_grenadelauncher_primary_animtime, w_ready);
+			}
+		}
+		else if (self.BUTTON_ATCK2)
+		{
+			if (cvar("g_balance_grenadelauncher_secondary_remote_detonateprimary"))
+			{
+				nadefound = 0;
+				for(nade = world; (nade = find(nade, classname, "grenade")); ) if(nade.realowner == self)
+				{
+					if(!nade.gl_detonate_later)
+					{
+						nade.gl_detonate_later = TRUE;
+						nadefound = 1;
+					}
+				}
+				if(nadefound)
+					sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTEN_NORM);
+			}
+			else if (weapon_prepareattack(1, autocvar_g_balance_grenadelauncher_secondary_refire))
+			{
+				W_Grenade_Attack2();
+				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_grenadelauncher_secondary_animtime, w_ready);
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_gl.md3");
+		precache_model ("models/weapons/v_gl.md3");
+		precache_model ("models/weapons/h_gl.iqm");
+		precache_sound ("weapons/grenade_bounce1.wav");
+		precache_sound ("weapons/grenade_bounce2.wav");
+		precache_sound ("weapons/grenade_bounce3.wav");
+		precache_sound ("weapons/grenade_bounce4.wav");
+		precache_sound ("weapons/grenade_bounce5.wav");
+		precache_sound ("weapons/grenade_bounce6.wav");
+		precache_sound ("weapons/grenade_stick.wav");
+		precache_sound ("weapons/grenade_fire.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_GRENADE_LAUNCHER);
+		self.current_ammo = ammo_rockets;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_primary_ammo;
+		ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_primary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		ammo_amount = self.ammo_rockets >= autocvar_g_balance_grenadelauncher_secondary_ammo;
+		ammo_amount += self.(weapon_load[WEP_GRENADE_LAUNCHER]) >= autocvar_g_balance_grenadelauncher_secondary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(min(autocvar_g_balance_grenadelauncher_primary_ammo, autocvar_g_balance_grenadelauncher_secondary_ammo), autocvar_g_balance_grenadelauncher_reload_ammo, autocvar_g_balance_grenadelauncher_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+			return WEAPON_MORTAR_SUICIDE_BOUNCE;
+		else
+			return WEAPON_MORTAR_SUICIDE_EXPLODE;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+			return WEAPON_MORTAR_MURDER_BOUNCE;
+		else
+			return WEAPON_MORTAR_MURDER_EXPLODE;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_glauncher(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 12;
+		pointparticles(particleeffectnum("grenade_explode"), org2, '0 0 0', 1);
+		if(!w_issilent)
+			sound(self, CH_SHOTS, "weapons/grenade_impact.wav", VOL_BASE, ATTEN_NORM);
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/grenade_impact.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_hagar.qc b/qcsrc/server/w_hagar.qc
new file mode 100644
index 000000000..05768fc50
--- /dev/null
+++ b/qcsrc/server/w_hagar.qc
@@ -0,0 +1,489 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ HAGAR,
+/* function  */ w_hagar,
+/* ammotype  */ IT_ROCKETS,
+/* impulse   */ 8,
+/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
+/* rating    */ BOT_PICKUP_RATING_MID,
+/* model     */ "hagar",
+/* shortname */ "hagar",
+/* fullname  */ _("Hagar")
+);
+#else
+#ifdef SVQC
+// NO bounce protection, as bounces are limited!
+
+void W_Hagar_Explode (void)
+{
+	self.event_damage = func_null;
+	RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_primary_damage, autocvar_g_balance_hagar_primary_edgedamage, autocvar_g_balance_hagar_primary_radius, world, autocvar_g_balance_hagar_primary_force, self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void W_Hagar_Explode2 (void)
+{
+	self.event_damage = func_null;
+	RadiusDamage (self, self.realowner, autocvar_g_balance_hagar_secondary_damage, autocvar_g_balance_hagar_secondary_edgedamage, autocvar_g_balance_hagar_secondary_radius, world, autocvar_g_balance_hagar_secondary_force, self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void W_Hagar_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	if (self.health <= 0)
+		return;
+
+	float is_linkexplode = ( ((inflictor.owner != world) ? (inflictor.owner == self.owner) : TRUE)
+		&& (inflictor.projectiledeathtype & HITTYPE_SECONDARY)
+		&& (self.projectiledeathtype & HITTYPE_SECONDARY));
+
+	if(is_linkexplode)
+		is_linkexplode = (is_linkexplode && autocvar_g_balance_hagar_secondary_load_linkexplode);
+	else
+		is_linkexplode = -1; // not secondary load, so continue as normal without exception.
+
+	if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, is_linkexplode))
+		return; // g_projectiles_damage says to halt
+
+	self.health = self.health - damage;
+	self.angles = vectoangles(self.velocity);
+
+	if (self.health <= 0)
+		W_PrepareExplosionByDamage(attacker, self.think);
+}
+
+void W_Hagar_Touch (void)
+{
+	PROJECTILE_TOUCH;
+	self.use ();
+}
+
+void W_Hagar_Touch2 (void)
+{
+	PROJECTILE_TOUCH;
+
+	if(self.cnt > 0 || other.takedamage == DAMAGE_AIM) {
+		self.use();
+	} else {
+		self.cnt++;
+		pointparticles(particleeffectnum("hagar_bounce"), self.origin, self.velocity, 1);
+		self.angles = vectoangles (self.velocity);
+		self.owner = world;
+		self.projectiledeathtype |= HITTYPE_BOUNCE;
+	}
+}
+
+void W_Hagar_Attack (void)
+{
+	entity missile;
+
+	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_reload_ammo);
+
+	W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, autocvar_g_balance_hagar_primary_damage);
+
+	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	missile = spawn ();
+	missile.owner = missile.realowner = self;
+	missile.classname = "missile";
+	missile.bot_dodge = TRUE;
+	missile.bot_dodgerating = autocvar_g_balance_hagar_primary_damage;
+
+	missile.takedamage = DAMAGE_YES;
+	missile.health = autocvar_g_balance_hagar_primary_health;
+	missile.damageforcescale = autocvar_g_balance_hagar_primary_damageforcescale;
+	missile.event_damage = W_Hagar_Damage;
+	missile.damagedbycontents = TRUE;
+
+	missile.touch = W_Hagar_Touch;
+	missile.use = W_Hagar_Explode;
+	missile.think = adaptor_think2use_hittype_splash;
+	missile.nextthink = time + autocvar_g_balance_hagar_primary_lifetime;
+	PROJECTILE_MAKETRIGGER(missile);
+	missile.projectiledeathtype = WEP_HAGAR;
+	setorigin (missile, w_shotorg);
+	setsize(missile, '0 0 0', '0 0 0');
+
+	missile.movetype = MOVETYPE_FLY;
+	W_SETUPPROJECTILEVELOCITY(missile, g_balance_hagar_primary);
+
+	missile.angles = vectoangles (missile.velocity);
+	missile.flags = FL_PROJECTILE;
+	missile.missile_flags = MIF_SPLASH;
+
+	CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE);
+
+	other = missile; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void W_Hagar_Attack2 (void)
+{
+	entity missile;
+
+	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo, autocvar_g_balance_hagar_reload_ammo);
+
+	W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, autocvar_g_balance_hagar_secondary_damage);
+
+	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	missile = spawn ();
+	missile.owner = missile.realowner = self;
+	missile.classname = "missile";
+	missile.bot_dodge = TRUE;
+	missile.bot_dodgerating = autocvar_g_balance_hagar_secondary_damage;
+
+	missile.takedamage = DAMAGE_YES;
+	missile.health = autocvar_g_balance_hagar_secondary_health;
+	missile.damageforcescale = autocvar_g_balance_hagar_secondary_damageforcescale;
+	missile.event_damage = W_Hagar_Damage;
+	missile.damagedbycontents = TRUE;
+
+	missile.touch = W_Hagar_Touch2;
+	missile.cnt = 0;
+	missile.use = W_Hagar_Explode2;
+	missile.think = adaptor_think2use_hittype_splash;
+	missile.nextthink = time + autocvar_g_balance_hagar_secondary_lifetime_min + random() * autocvar_g_balance_hagar_secondary_lifetime_rand;
+	PROJECTILE_MAKETRIGGER(missile);
+	missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY;
+	setorigin (missile, w_shotorg);
+	setsize(missile, '0 0 0', '0 0 0');
+
+	missile.movetype = MOVETYPE_BOUNCEMISSILE;
+	W_SETUPPROJECTILEVELOCITY(missile, g_balance_hagar_secondary);
+
+	missile.angles = vectoangles (missile.velocity);
+	missile.flags = FL_PROJECTILE;
+	missile.missile_flags = MIF_SPLASH;
+
+	CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR_BOUNCING, TRUE);
+
+	other = missile; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+.float hagar_loadstep, hagar_loadblock, hagar_loadbeep, hagar_warning;
+void W_Hagar_Attack2_Load_Release (void)
+{
+	// time to release the rockets we've loaded
+
+	entity missile;
+	float counter, shots, spread_pershot;
+	vector s;
+	vector forward, right, up;
+
+	if(!self.hagar_load)
+		return;
+
+	weapon_prepareattack_do(1, autocvar_g_balance_hagar_secondary_refire);
+
+	W_SetupShot (self, FALSE, 2, "weapons/hagar_fire.wav", CH_WEAPON_A, autocvar_g_balance_hagar_secondary_damage);
+	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	forward = v_forward;
+	right = v_right;
+	up = v_up;
+
+	shots = self.hagar_load;
+	missile = world;
+	for(counter = 0; counter < shots; ++counter)
+	{
+		missile = spawn ();
+		missile.owner = missile.realowner = self;
+		missile.classname = "missile";
+		missile.bot_dodge = TRUE;
+		missile.bot_dodgerating = autocvar_g_balance_hagar_secondary_damage;
+
+		missile.takedamage = DAMAGE_YES;
+		missile.health = autocvar_g_balance_hagar_secondary_health;
+		missile.damageforcescale = autocvar_g_balance_hagar_secondary_damageforcescale;
+		missile.event_damage = W_Hagar_Damage;
+		missile.damagedbycontents = TRUE;
+
+		missile.touch = W_Hagar_Touch; // not bouncy
+		missile.use = W_Hagar_Explode2;
+		missile.think = adaptor_think2use_hittype_splash;
+		missile.nextthink = time + autocvar_g_balance_hagar_secondary_lifetime_min + random() * autocvar_g_balance_hagar_secondary_lifetime_rand;
+		PROJECTILE_MAKETRIGGER(missile);
+		missile.projectiledeathtype = WEP_HAGAR | HITTYPE_SECONDARY;
+		setorigin (missile, w_shotorg);
+		setsize(missile, '0 0 0', '0 0 0');
+		missile.movetype = MOVETYPE_FLY;
+		missile.missile_flags = MIF_SPLASH;
+
+		// per-shot spread calculation: the more shots there are, the less spread is applied (based on the bias cvar)
+		spread_pershot = ((shots - 1) / (autocvar_g_balance_hagar_secondary_load_max - 1));
+		spread_pershot = (1 - (spread_pershot * autocvar_g_balance_hagar_secondary_load_spread_bias));
+		spread_pershot = (autocvar_g_balance_hagar_secondary_spread * spread_pershot * g_weaponspreadfactor);
+
+		// pattern spread calculation
+		s = '0 0 0';
+		if (counter == 0)
+			s = '0 0 0';
+		else
+		{
+			makevectors('0 360 0' * (0.75 + (counter - 0.5) / (shots - 1)));
+			s_y = v_forward_x;
+			s_z = v_forward_y;
+		}
+		s = s * autocvar_g_balance_hagar_secondary_load_spread * g_weaponspreadfactor;
+
+		W_SetupProjectileVelocityEx(missile, w_shotdir + right * s_y + up * s_z, v_up, autocvar_g_balance_hagar_secondary_speed, 0, 0, spread_pershot, FALSE);
+
+		missile.angles = vectoangles (missile.velocity);
+		missile.flags = FL_PROJECTILE;
+
+		CSQCProjectile(missile, TRUE, PROJECTILE_HAGAR, TRUE);
+
+		other = missile; MUTATOR_CALLHOOK(EditProjectile);
+	}
+
+	weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_load_animtime, w_ready);
+	self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_refire * W_WeaponRateFactor();
+	self.hagar_load = 0;
+}
+
+void W_Hagar_Attack2_Load (void)
+{
+	// loadable hagar secondary attack, must always run each frame
+
+	if(time < game_starttime)
+		return;
+
+	float loaded, enough_ammo;
+	loaded = self.hagar_load >= autocvar_g_balance_hagar_secondary_load_max;
+
+	// this is different than WR_CHECKAMMO when it comes to reloading
+	if(autocvar_g_balance_hagar_reload_ammo)
+		enough_ammo = self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_secondary_ammo;
+	else
+		enough_ammo = self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo;
+
+	if(self.BUTTON_ATCK2)
+	{
+		if(self.BUTTON_ATCK && autocvar_g_balance_hagar_secondary_load_abort)
+		{
+			if(self.hagar_load)
+			{
+				// if we pressed primary fire while loading, unload all rockets and abort
+				self.weaponentity.state = WS_READY;
+				W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo * self.hagar_load * -1, autocvar_g_balance_hagar_reload_ammo); // give back ammo
+				self.hagar_load = 0;
+				sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTEN_NORM);
+
+				// pause until we can load rockets again, once we re-press the alt fire button
+				self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_speed * W_WeaponRateFactor();
+
+				// require letting go of the alt fire button before we can load again
+				self.hagar_loadblock = TRUE;
+			}
+		}
+		else
+		{
+			// check if we can attempt to load another rocket
+			if(!loaded && enough_ammo)
+			{
+				if(!self.hagar_loadblock && self.hagar_loadstep < time)
+				{
+					W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo, autocvar_g_balance_hagar_reload_ammo);
+					self.weaponentity.state = WS_INUSE;
+					self.hagar_load += 1;
+					sound(self, CH_WEAPON_B, "weapons/hagar_load.wav", VOL_BASE * 0.8, ATTEN_NORM); // sound is too loud according to most
+
+					if (self.hagar_load >= autocvar_g_balance_hagar_secondary_load_max)
+						self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_hold * W_WeaponRateFactor();
+					else
+						self.hagar_loadstep = time + autocvar_g_balance_hagar_secondary_load_speed * W_WeaponRateFactor();
+				}
+			}
+			else if(!self.hagar_loadbeep && self.hagar_load) // prevents the beep from playing each frame
+			{
+				// if this is the last rocket we can load, play a beep sound to notify the player
+				sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTEN_NORM);
+				self.hagar_loadbeep = TRUE;
+			}
+		}
+	}
+	else if(self.hagar_loadblock)
+	{
+		// the alt fire button has been released, so re-enable loading if blocked
+		self.hagar_loadblock = FALSE;
+	}
+
+	if(self.hagar_load)
+	{
+		// play warning sound if we're about to release
+		if((loaded || !enough_ammo) && self.hagar_loadstep - 0.5 < time && autocvar_g_balance_hagar_secondary_load_hold >= 0)
+		{
+			if(!self.hagar_warning && self.hagar_load) // prevents the beep from playing each frame
+			{
+				// we're about to automatically release after holding time, play a beep sound to notify the player
+				sound(self, CH_WEAPON_A, "weapons/hagar_beep.wav", VOL_BASE, ATTEN_NORM);
+				self.hagar_warning = TRUE;
+			}
+		}
+
+		// release if player let go of button or if they've held it in too long
+		if(!self.BUTTON_ATCK2 || ((loaded || !enough_ammo) && self.hagar_loadstep < time && autocvar_g_balance_hagar_secondary_load_hold >= 0))
+		{
+			self.weaponentity.state = WS_READY;
+			W_Hagar_Attack2_Load_Release();
+		}
+	}
+	else
+	{
+		self.hagar_loadbeep = FALSE;
+		self.hagar_warning = FALSE;
+	}
+
+	// we aren't checking ammo during an attack, so we must do it here
+	if (!(weapon_action(self.weapon, WR_CHECKAMMO1) + weapon_action(self.weapon, WR_CHECKAMMO2)))
+	{
+		// note: this doesn't force the switch
+		W_SwitchToOtherWeapon(self);
+		return;
+	}
+}
+
+void spawnfunc_weapon_hagar (void)
+{
+	weapon_defaultspawnfunc(WEP_HAGAR);
+}
+
+float w_hagar(float req)
+{
+	float ammo_amount;
+	if (req == WR_AIM)
+		if (random()>0.15)
+			self.BUTTON_ATCK = bot_aim(autocvar_g_balance_hagar_primary_speed, 0, autocvar_g_balance_hagar_primary_lifetime, FALSE);
+		else
+		{
+			// not using secondary_speed since these are only 15% and should cause some ricochets without re-aiming
+			self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_hagar_primary_speed, 0, autocvar_g_balance_hagar_primary_lifetime, FALSE);
+		}
+	else if (req == WR_THINK)
+	{
+		float loadable_secondary;
+		loadable_secondary = (autocvar_g_balance_hagar_secondary_load && autocvar_g_balance_hagar_secondary);
+
+		if (loadable_secondary)
+			W_Hagar_Attack2_Load(); // must always run each frame
+		if(autocvar_g_balance_hagar_reload_ammo && self.clip_load < min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo)) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+		else if (self.BUTTON_ATCK && !self.hagar_load && !self.hagar_loadblock) // not while secondary is loaded or awaiting reset
+		{
+			if (weapon_prepareattack(0, autocvar_g_balance_hagar_primary_refire))
+			{
+				W_Hagar_Attack();
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hagar_primary_refire, w_ready);
+			}
+		}
+		else if (self.BUTTON_ATCK2 && !loadable_secondary && autocvar_g_balance_hagar_secondary)
+		{
+			if (weapon_prepareattack(1, autocvar_g_balance_hagar_secondary_refire))
+			{
+				W_Hagar_Attack2();
+				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hagar_secondary_refire, w_ready);
+			}
+		}
+	}
+	else if (req == WR_GONETHINK)
+	{
+		// we lost the weapon and want to prepare switching away
+		if(self.hagar_load)
+		{
+			self.weaponentity.state = WS_READY;
+			W_Hagar_Attack2_Load_Release();
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_hagar.md3");
+		precache_model ("models/weapons/v_hagar.md3");
+		precache_model ("models/weapons/h_hagar.iqm");
+		precache_sound ("weapons/hagar_fire.wav");
+		precache_sound ("weapons/hagar_load.wav");
+		precache_sound ("weapons/hagar_beep.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_HAGAR);
+		self.current_ammo = ammo_rockets;
+		self.hagar_loadblock = FALSE;
+
+		if(self.hagar_load)
+		{
+			W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_hagar_secondary_ammo * self.hagar_load * -1, autocvar_g_balance_hagar_reload_ammo); // give back ammo if necessary
+			self.hagar_load = 0;
+		}
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_primary_ammo;
+		ammo_amount += self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_primary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		ammo_amount = self.ammo_rockets >= autocvar_g_balance_hagar_secondary_ammo;
+		ammo_amount += self.(weapon_load[WEP_HAGAR]) >= autocvar_g_balance_hagar_secondary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_RESETPLAYER)
+	{
+		self.hagar_load = 0;
+	}
+	else if (req == WR_PLAYERDEATH)
+	{
+		// if we have any rockets loaded when we die, release them
+		if(self.hagar_load && autocvar_g_balance_hagar_secondary_load_releasedeath)
+			W_Hagar_Attack2_Load_Release();
+	}
+	else if (req == WR_RELOAD)
+	{
+		if (!self.hagar_load) // require releasing loaded rockets first
+			W_Reload(min(autocvar_g_balance_hagar_primary_ammo, autocvar_g_balance_hagar_secondary_ammo), autocvar_g_balance_hagar_reload_ammo, autocvar_g_balance_hagar_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_HAGAR_SUICIDE;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+			return WEAPON_HAGAR_MURDER_BURST;
+		else
+			return WEAPON_HAGAR_MURDER_SPRAY;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_hagar(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 6;
+		pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
+		if(!w_issilent)
+		{
+			if (w_random<0.15)
+				sound(self, CH_SHOTS, "weapons/hagexp1.wav", VOL_BASE, ATTEN_NORM);
+			else if (w_random<0.7)
+				sound(self, CH_SHOTS, "weapons/hagexp2.wav", VOL_BASE, ATTEN_NORM);
+			else
+				sound(self, CH_SHOTS, "weapons/hagexp3.wav", VOL_BASE, ATTEN_NORM);
+		}
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/hagexp1.wav");
+		precache_sound("weapons/hagexp2.wav");
+		precache_sound("weapons/hagexp3.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_hlac.qc b/qcsrc/server/w_hlac.qc
new file mode 100644
index 000000000..5642ef057
--- /dev/null
+++ b/qcsrc/server/w_hlac.qc
@@ -0,0 +1,261 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ HLAC,
+/* function  */ w_hlac,
+/* ammotype  */ IT_CELLS,
+/* impulse   */ 6,
+/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
+/* rating    */ BOT_PICKUP_RATING_MID,
+/* model     */ "hlac",
+/* shortname */ "hlac",
+/* fullname  */ _("Heavy Laser Assault Cannon")
+);
+#else
+#ifdef SVQC
+
+void W_HLAC_Touch (void)
+{
+	PROJECTILE_TOUCH;
+
+	self.event_damage = func_null;
+
+	if(self.projectiledeathtype & HITTYPE_SECONDARY)
+		RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_secondary_damage, autocvar_g_balance_hlac_secondary_edgedamage, autocvar_g_balance_hlac_secondary_radius, world, autocvar_g_balance_hlac_secondary_force, self.projectiledeathtype, other);
+	else
+		RadiusDamage (self, self.realowner, autocvar_g_balance_hlac_primary_damage, autocvar_g_balance_hlac_primary_edgedamage, autocvar_g_balance_hlac_primary_radius, world, autocvar_g_balance_hlac_primary_force, self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void W_HLAC_Attack (void)
+{
+	entity missile;
+    float spread;
+
+	W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_reload_ammo);
+
+    spread = autocvar_g_balance_hlac_primary_spread_min + (autocvar_g_balance_hlac_primary_spread_add * self.misc_bulletcounter);
+    spread = min(spread,autocvar_g_balance_hlac_primary_spread_max);
+    if(self.crouch)
+        spread = spread * autocvar_g_balance_hlac_primary_spread_crouchmod;
+
+	W_SetupShot (self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, autocvar_g_balance_hlac_primary_damage);
+	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+	if (!autocvar_g_norecoil)
+	{
+		self.punchangle_x = random () - 0.5;
+		self.punchangle_y = random () - 0.5;
+	}
+
+	missile = spawn ();
+	missile.owner = missile.realowner = self;
+	missile.classname = "hlacbolt";
+	missile.bot_dodge = TRUE;
+
+    missile.bot_dodgerating = autocvar_g_balance_hlac_primary_damage;
+
+	missile.movetype = MOVETYPE_FLY;
+	PROJECTILE_MAKETRIGGER(missile);
+
+	setorigin (missile, w_shotorg);
+	setsize(missile, '0 0 0', '0 0 0');
+
+	W_SetupProjectileVelocity(missile, autocvar_g_balance_hlac_primary_speed, spread);
+	//missile.angles = vectoangles (missile.velocity); // csqc
+
+	missile.touch = W_HLAC_Touch;
+	missile.think = SUB_Remove;
+
+    missile.nextthink = time + autocvar_g_balance_hlac_primary_lifetime;
+
+	missile.flags = FL_PROJECTILE;
+	missile.projectiledeathtype = WEP_HLAC;
+
+	CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE);
+
+	other = missile; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void W_HLAC_Attack2f (void)
+{
+	entity missile;
+    float spread;
+
+    spread = autocvar_g_balance_hlac_secondary_spread;
+
+
+    if(self.crouch)
+        spread = spread * autocvar_g_balance_hlac_secondary_spread_crouchmod;
+
+	W_SetupShot (self, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_A, autocvar_g_balance_hlac_secondary_damage);
+	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	missile = spawn ();
+	missile.owner = missile.realowner = self;
+	missile.classname = "hlacbolt";
+	missile.bot_dodge = TRUE;
+
+    missile.bot_dodgerating = autocvar_g_balance_hlac_secondary_damage;
+
+	missile.movetype = MOVETYPE_FLY;
+	PROJECTILE_MAKETRIGGER(missile);
+
+	setorigin (missile, w_shotorg);
+	setsize(missile, '0 0 0', '0 0 0');
+
+	W_SetupProjectileVelocity(missile, autocvar_g_balance_hlac_secondary_speed, spread);
+	//missile.angles = vectoangles (missile.velocity); // csqc
+
+	missile.touch = W_HLAC_Touch;
+	missile.think = SUB_Remove;
+
+    missile.nextthink = time + autocvar_g_balance_hlac_secondary_lifetime;
+
+	missile.flags = FL_PROJECTILE;
+	missile.missile_flags = MIF_SPLASH;
+	missile.projectiledeathtype = WEP_HLAC | HITTYPE_SECONDARY;
+
+	CSQCProjectile(missile, TRUE, PROJECTILE_HLAC, TRUE);
+
+	other = missile; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void W_HLAC_Attack2 (void)
+{
+    float i;
+
+	W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hlac_secondary_ammo, autocvar_g_balance_hlac_reload_ammo);
+
+    for(i=autocvar_g_balance_hlac_secondary_shots;i>0;--i)
+        W_HLAC_Attack2f();
+
+	if (!autocvar_g_norecoil)
+	{
+		self.punchangle_x = random () - 0.5;
+		self.punchangle_y = random () - 0.5;
+	}
+}
+
+// weapon frames
+void HLAC_fire1_02()
+{
+	if(self.weapon != self.switchweapon) // abort immediately if switching
+	{
+		w_ready();
+		return;
+	}
+
+	if (self.BUTTON_ATCK)
+	{
+		if (!weapon_action(self.weapon, WR_CHECKAMMO1))
+		if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+		{
+			W_SwitchWeapon_Force(self, w_getbestweapon(self));
+			w_ready();
+			return;
+		}
+
+		ATTACK_FINISHED(self) = time + autocvar_g_balance_hlac_primary_refire * W_WeaponRateFactor();
+		W_HLAC_Attack();
+		self.misc_bulletcounter = self.misc_bulletcounter + 1;
+        weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_refire, HLAC_fire1_02);
+	}
+	else
+	{
+		weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_animtime, w_ready);
+	}
+}
+
+void spawnfunc_weapon_hlac (void)
+{
+	weapon_defaultspawnfunc(WEP_HLAC);
+}
+
+float w_hlac(float req)
+{
+	float ammo_amount;
+	if (req == WR_AIM)
+        self.BUTTON_ATCK = bot_aim(autocvar_g_balance_hlac_primary_speed, 0, autocvar_g_balance_hlac_primary_lifetime, FALSE);
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_hlac_reload_ammo && self.clip_load < min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo)) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+		else if (self.BUTTON_ATCK)
+		{
+			if (weapon_prepareattack(0, autocvar_g_balance_hlac_primary_refire))
+			{
+				self.misc_bulletcounter = 0;
+				W_HLAC_Attack();
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hlac_primary_refire, HLAC_fire1_02);
+			}
+		}
+
+		else if (self.BUTTON_ATCK2 && autocvar_g_balance_hlac_secondary)
+		{
+			if (weapon_prepareattack(1, autocvar_g_balance_hlac_secondary_refire))
+			{
+				W_HLAC_Attack2();
+				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hlac_secondary_animtime, w_ready);
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+        precache_model ("models/weapons/g_hlac.md3");
+		precache_model ("models/weapons/v_hlac.md3");
+		precache_model ("models/weapons/h_hlac.iqm");
+		precache_sound ("weapons/lasergun_fire.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_HLAC);
+		self.current_ammo = ammo_cells;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_primary_ammo;
+		ammo_amount += self.(weapon_load[WEP_HLAC]) >= autocvar_g_balance_hlac_primary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		ammo_amount = self.ammo_cells >= autocvar_g_balance_hlac_secondary_ammo;
+		ammo_amount += self.(weapon_load[WEP_HLAC]) >= autocvar_g_balance_hlac_secondary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(min(autocvar_g_balance_hlac_primary_ammo, autocvar_g_balance_hlac_secondary_ammo), autocvar_g_balance_hlac_reload_ammo, autocvar_g_balance_hlac_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_HLAC_SUICIDE;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		return WEAPON_HLAC_MURDER;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_hlac(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 6;
+		pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1);
+		if(!w_issilent)
+			sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTEN_NORM);
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/laserimpact.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_hook.qc b/qcsrc/server/w_hook.qc
new file mode 100644
index 000000000..f0310c702
--- /dev/null
+++ b/qcsrc/server/w_hook.qc
@@ -0,0 +1,307 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ HOOK,
+/* function  */ w_hook,
+/* ammotype  */ IT_CELLS|IT_FUEL,
+/* impulse   */ 0,
+/* flags     */ WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
+/* rating    */ 0,
+/* model     */ "hookgun",
+/* shortname */ "hook",
+/* fullname  */ _("Grappling Hook")
+);
+#else
+#ifdef SVQC
+.float dmg;
+.float dmg_edge;
+.float dmg_radius;
+.float dmg_force;
+.float dmg_power;
+.float dmg_duration;
+.float dmg_last;
+.float hook_refire;
+.float hook_time_hooked;
+.float hook_time_fueldecrease;
+
+void W_Hook_ExplodeThink (void)
+{
+	float dt, dmg_remaining_next, f;
+
+	dt = time - self.teleport_time;
+	dmg_remaining_next = pow(bound(0, 1 - dt / self.dmg_duration, 1), self.dmg_power);
+
+	f = self.dmg_last - dmg_remaining_next;
+	self.dmg_last = dmg_remaining_next;
+
+	RadiusDamage (self, self.realowner, self.dmg * f, self.dmg_edge * f, self.dmg_radius, self.realowner, self.dmg_force * f, self.projectiledeathtype, world);
+	self.projectiledeathtype |= HITTYPE_BOUNCE;
+	//RadiusDamage (self, world, self.dmg * f, self.dmg_edge * f, self.dmg_radius, world, self.dmg_force * f, self.projectiledeathtype, world);
+
+	if(dt < self.dmg_duration)
+		self.nextthink = time + 0.05; // soon
+	else
+		remove(self);
+}
+
+void W_Hook_Explode2 (void)
+{
+	self.event_damage = func_null;
+	self.touch = func_null;
+	self.effects |= EF_NODRAW;
+
+	self.think = W_Hook_ExplodeThink;
+	self.nextthink = time;
+	self.dmg = autocvar_g_balance_hook_secondary_damage;
+	self.dmg_edge = autocvar_g_balance_hook_secondary_edgedamage;
+	self.dmg_radius = autocvar_g_balance_hook_secondary_radius;
+	self.dmg_force = autocvar_g_balance_hook_secondary_force;
+	self.dmg_power = autocvar_g_balance_hook_secondary_power;
+	self.dmg_duration = autocvar_g_balance_hook_secondary_duration;
+	self.teleport_time = time;
+	self.dmg_last = 1;
+	self.movetype = MOVETYPE_NONE;
+}
+
+void W_Hook_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	if (self.health <= 0)
+		return;
+
+	if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+		return; // g_projectiles_damage says to halt
+
+	self.health = self.health - damage;
+
+	if (self.health <= 0)
+		W_PrepareExplosionByDamage(self.realowner, W_Hook_Explode2);
+}
+
+void W_Hook_Touch2 (void)
+{
+	PROJECTILE_TOUCH;
+	self.use();
+}
+
+void W_Hook_Attack2()
+{
+	entity gren;
+
+	W_DecreaseAmmo(ammo_cells, autocvar_g_balance_hook_secondary_ammo, FALSE);
+	W_SetupShot (self, FALSE, 4, "weapons/hookbomb_fire.wav", CH_WEAPON_A, autocvar_g_balance_hook_secondary_damage);
+
+	gren = spawn ();
+	gren.owner = gren.realowner = self;
+	gren.classname = "hookbomb";
+	gren.bot_dodge = TRUE;
+	gren.bot_dodgerating = autocvar_g_balance_hook_secondary_damage;
+	gren.movetype = MOVETYPE_TOSS;
+	PROJECTILE_MAKETRIGGER(gren);
+	gren.projectiledeathtype = WEP_HOOK | HITTYPE_SECONDARY;
+	setorigin(gren, w_shotorg);
+	setsize(gren, '0 0 0', '0 0 0');
+
+	gren.nextthink = time + autocvar_g_balance_hook_secondary_lifetime;
+	gren.think = adaptor_think2use_hittype_splash;
+	gren.use = W_Hook_Explode2;
+	gren.touch = W_Hook_Touch2;
+
+	gren.takedamage = DAMAGE_YES;
+	gren.health = autocvar_g_balance_hook_secondary_health;
+	gren.damageforcescale = autocvar_g_balance_hook_secondary_damageforcescale;
+	gren.event_damage = W_Hook_Damage;
+	gren.damagedbycontents = TRUE;
+	gren.missile_flags = MIF_SPLASH | MIF_ARC;
+
+	gren.velocity = '0 0 1' * autocvar_g_balance_hook_secondary_speed;
+	if(autocvar_g_projectiles_newton_style)
+		gren.velocity = gren.velocity + self.velocity;
+
+	gren.gravity = autocvar_g_balance_hook_secondary_gravity;
+	//W_SetupProjectileVelocity(gren); // just falling down!
+
+	gren.angles = '0 0 0';
+	gren.flags = FL_PROJECTILE;
+
+	CSQCProjectile(gren, TRUE, PROJECTILE_HOOKBOMB, TRUE);
+
+	other = gren; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void spawnfunc_weapon_hook (void)
+{
+	if(g_grappling_hook) // offhand hook
+	{
+		startitem_failed = TRUE;
+		remove(self);
+		return;
+	}
+	weapon_defaultspawnfunc(WEP_HOOK);
+}
+
+float w_hook(float req)
+{
+	float hooked_time_max, hooked_fuel;
+
+	if (req == WR_AIM)
+	{
+		// ... sorry ...
+	}
+	else if (req == WR_THINK)
+	{
+		if (self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK))
+		{
+			if(!self.hook)
+			if (!(self.hook_state & HOOK_WAITING_FOR_RELEASE))
+			if (!(self.hook_state & HOOK_FIRING))
+			if (time > self.hook_refire)
+			if (weapon_prepareattack(0, -1))
+			{
+				W_DecreaseAmmo(ammo_fuel, autocvar_g_balance_hook_primary_fuel, FALSE);
+				self.hook_state |= HOOK_FIRING;
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_hook_primary_animtime, w_ready);
+			}
+		}
+
+		if (self.BUTTON_ATCK2)
+		{
+			if (weapon_prepareattack(1, autocvar_g_balance_hook_secondary_refire))
+			{
+				W_Hook_Attack2();
+				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_hook_secondary_animtime, w_ready);
+			}
+		}
+
+		if(self.hook)
+		{
+			// if hooked, no bombs, and increase the timer
+			self.hook_refire = max(self.hook_refire, time + autocvar_g_balance_hook_primary_refire * W_WeaponRateFactor());
+
+			// hook also inhibits health regeneration, but only for 1 second
+			if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+				self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_pause_fuel_regen);
+		}
+
+		if(self.hook && self.hook.state == 1)
+		{
+			hooked_time_max = autocvar_g_balance_hook_primary_hooked_time_max;
+			if (hooked_time_max > 0)
+			{
+				if ( time > self.hook_time_hooked + hooked_time_max )
+					self.hook_state |= HOOK_REMOVING;
+			}
+
+			hooked_fuel = autocvar_g_balance_hook_primary_hooked_fuel;
+			if (hooked_fuel > 0)
+			{
+				if ( time > self.hook_time_fueldecrease )
+				{
+					if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+					{
+						if ( self.ammo_fuel >= (time - self.hook_time_fueldecrease) * hooked_fuel )
+						{
+							W_DecreaseAmmo(ammo_fuel, (time - self.hook_time_fueldecrease) * hooked_fuel, FALSE);
+							self.hook_time_fueldecrease = time;
+							// decrease next frame again
+						}
+						else
+						{
+							self.ammo_fuel = 0;
+							self.hook_state |= HOOK_REMOVING;
+							W_SwitchWeapon_Force(self, w_getbestweapon(self));
+						}
+					}
+				}
+			}
+		}
+		else
+		{
+			self.hook_time_hooked = time;
+			self.hook_time_fueldecrease = time + autocvar_g_balance_hook_primary_hooked_time_free;
+		}
+
+		if (self.BUTTON_CROUCH)
+		{
+			self.hook_state &= ~HOOK_PULLING;
+			if (self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK))
+				self.hook_state &= ~HOOK_RELEASING;
+			else
+				self.hook_state |= HOOK_RELEASING;
+		}
+		else
+		{
+			self.hook_state |= HOOK_PULLING;
+			self.hook_state &= ~HOOK_RELEASING;
+
+			if (self.BUTTON_ATCK || (!(self.items & IT_JETPACK) && self.BUTTON_HOOK))
+			{
+				// already fired
+				if(self.hook)
+					self.hook_state |= HOOK_WAITING_FOR_RELEASE;
+			}
+			else
+			{
+				self.hook_state |= HOOK_REMOVING;
+				self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_hookgun.md3");
+		precache_model ("models/weapons/v_hookgun.md3");
+		precache_model ("models/weapons/h_hookgun.iqm");
+		precache_sound ("weapons/hook_impact.wav"); // done by g_hook.qc
+		precache_sound ("weapons/hook_fire.wav");
+		precache_sound ("weapons/hookbomb_fire.wav");
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_HOOK);
+		self.current_ammo = ammo_fuel;
+		self.hook_state &= ~HOOK_WAITING_FOR_RELEASE;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		if(self.hook)
+			return self.ammo_fuel > 0;
+		else
+			return self.ammo_fuel >= autocvar_g_balance_hook_primary_fuel;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		return self.ammo_cells >= autocvar_g_balance_hook_secondary_ammo;
+	}
+	else if (req == WR_RESETPLAYER)
+	{
+		self.hook_refire = time;
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return FALSE;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		return WEAPON_HOOK_MURDER;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_hook(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 2;
+		pointparticles(particleeffectnum("hookbomb_explode"), org2, '0 0 0', 1);
+		if(!w_issilent)
+			sound(self, CH_SHOTS, "weapons/hookbomb_impact.wav", VOL_BASE, ATTEN_NORM);
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/hookbomb_impact.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_laser.qc b/qcsrc/server/w_laser.qc
new file mode 100644
index 000000000..0a0704638
--- /dev/null
+++ b/qcsrc/server/w_laser.qc
@@ -0,0 +1,322 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ LASER,
+/* function  */ w_laser,
+/* ammotype  */ 0,
+/* impulse   */ 1,
+/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
+/* rating    */ 0,
+/* model     */ "laser",
+/* shortname */ "laser",
+/* fullname  */ _("Laser")
+);
+#else
+#ifdef SVQC
+void(float imp) W_SwitchWeapon;
+void() W_LastWeapon;
+
+void W_Laser_Touch (void)
+{
+	PROJECTILE_TOUCH;
+
+	self.event_damage = func_null;
+	if (self.dmg)
+		RadiusDamage (self, self.realowner, autocvar_g_balance_laser_secondary_damage, autocvar_g_balance_laser_secondary_edgedamage, autocvar_g_balance_laser_secondary_radius, world, autocvar_g_balance_laser_secondary_force, self.projectiledeathtype, other);
+	else
+		RadiusDamage (self, self.realowner, autocvar_g_balance_laser_primary_damage, autocvar_g_balance_laser_primary_edgedamage, autocvar_g_balance_laser_primary_radius, world, autocvar_g_balance_laser_primary_force, self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void W_Laser_Think()
+{
+	self.movetype = MOVETYPE_FLY;
+	self.think = SUB_Remove;
+	if (self.dmg)
+		self.nextthink = time + autocvar_g_balance_laser_secondary_lifetime;
+	else
+		self.nextthink = time + autocvar_g_balance_laser_primary_lifetime;
+	CSQCProjectile(self, TRUE, PROJECTILE_LASER, TRUE);
+}
+
+void W_Laser_Attack (float issecondary)
+{
+	entity missile;
+	vector s_forward;
+	float a;
+
+	a = autocvar_g_balance_laser_primary_shotangle;
+	s_forward = v_forward * cos(a * DEG2RAD) + v_up * sin(a * DEG2RAD);
+
+	if(issecondary == 1)
+		W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_balance_laser_secondary_damage);
+	else
+		W_SetupShot_Dir (self, s_forward, FALSE, 3, "weapons/lasergun_fire.wav", CH_WEAPON_B, autocvar_g_balance_laser_primary_damage);
+	pointparticles(particleeffectnum("laser_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	missile = spawn ();
+	missile.owner = missile.realowner = self;
+	missile.classname = "laserbolt";
+	missile.dmg = 0;
+	missile.bot_dodge = TRUE;
+	missile.bot_dodgerating = autocvar_g_balance_laser_primary_damage;
+
+	PROJECTILE_MAKETRIGGER(missile);
+	missile.projectiledeathtype = WEP_LASER;
+
+	setorigin (missile, w_shotorg);
+	setsize(missile, '0 0 0', '0 0 0');
+
+	W_SETUPPROJECTILEVELOCITY(missile, g_balance_laser_primary);
+	missile.angles = vectoangles (missile.velocity);
+	//missile.glow_color = 250; // 244, 250
+	//missile.glow_size = 120;
+	missile.touch = W_Laser_Touch;
+
+	missile.flags = FL_PROJECTILE;
+	missile.missile_flags = MIF_SPLASH;
+
+	missile.think = W_Laser_Think;
+	missile.nextthink = time + autocvar_g_balance_laser_primary_delay;
+
+	other = missile; MUTATOR_CALLHOOK(EditProjectile);
+
+	if(time >= missile.nextthink)
+	{
+		entity oldself;
+		oldself = self;
+		self = missile;
+		self.think();
+		self = oldself;
+	}
+}
+
+.vector hook_start, hook_end;
+float gauntletbeam_send(entity to, float sf)
+{
+	WriteByte(MSG_ENTITY, ENT_CLIENT_GAUNTLET);
+	sf = sf & 0x7F;
+	if(sound_allowed(MSG_BROADCAST, self.realowner))
+		sf |= 0x80;
+	WriteByte(MSG_ENTITY, sf);
+	if(sf & 1)
+	{
+		WriteByte(MSG_ENTITY, num_for_edict(self.realowner));
+	}
+	if(sf & 2)
+	{
+		WriteCoord(MSG_ENTITY, self.hook_start_x);
+		WriteCoord(MSG_ENTITY, self.hook_start_y);
+		WriteCoord(MSG_ENTITY, self.hook_start_z);
+	}
+	if(sf & 4)
+	{
+		WriteCoord(MSG_ENTITY, self.hook_end_x);
+		WriteCoord(MSG_ENTITY, self.hook_end_y);
+		WriteCoord(MSG_ENTITY, self.hook_end_z);
+	}
+	return TRUE;
+}
+.entity gauntletbeam;
+.float prevgauntletfire;
+entity lgbeam_owner_ent;
+void gauntletbeam_think()
+{
+	float damage, myforce, myradius;
+	damage = autocvar_g_balance_laser_secondary_damage;
+	myforce = autocvar_g_balance_laser_secondary_force;
+	myradius = autocvar_g_balance_laser_secondary_radius;
+
+	self.realowner.prevgauntletfire = time;
+	if (self.realowner.weaponentity.state != WS_INUSE || self != self.realowner.gauntletbeam || self.realowner.deadflag != DEAD_NO || !self.realowner.BUTTON_ATCK2)
+	{
+		remove(self);
+		return;
+	}
+
+	self.nextthink = time;
+
+	makevectors(self.realowner.v_angle);
+
+	float dt;
+	dt = frametime;
+
+	W_SetupShot_Range(self.realowner, TRUE, 0, "", 0, damage * dt, myradius);
+	if(!lgbeam_owner_ent)
+	{
+		lgbeam_owner_ent = spawn();
+		lgbeam_owner_ent.classname = "lgbeam_owner_ent";
+	}
+	WarpZone_traceline_antilag(lgbeam_owner_ent, w_shotorg, w_shotend, MOVE_NORMAL, lgbeam_owner_ent, ANTILAG_LATENCY(self.owner));
+
+	// apply the damage
+	if(trace_ent)
+	{
+		vector force;
+		force = w_shotdir * myforce;
+		if(accuracy_isgooddamage(self.owner, trace_ent))
+			accuracy_add(self.owner, WEP_LASER, 0, damage * dt);
+		Damage (trace_ent, self.owner, self.owner, damage * dt, WEP_LASER | HITTYPE_SECONDARY, trace_endpos, force * dt);
+	}
+
+	// draw effect
+	if(w_shotorg != self.hook_start)
+	{
+		self.SendFlags |= 2;
+		self.hook_start = w_shotorg;
+	}
+	if(w_shotend != self.hook_end)
+	{
+		self.SendFlags |= 4;
+		self.hook_end = w_shotend;
+	}
+}
+
+// experimental gauntlet
+void W_Laser_Attack2 ()
+{
+	// only play fire sound if 0.5 sec has passed since player let go the fire button
+	if(time - self.prevgauntletfire > 0.5)
+	{
+		sound (self, CH_WEAPON_A, "weapons/gauntlet_fire.wav", VOL_BASE, ATTEN_NORM);
+	}
+
+	entity beam, oldself;
+
+	self.gauntletbeam = beam = spawn();
+	beam.solid = SOLID_NOT;
+	beam.think = gauntletbeam_think;
+	beam.owner = self;
+	beam.movetype = MOVETYPE_NONE;
+	beam.shot_spread = 0;
+	beam.bot_dodge = TRUE;
+	beam.bot_dodgerating = autocvar_g_balance_laser_primary_damage;
+	Net_LinkEntity(beam, FALSE, 0, gauntletbeam_send);
+
+	oldself = self;
+	self = beam;
+	self.think();
+	self = oldself;
+}
+
+void LaserInit()
+{
+	weapon_action(WEP_LASER, WR_PRECACHE);
+	gauntlet_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 1);
+	gauntlet_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 2);
+	gauntlet_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 3);
+	gauntlet_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_LASER), FALSE, FALSE, 4);
+}
+
+void spawnfunc_weapon_laser (void)
+{
+	weapon_defaultspawnfunc(WEP_LASER);
+}
+
+float w_laser(float req)
+{
+	float r1;
+	float r2;
+	if (req == WR_AIM)
+	{
+		if(autocvar_g_balance_laser_secondary)
+		{
+			r1 = autocvar_g_balance_laser_primary_damage;
+			r2 = autocvar_g_balance_laser_secondary_damage;
+			if (random() * (r2 + r1) > r1)
+				self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_laser_secondary_speed, 0, autocvar_g_balance_laser_secondary_lifetime, FALSE);
+			else
+				self.BUTTON_ATCK = bot_aim(autocvar_g_balance_laser_primary_speed, 0, autocvar_g_balance_laser_primary_lifetime, FALSE);
+		}
+		else
+			self.BUTTON_ATCK = bot_aim(autocvar_g_balance_laser_primary_speed, 0, autocvar_g_balance_laser_primary_lifetime, FALSE);
+	}
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_laser_reload_ammo && self.clip_load < 1) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+		else if (self.BUTTON_ATCK)
+		{
+			if (weapon_prepareattack(0, autocvar_g_balance_laser_primary_refire))
+			{
+				W_DecreaseAmmo(ammo_none, 1, TRUE);
+
+				W_Laser_Attack(0);
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_laser_primary_animtime, w_ready);
+			}
+		}
+		else if (self.BUTTON_ATCK2)
+		{
+			if(autocvar_g_balance_laser_secondary)
+			{
+				W_DecreaseAmmo(ammo_none, 1, TRUE);
+
+				if (weapon_prepareattack(0, 0))
+				{
+					W_Laser_Attack2();
+					weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_laser_secondary_animtime, w_ready);
+				}
+			}
+			else
+			{
+				if(self.switchweapon == WEP_LASER) // don't do this if already switching
+					W_LastWeapon();
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_laser.md3");
+		precache_model ("models/weapons/v_laser.md3");
+		precache_model ("models/weapons/h_laser.iqm");
+		precache_sound ("weapons/lasergun_fire.wav");
+		precache_sound ("weapons/gauntlet_fire.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_LASER);
+		self.current_ammo = ammo_none;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		return TRUE;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		return TRUE;
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(0, autocvar_g_balance_laser_reload_ammo, autocvar_g_balance_laser_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_LASER_SUICIDE;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		return WEAPON_LASER_MURDER;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_laser(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 6;
+		pointparticles(particleeffectnum("laser_impact"), org2, w_backoff * 1000, 1);
+		if(!w_issilent)
+			sound(self, CH_SHOTS, "weapons/laserimpact.wav", VOL_BASE, ATTEN_NORM);
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/laserimpact.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_laser.qh b/qcsrc/server/w_laser.qh
new file mode 100644
index 000000000..0f2c13703
--- /dev/null
+++ b/qcsrc/server/w_laser.qh
@@ -0,0 +1,2 @@
+void LaserInit();
+vector gauntlet_shotorigin[4];
diff --git a/qcsrc/server/w_minstanex.qc b/qcsrc/server/w_minstanex.qc
new file mode 100644
index 000000000..9fb80c6d5
--- /dev/null
+++ b/qcsrc/server/w_minstanex.qc
@@ -0,0 +1,213 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ MINSTANEX,
+/* function  */ w_minstanex,
+/* ammotype  */ IT_CELLS,
+/* impulse   */ 7,
+/* flags     */ WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_FLAG_SUPERWEAPON | WEP_TYPE_HITSCAN,
+/* rating    */ BOT_PICKUP_RATING_HIGH,
+/* model     */ "minstanex",
+/* shortname */ "minstanex",
+/* fullname  */ _("MinstaNex")
+);
+#else
+#ifdef SVQC
+.float minstanex_lasthit;
+.float jump_interval;
+
+void W_MinstaNex_Attack (void)
+{
+	float flying;
+	flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+	W_SetupShot (self, TRUE, 0, "weapons/minstanexfire.wav", CH_WEAPON_A, 10000);
+
+	yoda = 0;
+	damage_goodhits = 0;
+	FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, 10000, 800, 0, 0, 0, 0, WEP_MINSTANEX);
+
+	if(yoda && flying)
+		Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
+	if(damage_goodhits && self.minstanex_lasthit)
+	{
+		Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+		damage_goodhits = 0; // only every second time
+	}
+
+	self.minstanex_lasthit = damage_goodhits;
+
+	pointparticles(particleeffectnum("nex_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	// teamcolor / hit beam effect
+	vector v;
+	v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+	switch(self.team)
+	{
+		case NUM_TEAM_1:   // Red
+			if(damage_goodhits)
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED_HIT"), w_shotorg, v);
+			else
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3RED"), w_shotorg, v);
+			break;
+		case NUM_TEAM_2:   // Blue
+			if(damage_goodhits)
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE_HIT"), w_shotorg, v);
+			else
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3BLUE"), w_shotorg, v);
+			break;
+		case NUM_TEAM_3:   // Yellow
+			if(damage_goodhits)
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW_HIT"), w_shotorg, v);
+			else
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3YELLOW"), w_shotorg, v);
+			break;
+		case NUM_TEAM_4:   // Pink
+			if(damage_goodhits)
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK_HIT"), w_shotorg, v);
+			else
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3PINK"), w_shotorg, v);
+			break;
+		default:
+			if(damage_goodhits)
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3_HIT"), w_shotorg, v);
+			else
+				WarpZone_TrailParticles(world, particleeffectnum("TE_TEI_G3"), w_shotorg, v);
+			break;
+	}
+
+	W_DecreaseAmmo(ammo_cells, ((g_minstagib) ? 1 : autocvar_g_balance_minstanex_ammo), autocvar_g_balance_minstanex_reload_ammo);
+}
+
+void spawnfunc_weapon_minstanex (void); // defined in t_items.qc
+
+float w_minstanex(float req)
+{
+	float ammo_amount;
+	float minstanex_ammo;
+
+	// now multiple WR_s use this
+	minstanex_ammo = ((g_minstagib) ? 1 : autocvar_g_balance_minstanex_ammo);
+
+	if (req == WR_AIM)
+	{
+		if(self.ammo_cells > 0)
+			self.BUTTON_ATCK = bot_aim(1000000, 0, 1, FALSE);
+		else
+			self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_laser_primary_speed, 0, autocvar_g_balance_laser_primary_lifetime, FALSE);
+	}
+	else if (req == WR_THINK)
+	{
+		// if the laser uses load, we also consider its ammo for reloading
+		if(autocvar_g_balance_minstanex_reload_ammo && autocvar_g_balance_minstanex_laser_ammo && self.clip_load < min(minstanex_ammo, autocvar_g_balance_minstanex_laser_ammo)) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+		else if(autocvar_g_balance_minstanex_reload_ammo && self.clip_load < minstanex_ammo) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+		else if (self.BUTTON_ATCK)
+		{
+			if (weapon_prepareattack(0, autocvar_g_balance_minstanex_refire))
+			{
+				W_MinstaNex_Attack();
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_minstanex_animtime, w_ready);
+			}
+		}
+		else if (self.BUTTON_ATCK2)
+		{
+			if (self.jump_interval <= time)
+			if (weapon_prepareattack(1, -1))
+			{
+				// handle refire manually, so that primary and secondary can be fired without conflictions (important for minstagib)
+				self.jump_interval = time + autocvar_g_balance_minstanex_laser_refire * W_WeaponRateFactor();
+
+				// decrease ammo for the laser?
+				if(autocvar_g_balance_minstanex_laser_ammo)
+					W_DecreaseAmmo(ammo_cells, autocvar_g_balance_minstanex_laser_ammo, autocvar_g_balance_minstanex_reload_ammo);
+
+				// ugly minstagib hack to reuse the fire mode of the laser
+				float w;
+				w = self.weapon;
+				self.weapon = WEP_LASER;
+				W_Laser_Attack(2);
+				self.weapon = w;
+
+				// now do normal refire
+				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_minstanex_laser_animtime, w_ready);
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/nexflash.md3");
+		precache_model ("models/weapons/g_minstanex.md3");
+		precache_model ("models/weapons/v_minstanex.md3");
+		precache_model ("models/weapons/h_minstanex.iqm");
+		precache_sound ("weapons/minstanexfire.wav");
+		precache_sound ("weapons/nexwhoosh1.wav");
+		precache_sound ("weapons/nexwhoosh2.wav");
+		precache_sound ("weapons/nexwhoosh3.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+		w_laser(WR_PRECACHE);
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_MINSTANEX);
+		self.current_ammo = ammo_cells;
+		self.minstanex_lasthit = 0;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		ammo_amount = self.ammo_cells >= minstanex_ammo;
+		ammo_amount += self.(weapon_load[WEP_MINSTANEX]) >= minstanex_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		if(!autocvar_g_balance_minstanex_laser_ammo)
+			return TRUE;
+		ammo_amount = self.ammo_cells >= autocvar_g_balance_minstanex_laser_ammo;
+		ammo_amount += self.(weapon_load[WEP_MINSTANEX]) >= autocvar_g_balance_minstanex_laser_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_RESETPLAYER)
+	{
+		self.minstanex_lasthit = 0;
+	}
+	else if (req == WR_RELOAD)
+	{
+		float used_ammo;
+		if(autocvar_g_balance_minstanex_laser_ammo)
+			used_ammo = min(minstanex_ammo, autocvar_g_balance_minstanex_laser_ammo);
+		else
+			used_ammo = minstanex_ammo;
+
+		W_Reload(used_ammo, autocvar_g_balance_minstanex_reload_ammo, autocvar_g_balance_minstanex_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_THINKING_WITH_PORTALS;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		return WEAPON_MINSTANEX_MURDER;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_minstanex(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 6;
+		pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1);
+		if(!w_issilent)
+			sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTEN_NORM);
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/neximpact.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_nex.qc b/qcsrc/server/w_nex.qc
new file mode 100644
index 000000000..919e27e5a
--- /dev/null
+++ b/qcsrc/server/w_nex.qc
@@ -0,0 +1,275 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ NEX,
+/* function  */ w_nex,
+/* ammotype  */ IT_CELLS,
+/* impulse   */ 7,
+/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
+/* rating    */ BOT_PICKUP_RATING_HIGH,
+/* model     */ "nex",
+/* shortname */ "nex",
+/* fullname  */ _("Nex")
+);
+#else
+#ifdef SVQC
+
+void SendCSQCNexBeamParticle(float charge) {
+	vector v;
+	v = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
+	WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
+	WriteByte(MSG_BROADCAST, TE_CSQC_NEXGUNBEAMPARTICLE);
+	WriteCoord(MSG_BROADCAST, w_shotorg_x);
+	WriteCoord(MSG_BROADCAST, w_shotorg_y);
+	WriteCoord(MSG_BROADCAST, w_shotorg_z);
+	WriteCoord(MSG_BROADCAST, v_x);
+	WriteCoord(MSG_BROADCAST, v_y);
+	WriteCoord(MSG_BROADCAST, v_z);
+	WriteByte(MSG_BROADCAST, bound(0, 255 * charge, 255));
+}
+
+void W_Nex_Attack (float issecondary)
+{
+	float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
+	if(issecondary)
+	{
+		mydmg = autocvar_g_balance_nex_secondary_damage;
+		myforce = autocvar_g_balance_nex_secondary_force;
+		mymindist = autocvar_g_balance_nex_secondary_damagefalloff_mindist;
+		mymaxdist = autocvar_g_balance_nex_secondary_damagefalloff_maxdist;
+		myhalflife = autocvar_g_balance_nex_secondary_damagefalloff_halflife;
+		myforcehalflife = autocvar_g_balance_nex_secondary_damagefalloff_forcehalflife;
+		myammo = autocvar_g_balance_nex_secondary_ammo;
+	}
+	else
+	{
+		mydmg = autocvar_g_balance_nex_primary_damage;
+		myforce = autocvar_g_balance_nex_primary_force;
+		mymindist = autocvar_g_balance_nex_primary_damagefalloff_mindist;
+		mymaxdist = autocvar_g_balance_nex_primary_damagefalloff_maxdist;
+		myhalflife = autocvar_g_balance_nex_primary_damagefalloff_halflife;
+		myforcehalflife = autocvar_g_balance_nex_primary_damagefalloff_forcehalflife;
+		myammo = autocvar_g_balance_nex_primary_ammo;
+	}
+
+	float flying;
+	flying = IsFlying(self); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+	if(autocvar_g_balance_nex_charge)
+	{
+		charge = autocvar_g_balance_nex_charge_mindmg / mydmg + (1 - autocvar_g_balance_nex_charge_mindmg / mydmg) * self.nex_charge;
+		self.nex_charge *= autocvar_g_balance_nex_charge_shot_multiplier; // do this AFTER setting mydmg/myforce
+		// O RLY? -- divVerent
+		// YA RLY -- FruitieX
+	}
+	else
+		charge = 1;
+	mydmg *= charge;
+	myforce *= charge;
+
+	W_SetupShot (self, TRUE, 5, "weapons/nexfire.wav", CH_WEAPON_A, mydmg);
+	if(charge > autocvar_g_balance_nex_charge_animlimit && autocvar_g_balance_nex_charge_animlimit) // if the Nex is overcharged, we play an extra sound
+	{
+		sound (self, CH_WEAPON_B, "weapons/nexcharge.wav", VOL_BASE * (charge - 0.5 * autocvar_g_balance_nex_charge_animlimit) / (1 - 0.5 * autocvar_g_balance_nex_charge_animlimit), ATTEN_NORM);
+	}
+
+	yoda = 0;
+	FireRailgunBullet (w_shotorg, w_shotorg + w_shotdir * MAX_SHOT_DISTANCE, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_NEX);
+
+	if(yoda && flying)
+		Send_Notification(NOTIF_ONE, self, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
+
+	//beam and muzzle flash done on client
+	SendCSQCNexBeamParticle(charge);
+
+	W_DecreaseAmmo(ammo_cells, myammo, autocvar_g_balance_nex_reload_ammo);
+}
+
+void spawnfunc_weapon_nex (void); // defined in t_items.qc
+
+.float nex_chargepool_pauseregen_finished;
+float w_nex(float req)
+{
+	float dt;
+	float ammo_amount;
+	if (req == WR_AIM)
+	{
+		if(bot_aim(1000000, 0, 1, FALSE))
+			self.BUTTON_ATCK = TRUE;
+		else
+		{
+			if(autocvar_g_balance_nex_charge)
+				self.BUTTON_ATCK2 = TRUE;
+		}
+	}
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_nex_charge && self.nex_charge < autocvar_g_balance_nex_charge_limit)
+			self.nex_charge = min(1, self.nex_charge + autocvar_g_balance_nex_charge_rate * frametime / W_TICSPERFRAME);
+
+		if(autocvar_g_balance_nex_secondary_chargepool)
+			if(self.nex_chargepool_ammo < 1)
+			{
+				if(self.nex_chargepool_pauseregen_finished < time)
+					self.nex_chargepool_ammo = min(1, self.nex_chargepool_ammo + autocvar_g_balance_nex_secondary_chargepool_regen * frametime / W_TICSPERFRAME);
+				self.pauseregen_finished = max(self.pauseregen_finished, time + autocvar_g_balance_nex_secondary_chargepool_pause_health_regen);
+			}
+
+		if(autocvar_g_balance_nex_reload_ammo && self.clip_load < min(autocvar_g_balance_nex_primary_ammo, autocvar_g_balance_nex_secondary_ammo)) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+		else
+		{
+			if (self.BUTTON_ATCK)
+			{
+				if (weapon_prepareattack(0, autocvar_g_balance_nex_primary_refire))
+				{
+					W_Nex_Attack(0);
+					weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_primary_animtime, w_ready);
+				}
+			}
+			if ((autocvar_g_balance_nex_secondary_charge && !autocvar_g_balance_nex_secondary) ? (self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) : self.BUTTON_ATCK2)
+			{
+				if(autocvar_g_balance_nex_secondary_charge)
+				{
+					self.nex_charge_rottime = time + autocvar_g_balance_nex_charge_rot_pause;
+					dt = frametime / W_TICSPERFRAME;
+
+					if(self.nex_charge < 1)
+					{
+						if(autocvar_g_balance_nex_secondary_chargepool)
+						{
+							if(autocvar_g_balance_nex_secondary_ammo)
+							{
+								// always deplete if secondary is held
+								self.nex_chargepool_ammo = max(0, self.nex_chargepool_ammo - autocvar_g_balance_nex_secondary_ammo * dt);
+
+								dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate);
+								self.nex_chargepool_pauseregen_finished = time + autocvar_g_balance_nex_secondary_chargepool_pause_regen;
+								dt = min(dt, self.nex_chargepool_ammo);
+								dt = max(0, dt);
+
+								self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate;
+							}
+						}
+
+						else if(autocvar_g_balance_nex_secondary_ammo)
+						{
+							if(self.BUTTON_ATCK2) // only eat ammo when the button is pressed
+							{
+								dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate);
+								if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+								{
+									// if this weapon is reloadable, decrease its load. Else decrease the player's ammo
+									if(autocvar_g_balance_nex_reload_ammo)
+									{
+										dt = min(dt, (self.clip_load - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo);
+										dt = max(0, dt);
+										if(dt > 0)
+										{
+											self.clip_load = max(autocvar_g_balance_nex_secondary_ammo, self.clip_load - autocvar_g_balance_nex_secondary_ammo * dt);
+										}
+										self.(weapon_load[WEP_NEX]) = self.clip_load;
+									}
+									else
+									{
+										dt = min(dt, (self.ammo_cells - autocvar_g_balance_nex_primary_ammo) / autocvar_g_balance_nex_secondary_ammo);
+										dt = max(0, dt);
+										if(dt > 0)
+										{
+											self.ammo_cells = max(autocvar_g_balance_nex_secondary_ammo, self.ammo_cells - autocvar_g_balance_nex_secondary_ammo * dt);
+										}
+									}
+								}
+								self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate;
+							}
+						}
+
+						else
+						{
+							dt = min(dt, (1 - self.nex_charge) / autocvar_g_balance_nex_secondary_charge_rate);
+							self.nex_charge += dt * autocvar_g_balance_nex_secondary_charge_rate;
+						}
+					}
+				}
+				else if(autocvar_g_balance_nex_secondary)
+				{
+					if (weapon_prepareattack(0, autocvar_g_balance_nex_secondary_refire))
+					{
+						W_Nex_Attack(1);
+						weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_nex_secondary_animtime, w_ready);
+					}
+				}
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/nexflash.md3");
+		precache_model ("models/weapons/g_nex.md3");
+		precache_model ("models/weapons/v_nex.md3");
+		precache_model ("models/weapons/h_nex.iqm");
+		precache_sound ("weapons/nexfire.wav");
+		precache_sound ("weapons/nexcharge.wav");
+		precache_sound ("weapons/nexwhoosh1.wav");
+		precache_sound ("weapons/nexwhoosh2.wav");
+		precache_sound ("weapons/nexwhoosh3.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_NEX);
+		self.current_ammo = ammo_cells;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_primary_ammo;
+		ammo_amount += (autocvar_g_balance_nex_reload_ammo && self.(weapon_load[WEP_NEX]) >= autocvar_g_balance_nex_primary_ammo);
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		if(autocvar_g_balance_nex_secondary)
+		{
+			// don't allow charging if we don't have enough ammo
+			ammo_amount = self.ammo_cells >= autocvar_g_balance_nex_secondary_ammo;
+			ammo_amount += self.(weapon_load[WEP_NEX]) >= autocvar_g_balance_nex_secondary_ammo;
+			return ammo_amount;
+		}
+		else
+		{
+			return FALSE; // zoom is not a fire mode
+		}
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(min(autocvar_g_balance_nex_primary_ammo, autocvar_g_balance_nex_secondary_ammo), autocvar_g_balance_nex_reload_ammo, autocvar_g_balance_nex_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_THINKING_WITH_PORTALS;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		return WEAPON_NEX_MURDER;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_nex(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 6;
+		pointparticles(particleeffectnum("nex_impact"), org2, '0 0 0', 1);
+		if(!w_issilent)
+			sound(self, CH_SHOTS, "weapons/neximpact.wav", VOL_BASE, ATTEN_NORM);
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/neximpact.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_porto.qc b/qcsrc/server/w_porto.qc
new file mode 100644
index 000000000..1eb0f4b0b
--- /dev/null
+++ b/qcsrc/server/w_porto.qc
@@ -0,0 +1,391 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ PORTO,
+/* function  */ w_porto,
+/* ammotype  */ 0,
+/* impulse   */ 0,
+/* flags     */ WEP_TYPE_OTHER | WEP_FLAG_SUPERWEAPON,
+/* rating    */ 0,
+/* model     */ "porto" ,
+/* shortname */ "porto",
+/* fullname  */ _("Port-O-Launch")
+);
+#else
+#ifdef SVQC
+.entity porto_current;
+.vector porto_v_angle; // holds "held" view angles
+.float porto_v_angle_held;
+.vector right_vector;
+
+void W_Porto_Success (void)
+{
+	if(self.realowner == world)
+	{
+		objerror("Cannot succeed successfully: no owner\n");
+		return;
+	}
+
+	self.realowner.porto_current = world;
+	remove(self);
+}
+
+string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
+void W_Porto_Fail (float failhard)
+{
+	if(self.realowner == world)
+	{
+		objerror("Cannot fail successfully: no owner\n");
+		return;
+	}
+
+	// no portals here!
+	if(self.cnt < 0)
+	{
+		Portal_ClearWithID(self.realowner, self.portal_id);
+	}
+
+	self.realowner.porto_current = world;
+
+	if(self.cnt < 0 && !failhard && self.realowner.playerid == self.playerid && self.realowner.deadflag == DEAD_NO && !(self.realowner.weapons & WEPSET_PORTO))
+	{
+		setsize (self, '-16 -16 0', '16 16 32');
+		setorigin(self, self.origin + trace_plane_normal);
+		if(move_out_of_solid(self))
+		{
+			self.flags = FL_ITEM;
+			self.velocity = trigger_push_calculatevelocity(self.origin, self.realowner, 128);
+			tracetoss(self, self);
+			if(vlen(trace_endpos - self.realowner.origin) < 128)
+			{
+				W_ThrowNewWeapon(self.realowner, WEP_PORTO, 0, self.origin, self.velocity);
+				centerprint(self.realowner, "^1Portal deployment failed.\n\n^2Catch it to try again!");
+			}
+		}
+	}
+	remove(self);
+}
+
+void W_Porto_Remove (entity p)
+{
+	if(p.porto_current.realowner == p && p.porto_current.classname == "porto")
+	{
+		entity oldself;
+		oldself = self;
+		self = p.porto_current;
+		W_Porto_Fail(1);
+		self = oldself;
+	}
+}
+
+void W_Porto_Think (void)
+{
+	trace_plane_normal = '0 0 0';
+	if(self.realowner.playerid != self.playerid)
+		remove(self);
+	else
+		W_Porto_Fail(0);
+}
+
+void W_Porto_Touch (void)
+{
+	vector norm;
+
+	// do not use PROJECTILE_TOUCH here
+	// FIXME but DO handle warpzones!
+
+	if(other.classname == "portal")
+		return; // handled by the portal
+
+	norm = trace_plane_normal;
+	if(trace_ent.iscreature)
+	{
+		traceline(trace_ent.origin, trace_ent.origin + '0 0 2' * PL_MIN_z, MOVE_WORLDONLY, self);
+		if(trace_fraction >= 1)
+			return;
+		if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+			return;
+		if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+			return;
+	}
+
+	if(self.realowner.playerid != self.playerid)
+	{
+		sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+		remove(self);
+	}
+	else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK || trace_dphitcontents & DPCONTENTS_PLAYERCLIP)
+	{
+		spamsound(self, CH_SHOTS, "porto/bounce.wav", VOL_BASE, ATTEN_NORM);
+		// just reflect
+		self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * trace_plane_normal);
+		self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * trace_plane_normal));
+	}
+	else if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
+	{
+		sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+		W_Porto_Fail(0);
+		if(self.cnt < 0)
+			Portal_ClearAll_PortalsOnly(self.realowner);
+	}
+	else if(self.cnt == 0)
+	{
+		// in-portal only
+		if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
+		{
+			sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+			trace_plane_normal = norm;
+			centerprint(self.realowner, "^1In^7-portal created.");
+			W_Porto_Success();
+		}
+		else
+		{
+			sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+			trace_plane_normal = norm;
+			W_Porto_Fail(0);
+		}
+	}
+	else if(self.cnt == 1)
+	{
+		// out-portal only
+		if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
+		{
+			sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+			trace_plane_normal = norm;
+			centerprint(self.realowner, "^4Out^7-portal created.");
+			W_Porto_Success();
+		}
+		else
+		{
+			sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+			trace_plane_normal = norm;
+			W_Porto_Fail(0);
+		}
+	}
+	else if(self.effects & EF_RED)
+	{
+		self.effects += EF_BLUE - EF_RED;
+		if(Portal_SpawnInPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
+		{
+			sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+			trace_plane_normal = norm;
+			centerprint(self.realowner, "^1In^7-portal created.");
+			self.right_vector = self.right_vector - 2 * trace_plane_normal * (self.right_vector * norm);
+			self.angles = vectoangles(self.velocity - 2 * trace_plane_normal * (self.velocity * norm));
+			CSQCProjectile(self, TRUE, PROJECTILE_PORTO_BLUE, TRUE); // change type
+		}
+		else
+		{
+			sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+			trace_plane_normal = norm;
+			Portal_ClearAll_PortalsOnly(self.realowner);
+			W_Porto_Fail(0);
+		}
+	}
+	else
+	{
+		if(self.realowner.portal_in.portal_id == self.portal_id)
+		{
+			if(Portal_SpawnOutPortalAtTrace(self.realowner, self.right_vector, self.portal_id))
+			{
+				sound(self, CH_SHOTS, "porto/create.wav", VOL_BASE, ATTEN_NORM);
+				trace_plane_normal = norm;
+				centerprint(self.realowner, "^4Out^7-portal created.");
+				W_Porto_Success();
+			}
+			else
+			{
+				sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+				Portal_ClearAll_PortalsOnly(self.realowner);
+				W_Porto_Fail(0);
+			}
+		}
+		else
+		{
+			sound(self, CH_SHOTS, "porto/unsupported.wav", VOL_BASE, ATTEN_NORM);
+			Portal_ClearAll_PortalsOnly(self.realowner);
+			W_Porto_Fail(0);
+		}
+	}
+}
+
+void W_Porto_Attack (float type)
+{
+	entity gren;
+
+	W_SetupShot (self, FALSE, 4, "porto/fire.wav", CH_WEAPON_A, 0);
+	// always shoot from the eye
+	w_shotdir = v_forward;
+	w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
+
+	//pointparticles(particleeffectnum("grenadelauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	gren = spawn ();
+	gren.cnt = type;
+	gren.owner = gren.realowner = self;
+	gren.playerid = self.playerid;
+	gren.classname = "porto";
+	gren.bot_dodge = TRUE;
+	gren.bot_dodgerating = 200;
+	gren.movetype = MOVETYPE_BOUNCEMISSILE;
+	PROJECTILE_MAKETRIGGER(gren);
+	gren.effects = EF_RED;
+	gren.scale = 4;
+	setorigin(gren, w_shotorg);
+	setsize(gren, '0 0 0', '0 0 0');
+
+	if(type > 0)
+		gren.nextthink = time + autocvar_g_balance_porto_secondary_lifetime;
+	else
+		gren.nextthink = time + autocvar_g_balance_porto_primary_lifetime;
+	gren.think = W_Porto_Think;
+	gren.touch = W_Porto_Touch;
+
+	if(type > 0)
+	{
+		if(self.items & IT_STRENGTH)
+			W_SetupProjectileVelocity(gren, autocvar_g_balance_porto_secondary_speed * autocvar_g_balance_powerup_strength_force, 0);
+		else
+			W_SetupProjectileVelocity(gren, autocvar_g_balance_porto_secondary_speed, 0);
+	}
+	else
+	{
+		if(self.items & IT_STRENGTH)
+			W_SetupProjectileVelocity(gren, autocvar_g_balance_porto_primary_speed * autocvar_g_balance_powerup_strength_force, 0);
+		else
+			W_SetupProjectileVelocity(gren, autocvar_g_balance_porto_primary_speed, 0);
+	}
+
+	gren.angles = vectoangles (gren.velocity);
+	gren.flags = FL_PROJECTILE;
+
+	gren.portal_id = time;
+	self.porto_current = gren;
+	gren.playerid = self.playerid;
+	fixedmakevectors(fixedvectoangles(gren.velocity));
+	gren.right_vector = v_right;
+
+	gren.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
+
+	if(type > 0)
+		CSQCProjectile(gren, TRUE, PROJECTILE_PORTO_BLUE, TRUE);
+	else
+		CSQCProjectile(gren, TRUE, PROJECTILE_PORTO_RED, TRUE);
+
+	other = gren; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void spawnfunc_weapon_porto (void)
+{
+	weapon_defaultspawnfunc(WEP_PORTO);
+}
+
+float w_nexball_weapon(float req);
+float w_porto(float req)
+{
+	//vector v_angle_save;
+
+	if (g_nexball) { return w_nexball_weapon(req); }
+	if (req == WR_AIM)
+	{
+		self.BUTTON_ATCK = FALSE;
+		self.BUTTON_ATCK2 = FALSE;
+		if(!autocvar_g_balance_porto_secondary)
+			if(bot_aim(autocvar_g_balance_porto_primary_speed, 0, autocvar_g_balance_grenadelauncher_primary_lifetime, FALSE))
+				self.BUTTON_ATCK = TRUE;
+	}
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_porto_secondary)
+		{
+			if (self.BUTTON_ATCK)
+			if (!self.porto_current)
+			if (!self.porto_forbidden)
+			if (weapon_prepareattack(0, autocvar_g_balance_porto_primary_refire))
+			{
+				W_Porto_Attack(0);
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_porto_primary_animtime, w_ready);
+			}
+
+			if (self.BUTTON_ATCK2)
+			if (!self.porto_current)
+			if (!self.porto_forbidden)
+			if (weapon_prepareattack(1, autocvar_g_balance_porto_secondary_refire))
+			{
+				W_Porto_Attack(1);
+				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_porto_secondary_animtime, w_ready);
+			}
+		}
+		else
+		{
+			if(self.porto_v_angle_held)
+			{
+				if(!self.BUTTON_ATCK2)
+				{
+					self.porto_v_angle_held = 0;
+
+					ClientData_Touch(self);
+				}
+			}
+			else
+			{
+				if(self.BUTTON_ATCK2)
+				{
+					self.porto_v_angle = self.v_angle;
+					self.porto_v_angle_held = 1;
+
+					ClientData_Touch(self);
+				}
+			}
+			if(self.porto_v_angle_held)
+				makevectors(self.porto_v_angle); // override the previously set angles
+
+			if (self.BUTTON_ATCK)
+			if (!self.porto_current)
+			if (!self.porto_forbidden)
+			if (weapon_prepareattack(0, autocvar_g_balance_porto_primary_refire))
+			{
+				W_Porto_Attack(-1);
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_porto_primary_animtime, w_ready);
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_porto.md3");
+		precache_model ("models/weapons/v_porto.md3");
+		precache_model ("models/weapons/h_porto.iqm");
+		precache_model ("models/portal.md3");
+		precache_sound ("porto/bounce.wav");
+		precache_sound ("porto/create.wav");
+		precache_sound ("porto/expire.wav");
+		precache_sound ("porto/explode.wav");
+		precache_sound ("porto/fire.wav");
+		precache_sound ("porto/unsupported.wav");
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_PORTO);
+		self.current_ammo = ammo_none;
+	}
+	else if (req == WR_RESETPLAYER)
+	{
+		self.porto_current = world;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_porto(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		print("Since when does Porto send DamageInfo?\n");
+	}
+	else if(req == WR_PRECACHE)
+	{
+		// nothing to do
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_rifle.qc b/qcsrc/server/w_rifle.qc
new file mode 100644
index 000000000..0e3a5c0b0
--- /dev/null
+++ b/qcsrc/server/w_rifle.qc
@@ -0,0 +1,264 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ RIFLE,
+/* function  */ w_rifle,
+/* ammotype  */ IT_NAILS,
+/* impulse   */ 7,
+/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
+/* rating    */ BOT_PICKUP_RATING_MID,
+/* model     */ "campingrifle",
+/* shortname */ "rifle",
+/* fullname  */ _("Rifle")
+);
+#else
+#ifdef SVQC
+
+.float rifle_accumulator;
+
+void W_Rifle_FireBullet(float pSpread, float pDamage, float pForce, float pSolidPenetration, float pAmmo, float deathtype, float pTracer, float pShots, string pSound)
+{
+	float i;
+
+	W_DecreaseAmmo(ammo_nails, pAmmo, autocvar_g_balance_rifle_reload_ammo);
+
+	W_SetupShot (self, TRUE, 2, pSound, CH_WEAPON_A, pDamage * pShots);
+
+	pointparticles(particleeffectnum("rifle_muzzleflash"), w_shotorg, w_shotdir * 2000, 1);
+
+	if(self.BUTTON_ZOOM | self.BUTTON_ZOOMSCRIPT) // if zoomed, shoot from the eye
+	{
+		w_shotdir = v_forward;
+		w_shotorg = self.origin + self.view_ofs + ((w_shotorg - self.origin - self.view_ofs) * v_forward) * v_forward;
+	}
+
+	for(i = 0; i < pShots; ++i)
+		fireBullet(w_shotorg, w_shotdir, pSpread, pSolidPenetration, pDamage, pForce, deathtype, (pTracer ? EF_RED : EF_BLUE));
+
+	if (autocvar_g_casings >= 2)
+		SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
+}
+
+void W_Rifle_Attack()
+{
+	W_Rifle_FireBullet(autocvar_g_balance_rifle_primary_spread, autocvar_g_balance_rifle_primary_damage, autocvar_g_balance_rifle_primary_force, autocvar_g_balance_rifle_primary_solidpenetration, autocvar_g_balance_rifle_primary_ammo, WEP_RIFLE, autocvar_g_balance_rifle_primary_tracer, autocvar_g_balance_rifle_primary_shots, "weapons/campingrifle_fire.wav");
+}
+
+void W_Rifle_Attack2()
+{
+	W_Rifle_FireBullet(autocvar_g_balance_rifle_secondary_spread, autocvar_g_balance_rifle_secondary_damage, autocvar_g_balance_rifle_secondary_force, autocvar_g_balance_rifle_secondary_solidpenetration, autocvar_g_balance_rifle_secondary_ammo, WEP_RIFLE | HITTYPE_SECONDARY, autocvar_g_balance_rifle_secondary_tracer, autocvar_g_balance_rifle_secondary_shots, "weapons/campingrifle_fire2.wav");
+}
+
+void spawnfunc_weapon_rifle (void)
+{
+	weapon_defaultspawnfunc(WEP_RIFLE);
+}
+
+// compatibility alias
+void spawnfunc_weapon_campingrifle (void)
+{
+	spawnfunc_weapon_rifle();
+}
+void spawnfunc_weapon_sniperrifle (void)
+{
+	spawnfunc_weapon_rifle();
+}
+
+.void(void) rifle_bullethail_attackfunc;
+.float rifle_bullethail_frame;
+.float rifle_bullethail_animtime;
+.float rifle_bullethail_refire;
+void W_Rifle_BulletHail_Continue()
+{
+	float r, sw, af;
+
+	sw = self.switchweapon; // make it not detect weapon changes as reason to abort firing
+	af = ATTACK_FINISHED(self);
+	self.switchweapon = self.weapon;
+	ATTACK_FINISHED(self) = time;
+	print(ftos(self.ammo_nails), "\n");
+	r = weapon_prepareattack(self.rifle_bullethail_frame == WFRAME_FIRE2, self.rifle_bullethail_refire);
+	if(self.switchweapon == self.weapon)
+		self.switchweapon = sw;
+	if(r)
+	{
+		self.rifle_bullethail_attackfunc();
+		weapon_thinkf(self.rifle_bullethail_frame, self.rifle_bullethail_animtime, W_Rifle_BulletHail_Continue);
+		print("thinkf set\n");
+	}
+	else
+	{
+		ATTACK_FINISHED(self) = af; // reset attack_finished if we didn't fire, so the last shot enforces the refire time
+		print("out of ammo... ", ftos(self.weaponentity.state), "\n");
+	}
+}
+
+void W_Rifle_BulletHail(float mode, void(void) AttackFunc, float fr, float animtime, float refire)
+{
+	// if we get here, we have at least one bullet to fire
+	AttackFunc();
+	if(mode)
+	{
+		// continue hail
+		self.rifle_bullethail_attackfunc = AttackFunc;
+		self.rifle_bullethail_frame = fr;
+		self.rifle_bullethail_animtime = animtime;
+		self.rifle_bullethail_refire = refire;
+		weapon_thinkf(fr, animtime, W_Rifle_BulletHail_Continue);
+	}
+	else
+	{
+		// just one shot
+		weapon_thinkf(fr, animtime, w_ready);
+	}
+}
+
+.float bot_secondary_riflemooth;
+float w_rifle(float req)
+{
+	float ammo_amount;
+
+	if (req == WR_AIM)
+	{
+		self.BUTTON_ATCK=FALSE;
+		self.BUTTON_ATCK2=FALSE;
+		if(vlen(self.origin-self.enemy.origin) > 1000)
+			self.bot_secondary_riflemooth = 0;
+		if(self.bot_secondary_riflemooth == 0)
+		{
+			if(bot_aim(1000000, 0, 0.001, FALSE))
+			{
+				self.BUTTON_ATCK = TRUE;
+				if(random() < 0.01) self.bot_secondary_riflemooth = 1;
+			}
+		}
+		else
+		{
+			if(bot_aim(1000000, 0, 0.001, FALSE))
+			{
+				self.BUTTON_ATCK2 = TRUE;
+				if(random() < 0.03) self.bot_secondary_riflemooth = 0;
+			}
+		}
+	}
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_rifle_reload_ammo && self.clip_load < min(autocvar_g_balance_rifle_primary_ammo, autocvar_g_balance_rifle_secondary_ammo)) // forced reload
+            weapon_action(self.weapon, WR_RELOAD);
+		else
+		{
+			self.rifle_accumulator = bound(time - autocvar_g_balance_rifle_bursttime, self.rifle_accumulator, time);
+			if (self.BUTTON_ATCK)
+			if (weapon_prepareattack_check(0, autocvar_g_balance_rifle_primary_refire))
+			if (time >= self.rifle_accumulator + autocvar_g_balance_rifle_primary_burstcost)
+			{
+				weapon_prepareattack_do(0, autocvar_g_balance_rifle_primary_refire);
+				W_Rifle_BulletHail(autocvar_g_balance_rifle_primary_bullethail, W_Rifle_Attack, WFRAME_FIRE1, autocvar_g_balance_rifle_primary_animtime, autocvar_g_balance_rifle_primary_refire);
+				self.rifle_accumulator += autocvar_g_balance_rifle_primary_burstcost;
+			}
+			if (self.BUTTON_ATCK2)
+			{
+				if (autocvar_g_balance_rifle_secondary)
+				{
+                    if(autocvar_g_balance_rifle_secondary_reload)
+                        weapon_action(self.weapon, WR_RELOAD);
+                    else
+                    {
+                        if (weapon_prepareattack_check(1, autocvar_g_balance_rifle_secondary_refire))
+                        if (time >= self.rifle_accumulator + autocvar_g_balance_rifle_secondary_burstcost)
+                        {
+                            weapon_prepareattack_do(1, autocvar_g_balance_rifle_secondary_refire);
+                            W_Rifle_BulletHail(autocvar_g_balance_rifle_secondary_bullethail, W_Rifle_Attack2, WFRAME_FIRE2, autocvar_g_balance_rifle_secondary_animtime, autocvar_g_balance_rifle_primary_refire);
+                            self.rifle_accumulator += autocvar_g_balance_rifle_secondary_burstcost;
+                        }
+                    }
+				}
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_campingrifle.md3");
+		precache_model ("models/weapons/v_campingrifle.md3");
+		precache_model ("models/weapons/h_campingrifle.iqm");
+		precache_sound ("weapons/campingrifle_fire.wav");
+		precache_sound ("weapons/campingrifle_fire2.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_RIFLE);
+		self.current_ammo = ammo_nails;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		ammo_amount = self.ammo_nails >= autocvar_g_balance_rifle_primary_ammo;
+		ammo_amount += self.(weapon_load[WEP_RIFLE]) >= autocvar_g_balance_rifle_primary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		ammo_amount = self.ammo_nails >= autocvar_g_balance_rifle_secondary_ammo;
+		ammo_amount += self.(weapon_load[WEP_RIFLE]) >= autocvar_g_balance_rifle_secondary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_RESETPLAYER)
+	{
+		self.rifle_accumulator = time - autocvar_g_balance_rifle_bursttime;
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(min(autocvar_g_balance_rifle_primary_ammo, autocvar_g_balance_rifle_secondary_ammo), autocvar_g_balance_rifle_reload_ammo, autocvar_g_balance_rifle_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_THINKING_WITH_PORTALS;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+		{
+			if(w_deathtype & HITTYPE_BOUNCE)
+				return WEAPON_RIFLE_MURDER_HAIL_PIERCING;
+			else
+				return WEAPON_RIFLE_MURDER_HAIL;
+		}
+		else
+		{
+			if(w_deathtype & HITTYPE_BOUNCE)
+				return WEAPON_RIFLE_MURDER_PIERCING;
+			else
+				return WEAPON_RIFLE_MURDER;
+		}
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_rifle(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 2;
+		pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1);
+		if(!w_issilent)
+		{
+			if(w_random < 0.2)
+				sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_NORM);
+			else if(w_random < 0.4)
+				sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTEN_NORM);
+			else if(w_random < 0.5)
+				sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTEN_NORM);
+		}
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/ric1.wav");
+		precache_sound("weapons/ric2.wav");
+		precache_sound("weapons/ric3.wav");
+	}
+
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_rocketlauncher.qc b/qcsrc/server/w_rocketlauncher.qc
new file mode 100644
index 000000000..6cd8929f6
--- /dev/null
+++ b/qcsrc/server/w_rocketlauncher.qc
@@ -0,0 +1,491 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ ROCKET_LAUNCHER,
+/* function  */ w_rlauncher,
+/* ammotype  */ IT_ROCKETS,
+/* impulse   */ 9,
+/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_FLAG_CANCLIMB | WEP_TYPE_SPLASH,
+/* rating    */ BOT_PICKUP_RATING_HIGH,
+/* model     */ "rl",
+/* shortname */ "rocketlauncher",
+/* fullname  */ _("Rocket Launcher")
+);
+#else
+#ifdef SVQC
+.float rl_release;
+.float rl_detonate_later;
+
+void W_Rocket_Unregister()
+{
+	if(self.realowner && self.realowner.lastrocket == self)
+	{
+		self.realowner.lastrocket = world;
+		// self.realowner.rl_release = 1;
+	}
+}
+
+void W_Rocket_Explode ()
+{
+	W_Rocket_Unregister();
+
+	if(other.takedamage == DAMAGE_AIM)
+		if(IS_PLAYER(other))
+			if(DIFF_TEAM(self.realowner, other))
+				if(other.deadflag == DEAD_NO)
+					if(IsFlying(other))
+						Send_Notification(NOTIF_ONE, self.realowner, MSG_ANNCE, ANNCE_ACHIEVEMENT_AIRSHOT);
+
+	self.event_damage = func_null;
+	self.takedamage = DAMAGE_NO;
+
+	RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_damage, autocvar_g_balance_rocketlauncher_edgedamage, autocvar_g_balance_rocketlauncher_radius, world, autocvar_g_balance_rocketlauncher_force, self.projectiledeathtype, other);
+
+	if (self.realowner.weapon == WEP_ROCKET_LAUNCHER)
+	{
+		if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo)
+		{
+			self.realowner.cnt = WEP_ROCKET_LAUNCHER;
+			ATTACK_FINISHED(self.realowner) = time;
+			self.realowner.switchweapon = w_getbestweapon(self.realowner);
+		}
+	}
+	remove (self);
+}
+
+void W_Rocket_DoRemoteExplode ()
+{
+	W_Rocket_Unregister();
+
+	self.event_damage = func_null;
+	self.takedamage = DAMAGE_NO;
+
+	RadiusDamage (self, self.realowner, autocvar_g_balance_rocketlauncher_remote_damage, autocvar_g_balance_rocketlauncher_remote_edgedamage, autocvar_g_balance_rocketlauncher_remote_radius, world, autocvar_g_balance_rocketlauncher_remote_force, self.projectiledeathtype | HITTYPE_BOUNCE, world);
+
+	if (self.realowner.weapon == WEP_ROCKET_LAUNCHER)
+	{
+		if(self.realowner.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo)
+		{
+			self.realowner.cnt = WEP_ROCKET_LAUNCHER;
+			ATTACK_FINISHED(self.realowner) = time;
+			self.realowner.switchweapon = w_getbestweapon(self.realowner);
+		}
+	}
+	remove (self);
+}
+
+void W_Rocket_RemoteExplode()
+{
+	if(self.realowner.deadflag == DEAD_NO)
+	if(self.realowner.lastrocket)
+	{
+		if((self.spawnshieldtime >= 0)
+			? (time >= self.spawnshieldtime) // timer
+			: (vlen(NearestPointOnBox(self.realowner, self.origin) - self.origin) > autocvar_g_balance_rocketlauncher_remote_radius) // safety device
+		)
+		{
+			W_Rocket_DoRemoteExplode();
+		}
+	}
+}
+
+vector rocket_steerto(vector thisdir, vector goaldir, float maxturn_cos)
+{
+	if(thisdir * goaldir > maxturn_cos)
+		return goaldir;
+	if(thisdir * goaldir < -0.9998) // less than 1 degree and opposite
+		return thisdir; // refuse to guide (better than letting a numerical error happen)
+	float f, m2;
+	vector v;
+	// solve:
+	//   g = normalize(thisdir + goaldir * X)
+	//   thisdir * g = maxturn
+	//
+	//   gg = thisdir + goaldir * X
+	//   (thisdir * gg)^2 = maxturn^2 * (gg * gg)
+	//
+	//   (1 + (thisdir * goaldir) * X)^2 = maxturn^2 * (1 + X*X + 2 * X * thisdir * goaldir)
+	f = thisdir * goaldir;
+	//   (1 + f * X)^2 = maxturn^2 * (1 + X*X + 2 * X * f)
+	//   0 = (m^2 - f^2) * x^2 + (2 * f * (m^2 - 1)) * x + (m^2 - 1)
+	m2 = maxturn_cos * maxturn_cos;
+	v = solve_quadratic(m2 - f * f, 2 * f * (m2 - 1), m2 - 1);
+	return normalize(thisdir + goaldir * v_y); // the larger solution!
+}
+// assume thisdir == -goaldir:
+//   f == -1
+//   v = solve_qadratic(m2 - 1, -2 * (m2 - 1), m2 - 1)
+//   (m2 - 1) x^2 - 2 * (m2 - 1) * x + (m2 - 1) = 0
+//   x^2 - 2 * x + 1 = 0
+//   (x - 1)^2 = 0
+//   x = 1
+//   normalize(thisdir + goaldir)
+//   normalize(0)
+
+void W_Rocket_Think (void)
+{
+	vector desireddir, olddir, newdir, desiredorigin, goal;
+#if 0
+	float cosminang, cosmaxang, cosang;
+#endif
+	float velspeed, f;
+	self.nextthink = time;
+	if (time > self.cnt)
+	{
+		other = world;
+		self.projectiledeathtype |= HITTYPE_BOUNCE;
+		W_Rocket_Explode ();
+		return;
+	}
+
+	// accelerate
+	makevectors(self.angles_x * '-1 0 0' + self.angles_y * '0 1 0');
+	velspeed = autocvar_g_balance_rocketlauncher_speed * g_weaponspeedfactor - (self.velocity * v_forward);
+	if (velspeed > 0)
+		self.velocity = self.velocity + v_forward * min(autocvar_g_balance_rocketlauncher_speedaccel * g_weaponspeedfactor * frametime, velspeed);
+
+	// laser guided, or remote detonation
+	if (self.realowner.weapon == WEP_ROCKET_LAUNCHER)
+	{
+		if(self == self.realowner.lastrocket)
+		if (!self.realowner.rl_release)
+		if (!self.BUTTON_ATCK2)
+		if(autocvar_g_balance_rocketlauncher_guiderate)
+		if(time > self.pushltime)
+		if(self.realowner.deadflag == DEAD_NO)
+		{
+			f = autocvar_g_balance_rocketlauncher_guideratedelay;
+			if(f)
+				f = bound(0, (time - self.pushltime) / f, 1);
+			else
+				f = 1;
+
+			velspeed = vlen(self.velocity);
+
+			makevectors(self.realowner.v_angle);
+			desireddir = WarpZone_RefSys_TransformVelocity(self.realowner, self, v_forward);
+			desiredorigin = WarpZone_RefSys_TransformOrigin(self.realowner, self, self.realowner.origin + self.realowner.view_ofs);
+			olddir = normalize(self.velocity);
+
+			// now it gets tricky... we want to move like some curve to approximate the target direction
+			// but we are limiting the rate at which we can turn!
+			goal = desiredorigin + ((self.origin - desiredorigin) * desireddir + autocvar_g_balance_rocketlauncher_guidegoal) * desireddir;
+			newdir = rocket_steerto(olddir, normalize(goal - self.origin), cos(autocvar_g_balance_rocketlauncher_guiderate * f * frametime * DEG2RAD));
+
+			self.velocity = newdir * velspeed;
+			self.angles = vectoangles(self.velocity);
+
+			if(!self.count)
+			{
+				pointparticles(particleeffectnum("rocket_guide"), self.origin, self.velocity, 1);
+				// TODO add a better sound here
+				sound (self.realowner, CH_WEAPON_B, "weapons/rocket_mode.wav", VOL_BASE, ATTEN_NORM);
+				self.count = 1;
+			}
+		}
+
+		if(self.rl_detonate_later)
+			W_Rocket_RemoteExplode();
+	}
+
+	if(self.csqcprojectile_clientanimate == 0)
+		UpdateCSQCProjectile(self);
+}
+
+void W_Rocket_Touch (void)
+{
+	if(WarpZone_Projectile_Touch())
+	{
+		if(wasfreed(self))
+			W_Rocket_Unregister();
+		return;
+	}
+	W_Rocket_Unregister();
+	W_Rocket_Explode ();
+}
+
+void W_Rocket_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	if (self.health <= 0)
+		return;
+
+	if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+		return; // g_projectiles_damage says to halt
+
+	self.health = self.health - damage;
+	self.angles = vectoangles(self.velocity);
+
+	if (self.health <= 0)
+		W_PrepareExplosionByDamage(attacker, W_Rocket_Explode);
+}
+
+void W_Rocket_Attack (void)
+{
+	entity missile;
+	entity flash;
+
+	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo);
+
+	W_SetupShot_ProjectileSize (self, '-3 -3 -3', '3 3 3', FALSE, 5, "weapons/rocket_fire.wav", CH_WEAPON_A, autocvar_g_balance_rocketlauncher_damage);
+	pointparticles(particleeffectnum("rocketlauncher_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	missile = WarpZone_RefSys_SpawnSameRefSys(self);
+	missile.owner = missile.realowner = self;
+	self.lastrocket = missile;
+	if(autocvar_g_balance_rocketlauncher_detonatedelay >= 0)
+		missile.spawnshieldtime = time + autocvar_g_balance_rocketlauncher_detonatedelay;
+	else
+		missile.spawnshieldtime = -1;
+	missile.pushltime = time + autocvar_g_balance_rocketlauncher_guidedelay;
+	missile.classname = "rocket";
+	missile.bot_dodge = TRUE;
+	missile.bot_dodgerating = autocvar_g_balance_rocketlauncher_damage * 2; // * 2 because it can be detonated inflight which makes it even more dangerous
+
+	missile.takedamage = DAMAGE_YES;
+	missile.damageforcescale = autocvar_g_balance_rocketlauncher_damageforcescale;
+	missile.health = autocvar_g_balance_rocketlauncher_health;
+	missile.event_damage = W_Rocket_Damage;
+	missile.damagedbycontents = TRUE;
+
+	missile.movetype = MOVETYPE_FLY;
+	PROJECTILE_MAKETRIGGER(missile);
+	missile.projectiledeathtype = WEP_ROCKET_LAUNCHER;
+	setsize (missile, '-3 -3 -3', '3 3 3'); // give it some size so it can be shot
+
+	setorigin (missile, w_shotorg - v_forward * 3); // move it back so it hits the wall at the right point
+	W_SetupProjectileVelocity(missile, autocvar_g_balance_rocketlauncher_speedstart, 0);
+	missile.angles = vectoangles (missile.velocity);
+
+	missile.touch = W_Rocket_Touch;
+	missile.think = W_Rocket_Think;
+	missile.nextthink = time;
+	missile.cnt = time + autocvar_g_balance_rocketlauncher_lifetime;
+	missile.flags = FL_PROJECTILE;
+	missile.missile_flags = MIF_SPLASH;
+
+	CSQCProjectile(missile, autocvar_g_balance_rocketlauncher_guiderate == 0 && autocvar_g_balance_rocketlauncher_speedaccel == 0, PROJECTILE_ROCKET, FALSE); // because of fly sound
+
+	// muzzle flash for 1st person view
+	flash = spawn ();
+	setmodel (flash, "models/flash.md3"); // precision set below
+	SUB_SetFade (flash, time, 0.1);
+	flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+	W_AttachToShotorg(flash, '5 0 0');
+
+	// common properties
+	other = missile; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+void spawnfunc_weapon_rocketlauncher (void); // defined in t_items.qc
+
+float w_rlauncher(float req)
+{
+	entity rock;
+	float rockfound;
+	float ammo_amount;
+
+	if (req == WR_AIM)
+	{
+		// aim and decide to fire if appropriate
+		self.BUTTON_ATCK = bot_aim(autocvar_g_balance_rocketlauncher_speed, 0, autocvar_g_balance_rocketlauncher_lifetime, FALSE);
+		if(skill >= 2) // skill 0 and 1 bots won't detonate rockets!
+		{
+			// decide whether to detonate rockets
+			entity missile, targetlist, targ;
+			float edgedamage, coredamage, edgeradius, recipricoledgeradius, d;
+			float selfdamage, teamdamage, enemydamage;
+			edgedamage = autocvar_g_balance_rocketlauncher_edgedamage;
+			coredamage = autocvar_g_balance_rocketlauncher_damage;
+			edgeradius = autocvar_g_balance_rocketlauncher_radius;
+			recipricoledgeradius = 1 / edgeradius;
+			selfdamage = 0;
+			teamdamage = 0;
+			enemydamage = 0;
+			targetlist = findchainfloat(bot_attack, TRUE);
+			missile = find(world, classname, "rocket");
+			while (missile)
+			{
+				if (missile.realowner != self)
+				{
+					missile = find(missile, classname, "rocket");
+					continue;
+				}
+				targ = targetlist;
+				while (targ)
+				{
+					d = vlen(targ.origin + (targ.mins + targ.maxs) * 0.5 - missile.origin);
+					d = bound(0, edgedamage + (coredamage - edgedamage) * sqrt(1 - d * recipricoledgeradius), 10000);
+					// count potential damage according to type of target
+					if (targ == self)
+						selfdamage = selfdamage + d;
+					else if (targ.team == self.team && teamplay)
+						teamdamage = teamdamage + d;
+					else if (bot_shouldattack(targ))
+						enemydamage = enemydamage + d;
+					targ = targ.chain;
+				}
+				missile = find(missile, classname, "rocket");
+			}
+			float desirabledamage;
+			desirabledamage = enemydamage;
+			if (time > self.invincible_finished && time > self.spawnshieldtime)
+				desirabledamage = desirabledamage - selfdamage * autocvar_g_balance_selfdamagepercent;
+			if (teamplay && self.team)
+				desirabledamage = desirabledamage - teamdamage;
+
+			missile = find(world, classname, "rocket");
+			while (missile)
+			{
+				if (missile.realowner != self)
+				{
+					missile = find(missile, classname, "rocket");
+					continue;
+				}
+				makevectors(missile.v_angle);
+				targ = targetlist;
+				if (skill > 9) // normal players only do this for the target they are tracking
+				{
+					targ = targetlist;
+					while (targ)
+					{
+						if (
+							(v_forward * normalize(missile.origin - targ.origin)< 0.1)
+							&& desirabledamage > 0.1*coredamage
+						)self.BUTTON_ATCK2 = TRUE;
+						targ = targ.chain;
+					}
+				}else{
+					float distance; distance= bound(300,vlen(self.origin-self.enemy.origin),30000);
+					//As the distance gets larger, a correct detonation gets near imposible
+					//Bots are assumed to use the rocket spawnfunc_light to see if the rocket gets near a player
+					if(v_forward * normalize(missile.origin - self.enemy.origin)< 0.1)
+						if(IS_PLAYER(self.enemy))
+							if(desirabledamage >= 0.1*coredamage)
+								if(random()/distance*300 > frametime*bound(0,(10-skill)*0.2,1))
+									self.BUTTON_ATCK2 = TRUE;
+				//	dprint(ftos(random()/distance*300),">");dprint(ftos(frametime*bound(0,(10-skill)*0.2,1)),"\n");
+				}
+
+				missile = find(missile, classname, "rocket");
+			}
+			// if we would be doing at X percent of the core damage, detonate it
+			// but don't fire a new shot at the same time!
+			if (desirabledamage >= 0.75 * coredamage) //this should do group damage in rare fortunate events
+				self.BUTTON_ATCK2 = TRUE;
+			if ((skill > 6.5) && (selfdamage > self.health))
+				self.BUTTON_ATCK2 = FALSE;
+			//if(self.BUTTON_ATCK2 == TRUE)
+			//	dprint(ftos(desirabledamage),"\n");
+			if (self.BUTTON_ATCK2 == TRUE) self.BUTTON_ATCK = FALSE;
+		}
+	}
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_rocketlauncher_reload_ammo && self.clip_load < autocvar_g_balance_rocketlauncher_ammo) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+		else
+		{
+			if (self.BUTTON_ATCK)
+			{
+				if(self.rl_release || autocvar_g_balance_rocketlauncher_guidestop)
+				if(weapon_prepareattack(0, autocvar_g_balance_rocketlauncher_refire))
+				{
+					W_Rocket_Attack();
+					weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_rocketlauncher_animtime, w_ready);
+					self.rl_release = 0;
+				}
+			}
+			else
+				self.rl_release = 1;
+
+			if (self.BUTTON_ATCK2)
+			{
+				rockfound = 0;
+				for(rock = world; (rock = find(rock, classname, "rocket")); ) if(rock.realowner == self)
+				{
+					if(!rock.rl_detonate_later)
+					{
+						rock.rl_detonate_later = TRUE;
+						rockfound = 1;
+					}
+				}
+				if(rockfound)
+					sound (self, CH_WEAPON_B, "weapons/rocket_det.wav", VOL_BASE, ATTEN_NORM);
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/flash.md3");
+		precache_model ("models/weapons/g_rl.md3");
+		precache_model ("models/weapons/v_rl.md3");
+		precache_model ("models/weapons/h_rl.iqm");
+		precache_sound ("weapons/rocket_det.wav");
+		precache_sound ("weapons/rocket_fire.wav");
+		precache_sound ("weapons/rocket_mode.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_ROCKET_LAUNCHER);
+		self.current_ammo = ammo_rockets;
+		self.rl_release = 1;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		// don't switch while guiding a missile
+		if (ATTACK_FINISHED(self) <= time || self.weapon != WEP_ROCKET_LAUNCHER)
+		{
+			ammo_amount = FALSE;
+			if(autocvar_g_balance_rocketlauncher_reload_ammo)
+			{
+				if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo && self.(weapon_load[WEP_ROCKET_LAUNCHER]) < autocvar_g_balance_rocketlauncher_ammo)
+					ammo_amount = TRUE;
+			}
+			else if(self.ammo_rockets < autocvar_g_balance_rocketlauncher_ammo)
+				ammo_amount = TRUE;
+			return !ammo_amount;
+		}
+	}
+	else if (req == WR_CHECKAMMO2)
+		return FALSE;
+	else if (req == WR_RESETPLAYER)
+	{
+		self.rl_release = 0;
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(autocvar_g_balance_rocketlauncher_ammo, autocvar_g_balance_rocketlauncher_reload_ammo, autocvar_g_balance_rocketlauncher_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_ROCKETLAUNCHER_SUICIDE;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if((w_deathtype & HITTYPE_BOUNCE) || (w_deathtype & HITTYPE_SPLASH))
+			return WEAPON_ROCKETLAUNCHER_MURDER_SPLASH;
+		else
+			return WEAPON_ROCKETLAUNCHER_MURDER_DIRECT;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_rlauncher(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 12;
+		pointparticles(particleeffectnum("rocket_explode"), org2, '0 0 0', 1);
+		if(!w_issilent)
+			sound(self, CH_SHOTS, "weapons/rocket_impact.wav", VOL_BASE, ATTEN_NORM);
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/rocket_impact.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_seeker.qc b/qcsrc/server/w_seeker.qc
new file mode 100644
index 000000000..c870f0868
--- /dev/null
+++ b/qcsrc/server/w_seeker.qc
@@ -0,0 +1,712 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ SEEKER,
+/* function  */ w_seeker,
+/* ammotype  */ IT_ROCKETS,
+/* impulse   */ 8,
+/* flags     */ WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH,
+/* rating    */ BOT_PICKUP_RATING_MID,
+/* model     */ "seeker",
+/* shortname */ "seeker",
+/* fullname  */ _("T.A.G. Seeker")
+);
+#else
+#ifdef SVQC
+//.float proxytime; = autoswitch
+//.float tl; = wait
+.entity tag_target, wps_tag_tracker;
+.float tag_time;
+
+// ============================
+// Begin: Missile functions, these are general functions to be manipulated by other code
+// ============================
+void Seeker_Missile_Explode ()
+{
+	self.event_damage = func_null;
+	RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_missile_damage, autocvar_g_balance_seeker_missile_edgedamage, autocvar_g_balance_seeker_missile_radius, world, autocvar_g_balance_seeker_missile_force, self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void Seeker_Missile_Touch()
+{
+	PROJECTILE_TOUCH;
+
+	Seeker_Missile_Explode();
+}
+
+void Seeker_Missile_Think()
+{
+	entity e;
+	vector desireddir, olddir, newdir, eorg;
+	float turnrate;
+	float dist;
+	float spd;
+
+	if (time > self.cnt)
+	{
+		self.projectiledeathtype |= HITTYPE_SPLASH;
+		Seeker_Missile_Explode();
+	}
+
+	spd = vlen(self.velocity);
+	spd = bound(
+		spd - autocvar_g_balance_seeker_missile_decel * frametime,
+		autocvar_g_balance_seeker_missile_speed_max,
+		spd + autocvar_g_balance_seeker_missile_accel * frametime
+	);
+
+	if (self.enemy != world)
+		if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
+			self.enemy = world;
+
+	if (self.enemy != world)
+	{
+		e               = self.enemy;
+		eorg            = 0.5 * (e.absmin + e.absmax);
+		turnrate        = autocvar_g_balance_seeker_missile_turnrate; // how fast to turn
+		desireddir      = normalize(eorg - self.origin);
+		olddir          = normalize(self.velocity); // get my current direction
+		dist            = vlen(eorg - self.origin);
+
+		// Do evasive maneuvers for world objects? ( this should be a cpu hog. :P )
+		if (autocvar_g_balance_seeker_missile_smart && (dist > autocvar_g_balance_seeker_missile_smart_mindist))
+		{
+			// Is it a better idea (shorter distance) to trace to the target itself?
+			if ( vlen(self.origin + olddir * self.wait) < dist)
+				traceline(self.origin, self.origin + olddir * self.wait, FALSE, self);
+			else
+				traceline(self.origin, eorg, FALSE, self);
+
+			// Setup adaptive tracelength
+			self.wait = bound(autocvar_g_balance_seeker_missile_smart_trace_min, vlen(self.origin - trace_endpos), self.wait = autocvar_g_balance_seeker_missile_smart_trace_max);
+
+			// Calc how important it is that we turn and add this to the desierd (enemy) dir.
+			desireddir  = normalize(((trace_plane_normal * (1 - trace_fraction)) + (desireddir * trace_fraction)) * 0.5);
+		}
+
+		newdir = normalize(olddir + desireddir * turnrate); // take the average of the 2 directions; not the best method but simple & easy
+		self.velocity = newdir * spd; // make me fly in the new direction at my flight speed
+	}
+	else
+		dist = 0;
+
+	// Proxy
+	if (autocvar_g_balance_seeker_missile_proxy)
+	{
+		if ( dist <= autocvar_g_balance_seeker_missile_proxy_maxrange)
+		{
+			if (self.autoswitch == 0)
+			{
+				self.autoswitch = time + autocvar_g_balance_seeker_missile_proxy_delay;
+			}
+			else
+			{
+				if (self.autoswitch <= time)
+				{
+					Seeker_Missile_Explode();
+					self.autoswitch = 0;
+				}
+			}
+		}
+		else
+		{
+			if (self.autoswitch != 0)
+				self.autoswitch = 0;
+		}
+	}
+	///////////////
+
+	if (self.enemy.deadflag != DEAD_NO)
+	{
+		self.enemy = world;
+		self.cnt = time + 1 + (random() * 4);
+		self.nextthink = self.cnt;
+		return;
+	}
+
+	//self.angles = vectoangles(self.velocity);			// turn model in the new flight direction
+	self.nextthink = time;// + 0.05; // csqc projectiles
+	UpdateCSQCProjectile(self);
+}
+
+
+
+void Seeker_Missile_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	if (self.health <= 0)
+		return;
+
+	if (!W_CheckProjectileDamage(inflictor.realowner, self.realowner, deathtype, -1)) // no exceptions
+		return; // g_projectiles_damage says to halt
+
+	if (self.realowner == attacker)
+		self.health = self.health - (damage * 0.25);
+	else
+		self.health = self.health - damage;
+
+	if (self.health <= 0)
+		W_PrepareExplosionByDamage(attacker, Seeker_Missile_Explode);
+}
+
+/*
+void Seeker_Missile_Animate()
+{
+	self.frame = self.frame +1;
+	self.nextthink = time + 0.05;
+
+	if (self.enemy != world)
+		if (self.enemy.takedamage != DAMAGE_AIM || self.enemy.deadflag != DEAD_NO)
+			self.enemy = world;
+
+	if(self.frame == 5)
+	{
+		self.think           = Seeker_Missile_Think;
+		self.nextthink       = time;// + cvar("g_balance_seeker_missile_activate_delay"); // cant dealy with csqc projectiles
+
+		if (autocvar_g_balance_seeker_missile_proxy)
+			self.movetype    = MOVETYPE_BOUNCEMISSILE;
+		else
+			self.movetype    = MOVETYPE_FLYMISSILE;
+	}
+
+	UpdateCSQCProjectile(self);
+}
+*/
+
+void Seeker_Fire_Missile(vector f_diff, entity m_target)
+{
+	entity missile;
+
+	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_reload_ammo);
+
+	makevectors(self.v_angle);
+	W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/seeker_fire.wav", CH_WEAPON_A, 0);
+	w_shotorg += f_diff;
+	pointparticles(particleeffectnum("seeker_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	//self.detornator         = FALSE;
+
+	missile                 = spawn();
+	missile.owner           = missile.realowner = self;
+	missile.classname       = "seeker_missile";
+	missile.bot_dodge       = TRUE;
+	missile.bot_dodgerating = autocvar_g_balance_seeker_missile_damage;
+
+	missile.think           = Seeker_Missile_Think;
+	missile.touch           = Seeker_Missile_Touch;
+	missile.event_damage    = Seeker_Missile_Damage;
+	missile.nextthink       = time;// + 0.2;// + cvar("g_balance_seeker_missile_activate_delay");
+	missile.cnt             = time + autocvar_g_balance_seeker_missile_lifetime;
+	missile.enemy           = m_target;
+	missile.solid           = SOLID_BBOX;
+	missile.scale           = 2;
+	missile.takedamage      = DAMAGE_YES;
+	missile.health          = autocvar_g_balance_seeker_missile_health;
+	missile.damageforcescale = autocvar_g_balance_seeker_missile_damageforcescale;
+	missile.damagedbycontents = TRUE;
+	//missile.think           = Seeker_Missile_Animate; // csqc projectiles.
+
+	if (missile.enemy != world)
+		missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
+	else
+		missile.projectiledeathtype = WEP_SEEKER;
+
+
+	setorigin (missile, w_shotorg);
+	setsize (missile, '-4 -4 -4', '4 4 4');
+	missile.movetype    = MOVETYPE_FLYMISSILE;
+	missile.flags       = FL_PROJECTILE;
+	missile.missile_flags = MIF_SPLASH | MIF_GUIDED_TAG;
+
+	W_SETUPPROJECTILEVELOCITY_UP(missile, g_balance_seeker_missile);
+
+	missile.angles = vectoangles (missile.velocity);
+
+	CSQCProjectile(missile, FALSE, PROJECTILE_SEEKER, TRUE);
+
+	other = missile; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+// ============================
+// Begin: FLAC, close range attack meant for defeating rockets which are coming at you.
+// ============================
+void Seeker_Flac_Explode ()
+{
+	self.event_damage = func_null;
+
+	RadiusDamage (self, self.realowner, autocvar_g_balance_seeker_flac_damage, autocvar_g_balance_seeker_flac_edgedamage, autocvar_g_balance_seeker_flac_radius, world, autocvar_g_balance_seeker_flac_force, self.projectiledeathtype, other);
+
+	remove (self);
+}
+
+void Seeker_Flac_Touch()
+{
+	PROJECTILE_TOUCH;
+
+	Seeker_Flac_Explode();
+}
+
+void Seeker_Fire_Flac()
+{
+	entity missile;
+	vector f_diff;
+	float c;
+
+	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_flac_ammo, autocvar_g_balance_seeker_reload_ammo);
+
+	c = mod(self.bulletcounter, 4);
+	switch(c)
+	{
+		case 0:
+			f_diff = '-1.25 -3.75 0';
+			break;
+		case 1:
+			f_diff = '+1.25 -3.75 0';
+			break;
+		case 2:
+			f_diff = '-1.25 +3.75 0';
+			break;
+		case 3:
+		default:
+			f_diff = '+1.25 +3.75 0';
+			break;
+	}
+	W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/flac_fire.wav", CH_WEAPON_A, autocvar_g_balance_seeker_flac_damage);
+	w_shotorg += f_diff;
+
+	pointparticles(particleeffectnum("hagar_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	missile 				= spawn ();
+	missile.owner 			= missile.realowner = self;
+	missile.classname 		= "missile";
+	missile.bot_dodge 		= TRUE;
+	missile.bot_dodgerating = autocvar_g_balance_seeker_flac_damage;
+	missile.touch 			= Seeker_Flac_Explode;
+	missile.use 			= Seeker_Flac_Explode;
+	missile.think 			= adaptor_think2use_hittype_splash;
+	missile.nextthink 		= time + autocvar_g_balance_seeker_flac_lifetime + autocvar_g_balance_seeker_flac_lifetime_rand;
+	missile.solid 			= SOLID_BBOX;
+	missile.movetype 		= MOVETYPE_FLY;
+	missile.projectiledeathtype = WEP_SEEKER;
+	missile.projectiledeathtype = WEP_SEEKER | HITTYPE_SECONDARY;
+	missile.flags 				= FL_PROJECTILE;
+	missile.missile_flags       = MIF_SPLASH;
+
+	// csqc projectiles
+	//missile.angles 				= vectoangles (missile.velocity);
+	//missile.scale = 0.4; // BUG: the model is too big
+
+	setorigin (missile, w_shotorg);
+	setsize (missile, '-2 -2 -2', '2 2 2');
+
+	W_SETUPPROJECTILEVELOCITY_UP(missile, g_balance_seeker_flac);
+	CSQCProjectile(missile, TRUE, PROJECTILE_FLAC, TRUE);
+
+	other = missile; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+// ============================
+// Begin: Tag and rocket controllers
+// ============================
+entity Seeker_Tagged_Info(entity isowner, entity istarget)
+{
+	entity tag;
+	for(tag = world; (tag = find(tag, classname, "tag_tracker")); )
+		if ((tag.realowner == isowner) && (tag.tag_target == istarget))
+			return tag;
+
+	return world;
+}
+
+void Seeker_Attack()
+{
+	entity tracker, closest_target;
+
+	closest_target = world;
+	for(tracker = world; (tracker = find(tracker, classname, "tag_tracker")); ) if (tracker.realowner == self)
+	{
+		if (closest_target)
+		{
+			if (vlen(self.origin - tracker.tag_target.origin) < vlen(self.origin - closest_target.origin))
+				closest_target = tracker.tag_target;
+		}
+		else
+			closest_target = tracker.tag_target;
+	}
+
+	traceline(self.origin + self.view_ofs, closest_target.origin, MOVE_NOMONSTERS, self);
+	if ((!closest_target) || ((trace_fraction < 1) && (trace_ent != closest_target)))
+		closest_target = world;
+
+	Seeker_Fire_Missile('0 0 0', closest_target);
+}
+
+void Seeker_Vollycontroller_Think() // TODO: Merge this with Seeker_Attack
+{
+	float c;
+	entity oldself,oldenemy;
+	self.cnt = self.cnt - 1;
+
+	if((!(self.realowner.items & IT_UNLIMITED_AMMO) && self.realowner.ammo_rockets < autocvar_g_balance_seeker_missile_ammo) || (self.cnt <= -1) || (self.realowner.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER))
+	{
+		remove(self);
+		return;
+	}
+
+	self.nextthink = time + autocvar_g_balance_seeker_missile_delay * W_WeaponRateFactor();
+
+	oldself = self;
+	self = self.realowner;
+
+	oldenemy = self.enemy;
+	self.enemy = oldself.enemy;
+
+	c = mod(self.cnt, 4);
+	switch(c)
+	{
+		case 0:
+			Seeker_Fire_Missile('-1.25 -3.75 0', self.enemy);
+			break;
+		case 1:
+			Seeker_Fire_Missile('+1.25 -3.75 0', self.enemy);
+			break;
+		case 2:
+			Seeker_Fire_Missile('-1.25 +3.75 0', self.enemy);
+			break;
+		case 3:
+		default:
+			Seeker_Fire_Missile('+1.25 +3.75 0', self.enemy);
+			break;
+	}
+
+	self.enemy = oldenemy;
+	self = oldself;
+}
+
+void Seeker_Tracker_Think()
+{
+	// commit suicide if: You die OR target dies OR you switch away from the seeker OR commit suicide if lifetime is up
+	if ((self.realowner.deadflag != DEAD_NO) || (self.tag_target.deadflag != DEAD_NO) || (self.realowner.switchweapon != WEP_SEEKER)
+	|| (time > self.tag_time + autocvar_g_balance_seeker_tag_tracker_lifetime))
+	{
+		if (self)
+		{
+			WaypointSprite_Kill(self.tag_target.wps_tag_tracker);
+			remove(self);
+		}
+		return;
+	}
+
+	// Update the think method information
+	self.nextthink = time;
+}
+
+// ============================
+// Begin: Tag projectile
+// ============================
+void Seeker_Tag_Explode ()
+{
+	//if(other==self.realowner)
+	//    return;
+	Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE, other.species, self);
+
+	remove (self);
+}
+
+void Seeker_Tag_Damage (entity inflictor, entity attacker, float damage, float deathtype, vector hitloc, vector force)
+{
+	if (self.health <= 0)
+		return;
+	self.health = self.health - damage;
+	if (self.health <= 0)
+		Seeker_Tag_Explode();
+}
+
+void Seeker_Tag_Touch()
+{
+	vector dir;
+	vector org2;
+	entity e;
+
+	PROJECTILE_TOUCH;
+
+	dir     = normalize (self.realowner.origin - self.origin);
+	org2    = findbetterlocation (self.origin, 8);
+
+	te_knightspike(org2);
+
+	self.event_damage = func_null;
+	Damage_DamageInfo(self.origin, 0, 0, 0, self.velocity, WEP_SEEKER | HITTYPE_BOUNCE | HITTYPE_SECONDARY, other.species, self);
+
+	if (other.takedamage == DAMAGE_AIM && other.deadflag == DEAD_NO)
+	{
+		// check to see if this person is already tagged by me
+		entity tag = Seeker_Tagged_Info(self.realowner, other);
+
+		if (tag != world)
+		{
+			if (other.wps_tag_tracker && (autocvar_g_balance_seeker_type == 1)) // don't attach another waypointsprite without killing the old one first
+				WaypointSprite_Kill(other.wps_tag_tracker);
+
+			tag.tag_time = time;
+		}
+		else
+		{
+			//sprint(self.realowner, strcat("You just tagged ^2", other.netname, "^7 with a tracking device!\n"));
+			e             = spawn();
+			e.cnt         = autocvar_g_balance_seeker_missile_count;
+			e.classname   = "tag_tracker";
+			e.owner       = self.owner;
+			e.realowner   = self.realowner;
+
+			if	(autocvar_g_balance_seeker_type == 1)
+			{
+				e.tag_target  = other;
+				e.tag_time    = time;
+				e.think       = Seeker_Tracker_Think;
+			}
+			else
+			{
+				e.enemy     = other;
+				e.think     = Seeker_Vollycontroller_Think;
+			}
+
+			e.nextthink   = time;
+		}
+
+		if	(autocvar_g_balance_seeker_type == 1)
+		{
+			WaypointSprite_Spawn("tagged-target", autocvar_g_balance_seeker_tag_tracker_lifetime, 0, other, '0 0 64', self.realowner, 0, other, wps_tag_tracker, TRUE, RADARICON_TAGGED, '0.5 1 0');
+			WaypointSprite_UpdateRule(other.wps_tag_tracker, 0, SPRITERULE_DEFAULT);
+		}
+	}
+
+	remove(self);
+	return;
+}
+
+void Seeker_Fire_Tag()
+{
+	entity missile;
+	W_DecreaseAmmo(ammo_rockets, autocvar_g_balance_seeker_tag_ammo, autocvar_g_balance_seeker_reload_ammo);
+
+	W_SetupShot_ProjectileSize (self, '-2 -2 -2', '2 2 2', FALSE, 2, "weapons/tag_fire.wav", CH_WEAPON_A, autocvar_g_balance_seeker_missile_damage * autocvar_g_balance_seeker_missile_count);
+
+	missile                 = spawn();
+	missile.owner           = missile.realowner = self;
+	missile.classname       = "seeker_tag";
+	missile.bot_dodge       = TRUE;
+	missile.bot_dodgerating = 50;
+	missile.touch           = Seeker_Tag_Touch;
+	missile.think           = SUB_Remove;
+	missile.nextthink       = time + autocvar_g_balance_seeker_tag_lifetime;
+	missile.movetype        = MOVETYPE_FLY;
+	missile.solid           = SOLID_BBOX;
+
+	missile.takedamage       = DAMAGE_YES;
+	missile.event_damage     = Seeker_Tag_Damage;
+	missile.health           = autocvar_g_balance_seeker_tag_health;
+	missile.damageforcescale = autocvar_g_balance_seeker_tag_damageforcescale;
+
+	setorigin (missile, w_shotorg);
+	setsize (missile, '-2 -2 -2', '2 2 2');
+
+	missile.flags       = FL_PROJECTILE;
+	//missile.missile_flags = MIF_..?;
+
+	missile.movetype    = MOVETYPE_FLY;
+	W_SETUPPROJECTILEVELOCITY(missile, g_balance_seeker_tag);
+	missile.angles = vectoangles (missile.velocity);
+
+	CSQCProjectile(missile, TRUE, PROJECTILE_TAG, FALSE); // has sound
+
+	other = missile; MUTATOR_CALLHOOK(EditProjectile);
+}
+
+// ============================
+// Begin: Genereal weapon functions
+// ============================
+void spawnfunc_weapon_seeker (void)
+{
+	weapon_defaultspawnfunc(WEP_SEEKER);
+}
+
+float w_seeker(float req)
+{
+	float ammo_amount;
+
+	if (req == WR_AIM)
+	{
+		if (autocvar_g_balance_seeker_type == 1)
+			if (Seeker_Tagged_Info(self, self.enemy) != world)
+				self.BUTTON_ATCK = bot_aim(autocvar_g_balance_seeker_missile_speed_max, 0, autocvar_g_balance_seeker_missile_lifetime, FALSE);
+			else
+				self.BUTTON_ATCK2 = bot_aim(autocvar_g_balance_seeker_tag_speed, 0, autocvar_g_balance_seeker_tag_lifetime, FALSE);
+		else
+			self.BUTTON_ATCK = bot_aim(autocvar_g_balance_seeker_tag_speed, 0, autocvar_g_balance_seeker_tag_lifetime, FALSE);
+	}
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_seeker_reload_ammo && self.clip_load < min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo)) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+
+		else if (self.BUTTON_ATCK)
+		{
+			if (autocvar_g_balance_seeker_type == 1)
+			{
+				if (weapon_prepareattack(0, autocvar_g_balance_seeker_missile_refire))
+				{
+					Seeker_Attack();
+					weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_missile_animtime, w_ready);
+				}
+			}
+			else
+			{
+				if (weapon_prepareattack(0, autocvar_g_balance_seeker_tag_refire))
+				{
+					Seeker_Fire_Tag();
+					weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_tag_animtime, w_ready);
+				}
+			}
+		}
+
+		else if (self.BUTTON_ATCK2)
+		{
+			if (autocvar_g_balance_seeker_type == 1)
+			{
+				if (weapon_prepareattack(0, autocvar_g_balance_seeker_tag_refire))
+				{
+					Seeker_Fire_Tag();
+					weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_tag_animtime, w_ready);
+				}
+			}
+			else
+			{
+				if (weapon_prepareattack(0, autocvar_g_balance_seeker_flac_refire))
+				{
+					Seeker_Fire_Flac();
+					weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_seeker_flac_animtime, w_ready);
+				}
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_seeker.md3");
+		precache_model ("models/weapons/v_seeker.md3");
+		precache_model ("models/weapons/h_seeker.iqm");
+		precache_sound ("weapons/tag_fire.wav");
+		precache_sound ("weapons/flac_fire.wav");
+		precache_sound ("weapons/seeker_fire.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_SEEKER);
+		self.current_ammo = ammo_rockets;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		if (autocvar_g_balance_seeker_type == 1)
+		{
+			ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_missile_ammo;
+			ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_missile_ammo;
+		}
+		else
+		{
+			ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo;
+			ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_tag_ammo;
+		}
+
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		if (autocvar_g_balance_seeker_type == 1)
+		{
+			ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_tag_ammo;
+			ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_tag_ammo;
+		}
+		else
+		{
+			ammo_amount = self.ammo_rockets >= autocvar_g_balance_seeker_flac_ammo;
+			ammo_amount += self.(weapon_load[WEP_SEEKER]) >= autocvar_g_balance_seeker_flac_ammo;
+		}
+
+		return ammo_amount;
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(min(autocvar_g_balance_seeker_missile_ammo, autocvar_g_balance_seeker_tag_ammo), autocvar_g_balance_seeker_reload_ammo, autocvar_g_balance_seeker_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_SEEKER_SUICIDE;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+			return WEAPON_SEEKER_MURDER_TAG;
+		else
+			return WEAPON_SEEKER_MURDER_SPRAY;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_seeker(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 6;
+		if(w_deathtype & HITTYPE_BOUNCE)
+		{
+			if(w_deathtype & HITTYPE_SECONDARY)
+			{
+				if(!w_issilent)
+					sound(self, CH_SHOTS, "weapons/tag_impact.wav", 1, ATTEN_NORM);
+			}
+			else
+			{
+				pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
+				if(!w_issilent)
+				{
+					if (w_random<0.15)
+						sound(self, CH_SHOTS, "weapons/tagexp1.wav", 1, ATTEN_NORM);
+					else if (w_random<0.7)
+						sound(self, CH_SHOTS, "weapons/tagexp2.wav", 1, ATTEN_NORM);
+					else
+						sound(self, CH_SHOTS, "weapons/tagexp3.wav", 1, ATTEN_NORM);
+				}
+			}
+		}
+		else
+		{
+			pointparticles(particleeffectnum("hagar_explode"), org2, '0 0 0', 1);
+			if(!w_issilent)
+			{
+				if (w_random<0.15)
+					sound(self, CH_SHOTS, "weapons/seekerexp1.wav", 1, ATTEN_NORM);
+				else if (w_random<0.7)
+					sound(self, CH_SHOTS, "weapons/seekerexp2.wav", 1, ATTEN_NORM);
+				else
+					sound(self, CH_SHOTS, "weapons/seekerexp3.wav", 1, ATTEN_NORM);
+			}
+		}
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/seekerexp1.wav");
+		precache_sound("weapons/seekerexp2.wav");
+		precache_sound("weapons/seekerexp3.wav");
+		precache_sound("weapons/tagexp1.wav");
+		precache_sound("weapons/tagexp2.wav");
+		precache_sound("weapons/tagexp3.wav");
+		precache_sound("weapons/tag_impact.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_shotgun.qc b/qcsrc/server/w_shotgun.qc
new file mode 100644
index 000000000..173f8c1a5
--- /dev/null
+++ b/qcsrc/server/w_shotgun.qc
@@ -0,0 +1,287 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ SHOTGUN,
+/* function  */ w_shotgun,
+/* ammotype  */ IT_SHELLS,
+/* impulse   */ 2,
+/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
+/* rating    */ BOT_PICKUP_RATING_LOW,
+/* model     */ "shotgun",
+/* shortname */ "shotgun",
+/* fullname  */ _("Shotgun")
+);
+#else
+#ifdef SVQC
+
+void W_Shotgun_Attack (void)
+{
+	float	sc;
+	float	ammoamount;
+	float	bullets;
+	float	d;
+	float	f;
+	float	spread;
+	float	solidpenetration;
+	entity flash;
+
+	ammoamount = autocvar_g_balance_shotgun_primary_ammo;
+	bullets = autocvar_g_balance_shotgun_primary_bullets;
+	d = autocvar_g_balance_shotgun_primary_damage;
+	f = autocvar_g_balance_shotgun_primary_force;
+	spread = autocvar_g_balance_shotgun_primary_spread;
+	solidpenetration = autocvar_g_balance_shotgun_primary_solidpenetration;
+
+	W_DecreaseAmmo(ammo_shells, ammoamount, autocvar_g_balance_shotgun_reload_ammo);
+
+	W_SetupShot (self, TRUE, 5, "weapons/shotgun_fire.wav", CH_WEAPON_A, d * bullets);
+	for (sc = 0;sc < bullets;sc = sc + 1)
+		fireBullet(w_shotorg, w_shotdir, spread, solidpenetration, d, f, WEP_SHOTGUN, 0);
+
+	pointparticles(particleeffectnum("shotgun_muzzleflash"), w_shotorg, w_shotdir * 1000, autocvar_g_balance_shotgun_primary_ammo);
+
+	// casing code
+	if (autocvar_g_casings >= 1)
+		for (sc = 0;sc < ammoamount;sc = sc + 1)
+			SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 30) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 1, self);
+
+	// muzzle flash for 1st person view
+	flash = spawn();
+	setmodel(flash, "models/uziflash.md3"); // precision set below
+	flash.think = SUB_Remove;
+	flash.nextthink = time + 0.06;
+	flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+	W_AttachToShotorg(flash, '5 0 0');
+}
+
+.float swing_prev;
+.entity swing_alreadyhit;
+void shotgun_meleethink (void)
+{
+	// declarations
+	float i, f, swing, swing_factor, swing_damage, meleetime, is_player, is_monster;
+	entity target_victim;
+	vector targpos;
+
+	if(!self.cnt) // set start time of melee
+	{
+		self.cnt = time;
+		W_PlayStrengthSound(self.realowner);
+	}
+
+	makevectors(self.realowner.v_angle); // update values for v_* vectors
+
+	// calculate swing percentage based on time
+	meleetime = autocvar_g_balance_shotgun_secondary_melee_time * W_WeaponRateFactor();
+	swing = bound(0, (self.cnt + meleetime - time) / meleetime, 10);
+	f = ((1 - swing) * autocvar_g_balance_shotgun_secondary_melee_traces);
+
+	// check to see if we can still continue, otherwise give up now
+	if((self.realowner.deadflag != DEAD_NO) && autocvar_g_balance_shotgun_secondary_melee_no_doubleslap)
+	{
+		remove(self);
+		return;
+	}
+
+	// if okay, perform the traces needed for this frame
+	for(i=self.swing_prev; i < f; ++i)
+	{
+		swing_factor = ((1 - (i / autocvar_g_balance_shotgun_secondary_melee_traces)) * 2 - 1);
+
+		targpos = (self.realowner.origin + self.realowner.view_ofs
+			+ (v_forward * autocvar_g_balance_shotgun_secondary_melee_range)
+			+ (v_up * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_up)
+			+ (v_right * swing_factor * autocvar_g_balance_shotgun_secondary_melee_swing_side));
+
+		WarpZone_traceline_antilag(self, self.realowner.origin + self.realowner.view_ofs, targpos, FALSE, self, ANTILAG_LATENCY(self.realowner));
+
+		// draw lightning beams for debugging
+		//te_lightning2(world, targpos, self.realowner.origin + self.realowner.view_ofs + v_forward * 5 - v_up * 5);
+		//te_customflash(targpos, 40,  2, '1 1 1');
+
+		is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body");
+		is_monster = (trace_ent.flags & FL_MONSTER);
+
+		if((trace_fraction < 1) // if trace is good, apply the damage and remove self
+			&& (trace_ent.takedamage == DAMAGE_AIM)
+			&& (trace_ent != self.swing_alreadyhit)
+			&& ((is_player || is_monster) || autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage))
+		{
+			target_victim = trace_ent; // so it persists through other calls
+
+			if(is_player || is_monster) // this allows us to be able to nerf the non-player damage done in e.g. assault or onslaught.
+				swing_damage = (autocvar_g_balance_shotgun_secondary_damage * min(1, swing_factor + 1));
+			else
+				swing_damage = (autocvar_g_balance_shotgun_secondary_melee_nonplayerdamage * min(1, swing_factor + 1));
+
+			//print(strcat(self.realowner.netname, " hitting ", target_victim.netname, " with ", strcat(ftos(swing_damage), " damage (factor: ", ftos(swing_factor), ") at "), ftos(time), " seconds.\n"));
+
+			Damage(target_victim, self.realowner, self.realowner,
+				swing_damage, WEP_SHOTGUN | HITTYPE_SECONDARY,
+				self.realowner.origin + self.realowner.view_ofs,
+				v_forward * autocvar_g_balance_shotgun_secondary_force);
+
+			if(accuracy_isgooddamage(self.realowner, target_victim)) { accuracy_add(self.realowner, WEP_SHOTGUN, 0, swing_damage); }
+
+			// draw large red flash for debugging
+			//te_customflash(targpos, 200, 2, '15 0 0');
+
+			if(autocvar_g_balance_shotgun_secondary_melee_multihit) // allow multiple hits with one swing, but not against the same player twice.
+			{
+				self.swing_alreadyhit = target_victim;
+				continue; // move along to next trace
+			}
+			else
+			{
+				remove(self);
+				return;
+			}
+		}
+	}
+
+	if(time >= self.cnt + meleetime)
+	{
+		// melee is finished
+		remove(self);
+		return;
+	}
+	else
+	{
+		// set up next frame
+		self.swing_prev = i;
+		self.nextthink = time;
+	}
+}
+
+void W_Shotgun_Attack2 (void)
+{
+	sound (self, CH_WEAPON_A, "weapons/shotgun_melee.wav", VOL_BASE, ATTEN_NORM);
+	weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_shotgun_secondary_animtime, w_ready);
+
+	entity meleetemp;
+	meleetemp = spawn();
+	meleetemp.realowner = self;
+	meleetemp.think = shotgun_meleethink;
+	meleetemp.nextthink = time + autocvar_g_balance_shotgun_secondary_melee_delay * W_WeaponRateFactor();
+	W_SetupShot_Range(self, TRUE, 0, "", 0, autocvar_g_balance_shotgun_secondary_damage, autocvar_g_balance_shotgun_secondary_melee_range);
+}
+
+void spawnfunc_weapon_shotgun(); // defined in t_items.qc
+
+.float shotgun_primarytime;
+
+float w_shotgun(float req)
+{
+	float ammo_amount;
+	if (req == WR_AIM)
+		if(vlen(self.origin-self.enemy.origin) <= autocvar_g_balance_shotgun_secondary_melee_range)
+			self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE);
+		else
+			self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
+
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_shotgun_reload_ammo && self.clip_load < autocvar_g_balance_shotgun_primary_ammo) // forced reload
+		{
+			// don't force reload an empty shotgun if its melee attack is active
+			if (!(autocvar_g_balance_shotgun_secondary && self.ammo_shells < autocvar_g_balance_shotgun_primary_ammo))
+				weapon_action(self.weapon, WR_RELOAD);
+		}
+		else
+		{
+			if (self.BUTTON_ATCK)
+			{
+				if (time >= self.shotgun_primarytime) // handle refire separately so the secondary can be fired straight after a primary
+				{
+					if(weapon_prepareattack(0, autocvar_g_balance_shotgun_primary_animtime))
+					{
+						W_Shotgun_Attack();
+						self.shotgun_primarytime = time + autocvar_g_balance_shotgun_primary_refire * W_WeaponRateFactor();
+						weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_shotgun_primary_animtime, w_ready);
+					}
+				}
+			}
+		}
+		if (self.clip_load >= 0) // we are not currently reloading
+		if (!self.crouch) // no crouchmelee please
+		if (self.BUTTON_ATCK2 && autocvar_g_balance_shotgun_secondary)
+		if (weapon_prepareattack(1, autocvar_g_balance_shotgun_secondary_refire))
+		{
+			// attempt forcing playback of the anim by switching to another anim (that we never play) here...
+			weapon_thinkf(WFRAME_FIRE1, 0, W_Shotgun_Attack2);
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/uziflash.md3");
+		precache_model ("models/weapons/g_shotgun.md3");
+		precache_model ("models/weapons/v_shotgun.md3");
+		precache_model ("models/weapons/h_shotgun.iqm");
+		precache_sound ("misc/itempickup.wav");
+		precache_sound ("weapons/shotgun_fire.wav");
+		precache_sound ("weapons/shotgun_melee.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_SHOTGUN);
+		self.current_ammo = ammo_shells;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		ammo_amount = self.ammo_shells >= autocvar_g_balance_shotgun_primary_ammo;
+		ammo_amount += self.(weapon_load[WEP_SHOTGUN]) >= autocvar_g_balance_shotgun_primary_ammo;
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		// melee attack is always available
+		return TRUE;
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(autocvar_g_balance_shotgun_primary_ammo, autocvar_g_balance_shotgun_reload_ammo, autocvar_g_balance_shotgun_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_THINKING_WITH_PORTALS;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+			return WEAPON_SHOTGUN_MURDER_SLAP;
+		else
+			return WEAPON_SHOTGUN_MURDER;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+.float prevric;
+float w_shotgun(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 2;
+		pointparticles(particleeffectnum("shotgun_impact"), org2, w_backoff * 1000, 1);
+		if(!w_issilent && time - self.prevric > 0.25)
+		{
+			if(w_random < 0.0165)
+				sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_NORM);
+			else if(w_random < 0.033)
+				sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTEN_NORM);
+			else if(w_random < 0.05)
+				sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTEN_NORM);
+			self.prevric = time;
+		}
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/ric1.wav");
+		precache_sound("weapons/ric2.wav");
+		precache_sound("weapons/ric3.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_tuba.qc b/qcsrc/server/w_tuba.qc
new file mode 100644
index 000000000..2e081095f
--- /dev/null
+++ b/qcsrc/server/w_tuba.qc
@@ -0,0 +1,466 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ TUBA,
+/* function  */ w_tuba,
+/* ammotype  */ 0,
+/* impulse   */ 1,
+/* flags     */ WEP_FLAG_HIDDEN | WEP_TYPE_SPLASH,
+/* rating    */ BOT_PICKUP_RATING_MID,
+/* model     */ "tuba",
+/* shortname */ "tuba",
+/* xgettext:no-c-format */
+/* fullname  */ _("@!#%'n Tuba")
+);
+#else
+#ifdef SVQC
+//#define TUBA_NOTE(n) strcat("weapons/tuba_note", ftos(n), ".wav")
+.entity tuba_note;
+.float tuba_smoketime;
+.float tuba_instrument;
+
+#define MAX_TUBANOTES 32
+.float tuba_lastnotes_last;
+.float tuba_lastnotes_cnt; // over
+.vector tuba_lastnotes[MAX_TUBANOTES];
+
+float W_Tuba_HasPlayed(entity pl, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo)
+{
+	float i, j, mmin, mmax, nolength;
+	float n = tokenize_console(melody);
+	if(n > pl.tuba_lastnotes_cnt)
+		return FALSE;
+	float pitchshift = 0;
+
+	if(instrument >= 0)
+		if(pl.tuba_instrument != instrument)
+			return FALSE;
+
+	// verify notes...
+	nolength = FALSE;
+	for(i = 0; i < n; ++i)
+	{
+		vector v = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]);
+		float ai = stof(argv(n - i - 1));
+		float np = floor(ai);
+		if(ai == np)
+			nolength = TRUE;
+		// n counts the last played notes BACKWARDS
+		// _x is start
+		// _y is end
+		// _z is note pitch
+		if(ignorepitch && i == 0)
+		{
+			pitchshift = np - v_z;
+		}
+		else
+		{
+			if(v_z + pitchshift != np)
+				return FALSE;
+		}
+	}
+
+	// now we know the right NOTES were played
+	if(!nolength)
+	{
+		// verify rhythm...
+		float ti = 0;
+		if(maxtempo > 0)
+			mmin = 240 / maxtempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec
+		else
+			mmin = 0;
+		if(mintempo > 0)
+			mmax = 240 / mintempo; // 60 = "0.25 means 1 sec", at 120 0.5 means 1 sec, at 240 1 means 1 sec
+		else
+			mmax = 240; // you won't try THAT hard... (tempo 1)
+		//printf("initial tempo rules: %f %f\n", mmin, mmax);
+
+		for(i = 0; i < n; ++i)
+		{
+			vector vi = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - i + MAX_TUBANOTES, MAX_TUBANOTES)]);
+			float ai = stof(argv(n - i - 1));
+			ti -= 1 / (ai - floor(ai));
+			float tj = ti;
+			for(j = i+1; j < n; ++j)
+			{
+				vector vj = pl.(tuba_lastnotes[mod(pl.tuba_lastnotes_last - j + MAX_TUBANOTES, MAX_TUBANOTES)]);
+				float aj = stof(argv(n - j - 1));
+				tj -= (aj - floor(aj));
+
+				// note i should be at m*ti+b
+				// note j should be at m*tj+b
+				// so:
+				// we have a LINE l, so that
+				// vi_x <= l(ti) <= vi_y
+				// vj_x <= l(tj) <= vj_y
+				// what is m?
+
+				// vi_x <= vi_y <= vj_x <= vj_y
+				// ti <= tj
+				//printf("first note: %f to %f, should be %f\n", vi_x, vi_y, ti);
+				//printf("second note: %f to %f, should be %f\n", vj_x, vj_y, tj);
+				//printf("m1 = %f\n", (vi_x - vj_y) / (ti - tj));
+				//printf("m2 = %f\n", (vi_y - vj_x) / (ti - tj));
+				mmin = max(mmin, (vi_x - vj_y) / (ti - tj)); // lower bound
+				mmax = min(mmax, (vi_y - vj_x) / (ti - tj)); // upper bound
+			}
+		}
+
+		if(mmin > mmax) // rhythm fail
+			return FALSE;
+	}
+
+	pl.tuba_lastnotes_cnt = 0;
+
+	return TRUE;
+}
+
+void W_Tuba_NoteOff()
+{
+	// we have a note:
+	//   on: self.spawnshieldtime
+	//   off: time
+	//   note: self.cnt
+	if(self.owner.tuba_note == self)
+	{
+		self.owner.tuba_lastnotes_last = mod(self.owner.tuba_lastnotes_last + 1, MAX_TUBANOTES);
+		self.owner.(tuba_lastnotes[self.owner.tuba_lastnotes_last]) = eX * self.spawnshieldtime + eY * time + eZ * self.cnt;
+		self.owner.tuba_note = world;
+		self.owner.tuba_lastnotes_cnt = bound(0, self.owner.tuba_lastnotes_cnt + 1, MAX_TUBANOTES);
+
+		string s;
+		s = trigger_magicear_processmessage_forallears(self.owner, 0, world, string_null);
+		if(s != "")
+		{
+			// simulate a server message
+			switch(self.tuba_instrument)
+			{
+				default:
+				case 0: // Tuba
+					bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Tuba: ^7", s, "\n"));
+					break;
+				case 1:
+					bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Accordeon: ^7", s, "\n"));
+					break;
+				case 2:
+					bprint(strcat("\{1}\{13}* ^3", self.owner.netname, "^3 played on the @!#%'n Klein Bottle: ^7", s, "\n"));
+					break;
+			}
+		}
+	}
+	remove(self);
+}
+
+float Tuba_GetNote(entity pl, float hittype)
+{
+	float note;
+	float movestate;
+	movestate = 5;
+	if(pl.movement_x < 0) movestate -= 3;
+	if(pl.movement_x > 0) movestate += 3;
+	if(pl.movement_y < 0) movestate -= 1;
+	if(pl.movement_y > 0) movestate += 1;
+#ifdef GMQCC
+	note = 0;
+#endif
+	switch(movestate)
+	{
+	// layout: originally I wanted
+	//   eb e  e#=f
+	//   B  c  d
+	//   Gb G  G#
+	// but then you only use forward and right key. So to make things more
+	// interesting, I swapped B with e#. Har har har...
+	//   eb e  B
+	// f=e# c  d
+	//   Gb G  G#
+		case 1: note = -6; break; // Gb
+		case 2: note = -5; break; // G
+		case 3: note = -4; break; // G#
+		case 4: note = +5; break; // e#
+		default:
+		case 5: note =  0; break; // c
+		case 6: note = +2; break; // d
+		case 7: note = +3; break; // eb
+		case 8: note = +4; break; // e
+		case 9: note = -1; break; // B
+	}
+	if(pl.BUTTON_CROUCH)
+		note -= 12;
+	if(pl.BUTTON_JUMP)
+		note += 12;
+	if(hittype & HITTYPE_SECONDARY)
+		note += 7;
+
+	// we support two kinds of tubas, those tuned in Eb and those tuned in C
+	// kind of tuba currently is player slot number, or team number if in
+	// teamplay
+	// that way, holes in the range of notes are "plugged"
+	if(teamplay)
+	{
+		if(pl.team == NUM_TEAM_2 || pl.team == NUM_TEAM_4)
+			note += 3;
+	}
+	else
+	{
+		if(pl.clientcolors & 1)
+			note += 3;
+	}
+
+	// total range of notes:
+	//                       0
+	//                 ***  ** ****
+	//                        ***  ** ****
+	//     ***  ** ****
+	//            ***  ** ****
+	//     ***  ********************* ****
+	//     -18.........................+12
+	//        ***  ********************* ****
+	//     -18............................+15
+	//     with jump: ... +24
+	//     ... +27
+	return note;
+}
+
+float W_Tuba_NoteSendEntity(entity to, float sf)
+{
+	float f;
+
+	msg_entity = to;
+	if(!sound_allowed(MSG_ONE, self.realowner))
+		return FALSE;
+
+	WriteByte(MSG_ENTITY, ENT_CLIENT_TUBANOTE);
+	WriteByte(MSG_ENTITY, sf);
+	if(sf & 1)
+	{
+		WriteChar(MSG_ENTITY, self.cnt);
+		f = 0;
+		if(self.realowner != to)
+			f |= 1;
+		f |= 2 * self.tuba_instrument;
+		WriteByte(MSG_ENTITY, f);
+	}
+	if(sf & 2)
+	{
+		WriteCoord(MSG_ENTITY, self.origin_x);
+		WriteCoord(MSG_ENTITY, self.origin_y);
+		WriteCoord(MSG_ENTITY, self.origin_z);
+	}
+	return TRUE;
+}
+
+void W_Tuba_NoteThink()
+{
+	float dist_mult;
+	float vol0, vol1;
+	vector dir0, dir1;
+	vector v;
+	entity e;
+	if(time > self.teleport_time)
+	{
+		W_Tuba_NoteOff();
+		return;
+	}
+	self.nextthink = time;
+	dist_mult = autocvar_g_balance_tuba_attenuation / autocvar_snd_soundradius;
+	FOR_EACH_REALCLIENT(e)
+	if(e != self.realowner)
+	{
+		v = self.origin - (e.origin + e.view_ofs);
+		vol0 = max(0, 1 - vlen(v) * dist_mult);
+		dir0 = normalize(v);
+		v = self.realowner.origin - (e.origin + e.view_ofs);
+		vol1 = max(0, 1 - vlen(v) * dist_mult);
+		dir1 = normalize(v);
+		if(fabs(vol0 - vol1) > 0.005) // 0.5 percent change in volume
+		{
+			setorigin(self, self.realowner.origin);
+			self.SendFlags |= 2;
+			break;
+		}
+		if(dir0 * dir1 < 0.9994) // 2 degrees change in angle
+		{
+			setorigin(self, self.realowner.origin);
+			self.SendFlags |= 2;
+			break;
+		}
+	}
+}
+
+void W_Tuba_NoteOn(float hittype)
+{
+	vector o;
+	float n;
+
+	W_SetupShot(self, FALSE, 2, "", 0, autocvar_g_balance_tuba_damage);
+
+	n = Tuba_GetNote(self, hittype);
+
+	hittype = 0;
+	if(self.tuba_instrument & 1)
+		hittype |= HITTYPE_SECONDARY;
+	if(self.tuba_instrument & 2)
+		hittype |= HITTYPE_BOUNCE;
+
+	if(self.tuba_note)
+	{
+		if(self.tuba_note.cnt != n || self.tuba_note.tuba_instrument != self.tuba_instrument)
+		{
+			entity oldself = self;
+			self = self.tuba_note;
+			W_Tuba_NoteOff();
+			self = oldself;
+		}
+	}
+
+	if (!self.tuba_note)
+	{
+		self.tuba_note = spawn();
+		self.tuba_note.owner = self.tuba_note.realowner = self;
+		self.tuba_note.cnt = n;
+		self.tuba_note.tuba_instrument = self.tuba_instrument;
+		self.tuba_note.think = W_Tuba_NoteThink;
+		self.tuba_note.nextthink = time;
+		self.tuba_note.spawnshieldtime = time;
+		Net_LinkEntity(self.tuba_note, FALSE, 0, W_Tuba_NoteSendEntity);
+	}
+
+	self.tuba_note.teleport_time = time + autocvar_g_balance_tuba_refire * 2 * W_WeaponRateFactor(); // so it can get prolonged safely
+
+	//sound(self, c, TUBA_NOTE(n), bound(0, VOL_BASE * cvar("g_balance_tuba_volume"), 1), autocvar_g_balance_tuba_attenuation);
+	RadiusDamage(self, self, autocvar_g_balance_tuba_damage, autocvar_g_balance_tuba_edgedamage, autocvar_g_balance_tuba_radius, world, autocvar_g_balance_tuba_force, hittype | WEP_TUBA, world);
+
+	o = gettaginfo(self.exteriorweaponentity, 0);
+	if(time > self.tuba_smoketime)
+	{
+		pointparticles(particleeffectnum("smoke_ring"), o + v_up * 45 + v_right * -6 + v_forward * 8, v_up * 100, 1);
+		self.tuba_smoketime = time + 0.25;
+	}
+}
+
+void spawnfunc_weapon_tuba (void)
+{
+	weapon_defaultspawnfunc(WEP_TUBA);
+}
+
+float w_tuba(float req)
+{
+	if (req == WR_AIM)
+	{
+		// bots cannot play the Tuba well yet
+		// I think they should start with the recorder first
+		if(vlen(self.origin - self.enemy.origin) < autocvar_g_balance_tuba_radius)
+		{
+			if(random() > 0.5)
+				self.BUTTON_ATCK = 1;
+			else
+				self.BUTTON_ATCK2 = 1;
+		}
+	}
+	else if (req == WR_THINK)
+	{
+		if (self.BUTTON_ATCK)
+		if (weapon_prepareattack(0, autocvar_g_balance_tuba_refire))
+		{
+			W_Tuba_NoteOn(0);
+			//weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_tuba_animtime, w_ready);
+			weapon_thinkf(WFRAME_IDLE, autocvar_g_balance_tuba_animtime, w_ready);
+		}
+		if (self.BUTTON_ATCK2)
+		if (weapon_prepareattack(1, autocvar_g_balance_tuba_refire))
+		{
+			W_Tuba_NoteOn(HITTYPE_SECONDARY);
+			//weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_tuba_animtime, w_ready);
+			weapon_thinkf(WFRAME_IDLE, autocvar_g_balance_tuba_animtime, w_ready);
+		}
+		if(self.tuba_note)
+		{
+			if(!self.BUTTON_ATCK && !self.BUTTON_ATCK2)
+			{
+				entity oldself = self;
+				self = self.tuba_note;
+				W_Tuba_NoteOff();
+				self = oldself;
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/weapons/g_tuba.md3");
+		precache_model ("models/weapons/v_tuba.md3");
+		precache_model ("models/weapons/h_tuba.iqm");
+		precache_model ("models/weapons/v_akordeon.md3");
+		precache_model ("models/weapons/h_akordeon.iqm");
+		precache_model ("models/weapons/v_kleinbottle.md3");
+		precache_model ("models/weapons/h_kleinbottle.iqm");
+
+		//float i;
+		//for(i = -18; i <= +27; ++i)
+		//	precache_sound(TUBA_NOTE(i));
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_TUBA);
+		self.current_ammo = ammo_none;
+		self.tuba_instrument = 0;
+	}
+	else if (req == WR_RELOAD)
+	{
+		// switch to alternate instruments :)
+		if(self.weaponentity.state == WS_READY)
+		{
+			switch(self.tuba_instrument)
+			{
+				case 0:
+					self.tuba_instrument = 1;
+					self.weaponname = "akordeon";
+					break;
+				case 1:
+					self.tuba_instrument = 2;
+					self.weaponname = "kleinbottle";
+					break;
+				case 2:
+					self.tuba_instrument = 0;
+					self.weaponname = "tuba";
+					break;
+			}
+			W_SetupShot(self, FALSE, 0, "", 0, 0);
+			pointparticles(particleeffectnum("teleport"), w_shotorg, '0 0 0', 1);
+			self.weaponentity.state = WS_INUSE;
+			weapon_thinkf(WFRAME_RELOAD, 0.5, w_ready);
+		}
+	}
+	else if (req == WR_CHECKAMMO1)
+		return TRUE; // TODO use fuel?
+	else if (req == WR_CHECKAMMO2)
+		return TRUE; // TODO use fuel?
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_BOUNCE)
+			return WEAPON_KLEINBOTTLE_SUICIDE;
+		else if(w_deathtype & HITTYPE_SECONDARY)
+			return WEAPON_ACCORDEON_SUICIDE;
+		else
+			return WEAPON_TUBA_SUICIDE;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_BOUNCE)
+			return WEAPON_KLEINBOTTLE_MURDER;
+		else if(w_deathtype & HITTYPE_SECONDARY)
+			return WEAPON_ACCORDEON_MURDER;
+		else
+			return WEAPON_TUBA_MURDER;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_tuba(float req)
+{
+	// nothing to do here; particles of tuba are handled differently
+
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/w_uzi.qc b/qcsrc/server/w_uzi.qc
new file mode 100644
index 000000000..4fb604743
--- /dev/null
+++ b/qcsrc/server/w_uzi.qc
@@ -0,0 +1,337 @@
+#ifdef REGISTER_WEAPON
+REGISTER_WEAPON(
+/* WEP_##id  */ UZI,
+/* function  */ w_uzi,
+/* ammotype  */ IT_NAILS,
+/* impulse   */ 3,
+/* flags     */ WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN,
+/* rating    */ BOT_PICKUP_RATING_MID,
+/* model     */ "uzi",
+/* shortname */ "uzi",
+/* fullname  */ _("Machine Gun")
+);
+#else
+#ifdef SVQC
+
+// leilei's fancy muzzleflash stuff
+void UZI_Flash_Go()
+{
+	self.frame = self.frame + 2;
+	self.scale = self.scale * 0.5;
+	self.alpha = self.alpha - 0.25;
+	self.nextthink = time + 0.05;
+
+	if (self.alpha <= 0)
+	{
+		self.think = SUB_Remove;
+		self.nextthink = time;
+		self.realowner.muzzle_flash = world;
+		return;
+	}
+
+}
+
+void UziFlash()
+{
+	if (self.muzzle_flash == world)
+		self.muzzle_flash = spawn();
+
+	// muzzle flash for 1st person view
+	setmodel(self.muzzle_flash, "models/uziflash.md3"); // precision set below
+
+	self.muzzle_flash.scale = 0.75;
+	self.muzzle_flash.think = UZI_Flash_Go;
+	self.muzzle_flash.nextthink = time + 0.02;
+	self.muzzle_flash.frame = 2;
+	self.muzzle_flash.alpha = 0.75;
+	self.muzzle_flash.angles_z = random() * 180;
+	self.muzzle_flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
+	self.muzzle_flash.owner = self.muzzle_flash.realowner = self;
+}
+
+void W_UZI_Attack (float deathtype)
+{
+	W_SetupShot (self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, ((self.misc_bulletcounter == 1) ? autocvar_g_balance_uzi_first_damage : autocvar_g_balance_uzi_sustained_damage));
+	if (!autocvar_g_norecoil)
+	{
+		self.punchangle_x = random () - 0.5;
+		self.punchangle_y = random () - 0.5;
+	}
+
+	// this attack_finished just enforces a cooldown at the end of a burst
+	ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor();
+
+	if (self.misc_bulletcounter == 1)
+		fireBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_first_spread, autocvar_g_balance_uzi_solidpenetration, autocvar_g_balance_uzi_first_damage, autocvar_g_balance_uzi_first_force, deathtype, 0);
+	else
+		fireBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_sustained_spread, autocvar_g_balance_uzi_solidpenetration, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_force, deathtype, 0);
+
+	pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	UziFlash();
+	W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+
+	// casing code
+	if (autocvar_g_casings >= 2)
+		SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
+
+	if (self.misc_bulletcounter == 1)
+		W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_first_ammo, autocvar_g_balance_uzi_reload_ammo);
+	else
+		W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_reload_ammo);
+}
+
+// weapon frames
+void uzi_fire1_02()
+{
+	if(self.weapon != self.switchweapon) // abort immediately if switching
+	{
+		w_ready();
+		return;
+	}
+	if (self.BUTTON_ATCK)
+	{
+		if (!weapon_action(self.weapon, WR_CHECKAMMO2))
+		if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+		{
+			W_SwitchWeapon_Force(self, w_getbestweapon(self));
+			w_ready();
+			return;
+		}
+		self.misc_bulletcounter = self.misc_bulletcounter + 1;
+		W_UZI_Attack(WEP_UZI);
+		weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02);
+	}
+	else
+		weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, w_ready);
+}
+
+
+void uzi_mode1_fire_auto()
+{
+	float uzi_spread;
+
+	if (!self.BUTTON_ATCK)
+	{
+		w_ready();
+		return;
+	}
+
+	if (!weapon_action(self.weapon, WR_CHECKAMMO1))
+	if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+	{
+		W_SwitchWeapon_Force(self, w_getbestweapon(self));
+		w_ready();
+		return;
+	}
+
+	W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_reload_ammo);
+
+	W_SetupShot (self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_balance_uzi_sustained_damage);
+	if (!autocvar_g_norecoil)
+	{
+		self.punchangle_x = random () - 0.5;
+		self.punchangle_y = random () - 0.5;
+	}
+
+	uzi_spread = bound(autocvar_g_balance_uzi_spread_min, autocvar_g_balance_uzi_spread_min + (autocvar_g_balance_uzi_spread_add * self.misc_bulletcounter), autocvar_g_balance_uzi_spread_max);
+	fireBullet(w_shotorg, w_shotdir, uzi_spread, autocvar_g_balance_uzi_solidpenetration, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0);
+
+	self.misc_bulletcounter = self.misc_bulletcounter + 1;
+
+	pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	UziFlash();
+	W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+
+	if (autocvar_g_casings >= 2) // casing code
+		SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
+
+	ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_first_refire * W_WeaponRateFactor();
+	weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_mode1_fire_auto);
+}
+
+void uzi_mode1_fire_burst()
+{
+	W_SetupShot (self, TRUE, 0, "weapons/uzi_fire.wav", CH_WEAPON_A, autocvar_g_balance_uzi_sustained_damage);
+	if (!autocvar_g_norecoil)
+	{
+		self.punchangle_x = random () - 0.5;
+		self.punchangle_y = random () - 0.5;
+	}
+
+	fireBullet(w_shotorg, w_shotdir, autocvar_g_balance_uzi_burst_spread, autocvar_g_balance_uzi_solidpenetration, autocvar_g_balance_uzi_sustained_damage, autocvar_g_balance_uzi_sustained_force, WEP_UZI, 0);
+
+	pointparticles(particleeffectnum("uzi_muzzleflash"), w_shotorg, w_shotdir * 1000, 1);
+
+	UziFlash();
+	W_AttachToShotorg(self.muzzle_flash, '5 0 0');
+
+	if (autocvar_g_casings >= 2) // casing code
+		SpawnCasing (((random () * 50 + 50) * v_right) - (v_forward * (random () * 25 + 25)) - ((random () * 5 - 70) * v_up), 2, vectoangles(v_forward),'0 250 0', 100, 3, self);
+
+	self.misc_bulletcounter = self.misc_bulletcounter + 1;
+	if (self.misc_bulletcounter == 0)
+	{
+		ATTACK_FINISHED(self) = time + autocvar_g_balance_uzi_burst_refire2 * W_WeaponRateFactor();
+		weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_animtime, w_ready);
+	}
+	else
+	{
+		weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_burst_refire, uzi_mode1_fire_burst);
+	}
+
+}
+
+void spawnfunc_weapon_machinegun(); // defined in t_items.qc
+
+float w_uzi(float req)
+{
+	float ammo_amount;
+	if (req == WR_AIM)
+		if(vlen(self.origin-self.enemy.origin) < 3000 - bound(0, skill, 10) * 200)
+			self.BUTTON_ATCK = bot_aim(1000000, 0, 0.001, FALSE);
+		else
+		{
+			self.BUTTON_ATCK2 = bot_aim(1000000, 0, 0.001, FALSE);
+		}
+	else if (req == WR_THINK)
+	{
+		if(autocvar_g_balance_uzi_reload_ammo && self.clip_load < min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo)) // forced reload
+			weapon_action(self.weapon, WR_RELOAD);
+		else if(autocvar_g_balance_uzi_mode == 1)
+		{
+			if (self.BUTTON_ATCK)
+			if (weapon_prepareattack(0, 0))
+			{
+				self.misc_bulletcounter = 0;
+				uzi_mode1_fire_auto();
+			}
+
+			if(self.BUTTON_ATCK2)
+			if(weapon_prepareattack(1, 0))
+			{
+				if (!weapon_action(self.weapon, WR_CHECKAMMO2))
+				if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
+				{
+					W_SwitchWeapon_Force(self, w_getbestweapon(self));
+					w_ready();
+					return FALSE;
+				}
+
+				W_DecreaseAmmo(ammo_nails, autocvar_g_balance_uzi_burst_ammo, autocvar_g_balance_uzi_reload_ammo);
+
+				self.misc_bulletcounter = autocvar_g_balance_uzi_burst * -1;
+				uzi_mode1_fire_burst();
+			}
+		}
+		else
+		{
+
+			if (self.BUTTON_ATCK)
+			if (weapon_prepareattack(0, 0))
+			{
+				self.misc_bulletcounter = 1;
+				W_UZI_Attack(WEP_UZI); // sets attack_finished
+				weapon_thinkf(WFRAME_FIRE1, autocvar_g_balance_uzi_sustained_refire, uzi_fire1_02);
+			}
+
+			if (self.BUTTON_ATCK2 && autocvar_g_balance_uzi_first)
+			if (weapon_prepareattack(1, 0))
+			{
+				self.misc_bulletcounter = 1;
+				W_UZI_Attack(WEP_UZI | HITTYPE_SECONDARY); // sets attack_finished
+				weapon_thinkf(WFRAME_FIRE2, autocvar_g_balance_uzi_first_refire, w_ready);
+			}
+		}
+	}
+	else if (req == WR_PRECACHE)
+	{
+		precache_model ("models/uziflash.md3");
+		precache_model ("models/weapons/g_uzi.md3");
+		precache_model ("models/weapons/v_uzi.md3");
+		precache_model ("models/weapons/h_uzi.iqm");
+		precache_sound ("weapons/uzi_fire.wav");
+		//precache_sound ("weapons/reload.wav"); // until weapons have individual reload sounds, precache the reload sound somewhere else
+	}
+	else if (req == WR_SETUP)
+	{
+		weapon_setup(WEP_UZI);
+		self.current_ammo = ammo_nails;
+	}
+	else if (req == WR_CHECKAMMO1)
+	{
+		if(autocvar_g_balance_uzi_mode == 1)
+			ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_sustained_ammo;
+		else
+			ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo;
+
+		if(autocvar_g_balance_uzi_reload_ammo)
+		{
+			if(autocvar_g_balance_uzi_mode == 1)
+				ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_sustained_ammo;
+			else
+				ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_first_ammo;
+		}
+		return ammo_amount;
+	}
+	else if (req == WR_CHECKAMMO2)
+	{
+		if(autocvar_g_balance_uzi_mode == 1)
+			ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_burst_ammo;
+		else
+			ammo_amount = self.ammo_nails >= autocvar_g_balance_uzi_first_ammo;
+
+		if(autocvar_g_balance_uzi_reload_ammo)
+		{
+			if(autocvar_g_balance_uzi_mode == 1)
+				ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_burst_ammo;
+			else
+				ammo_amount += self.(weapon_load[WEP_UZI]) >= autocvar_g_balance_uzi_first_ammo;
+		}
+		return ammo_amount;
+	}
+	else if (req == WR_RELOAD)
+	{
+		W_Reload(min(max(autocvar_g_balance_uzi_sustained_ammo, autocvar_g_balance_uzi_first_ammo), autocvar_g_balance_uzi_burst_ammo), autocvar_g_balance_uzi_reload_ammo, autocvar_g_balance_uzi_reload_time, "weapons/reload.wav");
+	}
+	else if (req == WR_SUICIDEMESSAGE)
+	{
+		return WEAPON_THINKING_WITH_PORTALS;
+	}
+	else if (req == WR_KILLMESSAGE)
+	{
+		if(w_deathtype & HITTYPE_SECONDARY)
+			return WEAPON_UZI_MURDER_SNIPE;
+		else
+			return WEAPON_UZI_MURDER_SPRAY;
+	}
+	return TRUE;
+}
+#endif
+#ifdef CSQC
+float w_uzi(float req)
+{
+	if(req == WR_IMPACTEFFECT)
+	{
+		vector org2;
+		org2 = w_org + w_backoff * 2;
+		pointparticles(particleeffectnum("machinegun_impact"), org2, w_backoff * 1000, 1);
+		if(!w_issilent)
+			if(w_random < 0.05)
+				sound(self, CH_SHOTS, "weapons/ric1.wav", VOL_BASE, ATTEN_NORM);
+			else if(w_random < 0.1)
+				sound(self, CH_SHOTS, "weapons/ric2.wav", VOL_BASE, ATTEN_NORM);
+			else if(w_random < 0.2)
+				sound(self, CH_SHOTS, "weapons/ric3.wav", VOL_BASE, ATTEN_NORM);
+	}
+	else if(req == WR_PRECACHE)
+	{
+		precache_sound("weapons/ric1.wav");
+		precache_sound("weapons/ric2.wav");
+		precache_sound("weapons/ric3.wav");
+	}
+	return TRUE;
+}
+#endif
+#endif
diff --git a/qcsrc/server/weapons/accuracy.qc b/qcsrc/server/weapons/accuracy.qc
deleted file mode 100644
index 09d42332a..000000000
--- a/qcsrc/server/weapons/accuracy.qc
+++ /dev/null
@@ -1,124 +0,0 @@
-float accuracy_byte(float n, float d)
-{
-	//printf("accuracy: %d / %d\n", n, d);
-	if(n <= 0)
-		return 0;
-	if(n > d)
-		return 255;
-	return 1 + rint(n * 100.0 / d);
-}
-
-float accuracy_send(entity to, float sf)
-{
-	float w, f;
-	entity a;
-	WriteByte(MSG_ENTITY, ENT_CLIENT_ACCURACY);
-
-	a = self.owner;
-	if(IS_SPEC(a))
-		a = a.enemy;
-	a = a.accuracy;
-
-	if(to != a.owner)
-		if (!(self.owner.cvar_cl_accuracy_data_share && autocvar_sv_accuracy_data_share))
-			sf = 0;
-	// note: zero sendflags can never be sent... so we can use that to say that we send no accuracy!
-	WriteInt24_t(MSG_ENTITY, sf);
-	if(sf == 0)
-		return TRUE;
-	// note: we know that client and server agree about SendFlags...
-	for(w = 0, f = 1; w <= WEP_LAST - WEP_FIRST; ++w)
-	{
-		if(sf & f)
-			WriteByte(MSG_ENTITY, accuracy_byte(self.(accuracy_hit[w]), self.(accuracy_fired[w])));
-		if(f == 0x800000)
-			f = 1;
-		else
-			f *= 2;
-	}
-	return TRUE;
-}
-
-// init/free
-void accuracy_init(entity e)
-{
-	e.accuracy = spawn();
-	e.accuracy.owner = e;
-	e.accuracy.classname = "accuracy";
-	e.accuracy.drawonlytoclient = e;
-	Net_LinkEntity(e.accuracy, FALSE, 0, accuracy_send);
-}
-
-void accuracy_free(entity e)
-{
-	remove(e.accuracy);
-}
-
-// force a resend of a player's accuracy stats
-void accuracy_resend(entity e)
-{
-	e.accuracy.SendFlags = 0xFFFFFF;
-}
-
-// update accuracy stats
-.float hit_time;
-.float fired_time;
-
-void accuracy_add(entity e, float w, float fired, float hit)
-{
-	entity a;
-	float b;
-	if(IS_INDEPENDENT_PLAYER(e))
-		return;
-	a = e.accuracy;
-	if(!a || !(hit || fired))
-		return;
-	w -= WEP_FIRST;
-	b = accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w]));
-	if(hit)
-		a.(accuracy_hit[w]) += hit;
-	if(fired)
-		a.(accuracy_fired[w]) += fired;
-
-    if(hit && a.hit_time != time) // only run this once per frame
-    {
-        a.(accuracy_cnt_hit[w]) += 1;
-        a.hit_time = time;
-    }
-
-    if(fired && a.fired_time != time) // only run this once per frame
-    {
-        a.(accuracy_cnt_fired[w]) += 1;
-        a.fired_time = time;
-    }
-
-	if(b == accuracy_byte(a.(accuracy_hit[w]), a.(accuracy_fired[w])))
-		return;
-	w = pow(2, mod(w, 24));
-	a.SendFlags |= w;
-	FOR_EACH_CLIENT(a)
-		if(IS_SPEC(a))
-			if(a.enemy == e)
-				a.SendFlags |= w;
-}
-
-float accuracy_isgooddamage(entity attacker, entity targ)
-{
-	frag_attacker = attacker;
-	frag_target = targ;
-	float mutator_check = MUTATOR_CALLHOOK(AccuracyTargetValid);
-
-	if(!warmup_stage)
-	if(targ.deadflag == DEAD_NO)
-	if(mutator_check == MUT_ACCADD_INVALID || (mutator_check == MUT_ACCADD_VALID && IS_CLIENT(targ)))
-	if(DIFF_TEAM(attacker, targ))
-		return TRUE;
-	return FALSE;
-}
-
-float accuracy_canbegooddamage(entity attacker)
-{
-	if(!warmup_stage)
-		return TRUE;
-	return FALSE;
-}
diff --git a/qcsrc/server/weapons/accuracy.qh b/qcsrc/server/weapons/accuracy.qh
deleted file mode 100644
index 4cd43ee8a..000000000
--- a/qcsrc/server/weapons/accuracy.qh
+++ /dev/null
@@ -1,25 +0,0 @@
-.float cvar_cl_accuracy_data_share;
-.float cvar_cl_accuracy_data_receive;
-
-.entity accuracy;
-.float accuracy_frags[WEP_MAXCOUNT];
-
-.float accuracy_hit[WEP_MAXCOUNT];
-.float accuracy_fired[WEP_MAXCOUNT];
-.float accuracy_cnt_hit[WEP_MAXCOUNT];
-.float accuracy_cnt_fired[WEP_MAXCOUNT];
-
-
-// init/free
-void accuracy_init(entity e);
-void accuracy_free(entity e);
-
-// force a resend of a player's accuracy stats
-void accuracy_resend(entity e);
-
-// update accuracy stats
-void accuracy_add(entity e, float w, float fired, float hit);
-
-// helper
-float accuracy_isgooddamage(entity attacker, entity targ);
-float accuracy_canbegooddamage(entity attacker);
diff --git a/qcsrc/server/weapons/common.qc b/qcsrc/server/weapons/common.qc
deleted file mode 100644
index 6e54cb060..000000000
--- a/qcsrc/server/weapons/common.qc
+++ /dev/null
@@ -1,89 +0,0 @@
-
-void W_GiveWeapon (entity e, float wep)
-{
-	entity oldself;
-
-	if (!wep)
-		return;
-
-	e.weapons |= WepSet_FromWeapon(wep);
-
-	oldself = self;
-	self = e;
-
-	if(IS_PLAYER(other))
-		{ Send_Notification(NOTIF_ONE, other, MSG_MULTI, ITEM_WEAPON_GOT, wep); }
-
-	self = oldself;
-}
-
-void W_PlayStrengthSound(entity player) // void W_PlayStrengthSound
-{
-	if((player.items & IT_STRENGTH)
-		&& ((time > player.prevstrengthsound + autocvar_sv_strengthsound_antispam_time) // prevent insane sound spam
-		|| (time > player.prevstrengthsoundattempt + autocvar_sv_strengthsound_antispam_refire_threshold)))
-		{
-			sound(player, CH_TRIGGER, "weapons/strength_fire.wav", VOL_BASE, ATTEN_NORM);
-			player.prevstrengthsound = time;
-		}
-		player.prevstrengthsoundattempt = time;
-}
-
-float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception)
-{
-	float is_from_contents = (deathtype == DEATH_SLIME || deathtype == DEATH_LAVA);
-	float is_from_owner = (inflictor == projowner);
-	float is_from_exception = (exception != -1);
-	
-	//dprint(strcat("W_CheckProjectileDamage: from_contents ", ftos(is_from_contents), " : from_owner ", ftos(is_from_owner), " : exception ", strcat(ftos(is_from_exception), " (", ftos(exception), "). \n")));
-
-	if(autocvar_g_projectiles_damage <= -2)
-	{
-		return FALSE; // no damage to projectiles at all, not even with the exceptions
-	}
-	else if(autocvar_g_projectiles_damage == -1)
-	{
-		if(is_from_exception)
-			return (exception); // if exception is detected, allow it to override
-		else
-			return FALSE; // otherwise, no other damage is allowed
-	}
-	else if(autocvar_g_projectiles_damage == 0)
-	{
-		if(is_from_exception)
-			return (exception); // if exception is detected, allow it to override
-		else if(!is_from_contents)
-			return FALSE; // otherwise, only allow damage from contents
-	}	
-	else if(autocvar_g_projectiles_damage == 1)
-	{
-		if(is_from_exception)
-			return (exception); // if exception is detected, allow it to override
-		else if(!(is_from_contents || is_from_owner))
-			return FALSE; // otherwise, only allow self damage and damage from contents
-	}
-	else if(autocvar_g_projectiles_damage == 2) // allow any damage, but override for exceptions
-	{
-		if(is_from_exception)
-			return (exception); // if exception is detected, allow it to override
-	}
-
-	return TRUE; // if none of these return, then allow damage anyway.
-}
-
-void W_PrepareExplosionByDamage(entity attacker, void() explode)
-{
-	self.takedamage = DAMAGE_NO;
-	self.event_damage = func_null;
-	
-	if(IS_CLIENT(attacker) && !autocvar_g_projectiles_keep_owner)
-	{
-		self.owner = attacker;
-		self.realowner = attacker;
-	}
-	
-	// do not explode NOW but in the NEXT FRAME!
-	// because recursive calls to RadiusDamage are not allowed
-	self.nextthink = time;
-	self.think = explode;
-}
diff --git a/qcsrc/server/weapons/common.qh b/qcsrc/server/weapons/common.qh
deleted file mode 100644
index 8f9454ed5..000000000
--- a/qcsrc/server/weapons/common.qh
+++ /dev/null
@@ -1,7 +0,0 @@
-
-void W_GiveWeapon (entity e, float wep);
-.float prevstrengthsound;
-.float prevstrengthsoundattempt;
-void W_PlayStrengthSound(entity player);
-float W_CheckProjectileDamage(entity inflictor, entity projowner, float deathtype, float exception);
-void W_PrepareExplosionByDamage(entity attacker, void() explode);
diff --git a/qcsrc/server/weapons/csqcprojectile.qc b/qcsrc/server/weapons/csqcprojectile.qc
deleted file mode 100644
index 3dd93c058..000000000
--- a/qcsrc/server/weapons/csqcprojectile.qc
+++ /dev/null
@@ -1,114 +0,0 @@
-.float csqcprojectile_type;
-
-float CSQCProjectile_SendEntity(entity to, float sf)
-{
-	float ft, fr;
-
-	// note: flag 0x08 = no trail please (teleport bit)
-	sf = sf & 0x0F;
-
-	if(self.csqcprojectile_clientanimate)
-		sf |= 0x80; // client animated, not interpolated
-
-	if(self.flags & FL_ONGROUND)
-		sf |= 0x40;
-
-	ft = fr = 0;
-	if(self.fade_time != 0 || self.fade_rate != 0)
-	{
-		ft = (self.fade_time - time) / sys_frametime;
-		fr = (1 / self.fade_rate) / sys_frametime;
-		if(ft <= 255 && fr <= 255 && fr >= 1)
-			sf |= 0x20;
-	}
-
-	if(self.gravity != 0)
-		sf |= 0x10;
-
-	WriteByte(MSG_ENTITY, ENT_CLIENT_PROJECTILE);
-	WriteByte(MSG_ENTITY, sf);
-
-	if(sf & 1)
-	{
-		WriteCoord(MSG_ENTITY, self.origin_x);
-		WriteCoord(MSG_ENTITY, self.origin_y);
-		WriteCoord(MSG_ENTITY, self.origin_z);
-
-		if(sf & 0x80)
-		{
-			WriteCoord(MSG_ENTITY, self.velocity_x);
-			WriteCoord(MSG_ENTITY, self.velocity_y);
-			WriteCoord(MSG_ENTITY, self.velocity_z);
-			if(sf & 0x10)
-				WriteCoord(MSG_ENTITY, self.gravity);
-		}
-
-		if(sf & 0x20)
-		{
-			WriteByte(MSG_ENTITY, ft);
-			WriteByte(MSG_ENTITY, fr);
-		}
-
-		WriteByte(MSG_ENTITY, self.realowner.team);
-	}
-
-	if(sf & 2)
-		WriteByte(MSG_ENTITY, self.csqcprojectile_type); // TODO maybe put this into sf?
-
-	return 1;
-}
-
-.vector csqcprojectile_oldorigin;
-void CSQCProjectile_Check(entity e)
-{
-	if(e.csqcprojectile_clientanimate)
-	if(e.flags & FL_ONGROUND)
-	if(e.origin != e.csqcprojectile_oldorigin)
-		UpdateCSQCProjectile(e);
-	e.csqcprojectile_oldorigin = e.origin;
-}
-
-void CSQCProjectile(entity e, float clientanimate, float type, float docull)
-{
-	Net_LinkEntity(e, docull, 0, CSQCProjectile_SendEntity);
-
-	e.csqcprojectile_clientanimate = clientanimate;
-
-	if(e.movetype == MOVETYPE_TOSS || e.movetype == MOVETYPE_BOUNCE)
-	{
-		if(e.gravity == 0)
-			e.gravity = 1;
-	}
-	else
-		e.gravity = 0;
-
-	if(!sound_allowed(MSG_BROADCAST, e))
-		type |= 0x80;
-	e.csqcprojectile_type = type;
-}
-
-void UpdateCSQCProjectile(entity e)
-{
-	if(e.SendEntity == CSQCProjectile_SendEntity)
-	{
-		// send new origin data
-		e.SendFlags |= 0x01;
-	}
-// FIXME HACK
-	else if(e.SendEntity == ItemSend)
-	{
-		ItemUpdate(e);
-	}
-// END HACK
-}
-
-void UpdateCSQCProjectileAfterTeleport(entity e)
-{
-	if(e.SendEntity == CSQCProjectile_SendEntity)
-	{
-		// send new origin data
-		e.SendFlags |= 0x01;
-		// mark as teleported
-		e.SendFlags |= 0x08;
-	}
-}
diff --git a/qcsrc/server/weapons/csqcprojectile.qh b/qcsrc/server/weapons/csqcprojectile.qh
deleted file mode 100644
index e00c0988b..000000000
--- a/qcsrc/server/weapons/csqcprojectile.qh
+++ /dev/null
@@ -1,6 +0,0 @@
-.float csqcprojectile_clientanimate;
-
-void CSQCProjectile(entity e, float clientanimate, float type, float docull);
-void UpdateCSQCProjectile(entity e);
-void UpdateCSQCProjectileAfterTeleport(entity e);
-void CSQCProjectile_Check(entity e);
diff --git a/qcsrc/server/weapons/hitplot.qc b/qcsrc/server/weapons/hitplot.qc
deleted file mode 100644
index 685741dab..000000000
--- a/qcsrc/server/weapons/hitplot.qc
+++ /dev/null
@@ -1,91 +0,0 @@
-vector W_HitPlotUnnormalizedUntransform(vector screenforward, vector screenright, vector screenup, vector v)
-{
-	vector ret;
-	ret_x = screenright * v;
-	ret_y = screenup * v;
-	ret_z = screenforward * v;
-	return ret;
-}
-
-vector W_HitPlotNormalizedUntransform(vector org, entity targ, vector screenforward, vector screenright, vector screenup, vector v)
-{
-	float i, j, k;
-	vector mi, ma, thisv, myv, ret;
-
-	myv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, org);
-
-	// x = 0..1 relative to hitbox; y = 0..1 relative to hitbox; z = distance
-
-	mi = ma = targ.origin + 0.5 * (targ.mins + targ.maxs);
-	for(i = 0; i < 2; ++i) for(j = 0; j < 2; ++j) for(k = 0; k < 2; ++k)
-	{
-		thisv = targ.origin;
-		if(i) thisv_x += targ.maxs_x; else thisv_x += targ.mins_x;
-		if(j) thisv_y += targ.maxs_y; else thisv_y += targ.mins_y;
-		if(k) thisv_z += targ.maxs_z; else thisv_z += targ.mins_z;
-		thisv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, thisv);
-		if(i || j || k)
-		{
-			if(mi_x > thisv_x) mi_x = thisv_x; if(ma_x < thisv_x) ma_x = thisv_x;
-			if(mi_y > thisv_y) mi_y = thisv_y; if(ma_y < thisv_y) ma_y = thisv_y;
-			//if(mi_z > thisv_z) mi_z = thisv_z; if(ma_z < thisv_z) ma_y = thisv_z;
-		}
-		else
-		{
-			// first run
-			mi = ma = thisv;
-		}
-	}
-
-	thisv = W_HitPlotUnnormalizedUntransform(screenforward, screenright, screenup, v);
-	ret_x = (thisv_x - mi_x) / (ma_x - mi_x);
-	ret_y = (thisv_y - mi_y) / (ma_y - mi_y);
-	ret_z = thisv_z - myv_z;
-	return ret;
-}
-
-void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright, vector screenup)
-{
-	vector hitplot;
-	vector org;
-	float lag;
-
-	if(player.hitplotfh >= 0)
-	{
-		lag = ANTILAG_LATENCY(player);
-		if(lag < 0.001)
-			lag = 0;
-		if(!IS_REAL_CLIENT(player))
-			lag = 0; // only antilag for clients
-
-		org = player.origin + player.view_ofs;
-		traceline_antilag_force(player, org, org + screenforward * MAX_SHOT_DISTANCE, MOVE_NORMAL, player, lag);
-		if(IS_CLIENT(trace_ent) || (trace_ent.flags & FL_MONSTER))
-		{
-			antilag_takeback(trace_ent, time - lag);
-			hitplot = W_HitPlotNormalizedUntransform(org, trace_ent, screenforward, screenright, screenup, trace_endpos);
-			antilag_restore(trace_ent);
-			fputs(player.hitplotfh, strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), " ", ftos(player.switchweapon), "\n"));
-			//print(strcat(ftos(hitplot_x), " ", ftos(hitplot_y), " ", ftos(hitplot_z), "\n"));
-		}
-	}
-}
-
-void W_HitPlotOpen(entity player)
-{
-	if(autocvar_g_hitplots || strstrofs(strcat(" ", autocvar_g_hitplots_individuals, " "), strcat(" ", player.netaddress, " "), 0) >= 0)
-	{
-		player.hitplotfh = fopen(strcat("hits-", matchid, "-", player.netaddress, "-", ftos(player.playerid), ".plot"), FILE_WRITE);
-		fputs(player.hitplotfh, strcat("#name ", player.netname, "\n"));
-	}
-	else { player.hitplotfh = -1; }
-}
-
-void W_HitPlotClose(entity player)
-{
-	if(player.hitplotfh >= 0)
-	{
-		fclose(player.hitplotfh);
-		player.hitplotfh = -1;
-	}
-}
diff --git a/qcsrc/server/weapons/hitplot.qh b/qcsrc/server/weapons/hitplot.qh
deleted file mode 100644
index 9bc8ff303..000000000
--- a/qcsrc/server/weapons/hitplot.qh
+++ /dev/null
@@ -1,5 +0,0 @@
-.float hitplotfh;
-
-void W_HitPlotAnalysis(entity player, vector screenforward, vector screenright, vector screenup);
-void W_HitPlotOpen(entity player);
-void W_HitPlotClose(entity player);
diff --git a/qcsrc/server/weapons/selection.qc b/qcsrc/server/weapons/selection.qc
deleted file mode 100644
index 482b3180a..000000000
--- a/qcsrc/server/weapons/selection.qc
+++ /dev/null
@@ -1,283 +0,0 @@
-// switch between weapons
-void Send_WeaponComplain(entity e, float wpn, float type)
-{
-	msg_entity = e;
-	WriteByte(MSG_ONE, SVC_TEMPENTITY);
-	WriteByte(MSG_ONE, TE_CSQC_WEAPONCOMPLAIN);
-	WriteByte(MSG_ONE, wpn);
-	WriteByte(MSG_ONE, type);
-}
-
-float client_hasweapon(entity cl, float wpn, float andammo, float complain)
-{
-	float f;
-	entity oldself;
-
-	if(time < self.hasweapon_complain_spam)
-		complain = 0;
-
-	if(wpn == WEP_HOOK && !g_grappling_hook && autocvar_g_nades && !((cl.weapons | weaponsInMap) & WepSet_FromWeapon(wpn)))
-		complain = 0;
-		
-	if(complain)
-		self.hasweapon_complain_spam = time + 0.2;
-
-	if (wpn < WEP_FIRST || wpn > WEP_LAST)
-	{
-		if (complain)
-			sprint(self, "Invalid weapon\n");
-		return FALSE;
-	}
-	if (cl.weapons & WepSet_FromWeapon(wpn))
-	{
-		if (andammo)
-		{
-			if(cl.items & IT_UNLIMITED_WEAPON_AMMO)
-			{
-				f = 1;
-			}
-			else
-			{
-				oldself = self;
-				self = cl;
-				f = WEP_ACTION(wpn, WR_CHECKAMMO1);
-				f = f + WEP_ACTION(wpn, WR_CHECKAMMO2);
-
-				// always allow selecting the Mine Layer if we placed mines, so that we can detonate them
-				entity mine;
-				if(wpn == WEP_MINE_LAYER)
-				for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
-					f = 1;
-
-				self = oldself;
-			}
-			if (!f)
-			{
-				if (complain)
-				if(IS_REAL_CLIENT(cl))
-				{
-					play2(cl, "weapons/unavailable.wav");
-					Send_WeaponComplain (cl, wpn, 0);
-				}
-				return FALSE;
-			}
-		}
-		return TRUE;
-	}
-	if (complain)
-	{
-		// DRESK - 3/16/07
-		// Report Proper Weapon Status / Modified Weapon Ownership Message
-		if (weaponsInMap & WepSet_FromWeapon(wpn))
-		{
-			Send_WeaponComplain(cl, wpn, 1);
-
-			if(autocvar_g_showweaponspawns)
-			{
-				entity e;
-
-				for(e = world; (e = findfloat(e, weapon, wpn)); )
-				{
-					if(e.classname == "droppedweapon")
-						continue;
-					if(!(e.flags & FL_ITEM))
-						continue;
-					WaypointSprite_Spawn(
-						(get_weaponinfo(wpn)).wpmodel,
-						1, 0,
-						world, e.origin,
-						self, 0,
-						world, enemy,
-						0,
-						RADARICON_NONE, '0 0 0'
-					);
-				}
-			}
-		}
-		else
-		{
-			Send_WeaponComplain (cl, wpn, 2);
-		}
-
-		play2(cl, "weapons/unavailable.wav");
-	}
-	return FALSE;
-}
-
-float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing)
-{
-	// We cannot tokenize in this function, as GiveItems calls this
-	// function. Thus we must use car/cdr.
-	float weaponwant, first_valid, prev_valid, switchtonext, switchtolast, c;
-	string rest;
-	switchtonext = switchtolast = 0;
-	first_valid = prev_valid = 0;
-	float weaponcur;
-	entity wep;
-
-	if(skipmissing || pl.selectweapon == 0)
-		weaponcur = pl.switchweapon;
-	else
-		weaponcur = pl.selectweapon;
-
-	if(dir == 0)
-		switchtonext = 1;
-
-	c = 0;
-
-	rest = weaponorder;
-	while(rest != "")
-	{
-		weaponwant = stof(car(rest)); rest = cdr(rest);
-		wep = get_weaponinfo(weaponwant);
-		if(imp >= 0)
-			if(wep.impulse != imp)
-				continue;
-
-		// skip weapons we don't own that aren't normal and aren't in the map
-		if(!(pl.weapons & WepSet_FromWeapon(weaponwant)))
-			if(!((get_weaponinfo(weaponwant)).spawnflags & WEP_FLAG_NORMAL))
-				if(!(weaponsInMap & WepSet_FromWeapon(weaponwant)))
-					continue;
-
-		++c;
-
-		if(!skipmissing || client_hasweapon(pl, weaponwant, TRUE, FALSE))
-		{
-			if(switchtonext)
-				return weaponwant;
-			if(!first_valid)
-				first_valid = weaponwant;
-			if(weaponwant == weaponcur)
-			{
-				if(dir >= 0)
-					switchtonext = 1;
-				else if(prev_valid)
-					return prev_valid;
-				else
-					switchtolast = 1;
-			}
-			prev_valid = weaponwant;
-		}
-	}
-	if(first_valid)
-	{
-		if(switchtolast)
-			return prev_valid;
-		else
-			return first_valid;
-	}
-	// complain (but only for one weapon on the button that has been pressed)
-	if(complain)
-	{
-		self.weaponcomplainindex += 1;
-		c = mod(self.weaponcomplainindex, c) + 1;
-		rest = weaponorder;
-		while(rest != "")
-		{
-			weaponwant = stof(car(rest)); rest = cdr(rest);
-			wep = get_weaponinfo(weaponwant);
-			if(imp >= 0)
-				if(wep.impulse != imp)
-					continue;
-
-			// skip weapons we don't own that aren't normal and aren't in the map
-			if(!(pl.weapons & WepSet_FromWeapon(weaponwant)))
-				if(!((get_weaponinfo(weaponwant)).spawnflags & WEP_FLAG_NORMAL))
-					if(!(weaponsInMap & WepSet_FromWeapon(weaponwant)))
-						continue;
-
-			--c;
-			if(c == 0)
-			{
-				client_hasweapon(pl, weaponwant, TRUE, TRUE);
-				break;
-			}
-		}
-	}
-	return 0;
-}
-
-void W_SwitchWeapon_Force(entity e, float w)
-{
-	e.cnt = e.switchweapon;
-	e.switchweapon = w;
-	e.selectweapon = w;
-}
-
-// perform weapon to attack (weaponstate and attack_finished check is here)
-void W_SwitchToOtherWeapon(entity pl)
-{
-	// hack to ensure it switches to an OTHER weapon (in case the other fire mode still has ammo, we want that anyway)
-	float w, ww;
-	w = pl.weapon;
-	if(pl.weapons & WepSet_FromWeapon(w))
-	{
-		pl.weapons &= ~WepSet_FromWeapon(w);
-		ww = w_getbestweapon(pl);
-		pl.weapons |= WepSet_FromWeapon(w);
-	}
-	else
-		ww = w_getbestweapon(pl);
-	if(ww)
-		W_SwitchWeapon_Force(pl, ww);
-}
-
-void W_SwitchWeapon(float imp)
-{
-	if (self.switchweapon != imp)
-	{
-		if (client_hasweapon(self, imp, TRUE, TRUE))
-			W_SwitchWeapon_Force(self, imp);
-		else
-			self.selectweapon = imp; // update selectweapon ANYWAY
-	}
-	else { WEP_ACTION(self.weapon, WR_RELOAD); }
-}
-
-void W_CycleWeapon(string weaponorder, float dir)
-{
-	float w;
-	w = W_GetCycleWeapon(self, weaponorder, dir, -1, 1, TRUE);
-	if(w > 0)
-		W_SwitchWeapon(w);
-}
-
-void W_NextWeaponOnImpulse(float imp)
-{
-	float w;
-	w = W_GetCycleWeapon(self, self.cvar_cl_weaponpriority, +1, imp, 1, (self.cvar_cl_weaponimpulsemode == 0));
-	if(w > 0)
-		W_SwitchWeapon(w);
-}
-
-// next weapon
-void W_NextWeapon(float list)
-{
-	if(list == 0)
-		W_CycleWeapon(weaponorder_byid, -1);
-	else if(list == 1)
-		W_CycleWeapon(self.weaponorder_byimpulse, -1);
-	else if(list == 2)
-		W_CycleWeapon(self.cvar_cl_weaponpriority, -1);
-}
-
-// prev weapon
-void W_PreviousWeapon(float list)
-{
-	if(list == 0)
-		W_CycleWeapon(weaponorder_byid, +1);
-	else if(list == 1)
-		W_CycleWeapon(self.weaponorder_byimpulse, +1);
-	else if(list == 2)
-		W_CycleWeapon(self.cvar_cl_weaponpriority, +1);
-}
-
-// previously used if exists and has ammo, (second) best otherwise
-void W_LastWeapon(void)
-{
-	if(client_hasweapon(self, self.cnt, TRUE, FALSE))
-		W_SwitchWeapon(self.cnt);
-	else
-		W_SwitchToOtherWeapon(self);
-}
diff --git a/qcsrc/server/weapons/selection.qh b/qcsrc/server/weapons/selection.qh
deleted file mode 100644
index 8e2937f0c..000000000
--- a/qcsrc/server/weapons/selection.qh
+++ /dev/null
@@ -1,29 +0,0 @@
-// switch between weapons
-void Send_WeaponComplain(entity e, float wpn, float type);
-
-.float hasweapon_complain_spam;
-float client_hasweapon(entity cl, float wpn, float andammo, float complain);
-
-.float weaponcomplainindex;
-float W_GetCycleWeapon(entity pl, string weaponorder, float dir, float imp, float complain, float skipmissing);
-
-#define w_getbestweapon(ent) W_GetCycleWeapon(ent, ent.cvar_cl_weaponpriority, 0, -1, FALSE, TRUE)
-
-void W_SwitchWeapon_Force(entity e, float w);
-
-// perform weapon to attack (weaponstate and attack_finished check is here)
-void W_SwitchToOtherWeapon(entity pl);
-void W_SwitchWeapon(float imp);
-
-void W_CycleWeapon(string weaponorder, float dir);
-
-void W_NextWeaponOnImpulse(float imp);
-
-// next weapon
-void W_NextWeapon(float list);
-
-// prev weapon
-void W_PreviousWeapon(float list);
-
-// previously used if exists and has ammo, (second) best otherwise
-void W_LastWeapon(void);
diff --git a/qcsrc/server/weapons/spawning.qc b/qcsrc/server/weapons/spawning.qc
deleted file mode 100644
index 04dd3f6f2..000000000
--- a/qcsrc/server/weapons/spawning.qc
+++ /dev/null
@@ -1,181 +0,0 @@
-string W_Apply_Weaponreplace(string in)
-{
-	float n = tokenize_console(in);
-	string out = "", s, replacement;
-	float i, j;
-	entity e;
-	for(i = 0; i < n; ++i)
-	{
-		replacement = "";
-		s = argv(i);
-		
-		for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-		{
-			e = get_weaponinfo(j);
-			if(e.netname == s)
-			{
-				replacement = e.weaponreplace;
-			}
-		}
-
-		if(replacement == "")
-			out = strcat(out, " ", s);
-		else if(replacement != "0")
-			out = strcat(out, " ", replacement);
-	}
-	return substring(out, 1, -1);
-}
-
-void weapon_defaultspawnfunc(float wpn)
-{
-	entity e;
-	float t;
-	string s;
-	entity oldself;
-	float i, j;
-	float f;
-
-	if(self.classname != "droppedweapon" && self.classname != "replacedweapon")
-	{
-		e = get_weaponinfo(wpn);
-
-		if(e.spawnflags & WEP_FLAG_MUTATORBLOCKED)
-		{
-			objerror("Attempted to spawn a mutator-blocked weapon rejected");
-			startitem_failed = TRUE;
-			return;
-		}
-
-		s = W_Apply_Weaponreplace(e.netname);
-		ret_string = s;
-		other = e;
-		MUTATOR_CALLHOOK(SetWeaponreplace);
-		s = ret_string;
-		if(s == "")
-		{
-			remove(self);
-			startitem_failed = TRUE;
-			return;
-		}
-		t = tokenize_console(s);
-		if(t >= 2)
-		{
-			self.team = --internalteam;
-			oldself = self;
-			for(i = 1; i < t; ++i)
-			{
-				s = argv(i);
-				for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-				{
-					e = get_weaponinfo(j);
-					if(e.netname == s)
-					{
-						self = spawn();
-						copyentity(oldself, self);
-						self.classname = "replacedweapon";
-						weapon_defaultspawnfunc(j);
-						break;
-					}
-				}
-				if(j > WEP_LAST)
-				{
-					print("The weapon replace list for ", oldself.classname, " contains an unknown weapon ", s, ". Skipped.\n");
-				}
-			}
-			self = oldself;
-		}
-		if(t >= 1) // always the case!
-		{
-			s = argv(0);
-			wpn = 0;
-			for(j = WEP_FIRST; j <= WEP_LAST; ++j)
-			{
-				e = get_weaponinfo(j);
-				if(e.netname == s)
-				{
-					wpn = j;
-					break;
-				}
-			}
-			if(j > WEP_LAST)
-			{
-				print("The weapon replace list for ", self.classname, " contains an unknown weapon ", s, ". Skipped.\n");
-			}
-		}
-		if(wpn == 0)
-		{
-			remove(self);
-			startitem_failed = TRUE;
-			return;
-		}
-	}
-
-	e = get_weaponinfo(wpn);
-
-	if(!self.respawntime)
-	{
-		if(e.weapons & WEPSET_SUPERWEAPONS)
-		{
-			self.respawntime = g_pickup_respawntime_superweapon;
-			self.respawntimejitter = g_pickup_respawntimejitter_superweapon;
-		}
-		else
-		{
-			self.respawntime = g_pickup_respawntime_weapon;
-			self.respawntimejitter = g_pickup_respawntimejitter_weapon;
-		}
-	}
-
-	if(e.weapons & WEPSET_SUPERWEAPONS)
-		if(!self.superweapons_finished)
-			self.superweapons_finished = autocvar_g_balance_superweapons_time;
-
-	// if we don't already have ammo, give us some ammo
-	if(!self.(e.ammo_field))
-	{
-		switch(e.ammo_field)
-		{
-			case ammo_shells:  self.ammo_shells  = cvar("g_pickup_shells_weapon");  break;
-			case ammo_nails:   self.ammo_nails   = cvar("g_pickup_nails_weapon");   break;
-			case ammo_rockets: self.ammo_rockets = cvar("g_pickup_rockets_weapon"); break;
-			case ammo_cells:   self.ammo_cells   = cvar("g_pickup_cells_weapon");   break;
-			case ammo_plasma:  self.ammo_plasma  = cvar("g_pickup_plasma_weapon");  break;
-			case ammo_fuel:    self.ammo_fuel    = cvar("g_pickup_fuel_weapon");    break;
-		}
-	}
-
-	#if 0 // WEAPONTODO
-	if(e.items)
-	{
-		for(i = 0, j = 1; i < 24; ++i, j *= 2)
-		{
-			if(e.items & j)
-			{
-				ammotype = Item_CounterField(j);
-				if(!self.ammotype)
-					self.ammotype = cvar(strcat("g_pickup_", Item_CounterFieldName(j), "_weapon"));
-			}
-		}
-	}
-	#endif
-
-	// pickup anyway
-	if(g_pickup_weapons_anyway)
-		self.pickup_anyway = TRUE;
-
-	f = FL_WEAPON;
-
-	// no weapon-stay on superweapons
-	if(e.weapons & WEPSET_SUPERWEAPONS)
-		f |= FL_NO_WEAPON_STAY;
-
-	// weapon stay isn't supported for teamed weapons
-	if(self.team)
-		f |= FL_NO_WEAPON_STAY;
-
-	StartItem(e.model, "weapons/weaponpickup.wav", self.respawntime, self.respawntimejitter, e.message, 0, e.weapon, f, weapon_pickupevalfunc, e.bot_pickupbasevalue);
-	#if 0 // WEAPONTODO
-	if (self.modelindex) // don't precache if self was removed
-		WEP_ACTION(e.weapon, WR_INIT);
-	#endif
-}
diff --git a/qcsrc/server/weapons/spawning.qh b/qcsrc/server/weapons/spawning.qh
deleted file mode 100644
index c6939e53a..000000000
--- a/qcsrc/server/weapons/spawning.qh
+++ /dev/null
@@ -1,3 +0,0 @@
-string W_Apply_Weaponreplace(string in);
-
-void weapon_defaultspawnfunc(float wpn);
diff --git a/qcsrc/server/weapons/throwing.qc b/qcsrc/server/weapons/throwing.qc
deleted file mode 100644
index 2d5a83118..000000000
--- a/qcsrc/server/weapons/throwing.qc
+++ /dev/null
@@ -1,187 +0,0 @@
-void thrown_wep_think()
-{
-	self.nextthink = time;
-	if(self.oldorigin != self.origin)
-	{
-		self.SendFlags |= ISF_LOCATION;
-		self.oldorigin = self.origin;
-	}
-	self.owner = world;
-	float timeleft = self.savenextthink - time;
-	if(timeleft > 1)
-		SUB_SetFade(self, self.savenextthink - 1, 1);
-	else if(timeleft > 0)
-		SUB_SetFade(self, time, timeleft);
-	else
-		SUB_VanishOrRemove(self);
-}
-
-// returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo)
-{
-	entity oldself, wep;
-	float thisammo, i;
-	string s;
-	var .float ammotype = (get_weaponinfo(wpn)).ammo_field;
-
-	wep = spawn();
-
-	setorigin(wep, org);
-	wep.classname = "droppedweapon";
-	wep.velocity = velo;
-	wep.owner = wep.enemy = own;
-	wep.flags |= FL_TOSSED;
-	wep.colormap = own.colormap;
-
-	if(WepSet_FromWeapon(wpn) & WEPSET_SUPERWEAPONS)
-	{
-		if(own.items & IT_UNLIMITED_SUPERWEAPONS)
-		{
-			wep.superweapons_finished = time + autocvar_g_balance_superweapons_time;
-		}
-		else
-		{
-			float superweapons = 1;
-			for(i = WEP_FIRST; i <= WEP_LAST; ++i)
-				if(WepSet_FromWeapon(i) & WEPSET_SUPERWEAPONS)
-					if(own.weapons & WepSet_FromWeapon(i))
-						++superweapons;
-			if(superweapons <= 1)
-			{
-				wep.superweapons_finished = own.superweapons_finished;
-				own.superweapons_finished = 0;
-			}
-			else
-			{
-				float timeleft = own.superweapons_finished - time;
-				float weptimeleft = timeleft / superweapons;
-				wep.superweapons_finished = time + weptimeleft;
-				own.superweapons_finished -= weptimeleft;
-			}
-		}
-	}
-
-	oldself = self;
-	self = wep;
-	weapon_defaultspawnfunc(wpn);
-	self = oldself;
-	if(startitem_failed)
-		return string_null;
-	wep.glowmod = own.weaponentity_glowmod;
-	wep.think = thrown_wep_think;
-	wep.savenextthink = wep.nextthink;
-	wep.nextthink = min(wep.nextthink, time + 0.5);
-	wep.pickup_anyway = TRUE; // these are ALWAYS pickable
-	
-	//wa = W_AmmoItemCode(wpn);
-	if(ammotype == ammo_none)
-	{
-		return "";
-	}
-	else
-	{
-		s = "";
-
-		if(doreduce && g_weapon_stay == 2)
-		{
-			// if our weapon is loaded, give its load back to the player
-			if(self.(weapon_load[self.weapon]) > 0)
-			{
-				own.ammotype += self.(weapon_load[self.weapon]);
-				self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading
-			}
-
-			wep.ammotype = 0;
-		}
-		else if(doreduce)
-		{
-			// if our weapon is loaded, give its load back to the player
-			if(self.(weapon_load[self.weapon]) > 0)
-			{
-				own.ammotype += self.(weapon_load[self.weapon]);
-				self.(weapon_load[self.weapon]) = -1; // schedule the weapon for reloading
-			}
-
-			thisammo = min(own.ammotype, wep.ammotype);
-			wep.ammotype = thisammo;
-			own.ammotype -= thisammo;
-
-			switch(ammotype)
-			{
-				case ammo_shells:  s = sprintf("%s and %d shells", s, thisammo);  break;
-				case ammo_nails:   s = sprintf("%s and %d nails", s, thisammo);   break;
-				case ammo_rockets: s = sprintf("%s and %d rockets", s, thisammo); break;
-				case ammo_cells:   s = sprintf("%s and %d cells", s, thisammo);   break;
-				case ammo_plasma:  s = sprintf("%s and %d plasma", s, thisammo);  break;
-				case ammo_fuel:    s = sprintf("%s and %d fuel", s, thisammo);    break;
-			}
-
-			s = substring(s, 5, -1);
-		}
-		return s;
-	}
-}
-
-float W_IsWeaponThrowable(float w)
-{
-	if (!autocvar_g_pickup_items)
-		return 0;
-	if (g_weaponarena)
-		return 0;
-	if (g_cts)
-		return 0;
-	if (g_nexball && w == WEP_MORTAR)
-		return 0;
-    if(w == 0)
-        return 0;
-
-	#if 0
-	if(start_weapons & WepSet_FromWeapon(w))
-	{
-		// start weapons that take no ammo can't be dropped (this prevents dropping the laser, as long as it continues to use no ammo)
-		if(start_items & IT_UNLIMITED_WEAPON_AMMO)
-			return 0;
-		if((get_weaponinfo(w)).ammo_field == ammo_none)
-			return 0;
-	}
-	return 1;
-	#else
-	return (get_weaponinfo(w)).weaponthrowable;
-	#endif
-}
-
-// toss current weapon
-void W_ThrowWeapon(vector velo, vector delta, float doreduce)
-{
-	float w;
-	string a;
-
-	w = self.weapon;
-	if (w == 0)
-		return; // just in case
-	if(MUTATOR_CALLHOOK(ForbidThrowCurrentWeapon))
-		return;
-	if(!autocvar_g_weapon_throwable)
-		return;
-	if(self.weaponentity.state != WS_READY)
-		return;
-	if(!W_IsWeaponThrowable(w))
-		return;
-
-	if(!(self.weapons & WepSet_FromWeapon(w)))
-		return;
-	self.weapons &= ~WepSet_FromWeapon(w);
-
-	W_SwitchWeapon_Force(self, w_getbestweapon(self));
-	a = W_ThrowNewWeapon(self, w, doreduce, self.origin + delta, velo);
-	
-	if(!a) return;
-	Send_Notification(NOTIF_ONE, self, MSG_MULTI, ITEM_WEAPON_DROP, a, w);
-}
-
-void SpawnThrownWeapon(vector org, float w)
-{
-	if(self.weapons & WepSet_FromWeapon(self.weapon))
-		if(W_IsWeaponThrowable(self.weapon))
-			W_ThrowNewWeapon(self, self.weapon, FALSE, org, randomvec() * 125 + '0 0 200');
-}
diff --git a/qcsrc/server/weapons/throwing.qh b/qcsrc/server/weapons/throwing.qh
deleted file mode 100644
index c09a8f882..000000000
--- a/qcsrc/server/weapons/throwing.qh
+++ /dev/null
@@ -1,12 +0,0 @@
-.float savenextthink;
-void thrown_wep_think();
-
-// returns amount of ammo used as string, or -1 for failure, or 0 for no ammo count
-string W_ThrowNewWeapon(entity own, float wpn, float doreduce, vector org, vector velo);
-
-float W_IsWeaponThrowable(float w);
-
-// toss current weapon
-void W_ThrowWeapon(vector velo, vector delta, float doreduce);
-
-void SpawnThrownWeapon(vector org, float w);
diff --git a/qcsrc/server/weapons/tracing.qc b/qcsrc/server/weapons/tracing.qc
deleted file mode 100644
index 755ab59e5..000000000
--- a/qcsrc/server/weapons/tracing.qc
+++ /dev/null
@@ -1,470 +0,0 @@
-// this function calculates w_shotorg and w_shotdir based on the weapon model
-// offset, trueaim and antilag, and won't put w_shotorg inside a wall.
-// make sure you call makevectors first (FIXME?)
-void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float chan, float maxdamage, float range)
-{
-	float nudge = 1; // added to traceline target and subtracted from result  TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
-	float oldsolid;
-	vector vecs, dv;
-	oldsolid = ent.dphitcontentsmask;
-	if(ent.weapon == WEP_RIFLE)
-		ent.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-	else
-		ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-	if(antilag)
-		WarpZone_traceline_antilag(world, ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
-		// passing world, because we do NOT want it to touch dphitcontentsmask
-	else
-		WarpZone_TraceLine(ent.origin + ent.view_ofs, ent.origin + ent.view_ofs + s_forward * range, MOVE_NOMONSTERS, ent);
-	ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE;
-
-	vector vf, vr, vu;
-	vf = v_forward;
-	vr = v_right;
-	vu = v_up;
-	w_shotend = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos); // warpzone support
-	v_forward = vf;
-	v_right = vr;
-	v_up = vu;
-
-	// un-adjust trueaim if shotend is too close
-	if(vlen(w_shotend - (ent.origin + ent.view_ofs)) < autocvar_g_trueaim_minrange)
-		w_shotend = ent.origin + ent.view_ofs + s_forward * autocvar_g_trueaim_minrange;
-
-	// track max damage
-	if(accuracy_canbegooddamage(ent))
-		accuracy_add(ent, ent.weapon, maxdamage, 0);
-
-	W_HitPlotAnalysis(ent, v_forward, v_right, v_up);
-
-	if(ent.weaponentity.movedir_x > 0)
-		vecs = ent.weaponentity.movedir;
-	else
-		vecs = '0 0 0';
-
-	dv = v_right * -vecs_y + v_up * vecs_z;
-	w_shotorg = ent.origin + ent.view_ofs + dv;
-
-	// now move the shotorg forward as much as requested if possible
-	if(antilag)
-	{
-		if(ent.antilag_debug)
-			tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ent.antilag_debug);
-		else
-			tracebox_antilag(ent, w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
-	}
-	else
-		tracebox(w_shotorg, mi, ma, w_shotorg + v_forward * (vecs_x + nudge), MOVE_NORMAL, ent);
-	w_shotorg = trace_endpos - v_forward * nudge;
-	// calculate the shotdir from the chosen shotorg
-	w_shotdir = normalize(w_shotend - w_shotorg);
-
-	//vector prevdir = w_shotdir;
-	//vector prevorg = w_shotorg;
-	//vector prevend = w_shotend; 
-
-	if (antilag)
-	if (!ent.cvar_cl_noantilag)
-	{
-		if (autocvar_g_antilag == 1) // switch to "ghost" if not hitting original
-		{
-			traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent);
-			if (!trace_ent.takedamage)
-			{
-				traceline_antilag_force (ent, w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent, ANTILAG_LATENCY(ent));
-				if (trace_ent.takedamage && IS_PLAYER(trace_ent))
-				{
-					entity e;
-					e = trace_ent;
-					traceline(w_shotorg, e.origin, MOVE_NORMAL, ent);
-					if(trace_ent == e)
-						w_shotdir = normalize(trace_ent.origin - w_shotorg);
-				}
-			}
-		}
-		else if(autocvar_g_antilag == 3) // client side hitscan
-		{
-			// this part MUST use prydon cursor
-			if (ent.cursor_trace_ent)                 // client was aiming at someone
-			if (ent.cursor_trace_ent != ent)         // just to make sure
-			if (ent.cursor_trace_ent.takedamage)      // and that person is killable
-			if (IS_PLAYER(ent.cursor_trace_ent)) // and actually a player
-			{
-				// verify that the shot would miss without antilag
-				// (avoids an issue where guns would always shoot at their origin)
-				traceline(w_shotorg, w_shotorg + w_shotdir * range, MOVE_NORMAL, ent);
-				if (!trace_ent.takedamage)
-				{
-					// verify that the shot would hit if altered
-					traceline(w_shotorg, ent.cursor_trace_ent.origin, MOVE_NORMAL, ent);
-					if (trace_ent == ent.cursor_trace_ent)
-						w_shotdir = normalize(ent.cursor_trace_ent.origin - w_shotorg);
-					else
-						print("antilag fail\n");
-				}
-			}
-		}
-	}
-
-	ent.dphitcontentsmask = oldsolid; // restore solid type (generally SOLID_SLIDEBOX)
-
-	if (!autocvar_g_norecoil)
-		ent.punchangle_x = recoil * -1;
-
-	if (snd != "")
-	{
-		sound (ent, chan, snd, VOL_BASE, ATTN_NORM);
-		W_PlayStrengthSound(ent);
-	}
-
-	// nudge w_shotend so a trace to w_shotend hits
-	w_shotend = w_shotend + normalize(w_shotend - w_shotorg) * nudge;
-	//if(w_shotend != prevend) { printf("SERVER: shotEND differs: %s - %s\n", vtos(w_shotend), vtos(prevend)); }
-	//if(w_shotorg != prevorg) { printf("SERVER: shotORG differs: %s - %s\n", vtos(w_shotorg), vtos(prevorg)); }
-	//if(w_shotdir != prevdir) { printf("SERVER: shotDIR differs: %s - %s\n", vtos(w_shotdir), vtos(prevdir)); }
-}
-
-vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float forceAbsolute)
-{
-	vector mdirection;
-	float mspeed;
-	vector outvelocity;
-
-	mvelocity = mvelocity * g_weaponspeedfactor;
-
-	mdirection = normalize(mvelocity);
-	mspeed = vlen(mvelocity);
-
-	outvelocity = get_shotvelocity(pvelocity, mdirection, mspeed, (forceAbsolute ? 0 : autocvar_g_projectiles_newton_style), autocvar_g_projectiles_newton_style_2_minfactor, autocvar_g_projectiles_newton_style_2_maxfactor);
-
-	return outvelocity;
-}
-
-void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute)
-{
-	if(proj.owner == world)
-		error("Unowned missile");
-
-	dir = dir + upDir * (pUpSpeed / pSpeed);
-	dir_z += pZSpeed / pSpeed;
-	pSpeed *= vlen(dir);
-	dir = normalize(dir);
-
-	#if 0
-	if(autocvar_g_projectiles_spread_style != mspercallsstyle)
-	{
-		mspercallsum = mspercallcount = 0;
-		mspercallsstyle = autocvar_g_projectiles_spread_style;
-	}
-	mspercallsum -= gettime(GETTIME_HIRES);
-	#endif
-	
-	dir = W_CalculateSpread(dir, spread, g_weaponspreadfactor, autocvar_g_projectiles_spread_style);
-	
-	#if 0
-	mspercallsum += gettime(GETTIME_HIRES);
-	mspercallcount += 1;
-	print("avg: ", ftos(mspercallcount / mspercallsum), " per sec\n");
-	#endif
-
-	proj.velocity = W_CalculateProjectileVelocity(proj.owner.velocity, pSpeed * dir, forceAbsolute);
-}
-
-
-// ====================
-//  Ballistics Tracing
-// ====================
-
-void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype)
-{
-	vector hitloc, force, endpoint, dir;
-	entity ent, endent;
-	float endq3surfaceflags;
-	float totaldmg;
-	entity o;
-
-	float length;
-	vector beampos;
-	string snd;
-	entity pseudoprojectile;
-	float f, ffs;
-
-	pseudoprojectile = world;
-
-	dir = normalize(end - start);
-	length = vlen(end - start);
-	force = dir * bforce;
-
-	// go a little bit into the wall because we need to hit this wall later
-	end = end + dir;
-
-	totaldmg = 0;
-
-	// trace multiple times until we hit a wall, each obstacle will be made
-	// non-solid so we can hit the next, while doing this we spawn effects and
-	// note down which entities were hit so we can damage them later
-	o = self;
-	while (1)
-	{
-		if(self.antilag_debug)
-			WarpZone_traceline_antilag (self, start, end, FALSE, o, self.antilag_debug);
-		else
-			WarpZone_traceline_antilag (self, start, end, FALSE, o, ANTILAG_LATENCY(self));
-		if(o && WarpZone_trace_firstzone)
-		{
-			o = world;
-			continue;
-		}
-
-		if(trace_ent.solid == SOLID_BSP || trace_ent.solid == SOLID_SLIDEBOX)
-			Damage_DamageInfo(trace_endpos, bdamage, 0, 0, force, deathtype, trace_ent.species, self);
-
-		// if it is world we can't hurt it so stop now
-		if (trace_ent == world || trace_fraction == 1)
-			break;
-
-		// make the entity non-solid so we can hit the next one
-		trace_ent.railgunhit = TRUE;
-		trace_ent.railgunhitloc = end;
-		trace_ent.railgunhitsolidbackup = trace_ent.solid;
-		trace_ent.railgundistance = vlen(WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos) - start);
-		trace_ent.railgunforce = WarpZone_TransformVelocity(WarpZone_trace_transform, force);
-
-		// stop if this is a wall
-		if (trace_ent.solid == SOLID_BSP)
-			break;
-
-		// make the entity non-solid
-		trace_ent.solid = SOLID_NOT;
-	}
-
-	endpoint = trace_endpos;
-	endent = trace_ent;
-	endq3surfaceflags = trace_dphitq3surfaceflags;
-
-	// find all the entities the railgun hit and restore their solid state
-	ent = findfloat(world, railgunhit, TRUE);
-	while (ent)
-	{
-		// restore their solid type
-		ent.solid = ent.railgunhitsolidbackup;
-		ent = findfloat(ent, railgunhit, TRUE);
-	}
-
-	// spawn a temporary explosion entity for RadiusDamage calls
-	//explosion = spawn();
-
-	// Find all non-hit players the beam passed close by
-	if(deathtype == WEP_VAPORIZER || deathtype == WEP_VORTEX)
-	{
-		FOR_EACH_REALCLIENT(msg_entity)
-		if(msg_entity != self)
-		if(!msg_entity.railgunhit)
-		if(!(IS_SPEC(msg_entity) && msg_entity.enemy == self)) // we use realclient, so spectators can hear the whoosh too
-		{
-			// nearest point on the beam
-			beampos = start + dir * bound(0, (msg_entity.origin - start) * dir, length);
-
-			f = bound(0, 1 - vlen(beampos - msg_entity.origin) / 512, 1);
-			if(f <= 0)
-				continue;
-
-			snd = strcat("weapons/nexwhoosh", ftos(floor(random() * 3) + 1), ".wav");
-
-			if(!pseudoprojectile)
-				pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume
-			soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, snd, VOL_BASE * f, ATTEN_NONE);
-		}
-
-		if(pseudoprojectile)
-			remove(pseudoprojectile);
-	}
-
-	// find all the entities the railgun hit and hurt them
-	ent = findfloat(world, railgunhit, TRUE);
-	while (ent)
-	{
-		// get the details we need to call the damage function
-		hitloc = ent.railgunhitloc;
-
-		f = ExponentialFalloff(mindist, maxdist, halflifedist, ent.railgundistance);
-		ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, ent.railgundistance);
-
-		if(accuracy_isgooddamage(self.realowner, ent))
-			totaldmg += bdamage * f;
-
-		// apply the damage
-		if (ent.takedamage)
-			Damage (ent, self, self, bdamage * f, deathtype, hitloc, ent.railgunforce * ffs);
-
-		// create a small explosion to throw gibs around (if applicable)
-		//setorigin (explosion, hitloc);
-		//RadiusDamage (explosion, self, 10, 0, 50, world, world, 300, deathtype);
-
-		ent.railgunhitloc = '0 0 0';
-		ent.railgunhitsolidbackup = SOLID_NOT;
-		ent.railgunhit = FALSE;
-		ent.railgundistance = 0;
-
-		// advance to the next entity
-		ent = findfloat(ent, railgunhit, TRUE);
-	}
-
-	// calculate hits and fired shots for hitscan
-	accuracy_add(self, self.weapon, 0, min(bdamage, totaldmg));
-
-	trace_endpos = endpoint;
-	trace_ent = endent;
-	trace_dphitq3surfaceflags = endq3surfaceflags;
-}
-
-void fireBullet_trace_callback(vector start, vector hit, vector end)
-{
-	if(vlen(hit - start) > 16)
-		trailparticles(world, fireBullet_trace_callback_eff, start, hit);
-	WarpZone_trace_forent = world;
-	fireBullet_last_hit = world;
-}
-
-void fireBullet(vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, float tracereffects)
-{
-	vector  end;
-
-	dir = normalize(dir + randomvec() * spread);
-	end = start + dir * MAX_SHOT_DISTANCE;
-
-	entity pl;
-	fireBullet_last_hit = world;
-	float solid_penetration_left = 1;
-	float total_damage = 0;
-
-	if(tracereffects & EF_RED)
-		fireBullet_trace_callback_eff = particleeffectnum("tr_rifle");
-	else if(tracereffects & EF_BLUE)
-		fireBullet_trace_callback_eff = particleeffectnum("tr_rifle_weak");
-	else
-		fireBullet_trace_callback_eff = particleeffectnum("tr_bullet");
-
-	float lag = ANTILAG_LATENCY(self);
-	if(lag < 0.001)
-		lag = 0;
-	if (!IS_REAL_CLIENT(self))
-		lag = 0;
-	if(autocvar_g_antilag == 0 || self.cvar_cl_noantilag)
-		lag = 0; // only do hitscan, but no antilag
-	if(lag)
-	{
-		FOR_EACH_PLAYER(pl)
-			if(pl != self)
-				antilag_takeback(pl, time - lag);
-		FOR_EACH_MONSTER(pl)
-			antilag_takeback(pl, time - lag);
-	}
-
-	WarpZone_trace_forent = self;
-
-	for (;;)
-	{
-		// TODO also show effect while tracing
-		WarpZone_TraceBox_ThroughZone(start, '0 0 0', '0 0 0', end, FALSE, WarpZone_trace_forent, world, fireBullet_trace_callback);
-		dir = WarpZone_TransformVelocity(WarpZone_trace_transform, dir);
-		end = WarpZone_TransformOrigin(WarpZone_trace_transform, end);
-		start = trace_endpos;
-		entity hit = trace_ent;
-
-		// When hitting sky, stop.
-		if (pointcontents(start) == CONTENT_SKY)
-			break;
-
-		if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
-			break;
-
-		// if we hit "weapclip", bail out
-		//
-		// rationale of this check:
-		//
-		// any shader that is solid, nodraw AND trans is meant to clip weapon
-		// shots and players, but has no other effect!
-		//
-		// if it is not trans, it is caulk and should not have this side effect
-		//
-		// matching shaders:
-		//   common/weapclip (intended)
-		//   common/noimpact (is supposed to eat projectiles, but is erased anyway)
-		float is_weapclip = 0;
-		if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODRAW)
-		if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NONSOLID))
-		if (!(trace_dphitcontents & DPCONTENTS_OPAQUE))
-			is_weapclip = 1;
-
-		if(!hit || hit.solid == SOLID_BSP || hit.solid == SOLID_SLIDEBOX)
-			Damage_DamageInfo(start, damage * solid_penetration_left, 0, 0, max(1, force) * dir * solid_penetration_left, dtype, hit.species, self);
-
-		if (hit && hit != WarpZone_trace_forent && hit != fireBullet_last_hit)  // Avoid self-damage (except after going through a warp); avoid hitting the same entity twice (engine bug).
-		{
-			fireBullet_last_hit = hit;
-			yoda = 0;
-			float g = accuracy_isgooddamage(self, hit);
-			Damage(hit, self, self, damage * solid_penetration_left, dtype, start, force * dir * solid_penetration_left);
-			// calculate hits for ballistic weapons
-			if(g)
-			{
-				// do not exceed 100%
-				float added_damage = min(damage - total_damage, damage * solid_penetration_left);
-				total_damage += damage * solid_penetration_left;
-				accuracy_add(self, self.weapon, 0, added_damage);
-			}
-		}
-
-		if (is_weapclip)
-			break;
-
-		// go through solid!
-		// outside the world? forget it
-		if(start_x > world.maxs_x || start_y > world.maxs_y || start_z > world.maxs_z || start_x < world.mins_x || start_y < world.mins_y || start_z < world.mins_z)
-			break;
-
-		float maxdist;
-		if(max_solid_penetration < 0)
-			break;
-		else if(hit.ballistics_density < -1)
-			break; // -2: no solid penetration, ever
-		else if(hit.ballistics_density < 0)
-			maxdist = vlen(hit.maxs - hit.mins) + 1; // -1: infinite travel distance
-		else if(hit.ballistics_density == 0)
-			maxdist = max_solid_penetration * solid_penetration_left;
-		else
-			maxdist = max_solid_penetration * solid_penetration_left * hit.ballistics_density;
-
-		if(maxdist <= autocvar_g_ballistics_mindistance)
-			break;
-
-		// move the entity along its velocity until it's out of solid, then let it resume
-		// The previously hit entity is ignored here!
-		traceline_inverted (start, start + dir * maxdist, MOVE_NORMAL, WarpZone_trace_forent, TRUE, hit);
-		if(trace_fraction == 1) // 1: we never got out of solid
-			break;
-
-		float dist_taken = max(autocvar_g_ballistics_mindistance, vlen(trace_endpos - start));
-		solid_penetration_left *= (dist_taken / maxdist);
-
-		// Only show effect when going through a player (invisible otherwise)
-		if (hit && (hit.solid != SOLID_BSP))
-			if(vlen(trace_endpos - start) > 4)
-				trailparticles(self, fireBullet_trace_callback_eff, start, trace_endpos);
-
-		start = trace_endpos;
-
-		if(hit.solid == SOLID_BSP)
-			Damage_DamageInfo(start, 0, 0, 0, max(1, force) * normalize(dir) * -solid_penetration_left, dtype, 0, self);
-	}
-
-	if(lag)
-	{
-		FOR_EACH_PLAYER(pl)
-			if(pl != self)
-				antilag_restore(pl);
-		FOR_EACH_MONSTER(pl)
-			antilag_restore(pl);
-	}
-}
diff --git a/qcsrc/server/weapons/tracing.qh b/qcsrc/server/weapons/tracing.qh
deleted file mode 100644
index 49605e8f2..000000000
--- a/qcsrc/server/weapons/tracing.qh
+++ /dev/null
@@ -1,55 +0,0 @@
-vector w_shotorg;
-vector w_shotdir;
-vector w_shotend;
-
-// this function calculates w_shotorg and w_shotdir based on the weapon model
-// offset, trueaim and antilag, and won't put w_shotorg inside a wall.
-// make sure you call makevectors first (FIXME?)
-void W_SetupShot_Dir_ProjectileSize_Range(entity ent, vector s_forward, vector mi, vector ma, float antilag, float recoil, string snd, float chan, float maxdamage, float range);
-
-#define W_SetupShot_Dir_ProjectileSize(ent,s_forward,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize_Range(ent, s_forward, mi, ma, antilag, recoil, snd, chan, maxdamage, MAX_SHOT_DISTANCE)
-#define W_SetupShot_ProjectileSize(ent,mi,ma,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, v_forward, mi, ma, antilag, recoil, snd, chan, maxdamage)
-#define W_SetupShot_Dir(ent,s_forward,antilag,recoil,snd,chan,maxdamage) W_SetupShot_Dir_ProjectileSize(ent, s_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
-#define W_SetupShot(ent,antilag,recoil,snd,chan,maxdamage) W_SetupShot_ProjectileSize(ent, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage)
-#define W_SetupShot_Range(ent,antilag,recoil,snd,chan,maxdamage,range) W_SetupShot_Dir_ProjectileSize_Range(ent, v_forward, '0 0 0', '0 0 0', antilag, recoil, snd, chan, maxdamage, range)
-
-vector W_CalculateProjectileVelocity(vector pvelocity, vector mvelocity, float forceAbsolute);
-
-#if 0
-float mspercallsum;
-float mspercallsstyle;
-float mspercallcount;
-#endif
-
-void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float pSpeed, float pUpSpeed, float pZSpeed, float spread, float forceAbsolute);
-
-#define W_SetupProjVelocity_Basic(ent,pspeed,pspread) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, pspeed, 0, 0, pspread, FALSE)
-
-#define W_SetupProjVelocity_UP_PRE(ent,wepname,prefix) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR(wepname, prefix##speed), WEP_CVAR(wepname, prefix##speed_up), WEP_CVAR(wepname, prefix##speed_z), WEP_CVAR(wepname, prefix##spread), FALSE)
-#define W_SetupProjVelocity_UP_PRI(ent,wepname) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR_PRI(wepname, speed), WEP_CVAR_PRI(wepname, speed_up), WEP_CVAR_PRI(wepname, speed_z), WEP_CVAR_PRI(wepname, spread), FALSE)
-#define W_SetupProjVelocity_UP_SEC(ent,wepname) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR_SEC(wepname, speed), WEP_CVAR_SEC(wepname, speed_up), WEP_CVAR_SEC(wepname, speed_z), WEP_CVAR_SEC(wepname, spread), FALSE)
-
-#define W_SetupProjVelocity_UP_BOTH(ent,wepname,isprimary) \
-	if(isprimary) { W_SetupProjVelocity_UP_PRI(ent, wepname); } \
-	else { W_SetupProjVelocity_UP_SEC(ent, wepname); }
-
-#define W_SetupProjVelocity_PRE(ent,wepname,prefix) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR(wepname, prefix##speed), 0, 0, WEP_CVAR(wepname, prefix##spread), FALSE)
-#define W_SetupProjVelocity_PRI(ent,wepname) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR_PRI(wepname, speed), 0, 0, WEP_CVAR_PRI(wepname, spread), FALSE)
-#define W_SetupProjVelocity_SEC(ent,wepname) W_SetupProjVelocity_Explicit(ent, w_shotdir, v_up, WEP_CVAR_SEC(wepname, speed), 0, 0, WEP_CVAR_SEC(wepname, spread), FALSE)
-
-#define W_SetupProjVelocity_BOTH(ent,wepname,isprimary) \
-	if(isprimary) { W_SetupProjVelocity_PRI(ent, wepname); } \
-	else { W_SetupProjVelocity_SEC(ent, wepname); }
-
-// ====================
-//  Ballistics Tracing
-// ====================
-
-.float railgundistance;
-.vector railgunforce;
-void FireRailgunBullet (vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, float deathtype);
-
-float fireBullet_trace_callback_eff;
-entity fireBullet_last_hit;
-void fireBullet_trace_callback(vector start, vector hit, vector end);
-void fireBullet(vector start, vector dir, float spread, float max_solid_penetration, float damage, float force, float dtype, float tracereffects);
diff --git a/qcsrc/server/weapons/weaponstats.qc b/qcsrc/server/weapons/weaponstats.qc
deleted file mode 100644
index d83db8b82..000000000
--- a/qcsrc/server/weapons/weaponstats.qc
+++ /dev/null
@@ -1,103 +0,0 @@
-void WeaponStats_Init()
-{
-	weaponstats_buffer = ((autocvar_sv_weaponstats_file != "") ? buf_create() : -1);
-}
-
-void WeaponStats_ready(entity fh, entity pass, float status)
-{
-	float i, j, n, ibot, jbot, idx;
-	vector v;
-	string prefix, s;
-	switch(status)
-	{
-		case URL_READY_CANWRITE:
-			// we can write
-			prefix = strcat(autocvar_hostname, "\t", GetGametype(), "_", GetMapname(), "\t");
-			url_fputs(fh, "#begin statsfile\n");
-			url_fputs(fh, strcat("#date ", strftime(TRUE, "%a %b %e %H:%M:%S %Z %Y"), "\n"));
-#ifdef WATERMARK
-			url_fputs(fh, strcat("#version ", WATERMARK, "\n"));
-#endif
-			url_fputs(fh, strcat("#config ", ftos(crc16(FALSE, cvar_purechanges)), "\n"));
-			url_fputs(fh, strcat("#cvar_purechanges ", ftos(cvar_purechanges_count), "\n"));
-			n = tokenizebyseparator(cvar_purechanges, "\n");
-			for(i = 0; i < n; ++i)
-				url_fputs(fh, strcat("#cvar_purechange ", argv(i), "\n"));
-			for(i = WEP_FIRST; i <= WEP_LAST; ++i) for(ibot = 0; ibot <= 1; ++ibot)
-				for(j = WEP_FIRST; j <= WEP_LAST; ++j) for(jbot = 0; jbot <= 1; ++jbot)
-				{
-					idx = WEAPONSTATS_GETINDEX(i, ibot, j, jbot);
-					v = stov(bufstr_get(weaponstats_buffer, idx));
-					if(v != '0 0 0')
-					{
-						//vector is: kills hits damage
-						url_fputs(fh, sprintf("%s%d %d\t%d %d\t", prefix, i, ibot, j, jbot));
-						url_fputs(fh, sprintf("%d %d %g\n", v_x, v_y, v_z));
-					}
-				}
-			url_fputs(fh, "#end\n\n");
-			url_fclose(fh);
-			break;
-		case URL_READY_CANREAD:
-			// url_fclose is processing, we got a response for writing the data
-			// this must come from HTTP
-			print("Got response from weapon stats server:\n");
-			while((s = url_fgets(fh)))
-				print("  ", s, "\n");
-			print("End of response.\n");
-			url_fclose(fh);
-			break;
-		case URL_READY_CLOSED:
-			// url_fclose has finished
-			print("Weapon stats written\n");
-			buf_del(weaponstats_buffer);
-			weaponstats_buffer = -1;
-			break;
-		case URL_READY_ERROR:
-		default:
-			print("Weapon stats writing failed: ", ftos(status), "\n");
-			buf_del(weaponstats_buffer);
-			weaponstats_buffer = -1;
-			break;
-	}
-}
-
-void WeaponStats_Shutdown()
-{
-	if(weaponstats_buffer < 0)
-		return;
-	if(autocvar_sv_weaponstats_file != "")
-	{
-		url_multi_fopen(autocvar_sv_weaponstats_file, FILE_APPEND, WeaponStats_ready, world);
-	}
-	else
-	{
-		buf_del(weaponstats_buffer);
-		weaponstats_buffer = -1;
-	}
-}
-
-void WeaponStats_LogItem(float awep, float abot, float vwep, float vbot, vector item)
-{
-	float idx;
-	if(weaponstats_buffer < 0)
-		return;
-	if(awep < WEP_FIRST || vwep < WEP_FIRST)
-		return;
-	if(awep > WEP_LAST || vwep > WEP_LAST)
-		return;
-	idx = WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot);
-	bufstr_set(weaponstats_buffer, idx, vtos(stov(bufstr_get(weaponstats_buffer, idx)) + item));
-}
-
-void WeaponStats_LogDamage(float awep, float abot, float vwep, float vbot, float damage)
-{
-	if(damage < 0)
-		error("negative damage?");
-	WeaponStats_LogItem(awep, abot, vwep, vbot, '0 0 1' * damage + '0 1 0');
-}
-
-void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot)
-{
-	WeaponStats_LogItem(awep, abot, vwep, vbot, '1 0 0');
-}
diff --git a/qcsrc/server/weapons/weaponstats.qh b/qcsrc/server/weapons/weaponstats.qh
deleted file mode 100644
index 08ae8dd0a..000000000
--- a/qcsrc/server/weapons/weaponstats.qh
+++ /dev/null
@@ -1,10 +0,0 @@
-float weaponstats_buffer;
-
-void WeaponStats_Init();
-void WeaponStats_ready(entity fh, entity pass, float status);
-void WeaponStats_Shutdown();
-void WeaponStats_LogItem(float awep, float abot, float vwep, float vbot, vector item);
-void WeaponStats_LogDamage(float awep, float abot, float vwep, float vbot, float damage);
-void WeaponStats_LogKill(float awep, float abot, float vwep, float vbot);
-
-#define WEAPONSTATS_GETINDEX(awep,abot,vwep,vbot) (((vwep) + (awep) * (WEP_LAST - WEP_FIRST + 1) - (WEP_FIRST + WEP_FIRST * (WEP_LAST - WEP_FIRST + 1))) * 4 + (abot) * 2 + (vbot))
diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc
deleted file mode 100644
index 4eb6a7364..000000000
--- a/qcsrc/server/weapons/weaponsystem.qc
+++ /dev/null
@@ -1,942 +0,0 @@
-/*
-===========================================================================
-
-  CLIENT WEAPONSYSTEM CODE
-  Bring back W_Weaponframe
-
-===========================================================================
-*/
-
-.float weapon_frametime;
-
-float W_WeaponRateFactor()
-{
-	float t;
-	t = 1.0 / g_weaponratefactor;
-
-	weapon_rate = t;
-	MUTATOR_CALLHOOK(WeaponRateFactor);
-	t = weapon_rate;
-
-	return t;
-}
-
-// VorteX: static frame globals
-const float WFRAME_DONTCHANGE = -1;
-const float WFRAME_FIRE1 = 0;
-const float WFRAME_FIRE2 = 1;
-const float WFRAME_IDLE = 2;
-const float WFRAME_RELOAD = 3;
-.float wframe;
-
-void(float fr, float t, void() func) weapon_thinkf;
-
-float CL_Weaponentity_CustomizeEntityForClient()
-{
-	self.viewmodelforclient = self.owner;
-	if(IS_SPEC(other))
-		if(other.enemy == self.owner)
-			self.viewmodelforclient = other;
-	return TRUE;
-}
-
-/*
- * supported formats:
- *
- * 1. simple animated model, muzzle flash handling on h_ model:
- *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
- *      tags:
- *        shot = muzzle end (shot origin, also used for muzzle flashes)
- *        shell = casings ejection point (must be on the right hand side of the gun)
- *        weapon = attachment for v_tuba.md3
- *    v_tuba.md3 - first and third person model
- *    g_tuba.md3 - pickup model
- *
- * 2. simple animated model, muzzle flash handling on v_ model:
- *    h_tuba.dpm, h_tuba.dpm.framegroups - invisible model controlling the animation
- *      tags:
- *        weapon = attachment for v_tuba.md3
- *    v_tuba.md3 - first and third person model
- *      tags:
- *        shot = muzzle end (shot origin, also used for muzzle flashes)
- *        shell = casings ejection point (must be on the right hand side of the gun)
- *    g_tuba.md3 - pickup model
- *
- * 3. fully animated model, muzzle flash handling on h_ model:
- *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
- *      tags:
- *        shot = muzzle end (shot origin, also used for muzzle flashes)
- *        shell = casings ejection point (must be on the right hand side of the gun)
- *        handle = corresponding to the origin of v_tuba.md3 (used for muzzle flashes)
- *    v_tuba.md3 - third person model
- *    g_tuba.md3 - pickup model
- *
- * 4. fully animated model, muzzle flash handling on v_ model:
- *    h_tuba.dpm, h_tuba.dpm.framegroups - animated first person model
- *      tags:
- *        shot = muzzle end (shot origin)
- *        shell = casings ejection point (must be on the right hand side of the gun)
- *    v_tuba.md3 - third person model
- *      tags:
- *        shot = muzzle end (for muzzle flashes)
- *    g_tuba.md3 - pickup model
- */
-
-// writes:
-//   self.origin, self.angles
-//   self.weaponentity
-//   self.movedir, self.view_ofs
-//   attachment stuff
-//   anim stuff
-// to free:
-//   call again with ""
-//   remove the ent
-void CL_WeaponEntity_SetModel(string name)
-{
-	float v_shot_idx;
-	if (name != "")
-	{
-		// if there is a child entity, hide it until we're sure we use it
-		if (self.weaponentity)
-			self.weaponentity.model = "";
-		setmodel(self, strcat("models/weapons/v_", name, ".md3")); // precision set below
-		v_shot_idx = gettagindex(self, "shot"); // used later
-		if(!v_shot_idx)
-			v_shot_idx = gettagindex(self, "tag_shot");
-
-		setmodel(self, strcat("models/weapons/h_", name, ".iqm")); // precision set below
-		// preset some defaults that work great for renamed zym files (which don't need an animinfo)
-		self.anim_fire1  = animfixfps(self, '0 1 0.01', '0 0 0');
-		self.anim_fire2  = animfixfps(self, '1 1 0.01', '0 0 0');
-		self.anim_idle   = animfixfps(self, '2 1 0.01', '0 0 0');
-		self.anim_reload = animfixfps(self, '3 1 0.01', '0 0 0');
-
-		// if we have a "weapon" tag, let's attach the v_ model to it ("invisible hand" style model)
-		// if we don't, this is a "real" animated model
-		if(gettagindex(self, "weapon"))
-		{
-			if (!self.weaponentity)
-				self.weaponentity = spawn();
-			setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter
-			setattachment(self.weaponentity, self, "weapon");
-		}
-		else if(gettagindex(self, "tag_weapon"))
-		{
-			if (!self.weaponentity)
-				self.weaponentity = spawn();
-			setmodel(self.weaponentity, strcat("models/weapons/v_", name, ".md3")); // precision does not matter
-			setattachment(self.weaponentity, self, "tag_weapon");
-		}
-		else
-		{
-			if(self.weaponentity)
-				remove(self.weaponentity);
-			self.weaponentity = world;
-		}
-
-		setorigin(self,'0 0 0');
-		self.angles = '0 0 0';
-		self.frame = 0;
-		self.viewmodelforclient = world;
-
-		float idx;
-
-		if(v_shot_idx) // v_ model attached to invisible h_ model
-		{
-			self.movedir = gettaginfo(self.weaponentity, v_shot_idx);
-		}
-		else
-		{
-			idx = gettagindex(self, "shot");
-			if(!idx)
-				idx = gettagindex(self, "tag_shot");
-			if(idx)
-				self.movedir = gettaginfo(self, idx);
-			else
-			{
-				print("WARNING: weapon model ", self.model, " does not support the 'shot' tag, will display shots TOTALLY wrong\n");
-				self.movedir = '0 0 0';
-			}
-		}
-
-		if(self.weaponentity) // v_ model attached to invisible h_ model
-		{
-			idx = gettagindex(self.weaponentity, "shell");
-			if(!idx)
-				idx = gettagindex(self.weaponentity, "tag_shell");
-			if(idx)
-				self.spawnorigin = gettaginfo(self.weaponentity, idx);
-		}
-		else
-			idx = 0;
-		if(!idx)
-		{
-			idx = gettagindex(self, "shell");
-			if(!idx)
-				idx = gettagindex(self, "tag_shell");
-			if(idx)
-				self.spawnorigin = gettaginfo(self, idx);
-			else
-			{
-				print("WARNING: weapon model ", self.model, " does not support the 'shell' tag, will display casings wrong\n");
-				self.spawnorigin = self.movedir;
-			}
-		}
-
-		if(v_shot_idx)
-		{
-			self.oldorigin = '0 0 0'; // use regular attachment
-		}
-		else
-		{
-			if(self.weaponentity)
-			{
-				idx = gettagindex(self, "weapon");
-				if(!idx)
-					idx = gettagindex(self, "tag_weapon");
-			}
-			else
-			{
-				idx = gettagindex(self, "handle");
-				if(!idx)
-					idx = gettagindex(self, "tag_handle");
-			}
-			if(idx)
-			{
-				self.oldorigin = self.movedir - gettaginfo(self, idx);
-			}
-			else
-			{
-				print("WARNING: weapon model ", self.model, " does not support the 'handle' tag and neither does the v_ model support the 'shot' tag, will display muzzle flashes TOTALLY wrong\n");
-				self.oldorigin = '0 0 0'; // there is no way to recover from this
-			}
-		}
-
-		self.viewmodelforclient = self.owner;
-	}
-	else
-	{
-		self.model = "";
-		if(self.weaponentity)
-			remove(self.weaponentity);
-		self.weaponentity = world;
-		self.movedir = '0 0 0';
-		self.spawnorigin = '0 0 0';
-		self.oldorigin = '0 0 0';
-		self.anim_fire1  = '0 1 0.01';
-		self.anim_fire2  = '0 1 0.01';
-		self.anim_idle   = '0 1 0.01';
-		self.anim_reload = '0 1 0.01';
-	}
-
-	self.view_ofs = '0 0 0';
-
-	if(self.movedir_x >= 0)
-	{
-		vector v0;
-		v0 = self.movedir;
-		self.movedir = shotorg_adjust(v0, FALSE, FALSE);
-		self.view_ofs = shotorg_adjust(v0, FALSE, TRUE) - v0;
-	}
-	self.owner.stat_shotorg = compressShotOrigin(self.movedir);
-	self.movedir = decompressShotOrigin(self.owner.stat_shotorg); // make them match perfectly
-
-	self.spawnorigin += self.view_ofs; // offset the casings origin by the same amount
-
-	// check if an instant weapon switch occurred
-	setorigin(self, self.view_ofs);
-	// reset animstate now
-	self.wframe = WFRAME_IDLE;
-	setanim(self, self.anim_idle, TRUE, FALSE, TRUE);
-}
-
-vector CL_Weapon_GetShotOrg(float wpn)
-{
-	entity wi, oldself;
-	vector ret;
-	wi = get_weaponinfo(wpn);
-	oldself = self;
-	self = spawn();
-	CL_WeaponEntity_SetModel(wi.mdl);
-	ret = self.movedir;
-	CL_WeaponEntity_SetModel("");
-	remove(self);
-	self = oldself;
-	return ret;
-}
-
-void CL_Weaponentity_Think()
-{
-	float tb;
-	self.nextthink = time;
-	if (intermission_running)
-		self.frame = self.anim_idle_x;
-	if (self.owner.weaponentity != self)
-	{
-		if (self.weaponentity)
-			remove(self.weaponentity);
-		remove(self);
-		return;
-	}
-	if (self.owner.deadflag != DEAD_NO)
-	{
-		self.model = "";
-		if (self.weaponentity)
-			self.weaponentity.model = "";
-		return;
-	}
-	if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
-	{
-		self.weaponname = self.owner.weaponname;
-		self.dmg = self.owner.modelindex;
-		self.deadflag = self.owner.deadflag;
-
-		CL_WeaponEntity_SetModel(self.owner.weaponname);
-	}
-
-	tb = (self.effects & (EF_TELEPORT_BIT | EF_RESTARTANIM_BIT));
-	self.effects = self.owner.effects & EFMASK_CHEAP;
-	self.effects &= ~EF_LOWPRECISION;
-	self.effects &= ~EF_FULLBRIGHT; // can mask team color, so get rid of it
-	self.effects &= ~EF_TELEPORT_BIT;
-	self.effects &= ~EF_RESTARTANIM_BIT;
-	self.effects |= tb;
-
-	if(self.owner.alpha == default_player_alpha)
-		self.alpha = default_weapon_alpha;
-	else if(self.owner.alpha != 0)
-		self.alpha = self.owner.alpha;
-	else
-		self.alpha = 1;
-
-	self.glowmod = self.owner.weaponentity_glowmod;
-	self.colormap = self.owner.colormap;
-	if (self.weaponentity)
-	{
-		self.weaponentity.effects = self.effects;
-		self.weaponentity.alpha = self.alpha;
-		self.weaponentity.colormap = self.colormap;
-		self.weaponentity.glowmod = self.glowmod;
-	}
-
-	self.angles = '0 0 0';
-
-	float f = (self.owner.weapon_nextthink - time);
-	if (self.state == WS_RAISE && !intermission_running)
-	{
-		entity newwep = get_weaponinfo(self.owner.switchweapon);
-		f = f * g_weaponratefactor / max(f, newwep.switchdelay_raise);
-		self.angles_x = -90 * f * f;
-	}
-	else if (self.state == WS_DROP && !intermission_running)
-	{
-		entity oldwep = get_weaponinfo(self.owner.weapon);
-		f = 1 - f * g_weaponratefactor / max(f, oldwep.switchdelay_drop);
-		self.angles_x = -90 * f * f;
-	}
-	else if (self.state == WS_CLEAR)
-	{
-		f = 1;
-		self.angles_x = -90 * f * f;
-	}
-}
-
-void CL_ExteriorWeaponentity_Think()
-{
-	float tag_found;
-	self.nextthink = time;
-	if (self.owner.exteriorweaponentity != self)
-	{
-		remove(self);
-		return;
-	}
-	if (self.owner.deadflag != DEAD_NO)
-	{
-		self.model = "";
-		return;
-	}
-	if (self.weaponname != self.owner.weaponname || self.dmg != self.owner.modelindex || self.deadflag != self.owner.deadflag)
-	{
-		self.weaponname = self.owner.weaponname;
-		self.dmg = self.owner.modelindex;
-		self.deadflag = self.owner.deadflag;
-		if (self.owner.weaponname != "")
-			setmodel(self, strcat("models/weapons/v_", self.owner.weaponname, ".md3")); // precision set below
-		else
-			self.model = "";
-
-		if((tag_found = gettagindex(self.owner, "tag_weapon")))
-		{
-			self.tag_index = tag_found;
-			self.tag_entity = self.owner;
-		}
-		else
-			setattachment(self, self.owner, "bip01 r hand");
-	}
-	self.effects = self.owner.effects;
-	self.effects |= EF_LOWPRECISION;
-	self.effects = self.effects & EFMASK_CHEAP; // eat performance
-	if(self.owner.alpha == default_player_alpha)
-		self.alpha = default_weapon_alpha;
-	else if(self.owner.alpha != 0)
-		self.alpha = self.owner.alpha;
-	else
-		self.alpha = 1;
-
-	self.glowmod = self.owner.weaponentity_glowmod;
-	self.colormap = self.owner.colormap;
-
-	CSQCMODEL_AUTOUPDATE();
-}
-
-// spawning weaponentity for client
-void CL_SpawnWeaponentity()
-{
-	self.weaponentity = spawn();
-	self.weaponentity.classname = "weaponentity";
-	self.weaponentity.solid = SOLID_NOT;
-	self.weaponentity.owner = self;
-	setmodel(self.weaponentity, ""); // precision set when changed
-	setorigin(self.weaponentity, '0 0 0');
-	self.weaponentity.angles = '0 0 0';
-	self.weaponentity.viewmodelforclient = self;
-	self.weaponentity.flags = 0;
-	self.weaponentity.think = CL_Weaponentity_Think;
-	self.weaponentity.customizeentityforclient = CL_Weaponentity_CustomizeEntityForClient;
-	self.weaponentity.nextthink = time;
-
-	self.exteriorweaponentity = spawn();
-	self.exteriorweaponentity.classname = "exteriorweaponentity";
-	self.exteriorweaponentity.solid = SOLID_NOT;
-	self.exteriorweaponentity.exteriorweaponentity = self.exteriorweaponentity;
-	self.exteriorweaponentity.owner = self;
-	setorigin(self.exteriorweaponentity, '0 0 0');
-	self.exteriorweaponentity.angles = '0 0 0';
-	self.exteriorweaponentity.think = CL_ExteriorWeaponentity_Think;
-	self.exteriorweaponentity.nextthink = time;
-
-	{
-		entity oldself = self;
-		self = self.exteriorweaponentity;
-		CSQCMODEL_AUTOINIT();
-		self = oldself;
-	}
-}
-
-// Weapon subs
-void w_clear()
-{
-	if (self.weapon != -1)
-	{
-		self.weapon = 0;
-		self.switchingweapon = 0;
-	}
-	if (self.weaponentity)
-	{
-		self.weaponentity.state = WS_CLEAR;
-		self.weaponentity.effects = 0;
-	}
-}
-
-void w_ready()
-{
-	if (self.weaponentity)
-		self.weaponentity.state = WS_READY;
-	weapon_thinkf(WFRAME_IDLE, 1000000, w_ready);
-}
-
-.float prevdryfire;
-.float prevwarntime;
-float weapon_prepareattack_checkammo(float secondary)
-{
-	if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-	if (!WEP_ACTION(self.weapon, WR_CHECKAMMO1 + secondary))
-	{
-		// always keep the Mine Layer if we placed mines, so that we can detonate them
-		entity mine;
-		if(self.weapon == WEP_MINE_LAYER)
-		for(mine = world; (mine = find(mine, classname, "mine")); ) if(mine.owner == self)
-			return FALSE;
-
-		if(self.weapon == self.switchweapon && time - self.prevdryfire > 1) // only play once BEFORE starting to switch weapons
-		{
-			sound (self, CH_WEAPON_A, "weapons/dryfire.wav", VOL_BASE, ATTEN_NORM);
-			self.prevdryfire = time;
-		}
-
-		if(WEP_ACTION(self.weapon, WR_CHECKAMMO2 - secondary)) // check if the other firing mode has enough ammo
-		{
-			if(time - self.prevwarntime > 1)
-			{
-				Send_Notification(
-					NOTIF_ONE,
-					self,
-					MSG_MULTI,
-					ITEM_WEAPON_PRIMORSEC,
-					self.weapon,
-					secondary,
-					(1 - secondary)
-				);
-			}
-			self.prevwarntime = time;
-		}
-		else // this weapon is totally unable to fire, switch to another one
-		{
-			W_SwitchToOtherWeapon(self);
-		}
-
-		return FALSE;
-	}
-	return TRUE;
-}
-.float race_penalty;
-float weapon_prepareattack_check(float secondary, float attacktime)
-{
-	if(!weapon_prepareattack_checkammo(secondary))
-		return FALSE;
-
-	//if sv_ready_restart_after_countdown is set, don't allow the player to shoot
-	//if all players readied up and the countdown is running
-	if(time < game_starttime || time < self.race_penalty) {
-		return FALSE;
-	}
-
-	if (timeout_status == TIMEOUT_ACTIVE) //don't allow the player to shoot while game is paused
-		return FALSE;
-
-	// do not even think about shooting if switching
-	if(self.switchweapon != self.weapon)
-		return FALSE;
-
-	if(attacktime >= 0)
-	{
-		// don't fire if previous attack is not finished
-		if (ATTACK_FINISHED(self) > time + self.weapon_frametime * 0.5)
-			return FALSE;
-		// don't fire while changing weapon
-		if (self.weaponentity.state != WS_READY)
-			return FALSE;
-	}
-
-	return TRUE;
-}
-float weapon_prepareattack_do(float secondary, float attacktime)
-{
-	self.weaponentity.state = WS_INUSE;
-
-	self.spawnshieldtime = min(self.spawnshieldtime, time); // kill spawn shield when you fire
-
-	// if the weapon hasn't been firing continuously, reset the timer
-	if(attacktime >= 0)
-	{
-		if (ATTACK_FINISHED(self) < time - self.weapon_frametime * 1.5)
-		{
-			ATTACK_FINISHED(self) = time;
-			//dprint("resetting attack finished to ", ftos(time), "\n");
-		}
-		ATTACK_FINISHED(self) = ATTACK_FINISHED(self) + attacktime * W_WeaponRateFactor();
-	}
-	self.bulletcounter += 1;
-	//dprint("attack finished ", ftos(ATTACK_FINISHED(self)), "\n");
-	return TRUE;
-}
-float weapon_prepareattack(float secondary, float attacktime)
-{
-	if(weapon_prepareattack_check(secondary, attacktime))
-	{
-		weapon_prepareattack_do(secondary, attacktime);
-		return TRUE;
-	}
-	else
-		return FALSE;
-}
-
-void weapon_thinkf(float fr, float t, void() func)
-{
-	vector a;
-	vector of, or, ou;
-	float restartanim;
-
-	if(fr == WFRAME_DONTCHANGE)
-	{
-		fr = self.weaponentity.wframe;
-		restartanim = FALSE;
-	}
-	else if (fr == WFRAME_IDLE)
-		restartanim = FALSE;
-	else
-		restartanim = TRUE;
-
-	of = v_forward;
-	or = v_right;
-	ou = v_up;
-
-	if (self.weaponentity)
-	{
-		self.weaponentity.wframe = fr;
-		a = '0 0 0';
-		if (fr == WFRAME_IDLE)
-			a = self.weaponentity.anim_idle;
-		else if (fr == WFRAME_FIRE1)
-			a = self.weaponentity.anim_fire1;
-		else if (fr == WFRAME_FIRE2)
-			a = self.weaponentity.anim_fire2;
-		else // if (fr == WFRAME_RELOAD)
-			a = self.weaponentity.anim_reload;
-		a_z *= g_weaponratefactor;
-		setanim(self.weaponentity, a, restartanim == FALSE, restartanim, restartanim);
-	}
-
-	v_forward = of;
-	v_right = or;
-	v_up = ou;
-
-	if(self.weapon_think == w_ready && func != w_ready && self.weaponentity.state == WS_RAISE)
-	{
-		backtrace("Tried to override initial weapon think function - should this really happen?");
-	}
-
-	t *= W_WeaponRateFactor();
-
-	// VorteX: haste can be added here
-	if (self.weapon_think == w_ready)
-	{
-		self.weapon_nextthink = time;
-		//dprint("started firing at ", ftos(time), "\n");
-	}
-	if (self.weapon_nextthink < time - self.weapon_frametime * 1.5 || self.weapon_nextthink > time + self.weapon_frametime * 1.5)
-	{
-		self.weapon_nextthink = time;
-		//dprint("reset weapon animation timer at ", ftos(time), "\n");
-	}
-	self.weapon_nextthink = self.weapon_nextthink + t;
-	self.weapon_think = func;
-	//dprint("next ", ftos(self.weapon_nextthink), "\n");
-
-	if((fr == WFRAME_FIRE1 || fr == WFRAME_FIRE2) && t)
-	{
-		if((self.weapon == WEP_SHOCKWAVE || self.weapon == WEP_SHOTGUN) && fr == WFRAME_FIRE2)
-			animdecide_setaction(self, ANIMACTION_MELEE, restartanim);
-		else
-			animdecide_setaction(self, ANIMACTION_SHOOT, restartanim);
-	}
-	else
-	{
-		if(self.anim_upper_action == ANIMACTION_SHOOT || self.anim_upper_action == ANIMACTION_MELEE)
-			self.anim_upper_action = 0;
-	}
-}
-
-float forbidWeaponUse()
-{
-	if(time < game_starttime && !autocvar_sv_ready_restart_after_countdown)
-		return 1;
-	if(round_handler_IsActive() && !round_handler_IsRoundStarted())
-		return 1;
-	if(self.player_blocked)
-		return 1;
-	if(self.frozen)
-		return 1;
-	return 0;
-}
-
-void W_WeaponFrame()
-{
-	vector fo, ri, up;
-
-	if (frametime)
-		self.weapon_frametime = frametime;
-
-	if (!self.weaponentity || self.health < 1)
-		return; // Dead player can't use weapons and injure impulse commands
-
-	if(forbidWeaponUse())
-	if(self.weaponentity.state != WS_CLEAR)
-	{
-		w_ready();
-		return;
-	}
-
-	if(!self.switchweapon)
-	{
-		self.weapon = 0;
-		self.switchingweapon = 0;
-		self.weaponentity.state = WS_CLEAR;
-		self.weaponname = "";
-		//self.items &= ~IT_AMMO;
-		return;
-	}
-
-	makevectors(self.v_angle);
-	fo = v_forward; // save them in case the weapon think functions change it
-	ri = v_right;
-	up = v_up;
-
-	// Change weapon
-	if (self.weapon != self.switchweapon)
-	{
-		if (self.weaponentity.state == WS_CLEAR)
-		{
-			// end switching!
-			self.switchingweapon = self.switchweapon;
-			entity newwep = get_weaponinfo(self.switchweapon);
-
-			// the two weapon entities will notice this has changed and update their models
-			self.weapon = self.switchweapon;
-			self.weaponname = newwep.mdl;
-			self.bulletcounter = 0;
-			//self.ammo_field = newwep.ammo_field;
-			WEP_ACTION(self.switchweapon, WR_SETUP);
-			self.weaponentity.state = WS_RAISE;
-
-			// set our clip load to the load of the weapon we switched to, if it's reloadable
-			if(newwep.spawnflags & WEP_FLAG_RELOADABLE && newwep.reloading_ammo) // prevent accessing undefined cvars
-			{
-				self.clip_load = self.(weapon_load[self.switchweapon]);
-				self.clip_size = newwep.reloading_ammo;
-			}
-			else
-				self.clip_load = self.clip_size = 0;
-
-			weapon_thinkf(WFRAME_IDLE, newwep.switchdelay_raise, w_ready);
-		}
-		else if (self.weaponentity.state == WS_DROP)
-		{
-			// in dropping phase we can switch at any time
-			self.switchingweapon = self.switchweapon;
-		}
-		else if (self.weaponentity.state == WS_READY)
-		{
-			// start switching!
-			self.switchingweapon = self.switchweapon;
-			entity oldwep = get_weaponinfo(self.weapon);
-
-			// set up weapon switch think in the future, and start drop anim
-			#ifndef INDEPENDENT_ATTACK_FINISHED
-			if(ATTACK_FINISHED(self) <= time + self.weapon_frametime * 0.5)
-			{
-			#endif
-				sound(self, CH_WEAPON_SINGLE, "weapons/weapon_switch.wav", VOL_BASE, ATTN_NORM);
-				self.weaponentity.state = WS_DROP;
-				weapon_thinkf(WFRAME_DONTCHANGE, oldwep.switchdelay_drop, w_clear);
-			#ifndef INDEPENDENT_ATTACK_FINISHED
-			}
-			#endif
-		}
-	}
-
-	// LordHavoc: network timing test code
-	//if (self.button0)
-	//	print(ftos(frametime), " ", ftos(time), " >= ", ftos(ATTACK_FINISHED(self)), " >= ", ftos(self.weapon_nextthink), "\n");
-
-	float w;
-	w = self.weapon;
-
-	// call the think code which may fire the weapon
-	// and do so multiple times to resolve framerate dependency issues if the
-	// server framerate is very low and the weapon fire rate very high
-	float c;
-	c = 0;
-	while (c < W_TICSPERFRAME)
-	{
-		c = c + 1;
-		if(w && !(self.weapons & WepSet_FromWeapon(w)))
-		{
-			if(self.weapon == self.switchweapon)
-				W_SwitchWeapon_Force(self, w_getbestweapon(self));
-			w = 0;
-		}
-
-		v_forward = fo;
-		v_right = ri;
-		v_up = up;
-
-		if(w)
-			WEP_ACTION(self.weapon, WR_THINK);
-		else
-			WEP_ACTION(self.weapon, WR_GONETHINK);
-
-		if (time + self.weapon_frametime * 0.5 >= self.weapon_nextthink)
-		{
-			if(self.weapon_think)
-			{
-				v_forward = fo;
-				v_right = ri;
-				v_up = up;
-				self.weapon_think();
-			}
-			else
-				bprint("\{1}^1ERROR: undefined weapon think function for ", self.netname, "\n");
-		}
-	}
-}
-
-void W_AttachToShotorg(entity flash, vector offset)
-{
-	entity xflash;
-	flash.owner = self;
-	flash.angles_z = random() * 360;
-
-	if(gettagindex(self.weaponentity, "shot"))
-		setattachment(flash, self.weaponentity, "shot");
-	else
-		setattachment(flash, self.weaponentity, "tag_shot");
-	setorigin(flash, offset);
-
-	xflash = spawn();
-	copyentity(flash, xflash);
-
-	flash.viewmodelforclient = self;
-
-	if(self.weaponentity.oldorigin_x > 0)
-	{
-		setattachment(xflash, self.exteriorweaponentity, "");
-		setorigin(xflash, self.weaponentity.oldorigin + offset);
-	}
-	else
-	{
-		if(gettagindex(self.exteriorweaponentity, "shot"))
-			setattachment(xflash, self.exteriorweaponentity, "shot");
-		else
-			setattachment(xflash, self.exteriorweaponentity, "tag_shot");
-		setorigin(xflash, offset);
-	}
-}
-
-void W_DecreaseAmmo(float ammo_use)
-{
-	entity wep = get_weaponinfo(self.weapon);
-
-	if((self.items & IT_UNLIMITED_WEAPON_AMMO) && !wep.reloading_ammo)
-		return;
-
-	// if this weapon is reloadable, decrease its load. Else decrease the player's ammo
-	if(wep.reloading_ammo)
-	{
-		self.clip_load -= ammo_use;
-		self.(weapon_load[self.weapon]) = self.clip_load;
-	}
-	else if(wep.ammo_field != ammo_none)
-	{
-		self.(wep.ammo_field) -= ammo_use;
-		if(self.(wep.ammo_field) < 0)
-		{
-			backtrace(sprintf(
-				"W_DecreaseAmmo(%.2f): '%s' subtracted too much %s from '%s', resulting with '%.2f' left... "
-				"Please notify Samual immediately with a copy of this backtrace!\n",
-				ammo_use,
-				wep.netname,
-				GetAmmoPicture(wep.ammo_field),
-				self.netname,
-				self.(wep.ammo_field)
-			));
-		}
-	}
-}
-
-// weapon reloading code
-
-.float reload_ammo_amount, reload_ammo_min, reload_time;
-.float reload_complain;
-.string reload_sound;
-
-void W_ReloadedAndReady()
-{
-	// finish the reloading process, and do the ammo transfer
-
-	self.clip_load = self.old_clip_load; // restore the ammo counter, in case we still had ammo in the weapon before reloading
-
-	// if the gun uses no ammo, max out weapon load, else decrease ammo as we increase weapon load
-	if(!self.reload_ammo_min || self.items & IT_UNLIMITED_WEAPON_AMMO || self.ammo_field == ammo_none)
-		self.clip_load = self.reload_ammo_amount;
-	else
-	{
-		while(self.clip_load < self.reload_ammo_amount && self.(self.ammo_field)) // make sure we don't add more ammo than we have
-		{
-			self.clip_load += 1;
-			self.(self.ammo_field) -= 1;
-		}
-	}
-	self.(weapon_load[self.weapon]) = self.clip_load;
-
-	// do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
-	// then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
-	// so your weapon is disabled for a few seconds without reason
-
-	//ATTACK_FINISHED(self) -= self.reload_time - 1;
-
-	w_ready();
-}
-
-void W_Reload(float sent_ammo_min, string sent_sound)
-{
-	// set global values to work with
-	entity e;
-	e = get_weaponinfo(self.weapon);
-
-	self.reload_ammo_min = sent_ammo_min;
-	self.reload_ammo_amount = e.reloading_ammo;;
-	self.reload_time = e.reloading_time;
-	self.reload_sound = sent_sound;
-
-	// don't reload weapons that don't have the RELOADABLE flag
-	if (!(e.spawnflags & WEP_FLAG_RELOADABLE))
-	{
-		dprint("Warning: Attempted to reload a weapon that does not have the WEP_FLAG_RELOADABLE flag. Fix your code!\n");
-		return;
-	}
-
-	// return if reloading is disabled for this weapon
-	if(!self.reload_ammo_amount)
-		return;
-
-	// our weapon is fully loaded, no need to reload
-	if (self.clip_load >= self.reload_ammo_amount)
-		return;
-
-	// no ammo, so nothing to load
-	if(self.ammo_field != ammo_none)
-	if(!self.(self.ammo_field) && self.reload_ammo_min)
-	if (!(self.items & IT_UNLIMITED_WEAPON_AMMO))
-	{
-		if(IS_REAL_CLIENT(self) && self.reload_complain < time)
-		{
-			play2(self, "weapons/unavailable.wav");
-			sprint(self, strcat("You don't have enough ammo to reload the ^2", WEP_NAME(self.weapon), "\n"));
-			self.reload_complain = time + 1;
-		}
-		// switch away if the amount of ammo is not enough to keep using this weapon
-		if (!(WEP_ACTION(self.weapon, WR_CHECKAMMO1) + WEP_ACTION(self.weapon, WR_CHECKAMMO2)))
-		{
-			self.clip_load = -1; // reload later
-			W_SwitchToOtherWeapon(self);
-		}
-		return;
-	}
-
-	if (self.weaponentity)
-	{
-		if (self.weaponentity.wframe == WFRAME_RELOAD)
-			return;
-
-		// allow switching away while reloading, but this will cause a new reload!
-		self.weaponentity.state = WS_READY;
-	}
-
-	// now begin the reloading process
-
-	sound(self, CH_WEAPON_SINGLE, self.reload_sound, VOL_BASE, ATTEN_NORM);
-
-	// do not set ATTACK_FINISHED in reload code any more. This causes annoying delays if eg: You start reloading a weapon,
-	// then quickly switch to another weapon and back. Reloading is canceled, but the reload delay is still there,
-	// so your weapon is disabled for a few seconds without reason
-
-	//ATTACK_FINISHED(self) = max(time, ATTACK_FINISHED(self)) + self.reload_time + 1;
-
-	weapon_thinkf(WFRAME_RELOAD, self.reload_time, W_ReloadedAndReady);
-
-	if(self.clip_load < 0)
-		self.clip_load = 0;
-	self.old_clip_load = self.clip_load;
-	self.clip_load = self.(weapon_load[self.weapon]) = -1;
-}
diff --git a/qcsrc/server/weapons/weaponsystem.qh b/qcsrc/server/weapons/weaponsystem.qh
deleted file mode 100644
index 47ae74b42..000000000
--- a/qcsrc/server/weapons/weaponsystem.qh
+++ /dev/null
@@ -1,2 +0,0 @@
-float weaponswapping;
-float internalteam;
diff --git a/qcsrc/warpzonelib/TODO b/qcsrc/warpzonelib/TODO
index 89f527790..5c9a55fc1 100644
--- a/qcsrc/warpzonelib/TODO
+++ b/qcsrc/warpzonelib/TODO
@@ -6,7 +6,7 @@ Weapon support:
 
 - laser: YES
 - shotgun: YES
-- machinegun: YES
+- uzi: YES
 - grenadelauncher: YES
 - electro: YES
 - crylink: YES
@@ -15,7 +15,7 @@ Weapon support:
 - rocketlauncher: YES (except for trail bug)
 - porto: YES (bwahahahaha)
 - hlac: YES
-- vaporizer: YES
+- minstanex: YES
 - rifle: YES
 - fireball: YES (BFG effect cannot work through warpzones by design, so it's not available through warpzones)
 - hook: YES
diff --git a/qcsrc/warpzonelib/client.qc b/qcsrc/warpzonelib/client.qc
index c2a110b4a..f55cec1d5 100644
--- a/qcsrc/warpzonelib/client.qc
+++ b/qcsrc/warpzonelib/client.qc
@@ -239,8 +239,8 @@ void WarpZone_FixView()
 	vector org, ang, nearclip, corner0, corner1, corner2, corner3, o;
 	float f;
 
-	warpzone_save_view_origin = org = getpropertyvec(VF_ORIGIN);
-	warpzone_save_view_angles = ang = getpropertyvec(VF_ANGLES);
+	org = getpropertyvec(VF_ORIGIN);
+	ang = getpropertyvec(VF_ANGLES);
 #ifdef WORKAROUND_XON010
 	float dirty;
 	dirty = checkextension("DP_CSQC_ROTATEMOVES");
diff --git a/qcsrc/warpzonelib/client.qh b/qcsrc/warpzonelib/client.qh
index c0a4ca0f0..446c917db 100644
--- a/qcsrc/warpzonelib/client.qh
+++ b/qcsrc/warpzonelib/client.qh
@@ -7,6 +7,3 @@ void WarpZone_FixView();
 
 void WarpZone_Init();
 void WarpZone_Shutdown();
-
-vector warpzone_save_view_origin;
-vector warpzone_save_view_angles;
diff --git a/scripts/weapons.shader b/scripts/weapons.shader
index c5c673fbf..a6dcfaab8 100644
--- a/scripts/weapons.shader
+++ b/scripts/weapons.shader
@@ -103,11 +103,3 @@ minelayer
 		rgbgen lightingDiffuse
 	}
 }
-shotgun
-{
-	dpreflectcube cubemaps/default/sky
-	{
-		map textures/arc.tga
-		rgbgen lightingDiffuse
-	}
-}
diff --git a/sound/weapons/gauntlet_fire.ogg b/sound/weapons/gauntlet_fire.ogg
new file mode 100644
index 000000000..03802f65d
Binary files /dev/null and b/sound/weapons/gauntlet_fire.ogg differ
diff --git a/sound/weapons/gauntletbeam_fly.ogg b/sound/weapons/gauntletbeam_fly.ogg
new file mode 100644
index 000000000..874d246f5
Binary files /dev/null and b/sound/weapons/gauntletbeam_fly.ogg differ
diff --git a/textures/arc.tga b/textures/arc.tga
deleted file mode 100644
index 55d2f34b3..000000000
Binary files a/textures/arc.tga and /dev/null differ
diff --git a/textures/arc_gloss.tga b/textures/arc_gloss.tga
deleted file mode 100644
index 45734a7ef..000000000
Binary files a/textures/arc_gloss.tga and /dev/null differ
diff --git a/textures/arc_glow.tga b/textures/arc_glow.tga
deleted file mode 100644
index 2b3575116..000000000
Binary files a/textures/arc_glow.tga and /dev/null differ
diff --git a/textures/arc_norm.tga b/textures/arc_norm.tga
deleted file mode 100644
index 39e183148..000000000
Binary files a/textures/arc_norm.tga and /dev/null differ
diff --git a/textures/arc_reflect.tga b/textures/arc_reflect.tga
deleted file mode 100644
index b60f891b0..000000000
Binary files a/textures/arc_reflect.tga and /dev/null differ
diff --git a/textures/arc_shirt.tga b/textures/arc_shirt.tga
deleted file mode 100644
index 90107daa1..000000000
Binary files a/textures/arc_shirt.tga and /dev/null differ
diff --git a/vehicles.cfg b/vehicles.cfg
index ea296146d..d28aa4cad 100644
--- a/vehicles.cfg
+++ b/vehicles.cfg
@@ -18,9 +18,9 @@ set cl_vehicles_hudscale 0.5
 set g_vehicles_delayspawn 1
 set g_vehicles_delayspawn_jitter 10
 
-set g_vehicles_vortex_damagerate 0.5
-set g_vehicles_machinegun_damagerate 0.65
+set g_vehicles_nex_damagerate 0.5
+set g_vehicles_uzi_damagerate 0.65
 set g_vehicles_rifle_damagerate 1
-set g_vehicles_vaporizer_damagerate 0.007
+set g_vehicles_minstanex_damagerate 0.007
 set g_vehicles_tag_damagerate 2