Merge branch 'master' into Lyberta/StandaloneOverkillWeapons
authorLyberta <lyberta@lyberta.net>
Tue, 29 Aug 2017 00:46:57 +0000 (03:46 +0300)
committerLyberta <lyberta@lyberta.net>
Tue, 29 Aug 2017 00:46:57 +0000 (03:46 +0300)
26 files changed:
bal-wep-overkill-nerfed.cfg [new file with mode: 0644]
bal-wep-overkill.cfg
bal-wep-xonotic.cfg
defaultClient.cfg
defaultServer.cfg
qcsrc/client/view.qc
qcsrc/common/mutators/mutator/overkill/_mod.inc
qcsrc/common/mutators/mutator/overkill/_mod.qh
qcsrc/common/mutators/mutator/overkill/cl_overkill.qc
qcsrc/common/mutators/mutator/overkill/hmg.qc
qcsrc/common/mutators/mutator/overkill/hmg.qh
qcsrc/common/mutators/mutator/overkill/okmachinegun.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/overkill/okmachinegun.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/overkill/okshotgun.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/overkill/okshotgun.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/overkill/okvortex.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/overkill/okvortex.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/overkill/rpc.qc
qcsrc/common/mutators/mutator/overkill/rpc.qh
qcsrc/common/mutators/mutator/overkill/sv_overkill.qc
qcsrc/common/stats.qh
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/common/wepent.qc
qcsrc/common/wepent.qh
qcsrc/server/client.qc
qcsrc/server/defs.qh

diff --git a/bal-wep-overkill-nerfed.cfg b/bal-wep-overkill-nerfed.cfg
new file mode 100644 (file)
index 0000000..49d9948
--- /dev/null
@@ -0,0 +1,132 @@
+// This config file is for overkill weapons that were nerfed to have the same
+// stats as vanilla weapons, secondary attack uses stats of vanilla blaster.
+
+// {{{ Overkill Shotgun
+set g_balance_okshotgun_primary_ammo 1
+set g_balance_okshotgun_primary_animtime 0.2
+set g_balance_okshotgun_primary_bot_range 512
+set g_balance_okshotgun_primary_bullets 12
+set g_balance_okshotgun_primary_damage 4
+set g_balance_okshotgun_primary_force 15
+set g_balance_okshotgun_primary_refire 0.75
+set g_balance_okshotgun_primary_solidpenetration 3.8
+set g_balance_okshotgun_primary_spread 0.12
+set g_balance_okshotgun_reload_ammo 0
+set g_balance_okshotgun_reload_time 2
+set g_balance_okshotgun_secondary_ammo 0
+set g_balance_okshotgun_secondary_animtime 0.2
+set g_balance_okshotgun_secondary_damage 20
+set g_balance_okshotgun_secondary_delay 0
+set g_balance_okshotgun_secondary_edgedamage 10
+set g_balance_okshotgun_secondary_force 300
+set g_balance_okshotgun_secondary_lifetime 5
+set g_balance_okshotgun_secondary_radius 60
+set g_balance_okshotgun_secondary_refire 0.7
+set g_balance_okshotgun_secondary_refire_type 0
+set g_balance_okshotgun_secondary_shotangle 0
+set g_balance_okshotgun_secondary_speed 6000
+set g_balance_okshotgun_secondary_spread 0
+set g_balance_okshotgun_switchdelay_drop 0.2
+set g_balance_okshotgun_switchdelay_raise 0.2
+set g_balance_okshotgun_weaponreplace ""
+set g_balance_okshotgun_weaponstart 0
+set g_balance_okshotgun_weaponstartoverride -1
+set g_balance_okshotgun_weaponthrowable 1
+// }}}
+// {{{ Overkill Machine Gun
+set g_balance_okmachinegun_burst 3
+set g_balance_okmachinegun_burst_ammo 3
+set g_balance_okmachinegun_burst_animtime 0.3
+set g_balance_okmachinegun_burst_refire 0.06
+set g_balance_okmachinegun_burst_refire2 0.45
+set g_balance_okmachinegun_burst_speed 0
+set g_balance_okmachinegun_first 1
+set g_balance_okmachinegun_first_ammo 1
+set g_balance_okmachinegun_first_damage 14
+set g_balance_okmachinegun_first_force 3
+set g_balance_okmachinegun_first_refire 0.125
+set g_balance_okmachinegun_first_spread 0.03
+set g_balance_okmachinegun_mode 1
+set g_balance_okmachinegun_reload_ammo 60
+set g_balance_okmachinegun_reload_time 2
+set g_balance_okmachinegun_secondary_ammo 0
+set g_balance_okmachinegun_secondary_animtime 0.2
+set g_balance_okmachinegun_secondary_damage 20
+set g_balance_okmachinegun_secondary_delay 0
+set g_balance_okmachinegun_secondary_edgedamage 10
+set g_balance_okmachinegun_secondary_force 300
+set g_balance_okmachinegun_secondary_lifetime 5
+set g_balance_okmachinegun_secondary_radius 60
+set g_balance_okmachinegun_secondary_refire 0.7
+set g_balance_okmachinegun_secondary_refire_type 0
+set g_balance_okmachinegun_secondary_shotangle 0
+set g_balance_okmachinegun_secondary_speed 6000
+set g_balance_okmachinegun_secondary_spread 0
+set g_balance_okmachinegun_solidpenetration 13.1
+set g_balance_okmachinegun_spread_add 0.012
+set g_balance_okmachinegun_spread_max 0.05
+set g_balance_okmachinegun_spread_min 0.02
+set g_balance_okmachinegun_sustained_ammo 1
+set g_balance_okmachinegun_sustained_damage 10
+set g_balance_okmachinegun_sustained_force 3
+set g_balance_okmachinegun_sustained_refire 0.1
+set g_balance_okmachinegun_sustained_spread 0.03
+set g_balance_okmachinegun_switchdelay_drop 0.2
+set g_balance_okmachinegun_switchdelay_raise 0.2
+set g_balance_okmachinegun_weaponreplace ""
+set g_balance_okmachinegun_weaponstart 0
+set g_balance_okmachinegun_weaponstartoverride -1
+set g_balance_okmachinegun_weaponthrowable 1
+// }}}
+// {{{ Overkill Vortex
+set g_balance_okvortex_charge 1
+set g_balance_okvortex_charge_animlimit 0.5
+set g_balance_okvortex_charge_limit 1
+set g_balance_okvortex_charge_maxspeed 800
+set g_balance_okvortex_charge_mindmg 40
+set g_balance_okvortex_charge_minspeed 400
+set g_balance_okvortex_charge_rate 0.6
+set g_balance_okvortex_charge_rot_pause 0
+set g_balance_okvortex_charge_rot_rate 0
+set g_balance_okvortex_charge_shot_multiplier 0
+set g_balance_okvortex_charge_start 0.5
+set g_balance_okvortex_charge_velocity_rate 0
+set g_balance_okvortex_primary_ammo 6
+set g_balance_okvortex_primary_animtime 0.4
+set g_balance_okvortex_primary_damage 80
+set g_balance_okvortex_primary_damagefalloff_forcehalflife 0
+set g_balance_okvortex_primary_damagefalloff_halflife 0
+set g_balance_okvortex_primary_damagefalloff_maxdist 0
+set g_balance_okvortex_primary_damagefalloff_mindist 0
+set g_balance_okvortex_primary_force 400
+set g_balance_okvortex_primary_refire 1.5
+set g_balance_okvortex_reload_ammo 0
+set g_balance_okvortex_reload_time 2
+set g_balance_okvortex_secondary 0
+set g_balance_okvortex_secondary_ammo 2
+set g_balance_okvortex_secondary_animtime 0
+set g_balance_okvortex_secondary_chargepool 0
+set g_balance_okvortex_secondary_chargepool_pause_regen 1
+set g_balance_okvortex_secondary_chargepool_regen 0.15
+set g_balance_okvortex_secondary_damage 0
+set g_balance_okvortex_secondary_damagefalloff_forcehalflife 0
+set g_balance_okvortex_secondary_damagefalloff_halflife 0
+set g_balance_okvortex_secondary_damagefalloff_maxdist 0
+set g_balance_okvortex_secondary_damagefalloff_mindist 0
+set g_balance_okvortex_secondary_force 0
+set g_balance_okvortex_secondary_refire 0
+set g_balance_okvortex_secondary_refire_type 0
+set g_balance_okvortex_secondary_delay 0
+set g_balance_okvortex_secondary_edgedamage 10
+set g_balance_okvortex_secondary_lifetime 5
+set g_balance_okvortex_secondary_radius 60
+set g_balance_okvortex_secondary_shotangle 0
+set g_balance_okvortex_secondary_speed 6000
+set g_balance_okvortex_secondary_spread 0
+set g_balance_okvortex_switchdelay_drop 0.2
+set g_balance_okvortex_switchdelay_raise 0.2
+set g_balance_okvortex_weaponreplace ""
+set g_balance_okvortex_weaponstart 0
+set g_balance_okvortex_weaponstartoverride -1
+set g_balance_okvortex_weaponthrowable 1
+// }}}
index 9cfffed..67cc815 100644 (file)
@@ -778,16 +778,16 @@ set g_balance_arc_weaponstartoverride -1
 set g_balance_arc_weaponthrowable 1
 // }}}
 // {{{ #21: Heavy Machine Gun
-set g_balance_hmg_ammo 1
-set g_balance_hmg_damage 30
-set g_balance_hmg_force 10
-set g_balance_hmg_refire 0.05
+set g_balance_hmg_primary_ammo 1
+set g_balance_hmg_primary_damage 30
+set g_balance_hmg_primary_force 10
+set g_balance_hmg_primary_refire 0.05
+set g_balance_hmg_primary_solidpenetration 32
+set g_balance_hmg_primary_spread_add 0.005
+set g_balance_hmg_primary_spread_max 0.06
+set g_balance_hmg_primary_spread_min 0.01
 set g_balance_hmg_reload_ammo 120
 set g_balance_hmg_reload_time 1
-set g_balance_hmg_solidpenetration 32
-set g_balance_hmg_spread_add 0.005
-set g_balance_hmg_spread_max 0.06
-set g_balance_hmg_spread_min 0.01
 set g_balance_hmg_switchdelay_drop 0.2
 set g_balance_hmg_switchdelay_raise 0.2
 set g_balance_hmg_weaponreplace ""
@@ -796,21 +796,21 @@ set g_balance_hmg_weaponstartoverride 0
 set g_balance_hmg_weaponthrowable 0
 // }}}
 // {{{ #22: Rocket Propelled Chainsaw
-set g_balance_rpc_ammo 10
-set g_balance_rpc_animtime 1
-set g_balance_rpc_damage 150
-set g_balance_rpc_damage2 500
-set g_balance_rpc_damageforcescale 2
-set g_balance_rpc_edgedamage 50
-set g_balance_rpc_force 400
-set g_balance_rpc_health 25
-set g_balance_rpc_lifetime 30
-set g_balance_rpc_radius 300
-set g_balance_rpc_refire 1
+set g_balance_rpc_primary_ammo 10
+set g_balance_rpc_primary_animtime 1
+set g_balance_rpc_primary_damage 150
+set g_balance_rpc_primary_damage2 500
+set g_balance_rpc_primary_damageforcescale 2
+set g_balance_rpc_primary_edgedamage 50
+set g_balance_rpc_primary_force 400
+set g_balance_rpc_primary_health 25
+set g_balance_rpc_primary_lifetime 30
+set g_balance_rpc_primary_radius 300
+set g_balance_rpc_primary_refire 1
+set g_balance_rpc_primary_speed 2500
+set g_balance_rpc_primary_speedaccel 5000
 set g_balance_rpc_reload_ammo 10
 set g_balance_rpc_reload_time 1
-set g_balance_rpc_speed 2500
-set g_balance_rpc_speedaccel 5000
 set g_balance_rpc_switchdelay_drop 0.2
 set g_balance_rpc_switchdelay_raise 0.2
 set g_balance_rpc_weaponreplace ""
@@ -818,3 +818,132 @@ set g_balance_rpc_weaponstart 0
 set g_balance_rpc_weaponstartoverride 0
 set g_balance_rpc_weaponthrowable 0
 // }}}
+// {{{ Overkill Shotgun
+set g_balance_okshotgun_primary_ammo 3
+set g_balance_okshotgun_primary_animtime 0.65
+set g_balance_okshotgun_primary_bot_range 512
+set g_balance_okshotgun_primary_bullets 10
+set g_balance_okshotgun_primary_damage 17
+set g_balance_okshotgun_primary_force 80
+set g_balance_okshotgun_primary_refire 0.75
+set g_balance_okshotgun_primary_solidpenetration 3.8
+set g_balance_okshotgun_primary_spread 0.07
+set g_balance_okshotgun_reload_ammo 24
+set g_balance_okshotgun_reload_time 2
+set g_balance_okshotgun_secondary_ammo 0
+set g_balance_okshotgun_secondary_animtime 0.2
+set g_balance_okshotgun_secondary_damage 25
+set g_balance_okshotgun_secondary_delay 0
+set g_balance_okshotgun_secondary_edgedamage 12.5
+set g_balance_okshotgun_secondary_force 300
+set g_balance_okshotgun_secondary_lifetime 5
+set g_balance_okshotgun_secondary_radius 70
+set g_balance_okshotgun_secondary_refire 0.7
+set g_balance_okshotgun_secondary_refire_type 1
+set g_balance_okshotgun_secondary_shotangle 0
+set g_balance_okshotgun_secondary_speed 6000
+set g_balance_okshotgun_secondary_spread 0
+set g_balance_okshotgun_switchdelay_drop 0.2
+set g_balance_okshotgun_switchdelay_raise 0.2
+set g_balance_okshotgun_weaponreplace ""
+set g_balance_okshotgun_weaponstart 0
+set g_balance_okshotgun_weaponstartoverride -1
+set g_balance_okshotgun_weaponthrowable 1
+// }}}
+// {{{ Overkill Machine Gun
+set g_balance_okmachinegun_burst 3
+set g_balance_okmachinegun_burst_ammo 3
+set g_balance_okmachinegun_burst_animtime 0.3
+set g_balance_okmachinegun_burst_refire 0.06
+set g_balance_okmachinegun_burst_refire2 0.45
+set g_balance_okmachinegun_burst_speed 0
+set g_balance_okmachinegun_first 1
+set g_balance_okmachinegun_first_ammo 1
+set g_balance_okmachinegun_first_damage 14
+set g_balance_okmachinegun_first_force 5
+set g_balance_okmachinegun_first_refire 0.125
+set g_balance_okmachinegun_first_spread 0.03
+set g_balance_okmachinegun_mode 1
+set g_balance_okmachinegun_reload_ammo 30
+set g_balance_okmachinegun_reload_time 1.5
+set g_balance_okmachinegun_secondary_ammo 0
+set g_balance_okmachinegun_secondary_animtime 0.2
+set g_balance_okmachinegun_secondary_damage 25
+set g_balance_okmachinegun_secondary_delay 0
+set g_balance_okmachinegun_secondary_edgedamage 12.5
+set g_balance_okmachinegun_secondary_force 300
+set g_balance_okmachinegun_secondary_lifetime 5
+set g_balance_okmachinegun_secondary_radius 70
+set g_balance_okmachinegun_secondary_refire 0.7
+set g_balance_okmachinegun_secondary_refire_type 1
+set g_balance_okmachinegun_secondary_shotangle 0
+set g_balance_okmachinegun_secondary_speed 6000
+set g_balance_okmachinegun_secondary_spread 0
+set g_balance_okmachinegun_solidpenetration 13.1
+set g_balance_okmachinegun_spread_add 0.012
+set g_balance_okmachinegun_spread_max 0.05
+set g_balance_okmachinegun_spread_min 0
+set g_balance_okmachinegun_sustained_ammo 1
+set g_balance_okmachinegun_sustained_damage 25
+set g_balance_okmachinegun_sustained_force 5
+set g_balance_okmachinegun_sustained_refire 0.1
+set g_balance_okmachinegun_sustained_spread 0.01
+set g_balance_okmachinegun_switchdelay_drop 0.2
+set g_balance_okmachinegun_switchdelay_raise 0.2
+set g_balance_okmachinegun_weaponreplace ""
+set g_balance_okmachinegun_weaponstart 0
+set g_balance_okmachinegun_weaponstartoverride -1
+set g_balance_okmachinegun_weaponthrowable 1
+// }}}
+// {{{ Overkill Vortex
+set g_balance_okvortex_charge 0
+set g_balance_okvortex_charge_animlimit 0.5
+set g_balance_okvortex_charge_limit 1
+set g_balance_okvortex_charge_maxspeed 800
+set g_balance_okvortex_charge_mindmg 40
+set g_balance_okvortex_charge_minspeed 400
+set g_balance_okvortex_charge_rate 0.6
+set g_balance_okvortex_charge_rot_pause 0
+set g_balance_okvortex_charge_rot_rate 0
+set g_balance_okvortex_charge_shot_multiplier 0
+set g_balance_okvortex_charge_start 0.5
+set g_balance_okvortex_charge_velocity_rate 0
+set g_balance_okvortex_primary_ammo 10
+set g_balance_okvortex_primary_animtime 0.65
+set g_balance_okvortex_primary_damage 100
+set g_balance_okvortex_primary_damagefalloff_forcehalflife 0
+set g_balance_okvortex_primary_damagefalloff_halflife 0
+set g_balance_okvortex_primary_damagefalloff_maxdist 0
+set g_balance_okvortex_primary_damagefalloff_mindist 0
+set g_balance_okvortex_primary_force 500
+set g_balance_okvortex_primary_refire 1
+set g_balance_okvortex_reload_ammo 50
+set g_balance_okvortex_reload_time 2
+set g_balance_okvortex_secondary 2
+set g_balance_okvortex_secondary_ammo 0
+set g_balance_okvortex_secondary_animtime 0.2
+set g_balance_okvortex_secondary_chargepool 0
+set g_balance_okvortex_secondary_chargepool_pause_regen 1
+set g_balance_okvortex_secondary_chargepool_regen 0.15
+set g_balance_okvortex_secondary_damage 25
+set g_balance_okvortex_secondary_damagefalloff_forcehalflife 0
+set g_balance_okvortex_secondary_damagefalloff_halflife 0
+set g_balance_okvortex_secondary_damagefalloff_maxdist 0
+set g_balance_okvortex_secondary_damagefalloff_mindist 0
+set g_balance_okvortex_secondary_force 300
+set g_balance_okvortex_secondary_refire 0.7
+set g_balance_okvortex_secondary_refire_type 1
+set g_balance_okvortex_secondary_delay 0
+set g_balance_okvortex_secondary_edgedamage 12.5
+set g_balance_okvortex_secondary_lifetime 5
+set g_balance_okvortex_secondary_radius 70
+set g_balance_okvortex_secondary_shotangle 0
+set g_balance_okvortex_secondary_speed 6000
+set g_balance_okvortex_secondary_spread 0
+set g_balance_okvortex_switchdelay_drop 0.2
+set g_balance_okvortex_switchdelay_raise 0.2
+set g_balance_okvortex_weaponreplace ""
+set g_balance_okvortex_weaponstart 0
+set g_balance_okvortex_weaponstartoverride -1
+set g_balance_okvortex_weaponthrowable 1
+// }}}
index ac5be34..aea4a1a 100644 (file)
@@ -778,16 +778,29 @@ set g_balance_arc_weaponstartoverride -1
 set g_balance_arc_weaponthrowable 1
 // }}}
 // {{{ #21: Heavy Machine Gun
-set g_balance_hmg_ammo 1
-set g_balance_hmg_damage 30
-set g_balance_hmg_force 10
-set g_balance_hmg_refire 0.05
+set g_balance_hmg_primary_ammo 1
+set g_balance_hmg_primary_damage 30
+set g_balance_hmg_primary_force 10
+set g_balance_hmg_primary_refire 0.05
+set g_balance_hmg_primary_solidpenetration 32
+set g_balance_hmg_primary_spread_add 0.005
+set g_balance_hmg_primary_spread_max 0.06
+set g_balance_hmg_primary_spread_min 0.01
 set g_balance_hmg_reload_ammo 120
 set g_balance_hmg_reload_time 1
-set g_balance_hmg_solidpenetration 32
-set g_balance_hmg_spread_add 0.005
-set g_balance_hmg_spread_max 0.06
-set g_balance_hmg_spread_min 0.01
+set g_balance_hmg_secondary_ammo 0
+set g_balance_hmg_secondary_animtime 0.2
+set g_balance_hmg_secondary_damage 25
+set g_balance_hmg_secondary_delay 0
+set g_balance_hmg_secondary_edgedamage 12.5
+set g_balance_hmg_secondary_force 300
+set g_balance_hmg_secondary_lifetime 5
+set g_balance_hmg_secondary_radius 70
+set g_balance_hmg_secondary_refire 0.7
+set g_balance_hmg_secondary_refire_type 1
+set g_balance_hmg_secondary_shotangle 0
+set g_balance_hmg_secondary_speed 6000
+set g_balance_hmg_secondary_spread 0
 set g_balance_hmg_switchdelay_drop 0.2
 set g_balance_hmg_switchdelay_raise 0.2
 set g_balance_hmg_weaponreplace ""
@@ -796,21 +809,34 @@ set g_balance_hmg_weaponstartoverride 0
 set g_balance_hmg_weaponthrowable 0
 // }}}
 // {{{ #22: Rocket Propelled Chainsaw
-set g_balance_rpc_ammo 10
-set g_balance_rpc_animtime 1
-set g_balance_rpc_damage 150
-set g_balance_rpc_damage2 500
-set g_balance_rpc_damageforcescale 2
-set g_balance_rpc_edgedamage 50
-set g_balance_rpc_force 400
-set g_balance_rpc_health 25
-set g_balance_rpc_lifetime 30
-set g_balance_rpc_radius 300
-set g_balance_rpc_refire 1
+set g_balance_rpc_primary_ammo 10
+set g_balance_rpc_primary_animtime 1
+set g_balance_rpc_primary_damage 150
+set g_balance_rpc_primary_damage2 500
+set g_balance_rpc_primary_damageforcescale 2
+set g_balance_rpc_primary_edgedamage 50
+set g_balance_rpc_primary_force 400
+set g_balance_rpc_primary_health 25
+set g_balance_rpc_primary_lifetime 30
+set g_balance_rpc_primary_radius 300
+set g_balance_rpc_primary_refire 1
+set g_balance_rpc_primary_speed 2500
+set g_balance_rpc_primary_speedaccel 5000
 set g_balance_rpc_reload_ammo 10
 set g_balance_rpc_reload_time 1
-set g_balance_rpc_speed 2500
-set g_balance_rpc_speedaccel 5000
+set g_balance_rpc_secondary_ammo 0
+set g_balance_rpc_secondary_animtime 0.2
+set g_balance_rpc_secondary_damage 25
+set g_balance_rpc_secondary_delay 0
+set g_balance_rpc_secondary_edgedamage 12.5
+set g_balance_rpc_secondary_force 300
+set g_balance_rpc_secondary_lifetime 5
+set g_balance_rpc_secondary_radius 70
+set g_balance_rpc_secondary_refire 0.7
+set g_balance_rpc_secondary_refire_type 1
+set g_balance_rpc_secondary_shotangle 0
+set g_balance_rpc_secondary_speed 6000
+set g_balance_rpc_secondary_spread 0
 set g_balance_rpc_switchdelay_drop 0.2
 set g_balance_rpc_switchdelay_raise 0.2
 set g_balance_rpc_weaponreplace ""
@@ -818,3 +844,132 @@ set g_balance_rpc_weaponstart 0
 set g_balance_rpc_weaponstartoverride 0
 set g_balance_rpc_weaponthrowable 0
 // }}}
+// {{{ Overkill Shotgun
+set g_balance_okshotgun_primary_ammo 3
+set g_balance_okshotgun_primary_animtime 0.65
+set g_balance_okshotgun_primary_bot_range 512
+set g_balance_okshotgun_primary_bullets 10
+set g_balance_okshotgun_primary_damage 17
+set g_balance_okshotgun_primary_force 80
+set g_balance_okshotgun_primary_refire 0.75
+set g_balance_okshotgun_primary_solidpenetration 3.8
+set g_balance_okshotgun_primary_spread 0.07
+set g_balance_okshotgun_reload_ammo 24
+set g_balance_okshotgun_reload_time 2
+set g_balance_okshotgun_secondary_ammo 0
+set g_balance_okshotgun_secondary_animtime 0.2
+set g_balance_okshotgun_secondary_damage 25
+set g_balance_okshotgun_secondary_delay 0
+set g_balance_okshotgun_secondary_edgedamage 12.5
+set g_balance_okshotgun_secondary_force 300
+set g_balance_okshotgun_secondary_lifetime 5
+set g_balance_okshotgun_secondary_radius 70
+set g_balance_okshotgun_secondary_refire 0.7
+set g_balance_okshotgun_secondary_refire_type 1
+set g_balance_okshotgun_secondary_shotangle 0
+set g_balance_okshotgun_secondary_speed 6000
+set g_balance_okshotgun_secondary_spread 0
+set g_balance_okshotgun_switchdelay_drop 0.2
+set g_balance_okshotgun_switchdelay_raise 0.2
+set g_balance_okshotgun_weaponreplace ""
+set g_balance_okshotgun_weaponstart 0
+set g_balance_okshotgun_weaponstartoverride -1
+set g_balance_okshotgun_weaponthrowable 1
+// }}}
+// {{{ Overkill Machine Gun
+set g_balance_okmachinegun_burst 3
+set g_balance_okmachinegun_burst_ammo 3
+set g_balance_okmachinegun_burst_animtime 0.3
+set g_balance_okmachinegun_burst_refire 0.06
+set g_balance_okmachinegun_burst_refire2 0.45
+set g_balance_okmachinegun_burst_speed 0
+set g_balance_okmachinegun_first 1
+set g_balance_okmachinegun_first_ammo 1
+set g_balance_okmachinegun_first_damage 14
+set g_balance_okmachinegun_first_force 5
+set g_balance_okmachinegun_first_refire 0.125
+set g_balance_okmachinegun_first_spread 0.03
+set g_balance_okmachinegun_mode 1
+set g_balance_okmachinegun_reload_ammo 30
+set g_balance_okmachinegun_reload_time 1.5
+set g_balance_okmachinegun_secondary_ammo 0
+set g_balance_okmachinegun_secondary_animtime 0.2
+set g_balance_okmachinegun_secondary_damage 25
+set g_balance_okmachinegun_secondary_delay 0
+set g_balance_okmachinegun_secondary_edgedamage 12.5
+set g_balance_okmachinegun_secondary_force 300
+set g_balance_okmachinegun_secondary_lifetime 5
+set g_balance_okmachinegun_secondary_radius 70
+set g_balance_okmachinegun_secondary_refire 0.7
+set g_balance_okmachinegun_secondary_refire_type 1
+set g_balance_okmachinegun_secondary_shotangle 0
+set g_balance_okmachinegun_secondary_speed 6000
+set g_balance_okmachinegun_secondary_spread 0
+set g_balance_okmachinegun_solidpenetration 13.1
+set g_balance_okmachinegun_spread_add 0.012
+set g_balance_okmachinegun_spread_max 0.05
+set g_balance_okmachinegun_spread_min 0
+set g_balance_okmachinegun_sustained_ammo 1
+set g_balance_okmachinegun_sustained_damage 25
+set g_balance_okmachinegun_sustained_force 5
+set g_balance_okmachinegun_sustained_refire 0.1
+set g_balance_okmachinegun_sustained_spread 0.01
+set g_balance_okmachinegun_switchdelay_drop 0.2
+set g_balance_okmachinegun_switchdelay_raise 0.2
+set g_balance_okmachinegun_weaponreplace ""
+set g_balance_okmachinegun_weaponstart 0
+set g_balance_okmachinegun_weaponstartoverride -1
+set g_balance_okmachinegun_weaponthrowable 1
+// }}}
+// {{{ Overkill Vortex
+set g_balance_okvortex_charge 0
+set g_balance_okvortex_charge_animlimit 0.5
+set g_balance_okvortex_charge_limit 1
+set g_balance_okvortex_charge_maxspeed 800
+set g_balance_okvortex_charge_mindmg 40
+set g_balance_okvortex_charge_minspeed 400
+set g_balance_okvortex_charge_rate 0.6
+set g_balance_okvortex_charge_rot_pause 0
+set g_balance_okvortex_charge_rot_rate 0
+set g_balance_okvortex_charge_shot_multiplier 0
+set g_balance_okvortex_charge_start 0.5
+set g_balance_okvortex_charge_velocity_rate 0
+set g_balance_okvortex_primary_ammo 10
+set g_balance_okvortex_primary_animtime 0.65
+set g_balance_okvortex_primary_damage 100
+set g_balance_okvortex_primary_damagefalloff_forcehalflife 0
+set g_balance_okvortex_primary_damagefalloff_halflife 0
+set g_balance_okvortex_primary_damagefalloff_maxdist 0
+set g_balance_okvortex_primary_damagefalloff_mindist 0
+set g_balance_okvortex_primary_force 500
+set g_balance_okvortex_primary_refire 1
+set g_balance_okvortex_reload_ammo 50
+set g_balance_okvortex_reload_time 2
+set g_balance_okvortex_secondary 2
+set g_balance_okvortex_secondary_ammo 0
+set g_balance_okvortex_secondary_animtime 0.2
+set g_balance_okvortex_secondary_chargepool 0
+set g_balance_okvortex_secondary_chargepool_pause_regen 1
+set g_balance_okvortex_secondary_chargepool_regen 0.15
+set g_balance_okvortex_secondary_damage 25
+set g_balance_okvortex_secondary_damagefalloff_forcehalflife 0
+set g_balance_okvortex_secondary_damagefalloff_halflife 0
+set g_balance_okvortex_secondary_damagefalloff_maxdist 0
+set g_balance_okvortex_secondary_damagefalloff_mindist 0
+set g_balance_okvortex_secondary_force 300
+set g_balance_okvortex_secondary_refire 0.7
+set g_balance_okvortex_secondary_refire_type 1
+set g_balance_okvortex_secondary_delay 0
+set g_balance_okvortex_secondary_edgedamage 12.5
+set g_balance_okvortex_secondary_lifetime 5
+set g_balance_okvortex_secondary_radius 70
+set g_balance_okvortex_secondary_shotangle 0
+set g_balance_okvortex_secondary_speed 6000
+set g_balance_okvortex_secondary_spread 0
+set g_balance_okvortex_switchdelay_drop 0.2
+set g_balance_okvortex_switchdelay_raise 0.2
+set g_balance_okvortex_weaponreplace ""
+set g_balance_okvortex_weaponstart 0
+set g_balance_okvortex_weaponstartoverride -1
+set g_balance_okvortex_weaponthrowable 1
+// }}}
index e4904ff..f08874c 100644 (file)
@@ -608,13 +608,13 @@ seta menu_mouse_speed 1 "speed multiplier for the mouse in the menu (does not af
 set menu_use_default_hostname 1
 alias sethostname "set menu_use_default_hostname 0; hostname $*"
 
-seta cl_weaponpriority "vaporizer hmg rpc vortex fireball mortar machinegun hagar rifle arc electro devastator crylink minelayer shotgun shockwave hlac tuba blaster porto seeker hook" "weapon priority list"
+seta cl_weaponpriority "vaporizer hmg rpc okvortex vortex fireball mortar okmachinegun machinegun hagar rifle arc electro devastator crylink minelayer okshotgun shotgun shockwave hlac tuba blaster 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 "rpc devastator mortar hagar seeker fireball"                   "use weapon_priority_0_prev for prev gun from this list, weapon_priority_0_best for best gun, weapon_priority_0_next for next gun.  Default value: explosives"
-seta cl_weaponpriority1 "vaporizer vortex crylink hlac arc electro blaster shockwave"   "use weapon_priority_1_prev for prev gun from this list, weapon_priority_1_best for best gun, weapon_priority_1_next for next gun.  Default value: energy"
-seta cl_weaponpriority2 "vaporizer vortex rifle"                                        "use weapon_priority_2_prev for prev gun from this list, weapon_priority_2_best for best gun, weapon_priority_2_next for next gun.  Default value: hitscan exact"
-seta cl_weaponpriority3 "vaporizer hmg vortex rifle machinegun shotgun shockwave"       "use weapon_priority_3_prev for prev gun from this list, weapon_priority_3_best for best gun, weapon_priority_3_next for next gun.  Default value: hitscan all"
-seta cl_weaponpriority4 "mortar minelayer hlac hagar crylink seeker shotgun shockwave"  "use weapon_priority_4_prev for prev gun from this list, weapon_priority_4_best for best gun, weapon_priority_4_next for next gun.  Default value: spam weapons"
+seta cl_weaponpriority1 "vaporizer okvortex vortex crylink hlac arc electro blaster shockwave"   "use weapon_priority_1_prev for prev gun from this list, weapon_priority_1_best for best gun, weapon_priority_1_next for next gun.  Default value: energy"
+seta cl_weaponpriority2 "vaporizer okvortex vortex rifle"                                        "use weapon_priority_2_prev for prev gun from this list, weapon_priority_2_best for best gun, weapon_priority_2_next for next gun.  Default value: hitscan exact"
+seta cl_weaponpriority3 "vaporizer hmg okvortex vortex rifle okmachinegun machinegun okshotgun shotgun shockwave"       "use weapon_priority_3_prev for prev gun from this list, weapon_priority_3_best for best gun, weapon_priority_3_next for next gun.  Default value: hitscan all"
+seta cl_weaponpriority4 "mortar minelayer hlac hagar crylink seeker okshotgun shotgun shockwave"  "use weapon_priority_4_prev for prev gun from this list, weapon_priority_4_best for best gun, weapon_priority_4_next for next gun.  Default value: spam weapons"
 seta cl_weaponpriority5 "blaster shockwave hook porto"                                  "use weapon_priority_5_prev for prev gun from this list, weapon_priority_5_best for best gun, weapon_priority_5_next for next gun.  Default value: weapons for moving"
 seta cl_weaponpriority6 ""                                                              "use weapon_priority_6_prev for prev gun from this list, weapon_priority_6_best for best gun, weapon_priority_6_next for next gun"
 seta cl_weaponpriority7 ""                                                              "use weapon_priority_7_prev for prev gun from this list, weapon_priority_7_best for best gun, weapon_priority_7_next for next gun"
index 596576a..d199d3a 100644 (file)
@@ -133,9 +133,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 mortar hagar hlac crylink blaster machinegun fireball seeker shotgun shockwave 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 arc crylink hlac hagar shotgun shockwave blaster rifle tuba minelayer"  "Desired weapons for middle distances ordered by priority"
-set bot_ai_custom_weapon_priority_close "vaporizer vortex shotgun shockwave machinegun arc hlac tuba seeker hagar crylink mortar electro devastator blaster fireball rifle minelayer"  "Desired weapons for close distances ordered by priority"
+set bot_ai_custom_weapon_priority_far   "vaporizer okvortex vortex rifle electro devastator mortar hagar hlac crylink blaster okmachinegun machinegun fireball seeker okshotgun shotgun shockwave tuba minelayer"      "Desired weapons for far distances ordered by priority"
+set bot_ai_custom_weapon_priority_mid   "vaporizer devastator okvortex vortex fireball seeker mortar electro okmachinegun machinegun arc crylink hlac hagar okshotgun shotgun shockwave blaster rifle tuba minelayer"  "Desired weapons for middle distances ordered by priority"
+set bot_ai_custom_weapon_priority_close "vaporizer okvortex vortex okshotgun shotgun shockwave okmachinegun machinegun arc hlac tuba seeker hagar crylink mortar electro devastator blaster 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"
index 7a05460..e2aadf1 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <common/vehicles/all.qh>
 #include <common/weapons/_all.qh>
+#include <common/mutators/mutator/overkill/okvortex.qh>
 #include <common/viewloc.qh>
 #include <common/minigames/cl_minigames.qh>
 #include <common/minigames/cl_minigames_hud.qh>
@@ -470,7 +471,7 @@ vector GetCurrentFov(float fov)
                {
                        entity wepent = viewmodels[slot];
                        if(wepent.switchweapon == wepent.activeweapon)
-                       if((wepent.activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (wepent.activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary))) // do NOT use switchweapon here
+                       if((wepent.activeweapon == WEP_VORTEX && !WEP_CVAR(vortex, secondary)) || (wepent.activeweapon == WEP_RIFLE && !WEP_CVAR(rifle, secondary)) || (wepent.activeweapon == WEP_OVERKILL_VORTEX && !WEP_CVAR(okvortex, secondary))) // do NOT use switchweapon here
                                zoomdir += button_attack2;
                }
        }
@@ -662,6 +663,7 @@ float TrueAimCheck(entity wepent)
                case WEP_MORTAR: // toss curve
                        return SHOTTYPE_HITWORLD;
                case WEP_VORTEX:
+               case WEP_OVERKILL_VORTEX:
                case WEP_VAPORIZER:
                        mv = MOVE_NORMAL;
                        break;
@@ -1186,6 +1188,10 @@ void HUD_Crosshair(entity this)
                                vortex_charge = STAT(VORTEX_CHARGE);
                                vortex_chargepool = STAT(VORTEX_CHARGEPOOL);
 
+                               float okvortex_charge, okvortex_chargepool;
+                               okvortex_charge = STAT(OVERKILL_VORTEX_CHARGE);
+                               okvortex_chargepool = STAT(OVERKILL_VORTEX_CHARGEPOOL);
+
                                float arc_heat = STAT(ARC_HEAT);
 
                                if(vortex_charge_movingavg == 0) // this should only happen if we have just loaded up the game
@@ -1214,6 +1220,26 @@ void HUD_Crosshair(entity this)
                                        ring_rgb = wcross_color;
                                        ring_image = "gfx/crosshair_ring_nexgun.tga";
                                }
+                               else if (autocvar_crosshair_ring && (wepent.activeweapon == WEP_OVERKILL_VORTEX) && okvortex_charge && autocvar_crosshair_ring_vortex)
+                               {
+                                       if (okvortex_chargepool || use_vortex_chargepool) {
+                                               use_vortex_chargepool = 1;
+                                               ring_inner_value = okvortex_chargepool;
+                                       } else {
+                                               vortex_charge_movingavg = (1 - autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate) * vortex_charge_movingavg + autocvar_crosshair_ring_vortex_currentcharge_movingavg_rate * okvortex_charge;
+                                               ring_inner_value = bound(0, autocvar_crosshair_ring_vortex_currentcharge_scale * (okvortex_charge - vortex_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_image = "gfx/crosshair_ring_inner.tga";
+
+                                       // draw the outer ring to show the current charge of the weapon
+                                       ring_value = okvortex_charge;
+                                       ring_alpha = autocvar_crosshair_ring_vortex_alpha;
+                                       ring_rgb = wcross_color;
+                                       ring_image = "gfx/crosshair_ring_nexgun.tga";
+                               }
                                else if (autocvar_crosshair_ring && wepent.activeweapon == WEP_MINE_LAYER && WEP_CVAR(minelayer, limit) && autocvar_crosshair_ring_minelayer)
                                {
                                        ring_value = bound(0, STAT(LAYED_MINES) / WEP_CVAR(minelayer, limit), 1); // if you later need to use the count of bullets in another place, then add a float for it. For now, no need to.
index 0552173..55d4fd8 100644 (file)
@@ -1,5 +1,8 @@
 // generated file; do not modify
 #include <common/mutators/mutator/overkill/hmg.qc>
+#include <common/mutators/mutator/overkill/okmachinegun.qc>
+#include <common/mutators/mutator/overkill/okshotgun.qc>
+#include <common/mutators/mutator/overkill/okvortex.qc>
 #include <common/mutators/mutator/overkill/overkill.qc>
 #ifdef CSQC
     #include <common/mutators/mutator/overkill/cl_overkill.qc>
index 13e4243..d259516 100644 (file)
@@ -1,5 +1,8 @@
 // generated file; do not modify
 #include <common/mutators/mutator/overkill/hmg.qh>
+#include <common/mutators/mutator/overkill/okmachinegun.qh>
+#include <common/mutators/mutator/overkill/okshotgun.qh>
+#include <common/mutators/mutator/overkill/okvortex.qh>
 #include <common/mutators/mutator/overkill/overkill.qh>
 #ifdef CSQC
     #include <common/mutators/mutator/overkill/cl_overkill.qh>
index eb21953..4b14194 100644 (file)
@@ -4,8 +4,5 @@ REGISTER_MUTATOR(ok, false)
 {
        MUTATOR_ONADD {
                cvar_settemp("g_overkill", "1");
-               WEP_SHOTGUN.mdl = "ok_shotgun";
-               WEP_MACHINEGUN.mdl = "ok_mg";
-               WEP_VORTEX.mdl = "ok_sniper";
        }
 }
index caf96a6..28ce460 100644 (file)
@@ -27,9 +27,9 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
                return;
        }
 
-       W_DecreaseAmmo(WEP_HMG, actor, WEP_CVAR(hmg, ammo), weaponentity);
+       W_DecreaseAmmo(WEP_HMG, actor, WEP_CVAR_PRI(hmg, ammo), weaponentity);
 
-       W_SetupShot (actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(hmg, damage));
+       W_SetupShot (actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hmg, damage));
 
        if(!autocvar_g_norecoil)
        {
@@ -37,8 +37,8 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
                actor.punchangle_y = random () - 0.5;
        }
 
-       float hmg_spread = bound(WEP_CVAR(hmg, spread_min), WEP_CVAR(hmg, spread_min) + (WEP_CVAR(hmg, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR(hmg, spread_max));
-       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, hmg_spread, WEP_CVAR(hmg, solidpenetration), WEP_CVAR(hmg, damage), WEP_CVAR(hmg, force), WEP_HMG.m_id, 0);
+       float hmg_spread = bound(WEP_CVAR_PRI(hmg, spread_min), WEP_CVAR_PRI(hmg, spread_min) + (WEP_CVAR_PRI(hmg, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR_PRI(hmg, spread_max));
+       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, hmg_spread, WEP_CVAR_PRI(hmg, solidpenetration), WEP_CVAR_PRI(hmg, damage), WEP_CVAR_PRI(hmg, force), WEP_HMG.m_id, 0);
 
        actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
 
@@ -54,8 +54,8 @@ void W_HeavyMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weapone
        }
 
        int slot = weaponslot(weaponentity);
-       ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(hmg, refire) * W_WeaponRateFactor(actor);
-       weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(hmg, refire), W_HeavyMachineGun_Attack_Auto);
+       ATTACK_FINISHED(actor, slot) = time + WEP_CVAR_PRI(hmg, refire) * W_WeaponRateFactor(actor);
+       weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(hmg, refire), W_HeavyMachineGun_Attack_Auto);
 }
 
 METHOD(HeavyMachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
@@ -68,42 +68,114 @@ METHOD(HeavyMachineGun, wr_aim, void(entity thiswep, entity actor, .entity weapo
 
 METHOD(HeavyMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(hmg, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR(hmg, ammo)) { // forced reload
+       if ((WEP_CVAR_SEC(hmg, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
+       {
+               // Secondary uses it's own refire timer if refire_type is 1.
+               actor.jump_interval = time + WEP_CVAR_SEC(hmg, refire) * W_WeaponRateFactor(actor);
+               // Ugly hack to reuse the fire mode of the blaster.
+               makevectors(actor.v_angle);
+               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+               actor.(weaponentity).m_weapon = WEP_BLASTER;
+               W_Blaster_Attack(
+                       actor,
+                       weaponentity,
+                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                       WEP_CVAR_SEC(hmg, shotangle),
+                       WEP_CVAR_SEC(hmg, damage),
+                       WEP_CVAR_SEC(hmg, edgedamage),
+                       WEP_CVAR_SEC(hmg, radius),
+                       WEP_CVAR_SEC(hmg, force),
+                       WEP_CVAR_SEC(hmg, speed),
+                       WEP_CVAR_SEC(hmg, spread),
+                       WEP_CVAR_SEC(hmg, delay),
+                       WEP_CVAR_SEC(hmg, lifetime)
+               );
+               actor.(weaponentity).m_weapon = oldwep;
+               if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
+                       (actor.(weaponentity).wframe == WFRAME_FIRE2))
+               {
+                       // Set secondary fire animation.
+                       vector a = '0 0 0';
+                       actor.(weaponentity).wframe = WFRAME_FIRE2;
+                       a = actor.(weaponentity).anim_fire2;
+                       a.z *= g_weaponratefactor;
+                       FOREACH_CLIENT(true, LAMBDA(
+                               if (it == actor || (IS_SPEC(it) && it.enemy == actor))
+                               {
+                                       wframe_send(it, actor.(weaponentity), a, true);
+                               }
+                       ));
+                       animdecide_setaction(actor, ANIMACTION_SHOOT, true);
+               }
+       }
+    if (WEP_CVAR(hmg, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(hmg, ammo))
+       {
+               // Forced reload.
         thiswep.wr_reload(thiswep, actor, weaponentity);
-    } else
-    {
-        if (fire & 1)
-        if (weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
-        {
-            actor.(weaponentity).misc_bulletcounter = 0;
-            W_HeavyMachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
-        }
-    }
+               return;
+       }
+       if (fire & 1) // Primary attack
+       {
+               if (!weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
+               {
+                       return;
+               }
+               actor.(weaponentity).misc_bulletcounter = 0;
+               W_HeavyMachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
+               return;
+       }
+       if ((fire & 2) && (WEP_CVAR_SEC(hmg, refire_type) == 0)) // Secondary attack
+       {
+               if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(hmg, refire)))
+               {
+                       return;
+               }
+               // ugly instagib hack to reuse the fire mode of the laser
+               makevectors(actor.v_angle);
+               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+               actor.(weaponentity).m_weapon = WEP_BLASTER;
+               W_Blaster_Attack(
+                       actor,
+                       weaponentity,
+                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                       WEP_CVAR_SEC(hmg, shotangle),
+                       WEP_CVAR_SEC(hmg, damage),
+                       WEP_CVAR_SEC(hmg, edgedamage),
+                       WEP_CVAR_SEC(hmg, radius),
+                       WEP_CVAR_SEC(hmg, force),
+                       WEP_CVAR_SEC(hmg, speed),
+                       WEP_CVAR_SEC(hmg, spread),
+                       WEP_CVAR_SEC(hmg, delay),
+                       WEP_CVAR_SEC(hmg, lifetime)
+               );
+               actor.(weaponentity).m_weapon = oldwep;
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(hmg, animtime), w_ready);
+       }
 }
 
 METHOD(HeavyMachineGun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
-    float ammo_amount = actor.ammo_nails >= WEP_CVAR(hmg, ammo);
+    float ammo_amount = actor.ammo_nails >= WEP_CVAR_PRI(hmg, ammo);
 
     if(autocvar_g_balance_hmg_reload_ammo)
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR_PRI(hmg, ammo);
 
     return ammo_amount;
 }
 
 METHOD(HeavyMachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
-    float ammo_amount = actor.ammo_nails >= WEP_CVAR(hmg, ammo);
+    float ammo_amount = actor.ammo_nails >= WEP_CVAR_SEC(hmg, ammo);
 
     if(autocvar_g_balance_hmg_reload_ammo)
-        ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR(hmg, ammo);
+        ammo_amount += actor.(weaponentity).(weapon_load[WEP_HMG.m_id]) >= WEP_CVAR_SEC(hmg, ammo);
 
     return ammo_amount;
 }
 
 METHOD(HeavyMachineGun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, weaponentity, WEP_CVAR(hmg, ammo), SND_RELOAD);
+    W_Reload(actor, weaponentity, WEP_CVAR_PRI(hmg, ammo), SND_RELOAD);
 }
 
 METHOD(HeavyMachineGun, wr_suicidemessage, Notification(entity thiswep))
index 99eb4c8..44eef90 100644 (file)
@@ -18,16 +18,29 @@ CLASS(HeavyMachineGun, Weapon)
 
 #define X(BEGIN, P, END, class, prefix) \
        BEGIN(class) \
-               P(class, prefix, ammo, float, NONE) \
-               P(class, prefix, damage, float, NONE) \
-               P(class, prefix, force, float, NONE) \
-               P(class, prefix, refire, float, NONE) \
+               P(class, prefix, ammo, float, PRI) \
+               P(class, prefix, damage, float, PRI) \
+               P(class, prefix, force, float, PRI) \
+               P(class, prefix, refire, float, PRI) \
+               P(class, prefix, solidpenetration, float, PRI) \
+               P(class, prefix, spread_add, float, PRI) \
+               P(class, prefix, spread_max, float, PRI) \
+               P(class, prefix, spread_min, float, PRI) \
+               P(class, prefix, ammo, float, SEC) \
+               P(class, prefix, animtime, float, SEC) \
+               P(class, prefix, damage, float, SEC) \
+               P(class, prefix, delay, float, SEC) \
+               P(class, prefix, edgedamage, float, SEC) \
+               P(class, prefix, force, float, SEC) \
+               P(class, prefix, lifetime, float, SEC) \
+               P(class, prefix, radius, float, SEC) \
+               P(class, prefix, refire, float, SEC) \
+               P(class, prefix, refire_type, float, SEC) \
+               P(class, prefix, shotangle, float, SEC) \
+               P(class, prefix, speed, float, SEC) \
+               P(class, prefix, spread, float, SEC) \
                P(class, prefix, reload_ammo, float, NONE) \
                P(class, prefix, reload_time, float, NONE) \
-               P(class, prefix, solidpenetration, float, NONE) \
-               P(class, prefix, spread_add, float, NONE) \
-               P(class, prefix, spread_max, float, NONE) \
-               P(class, prefix, spread_min, float, NONE) \
                P(class, prefix, switchdelay_drop, float, NONE) \
                P(class, prefix, switchdelay_raise, float, NONE) \
                P(class, prefix, weaponreplace, string, NONE) \
diff --git a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc
new file mode 100644 (file)
index 0000000..4327fa8
--- /dev/null
@@ -0,0 +1,330 @@
+#include "okmachinegun.qh"
+
+#ifdef SVQC
+
+spawnfunc(weapon_okmachinegun)
+{
+       if(autocvar_sv_q3acompat_machineshotgunswap)
+       if(this.classname != "droppedweapon")
+       {
+               weapon_defaultspawnfunc(this, WEP_SHOCKWAVE);
+               return;
+       }
+       weapon_defaultspawnfunc(this, WEP_OVERKILL_MACHINEGUN);
+}
+
+void W_OverkillMachineGun_Attack(Weapon thiswep, int deathtype, entity actor, .entity weaponentity)
+{
+       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, ((actor.(weaponentity).misc_bulletcounter == 1) ? WEP_CVAR(okmachinegun, first_damage) : WEP_CVAR(okmachinegun, sustained_damage)));
+       if(!autocvar_g_norecoil)
+       {
+               actor.punchangle_x = random() - 0.5;
+               actor.punchangle_y = random() - 0.5;
+       }
+       int slot = weaponslot(weaponentity);
+       // this attack_finished just enforces a cooldown at the end of a burst
+       ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(okmachinegun, first_refire) * W_WeaponRateFactor(actor);
+
+       if(actor.(weaponentity).misc_bulletcounter == 1)
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(okmachinegun, first_spread), WEP_CVAR(okmachinegun, solidpenetration), WEP_CVAR(okmachinegun, first_damage), WEP_CVAR(okmachinegun, first_force), deathtype, 0);
+       else
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(okmachinegun, sustained_spread), WEP_CVAR(okmachinegun, solidpenetration), WEP_CVAR(okmachinegun, sustained_damage), WEP_CVAR(okmachinegun, sustained_force), deathtype, 0);
+
+       Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
+
+       W_MachineGun_MuzzleFlash(actor, weaponentity);
+       W_AttachToShotorg(actor, weaponentity, actor.(weaponentity).muzzle_flash, '5 0 0');
+
+       // casing code
+       if(autocvar_g_casings >= 2)
+       {
+               makevectors(actor.v_angle); // for some reason, this is lost
+               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, actor, weaponentity);
+       }
+
+       if(actor.(weaponentity).misc_bulletcounter == 1)
+               W_DecreaseAmmo(thiswep, actor, WEP_CVAR(okmachinegun, first_ammo), weaponentity);
+       else
+               W_DecreaseAmmo(thiswep, actor, WEP_CVAR(okmachinegun, sustained_ammo), weaponentity);
+}
+
+// weapon frames
+void W_OverkillMachineGun_Attack_Frame(Weapon thiswep, entity actor, .entity weaponentity, int fire)
+{
+       if(actor.(weaponentity).m_weapon != actor.(weaponentity).m_switchweapon) // abort immediately if switching
+       {
+               w_ready(thiswep, actor, weaponentity, fire);
+               return;
+       }
+       if(PHYS_INPUT_BUTTON_ATCK(actor))
+       {
+               if(!thiswep.wr_checkammo2(thiswep, actor, weaponentity))
+               if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+               {
+                       W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
+                       w_ready(thiswep, actor, weaponentity, fire);
+                       return;
+               }
+               actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
+               W_OverkillMachineGun_Attack(WEP_OVERKILL_MACHINEGUN, WEP_OVERKILL_MACHINEGUN.m_id, actor, weaponentity);
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(okmachinegun, sustained_refire), W_OverkillMachineGun_Attack_Frame);
+       }
+       else
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(okmachinegun, sustained_refire), w_ready);
+}
+
+void W_OverkillMachineGun_Attack_Auto(Weapon thiswep, entity actor, .entity weaponentity, int fire)
+{
+       float okmachinegun_spread;
+
+       if(!(fire & 1))
+       {
+               w_ready(thiswep, actor, weaponentity, fire);
+               return;
+       }
+
+       if(!thiswep.wr_checkammo1(thiswep, actor, weaponentity))
+       if(!(actor.items & IT_UNLIMITED_WEAPON_AMMO))
+       {
+               W_SwitchWeapon_Force(actor, w_getbestweapon(actor, weaponentity), weaponentity);
+               w_ready(thiswep, actor, weaponentity, fire);
+               return;
+       }
+
+       W_DecreaseAmmo(WEP_OVERKILL_MACHINEGUN, actor, WEP_CVAR(okmachinegun, sustained_ammo), weaponentity);
+
+       W_SetupShot(actor, weaponentity, true, 0, SND_UZI_FIRE, CH_WEAPON_A, WEP_CVAR(okmachinegun, sustained_damage));
+       if(!autocvar_g_norecoil)
+       {
+               actor.punchangle_x = random() - 0.5;
+               actor.punchangle_y = random() - 0.5;
+       }
+
+       okmachinegun_spread = bound(WEP_CVAR(okmachinegun, spread_min), WEP_CVAR(okmachinegun, spread_min) + (WEP_CVAR(okmachinegun, spread_add) * actor.(weaponentity).misc_bulletcounter), WEP_CVAR(okmachinegun, spread_max));
+       fireBullet(actor, weaponentity, w_shotorg, w_shotdir, okmachinegun_spread, WEP_CVAR(okmachinegun, solidpenetration), WEP_CVAR(okmachinegun, sustained_damage), WEP_CVAR(okmachinegun, sustained_force), WEP_OVERKILL_MACHINEGUN.m_id, 0);
+
+       actor.(weaponentity).misc_bulletcounter = actor.(weaponentity).misc_bulletcounter + 1;
+
+       Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
+
+       W_MachineGun_MuzzleFlash(actor, weaponentity);
+       W_AttachToShotorg(actor, weaponentity, actor.(weaponentity).muzzle_flash, '5 0 0');
+
+       if(autocvar_g_casings >= 2) // casing code
+       {
+               makevectors(actor.v_angle); // for some reason, this is lost
+               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, actor, weaponentity);
+       }
+
+       int slot = weaponslot(weaponentity);
+       ATTACK_FINISHED(actor, slot) = time + WEP_CVAR(okmachinegun, first_refire) * W_WeaponRateFactor(actor);
+       weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(okmachinegun, sustained_refire), W_OverkillMachineGun_Attack_Auto);
+}
+
+METHOD(OverkillMachineGun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
+{
+       if(vdist(actor.origin - actor.enemy.origin, <, 3000 - bound(0, skill, 10) * 200))
+               PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
+       else
+               PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
+}
+
+METHOD(OverkillMachineGun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
+{
+       if ((WEP_CVAR_SEC(okmachinegun, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
+       {
+               // Secondary uses it's own refire timer if refire_type is 1.
+               actor.jump_interval = time + WEP_CVAR_SEC(okmachinegun, refire) * W_WeaponRateFactor(actor);
+               // Ugly hack to reuse the fire mode of the blaster.
+               makevectors(actor.v_angle);
+               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+               actor.(weaponentity).m_weapon = WEP_BLASTER;
+               W_Blaster_Attack(
+                       actor,
+                       weaponentity,
+                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                       WEP_CVAR_SEC(okmachinegun, shotangle),
+                       WEP_CVAR_SEC(okmachinegun, damage),
+                       WEP_CVAR_SEC(okmachinegun, edgedamage),
+                       WEP_CVAR_SEC(okmachinegun, radius),
+                       WEP_CVAR_SEC(okmachinegun, force),
+                       WEP_CVAR_SEC(okmachinegun, speed),
+                       WEP_CVAR_SEC(okmachinegun, spread),
+                       WEP_CVAR_SEC(okmachinegun, delay),
+                       WEP_CVAR_SEC(okmachinegun, lifetime)
+               );
+               actor.(weaponentity).m_weapon = oldwep;
+               if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
+                       (actor.(weaponentity).wframe == WFRAME_FIRE2))
+               {
+                       // Set secondary fire animation.
+                       vector a = '0 0 0';
+                       actor.(weaponentity).wframe = WFRAME_FIRE2;
+                       a = actor.(weaponentity).anim_fire2;
+                       a.z *= g_weaponratefactor;
+                       FOREACH_CLIENT(true, LAMBDA(
+                               if (it == actor || (IS_SPEC(it) && it.enemy == actor))
+                               {
+                                       wframe_send(it, actor.(weaponentity), a, true);
+                               }
+                       ));
+                       animdecide_setaction(actor, ANIMACTION_SHOOT, true);
+               }
+       }
+       if (WEP_CVAR(okmachinegun, reload_ammo) && actor.(weaponentity).clip_load < min(max(WEP_CVAR(okmachinegun, sustained_ammo), WEP_CVAR(okmachinegun, first_ammo)), WEP_CVAR(okmachinegun, burst_ammo)))
+       {
+               // Forced reload
+               thiswep.wr_reload(thiswep, actor, weaponentity);
+               return;
+       }
+       if (WEP_CVAR(okmachinegun, mode) == 1)
+       {
+               if(fire & 1) // Primary attack
+               {
+                       if (!weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
+                       {
+                               return;
+                       }
+                       actor.(weaponentity).misc_bulletcounter = 0;
+                       W_OverkillMachineGun_Attack_Auto(thiswep, actor, weaponentity, fire);
+                       return;
+               }
+               if ((fire & 2) && (WEP_CVAR_SEC(okmachinegun, refire_type) == 0)) // Secondary attack
+               {
+                       if (!weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(okmachinegun, refire)))
+                       {
+                               return;
+                       }
+                       // ugly instagib hack to reuse the fire mode of the laser
+                       makevectors(actor.v_angle);
+                       Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+                       actor.(weaponentity).m_weapon = WEP_BLASTER;
+                       W_Blaster_Attack(
+                               actor,
+                               weaponentity,
+                               WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                               WEP_CVAR_SEC(okmachinegun, shotangle),
+                               WEP_CVAR_SEC(okmachinegun, damage),
+                               WEP_CVAR_SEC(okmachinegun, edgedamage),
+                               WEP_CVAR_SEC(okmachinegun, radius),
+                               WEP_CVAR_SEC(okmachinegun, force),
+                               WEP_CVAR_SEC(okmachinegun, speed),
+                               WEP_CVAR_SEC(okmachinegun, spread),
+                               WEP_CVAR_SEC(okmachinegun, delay),
+                               WEP_CVAR_SEC(okmachinegun, lifetime)
+                       );
+                       actor.(weaponentity).m_weapon = oldwep;
+                       weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(okmachinegun, animtime), w_ready);
+               }
+       }
+       else
+       {
+               if (fire & 1) // Primary attack
+               {
+                       if (!weapon_prepareattack(thiswep, actor, weaponentity, false, 0))
+                       {
+                               return;
+                       }
+                       actor.(weaponentity).misc_bulletcounter = 1;
+                       W_OverkillMachineGun_Attack(WEP_OVERKILL_MACHINEGUN, WEP_OVERKILL_MACHINEGUN.m_id, actor, weaponentity); // sets attack_finished
+                       weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(okmachinegun, sustained_refire), W_OverkillMachineGun_Attack_Frame);
+                       return;
+               }
+               if ((fire & 2) && (WEP_CVAR_SEC(okmachinegun, refire_type) == 0)) // Secondary attack
+               {
+                       if (!weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(okmachinegun, refire)))
+                       {
+                               return;
+                       }
+                       // ugly instagib hack to reuse the fire mode of the laser
+                       makevectors(actor.v_angle);
+                       Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+                       actor.(weaponentity).m_weapon = WEP_BLASTER;
+                       W_Blaster_Attack(
+                               actor,
+                               weaponentity,
+                               WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                               WEP_CVAR_SEC(okmachinegun, shotangle),
+                               WEP_CVAR_SEC(okmachinegun, damage),
+                               WEP_CVAR_SEC(okmachinegun, edgedamage),
+                               WEP_CVAR_SEC(okmachinegun, radius),
+                               WEP_CVAR_SEC(okmachinegun, force),
+                               WEP_CVAR_SEC(okmachinegun, speed),
+                               WEP_CVAR_SEC(okmachinegun, spread),
+                               WEP_CVAR_SEC(okmachinegun, delay),
+                               WEP_CVAR_SEC(okmachinegun, lifetime)
+                       );
+                       actor.(weaponentity).m_weapon = oldwep;
+                       weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(okmachinegun, animtime), w_ready);
+               }
+       }
+}
+
+METHOD(OverkillMachineGun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
+{
+       float ammo_amount;
+       if(WEP_CVAR(okmachinegun, mode) == 1)
+               ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(okmachinegun, sustained_ammo);
+       else
+               ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(okmachinegun, first_ammo);
+
+       if(WEP_CVAR(okmachinegun, reload_ammo))
+       {
+               if(WEP_CVAR(okmachinegun, mode) == 1)
+                       ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_MACHINEGUN.m_id]) >= WEP_CVAR(okmachinegun, sustained_ammo);
+               else
+                       ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_MACHINEGUN.m_id]) >= WEP_CVAR(okmachinegun, first_ammo);
+       }
+       return ammo_amount;
+}
+
+METHOD(OverkillMachineGun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
+{
+       float ammo_amount;
+       if(WEP_CVAR(okmachinegun, mode) == 1)
+               ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(okmachinegun, burst_ammo);
+       else
+               ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(okmachinegun, first_ammo);
+
+       if(WEP_CVAR(okmachinegun, reload_ammo))
+       {
+               if(WEP_CVAR(okmachinegun, mode) == 1)
+                       ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_MACHINEGUN.m_id]) >= WEP_CVAR(okmachinegun, burst_ammo);
+               else
+                       ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_MACHINEGUN.m_id]) >= WEP_CVAR(okmachinegun, first_ammo);
+       }
+       return ammo_amount;
+}
+
+METHOD(OverkillMachineGun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
+{
+       W_Reload(actor, weaponentity, min(max(WEP_CVAR(okmachinegun, sustained_ammo), WEP_CVAR(okmachinegun, first_ammo)), WEP_CVAR(okmachinegun, burst_ammo)), SND_RELOAD);
+}
+
+METHOD(OverkillMachineGun, wr_suicidemessage, Notification(entity thiswep))
+{
+       return WEAPON_THINKING_WITH_PORTALS;
+}
+
+METHOD(OverkillMachineGun, wr_killmessage, Notification(entity thiswep))
+{
+       if(w_deathtype & HITTYPE_SECONDARY)
+               return WEAPON_MACHINEGUN_MURDER_SNIPE;
+       else
+               return WEAPON_MACHINEGUN_MURDER_SPRAY;
+}
+
+#endif
+#ifdef CSQC
+
+METHOD(OverkillMachineGun, wr_impacteffect, void(entity thiswep, entity actor))
+{
+       vector org2;
+       org2 = w_org + w_backoff * 2;
+       pointparticles(EFFECT_MACHINEGUN_IMPACT, org2, w_backoff * 1000, 1);
+       if(!w_issilent)
+               sound(actor, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTN_NORM);
+}
+
+#endif
+
diff --git a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qh b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qh
new file mode 100644 (file)
index 0000000..aa76e79
--- /dev/null
@@ -0,0 +1,71 @@
+#pragma once
+
+CLASS(OverkillMachineGun, Weapon)
+/* ammotype  */ ATTRIB(OverkillMachineGun, ammo_field, .int, ammo_nails);
+/* impulse   */ ATTRIB(OverkillMachineGun, impulse, int, 3);
+/* flags        */ ATTRIB(OverkillMachineGun, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
+/* rating      */ ATTRIB(OverkillMachineGun, bot_pickupbasevalue, float, 7000);
+/* color        */ ATTRIB(OverkillMachineGun, wpcolor, vector, '1 1 0');
+/* modelname */ ATTRIB(OverkillMachineGun, mdl, string, "ok_mg");
+#ifdef GAMEQC
+/* model        */ ATTRIB(OverkillMachineGun, m_model, Model, MDL_OK_MG_ITEM);
+#endif
+/* crosshair */ ATTRIB(OverkillMachineGun, w_crosshair, string, "gfx/crosshairuzi");
+/* crosshair */ ATTRIB(OverkillMachineGun, w_crosshair_size, float, 0.6);
+/* wepimg      */ ATTRIB(OverkillMachineGun, model2, string, "weaponuzi");
+/* refname   */ ATTRIB(OverkillMachineGun, netname, string, "okmachinegun");
+/* wepname   */ ATTRIB(OverkillMachineGun, m_name, string, _("Overkill MachineGun"));
+
+#define X(BEGIN, P, END, class, prefix) \
+       BEGIN(class) \
+               P(class, prefix, burst, float, NONE) \
+               P(class, prefix, burst_ammo, float, NONE) \
+               P(class, prefix, burst_animtime, float, NONE) \
+               P(class, prefix, burst_refire2, float, NONE) \
+               P(class, prefix, burst_refire, float, NONE) \
+               P(class, prefix, burst_speed, float, NONE) \
+               P(class, prefix, first, float, NONE) \
+               P(class, prefix, first_ammo, float, NONE) \
+               P(class, prefix, first_damage, float, NONE) \
+               P(class, prefix, first_force, float, NONE) \
+               P(class, prefix, first_refire, float, NONE) \
+               P(class, prefix, first_spread, float, NONE) \
+               P(class, prefix, mode, float, NONE) \
+               P(class, prefix, reload_ammo, float, NONE) \
+               P(class, prefix, reload_time, float, NONE) \
+               P(class, prefix, solidpenetration, float, NONE) \
+               P(class, prefix, spread_add, float, NONE) \
+               P(class, prefix, spread_max, float, NONE) \
+               P(class, prefix, spread_min, float, NONE) \
+               P(class, prefix, sustained_ammo, float, NONE) \
+               P(class, prefix, sustained_damage, float, NONE) \
+               P(class, prefix, sustained_force, float, NONE) \
+               P(class, prefix, sustained_refire, float, NONE) \
+               P(class, prefix, sustained_spread, float, NONE) \
+               P(class, prefix, switchdelay_drop, float, NONE) \
+               P(class, prefix, switchdelay_raise, float, NONE) \
+               P(class, prefix, weaponreplace, string,NONE) \
+               P(class, prefix, weaponstartoverride, float, NONE) \
+               P(class, prefix, weaponstart, float, NONE) \
+               P(class, prefix, weaponthrowable, float, NONE) \
+               P(class, prefix, ammo, float, SEC) \
+               P(class, prefix, animtime, float, SEC) \
+               P(class, prefix, damage, float, SEC) \
+               P(class, prefix, delay, float, SEC) \
+               P(class, prefix, edgedamage, float, SEC) \
+               P(class, prefix, force, float, SEC) \
+               P(class, prefix, lifetime, float, SEC) \
+               P(class, prefix, radius, float, SEC) \
+               P(class, prefix, refire, float, SEC) \
+               P(class, prefix, refire_type, float, SEC) \
+               P(class, prefix, shotangle, float, SEC) \
+               P(class, prefix, speed, float, SEC) \
+               P(class, prefix, spread, float, SEC) \
+               P(class, prefix, type, float, SEC) \
+       END()
+       W_PROPS(X, OverkillMachineGun, okmachinegun)
+#undef X
+
+ENDCLASS(OverkillMachineGun)
+REGISTER_WEAPON(OVERKILL_MACHINEGUN, okmachinegun, NEW(OverkillMachineGun));
+
diff --git a/qcsrc/common/mutators/mutator/overkill/okshotgun.qc b/qcsrc/common/mutators/mutator/overkill/okshotgun.qc
new file mode 100644 (file)
index 0000000..788c9ce
--- /dev/null
@@ -0,0 +1,163 @@
+#include "okshotgun.qh"
+
+#ifdef SVQC
+spawnfunc(weapon_okshotgun) { weapon_defaultspawnfunc(this, WEP_OVERKILL_SHOTGUN); }
+
+METHOD(OverkillShotgun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
+{
+       if (vdist(actor.origin - actor.enemy.origin, >, WEP_CVAR_PRI(okshotgun, bot_range)))
+       {
+               PHYS_INPUT_BUTTON_ATCK2(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
+       }
+       else
+       {
+               PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
+       }
+}
+
+METHOD(OverkillShotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
+{
+       if ((WEP_CVAR_SEC(okshotgun, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
+       {
+               // Secondary uses it's own refire timer if refire_type is 1.
+               actor.jump_interval = time + WEP_CVAR_SEC(okshotgun, refire) * W_WeaponRateFactor(actor);
+               // Ugly hack to reuse the fire mode of the blaster.
+               makevectors(actor.v_angle);
+               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+               actor.(weaponentity).m_weapon = WEP_BLASTER;
+               W_Blaster_Attack(
+                       actor,
+                       weaponentity,
+                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                       WEP_CVAR_SEC(okshotgun, shotangle),
+                       WEP_CVAR_SEC(okshotgun, damage),
+                       WEP_CVAR_SEC(okshotgun, edgedamage),
+                       WEP_CVAR_SEC(okshotgun, radius),
+                       WEP_CVAR_SEC(okshotgun, force),
+                       WEP_CVAR_SEC(okshotgun, speed),
+                       WEP_CVAR_SEC(okshotgun, spread),
+                       WEP_CVAR_SEC(okshotgun, delay),
+                       WEP_CVAR_SEC(okshotgun, lifetime)
+               );
+               actor.(weaponentity).m_weapon = oldwep;
+               if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
+                       (actor.(weaponentity).wframe == WFRAME_FIRE2))
+               {
+                       // Set secondary fire animation.
+                       vector a = '0 0 0';
+                       actor.(weaponentity).wframe = WFRAME_FIRE2;
+                       a = actor.(weaponentity).anim_fire2;
+                       a.z *= g_weaponratefactor;
+                       FOREACH_CLIENT(true, LAMBDA(
+                               if (it == actor || (IS_SPEC(it) && it.enemy == actor))
+                               {
+                                       wframe_send(it, actor.(weaponentity), a, true);
+                               }
+                       ));
+                       animdecide_setaction(actor, ANIMACTION_SHOOT, true);
+               }
+       }
+       if (WEP_CVAR(okshotgun, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(okshotgun, ammo))
+       {
+               // Forced reload
+               thiswep.wr_reload(thiswep, actor, weaponentity);
+               return;
+       }
+       if (fire & 1) // Primary attack
+       {
+               if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(okshotgun, animtime)))
+               {
+                       return;
+               }
+               W_Shotgun_Attack(thiswep, actor, weaponentity, true,
+                       WEP_CVAR_PRI(okshotgun, ammo),
+                       WEP_CVAR_PRI(okshotgun, damage),
+                       WEP_CVAR_PRI(okshotgun, bullets),
+                       WEP_CVAR_PRI(okshotgun, spread),
+                       WEP_CVAR_PRI(okshotgun, solidpenetration),
+                       WEP_CVAR_PRI(okshotgun, force));
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(okshotgun, animtime), w_ready);
+               return;
+       }
+       if ((fire & 2) && (WEP_CVAR_SEC(okshotgun, refire_type) == 0)) // Secondary attack
+       {
+               if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(okshotgun, refire)))
+               {
+                       return;
+               }
+               // ugly instagib hack to reuse the fire mode of the laser
+               makevectors(actor.v_angle);
+               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+               actor.(weaponentity).m_weapon = WEP_BLASTER;
+               W_Blaster_Attack(
+                       actor,
+                       weaponentity,
+                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                       WEP_CVAR_SEC(okshotgun, shotangle),
+                       WEP_CVAR_SEC(okshotgun, damage),
+                       WEP_CVAR_SEC(okshotgun, edgedamage),
+                       WEP_CVAR_SEC(okshotgun, radius),
+                       WEP_CVAR_SEC(okshotgun, force),
+                       WEP_CVAR_SEC(okshotgun, speed),
+                       WEP_CVAR_SEC(okshotgun, spread),
+                       WEP_CVAR_SEC(okshotgun, delay),
+                       WEP_CVAR_SEC(okshotgun, lifetime)
+               );
+               actor.(weaponentity).m_weapon = oldwep;
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(okshotgun, animtime), w_ready);
+       }
+}
+
+METHOD(OverkillShotgun, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
+{
+       float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(okshotgun, ammo);
+       ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_SHOTGUN.m_id]) >= WEP_CVAR_PRI(okshotgun, ammo);
+       return ammo_amount;
+}
+
+METHOD(OverkillShotgun, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
+{
+       if (WEP_CVAR_SEC(okshotgun, ammo) == 0)
+       {
+               return true;
+       }
+       float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(okshotgun, ammo);
+       ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_SHOTGUN.m_id]) >= WEP_CVAR_SEC(okshotgun, ammo);
+       return ammo_amount;
+}
+
+METHOD(OverkillShotgun, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
+{
+       W_Reload(actor, weaponentity, WEP_CVAR_PRI(okshotgun, ammo), SND_RELOAD); // WEAPONTODO
+}
+
+METHOD(OverkillShotgun, wr_suicidemessage, Notification(entity thiswep))
+{
+       return WEAPON_THINKING_WITH_PORTALS;
+}
+
+METHOD(OverkillShotgun, wr_killmessage, Notification(entity thiswep))
+{
+       if(w_deathtype & HITTYPE_SECONDARY)
+               return WEAPON_BLASTER_MURDER;
+       else
+               return WEAPON_SHOTGUN_MURDER;
+}
+
+#endif
+#ifdef CSQC
+.float prevric;
+
+METHOD(OverkillShotgun, wr_impacteffect, void(entity thiswep, entity actor))
+{
+       vector org2 = w_org + w_backoff * 2;
+       pointparticles(EFFECT_SHOTGUN_IMPACT, org2, w_backoff * 1000, 1);
+       if(!w_issilent && time - actor.prevric > 0.25)
+       {
+               if(w_random < 0.05)
+                       sound(actor, CH_SHOTS, SND_RIC_RANDOM(), VOL_BASE, ATTEN_NORM);
+               actor.prevric = time;
+       }
+}
+
+#endif
diff --git a/qcsrc/common/mutators/mutator/overkill/okshotgun.qh b/qcsrc/common/mutators/mutator/overkill/okshotgun.qh
new file mode 100644 (file)
index 0000000..c4b6109
--- /dev/null
@@ -0,0 +1,56 @@
+#pragma once
+
+CLASS(OverkillShotgun, Weapon)
+/* ammotype  */ ATTRIB(OverkillShotgun, ammo_field, .int, ammo_shells);
+/* impulse   */ ATTRIB(OverkillShotgun, impulse, int, 2);
+/* flags     */ ATTRIB(OverkillShotgun, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
+/* rating    */ ATTRIB(OverkillShotgun, bot_pickupbasevalue, float, 6000);
+/* color     */ ATTRIB(OverkillShotgun, wpcolor, vector, '0.5 0.25 0');
+/* modelname */ ATTRIB(OverkillShotgun, mdl, string, "ok_shotgun");
+#ifdef GAMEQC
+/* model     */ ATTRIB(OverkillShotgun, m_model, Model, MDL_OK_SHOTGUN_ITEM);
+#endif
+/* crosshair */ ATTRIB(OverkillShotgun, w_crosshair, string, "gfx/crosshairshotgun");
+/* crosshair */ ATTRIB(OverkillShotgun, w_crosshair_size, float, 0.65);
+/* wepimg    */ ATTRIB(OverkillShotgun, model2, string, "weaponshotgun");
+/* refname   */ ATTRIB(OverkillShotgun, netname, string, "okshotgun");
+/* wepname   */ ATTRIB(OverkillShotgun, m_name, string, _("Overkill Shotgun"));
+
+#define X(BEGIN, P, END, class, prefix) \
+       BEGIN(class) \
+               P(class, prefix, ammo, float, PRI) \
+               P(class, prefix, animtime, float, PRI) \
+               P(class, prefix, bot_range, float, PRI) \
+               P(class, prefix, bullets, float, PRI) \
+               P(class, prefix, damage, float, PRI) \
+               P(class, prefix, force, float, PRI) \
+               P(class, prefix, refire, float, PRI) \
+               P(class, prefix, solidpenetration, float, PRI) \
+               P(class, prefix, spread, float, PRI) \
+               P(class, prefix, ammo, float, SEC) \
+               P(class, prefix, animtime, float, SEC) \
+               P(class, prefix, damage, float, SEC) \
+               P(class, prefix, delay, float, SEC) \
+               P(class, prefix, edgedamage, float, SEC) \
+               P(class, prefix, force, float, SEC) \
+               P(class, prefix, lifetime, float, SEC) \
+               P(class, prefix, radius, float, SEC) \
+               P(class, prefix, refire, float, SEC) \
+               P(class, prefix, refire_type, float, SEC) \
+               P(class, prefix, shotangle, float, SEC) \
+               P(class, prefix, speed, float, SEC) \
+               P(class, prefix, spread, float, SEC) \
+               P(class, prefix, reload_ammo, float, NONE) \
+               P(class, prefix, reload_time, float, NONE) \
+               P(class, prefix, switchdelay_drop, float, NONE) \
+               P(class, prefix, switchdelay_raise, float, NONE) \
+               P(class, prefix, weaponreplace, string,NONE) \
+               P(class, prefix, weaponstartoverride, float, NONE) \
+               P(class, prefix, weaponstart, float, NONE) \
+               P(class, prefix, weaponthrowable, float, NONE) \
+       END()
+       W_PROPS(X, OverkillShotgun, okshotgun)
+#undef X
+
+ENDCLASS(OverkillShotgun)
+REGISTER_WEAPON(OVERKILL_SHOTGUN, okshotgun, NEW(OverkillShotgun));
diff --git a/qcsrc/common/mutators/mutator/overkill/okvortex.qc b/qcsrc/common/mutators/mutator/overkill/okvortex.qc
new file mode 100644 (file)
index 0000000..0341cc9
--- /dev/null
@@ -0,0 +1,409 @@
+#include "okvortex.qh"
+
+#ifdef SVQC
+
+.float okvortex_lasthit;
+#endif
+
+#if defined(GAMEQC)
+
+METHOD(OverkillVortex, wr_glow, vector(OverkillVortex this, entity actor, entity wepent))
+{
+       if (!WEP_CVAR(okvortex, charge)) return '0 0 0';
+       float charge = wepent.okvortex_charge;
+       float animlimit = WEP_CVAR(okvortex, charge_animlimit);
+       vector g;
+       g.x = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_half * min(1, charge / animlimit);
+       g.y = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_half * min(1, charge / animlimit);
+       g.z = autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_half * min(1, charge / animlimit);
+       if (charge > animlimit)
+       {
+               g.x += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_red_full * (charge - animlimit) / (1 - animlimit);
+               g.y += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_green_full * (charge - animlimit) / (1 - animlimit);
+               g.z += autocvar_g_weapon_charge_colormod_hdrmultiplier * autocvar_g_weapon_charge_colormod_blue_full * (charge - animlimit) / (1 - animlimit);
+       }
+       return g;
+}
+#endif
+
+#ifdef SVQC
+spawnfunc(weapon_okvortex) { weapon_defaultspawnfunc(this, WEP_OVERKILL_VORTEX); }
+
+REGISTER_MUTATOR(okvortex_charge, true);
+
+MUTATOR_HOOKFUNCTION(okvortex_charge, GetPressedKeys)
+{
+       entity player = M_ARGV(0, entity);
+
+       // WEAPONTODO
+       if(!WEP_CVAR(okvortex, charge) || !WEP_CVAR(okvortex, charge_velocity_rate))
+               return;
+
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               .entity weaponentity = weaponentities[slot];
+
+               if (player.(weaponentity).m_weapon == WEP_OVERKILL_VORTEX && WEP_CVAR(okvortex, charge) && WEP_CVAR(okvortex, charge_velocity_rate) && vdist(vec2(player.velocity), >, WEP_CVAR(okvortex, charge_minspeed)))
+               {
+                       float xyspeed = vlen(vec2(player.velocity));
+                       // 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(okvortex, charge_maxspeed));
+                       float f = (xyspeed - WEP_CVAR(okvortex, charge_minspeed)) / (WEP_CVAR(okvortex, charge_maxspeed) - WEP_CVAR(okvortex, charge_minspeed));
+                       // add the extra charge
+                       player.(weaponentity).okvortex_charge = min(1, player.(weaponentity).okvortex_charge + WEP_CVAR(okvortex, charge_velocity_rate) * f * PHYS_INPUT_TIMELENGTH);
+               }
+       }
+}
+
+void W_OverkillVortex_Attack(Weapon thiswep, entity actor, .entity weaponentity, float issecondary)
+{
+       float mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, myammo, charge;
+
+       mydmg = WEP_CVAR_BOTH(okvortex, !issecondary, damage);
+       myforce = WEP_CVAR_BOTH(okvortex, !issecondary, force);
+       mymindist = WEP_CVAR_BOTH(okvortex, !issecondary, damagefalloff_mindist);
+       mymaxdist = WEP_CVAR_BOTH(okvortex, !issecondary, damagefalloff_maxdist);
+       myhalflife = WEP_CVAR_BOTH(okvortex, !issecondary, damagefalloff_halflife);
+       myforcehalflife = WEP_CVAR_BOTH(okvortex, !issecondary, damagefalloff_forcehalflife);
+       myammo = WEP_CVAR_BOTH(okvortex, !issecondary, ammo);
+
+       float flying;
+       flying = IsFlying(actor); // do this BEFORE to make the trace values from FireRailgunBullet last
+
+       if (WEP_CVAR(okvortex, charge))
+       {
+               charge = WEP_CVAR(okvortex, charge_mindmg) / mydmg + (1 - WEP_CVAR(okvortex, charge_mindmg) / mydmg) * actor.(weaponentity).okvortex_charge;
+               actor.(weaponentity).okvortex_charge *= WEP_CVAR(okvortex, charge_shot_multiplier); // do this AFTER setting mydmg/myforce
+               // O RLY? -- divVerent
+               // YA RLY -- FruitieX
+       }
+       else
+       {
+               charge = 1;
+       }
+       mydmg *= charge;
+       myforce *= charge;
+
+       W_SetupShot(actor, weaponentity, true, 5, SND_NEXFIRE, CH_WEAPON_A, mydmg);
+       if(charge > WEP_CVAR(okvortex, charge_animlimit) && WEP_CVAR(okvortex, charge_animlimit)) // if the OverkillVortex is overcharged, we play an extra sound
+       {
+               sound(actor, CH_WEAPON_B, SND_NEXCHARGE, VOL_BASE * (charge - 0.5 * WEP_CVAR(okvortex, charge_animlimit)) / (1 - 0.5 * WEP_CVAR(okvortex, charge_animlimit)), ATTN_NORM);
+       }
+
+       yoda = 0;
+       damage_goodhits = 0;
+       FireRailgunBullet(actor, weaponentity, w_shotorg, w_shotorg + w_shotdir * max_shot_distance, mydmg, myforce, mymindist, mymaxdist, myhalflife, myforcehalflife, WEP_OVERKILL_VORTEX.m_id);
+
+       if(yoda && flying)
+               Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_YODA);
+       if(damage_goodhits && actor.okvortex_lasthit)
+       {
+               Send_Notification(NOTIF_ONE, actor, MSG_ANNCE, ANNCE_ACHIEVEMENT_IMPRESSIVE);
+               damage_goodhits = 0; // only every second time
+       }
+
+       actor.okvortex_lasthit = damage_goodhits;
+
+       //beam and muzzle flash done on client
+       SendCSQCVortexBeamParticle(charge);
+
+       W_DecreaseAmmo(thiswep, actor, myammo, weaponentity);
+}
+
+.float okvortex_chargepool_pauseregen_finished;
+
+METHOD(OverkillVortex, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
+{
+       if(bot_aim(actor, weaponentity, 1000000, 0, 1, false))
+               PHYS_INPUT_BUTTON_ATCK(actor) = true;
+       else
+       {
+               if(WEP_CVAR(okvortex, charge))
+                       PHYS_INPUT_BUTTON_ATCK2(actor) = true;
+       }
+}
+
+METHOD(OverkillVortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
+{
+       if (WEP_CVAR(okvortex, charge) && actor.(weaponentity).okvortex_charge < WEP_CVAR(okvortex, charge_limit))
+       {
+               actor.(weaponentity).okvortex_charge = min(1, actor.(weaponentity).okvortex_charge + WEP_CVAR(okvortex, charge_rate) * frametime / W_TICSPERFRAME);
+       }
+
+       if (weaponslot(weaponentity) == 0)
+       {
+               actor.okvortex_charge = actor.(weaponentity).okvortex_charge;
+       }
+
+       if (WEP_CVAR_SEC(okvortex, chargepool))
+               if (actor.(weaponentity).okvortex_chargepool_ammo < 1)
+               {
+                       if (actor.okvortex_chargepool_pauseregen_finished < time)
+                               actor.(weaponentity).okvortex_chargepool_ammo = min(1, actor.(weaponentity).okvortex_chargepool_ammo + WEP_CVAR_SEC(okvortex, chargepool_regen) * frametime / W_TICSPERFRAME);
+                       actor.pauseregen_finished = max(actor.pauseregen_finished, time + WEP_CVAR_SEC(okvortex, chargepool_pause_regen));
+               }
+
+       if(weaponslot(weaponentity) == 0)
+               actor.okvortex_chargepool_ammo = actor.(weaponentity).okvortex_chargepool_ammo;
+
+       if ((WEP_CVAR_SEC(okvortex, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
+       {
+               // Secondary uses it's own refire timer if refire_type is 1.
+               actor.jump_interval = time + WEP_CVAR_SEC(okvortex, refire) * W_WeaponRateFactor(actor);
+               // Ugly hack to reuse the fire mode of the blaster.
+               makevectors(actor.v_angle);
+               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+               actor.(weaponentity).m_weapon = WEP_BLASTER;
+               W_Blaster_Attack(
+                       actor,
+                       weaponentity,
+                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                       WEP_CVAR_SEC(okvortex, shotangle),
+                       WEP_CVAR_SEC(okvortex, damage),
+                       WEP_CVAR_SEC(okvortex, edgedamage),
+                       WEP_CVAR_SEC(okvortex, radius),
+                       WEP_CVAR_SEC(okvortex, force),
+                       WEP_CVAR_SEC(okvortex, speed),
+                       WEP_CVAR_SEC(okvortex, spread),
+                       WEP_CVAR_SEC(okvortex, delay),
+                       WEP_CVAR_SEC(okvortex, lifetime)
+               );
+               actor.(weaponentity).m_weapon = oldwep;
+               if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
+                       (actor.(weaponentity).wframe == WFRAME_FIRE2))
+               {
+                       // Set secondary fire animation.
+                       vector a = '0 0 0';
+                       actor.(weaponentity).wframe = WFRAME_FIRE2;
+                       a = actor.(weaponentity).anim_fire2;
+                       a.z *= g_weaponratefactor;
+                       FOREACH_CLIENT(true, LAMBDA(
+                               if (it == actor || (IS_SPEC(it) && it.enemy == actor))
+                               {
+                                       wframe_send(it, actor.(weaponentity), a, true);
+                               }
+                       ));
+                       animdecide_setaction(actor, ANIMACTION_SHOOT, true);
+               }
+       }
+
+       if (autocvar_g_balance_okvortex_reload_ammo && actor.(weaponentity).clip_load < WEP_CVAR_PRI(okvortex, ammo))
+       {
+               // Rorced reload
+               thiswep.wr_reload(thiswep, actor, weaponentity);
+               return;
+       }
+       if (fire & 1) // Primary attack
+       {
+               if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(okvortex, refire)))
+               {
+                       return;
+               }
+               W_OverkillVortex_Attack(thiswep, actor, weaponentity, 0);
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(okvortex, animtime), w_ready);
+               return;
+       }
+       if ((fire & 2) && (WEP_CVAR(okvortex, secondary) == 2) && (WEP_CVAR_SEC(okvortex, refire_type) == 0))
+       {
+               // Secondary attack
+               if (!weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR_SEC(okshotgun, refire)))
+               {
+                       return;
+               }
+               // ugly instagib hack to reuse the fire mode of the laser
+               makevectors(actor.v_angle);
+               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+               actor.(weaponentity).m_weapon = WEP_BLASTER;
+               W_Blaster_Attack(
+                       actor,
+                       weaponentity,
+                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                       WEP_CVAR_SEC(okvortex, shotangle),
+                       WEP_CVAR_SEC(okvortex, damage),
+                       WEP_CVAR_SEC(okvortex, edgedamage),
+                       WEP_CVAR_SEC(okvortex, radius),
+                       WEP_CVAR_SEC(okvortex, force),
+                       WEP_CVAR_SEC(okvortex, speed),
+                       WEP_CVAR_SEC(okvortex, spread),
+                       WEP_CVAR_SEC(okvortex, delay),
+                       WEP_CVAR_SEC(okvortex, lifetime)
+               );
+               actor.(weaponentity).m_weapon = oldwep;
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(okvortex, animtime), w_ready);
+               return;
+       }
+       //if ((WEP_CVAR(okvortex, charge) && (WEP_CVAR(okvortex, secondary) == 1)) ? (PHYS_INPUT_BUTTON_ZOOM(actor) | PHYS_INPUT_BUTTON_ZOOMSCRIPT(actor)) : (fire & 2))
+       //{
+       //      if(WEP_CVAR(okvortex, charge))
+       //      {
+       //              actor.(weaponentity).okvortex_charge_rottime = time + WEP_CVAR(okvortex, charge_rot_pause);
+       //              float dt = frametime / W_TICSPERFRAME;
+       //
+       //              if(actor.(weaponentity).okvortex_charge < 1)
+       //              {
+       //                      if(WEP_CVAR_SEC(okvortex, chargepool))
+       //                      {
+       //                              if(WEP_CVAR_SEC(okvortex, ammo))
+       //                              {
+       //                                      // always deplete if secondary is held
+       //                                      actor.okvortex_chargepool_ammo = max(0, actor.okvortex_chargepool_ammo - WEP_CVAR_SEC(okvortex, ammo) * dt);
+
+       //                                      dt = min(dt, (1 - actor.(weaponentity).okvortex_charge) / WEP_CVAR(okvortex, charge_rate));
+       //                                      actor.okvortex_chargepool_pauseregen_finished = time + WEP_CVAR_SEC(okvortex, chargepool_pause_regen);
+       //                                      dt = min(dt, actor.okvortex_chargepool_ammo);
+       //                                      dt = max(0, dt);
+
+       //                                      actor.(weaponentity).okvortex_charge += dt * WEP_CVAR(okvortex, charge_rate);
+       //                              }
+       //                      }
+
+       //                      else if(WEP_CVAR_SEC(okvortex, ammo))
+       //                      {
+       //                              if(fire & 2) // only eat ammo when the button is pressed
+       //                              {
+       //                                      dt = min(dt, (1 - actor.(weaponentity).okvortex_charge) / WEP_CVAR(okvortex, charge_rate));
+       //                                      if(!(actor.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, (actor.(weaponentity).clip_load - WEP_CVAR_PRI(okvortex, ammo)) / WEP_CVAR_SEC(okvortex, ammo));
+       //                                                      dt = max(0, dt);
+       //                                                      if(dt > 0)
+       //                                                      {
+       //                                                              actor.(weaponentity).clip_load = max(WEP_CVAR_SEC(okvortex, ammo), actor.(weaponentity).clip_load - WEP_CVAR_SEC(okvortex, ammo) * dt);
+       //                                                      }
+       //                                                      actor.(weaponentity).(weapon_load[WEP_OVERKILL_VORTEX.m_id]) = actor.(weaponentity).clip_load;
+       //                                              }
+       //                                              else
+       //                                              {
+       //                                                      dt = min(dt, (actor.(thiswep.ammo_field) - WEP_CVAR_PRI(okvortex, ammo)) / WEP_CVAR_SEC(okvortex, ammo));
+       //                                                      dt = max(0, dt);
+       //                                                      if(dt > 0)
+       //                                                      {
+       //                                                              actor.(thiswep.ammo_field) = max(WEP_CVAR_SEC(okvortex, ammo), actor.(thiswep.ammo_field) - WEP_CVAR_SEC(okvortex, ammo) * dt);
+       //                                                      }
+       //                                              }
+       //                                      }
+       //                                      actor.(weaponentity).okvortex_charge += dt * WEP_CVAR(okvortex, charge_rate);
+       //                              }
+       //                      }
+
+       //                      else
+       //                      {
+       //                              dt = min(dt, (1 - actor.(weaponentity).okvortex_charge) / WEP_CVAR(okvortex, charge_rate));
+       //                              actor.(weaponentity).okvortex_charge += dt * WEP_CVAR(okvortex, charge_rate);
+       //                      }
+       //              }
+       //      }
+       //      else if(WEP_CVAR(okvortex, secondary))
+       //      {
+       //              if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(okvortex, refire)))
+       //              {
+       //                      W_OverkillVortex_Attack(thiswep, actor, weaponentity, 1);
+       //                      weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(okvortex, animtime), w_ready);
+       //              }
+       //      }
+       //}
+}
+
+METHOD(OverkillVortex, wr_setup, void(entity thiswep, entity actor, .entity weaponentity))
+{
+       actor.okvortex_lasthit = 0;
+}
+
+METHOD(OverkillVortex, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
+{
+       float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(okvortex, ammo);
+       ammo_amount += (autocvar_g_balance_okvortex_reload_ammo && actor.(weaponentity).(weapon_load[WEP_OVERKILL_VORTEX.m_id]) >= WEP_CVAR_PRI(okvortex, ammo));
+       return ammo_amount;
+}
+
+METHOD(OverkillVortex, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
+{
+       if(WEP_CVAR(okvortex, secondary))
+       {
+               // don't allow charging if we don't have enough ammo
+               float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(okvortex, ammo);
+               ammo_amount += actor.(weaponentity).(weapon_load[WEP_OVERKILL_VORTEX.m_id]) >= WEP_CVAR_SEC(okvortex, ammo);
+               return ammo_amount;
+       }
+       else
+       {
+               return false; // zoom is not a fire mode
+       }
+}
+
+METHOD(OverkillVortex, wr_resetplayer, void(entity thiswep, entity actor))
+{
+       if (WEP_CVAR(okvortex, charge)) {
+               if (WEP_CVAR_SEC(okvortex, chargepool)) {
+                       actor.okvortex_chargepool_ammo = 1;
+               }
+               actor.okvortex_charge = WEP_CVAR(okvortex, charge_start);
+               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+               {
+                       .entity weaponentity = weaponentities[slot];
+                       actor.(weaponentity).okvortex_charge = WEP_CVAR(okvortex, charge_start);
+
+                       if (WEP_CVAR_SEC(okvortex, chargepool))
+                               actor.(weaponentity).okvortex_chargepool_ammo = 1;
+               }
+       }
+       actor.okvortex_lasthit = 0;
+}
+
+METHOD(OverkillVortex, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
+{
+       W_Reload(actor, weaponentity, WEP_CVAR_PRI(okvortex, ammo), SND_RELOAD);
+}
+
+METHOD(OverkillVortex, wr_suicidemessage, Notification(entity thiswep))
+{
+       return WEAPON_THINKING_WITH_PORTALS;
+}
+
+METHOD(OverkillVortex, wr_killmessage, Notification(entity thiswep))
+{
+       return WEAPON_VORTEX_MURDER;
+}
+
+METHOD(OverkillVortex, wr_zoom, bool(entity thiswep, entity actor))
+{
+       return PHYS_INPUT_BUTTON_ATCK2(actor) && !WEP_CVAR(okvortex, secondary);
+}
+
+#endif
+#ifdef CSQC
+
+METHOD(OverkillVortex, wr_impacteffect, void(entity thiswep, entity actor))
+{
+       entity this = actor;
+       vector org2 = w_org + w_backoff * 6;
+       pointparticles(EFFECT_VORTEX_IMPACT, org2, '0 0 0', 1);
+       if(!w_issilent)
+               sound(this, CH_SHOTS, SND_NEXIMPACT, VOL_BASE, ATTN_NORM);
+}
+
+METHOD(OverkillVortex, wr_init, void(entity thiswep))
+{
+       if(autocvar_cl_reticle && autocvar_cl_reticle_weapon)
+       {
+               precache_pic("gfx/reticle_nex");
+       }
+}
+
+METHOD(OverkillVortex, wr_zoom, bool(entity thiswep, entity actor))
+{
+       if(button_zoom || zoomscript_caught || (!WEP_CVAR(okvortex, secondary) && button_attack2))
+       {
+               return true;
+       }
+       else
+       {
+               // no weapon specific image for this weapon
+               return false;
+       }
+}
+
+#endif
diff --git a/qcsrc/common/mutators/mutator/overkill/okvortex.qh b/qcsrc/common/mutators/mutator/overkill/okvortex.qh
new file mode 100644 (file)
index 0000000..2a3137a
--- /dev/null
@@ -0,0 +1,74 @@
+#pragma once
+
+CLASS(OverkillVortex, Weapon)
+/* ammotype  */ ATTRIB(OverkillVortex, ammo_field, .int, ammo_cells);
+/* impulse   */ ATTRIB(OverkillVortex, impulse, int, 7);
+/* flags     */ ATTRIB(OverkillVortex, spawnflags, int, WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN);
+/* rating    */ ATTRIB(OverkillVortex, bot_pickupbasevalue, float, 8000);
+/* color     */ ATTRIB(OverkillVortex, wpcolor, vector, '0.5 1 1');
+/* modelname */ ATTRIB(OverkillVortex, mdl, string, "ok_sniper");
+#ifdef GAMEQC
+/* model     */ ATTRIB(OverkillVortex, m_model, Model, MDL_OK_SNIPER_ITEM);
+#endif
+/* crosshair */ ATTRIB(OverkillVortex, w_crosshair, string, "gfx/crosshairnex");
+/* crosshair */ ATTRIB(OverkillVortex, w_crosshair_size, float, 0.65);
+/* reticle   */ ATTRIB(OverkillVortex, w_reticle, string, "gfx/reticle_nex");
+/* wepimg    */ ATTRIB(OverkillVortex, model2, string, "weaponnex");
+/* refname   */ ATTRIB(OverkillVortex, netname, string, "okvortex");
+/* wepname   */ ATTRIB(OverkillVortex, m_name, string, _("Overkill Vortex"));
+
+#define X(BEGIN, P, END, class, prefix) \
+       BEGIN(class) \
+               P(class, prefix, ammo, float, PRI) \
+               P(class, prefix, animtime, float, PRI) \
+               P(class, prefix, chargepool, float, SEC) \
+               P(class, prefix, chargepool_pause_regen, float, SEC) \
+               P(class, prefix, chargepool_regen, float, SEC) \
+               P(class, prefix, charge, float, NONE) \
+               P(class, prefix, charge_animlimit, float, NONE) \
+               P(class, prefix, charge_limit, float, NONE) \
+               P(class, prefix, charge_maxspeed, float, NONE) \
+               P(class, prefix, charge_mindmg, float, NONE) \
+               P(class, prefix, charge_minspeed, float, NONE) \
+               P(class, prefix, charge_rate, float, NONE) \
+               P(class, prefix, charge_rot_pause, float, NONE) \
+               P(class, prefix, charge_rot_rate, float, NONE) \
+               P(class, prefix, charge_shot_multiplier, float, NONE) \
+               P(class, prefix, charge_start, float, NONE) \
+               P(class, prefix, charge_velocity_rate, float, NONE) \
+               P(class, prefix, damagefalloff_forcehalflife, float, BOTH) \
+               P(class, prefix, damagefalloff_halflife, float, BOTH) \
+               P(class, prefix, damagefalloff_maxdist, float, BOTH) \
+               P(class, prefix, damagefalloff_mindist, float, BOTH) \
+               P(class, prefix, damage, float, PRI) \
+               P(class, prefix, force, float, PRI) \
+               P(class, prefix, refire, float, PRI) \
+               P(class, prefix, secondary, float, NONE) \
+               P(class, prefix, reload_ammo, float, NONE) \
+        P(class, prefix, reload_time, float, NONE) \
+        P(class, prefix, switchdelay_raise, float, NONE) \
+        P(class, prefix, switchdelay_drop, float, NONE) \
+        P(class, prefix, weaponreplace, string, NONE) \
+        P(class, prefix, weaponstart, float, NONE) \
+        P(class, prefix, weaponstartoverride, float, NONE) \
+        P(class, prefix, weaponthrowable, float, NONE) \
+               P(class, prefix, ammo, float, SEC) \
+               P(class, prefix, animtime, float, SEC) \
+               P(class, prefix, damage, float, SEC) \
+               P(class, prefix, delay, float, SEC) \
+               P(class, prefix, edgedamage, float, SEC) \
+               P(class, prefix, force, float, SEC) \
+               P(class, prefix, lifetime, float, SEC) \
+               P(class, prefix, radius, float, SEC) \
+               P(class, prefix, refire, float, SEC) \
+               P(class, prefix, refire_type, float, SEC) \
+               P(class, prefix, shotangle, float, SEC) \
+               P(class, prefix, speed, float, SEC) \
+               P(class, prefix, spread, float, SEC) \
+       END()
+    W_PROPS(X, OverkillVortex, okvortex)
+#undef X
+
+ENDCLASS(OverkillVortex)
+REGISTER_WEAPON(OVERKILL_VORTEX, okvortex, NEW(OverkillVortex));
+
index e9a5ce2..536435d 100644 (file)
@@ -8,7 +8,7 @@ void W_RocketPropelledChainsaw_Explode(entity this, entity directhitentity)
        this.event_damage = func_null;
        this.takedamage = DAMAGE_NO;
 
-       RadiusDamage (this, this.realowner, WEP_CVAR(rpc, damage), WEP_CVAR(rpc, edgedamage), WEP_CVAR(rpc, radius), NULL, NULL, WEP_CVAR(rpc, force), this.projectiledeathtype, directhitentity);
+       RadiusDamage (this, this.realowner, WEP_CVAR_PRI(rpc, damage), WEP_CVAR_PRI(rpc, edgedamage), WEP_CVAR_PRI(rpc, radius), NULL, NULL, WEP_CVAR_PRI(rpc, force), this.projectiledeathtype, directhitentity);
 
        delete(this);
 }
@@ -55,9 +55,9 @@ void W_RocketPropelledChainsaw_Think(entity this)
 
        tracebox(this.origin, this.mins, this.maxs, this.origin + this.pos1 * (2 * this.wait), MOVE_NORMAL, this);
        if(IS_PLAYER(trace_ent))
-               Damage (trace_ent, this, this.realowner, WEP_CVAR(rpc, damage2), this.projectiledeathtype, this.origin, normalize(this.origin - trace_ent.origin) * WEP_CVAR(rpc, force));
+               Damage (trace_ent, this, this.realowner, WEP_CVAR_PRI(rpc, damage2), this.projectiledeathtype, this.origin, normalize(this.origin - other.origin) * WEP_CVAR_PRI(rpc, force));
 
-       this.velocity = this.pos1 * (this.cnt + (WEP_CVAR(rpc, speedaccel) * sys_frametime));
+       this.velocity = this.pos1 * (this.cnt + (WEP_CVAR_PRI(rpc, speedaccel) * sys_frametime));
 
        UpdateCSQCProjectile(this);
        this.nextthink = time;
@@ -68,18 +68,18 @@ void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .entity wea
        entity missile = spawn(); //WarpZone_RefSys_SpawnSameRefSys(actor);
        entity flash = spawn ();
 
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR(rpc, ammo), weaponentity);
-       W_SetupShot_ProjectileSize (actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR(rpc, damage));
+       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(rpc, ammo), weaponentity);
+       W_SetupShot_ProjectileSize (actor, weaponentity, '-3 -3 -3', '3 3 3', false, 5, SND_ROCKET_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(rpc, damage));
        Send_Effect(EFFECT_ROCKET_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
        PROJECTILE_MAKETRIGGER(missile);
 
        missile.owner = missile.realowner = actor;
        missile.bot_dodge = true;
-       missile.bot_dodgerating = WEP_CVAR(rpc, damage) * 2;
+       missile.bot_dodgerating = WEP_CVAR_PRI(rpc, damage) * 2;
 
        missile.takedamage = DAMAGE_YES;
-       missile.damageforcescale = WEP_CVAR(rpc, damageforcescale);
-       missile.health = WEP_CVAR(rpc, health);
+       missile.damageforcescale = WEP_CVAR_PRI(rpc, damageforcescale);
+       missile.health = WEP_CVAR_PRI(rpc, health);
        missile.event_damage = W_RocketPropelledChainsaw_Damage;
        missile.damagedbycontents = true;
        IL_PUSH(g_damagedbycontents, missile);
@@ -89,12 +89,12 @@ void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .entity wea
        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(rpc, speed), 0);
+       W_SetupProjVelocity_Basic(missile, WEP_CVAR_PRI(rpc, speed), 0);
 
        settouch(missile, W_RocketPropelledChainsaw_Touch);
 
        setthink(missile, W_RocketPropelledChainsaw_Think);
-       missile.cnt = time + WEP_CVAR(rpc, lifetime);
+       missile.cnt = time + WEP_CVAR_PRI(rpc, lifetime);
        missile.nextthink = time;
        missile.flags = FL_PROJECTILE;
        IL_PUSH(g_projectiles, missile);
@@ -113,46 +113,113 @@ void W_RocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .entity wea
 
 METHOD(RocketPropelledChainsaw, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR(rpc, speed), 0, WEP_CVAR(rpc, lifetime), false);
+    PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, WEP_CVAR_PRI(rpc, speed), 0, WEP_CVAR_PRI(rpc, lifetime), false);
 }
 
 METHOD(RocketPropelledChainsaw, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    if(WEP_CVAR(rpc, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR(rpc, ammo)) {
-        thiswep.wr_reload(thiswep, actor, weaponentity);
-    } else
-    {
-        if (fire & 1)
-        {
-            if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(rpc, refire)))
-            {
-                W_RocketPropelledChainsaw_Attack(thiswep, actor, weaponentity);
-                weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(rpc, animtime), w_ready);
-            }
-        }
-
-        if (fire & 2)
-        {
-            // to-do
-        }
-    }
+       if ((WEP_CVAR_SEC(rpc, refire_type) == 1) && (fire & 2) && (time >= actor.jump_interval))
+       {
+               // Secondary uses it's own refire timer if refire_type is 1.
+               actor.jump_interval = time + WEP_CVAR_SEC(rpc, refire) * W_WeaponRateFactor(actor);
+               // Ugly hack to reuse the fire mode of the blaster.
+               makevectors(actor.v_angle);
+               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+               actor.(weaponentity).m_weapon = WEP_BLASTER;
+               W_Blaster_Attack(
+                       actor,
+                       weaponentity,
+                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                       WEP_CVAR_SEC(rpc, shotangle),
+                       WEP_CVAR_SEC(rpc, damage),
+                       WEP_CVAR_SEC(rpc, edgedamage),
+                       WEP_CVAR_SEC(rpc, radius),
+                       WEP_CVAR_SEC(rpc, force),
+                       WEP_CVAR_SEC(rpc, speed),
+                       WEP_CVAR_SEC(rpc, spread),
+                       WEP_CVAR_SEC(rpc, delay),
+                       WEP_CVAR_SEC(rpc, lifetime)
+               );
+               actor.(weaponentity).m_weapon = oldwep;
+               if ((actor.(weaponentity).wframe == WFRAME_IDLE) ||
+                       (actor.(weaponentity).wframe == WFRAME_FIRE2))
+               {
+                       // Set secondary fire animation.
+                       vector a = '0 0 0';
+                       actor.(weaponentity).wframe = WFRAME_FIRE2;
+                       a = actor.(weaponentity).anim_fire2;
+                       a.z *= g_weaponratefactor;
+                       FOREACH_CLIENT(true, LAMBDA(
+                               if (it == actor || (IS_SPEC(it) && it.enemy == actor))
+                               {
+                                       wframe_send(it, actor.(weaponentity), a, true);
+                               }
+                       ));
+                       animdecide_setaction(actor, ANIMACTION_SHOOT, true);
+               }
+       }
+       if (WEP_CVAR(rpc, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(rpc, ammo))
+       {
+               // Forced reload
+               thiswep.wr_reload(thiswep, actor, weaponentity);
+               return;
+       }
+       if (fire & 1) // Primary attack
+       {
+               if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(rpc, refire)))
+               {
+                       return;
+               }
+               W_RocketPropelledChainsaw_Attack(thiswep, actor, weaponentity);
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(rpc, animtime), w_ready);
+               return;
+       }
+       if ((fire & 2) && (WEP_CVAR_SEC(rpc, refire_type) == 0)) // Secondary attack
+       {
+               if (!weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(rpc, refire)))
+               {
+                       return;
+               }
+               // ugly instagib hack to reuse the fire mode of the laser
+               makevectors(actor.v_angle);
+               Weapon oldwep = actor.(weaponentity).m_weapon; // we can't avoid this hack
+               actor.(weaponentity).m_weapon = WEP_BLASTER;
+               W_Blaster_Attack(
+                       actor,
+                       weaponentity,
+                       WEP_BLASTER.m_id | HITTYPE_SECONDARY,
+                       WEP_CVAR_SEC(rpc, shotangle),
+                       WEP_CVAR_SEC(rpc, damage),
+                       WEP_CVAR_SEC(rpc, edgedamage),
+                       WEP_CVAR_SEC(rpc, radius),
+                       WEP_CVAR_SEC(rpc, force),
+                       WEP_CVAR_SEC(rpc, speed),
+                       WEP_CVAR_SEC(rpc, spread),
+                       WEP_CVAR_SEC(rpc, delay),
+                       WEP_CVAR_SEC(rpc, lifetime)
+               );
+               actor.(weaponentity).m_weapon = oldwep;
+               weapon_thinkf(actor, weaponentity, WFRAME_FIRE2, WEP_CVAR_SEC(rpc, animtime), w_ready);
+       }
 }
 
 METHOD(RocketPropelledChainsaw, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
-    float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR(rpc, ammo);
-    ammo_amount += actor.(weaponentity).(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR(rpc, ammo);
+    float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_PRI(rpc, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR_PRI(rpc, ammo);
     return ammo_amount;
 }
 
 METHOD(RocketPropelledChainsaw, wr_checkammo2, bool(entity thiswep, entity actor, .entity weaponentity))
 {
-    return false;
+    float ammo_amount = actor.(thiswep.ammo_field) >= WEP_CVAR_SEC(rpc, ammo);
+    ammo_amount += actor.(weaponentity).(weapon_load[WEP_RPC.m_id]) >= WEP_CVAR_SEC(rpc, ammo);
+    return ammo_amount;
 }
 
 METHOD(RocketPropelledChainsaw, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    W_Reload(actor, weaponentity, WEP_CVAR(rpc, ammo), SND_RELOAD);
+    W_Reload(actor, weaponentity, WEP_CVAR_PRI(rpc, ammo), SND_RELOAD);
 }
 
 METHOD(RocketPropelledChainsaw, wr_suicidemessage, Notification(entity thiswep))
index 417e9a6..512f51a 100644 (file)
@@ -18,21 +18,34 @@ CLASS(RocketPropelledChainsaw, Weapon)
 
 #define X(BEGIN, P, END, class, prefix) \
        BEGIN(class) \
-               P(class, prefix, ammo, float, NONE) \
-               P(class, prefix, animtime, float, NONE) \
-               P(class, prefix, damage2, float, NONE) \
-               P(class, prefix, damageforcescale, float, NONE) \
-               P(class, prefix, damage, float, NONE) \
-               P(class, prefix, edgedamage, float, NONE) \
-               P(class, prefix, force, float, NONE) \
-               P(class, prefix, health, float, NONE) \
-               P(class, prefix, lifetime, float, NONE) \
-               P(class, prefix, radius, float, NONE) \
-               P(class, prefix, refire, float, NONE) \
+               P(class, prefix, ammo, float, PRI) \
+               P(class, prefix, animtime, float, PRI) \
+               P(class, prefix, damage, float, PRI) \
+               P(class, prefix, damage2, float, PRI) \
+               P(class, prefix, damageforcescale, float, PRI) \
+               P(class, prefix, edgedamage, float, PRI) \
+               P(class, prefix, force, float, PRI) \
+               P(class, prefix, health, float, PRI) \
+               P(class, prefix, lifetime, float, PRI) \
+               P(class, prefix, radius, float, PRI) \
+               P(class, prefix, refire, float, PRI) \
+               P(class, prefix, speedaccel, float, PRI) \
+               P(class, prefix, speed, float, PRI) \
+               P(class, prefix, ammo, float, SEC) \
+               P(class, prefix, animtime, float, SEC) \
+               P(class, prefix, damage, float, SEC) \
+               P(class, prefix, delay, float, SEC) \
+               P(class, prefix, edgedamage, float, SEC) \
+               P(class, prefix, force, float, SEC) \
+               P(class, prefix, lifetime, float, SEC) \
+               P(class, prefix, radius, float, SEC) \
+               P(class, prefix, refire, float, SEC) \
+               P(class, prefix, refire_type, float, SEC) \
+               P(class, prefix, shotangle, float, SEC) \
+               P(class, prefix, speed, float, SEC) \
+               P(class, prefix, spread, float, SEC) \
                P(class, prefix, reload_ammo, float, NONE) \
         P(class, prefix, reload_time, float, NONE) \
-               P(class, prefix, speedaccel, float, NONE) \
-               P(class, prefix, speed, float, NONE) \
         P(class, prefix, switchdelay_drop, float, NONE) \
         P(class, prefix, switchdelay_raise, float, NONE) \
         P(class, prefix, weaponreplace, string, NONE) \
index d2a7308..0c698e6 100644 (file)
@@ -110,53 +110,6 @@ MUTATOR_HOOKFUNCTION(ok, ForbidThrowCurrentWeapon)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ok, PlayerPreThink)
-{
-       if(game_stopped)
-               return;
-
-       entity player = M_ARGV(0, entity);
-
-       if(IS_DEAD(player) || !IS_PLAYER(player) || STAT(FROZEN, player))
-               return;
-
-       if(PHYS_INPUT_BUTTON_ATCK2(player) && time >= player.jump_interval)
-       if( !forbidWeaponUse(player)
-               || (round_handler_IsActive() && !round_handler_IsRoundStarted()) )
-       {
-               player.jump_interval = time + WEP_CVAR_PRI(blaster, refire) * W_WeaponRateFactor(player);
-               makevectors(player.v_angle);
-
-               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-               {
-                       .entity weaponentity = weaponentities[slot];
-
-                       if(player.(weaponentity).m_weapon == WEP_Null && slot != 0)
-                               continue;
-
-                       Weapon oldwep = player.(weaponentity).m_weapon;
-                       player.(weaponentity).m_weapon = WEP_BLASTER;
-                       W_Blaster_Attack(
-                               player,
-                               weaponentity,
-                               WEP_BLASTER.m_id | 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)
-                       );
-                       player.(weaponentity).m_weapon = oldwep;
-               }
-       }
-
-       PHYS_INPUT_BUTTON_ATCK2(player) = false;
-}
-
 MUTATOR_HOOKFUNCTION(ok, PlayerWeaponSelect)
 {
        entity player = M_ARGV(0, entity);
@@ -272,7 +225,7 @@ MUTATOR_HOOKFUNCTION(ok, FilterItem)
 
 MUTATOR_HOOKFUNCTION(ok, SetStartItems, CBC_ORDER_LAST)
 {
-       WepSet ok_start_items = (WEPSET(MACHINEGUN) | WEPSET(VORTEX) | WEPSET(SHOTGUN));
+       WepSet ok_start_items = (WEPSET(OVERKILL_MACHINEGUN) | WEPSET(OVERKILL_VORTEX) | WEPSET(OVERKILL_SHOTGUN));
 
        if(WEP_RPC.weaponstart > 0) { ok_start_items |= WEPSET(RPC); }
        if(WEP_HMG.weaponstart > 0) { ok_start_items |= WEPSET(HMG); }
@@ -310,7 +263,7 @@ void ok_Initialize()
        WEP_RPC.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
        WEP_HMG.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
 
-       WEP_SHOTGUN.mdl = "ok_shotgun";
-       WEP_MACHINEGUN.mdl = "ok_mg";
-       WEP_VORTEX.mdl = "ok_sniper";
+       //WEP_SHOTGUN.mdl = "ok_shotgun";
+       //WEP_MACHINEGUN.mdl = "ok_mg";
+       //WEP_VORTEX.mdl = "ok_sniper";
 }
index 94e408d..d506042 100644 (file)
@@ -86,9 +86,11 @@ REGISTER_STAT(WEAPON_CLIPLOAD, int)
 REGISTER_STAT(WEAPON_CLIPSIZE, int)
 
 REGISTER_STAT(VORTEX_CHARGE, float)
+REGISTER_STAT(OVERKILL_VORTEX_CHARGE, float)
 REGISTER_STAT(LAST_PICKUP, float)
 REGISTER_STAT(HUD, int)
 REGISTER_STAT(VORTEX_CHARGEPOOL, float)
+REGISTER_STAT(OVERKILL_VORTEX_CHARGEPOOL, float)
 REGISTER_STAT(HIT_TIME, float)
 REGISTER_STAT(DAMAGE_DEALT_TOTAL, int)
 REGISTER_STAT(TYPEHIT_TIME, float)
index 3644c13..e0d2e32 100644 (file)
@@ -3,15 +3,15 @@
 #ifdef SVQC
 spawnfunc(weapon_shotgun) { weapon_defaultspawnfunc(this, WEP_SHOTGUN); }
 
-void W_Shotgun_Attack(Weapon thiswep, entity actor, .entity weaponentity, float isprimary)
+void W_Shotgun_Attack(Weapon thiswep, entity actor, .entity weaponentity, float isprimary, float ammocount, float damage, float bullets, float spread, float solidpenetration, float force)
 {
-       W_DecreaseAmmo(thiswep, actor, WEP_CVAR_PRI(shotgun, ammo), weaponentity);
+       W_DecreaseAmmo(thiswep, actor, ammocount, weaponentity);
 
-       W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), WEP_CVAR_PRI(shotgun, damage) * WEP_CVAR_PRI(shotgun, bullets));
-       for(int sc = 0;sc < WEP_CVAR_PRI(shotgun, bullets);sc = sc + 1)
-               fireBullet(actor, weaponentity, 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.m_id, 0);
+       W_SetupShot(actor, weaponentity, true, 5, SND_SHOTGUN_FIRE, ((isprimary) ? CH_WEAPON_A : CH_WEAPON_SINGLE), damage * bullets);
+       for(int sc = 0;sc < bullets;sc = sc + 1)
+               fireBullet(actor, weaponentity, w_shotorg, w_shotdir, spread, solidpenetration, damage, force, WEP_SHOTGUN.m_id, 0);
 
-       Send_Effect(EFFECT_SHOTGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, WEP_CVAR_PRI(shotgun, ammo));
+       Send_Effect(EFFECT_SHOTGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, ammocount);
 
        // casing code
        if(autocvar_g_casings >= 1)
@@ -152,7 +152,13 @@ void W_Shotgun_Attack3_Frame2(Weapon thiswep, entity actor, .entity weaponentity
        }
 
        sound(actor, CH_WEAPON_SINGLE, SND_Null, VOL_BASE, ATTN_NORM); // kill previous sound
-       W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, true); // actually is secondary, but we trick the last shot into playing full reload sound
+       W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, true,
+               WEP_CVAR_PRI(shotgun, ammo),
+               WEP_CVAR_PRI(shotgun, damage),
+               WEP_CVAR_PRI(shotgun, bullets),
+               WEP_CVAR_PRI(shotgun, spread),
+               WEP_CVAR_PRI(shotgun, solidpenetration),
+               WEP_CVAR_PRI(shotgun, force)); // actually is secondary, but we trick the last shot into playing full reload sound
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), w_ready);
 }
 void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity, int fire)
@@ -165,7 +171,13 @@ void W_Shotgun_Attack3_Frame1(Weapon thiswep, entity actor, .entity weaponentity
                return;
        }
 
-       W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, false);
+       W_Shotgun_Attack(WEP_SHOTGUN, actor, weaponentity, false,
+               WEP_CVAR_PRI(shotgun, ammo),
+               WEP_CVAR_PRI(shotgun, damage),
+               WEP_CVAR_PRI(shotgun, bullets),
+               WEP_CVAR_PRI(shotgun, spread),
+               WEP_CVAR_PRI(shotgun, solidpenetration),
+               WEP_CVAR_PRI(shotgun, force));
        weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame2);
 }
 
@@ -178,6 +190,7 @@ METHOD(Shotgun, wr_aim, void(entity thiswep, entity actor, .entity weaponentity)
     else
         PHYS_INPUT_BUTTON_ATCK(actor) = bot_aim(actor, weaponentity, 1000000, 0, 0.001, false);
 }
+
 METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
     if(WEP_CVAR(shotgun, reload_ammo) && actor.(weaponentity).clip_load < WEP_CVAR_PRI(shotgun, ammo)) // forced reload
@@ -195,7 +208,13 @@ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentit
             {
                 if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_PRI(shotgun, animtime)))
                 {
-                    W_Shotgun_Attack(thiswep, actor, weaponentity, true);
+                    W_Shotgun_Attack(thiswep, actor, weaponentity, true,
+                                               WEP_CVAR_PRI(shotgun, ammo),
+                                               WEP_CVAR_PRI(shotgun, damage),
+                                               WEP_CVAR_PRI(shotgun, bullets),
+                                               WEP_CVAR_PRI(shotgun, spread),
+                                               WEP_CVAR_PRI(shotgun, solidpenetration),
+                                               WEP_CVAR_PRI(shotgun, force));
                     actor.(weaponentity).shotgun_primarytime = time + WEP_CVAR_PRI(shotgun, refire) * W_WeaponRateFactor(actor);
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_PRI(shotgun, animtime), w_ready);
                 }
@@ -207,7 +226,13 @@ METHOD(Shotgun, wr_think, void(entity thiswep, entity actor, .entity weaponentit
             {
                 if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR_SEC(shotgun, alt_animtime)))
                 {
-                    W_Shotgun_Attack(thiswep, actor, weaponentity, false);
+                    W_Shotgun_Attack(thiswep, actor, weaponentity, false,
+                                               WEP_CVAR_PRI(shotgun, ammo),
+                                               WEP_CVAR_PRI(shotgun, damage),
+                                               WEP_CVAR_PRI(shotgun, bullets),
+                                               WEP_CVAR_PRI(shotgun, spread),
+                                               WEP_CVAR_PRI(shotgun, solidpenetration),
+                                               WEP_CVAR_PRI(shotgun, force));
                     actor.(weaponentity).shotgun_primarytime = time + WEP_CVAR_SEC(shotgun, alt_refire) * W_WeaponRateFactor(actor);
                     weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR_SEC(shotgun, alt_animtime), W_Shotgun_Attack3_Frame1);
                 }
index 8d74a7b..43ca6e7 100644 (file)
@@ -26,6 +26,10 @@ MACRO_END
        { WriteByte(chan, this.vortex_charge * 16); }, \
        { (viewmodels[this.m_wepent_slot]).vortex_charge = ReadByte() / 16; }) \
     \
+    PROP(false, okvortex_charge, WEPENT_SET_NORMAL, \
+       { WriteByte(chan, this.okvortex_charge * 16); }, \
+       { (viewmodels[this.m_wepent_slot]).okvortex_charge = ReadByte() / 16; }) \
+    \
     PROP(false, m_gunalign, WEPENT_SET_NORMAL, \
        { WriteByte(chan, this.m_gunalign); }, \
        { (viewmodels[this.m_wepent_slot]).m_gunalign = ReadByte(); }) \
index 46180d7..25f3993 100644 (file)
@@ -4,6 +4,7 @@ REGISTER_NET_LINKED(ENT_CLIENT_WEPENT)
 REGISTER_NET_TEMP(CLIENT_WEPENT)
 
 .float vortex_charge;
+.float okvortex_charge;
 .int tuba_instrument;
 
 #ifdef SVQC
index f1d417d..b56305b 100644 (file)
@@ -59,6 +59,8 @@
 
 #include "../lib/warpzone/server.qh"
 
+#include <common/mutators/mutator/overkill/okvortex.qh>
+
 STATIC_METHOD(Client, Add, void(Client this, int _team))
 {
     ClientConnect(this);
@@ -1738,6 +1740,8 @@ void SpectateCopy(entity this, entity spectatee)
        this.weapons = spectatee.weapons;
        this.vortex_charge = spectatee.vortex_charge;
        this.vortex_chargepool_ammo = spectatee.vortex_chargepool_ammo;
+       this.okvortex_charge = spectatee.okvortex_charge;
+       this.okvortex_chargepool_ammo = spectatee.okvortex_chargepool_ammo;
        this.hagar_load = spectatee.hagar_load;
        this.arc_heat_percent = spectatee.arc_heat_percent;
        this.minelayer_mines = spectatee.minelayer_mines;
index 4c3b1d2..4adf563 100644 (file)
@@ -326,6 +326,9 @@ float client_cefc_accumulatortime;
 .float vortex_charge = _STAT(VORTEX_CHARGE);
 .float vortex_charge_rottime;
 .float vortex_chargepool_ammo = _STAT(VORTEX_CHARGEPOOL);
+.float okvortex_charge = _STAT(OVERKILL_VORTEX_CHARGE);
+.float okvortex_charge_rottime;
+.float okvortex_chargepool_ammo = _STAT(OVERKILL_VORTEX_CHARGEPOOL);
 .float hagar_load = _STAT(HAGAR_LOAD);
 
 .int grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab