- wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints
- wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache
- make
- - EXPECT=ce60a57e67f899e8b748c1b644082c74
+ - EXPECT=e1e069b401a7aaf28fed29e2e8cbc0c8
- HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
| tee /dev/stderr
| grep '^:'
set g_balance_blaster_primary_animtime 0.2
set g_balance_blaster_primary_damage 20
set g_balance_blaster_primary_delay 0
-set g_balance_blaster_primary_edgedamage 12.5
+set g_balance_blaster_primary_edgedamage 10
set g_balance_blaster_primary_force 300
set g_balance_blaster_primary_force_zscale 1.25
set g_balance_blaster_primary_lifetime 5
set g_balance_shotgun_reload_ammo 0
set g_balance_shotgun_reload_time 2
set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_alt_animtime 0.2
+set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_secondary_animtime 1.15
set g_balance_shotgun_secondary_damage 70
set g_balance_shotgun_secondary_force 200
set g_balance_shotgun_secondary_melee_time 0.15
set g_balance_shotgun_secondary_melee_traces 10
set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_switchdelay_drop 0.2
set g_balance_shotgun_switchdelay_raise 0.2
set g_balance_shotgun_weaponreplace ""
set g_balance_shotgun_weaponstartoverride -1
set g_balance_shotgun_weaponthrowable 1
// }}}
-// {{{ #3: Machine Gun
+// {{{ #3: MachineGun
set g_balance_machinegun_burst 3
set g_balance_machinegun_burst_ammo 3
set g_balance_machinegun_burst_animtime 0.3
set g_balance_machinegun_burst_refire 0.06
set g_balance_machinegun_burst_refire2 0.45
-set g_balance_machinegun_burst_speed 0
+set g_balance_machinegun_burst_spread 0.02
set g_balance_machinegun_first 1
set g_balance_machinegun_first_ammo 1
set g_balance_machinegun_first_damage 14
set g_balance_crylink_secondary_animtime 0.2
set g_balance_crylink_secondary_bouncedamagefactor 0.5
set g_balance_crylink_secondary_bounces 0
-set g_balance_crylink_secondary_damage 10
-set g_balance_crylink_secondary_edgedamage 5
+set g_balance_crylink_secondary_damage 8
+set g_balance_crylink_secondary_edgedamage 4
set g_balance_crylink_secondary_force -200
set g_balance_crylink_secondary_joindelay 0
set g_balance_crylink_secondary_joinexplode 0
set g_balance_crylink_secondary_radius 100
set g_balance_crylink_secondary_refire 0.65
set g_balance_crylink_secondary_shots 5
-set g_balance_crylink_secondary_speed 7000
+set g_balance_crylink_secondary_speed 4000
set g_balance_crylink_secondary_spread 0.08
set g_balance_crylink_secondary_spreadtype 0
set g_balance_crylink_switchdelay_drop 0.2
// }}}
// {{{ #8: Vortex
set g_balance_vortex_charge 0
+set g_balance_vortex_charge_always 0
set g_balance_vortex_charge_animlimit 0.5
set g_balance_vortex_charge_limit 1
set g_balance_vortex_charge_maxspeed 800
set g_balance_vaporizer_secondary_delay 0
set g_balance_vaporizer_secondary_edgedamage 12.5
set g_balance_vaporizer_secondary_force 400
+set g_balance_vaporizer_secondary_force_zscale 1.2
set g_balance_vaporizer_secondary_lifetime 5
set g_balance_vaporizer_secondary_radius 70
set g_balance_vaporizer_secondary_refire 0.7
set g_balance_seeker_weaponstartoverride -1
set g_balance_seeker_weaponthrowable 1
// }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
set g_balance_shockwave_blast_animtime 0.3
set g_balance_shockwave_blast_damage 40
set g_balance_shockwave_blast_distance 1000
set g_balance_arc_beam_healing_aps 50
set g_balance_arc_beam_healing_hmax 150
set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_cooldown 2.5
-set g_balance_arc_cooldown_release 0
-set g_balance_arc_overheat_max 5
-set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 0
-set g_balance_arc_burst_heat 5
set g_balance_arc_beam_maxangle 10
set g_balance_arc_beam_nonplayerdamage 80
set g_balance_arc_beam_range 1500
set g_balance_arc_burst_damage 250
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_burst_healing_hps 100
+set g_balance_arc_burst_heat 5
+set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 0
+set g_balance_arc_overheat_max 5
+set g_balance_arc_overheat_min 3
set g_balance_arc_switchdelay_drop 0.2
set g_balance_arc_switchdelay_raise 0.2
set g_balance_arc_weaponreplace ""
set g_balance_arc_weaponstartoverride -1
set g_balance_arc_weaponthrowable 1
// }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #21: Overkill Heavy Machine Gun (MUTATOR WEAPON)
set g_balance_okhmg_primary_ammo 1
set g_balance_okhmg_primary_damage 30
set g_balance_okhmg_primary_force 10
set g_balance_okhmg_secondary_delay 0
set g_balance_okhmg_secondary_edgedamage 12.5
set g_balance_okhmg_secondary_force 300
+set g_balance_okhmg_secondary_force_zscale 1
set g_balance_okhmg_secondary_lifetime 5
set g_balance_okhmg_secondary_radius 70
set g_balance_okhmg_secondary_refire 0.7
set g_balance_okhmg_weaponstartoverride 0
set g_balance_okhmg_weaponthrowable 0
// }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
-set g_balance_okrpc_primary_ammo 10
-set g_balance_okrpc_primary_animtime 1
-set g_balance_okrpc_primary_damage 150
-set g_balance_okrpc_primary_damage2 500
-set g_balance_okrpc_primary_damageforcescale 2
-set g_balance_okrpc_primary_edgedamage 50
-set g_balance_okrpc_primary_force 400
-set g_balance_okrpc_primary_health 25
-set g_balance_okrpc_primary_lifetime 30
-set g_balance_okrpc_primary_radius 300
-set g_balance_okrpc_primary_refire 1
-set g_balance_okrpc_primary_speed 2500
-set g_balance_okrpc_primary_speedaccel 5000
-set g_balance_okrpc_reload_ammo 10
-set g_balance_okrpc_reload_time 1
-set g_balance_okrpc_secondary_ammo 0
-set g_balance_okrpc_secondary_animtime 0.2
-set g_balance_okrpc_secondary_damage 25
-set g_balance_okrpc_secondary_delay 0
-set g_balance_okrpc_secondary_edgedamage 12.5
-set g_balance_okrpc_secondary_force 300
-set g_balance_okrpc_secondary_lifetime 5
-set g_balance_okrpc_secondary_radius 70
-set g_balance_okrpc_secondary_refire 0.7
-set g_balance_okrpc_secondary_refire_type 1
-set g_balance_okrpc_secondary_shotangle 0
-set g_balance_okrpc_secondary_speed 6000
-set g_balance_okrpc_secondary_spread 0
-set g_balance_okrpc_switchdelay_drop 0.2
-set g_balance_okrpc_switchdelay_raise 0.2
-set g_balance_okrpc_weaponreplace ""
-set g_balance_okrpc_weaponstart 0
-set g_balance_okrpc_weaponstartoverride 0
-set g_balance_okrpc_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_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
+// {{{ #22: Overkill MachineGun (MUTATOR WEAPON)
set g_balance_okmachinegun_primary_ammo 1
set g_balance_okmachinegun_primary_damage 25
set g_balance_okmachinegun_primary_force 5
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_force_zscale 1
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_weaponstartoverride -1
set g_balance_okmachinegun_weaponthrowable 1
// }}}
-// {{{ Overkill Nex
+// {{{ #23: Overkill Nex (MUTATOR WEAPON)
set g_balance_oknex_charge 0
set g_balance_oknex_charge_animlimit 0.5
set g_balance_oknex_charge_limit 1
set g_balance_oknex_secondary_damagefalloff_halflife 0
set g_balance_oknex_secondary_damagefalloff_maxdist 0
set g_balance_oknex_secondary_damagefalloff_mindist 0
-set g_balance_oknex_secondary_force 300
-set g_balance_oknex_secondary_refire 0.7
-set g_balance_oknex_secondary_refire_type 1
set g_balance_oknex_secondary_delay 0
set g_balance_oknex_secondary_edgedamage 12.5
+set g_balance_oknex_secondary_force 300
+set g_balance_oknex_secondary_force_zscale 1
set g_balance_oknex_secondary_lifetime 5
set g_balance_oknex_secondary_radius 70
+set g_balance_oknex_secondary_refire 0.7
+set g_balance_oknex_secondary_refire_type 1
set g_balance_oknex_secondary_shotangle 0
set g_balance_oknex_secondary_speed 6000
set g_balance_oknex_secondary_spread 0
set g_balance_oknex_weaponstartoverride -1
set g_balance_oknex_weaponthrowable 1
// }}}
+// {{{ #24: Overkill Rocket Propelled Chainsaw (MUTATOR WEAPON)
+set g_balance_okrpc_primary_ammo 10
+set g_balance_okrpc_primary_animtime 1
+set g_balance_okrpc_primary_damage 150
+set g_balance_okrpc_primary_damage2 500
+set g_balance_okrpc_primary_damageforcescale 2
+set g_balance_okrpc_primary_edgedamage 50
+set g_balance_okrpc_primary_force 400
+set g_balance_okrpc_primary_health 25
+set g_balance_okrpc_primary_lifetime 30
+set g_balance_okrpc_primary_radius 300
+set g_balance_okrpc_primary_refire 1
+set g_balance_okrpc_primary_speed 2500
+set g_balance_okrpc_primary_speedaccel 5000
+set g_balance_okrpc_reload_ammo 10
+set g_balance_okrpc_reload_time 1
+set g_balance_okrpc_secondary_ammo 0
+set g_balance_okrpc_secondary_animtime 0.2
+set g_balance_okrpc_secondary_damage 25
+set g_balance_okrpc_secondary_delay 0
+set g_balance_okrpc_secondary_edgedamage 12.5
+set g_balance_okrpc_secondary_force 300
+set g_balance_okrpc_secondary_force_zscale 1
+set g_balance_okrpc_secondary_lifetime 5
+set g_balance_okrpc_secondary_radius 70
+set g_balance_okrpc_secondary_refire 0.7
+set g_balance_okrpc_secondary_refire_type 1
+set g_balance_okrpc_secondary_shotangle 0
+set g_balance_okrpc_secondary_speed 6000
+set g_balance_okrpc_secondary_spread 0
+set g_balance_okrpc_switchdelay_drop 0.2
+set g_balance_okrpc_switchdelay_raise 0.2
+set g_balance_okrpc_weaponreplace ""
+set g_balance_okrpc_weaponstart 0
+set g_balance_okrpc_weaponstartoverride 0
+set g_balance_okrpc_weaponthrowable 0
+// }}}
+// {{{ #25: Overkill Shotgun (MUTATOR WEAPON)
+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_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_force_zscale 1
+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
+// }}}
set g_balance_shotgun_reload_ammo 0
set g_balance_shotgun_reload_time 2
set g_balance_shotgun_secondary 2
+set g_balance_shotgun_secondary_alt_animtime 0.2
+set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_secondary_animtime 1.15
set g_balance_shotgun_secondary_damage 80
set g_balance_shotgun_secondary_force 200
set g_balance_shotgun_secondary_melee_time 0.15
set g_balance_shotgun_secondary_melee_traces 10
set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_switchdelay_drop 0.15
set g_balance_shotgun_switchdelay_raise 0.15
set g_balance_shotgun_weaponreplace ""
set g_balance_shotgun_weaponstartoverride -1
set g_balance_shotgun_weaponthrowable 1
// }}}
-// {{{ #3: Machine Gun
+// {{{ #3: MachineGun
set g_balance_machinegun_burst 0
set g_balance_machinegun_burst_ammo 3
set g_balance_machinegun_burst_animtime 0.75
set g_balance_machinegun_burst_refire 0.05
set g_balance_machinegun_burst_refire2 0.75
-set g_balance_machinegun_burst_speed 0
+set g_balance_machinegun_burst_spread 0.04
set g_balance_machinegun_first 1
set g_balance_machinegun_first_ammo 1
set g_balance_machinegun_first_damage 30
// }}}
// {{{ #8: Vortex
set g_balance_vortex_charge 0
+set g_balance_vortex_charge_always 0
set g_balance_vortex_charge_animlimit 0.5
set g_balance_vortex_charge_limit 1
set g_balance_vortex_charge_maxspeed 800
set g_balance_hagar_primary_radius 65
set g_balance_hagar_primary_refire 0.15
set g_balance_hagar_primary_speed 3000
-set g_balance_hagar_primary_spread 0.010
+set g_balance_hagar_primary_spread 0.01
set g_balance_hagar_reload_ammo 0
set g_balance_hagar_reload_time 2
set g_balance_hagar_secondary 1
set g_balance_vaporizer_secondary_delay 0
set g_balance_vaporizer_secondary_edgedamage 12.5
set g_balance_vaporizer_secondary_force 400
+set g_balance_vaporizer_secondary_force_zscale 1
set g_balance_vaporizer_secondary_lifetime 5
set g_balance_vaporizer_secondary_radius 70
set g_balance_vaporizer_secondary_refire 0.7
set g_balance_seeker_weaponstartoverride -1
set g_balance_seeker_weaponthrowable 1
// }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
set g_balance_shockwave_blast_animtime 0.3
set g_balance_shockwave_blast_damage 20
set g_balance_shockwave_blast_distance 1000
set g_balance_arc_beam_healing_aps 50
set g_balance_arc_beam_healing_hmax 150
set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_cooldown 2.5
-set g_balance_arc_cooldown_release 1
-set g_balance_arc_overheat_max 5
-set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 1
-set g_balance_arc_burst_heat 3
set g_balance_arc_beam_maxangle 10
set g_balance_arc_beam_nonplayerdamage 80
set g_balance_arc_beam_range 1000
set g_balance_arc_burst_damage 150
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_burst_healing_hps 100
+set g_balance_arc_burst_heat 3
+set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 1
+set g_balance_arc_overheat_max 5
+set g_balance_arc_overheat_min 3
set g_balance_arc_switchdelay_drop 0.3
set g_balance_arc_switchdelay_raise 0.3
set g_balance_arc_weaponreplace ""
set g_balance_arc_weaponstartoverride -1
set g_balance_arc_weaponthrowable 1
// }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #21: Overkill Heavy Machine Gun (MUTATOR WEAPON)
set g_balance_okhmg_primary_ammo 1
set g_balance_okhmg_primary_damage 30
set g_balance_okhmg_primary_force 10
set g_balance_okhmg_secondary_delay 0
set g_balance_okhmg_secondary_edgedamage 12.5
set g_balance_okhmg_secondary_force 300
+set g_balance_okhmg_secondary_force_zscale 1
set g_balance_okhmg_secondary_lifetime 5
set g_balance_okhmg_secondary_radius 70
set g_balance_okhmg_secondary_refire 0.7
set g_balance_okhmg_weaponstartoverride 0
set g_balance_okhmg_weaponthrowable 0
// }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
+// {{{ #22: Overkill MachineGun (MUTATOR WEAPON)
+set g_balance_okmachinegun_primary_ammo 1
+set g_balance_okmachinegun_primary_damage 25
+set g_balance_okmachinegun_primary_force 5
+set g_balance_okmachinegun_primary_refire 0.1
+set g_balance_okmachinegun_primary_solidpenetration 63
+set g_balance_okmachinegun_primary_spread_add 0.012
+set g_balance_okmachinegun_primary_spread_max 0.05
+set g_balance_okmachinegun_primary_spread_min 0
+set g_balance_okmachinegun_reload_ammo 30
+set g_balance_okmachinegun_reload_time 1.5
+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_force_zscale 1
+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_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
+// }}}
+// {{{ #23: Overkill Nex (MUTATOR WEAPON)
+set g_balance_oknex_charge 0
+set g_balance_oknex_charge_animlimit 0.5
+set g_balance_oknex_charge_limit 1
+set g_balance_oknex_charge_maxspeed 800
+set g_balance_oknex_charge_mindmg 40
+set g_balance_oknex_charge_minspeed 400
+set g_balance_oknex_charge_rate 0.6
+set g_balance_oknex_charge_rot_pause 0
+set g_balance_oknex_charge_rot_rate 0
+set g_balance_oknex_charge_shot_multiplier 0
+set g_balance_oknex_charge_start 0.5
+set g_balance_oknex_charge_velocity_rate 0
+set g_balance_oknex_primary_ammo 10
+set g_balance_oknex_primary_animtime 0.65
+set g_balance_oknex_primary_damage 100
+set g_balance_oknex_primary_damagefalloff_forcehalflife 0
+set g_balance_oknex_primary_damagefalloff_halflife 0
+set g_balance_oknex_primary_damagefalloff_maxdist 0
+set g_balance_oknex_primary_damagefalloff_mindist 0
+set g_balance_oknex_primary_force 500
+set g_balance_oknex_primary_refire 1
+set g_balance_oknex_reload_ammo 50
+set g_balance_oknex_reload_time 2
+set g_balance_oknex_secondary 2
+set g_balance_oknex_secondary_ammo 0
+set g_balance_oknex_secondary_animtime 0.2
+set g_balance_oknex_secondary_chargepool 0
+set g_balance_oknex_secondary_chargepool_pause_regen 1
+set g_balance_oknex_secondary_chargepool_regen 0.15
+set g_balance_oknex_secondary_damage 25
+set g_balance_oknex_secondary_damagefalloff_forcehalflife 0
+set g_balance_oknex_secondary_damagefalloff_halflife 0
+set g_balance_oknex_secondary_damagefalloff_maxdist 0
+set g_balance_oknex_secondary_damagefalloff_mindist 0
+set g_balance_oknex_secondary_delay 0
+set g_balance_oknex_secondary_edgedamage 12.5
+set g_balance_oknex_secondary_force 300
+set g_balance_oknex_secondary_force_zscale 1
+set g_balance_oknex_secondary_lifetime 5
+set g_balance_oknex_secondary_radius 70
+set g_balance_oknex_secondary_refire 0.7
+set g_balance_oknex_secondary_refire_type 1
+set g_balance_oknex_secondary_shotangle 0
+set g_balance_oknex_secondary_speed 6000
+set g_balance_oknex_secondary_spread 0
+set g_balance_oknex_switchdelay_drop 0.2
+set g_balance_oknex_switchdelay_raise 0.2
+set g_balance_oknex_weaponreplace ""
+set g_balance_oknex_weaponstart 0
+set g_balance_oknex_weaponstartoverride -1
+set g_balance_oknex_weaponthrowable 1
+// }}}
+// {{{ #24: Overkill Rocket Propelled Chainsaw (MUTATOR WEAPON)
set g_balance_okrpc_primary_ammo 10
set g_balance_okrpc_primary_animtime 1
set g_balance_okrpc_primary_damage 150
set g_balance_okrpc_secondary_delay 0
set g_balance_okrpc_secondary_edgedamage 12.5
set g_balance_okrpc_secondary_force 300
+set g_balance_okrpc_secondary_force_zscale 1
set g_balance_okrpc_secondary_lifetime 5
set g_balance_okrpc_secondary_radius 70
set g_balance_okrpc_secondary_refire 0.7
set g_balance_okrpc_weaponstartoverride 0
set g_balance_okrpc_weaponthrowable 0
// }}}
+// {{{ #25: Overkill Shotgun (MUTATOR WEAPON)
+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_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_force_zscale 1
+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
+// }}}
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_force_zscale 1
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_okmachinegun_secondary_delay 0
set g_balance_okmachinegun_secondary_edgedamage 10
set g_balance_okmachinegun_secondary_force 300
+set g_balance_okmachinegun_secondary_force_zscale 1
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_oknex_secondary_damagefalloff_maxdist 0
set g_balance_oknex_secondary_damagefalloff_mindist 0
set g_balance_oknex_secondary_force 0
+set g_balance_oknex_secondary_force_zscale 1
set g_balance_oknex_secondary_refire 0
set g_balance_oknex_secondary_refire_type 0
set g_balance_oknex_secondary_delay 0
set g_balance_blaster_primary_delay 0
set g_balance_blaster_primary_edgedamage 12.5
set g_balance_blaster_primary_force 300
+set g_balance_blaster_primary_force_zscale 1
set g_balance_blaster_primary_lifetime 5
set g_balance_blaster_primary_radius 70
set g_balance_blaster_primary_refire 0.7
set g_balance_blaster_secondary_delay 0
set g_balance_blaster_secondary_edgedamage 12.5
set g_balance_blaster_secondary_force 300
+set g_balance_blaster_secondary_force_zscale 1
set g_balance_blaster_secondary_lifetime 5
set g_balance_blaster_secondary_radius 70
set g_balance_blaster_secondary_refire 0.7
set g_balance_blaster_weaponstartoverride -1
set g_balance_blaster_weaponthrowable 0
// }}}
-// {{{ #2: Shockwave
-set g_balance_shockwave_blast_animtime 0.3
-set g_balance_shockwave_blast_damage 20
-set g_balance_shockwave_blast_distance 1000
-set g_balance_shockwave_blast_edgedamage 0
-set g_balance_shockwave_blast_force 200
-set g_balance_shockwave_blast_force_forwardbias 50
-set g_balance_shockwave_blast_force_zscale 2
-set g_balance_shockwave_blast_jump_damage 20
-set g_balance_shockwave_blast_jump_edgedamage 0
-set g_balance_shockwave_blast_jump_force 300
-set g_balance_shockwave_blast_jump_force_velocitybias 0
-set g_balance_shockwave_blast_jump_force_zscale 1.25
-set g_balance_shockwave_blast_jump_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_jump_multiplier_distance 0.5
-set g_balance_shockwave_blast_jump_multiplier_min 0
-set g_balance_shockwave_blast_jump_radius 150
-set g_balance_shockwave_blast_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_multiplier_distance 0.5
-set g_balance_shockwave_blast_multiplier_min 0
-set g_balance_shockwave_blast_refire 0.75
-set g_balance_shockwave_blast_splash_damage 15
-set g_balance_shockwave_blast_splash_edgedamage 0
-set g_balance_shockwave_blast_splash_force 100
-set g_balance_shockwave_blast_splash_force_forwardbias 50
-set g_balance_shockwave_blast_splash_multiplier_accuracy 0.5
-set g_balance_shockwave_blast_splash_multiplier_distance 0.5
-set g_balance_shockwave_blast_splash_multiplier_min 0
-set g_balance_shockwave_blast_splash_radius 70
-set g_balance_shockwave_blast_spread_max 120
-set g_balance_shockwave_blast_spread_min 25
-set g_balance_shockwave_melee_animtime 1.3
-set g_balance_shockwave_melee_damage 80
-set g_balance_shockwave_melee_delay 0.25
-set g_balance_shockwave_melee_force 200
-set g_balance_shockwave_melee_multihit 1
-set g_balance_shockwave_melee_no_doubleslap 1
-set g_balance_shockwave_melee_nonplayerdamage 40
-set g_balance_shockwave_melee_range 120
-set g_balance_shockwave_melee_refire 1.25
-set g_balance_shockwave_melee_swing_side 120
-set g_balance_shockwave_melee_swing_up 30
-set g_balance_shockwave_melee_time 0.15
-set g_balance_shockwave_melee_traces 10
-set g_balance_shockwave_switchdelay_drop 0.2
-set g_balance_shockwave_switchdelay_raise 0.2
-set g_balance_shockwave_weaponreplace ""
-set g_balance_shockwave_weaponstart 1
-set g_balance_shockwave_weaponstartoverride -1
-set g_balance_shockwave_weaponthrowable 0
+// {{{ #2: Shotgun
+set g_balance_shotgun_primary_ammo 1
+set g_balance_shotgun_primary_animtime 0.2
+set g_balance_shotgun_primary_bullets 14
+set g_balance_shotgun_primary_damage 4
+set g_balance_shotgun_primary_force 15
+set g_balance_shotgun_primary_refire 0.75
+set g_balance_shotgun_primary_solidpenetration 3.8
+set g_balance_shotgun_primary_spread 0.12
+set g_balance_shotgun_reload_ammo 0
+set g_balance_shotgun_reload_time 2
+set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_alt_animtime 0.2
+set g_balance_shotgun_secondary_alt_refire 1.2
+set g_balance_shotgun_secondary_animtime 1.15
+set g_balance_shotgun_secondary_damage 80
+set g_balance_shotgun_secondary_force 200
+set g_balance_shotgun_secondary_melee_delay 0.25
+set g_balance_shotgun_secondary_melee_multihit 1
+set g_balance_shotgun_secondary_melee_no_doubleslap 1
+set g_balance_shotgun_secondary_melee_nonplayerdamage 40
+set g_balance_shotgun_secondary_melee_range 120
+set g_balance_shotgun_secondary_melee_swing_side 120
+set g_balance_shotgun_secondary_melee_swing_up 30
+set g_balance_shotgun_secondary_melee_time 0.15
+set g_balance_shotgun_secondary_melee_traces 10
+set g_balance_shotgun_secondary_refire 1.25
+set g_balance_shotgun_switchdelay_drop 0.2
+set g_balance_shotgun_switchdelay_raise 0.2
+set g_balance_shotgun_weaponreplace ""
+set g_balance_shotgun_weaponstart 0
+set g_balance_shotgun_weaponstartoverride -1
+set g_balance_shotgun_weaponthrowable 1
// }}}
-// {{{ #3: Machine Gun
+// {{{ #3: MachineGun
set g_balance_machinegun_burst 3
set g_balance_machinegun_burst_ammo 3
set g_balance_machinegun_burst_animtime 0.3
set g_balance_machinegun_burst_refire 0.06
set g_balance_machinegun_burst_refire2 0.45
-set g_balance_machinegun_burst_speed 0
+set g_balance_machinegun_burst_spread 0.02
set g_balance_machinegun_first 1
set g_balance_machinegun_first_ammo 1
set g_balance_machinegun_first_damage 14
set g_balance_electro_weaponstartoverride -1
set g_balance_electro_weaponthrowable 1
// }}}
-// {{{ #7: Arc
-set g_balance_arc_beam_ammo 0
-set g_balance_arc_beam_animtime 0.2
-set g_balance_arc_beam_botaimlifetime 0
-set g_balance_arc_beam_botaimspeed 0
-set g_balance_arc_beam_damage 150
-set g_balance_arc_beam_degreespersegment 1
-set g_balance_arc_beam_distancepersegment 0
-set g_balance_arc_beam_falloff_halflifedist 0
-set g_balance_arc_beam_falloff_maxdist 0
-set g_balance_arc_beam_falloff_mindist 0
-set g_balance_arc_beam_force 2000
-set g_balance_arc_beam_healing_amax 200
-set g_balance_arc_beam_healing_aps 50
-set g_balance_arc_beam_healing_hmax 200
-set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_beam_maxangle 10
-set g_balance_arc_beam_nonplayerdamage 80
-set g_balance_arc_beam_range 1000
-set g_balance_arc_beam_refire 0.5
-set g_balance_arc_beam_returnspeed 8
-set g_balance_arc_beam_tightness 0.5
-set g_balance_arc_bolt 0
-set g_balance_arc_bolt_ammo 1
-set g_balance_arc_bolt_damage 25
-set g_balance_arc_bolt_damageforcescale 0
-set g_balance_arc_bolt_edgedamage 12.5
-set g_balance_arc_bolt_force 100
-set g_balance_arc_bolt_health 15
-set g_balance_arc_bolt_lifetime 5
-set g_balance_arc_bolt_radius 65
-set g_balance_arc_bolt_refire 0.16667
-set g_balance_arc_bolt_speed 2200
-set g_balance_arc_bolt_spread 0.03
-set g_balance_arc_burst_ammo 0
-set g_balance_arc_burst_damage 500
-set g_balance_arc_burst_healing_aps 100
-set g_balance_arc_burst_healing_hps 100
-set g_balance_arc_cooldown 2.5
-set g_balance_arc_cooldown_release 1
-set g_balance_arc_overheat_max 5
-set g_balance_arc_overheat_min 3
-set g_balance_arc_beam_heat 1
-set g_balance_arc_burst_heat 5
-set g_balance_arc_switchdelay_drop 0.3
-set g_balance_arc_switchdelay_raise 0.3
-set g_balance_arc_weaponreplace ""
-set g_balance_arc_weaponstart 0
-set g_balance_arc_weaponstartoverride -1
-set g_balance_arc_weaponthrowable 1
-// }}}
-// {{{ #8: Crylink
+// {{{ #7: Crylink
set g_balance_crylink_primary_ammo 3
set g_balance_crylink_primary_animtime 0.3
set g_balance_crylink_primary_bouncedamagefactor 0.5
set g_balance_crylink_weaponstartoverride -1
set g_balance_crylink_weaponthrowable 1
// }}}
-// {{{ #9: Vortex
+// {{{ #8: Vortex
set g_balance_vortex_charge 1
+set g_balance_vortex_charge_always 0
set g_balance_vortex_charge_animlimit 0.5
set g_balance_vortex_charge_limit 1
set g_balance_vortex_charge_maxspeed 800
set g_balance_vortex_weaponstartoverride -1
set g_balance_vortex_weaponthrowable 1
// }}}
-// {{{ #10: Hagar
+// {{{ #9: Hagar
set g_balance_hagar_primary_ammo 1
set g_balance_hagar_primary_damage 25
set g_balance_hagar_primary_damageforcescale 0
set g_balance_hagar_weaponstartoverride -1
set g_balance_hagar_weaponthrowable 1
// }}}
-// {{{ #11: Devastator
+// {{{ #10: Devastator
set g_balance_devastator_ammo 4
set g_balance_devastator_animtime 0.4
set g_balance_devastator_damage 70
set g_balance_devastator_weaponstartoverride -1
set g_balance_devastator_weaponthrowable 1
// }}}
-// {{{ #12: Port-O-Launch
+// {{{ #11: Port-O-Launch
set g_balance_porto_primary_animtime 0.3
set g_balance_porto_primary_lifetime 5
set g_balance_porto_primary_refire 1.5
set g_balance_porto_weaponstartoverride -1
set g_balance_porto_weaponthrowable 1
// }}}
-// {{{ #13: Vaporizer
+// {{{ #12: Vaporizer
set g_balance_vaporizer_primary_ammo 10
set g_balance_vaporizer_primary_animtime 0.3
set g_balance_vaporizer_primary_damage 150
set g_balance_vaporizer_secondary_delay 0
set g_balance_vaporizer_secondary_edgedamage 12.5
set g_balance_vaporizer_secondary_force 400
+set g_balance_vaporizer_secondary_force_zscale 1
set g_balance_vaporizer_secondary_lifetime 5
set g_balance_vaporizer_secondary_radius 70
set g_balance_vaporizer_secondary_refire 0.7
set g_balance_vaporizer_weaponstartoverride -1
set g_balance_vaporizer_weaponthrowable 0
// }}}
-// {{{ #14: Grappling Hook
+// {{{ #13: Grappling Hook
set g_balance_hook_primary_ammo 5
set g_balance_hook_primary_animtime 0.3
set g_balance_hook_primary_hooked_ammo 5
set g_balance_hook_weaponstartoverride -1
set g_balance_hook_weaponthrowable 1
// }}}
-// {{{ #15: Heavy Laser Assault Cannon (MUTATOR WEAPON)
+// {{{ #14: Heavy Laser Assault Cannon (MUTATOR WEAPON)
set g_balance_hlac_primary_ammo 1
set g_balance_hlac_primary_animtime 0.4
set g_balance_hlac_primary_damage 18
set g_balance_hlac_weaponstartoverride -1
set g_balance_hlac_weaponthrowable 1
// }}}
-// {{{ #16: @!#%'n Tuba
+// {{{ #15: @!#%'n Tuba
set g_balance_tuba_animtime 0.05
set g_balance_tuba_attenuation 0.5
set g_balance_tuba_damage 5
set g_balance_tuba_weaponstartoverride -1
set g_balance_tuba_weaponthrowable 1
// }}}
-// {{{ #17: Rifle (MUTATOR WEAPON)
+// {{{ #16: Rifle (MUTATOR WEAPON)
set g_balance_rifle_bursttime 0
set g_balance_rifle_primary_ammo 10
set g_balance_rifle_primary_animtime 0.4
set g_balance_rifle_weaponstartoverride -1
set g_balance_rifle_weaponthrowable 1
// }}}
-// {{{ #18: Fireball
+// {{{ #17: Fireball
set g_balance_fireball_primary_animtime 0.2
set g_balance_fireball_primary_bfgdamage 100
set g_balance_fireball_primary_bfgforce 0
set g_balance_fireball_weaponstartoverride -1
set g_balance_fireball_weaponthrowable 0
// }}}
-// {{{ #19: T.A.G. Seeker (MUTATOR WEAPON)
+// {{{ #18: T.A.G. Seeker (MUTATOR WEAPON)
set g_balance_seeker_flac_ammo 1
set g_balance_seeker_flac_animtime 0.1
set g_balance_seeker_flac_damage 15
set g_balance_seeker_weaponstartoverride -1
set g_balance_seeker_weaponthrowable 1
// }}}
-// {{{ #20: Shotgun (MUTATOR WEAPON)
-set g_balance_shotgun_primary_ammo 1
-set g_balance_shotgun_primary_animtime 0.2
-set g_balance_shotgun_primary_bullets 14
-set g_balance_shotgun_primary_damage 4
-set g_balance_shotgun_primary_force 15
-set g_balance_shotgun_primary_refire 0.75
-set g_balance_shotgun_primary_solidpenetration 3.8
-set g_balance_shotgun_primary_spread 0.12
-set g_balance_shotgun_reload_ammo 0
-set g_balance_shotgun_reload_time 2
-set g_balance_shotgun_secondary 1
-set g_balance_shotgun_secondary_animtime 1.15
-set g_balance_shotgun_secondary_damage 80
-set g_balance_shotgun_secondary_force 200
-set g_balance_shotgun_secondary_melee_delay 0.25
-set g_balance_shotgun_secondary_melee_multihit 1
-set g_balance_shotgun_secondary_melee_no_doubleslap 1
-set g_balance_shotgun_secondary_melee_nonplayerdamage 40
-set g_balance_shotgun_secondary_melee_range 120
-set g_balance_shotgun_secondary_melee_swing_side 120
-set g_balance_shotgun_secondary_melee_swing_up 30
-set g_balance_shotgun_secondary_melee_time 0.15
-set g_balance_shotgun_secondary_melee_traces 10
-set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
-set g_balance_shotgun_switchdelay_drop 0.2
-set g_balance_shotgun_switchdelay_raise 0.2
-set g_balance_shotgun_weaponreplace ""
-set g_balance_shotgun_weaponstart 0
-set g_balance_shotgun_weaponstartoverride -1
-set g_balance_shotgun_weaponthrowable 1
+// {{{ #19: Shockwave
+set g_balance_shockwave_blast_animtime 0.3
+set g_balance_shockwave_blast_damage 20
+set g_balance_shockwave_blast_distance 1000
+set g_balance_shockwave_blast_edgedamage 0
+set g_balance_shockwave_blast_force 200
+set g_balance_shockwave_blast_force_forwardbias 50
+set g_balance_shockwave_blast_force_zscale 2
+set g_balance_shockwave_blast_jump_damage 20
+set g_balance_shockwave_blast_jump_edgedamage 0
+set g_balance_shockwave_blast_jump_force 300
+set g_balance_shockwave_blast_jump_force_velocitybias 0
+set g_balance_shockwave_blast_jump_force_zscale 1.25
+set g_balance_shockwave_blast_jump_multiplier_accuracy 0.5
+set g_balance_shockwave_blast_jump_multiplier_distance 0.5
+set g_balance_shockwave_blast_jump_multiplier_min 0
+set g_balance_shockwave_blast_jump_radius 150
+set g_balance_shockwave_blast_multiplier_accuracy 0.5
+set g_balance_shockwave_blast_multiplier_distance 0.5
+set g_balance_shockwave_blast_multiplier_min 0
+set g_balance_shockwave_blast_refire 0.75
+set g_balance_shockwave_blast_splash_damage 15
+set g_balance_shockwave_blast_splash_edgedamage 0
+set g_balance_shockwave_blast_splash_force 100
+set g_balance_shockwave_blast_splash_force_forwardbias 50
+set g_balance_shockwave_blast_splash_multiplier_accuracy 0.5
+set g_balance_shockwave_blast_splash_multiplier_distance 0.5
+set g_balance_shockwave_blast_splash_multiplier_min 0
+set g_balance_shockwave_blast_splash_radius 70
+set g_balance_shockwave_blast_spread_max 120
+set g_balance_shockwave_blast_spread_min 25
+set g_balance_shockwave_melee_animtime 1.3
+set g_balance_shockwave_melee_damage 80
+set g_balance_shockwave_melee_delay 0.25
+set g_balance_shockwave_melee_force 200
+set g_balance_shockwave_melee_multihit 1
+set g_balance_shockwave_melee_no_doubleslap 1
+set g_balance_shockwave_melee_nonplayerdamage 40
+set g_balance_shockwave_melee_range 120
+set g_balance_shockwave_melee_refire 1.25
+set g_balance_shockwave_melee_swing_side 120
+set g_balance_shockwave_melee_swing_up 30
+set g_balance_shockwave_melee_time 0.15
+set g_balance_shockwave_melee_traces 10
+set g_balance_shockwave_switchdelay_drop 0.2
+set g_balance_shockwave_switchdelay_raise 0.2
+set g_balance_shockwave_weaponreplace ""
+set g_balance_shockwave_weaponstart 1
+set g_balance_shockwave_weaponstartoverride -1
+set g_balance_shockwave_weaponthrowable 0
+// }}}
+// {{{ #20: Arc
+set g_balance_arc_beam_ammo 0
+set g_balance_arc_beam_animtime 0.2
+set g_balance_arc_beam_botaimlifetime 0
+set g_balance_arc_beam_botaimspeed 0
+set g_balance_arc_beam_damage 150
+set g_balance_arc_beam_degreespersegment 1
+set g_balance_arc_beam_distancepersegment 0
+set g_balance_arc_beam_falloff_halflifedist 0
+set g_balance_arc_beam_falloff_maxdist 0
+set g_balance_arc_beam_falloff_mindist 0
+set g_balance_arc_beam_force 2000
+set g_balance_arc_beam_healing_amax 200
+set g_balance_arc_beam_healing_aps 50
+set g_balance_arc_beam_healing_hmax 200
+set g_balance_arc_beam_healing_hps 50
+set g_balance_arc_beam_heat 1
+set g_balance_arc_beam_maxangle 10
+set g_balance_arc_beam_nonplayerdamage 80
+set g_balance_arc_beam_range 1000
+set g_balance_arc_beam_refire 0.5
+set g_balance_arc_beam_returnspeed 8
+set g_balance_arc_beam_tightness 0.5
+set g_balance_arc_bolt 0
+set g_balance_arc_bolt_ammo 1
+set g_balance_arc_bolt_damage 25
+set g_balance_arc_bolt_damageforcescale 0
+set g_balance_arc_bolt_edgedamage 12.5
+set g_balance_arc_bolt_force 100
+set g_balance_arc_bolt_health 15
+set g_balance_arc_bolt_lifetime 5
+set g_balance_arc_bolt_radius 65
+set g_balance_arc_bolt_refire 0.16667
+set g_balance_arc_bolt_speed 2200
+set g_balance_arc_bolt_spread 0.03
+set g_balance_arc_burst_ammo 0
+set g_balance_arc_burst_damage 500
+set g_balance_arc_burst_healing_aps 100
+set g_balance_arc_burst_healing_hps 100
+set g_balance_arc_burst_heat 5
+set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 1
+set g_balance_arc_overheat_max 5
+set g_balance_arc_overheat_min 3
+set g_balance_arc_switchdelay_drop 0.3
+set g_balance_arc_switchdelay_raise 0.3
+set g_balance_arc_weaponreplace ""
+set g_balance_arc_weaponstart 0
+set g_balance_arc_weaponstartoverride -1
+set g_balance_arc_weaponthrowable 1
// }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #21: Overkill Heavy Machine Gun (MUTATOR WEAPON)
set g_balance_okhmg_primary_ammo 1
set g_balance_okhmg_primary_damage 30
set g_balance_okhmg_primary_force 10
set g_balance_okhmg_secondary_delay 0
set g_balance_okhmg_secondary_edgedamage 12.5
set g_balance_okhmg_secondary_force 300
+set g_balance_okhmg_secondary_force_zscale 1
set g_balance_okhmg_secondary_lifetime 5
set g_balance_okhmg_secondary_radius 70
set g_balance_okhmg_secondary_refire 0.7
set g_balance_okhmg_weaponstartoverride 0
set g_balance_okhmg_weaponthrowable 0
// }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
+// {{{ #22: Overkill MachineGun (MUTATOR WEAPON)
+set g_balance_okmachinegun_primary_ammo 1
+set g_balance_okmachinegun_primary_damage 10
+set g_balance_okmachinegun_primary_force 3
+set g_balance_okmachinegun_primary_refire 0.1
+set g_balance_okmachinegun_primary_solidpenetration 13.1
+set g_balance_okmachinegun_primary_spread_add 0.012
+set g_balance_okmachinegun_primary_spread_max 0.05
+set g_balance_okmachinegun_primary_spread_min 0.02
+set g_balance_okmachinegun_reload_ammo 60
+set g_balance_okmachinegun_reload_time 2
+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_force_zscale 1
+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_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
+// }}}
+// {{{ #23: Overkill Nex (MUTATOR WEAPON)
+set g_balance_oknex_charge 1
+set g_balance_oknex_charge_animlimit 0.5
+set g_balance_oknex_charge_limit 1
+set g_balance_oknex_charge_maxspeed 800
+set g_balance_oknex_charge_mindmg 40
+set g_balance_oknex_charge_minspeed 400
+set g_balance_oknex_charge_rate 0.6
+set g_balance_oknex_charge_rot_pause 0
+set g_balance_oknex_charge_rot_rate 0
+set g_balance_oknex_charge_shot_multiplier 0
+set g_balance_oknex_charge_start 0.5
+set g_balance_oknex_charge_velocity_rate 0
+set g_balance_oknex_primary_ammo 6
+set g_balance_oknex_primary_animtime 0.4
+set g_balance_oknex_primary_damage 80
+set g_balance_oknex_primary_damagefalloff_forcehalflife 0
+set g_balance_oknex_primary_damagefalloff_halflife 0
+set g_balance_oknex_primary_damagefalloff_maxdist 0
+set g_balance_oknex_primary_damagefalloff_mindist 0
+set g_balance_oknex_primary_force 400
+set g_balance_oknex_primary_refire 1.5
+set g_balance_oknex_reload_ammo 0
+set g_balance_oknex_reload_time 2
+set g_balance_oknex_secondary 0
+set g_balance_oknex_secondary_ammo 2
+set g_balance_oknex_secondary_animtime 0
+set g_balance_oknex_secondary_chargepool 0
+set g_balance_oknex_secondary_chargepool_pause_regen 1
+set g_balance_oknex_secondary_chargepool_regen 0.15
+set g_balance_oknex_secondary_damage 0
+set g_balance_oknex_secondary_damagefalloff_forcehalflife 0
+set g_balance_oknex_secondary_damagefalloff_halflife 0
+set g_balance_oknex_secondary_damagefalloff_maxdist 0
+set g_balance_oknex_secondary_damagefalloff_mindist 0
+set g_balance_oknex_secondary_delay 0
+set g_balance_oknex_secondary_edgedamage 10
+set g_balance_oknex_secondary_force 0
+set g_balance_oknex_secondary_force_zscale 1
+set g_balance_oknex_secondary_lifetime 5
+set g_balance_oknex_secondary_radius 60
+set g_balance_oknex_secondary_refire 0
+set g_balance_oknex_secondary_refire_type 0
+set g_balance_oknex_secondary_shotangle 0
+set g_balance_oknex_secondary_speed 6000
+set g_balance_oknex_secondary_spread 0
+set g_balance_oknex_switchdelay_drop 0.2
+set g_balance_oknex_switchdelay_raise 0.2
+set g_balance_oknex_weaponreplace ""
+set g_balance_oknex_weaponstart 0
+set g_balance_oknex_weaponstartoverride -1
+set g_balance_oknex_weaponthrowable 1
+// }}}
+// {{{ #24: Overkill Rocket Propelled Chainsaw (MUTATOR WEAPON)
set g_balance_okrpc_primary_ammo 10
set g_balance_okrpc_primary_animtime 1
set g_balance_okrpc_primary_damage 150
set g_balance_okrpc_secondary_delay 0
set g_balance_okrpc_secondary_edgedamage 12.5
set g_balance_okrpc_secondary_force 300
+set g_balance_okrpc_secondary_force_zscale 1
set g_balance_okrpc_secondary_lifetime 5
set g_balance_okrpc_secondary_radius 70
set g_balance_okrpc_secondary_refire 0.7
set g_balance_okrpc_weaponstartoverride 0
set g_balance_okrpc_weaponthrowable 0
// }}}
+// {{{ #25: Overkill Shotgun (MUTATOR WEAPON)
+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_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_force_zscale 1
+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
+// }}}
set g_balance_shotgun_reload_ammo 0
set g_balance_shotgun_reload_time 2
set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_alt_animtime 0.2
+set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_secondary_animtime 1.15
set g_balance_shotgun_secondary_damage 70
set g_balance_shotgun_secondary_force 200
set g_balance_shotgun_secondary_melee_time 0.15
set g_balance_shotgun_secondary_melee_traces 10
set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_switchdelay_drop 0
set g_balance_shotgun_switchdelay_raise 0
set g_balance_shotgun_weaponreplace ""
set g_balance_shotgun_weaponstartoverride -1
set g_balance_shotgun_weaponthrowable 1
// }}}
-// {{{ #3: Machine Gun
+// {{{ #3: MachineGun
set g_balance_machinegun_burst 3
set g_balance_machinegun_burst_ammo 3
set g_balance_machinegun_burst_animtime 0.3
set g_balance_machinegun_burst_refire 0.06
set g_balance_machinegun_burst_refire2 0.45
-set g_balance_machinegun_burst_speed 0
+set g_balance_machinegun_burst_spread 0.03
set g_balance_machinegun_first 1
set g_balance_machinegun_first_ammo 1
set g_balance_machinegun_first_damage 14
// }}}
// {{{ #8: Vortex
set g_balance_vortex_charge 0
+set g_balance_vortex_charge_always 0
set g_balance_vortex_charge_animlimit 0.5
set g_balance_vortex_charge_limit 1
set g_balance_vortex_charge_maxspeed 800
set g_balance_vaporizer_secondary_delay 0
set g_balance_vaporizer_secondary_edgedamage 12.5
set g_balance_vaporizer_secondary_force 400
+set g_balance_vaporizer_secondary_force_zscale 1.2
set g_balance_vaporizer_secondary_lifetime 5
set g_balance_vaporizer_secondary_radius 70
set g_balance_vaporizer_secondary_refire 0.7
set g_balance_seeker_weaponstartoverride -1
set g_balance_seeker_weaponthrowable 1
// }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
set g_balance_shockwave_blast_animtime 0.3
set g_balance_shockwave_blast_damage 40
set g_balance_shockwave_blast_distance 1000
set g_balance_arc_beam_healing_aps 50
set g_balance_arc_beam_healing_hmax 150
set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_cooldown 2.5
-set g_balance_arc_cooldown_release 0
-set g_balance_arc_overheat_max 5
-set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 0
-set g_balance_arc_burst_heat 5
set g_balance_arc_beam_maxangle 10
set g_balance_arc_beam_nonplayerdamage 80
set g_balance_arc_beam_range 1000
set g_balance_arc_burst_damage 250
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_burst_healing_hps 100
+set g_balance_arc_burst_heat 5
+set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 0
+set g_balance_arc_overheat_max 5
+set g_balance_arc_overheat_min 3
set g_balance_arc_switchdelay_drop 0
set g_balance_arc_switchdelay_raise 0
set g_balance_arc_weaponreplace ""
set g_balance_arc_weaponstartoverride -1
set g_balance_arc_weaponthrowable 1
// }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #21: Overkill Heavy Machine Gun (MUTATOR WEAPON)
set g_balance_okhmg_primary_ammo 1
set g_balance_okhmg_primary_damage 30
set g_balance_okhmg_primary_force 10
set g_balance_okhmg_secondary_delay 0
set g_balance_okhmg_secondary_edgedamage 12.5
set g_balance_okhmg_secondary_force 300
+set g_balance_okhmg_secondary_force_zscale 1
set g_balance_okhmg_secondary_lifetime 5
set g_balance_okhmg_secondary_radius 70
set g_balance_okhmg_secondary_refire 0.7
set g_balance_okhmg_weaponstartoverride 0
set g_balance_okhmg_weaponthrowable 0
// }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
+// {{{ #22: Overkill MachineGun (MUTATOR WEAPON)
+set g_balance_okmachinegun_primary_ammo 1
+set g_balance_okmachinegun_primary_damage 10
+set g_balance_okmachinegun_primary_force 3
+set g_balance_okmachinegun_primary_refire 0.1
+set g_balance_okmachinegun_primary_solidpenetration 13.1
+set g_balance_okmachinegun_primary_spread_add 0.012
+set g_balance_okmachinegun_primary_spread_max 0.05
+set g_balance_okmachinegun_primary_spread_min 0.02
+set g_balance_okmachinegun_reload_ammo 60
+set g_balance_okmachinegun_reload_time 2
+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_force_zscale 1
+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_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
+// }}}
+// {{{ #23: Overkill Nex (MUTATOR WEAPON)
+set g_balance_oknex_charge 1
+set g_balance_oknex_charge_animlimit 0.5
+set g_balance_oknex_charge_limit 1
+set g_balance_oknex_charge_maxspeed 800
+set g_balance_oknex_charge_mindmg 40
+set g_balance_oknex_charge_minspeed 400
+set g_balance_oknex_charge_rate 0.6
+set g_balance_oknex_charge_rot_pause 0
+set g_balance_oknex_charge_rot_rate 0
+set g_balance_oknex_charge_shot_multiplier 0
+set g_balance_oknex_charge_start 0.5
+set g_balance_oknex_charge_velocity_rate 0
+set g_balance_oknex_primary_ammo 6
+set g_balance_oknex_primary_animtime 0.4
+set g_balance_oknex_primary_damage 80
+set g_balance_oknex_primary_damagefalloff_forcehalflife 0
+set g_balance_oknex_primary_damagefalloff_halflife 0
+set g_balance_oknex_primary_damagefalloff_maxdist 0
+set g_balance_oknex_primary_damagefalloff_mindist 0
+set g_balance_oknex_primary_force 400
+set g_balance_oknex_primary_refire 1.5
+set g_balance_oknex_reload_ammo 0
+set g_balance_oknex_reload_time 2
+set g_balance_oknex_secondary 0
+set g_balance_oknex_secondary_ammo 2
+set g_balance_oknex_secondary_animtime 0
+set g_balance_oknex_secondary_chargepool 0
+set g_balance_oknex_secondary_chargepool_pause_regen 1
+set g_balance_oknex_secondary_chargepool_regen 0.15
+set g_balance_oknex_secondary_damage 0
+set g_balance_oknex_secondary_damagefalloff_forcehalflife 0
+set g_balance_oknex_secondary_damagefalloff_halflife 0
+set g_balance_oknex_secondary_damagefalloff_maxdist 0
+set g_balance_oknex_secondary_damagefalloff_mindist 0
+set g_balance_oknex_secondary_delay 0
+set g_balance_oknex_secondary_edgedamage 10
+set g_balance_oknex_secondary_force 0
+set g_balance_oknex_secondary_force_zscale 1
+set g_balance_oknex_secondary_lifetime 5
+set g_balance_oknex_secondary_radius 60
+set g_balance_oknex_secondary_refire 0
+set g_balance_oknex_secondary_refire_type 0
+set g_balance_oknex_secondary_shotangle 0
+set g_balance_oknex_secondary_speed 6000
+set g_balance_oknex_secondary_spread 0
+set g_balance_oknex_switchdelay_drop 0.2
+set g_balance_oknex_switchdelay_raise 0.2
+set g_balance_oknex_weaponreplace ""
+set g_balance_oknex_weaponstart 0
+set g_balance_oknex_weaponstartoverride -1
+set g_balance_oknex_weaponthrowable 1
+// }}}
+// {{{ #24: Overkill Rocket Propelled Chainsaw (MUTATOR WEAPON)
set g_balance_okrpc_primary_ammo 10
set g_balance_okrpc_primary_animtime 1
set g_balance_okrpc_primary_damage 150
set g_balance_okrpc_secondary_delay 0
set g_balance_okrpc_secondary_edgedamage 12.5
set g_balance_okrpc_secondary_force 300
+set g_balance_okrpc_secondary_force_zscale 1
set g_balance_okrpc_secondary_lifetime 5
set g_balance_okrpc_secondary_radius 70
set g_balance_okrpc_secondary_refire 0.7
set g_balance_okrpc_weaponstartoverride 0
set g_balance_okrpc_weaponthrowable 0
// }}}
+// {{{ #25: Overkill Shotgun (MUTATOR WEAPON)
+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_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_force_zscale 1
+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
+// }}}
set g_balance_shotgun_reload_ammo 0
set g_balance_shotgun_reload_time 2
set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_alt_animtime 0.2
+set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_secondary_animtime 1.15
set g_balance_shotgun_secondary_damage 70
set g_balance_shotgun_secondary_force 200
set g_balance_shotgun_secondary_melee_time 0.15
set g_balance_shotgun_secondary_melee_traces 10
set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_switchdelay_drop 0.2
set g_balance_shotgun_switchdelay_raise 0.2
set g_balance_shotgun_weaponreplace ""
set g_balance_shotgun_weaponstartoverride -1
set g_balance_shotgun_weaponthrowable 1
// }}}
-// {{{ #3: Machine Gun
+// {{{ #3: MachineGun
set g_balance_machinegun_burst 3
set g_balance_machinegun_burst_ammo 3
set g_balance_machinegun_burst_animtime 0.3
set g_balance_machinegun_burst_refire 0.06
set g_balance_machinegun_burst_refire2 0.45
-set g_balance_machinegun_burst_speed 0
+set g_balance_machinegun_burst_spread 0
set g_balance_machinegun_first 1
set g_balance_machinegun_first_ammo 1
set g_balance_machinegun_first_damage 14
// }}}
// {{{ #8: Vortex
set g_balance_vortex_charge 1
+set g_balance_vortex_charge_always 0
set g_balance_vortex_charge_animlimit 0.5
set g_balance_vortex_charge_limit 1
set g_balance_vortex_charge_maxspeed 800
set g_balance_vaporizer_secondary_delay 0
set g_balance_vaporizer_secondary_edgedamage 12.5
set g_balance_vaporizer_secondary_force 400
+set g_balance_vaporizer_secondary_force_zscale 1.2
set g_balance_vaporizer_secondary_lifetime 5
set g_balance_vaporizer_secondary_radius 70
set g_balance_vaporizer_secondary_refire 0.7
set g_balance_seeker_weaponstartoverride -1
set g_balance_seeker_weaponthrowable 1
// }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
set g_balance_shockwave_blast_animtime 0.3
set g_balance_shockwave_blast_damage 40
set g_balance_shockwave_blast_distance 1000
set g_balance_arc_beam_healing_aps 50
set g_balance_arc_beam_healing_hmax 150
set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_cooldown 2.5
-set g_balance_arc_cooldown_release 0
-set g_balance_arc_overheat_max 5
-set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 0
-set g_balance_arc_burst_heat 5
set g_balance_arc_beam_maxangle 10
set g_balance_arc_beam_nonplayerdamage 80
set g_balance_arc_beam_range 1500
set g_balance_arc_burst_damage 250
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_burst_healing_hps 100
+set g_balance_arc_burst_heat 5
+set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 0
+set g_balance_arc_overheat_max 5
+set g_balance_arc_overheat_min 3
set g_balance_arc_switchdelay_drop 0.2
set g_balance_arc_switchdelay_raise 0.2
set g_balance_arc_weaponreplace ""
set g_balance_arc_weaponstartoverride -1
set g_balance_arc_weaponthrowable 1
// }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #21: Overkill Heavy Machine Gun (MUTATOR WEAPON)
set g_balance_okhmg_primary_ammo 1
set g_balance_okhmg_primary_damage 30
set g_balance_okhmg_primary_force 10
set g_balance_okhmg_primary_refire 0.05
-set g_balance_okhmg_primary_solidpenetration 32
+set g_balance_okhmg_primary_solidpenetration 127
set g_balance_okhmg_primary_spread_add 0.005
set g_balance_okhmg_primary_spread_max 0.06
set g_balance_okhmg_primary_spread_min 0.01
set g_balance_okhmg_secondary_damage 25
set g_balance_okhmg_secondary_delay 0
set g_balance_okhmg_secondary_edgedamage 12.5
-set g_balance_okhmg_secondary_force 300
+set g_balance_okhmg_secondary_force 360
+set g_balance_okhmg_secondary_force_zscale 1
set g_balance_okhmg_secondary_lifetime 5
set g_balance_okhmg_secondary_radius 70
set g_balance_okhmg_secondary_refire 0.7
set g_balance_okhmg_weaponstartoverride 0
set g_balance_okhmg_weaponthrowable 0
// }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
-set g_balance_okrpc_primary_ammo 10
-set g_balance_okrpc_primary_animtime 1
-set g_balance_okrpc_primary_damage 150
-set g_balance_okrpc_primary_damage2 500
-set g_balance_okrpc_primary_damageforcescale 2
-set g_balance_okrpc_primary_edgedamage 50
-set g_balance_okrpc_primary_force 400
-set g_balance_okrpc_primary_health 25
-set g_balance_okrpc_primary_lifetime 30
-set g_balance_okrpc_primary_radius 300
-set g_balance_okrpc_primary_refire 1
-set g_balance_okrpc_primary_speed 2500
-set g_balance_okrpc_primary_speedaccel 5000
-set g_balance_okrpc_reload_ammo 10
-set g_balance_okrpc_reload_time 1
-set g_balance_okrpc_secondary_ammo 0
-set g_balance_okrpc_secondary_animtime 0.2
-set g_balance_okrpc_secondary_damage 25
-set g_balance_okrpc_secondary_delay 0
-set g_balance_okrpc_secondary_edgedamage 12.5
-set g_balance_okrpc_secondary_force 300
-set g_balance_okrpc_secondary_lifetime 5
-set g_balance_okrpc_secondary_radius 70
-set g_balance_okrpc_secondary_refire 0.7
-set g_balance_okrpc_secondary_refire_type 1
-set g_balance_okrpc_secondary_shotangle 0
-set g_balance_okrpc_secondary_speed 6000
-set g_balance_okrpc_secondary_spread 0
-set g_balance_okrpc_switchdelay_drop 0.2
-set g_balance_okrpc_switchdelay_raise 0.2
-set g_balance_okrpc_weaponreplace ""
-set g_balance_okrpc_weaponstart 0
-set g_balance_okrpc_weaponstartoverride 0
-set g_balance_okrpc_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_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
+// {{{ #22: Overkill MachineGun (MUTATOR WEAPON)
set g_balance_okmachinegun_primary_ammo 1
set g_balance_okmachinegun_primary_damage 25
set g_balance_okmachinegun_primary_force 5
set g_balance_okmachinegun_primary_refire 0.1
-set g_balance_okmachinegun_primary_solidpenetration 63
+set g_balance_okmachinegun_primary_solidpenetration 100
set g_balance_okmachinegun_primary_spread_add 0.012
set g_balance_okmachinegun_primary_spread_max 0.05
set g_balance_okmachinegun_primary_spread_min 0
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_force 360
+set g_balance_okmachinegun_secondary_force_zscale 1
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_weaponstartoverride -1
set g_balance_okmachinegun_weaponthrowable 1
// }}}
-// {{{ Overkill Nex
+// {{{ #23: Overkill Nex (MUTATOR WEAPON)
set g_balance_oknex_charge 0
set g_balance_oknex_charge_animlimit 0.5
set g_balance_oknex_charge_limit 1
set g_balance_oknex_secondary_damagefalloff_halflife 0
set g_balance_oknex_secondary_damagefalloff_maxdist 0
set g_balance_oknex_secondary_damagefalloff_mindist 0
-set g_balance_oknex_secondary_force 300
-set g_balance_oknex_secondary_refire 0.7
-set g_balance_oknex_secondary_refire_type 1
set g_balance_oknex_secondary_delay 0
set g_balance_oknex_secondary_edgedamage 12.5
+set g_balance_oknex_secondary_force 360
+set g_balance_oknex_secondary_force_zscale 1
set g_balance_oknex_secondary_lifetime 5
set g_balance_oknex_secondary_radius 70
+set g_balance_oknex_secondary_refire 0.7
+set g_balance_oknex_secondary_refire_type 1
set g_balance_oknex_secondary_shotangle 0
set g_balance_oknex_secondary_speed 6000
set g_balance_oknex_secondary_spread 0
set g_balance_oknex_weaponstartoverride -1
set g_balance_oknex_weaponthrowable 1
// }}}
+// {{{ #24: Overkill Rocket Propelled Chainsaw (MUTATOR WEAPON)
+set g_balance_okrpc_primary_ammo 10
+set g_balance_okrpc_primary_animtime 1
+set g_balance_okrpc_primary_damage 150
+set g_balance_okrpc_primary_damage2 500
+set g_balance_okrpc_primary_damageforcescale 2
+set g_balance_okrpc_primary_edgedamage 50
+set g_balance_okrpc_primary_force 400
+set g_balance_okrpc_primary_health 25
+set g_balance_okrpc_primary_lifetime 30
+set g_balance_okrpc_primary_radius 300
+set g_balance_okrpc_primary_refire 1
+set g_balance_okrpc_primary_speed 2500
+set g_balance_okrpc_primary_speedaccel 5000
+set g_balance_okrpc_reload_ammo 10
+set g_balance_okrpc_reload_time 1
+set g_balance_okrpc_secondary_ammo 0
+set g_balance_okrpc_secondary_animtime 0.2
+set g_balance_okrpc_secondary_damage 25
+set g_balance_okrpc_secondary_delay 0
+set g_balance_okrpc_secondary_edgedamage 12.5
+set g_balance_okrpc_secondary_force 360
+set g_balance_okrpc_secondary_force_zscale 1
+set g_balance_okrpc_secondary_lifetime 5
+set g_balance_okrpc_secondary_radius 70
+set g_balance_okrpc_secondary_refire 0.7
+set g_balance_okrpc_secondary_refire_type 1
+set g_balance_okrpc_secondary_shotangle 0
+set g_balance_okrpc_secondary_speed 6000
+set g_balance_okrpc_secondary_spread 0
+set g_balance_okrpc_switchdelay_drop 0.2
+set g_balance_okrpc_switchdelay_raise 0.2
+set g_balance_okrpc_weaponreplace ""
+set g_balance_okrpc_weaponstart 0
+set g_balance_okrpc_weaponstartoverride 0
+set g_balance_okrpc_weaponthrowable 0
+// }}}
+// {{{ #25: Overkill Shotgun (MUTATOR WEAPON)
+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_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 360
+set g_balance_okshotgun_secondary_force_zscale 1
+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
+// }}}
set g_balance_shotgun_reload_ammo 0
set g_balance_shotgun_reload_time 2
set g_balance_shotgun_secondary 1
+set g_balance_shotgun_secondary_alt_animtime 0.2
+set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_secondary_animtime 1.15
set g_balance_shotgun_secondary_damage 70
set g_balance_shotgun_secondary_force 200
set g_balance_shotgun_secondary_melee_time 0.15
set g_balance_shotgun_secondary_melee_traces 10
set g_balance_shotgun_secondary_refire 1.25
-set g_balance_shotgun_secondary_alt_animtime 0.2
-set g_balance_shotgun_secondary_alt_refire 1.2
set g_balance_shotgun_switchdelay_drop 0.2
set g_balance_shotgun_switchdelay_raise 0.2
set g_balance_shotgun_weaponreplace ""
set g_balance_shotgun_weaponstartoverride -1
set g_balance_shotgun_weaponthrowable 1
// }}}
-// {{{ #3: Machine Gun
+// {{{ #3: MachineGun
set g_balance_machinegun_burst 3
set g_balance_machinegun_burst_ammo 3
set g_balance_machinegun_burst_animtime 0.3
set g_balance_machinegun_burst_refire 0.06
set g_balance_machinegun_burst_refire2 0.45
-set g_balance_machinegun_burst_speed 0
+set g_balance_machinegun_burst_spread 0
set g_balance_machinegun_first 1
set g_balance_machinegun_first_ammo 1
set g_balance_machinegun_first_damage 14
// }}}
// {{{ #8: Vortex
set g_balance_vortex_charge 1
+set g_balance_vortex_charge_always 0
set g_balance_vortex_charge_animlimit 0.5
set g_balance_vortex_charge_limit 1
set g_balance_vortex_charge_maxspeed 800
set g_balance_vaporizer_secondary_delay 0
set g_balance_vaporizer_secondary_edgedamage 12.5
set g_balance_vaporizer_secondary_force 400
+set g_balance_vaporizer_secondary_force_zscale 1.2
set g_balance_vaporizer_secondary_lifetime 5
set g_balance_vaporizer_secondary_radius 70
set g_balance_vaporizer_secondary_refire 0.7
set g_balance_seeker_weaponstartoverride -1
set g_balance_seeker_weaponthrowable 1
// }}}
-// {{{ #19: Shockwave (MUTATOR WEAPON)
+// {{{ #19: Shockwave
set g_balance_shockwave_blast_animtime 0.3
set g_balance_shockwave_blast_damage 40
set g_balance_shockwave_blast_distance 1000
set g_balance_arc_beam_healing_aps 50
set g_balance_arc_beam_healing_hmax 150
set g_balance_arc_beam_healing_hps 50
-set g_balance_arc_cooldown 2.5
-set g_balance_arc_cooldown_release 0
-set g_balance_arc_overheat_max 5
-set g_balance_arc_overheat_min 3
set g_balance_arc_beam_heat 0
-set g_balance_arc_burst_heat 5
set g_balance_arc_beam_maxangle 10
set g_balance_arc_beam_nonplayerdamage 80
set g_balance_arc_beam_range 1000
set g_balance_arc_burst_damage 250
set g_balance_arc_burst_healing_aps 100
set g_balance_arc_burst_healing_hps 100
+set g_balance_arc_burst_heat 5
+set g_balance_arc_cooldown 2.5
+set g_balance_arc_cooldown_release 0
+set g_balance_arc_overheat_max 5
+set g_balance_arc_overheat_min 3
set g_balance_arc_switchdelay_drop 0.2
set g_balance_arc_switchdelay_raise 0.2
set g_balance_arc_weaponreplace ""
set g_balance_arc_weaponstartoverride -1
set g_balance_arc_weaponthrowable 1
// }}}
-// {{{ #21: Overkill Heavy Machine Gun
+// {{{ #21: Overkill Heavy Machine Gun (MUTATOR WEAPON)
set g_balance_okhmg_primary_ammo 1
set g_balance_okhmg_primary_damage 30
set g_balance_okhmg_primary_force 10
set g_balance_okhmg_secondary_delay 0
set g_balance_okhmg_secondary_edgedamage 12.5
set g_balance_okhmg_secondary_force 300
+set g_balance_okhmg_secondary_force_zscale 1
set g_balance_okhmg_secondary_lifetime 5
set g_balance_okhmg_secondary_radius 70
set g_balance_okhmg_secondary_refire 0.7
set g_balance_okhmg_weaponstartoverride 0
set g_balance_okhmg_weaponthrowable 0
// }}}
-// {{{ #22: Overkill Rocket Propelled Chainsaw
+// {{{ #22: Overkill MachineGun (MUTATOR WEAPON)
+set g_balance_okmachinegun_primary_ammo 1
+set g_balance_okmachinegun_primary_damage 10
+set g_balance_okmachinegun_primary_force 3
+set g_balance_okmachinegun_primary_refire 0.1
+set g_balance_okmachinegun_primary_solidpenetration 13.1
+set g_balance_okmachinegun_primary_spread_add 0.012
+set g_balance_okmachinegun_primary_spread_max 0.05
+set g_balance_okmachinegun_primary_spread_min 0.02
+set g_balance_okmachinegun_reload_ammo 60
+set g_balance_okmachinegun_reload_time 2
+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_force_zscale 1
+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_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
+// }}}
+// {{{ #23: Overkill Nex (MUTATOR WEAPON)
+set g_balance_oknex_charge 1
+set g_balance_oknex_charge_animlimit 0.5
+set g_balance_oknex_charge_limit 1
+set g_balance_oknex_charge_maxspeed 800
+set g_balance_oknex_charge_mindmg 40
+set g_balance_oknex_charge_minspeed 400
+set g_balance_oknex_charge_rate 0.6
+set g_balance_oknex_charge_rot_pause 0
+set g_balance_oknex_charge_rot_rate 0
+set g_balance_oknex_charge_shot_multiplier 0
+set g_balance_oknex_charge_start 0.5
+set g_balance_oknex_charge_velocity_rate 0
+set g_balance_oknex_primary_ammo 6
+set g_balance_oknex_primary_animtime 0.4
+set g_balance_oknex_primary_damage 80
+set g_balance_oknex_primary_damagefalloff_forcehalflife 0
+set g_balance_oknex_primary_damagefalloff_halflife 0
+set g_balance_oknex_primary_damagefalloff_maxdist 0
+set g_balance_oknex_primary_damagefalloff_mindist 0
+set g_balance_oknex_primary_force 400
+set g_balance_oknex_primary_refire 1.5
+set g_balance_oknex_reload_ammo 0
+set g_balance_oknex_reload_time 2
+set g_balance_oknex_secondary 0
+set g_balance_oknex_secondary_ammo 2
+set g_balance_oknex_secondary_animtime 0
+set g_balance_oknex_secondary_chargepool 0
+set g_balance_oknex_secondary_chargepool_pause_regen 1
+set g_balance_oknex_secondary_chargepool_regen 0.15
+set g_balance_oknex_secondary_damage 0
+set g_balance_oknex_secondary_damagefalloff_forcehalflife 0
+set g_balance_oknex_secondary_damagefalloff_halflife 0
+set g_balance_oknex_secondary_damagefalloff_maxdist 0
+set g_balance_oknex_secondary_damagefalloff_mindist 0
+set g_balance_oknex_secondary_delay 0
+set g_balance_oknex_secondary_edgedamage 10
+set g_balance_oknex_secondary_force 0
+set g_balance_oknex_secondary_force_zscale 1
+set g_balance_oknex_secondary_lifetime 5
+set g_balance_oknex_secondary_radius 60
+set g_balance_oknex_secondary_refire 0
+set g_balance_oknex_secondary_refire_type 0
+set g_balance_oknex_secondary_shotangle 0
+set g_balance_oknex_secondary_speed 6000
+set g_balance_oknex_secondary_spread 0
+set g_balance_oknex_switchdelay_drop 0.2
+set g_balance_oknex_switchdelay_raise 0.2
+set g_balance_oknex_weaponreplace ""
+set g_balance_oknex_weaponstart 0
+set g_balance_oknex_weaponstartoverride -1
+set g_balance_oknex_weaponthrowable 1
+// }}}
+// {{{ #24: Overkill Rocket Propelled Chainsaw (MUTATOR WEAPON)
set g_balance_okrpc_primary_ammo 10
set g_balance_okrpc_primary_animtime 1
set g_balance_okrpc_primary_damage 150
set g_balance_okrpc_secondary_delay 0
set g_balance_okrpc_secondary_edgedamage 12.5
set g_balance_okrpc_secondary_force 300
+set g_balance_okrpc_secondary_force_zscale 1
set g_balance_okrpc_secondary_lifetime 5
set g_balance_okrpc_secondary_radius 70
set g_balance_okrpc_secondary_refire 0.7
set g_balance_okrpc_weaponstartoverride 0
set g_balance_okrpc_weaponthrowable 0
// }}}
+// {{{ #25: Overkill Shotgun (MUTATOR WEAPON)
+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_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_force_zscale 1
+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
+// }}}
set g_warmup_start_ammo_plasma 90 "starting values when being in warmup-stage"
set g_warmup_start_ammo_fuel 0 "starting values when being in warmup-stage"
set g_lms_start_health 200
-set g_lms_start_armor 200
+set g_lms_start_armor 100
set g_lms_start_ammo_shells 60
set g_lms_start_ammo_nails 320
set g_lms_start_ammo_rockets 160
set g_balance_pause_armor_rot_spawn 5
set g_balance_armor_regenstable 100
set g_balance_armor_rotstable 0
-set g_balance_armor_limit 200
+set g_balance_armor_limit 100
set g_balance_armor_blockpercent 0.6
set g_balance_fuel_regen 0.1 "fuel regeneration (only applies if the player owns IT_FUEL_REGEN)"
set g_balance_fuel_regenlinear 0
bind F11 disconnect
bind F12 screenshot
bind F4 ready
-bind ALT +showaccuracy
// Gamepad defaults. Tested with Logitech Rumblepad 2, I hope similar ones works as well.
bind JOY1 "+crouch"
seta "userbind32_press" ""; seta "userbind32_release" ""; seta "userbind32_description" ""
alias _userbind_call "${$1}"
alias +userbind "_userbind_call userbind${1}_press"
-alias -userbind "_userbind_call userbind${1}_release"
\ No newline at end of file
+alias -userbind "_userbind_call userbind${1}_release"
set g_ctf_stalemate_endcondition 1 "condition for stalemate mode to be finished: 1 = If ONE flag is no longer stale, 2 = If BOTH flags are no longer stale"
set g_ctf_stalemate_time 60 "time for each flag until stalemate mode is activated"
set g_ctf_flagcarrier_waypointforenemy_spotting 1 "show the enemy flagcarrier location if a team mate presses +use to spot them"
-set g_ctf_dropped_capture_delay 1 "dropped capture delay"
+set g_ctf_dropped_capture_delay 1.5 "autocapture delay when flag is thrown onto the base - counted from throw, not landing"
set g_ctf_dropped_capture_radius 100 "allow dropped flags to be automatically captured by base flags if the dropped flag is within this radius of it"
set g_ctf_flag_damageforcescale 2
set g_ctf_portalteleport 0 "allow flag carriers to go through portals made in portal gun without dropping the flag"
// ==========
// overkill
// ==========
-set g_overkill 0 "internal cvar, to enable overkill, use `exec ruleset-overkill.cfg`"
+set g_overkill 0 "internal cvar, to enable overkill, use `exec ruleset-overkill.cfg`"
set g_overkill_weapons 0 "Whether to enable overkill weapons outside of overkill ruleset."
-set g_overkill_powerups_replace 1
-set g_overkill_itemwaypoints 1
+set g_overkill_powerups_replace 1 "replace strength and shield with HMG and RPC"
+set g_overkill_itemwaypoints 1 "show waypoints with timer before health and armor spawns"
set g_overkill_filter_healthmega 0
-set g_overkill_filter_armormedium 0
-set g_overkill_filter_armorbig 0
+set g_overkill_filter_armormedium 1
+set g_overkill_filter_armorbig 1
set g_overkill_filter_armormega 0
g_mod_physics Overkill
sv_gravity 800
-sv_maxspeed 400
+sv_maxspeed 360
sv_maxairspeed 360
sv_stopspeed 100
sv_aircontrol_power 2
sv_aircontrol_backwards 0
sv_aircontrol_sidewards 0
-sv_airspeedlimit_nonqw 900
+sv_airspeedlimit_nonqw 800
sv_warsowbunny_turnaccel 0
sv_warsowbunny_accel 0.1593
sv_warsowbunny_topspeed 925
float autocvar_cl_announcer_maptime = 3;
bool autocvar_cl_autodemo_delete;
bool autocvar_cl_autodemo_delete_keeprecords;
-bool autocvar_cl_casings;
float autocvar_cl_casings_bronze_time;
int autocvar_cl_casings_maxcount = 100;
float autocvar_cl_casings_shell_time;
float autocvar_hud_panel_mapvote_highlight_border = 1;
bool autocvar_hud_panel_modicons;
int autocvar_hud_panel_modicons_ca_layout;
-int autocvar_hud_panel_modicons_dom_layout;
int autocvar_hud_panel_modicons_freezetag_layout;
bool autocvar_hud_panel_notify;
float autocvar_hud_panel_notify_fadetime;
// Mod icons (#10)
-bool mod_active; // is there any active mod icon?
-
void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
{
TC(int, layout); TC(int, i);
}
}
-// CTF HUD modicon section
-int redflag_prevframe, blueflag_prevframe, yellowflag_prevframe, pinkflag_prevframe, neutralflag_prevframe; // status during previous frame
-int redflag_prevstatus, blueflag_prevstatus, yellowflag_prevstatus, pinkflag_prevstatus, neutralflag_prevstatus; // last remembered status
-float redflag_statuschange_time, blueflag_statuschange_time, yellowflag_statuschange_time, pinkflag_statuschange_time, neutralflag_statuschange_time; // time when the status changed
-
-void HUD_Mod_CTF_Reset()
-{
- redflag_prevstatus = blueflag_prevstatus = yellowflag_prevstatus = pinkflag_prevstatus = neutralflag_prevstatus = 0;
- redflag_prevframe = blueflag_prevframe = yellowflag_prevframe = pinkflag_prevframe = neutralflag_prevframe = 0;
- redflag_statuschange_time = blueflag_statuschange_time = yellowflag_statuschange_time = pinkflag_statuschange_time = neutralflag_statuschange_time = 0;
-}
-
-int autocvar__teams_available;
-void HUD_Mod_CTF(vector pos, vector mySize)
-{
- vector redflag_pos, blueflag_pos, yellowflag_pos, pinkflag_pos, neutralflag_pos;
- vector flag_size;
- float f; // every function should have that
-
- int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
- float redflag_statuschange_elapsedtime = 0, blueflag_statuschange_elapsedtime = 0, yellowflag_statuschange_elapsedtime = 0, pinkflag_statuschange_elapsedtime = 0, neutralflag_statuschange_elapsedtime = 0; // time since the status changed
- bool ctf_oneflag; // one-flag CTF mode enabled/disabled
- bool ctf_stalemate; // currently in stalemate
- int stat_items = STAT(CTF_FLAGSTATUS);
- float fs, fs2, fs3, size1, size2;
- vector e1, e2;
-
- int nteams = autocvar__teams_available;
-
- redflag = (stat_items/CTF_RED_FLAG_TAKEN) & 3;
- blueflag = (stat_items/CTF_BLUE_FLAG_TAKEN) & 3;
- yellowflag = (stat_items/CTF_YELLOW_FLAG_TAKEN) & 3;
- pinkflag = (stat_items/CTF_PINK_FLAG_TAKEN) & 3;
- neutralflag = (stat_items/CTF_NEUTRAL_FLAG_TAKEN) & 3;
-
- ctf_oneflag = (stat_items & CTF_FLAG_NEUTRAL);
-
- ctf_stalemate = (stat_items & CTF_STALEMATE);
-
- mod_active = (redflag || blueflag || yellowflag || pinkflag || neutralflag || (stat_items & CTF_SHIELDED));
-
- if (autocvar__hud_configure) {
- redflag = 1;
- blueflag = 2;
- if (nteams & BIT(2))
- yellowflag = 2;
- if (nteams & BIT(3))
- pinkflag = 3;
- ctf_oneflag = neutralflag = 0; // disable neutral flag in hud editor?
- }
-
- // when status CHANGES, set old status into prevstatus and current status into status
- #define X(team) MACRO_BEGIN \
- if (team##flag != team##flag_prevframe) { \
- team##flag_statuschange_time = time; \
- team##flag_prevstatus = team##flag_prevframe; \
- team##flag_prevframe = team##flag; \
- } \
- team##flag_statuschange_elapsedtime = time - team##flag_statuschange_time; \
- MACRO_END
- X(red);
- X(blue);
- X(yellow);
- X(pink);
- X(neutral);
- #undef X
-
- const float BLINK_FACTOR = 0.15;
- const float BLINK_BASE = 0.85;
- // note:
- // RMS = sqrt(BLINK_BASE^2 + 0.5 * BLINK_FACTOR^2)
- // thus
- // BLINK_BASE = sqrt(RMS^2 - 0.5 * BLINK_FACTOR^2)
- // ensure RMS == 1
- const float BLINK_FREQ = 5; // circle frequency, = 2*pi*frequency in hertz
-
- #define X(team, cond) \
- string team##_icon = string_null, team##_icon_prevstatus = string_null; \
- int team##_alpha, team##_alpha_prevstatus; \
- team##_alpha = team##_alpha_prevstatus = 1; \
- MACRO_BEGIN \
- switch (team##flag) { \
- case 1: team##_icon = "flag_" #team "_taken"; break; \
- case 2: team##_icon = "flag_" #team "_lost"; break; \
- case 3: team##_icon = "flag_" #team "_carrying"; team##_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
- default: \
- if ((stat_items & CTF_SHIELDED) && (cond)) { \
- team##_icon = "flag_" #team "_shielded"; \
- } else { \
- team##_icon = string_null; \
- } \
- break; \
- } \
- switch (team##flag_prevstatus) { \
- case 1: team##_icon_prevstatus = "flag_" #team "_taken"; break; \
- case 2: team##_icon_prevstatus = "flag_" #team "_lost"; break; \
- case 3: team##_icon_prevstatus = "flag_" #team "_carrying"; team##_alpha_prevstatus = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
- default: \
- if (team##flag == 3) { \
- team##_icon_prevstatus = "flag_" #team "_carrying"; /* make it more visible */\
- } else if((stat_items & CTF_SHIELDED) && (cond)) { \
- team##_icon_prevstatus = "flag_" #team "_shielded"; \
- } else { \
- team##_icon_prevstatus = string_null; \
- } \
- break; \
- } \
- MACRO_END
- X(red, myteam != NUM_TEAM_1 && (nteams & BIT(0)));
- X(blue, myteam != NUM_TEAM_2 && (nteams & BIT(1)));
- X(yellow, myteam != NUM_TEAM_3 && (nteams & BIT(2)));
- X(pink, myteam != NUM_TEAM_4 && (nteams & BIT(3)));
- X(neutral, ctf_oneflag);
- #undef X
-
- int tcount = 2;
- if(nteams & BIT(2))
- tcount = 3;
- if(nteams & BIT(3))
- tcount = 4;
-
- if (ctf_oneflag) {
- // hacky, but these aren't needed
- red_icon = red_icon_prevstatus = blue_icon = blue_icon_prevstatus = yellow_icon = yellow_icon_prevstatus = pink_icon = pink_icon_prevstatus = string_null;
- fs = fs2 = fs3 = 1;
- } else switch (tcount) {
- default:
- case 2: fs = 0.5; fs2 = 0.5; fs3 = 0.5; break;
- case 3: fs = 1; fs2 = 0.35; fs3 = 0.35; break;
- case 4: fs = 0.75; fs2 = 0.25; fs3 = 0.5; break;
- }
-
- if (mySize_x > mySize_y) {
- size1 = mySize_x;
- size2 = mySize_y;
- e1 = eX;
- e2 = eY;
- } else {
- size1 = mySize_y;
- size2 = mySize_x;
- e1 = eY;
- e2 = eX;
- }
-
- switch (myteam) {
- default:
- case NUM_TEAM_1: {
- redflag_pos = pos;
- blueflag_pos = pos + eX * fs2 * size1;
- yellowflag_pos = pos - eX * fs2 * size1;
- pinkflag_pos = pos + eX * fs3 * size1;
- break;
- }
- case NUM_TEAM_2: {
- redflag_pos = pos + eX * fs2 * size1;
- blueflag_pos = pos;
- yellowflag_pos = pos - eX * fs2 * size1;
- pinkflag_pos = pos + eX * fs3 * size1;
- break;
- }
- case NUM_TEAM_3: {
- redflag_pos = pos + eX * fs3 * size1;
- blueflag_pos = pos - eX * fs2 * size1;
- yellowflag_pos = pos;
- pinkflag_pos = pos + eX * fs2 * size1;
- break;
- }
- case NUM_TEAM_4: {
- redflag_pos = pos - eX * fs2 * size1;
- blueflag_pos = pos + eX * fs3 * size1;
- yellowflag_pos = pos + eX * fs2 * size1;
- pinkflag_pos = pos;
- break;
- }
- }
- neutralflag_pos = pos;
- flag_size = e1 * fs * size1 + e2 * size2;
-
- #define X(team) MACRO_BEGIN \
- f = bound(0, team##flag_statuschange_elapsedtime * 2, 1); \
- if (team##_icon && ctf_stalemate) \
- drawpic_aspect_skin(team##flag_pos, "flag_stalemate", flag_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); \
- if (team##_icon_prevstatus && f < 1) \
- drawpic_aspect_skin_expanding(team##flag_pos, team##_icon_prevstatus, flag_size, '1 1 1', panel_fg_alpha * team##_alpha_prevstatus, DRAWFLAG_NORMAL, f); \
- if (team##_icon) \
- drawpic_aspect_skin(team##flag_pos, team##_icon, flag_size, '1 1 1', panel_fg_alpha * team##_alpha * f, DRAWFLAG_NORMAL); \
- MACRO_END
- X(red);
- X(blue);
- X(yellow);
- X(pink);
- X(neutral);
- #undef X
-}
-
-// Keyhunt HUD modicon section
-vector KH_SLOTS[4];
-
-void HUD_Mod_KH(vector pos, vector mySize)
-{
- mod_active = 1; // keyhunt should never hide the mod icons panel
-
- // Read current state
- int state = STAT(KH_KEYS);
- if(!state) return;
-
- int i, key_state;
- int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
- all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
-
- for(i = 0; i < 4; ++i)
- {
- key_state = (bitshift(state, i * -5) & 31) - 1;
-
- if(key_state == -1)
- continue;
-
- if(key_state == 30)
- {
- ++carrying_keys;
- key_state = myteam;
- }
-
- switch(key_state)
- {
- case NUM_TEAM_1: ++team1_keys; break;
- case NUM_TEAM_2: ++team2_keys; break;
- case NUM_TEAM_3: ++team3_keys; break;
- case NUM_TEAM_4: ++team4_keys; break;
- case 29: ++dropped_keys; break;
- }
-
- ++all_keys;
- }
-
- // Calculate slot measurements
- vector slot_size;
- if(all_keys == 4 && mySize.x * 0.5 < mySize.y && mySize.y * 0.5 < mySize.x)
- {
- // Quadratic arrangement
- slot_size = vec2(mySize.x * 0.5, mySize.y * 0.5);
- KH_SLOTS[0] = pos;
- KH_SLOTS[1] = pos + eX * slot_size.x;
- KH_SLOTS[2] = pos + eY * slot_size.y;
- KH_SLOTS[3] = pos + eX * slot_size.x + eY * slot_size.y;
- }
- else
- {
- if(mySize.x > mySize.y)
- {
- // Horizontal arrangement
- slot_size = vec2(mySize.x / all_keys, mySize.y);
- for(i = 0; i < all_keys; ++i)
- KH_SLOTS[i] = pos + eX * slot_size.x * i;
- }
- else
- {
- // Vertical arrangement
- slot_size = vec2(mySize.x, mySize.y / all_keys);
- for(i = 0; i < all_keys; ++i)
- KH_SLOTS[i] = pos + eY * slot_size.y * i;
- }
- }
-
- // Make icons blink in case of RUN HERE
-
- float alpha = 1;
- if(carrying_keys)
- {
- float blink = 0.6 + sin(2 * M_PI * time) * 0.4; // Oscillate between 0.2 and 1
- switch(myteam)
- {
- case NUM_TEAM_1: if(team1_keys == all_keys) alpha = blink; break;
- case NUM_TEAM_2: if(team2_keys == all_keys) alpha = blink; break;
- case NUM_TEAM_3: if(team3_keys == all_keys) alpha = blink; break;
- case NUM_TEAM_4: if(team4_keys == all_keys) alpha = blink; break;
- }
- }
-
- // Draw icons
-
- i = 0;
-
- while(team1_keys--)
- if(myteam == NUM_TEAM_1 && carrying_keys)
- {
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
- --carrying_keys;
- }
- else
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
- while(team2_keys--)
- if(myteam == NUM_TEAM_2 && carrying_keys)
- {
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
- --carrying_keys;
- }
- else
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
- while(team3_keys--)
- if(myteam == NUM_TEAM_3 && carrying_keys)
- {
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
- --carrying_keys;
- }
- else
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
- while(team4_keys--)
- if(myteam == NUM_TEAM_4 && carrying_keys)
- {
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
- --carrying_keys;
- }
- else
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-
- while(dropped_keys--)
- drawpic_aspect_skin(KH_SLOTS[i++], "kh_dropped", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
-}
-
-// Keepaway HUD mod icon
-int kaball_prevstatus; // last remembered status
-float kaball_statuschange_time; // time when the status changed
-
-// we don't need to reset for keepaway since it immediately
-// autocorrects prevstatus as to if the player has the ball or not
-
-void HUD_Mod_Keepaway(vector pos, vector mySize)
-{
- mod_active = 1; // keepaway should always show the mod HUD
-
- float BLINK_FACTOR = 0.15;
- float BLINK_BASE = 0.85;
- float BLINK_FREQ = 5;
- float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
-
- int stat_items = STAT(ITEMS);
- int kaball = (stat_items/IT_KEY1) & 1;
-
- if(kaball != kaball_prevstatus)
- {
- kaball_statuschange_time = time;
- kaball_prevstatus = kaball;
- }
-
- vector kaball_pos, kaball_size;
-
- if(mySize.x > mySize.y) {
- kaball_pos = pos + eX * 0.25 * mySize.x;
- kaball_size = vec2(0.5 * mySize.x, mySize.y);
- } else {
- kaball_pos = pos + eY * 0.25 * mySize.y;
- kaball_size = vec2(mySize.x, 0.5 * mySize.y);
- }
-
- float kaball_statuschange_elapsedtime = time - kaball_statuschange_time;
- float f = bound(0, kaball_statuschange_elapsedtime*2, 1);
-
- if(kaball_prevstatus && f < 1)
- drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f);
-
- if(kaball)
- drawpic_aspect_skin(pos, "keepawayball_carrying", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL);
-}
-
-
-// Nexball HUD mod icon
-void HUD_Mod_NexBall(vector pos, vector mySize)
-{
- float nb_pb_starttime, dt, p;
- int stat_items;
-
- stat_items = STAT(ITEMS);
- nb_pb_starttime = STAT(NB_METERSTART);
-
- if (stat_items & IT_KEY1)
- mod_active = 1;
- else
- mod_active = 0;
-
- //Manage the progress bar if any
- if (nb_pb_starttime > 0)
- {
- dt = (time - nb_pb_starttime) % nb_pb_period;
- // one period of positive triangle
- p = 2 * dt / nb_pb_period;
- if (p > 1)
- p = 2 - p;
-
- HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, (mySize.x <= mySize.y), 0, autocvar_hud_progressbar_nexball_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
- }
-
- if (stat_items & IT_KEY1)
- drawpic_aspect_skin(pos, "nexball_carrying", eX * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
-}
-
// Race/CTS HUD mod icons
float crecordtime_prev; // last remembered crecordtime
float crecordtime_change_time; // time when crecordtime last changed
}
}
-void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
-{
- TC(int, layout); TC(int, i);
- float stat = -1;
- string pic = "";
- vector color = '0 0 0';
- switch(i)
- {
- case 0: stat = STAT(DOM_PPS_RED); pic = "dom_icon_red"; color = '1 0 0'; break;
- case 1: stat = STAT(DOM_PPS_BLUE); pic = "dom_icon_blue"; color = '0 0 1'; break;
- case 2: stat = STAT(DOM_PPS_YELLOW); pic = "dom_icon_yellow"; color = '1 1 0'; break;
- default:
- case 3: stat = STAT(DOM_PPS_PINK); pic = "dom_icon_pink"; color = '1 0 1'; break;
- }
- float pps_ratio = 0;
- if(STAT(DOM_TOTAL_PPS))
- pps_ratio = stat / STAT(DOM_TOTAL_PPS);
-
- if(mySize.x/mySize.y > aspect_ratio)
- {
- i = aspect_ratio * mySize.y;
- myPos.x = myPos.x + (mySize.x - i) / 2;
- mySize.x = i;
- }
- else
- {
- i = 1/aspect_ratio * mySize.x;
- myPos.y = myPos.y + (mySize.y - i) / 2;
- mySize.y = i;
- }
-
- if (layout) // show text too
- {
- //draw the text
- color *= 0.5 + pps_ratio * (1 - 0.5); // half saturated color at min, full saturated at max
- if (layout == 2) // average pps
- drawstring_aspect(myPos + eX * mySize.y, ftos_decimals(stat, 2), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
- else // percentage of average pps
- drawstring_aspect(myPos + eX * mySize.y, strcat( ftos(floor(pps_ratio*100 + 0.5)), "%" ), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
- }
-
- //draw the icon
- drawpic_aspect_skin(myPos, pic, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- if (stat > 0)
- {
- drawsetcliparea(myPos.x, myPos.y + mySize.y * (1 - pps_ratio), mySize.y, mySize.y * pps_ratio);
- drawpic_aspect_skin(myPos, strcat(pic, "-highlighted"), '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
- drawresetcliparea();
- }
-}
-
-void HUD_Mod_Dom(vector myPos, vector mySize)
-{
- mod_active = 1; // required in each mod function that always shows something
-
- int layout = autocvar_hud_panel_modicons_dom_layout;
- int rows, columns;
- float aspect_ratio;
- aspect_ratio = (layout) ? 3 : 1;
- rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
- columns = ceil(team_count/rows);
-
- int i;
- float row = 0, column = 0;
- vector pos, itemSize;
- itemSize = vec2(mySize.x / columns, mySize.y / rows);
- for(i=0; i<team_count; ++i)
- {
- pos = myPos + vec2(column * itemSize.x, row * itemSize.y);
-
- DrawDomItem(pos, itemSize, aspect_ratio, layout, i);
-
- ++row;
- if(row >= rows)
- {
- row = 0;
- ++column;
- }
- }
-}
-
void HUD_ModIcons_SetFunc()
{
HUD_ModIcons_GameType = gametype.m_modicons;
#pragma once
#include "../panel.qh"
+
+bool mod_active; // is there any active mod icon?
}
if (weapon_stats < 0 && !((weapons_stat & set) || (weapons_inmap & set)))
{
- if (((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)))
+ if (it.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK))
++nHidden;
else
++disownedcnt;
int nHidden = 0; \
FOREACH(Weapons, it != WEP_Null, { \
if (weapons_stat & WepSet_FromWeapon(it)) continue; \
- if ((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) nHidden += 1; \
+ if (it.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)) nHidden += 1; \
}); \
vector table_size = HUD_GetTableSize_BestItemAR((Weapons_COUNT - 1) - nHidden, panel_size, aspect); \
columns = table_size.x; \
{
int j = 0;
FOREACH(Weapons, it != WEP_Null && it.impulse >= 0 && (it.impulse % 3 != 0) && j < 6, {
- if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED))
+ if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_SPECIALATTACK))
{
if(!panel_switchweapon || j < 4)
panel_switchweapon = it;
}
else
{
- if (((it.spawnflags & WEP_FLAG_HIDDEN) || (it.spawnflags & WEP_FLAG_MUTATORBLOCKED)) && !(weapons_stat & WepSet_FromWeapon(it)))
+ if (it.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)
+ && !(weapons_stat & WepSet_FromWeapon(it)))
+ {
continue;
+ }
}
// figure out the drawing position of weapon
{
if(wepent.activeweapon.spawnflags & WEP_FLAG_NOTRUEAIM)
return SHOTTYPE_HITWORLD;
-
+
float nudge = 1; // added to traceline target and subtracted from result TOOD(divVerent): do we still need this? Doesn't the engine do this now for us?
vector vecs, trueaimpoint, w_shotorg;
vector mi, ma, dv;
REGISTER_NET_TEMP(casings)
#ifdef SVQC
+
+.bool cvar_cl_casings;
+REPLICATE(cvar_cl_casings, bool, "cl_casings");
+
void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float randomavel, int casingtype, entity casingowner, .entity weaponentity)
{
+ if (!(CS(casingowner).cvar_cl_casings))
+ return;
+
entity wep = casingowner.(weaponentity);
vector org = casingowner.origin + casingowner.view_ofs + wep.spawnorigin.x * v_forward - wep.spawnorigin.y * v_right + wep.spawnorigin.z * v_up;
ang_z = ReadByte() * 360 / 256;
return = true;
- if (!autocvar_cl_casings) return;
-
Casing casing = RubbleNew("casing");
casing.silent = (_state & 0x80);
casing.state = (_state & 0x7F);
#include "sv_assault.qh"
+#include <common/mapobjects/func/breakable.qh>
+
.entity sprite;
#define AS_ROUND_DELAY 5
return true;
}
-spawnfunc(func_breakable);
spawnfunc(func_assault_destructible)
{
if (!g_assault) { delete(this); return; }
// most weapons arena
if (M_ARGV(0, string) == "0" || M_ARGV(0, string) == "") M_ARGV(0, string) = "most";
}
+
+MUTATOR_HOOKFUNCTION(ca, SV_ParseServerCommand)
+{
+ string cmd_name = M_ARGV(0, string);
+ if (cmd_name == "shuffleteams")
+ shuffleteams_on_reset_map = !allowed_to_spawn;
+ return false;
+}
#include <common/mutators/base.qh>
#include <server/round_handler.qh>
#include <server/miscfunctions.qh>
+#include <server/command/sv_cmd.qh>
int autocvar_g_ca_point_limit;
int autocvar_g_ca_point_leadlimit;
// generated file; do not modify
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/ctf/cl_ctf.qc>
+#endif
#ifdef SVQC
#include <common/gamemodes/gamemode/ctf/sv_ctf.qc>
#endif
// generated file; do not modify
#include <common/gamemodes/gamemode/ctf/ctf.qh>
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/ctf/cl_ctf.qh>
+#endif
#ifdef SVQC
#include <common/gamemodes/gamemode/ctf/sv_ctf.qh>
#endif
--- /dev/null
+#include "cl_ctf.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+// CTF HUD modicon section
+int redflag_prevframe, blueflag_prevframe, yellowflag_prevframe, pinkflag_prevframe, neutralflag_prevframe; // status during previous frame
+int redflag_prevstatus, blueflag_prevstatus, yellowflag_prevstatus, pinkflag_prevstatus, neutralflag_prevstatus; // last remembered status
+float redflag_statuschange_time, blueflag_statuschange_time, yellowflag_statuschange_time, pinkflag_statuschange_time, neutralflag_statuschange_time; // time when the status changed
+
+void HUD_Mod_CTF_Reset()
+{
+ redflag_prevstatus = blueflag_prevstatus = yellowflag_prevstatus = pinkflag_prevstatus = neutralflag_prevstatus = 0;
+ redflag_prevframe = blueflag_prevframe = yellowflag_prevframe = pinkflag_prevframe = neutralflag_prevframe = 0;
+ redflag_statuschange_time = blueflag_statuschange_time = yellowflag_statuschange_time = pinkflag_statuschange_time = neutralflag_statuschange_time = 0;
+}
+
+int autocvar__teams_available;
+void HUD_Mod_CTF(vector pos, vector mySize)
+{
+ vector redflag_pos, blueflag_pos, yellowflag_pos, pinkflag_pos, neutralflag_pos;
+ vector flag_size;
+ float f; // every function should have that
+
+ int redflag, blueflag, yellowflag, pinkflag, neutralflag; // current status
+ float redflag_statuschange_elapsedtime = 0, blueflag_statuschange_elapsedtime = 0, yellowflag_statuschange_elapsedtime = 0, pinkflag_statuschange_elapsedtime = 0, neutralflag_statuschange_elapsedtime = 0; // time since the status changed
+ bool ctf_oneflag; // one-flag CTF mode enabled/disabled
+ bool ctf_stalemate; // currently in stalemate
+ int stat_items = STAT(CTF_FLAGSTATUS);
+ float fs, fs2, fs3, size1, size2;
+ vector e1, e2;
+
+ int nteams = autocvar__teams_available;
+
+ redflag = (stat_items/CTF_RED_FLAG_TAKEN) & 3;
+ blueflag = (stat_items/CTF_BLUE_FLAG_TAKEN) & 3;
+ yellowflag = (stat_items/CTF_YELLOW_FLAG_TAKEN) & 3;
+ pinkflag = (stat_items/CTF_PINK_FLAG_TAKEN) & 3;
+ neutralflag = (stat_items/CTF_NEUTRAL_FLAG_TAKEN) & 3;
+
+ ctf_oneflag = (stat_items & CTF_FLAG_NEUTRAL);
+
+ ctf_stalemate = (stat_items & CTF_STALEMATE);
+
+ mod_active = (redflag || blueflag || yellowflag || pinkflag || neutralflag || (stat_items & CTF_SHIELDED));
+
+ if (autocvar__hud_configure) {
+ redflag = 1;
+ blueflag = 2;
+ if (nteams & BIT(2))
+ yellowflag = 2;
+ if (nteams & BIT(3))
+ pinkflag = 3;
+ ctf_oneflag = neutralflag = 0; // disable neutral flag in hud editor?
+ }
+
+ // when status CHANGES, set old status into prevstatus and current status into status
+ #define X(team) MACRO_BEGIN \
+ if (team##flag != team##flag_prevframe) { \
+ team##flag_statuschange_time = time; \
+ team##flag_prevstatus = team##flag_prevframe; \
+ team##flag_prevframe = team##flag; \
+ } \
+ team##flag_statuschange_elapsedtime = time - team##flag_statuschange_time; \
+ MACRO_END
+ X(red);
+ X(blue);
+ X(yellow);
+ X(pink);
+ X(neutral);
+ #undef X
+
+ const float BLINK_FACTOR = 0.15;
+ const float BLINK_BASE = 0.85;
+ // note:
+ // RMS = sqrt(BLINK_BASE^2 + 0.5 * BLINK_FACTOR^2)
+ // thus
+ // BLINK_BASE = sqrt(RMS^2 - 0.5 * BLINK_FACTOR^2)
+ // ensure RMS == 1
+ const float BLINK_FREQ = 5; // circle frequency, = 2*pi*frequency in hertz
+
+ #define X(team, cond) \
+ string team##_icon = string_null, team##_icon_prevstatus = string_null; \
+ int team##_alpha, team##_alpha_prevstatus; \
+ team##_alpha = team##_alpha_prevstatus = 1; \
+ MACRO_BEGIN \
+ switch (team##flag) { \
+ case 1: team##_icon = "flag_" #team "_taken"; break; \
+ case 2: team##_icon = "flag_" #team "_lost"; break; \
+ case 3: team##_icon = "flag_" #team "_carrying"; team##_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
+ default: \
+ if ((stat_items & CTF_SHIELDED) && (cond)) { \
+ team##_icon = "flag_" #team "_shielded"; \
+ } else { \
+ team##_icon = string_null; \
+ } \
+ break; \
+ } \
+ switch (team##flag_prevstatus) { \
+ case 1: team##_icon_prevstatus = "flag_" #team "_taken"; break; \
+ case 2: team##_icon_prevstatus = "flag_" #team "_lost"; break; \
+ case 3: team##_icon_prevstatus = "flag_" #team "_carrying"; team##_alpha_prevstatus = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ); break; \
+ default: \
+ if (team##flag == 3) { \
+ team##_icon_prevstatus = "flag_" #team "_carrying"; /* make it more visible */\
+ } else if((stat_items & CTF_SHIELDED) && (cond)) { \
+ team##_icon_prevstatus = "flag_" #team "_shielded"; \
+ } else { \
+ team##_icon_prevstatus = string_null; \
+ } \
+ break; \
+ } \
+ MACRO_END
+ X(red, myteam != NUM_TEAM_1 && (nteams & BIT(0)));
+ X(blue, myteam != NUM_TEAM_2 && (nteams & BIT(1)));
+ X(yellow, myteam != NUM_TEAM_3 && (nteams & BIT(2)));
+ X(pink, myteam != NUM_TEAM_4 && (nteams & BIT(3)));
+ X(neutral, ctf_oneflag);
+ #undef X
+
+ int tcount = 2;
+ if(nteams & BIT(2))
+ tcount = 3;
+ if(nteams & BIT(3))
+ tcount = 4;
+
+ if (ctf_oneflag) {
+ // hacky, but these aren't needed
+ red_icon = red_icon_prevstatus = blue_icon = blue_icon_prevstatus = yellow_icon = yellow_icon_prevstatus = pink_icon = pink_icon_prevstatus = string_null;
+ fs = fs2 = fs3 = 1;
+ } else switch (tcount) {
+ default:
+ case 2: fs = 0.5; fs2 = 0.5; fs3 = 0.5; break;
+ case 3: fs = 1; fs2 = 0.35; fs3 = 0.35; break;
+ case 4: fs = 0.75; fs2 = 0.25; fs3 = 0.5; break;
+ }
+
+ if (mySize_x > mySize_y) {
+ size1 = mySize_x;
+ size2 = mySize_y;
+ e1 = eX;
+ e2 = eY;
+ } else {
+ size1 = mySize_y;
+ size2 = mySize_x;
+ e1 = eY;
+ e2 = eX;
+ }
+
+ switch (myteam) {
+ default:
+ case NUM_TEAM_1: {
+ redflag_pos = pos;
+ blueflag_pos = pos + eX * fs2 * size1;
+ yellowflag_pos = pos - eX * fs2 * size1;
+ pinkflag_pos = pos + eX * fs3 * size1;
+ break;
+ }
+ case NUM_TEAM_2: {
+ redflag_pos = pos + eX * fs2 * size1;
+ blueflag_pos = pos;
+ yellowflag_pos = pos - eX * fs2 * size1;
+ pinkflag_pos = pos + eX * fs3 * size1;
+ break;
+ }
+ case NUM_TEAM_3: {
+ redflag_pos = pos + eX * fs3 * size1;
+ blueflag_pos = pos - eX * fs2 * size1;
+ yellowflag_pos = pos;
+ pinkflag_pos = pos + eX * fs2 * size1;
+ break;
+ }
+ case NUM_TEAM_4: {
+ redflag_pos = pos - eX * fs2 * size1;
+ blueflag_pos = pos + eX * fs3 * size1;
+ yellowflag_pos = pos + eX * fs2 * size1;
+ pinkflag_pos = pos;
+ break;
+ }
+ }
+ neutralflag_pos = pos;
+ flag_size = e1 * fs * size1 + e2 * size2;
+
+ #define X(team) MACRO_BEGIN \
+ f = bound(0, team##flag_statuschange_elapsedtime * 2, 1); \
+ if (team##_icon && ctf_stalemate) \
+ drawpic_aspect_skin(team##flag_pos, "flag_stalemate", flag_size, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL); \
+ if (team##_icon_prevstatus && f < 1) \
+ drawpic_aspect_skin_expanding(team##flag_pos, team##_icon_prevstatus, flag_size, '1 1 1', panel_fg_alpha * team##_alpha_prevstatus, DRAWFLAG_NORMAL, f); \
+ if (team##_icon) \
+ drawpic_aspect_skin(team##flag_pos, team##_icon, flag_size, '1 1 1', panel_fg_alpha * team##_alpha * f, DRAWFLAG_NORMAL); \
+ MACRO_END
+ X(red);
+ X(blue);
+ X(yellow);
+ X(pink);
+ X(neutral);
+ #undef X
+}
--- /dev/null
+#pragma once
+
+#include "ctf.qh"
+
+void HUD_Mod_CTF_Reset();
+void HUD_Mod_CTF(vector pos, vector mySize);
ctf_Handle_Throw(frag_target, NULL, DROP_THROW);
}
+MUTATOR_HOOKFUNCTION(ctf, LogDeath_AppendItemCodes)
+{
+ entity player = M_ARGV(0, entity);
+ if(player.flagcarried)
+ M_ARGV(1, string) = strcat(M_ARGV(1, string), "F"); // item codes
+}
+
// ==========
// Spawnfuncs
// generated file; do not modify
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/domination/cl_domination.qc>
+#endif
#ifdef SVQC
#include <common/gamemodes/gamemode/domination/sv_domination.qc>
#endif
// generated file; do not modify
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/domination/cl_domination.qh>
+#endif
#ifdef SVQC
#include <common/gamemodes/gamemode/domination/sv_domination.qh>
#endif
--- /dev/null
+#include "cl_domination.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+int autocvar_hud_panel_modicons_dom_layout;
+
+void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
+{
+ TC(int, layout); TC(int, i);
+ float stat = -1;
+ string pic = "";
+ vector color = '0 0 0';
+ switch(i)
+ {
+ case 0: stat = STAT(DOM_PPS_RED); pic = "dom_icon_red"; color = '1 0 0'; break;
+ case 1: stat = STAT(DOM_PPS_BLUE); pic = "dom_icon_blue"; color = '0 0 1'; break;
+ case 2: stat = STAT(DOM_PPS_YELLOW); pic = "dom_icon_yellow"; color = '1 1 0'; break;
+ default:
+ case 3: stat = STAT(DOM_PPS_PINK); pic = "dom_icon_pink"; color = '1 0 1'; break;
+ }
+ float pps_ratio = 0;
+ if(STAT(DOM_TOTAL_PPS))
+ pps_ratio = stat / STAT(DOM_TOTAL_PPS);
+
+ if(mySize.x/mySize.y > aspect_ratio)
+ {
+ i = aspect_ratio * mySize.y;
+ myPos.x = myPos.x + (mySize.x - i) / 2;
+ mySize.x = i;
+ }
+ else
+ {
+ i = 1/aspect_ratio * mySize.x;
+ myPos.y = myPos.y + (mySize.y - i) / 2;
+ mySize.y = i;
+ }
+
+ if (layout) // show text too
+ {
+ //draw the text
+ color *= 0.5 + pps_ratio * (1 - 0.5); // half saturated color at min, full saturated at max
+ if (layout == 2) // average pps
+ drawstring_aspect(myPos + eX * mySize.y, ftos_decimals(stat, 2), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
+ else // percentage of average pps
+ drawstring_aspect(myPos + eX * mySize.y, strcat( ftos(floor(pps_ratio*100 + 0.5)), "%" ), vec2((2/3) * mySize.x, mySize.y), color, panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+
+ //draw the icon
+ drawpic_aspect_skin(myPos, pic, '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ if (stat > 0)
+ {
+ drawsetcliparea(myPos.x, myPos.y + mySize.y * (1 - pps_ratio), mySize.y, mySize.y * pps_ratio);
+ drawpic_aspect_skin(myPos, strcat(pic, "-highlighted"), '1 1 0' * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+ drawresetcliparea();
+ }
+}
+
+void HUD_Mod_Dom(vector myPos, vector mySize)
+{
+ mod_active = 1; // required in each mod function that always shows something
+
+ int layout = autocvar_hud_panel_modicons_dom_layout;
+ int rows, columns;
+ float aspect_ratio;
+ aspect_ratio = (layout) ? 3 : 1;
+ rows = HUD_GetRowCount(team_count, mySize, aspect_ratio);
+ columns = ceil(team_count/rows);
+
+ int i;
+ float row = 0, column = 0;
+ vector pos, itemSize;
+ itemSize = vec2(mySize.x / columns, mySize.y / rows);
+ for(i=0; i<team_count; ++i)
+ {
+ pos = myPos + vec2(column * itemSize.x, row * itemSize.y);
+
+ DrawDomItem(pos, itemSize, aspect_ratio, layout, i);
+
+ ++row;
+ if(row >= rows)
+ {
+ row = 0;
+ ++column;
+ }
+ }
+}
--- /dev/null
+#pragma once
+
+void HUD_Mod_Dom(vector myPos, vector mySize);
if (STAT(FROZEN, frag_target) == FROZEN_NORMAL)
Unfreeze(frag_target, true);
freezetag_count_alive_players();
- return true; // let the player die so that he can respawn whenever he wants
+ frag_target.respawn_time = time;
+ frag_target.respawn_flags |= RESPAWN_FORCE;
+ return true;
}
// Cases DEATH_TEAMCHANGE and DEATH_AUTOTEAMCHANGE are needed to fix a bug whe
return true;
}
+MUTATOR_HOOKFUNCTION(ft, SV_ParseServerCommand)
+{
+ string cmd_name = M_ARGV(0, string);
+ if (cmd_name == "shuffleteams")
+ shuffleteams_on_reset_map = !(round_handler_IsActive() && !round_handler_IsRoundStarted());
+ return false;
+}
+
void freezetag_Initialize()
{
freezetag_teams = autocvar_g_freezetag_teams_override;
#pragma once
#include <common/mutators/base.qh>
+#include <server/command/sv_cmd.qh>
+
int autocvar_g_freezetag_point_limit;
int autocvar_g_freezetag_point_leadlimit;
bool autocvar_g_freezetag_team_spawns;
// generated file; do not modify
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/keepaway/cl_keepaway.qc>
+#endif
#ifdef SVQC
#include <common/gamemodes/gamemode/keepaway/sv_keepaway.qc>
#endif
// generated file; do not modify
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/keepaway/cl_keepaway.qh>
+#endif
#ifdef SVQC
#include <common/gamemodes/gamemode/keepaway/sv_keepaway.qh>
#endif
--- /dev/null
+#include "cl_keepaway.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+// Keepaway HUD mod icon
+int kaball_prevstatus; // last remembered status
+float kaball_statuschange_time; // time when the status changed
+
+// we don't need to reset for keepaway since it immediately
+// autocorrects prevstatus as to if the player has the ball or not
+
+void HUD_Mod_Keepaway(vector pos, vector mySize)
+{
+ mod_active = 1; // keepaway should always show the mod HUD
+
+ float BLINK_FACTOR = 0.15;
+ float BLINK_BASE = 0.85;
+ float BLINK_FREQ = 5;
+ float kaball_alpha = BLINK_BASE + BLINK_FACTOR * cos(time * BLINK_FREQ);
+
+ int stat_items = STAT(ITEMS);
+ int kaball = (stat_items/IT_KEY1) & 1;
+
+ if(kaball != kaball_prevstatus)
+ {
+ kaball_statuschange_time = time;
+ kaball_prevstatus = kaball;
+ }
+
+ vector kaball_pos, kaball_size;
+
+ if(mySize.x > mySize.y) {
+ kaball_pos = pos + eX * 0.25 * mySize.x;
+ kaball_size = vec2(0.5 * mySize.x, mySize.y);
+ } else {
+ kaball_pos = pos + eY * 0.25 * mySize.y;
+ kaball_size = vec2(mySize.x, 0.5 * mySize.y);
+ }
+
+ float kaball_statuschange_elapsedtime = time - kaball_statuschange_time;
+ float f = bound(0, kaball_statuschange_elapsedtime*2, 1);
+
+ if(kaball_prevstatus && f < 1)
+ drawpic_aspect_skin_expanding(kaball_pos, "keepawayball_carrying", kaball_size, '1 1 1', panel_fg_alpha * kaball_alpha, DRAWFLAG_NORMAL, f);
+
+ if(kaball)
+ drawpic_aspect_skin(pos, "keepawayball_carrying", vec2(mySize.x, mySize.y), '1 1 1', panel_fg_alpha * kaball_alpha * f, DRAWFLAG_NORMAL);
+}
--- /dev/null
+#pragma once
+
+void HUD_Mod_Keepaway(vector pos, vector mySize);
// generated file; do not modify
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/keyhunt/cl_keyhunt.qc>
+#endif
#ifdef SVQC
#include <common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc>
#endif
// generated file; do not modify
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/keyhunt/cl_keyhunt.qh>
+#endif
#ifdef SVQC
#include <common/gamemodes/gamemode/keyhunt/sv_keyhunt.qh>
#endif
--- /dev/null
+#include "cl_keyhunt.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+// Keyhunt HUD modicon section
+vector KH_SLOTS[4];
+
+void HUD_Mod_KH(vector pos, vector mySize)
+{
+ mod_active = 1; // keyhunt should never hide the mod icons panel
+
+ // Read current state
+ int state = STAT(KH_KEYS);
+ if(!state) return;
+
+ int i, key_state;
+ int all_keys, team1_keys, team2_keys, team3_keys, team4_keys, dropped_keys, carrying_keys;
+ all_keys = team1_keys = team2_keys = team3_keys = team4_keys = dropped_keys = carrying_keys = 0;
+
+ for(i = 0; i < 4; ++i)
+ {
+ key_state = (bitshift(state, i * -5) & 31) - 1;
+
+ if(key_state == -1)
+ continue;
+
+ if(key_state == 30)
+ {
+ ++carrying_keys;
+ key_state = myteam;
+ }
+
+ switch(key_state)
+ {
+ case NUM_TEAM_1: ++team1_keys; break;
+ case NUM_TEAM_2: ++team2_keys; break;
+ case NUM_TEAM_3: ++team3_keys; break;
+ case NUM_TEAM_4: ++team4_keys; break;
+ case 29: ++dropped_keys; break;
+ }
+
+ ++all_keys;
+ }
+
+ // Calculate slot measurements
+ vector slot_size;
+ if(all_keys == 4 && mySize.x * 0.5 < mySize.y && mySize.y * 0.5 < mySize.x)
+ {
+ // Quadratic arrangement
+ slot_size = vec2(mySize.x * 0.5, mySize.y * 0.5);
+ KH_SLOTS[0] = pos;
+ KH_SLOTS[1] = pos + eX * slot_size.x;
+ KH_SLOTS[2] = pos + eY * slot_size.y;
+ KH_SLOTS[3] = pos + eX * slot_size.x + eY * slot_size.y;
+ }
+ else
+ {
+ if(mySize.x > mySize.y)
+ {
+ // Horizontal arrangement
+ slot_size = vec2(mySize.x / all_keys, mySize.y);
+ for(i = 0; i < all_keys; ++i)
+ KH_SLOTS[i] = pos + eX * slot_size.x * i;
+ }
+ else
+ {
+ // Vertical arrangement
+ slot_size = vec2(mySize.x, mySize.y / all_keys);
+ for(i = 0; i < all_keys; ++i)
+ KH_SLOTS[i] = pos + eY * slot_size.y * i;
+ }
+ }
+
+ // Make icons blink in case of RUN HERE
+
+ float alpha = 1;
+ if(carrying_keys)
+ {
+ float blink = 0.6 + sin(2 * M_PI * time) * 0.4; // Oscillate between 0.2 and 1
+ switch(myteam)
+ {
+ case NUM_TEAM_1: if(team1_keys == all_keys) alpha = blink; break;
+ case NUM_TEAM_2: if(team2_keys == all_keys) alpha = blink; break;
+ case NUM_TEAM_3: if(team3_keys == all_keys) alpha = blink; break;
+ case NUM_TEAM_4: if(team4_keys == all_keys) alpha = blink; break;
+ }
+ }
+
+ // Draw icons
+
+ i = 0;
+
+ while(team1_keys--)
+ if(myteam == NUM_TEAM_1 && carrying_keys)
+ {
+ drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+ --carrying_keys;
+ }
+ else
+ drawpic_aspect_skin(KH_SLOTS[i++], "kh_red_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+ while(team2_keys--)
+ if(myteam == NUM_TEAM_2 && carrying_keys)
+ {
+ drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+ --carrying_keys;
+ }
+ else
+ drawpic_aspect_skin(KH_SLOTS[i++], "kh_blue_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+ while(team3_keys--)
+ if(myteam == NUM_TEAM_3 && carrying_keys)
+ {
+ drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+ --carrying_keys;
+ }
+ else
+ drawpic_aspect_skin(KH_SLOTS[i++], "kh_yellow_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+ while(team4_keys--)
+ if(myteam == NUM_TEAM_4 && carrying_keys)
+ {
+ drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_carrying", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+ --carrying_keys;
+ }
+ else
+ drawpic_aspect_skin(KH_SLOTS[i++], "kh_pink_taken", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+
+ while(dropped_keys--)
+ drawpic_aspect_skin(KH_SLOTS[i++], "kh_dropped", slot_size, '1 1 1', alpha, DRAWFLAG_NORMAL);
+}
--- /dev/null
+#pragma once
+
+void HUD_Mod_KH(vector pos, vector mySize);
int autocvar_g_keyhunt_teams_override;
// #define KH_PLAYER_USE_ATTACHMENT
+// TODO? no model exists for this
// #define KH_PLAYER_USE_CARRIEDMODEL
#ifdef KH_PLAYER_USE_ATTACHMENT
return 0;
}
-//entity kh_worldkeylist;
-.entity kh_worldkeynext;
entity kh_controller;
//bool kh_tracking_enabled;
int kh_teams;
return true;
}
+MUTATOR_HOOKFUNCTION(kh, LogDeath_AppendItemCodes)
+{
+ entity player = M_ARGV(0, entity);
+ if(player.kh_next)
+ M_ARGV(1, string) = strcat(M_ARGV(1, string), "K"); // item codes
+}
+
MUTATOR_HOOKFUNCTION(kh, DropSpecialItems)
{
entity frag_target = M_ARGV(0, entity);
return 0;
}
+entity kh_worldkeylist;
+.entity kh_worldkeynext;
+
#define FOR_EACH_KH_KEY(v) for(v = kh_worldkeylist; v; v = v.kh_worldkeynext )
// ALL OF THESE should be removed in the future, as other code should not have to care
// generated file; do not modify
-#include <common/gamemodes/gamemode/nexball/nexball.qc>
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/nexball/cl_nexball.qc>
+#endif
+#ifdef SVQC
+ #include <common/gamemodes/gamemode/nexball/sv_nexball.qc>
+#endif
#include <common/gamemodes/gamemode/nexball/weapon.qc>
#ifdef SVQC
#include <common/gamemodes/gamemode/nexball/sv_weapon.qc>
// generated file; do not modify
-#include <common/gamemodes/gamemode/nexball/nexball.qh>
+#ifdef CSQC
+ #include <common/gamemodes/gamemode/nexball/cl_nexball.qh>
+#endif
+#ifdef SVQC
+ #include <common/gamemodes/gamemode/nexball/sv_nexball.qh>
+#endif
#include <common/gamemodes/gamemode/nexball/weapon.qh>
#ifdef SVQC
#include <common/gamemodes/gamemode/nexball/sv_weapon.qh>
--- /dev/null
+#include "cl_nexball.qh"
+
+#include <client/hud/panel/modicons.qh>
+
+// Nexball HUD mod icon
+void HUD_Mod_NexBall(vector pos, vector mySize)
+{
+ float nb_pb_starttime, dt, p;
+ int stat_items;
+
+ stat_items = STAT(ITEMS);
+ nb_pb_starttime = STAT(NB_METERSTART);
+
+ if (stat_items & IT_KEY1)
+ mod_active = 1;
+ else
+ mod_active = 0;
+
+ //Manage the progress bar if any
+ if (nb_pb_starttime > 0)
+ {
+ dt = (time - nb_pb_starttime) % nb_pb_period;
+ // one period of positive triangle
+ p = 2 * dt / nb_pb_period;
+ if (p > 1)
+ p = 2 - p;
+
+ HUD_Panel_DrawProgressBar(pos, mySize, "progressbar", p, (mySize.x <= mySize.y), 0, autocvar_hud_progressbar_nexball_color, autocvar_hud_progressbar_alpha * panel_fg_alpha, DRAWFLAG_NORMAL);
+ }
+
+ if (stat_items & IT_KEY1)
+ drawpic_aspect_skin(pos, "nexball_carrying", eX * mySize.x + eY * mySize.y, '1 1 1', panel_fg_alpha, DRAWFLAG_NORMAL);
+}
+
+int autocvar_cl_eventchase_nexball = 1;
+
+REGISTER_MUTATOR(cl_nb, true);
+
+MUTATOR_HOOKFUNCTION(cl_nb, WantEventchase)
+{
+ if(autocvar_cl_eventchase_nexball && ISGAMETYPE(NEXBALL) && !(WepSet_GetFromStat() & WEPSET(NEXBALL)))
+ return true;
+ return false;
+}
--- /dev/null
+#pragma once
+
+void HUD_Mod_NexBall(vector pos, vector mySize);
+++ /dev/null
-#include "nexball.qh"
-
-#ifdef CSQC
-int autocvar_cl_eventchase_nexball = 1;
-
-REGISTER_MUTATOR(cl_nb, true);
-
-MUTATOR_HOOKFUNCTION(cl_nb, WantEventchase)
-{
- if(autocvar_cl_eventchase_nexball && ISGAMETYPE(NEXBALL) && !(WepSet_GetFromStat() & WEPSET(NEXBALL)))
- return true;
- return false;
-}
-#endif
-#ifdef SVQC
-.entity ballcarried;
-
-int autocvar_g_nexball_goalleadlimit;
-#define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
-
-bool autocvar_g_nexball_basketball_jumppad = true;
-float autocvar_g_nexball_basketball_bouncefactor;
-float autocvar_g_nexball_basketball_bouncestop;
-float autocvar_g_nexball_basketball_carrier_highspeed;
-bool autocvar_g_nexball_basketball_meter;
-float autocvar_g_nexball_basketball_meter_maxpower;
-float autocvar_g_nexball_basketball_meter_minpower;
-float autocvar_g_nexball_delay_collect;
-float autocvar_g_nexball_delay_goal;
-float autocvar_g_nexball_delay_start;
-bool autocvar_g_nexball_football_jumppad = true;
-float autocvar_g_nexball_football_bouncefactor;
-float autocvar_g_nexball_football_bouncestop;
-bool autocvar_g_nexball_radar_showallplayers;
-bool autocvar_g_nexball_sound_bounce;
-int autocvar_g_nexball_trail_color;
-bool autocvar_g_nexball_playerclip_collisions = true;
-
-float autocvar_g_nexball_safepass_turnrate;
-float autocvar_g_nexball_safepass_maxdist;
-float autocvar_g_nexball_safepass_holdtime;
-float autocvar_g_nexball_viewmodel_scale;
-float autocvar_g_nexball_tackling;
-vector autocvar_g_nexball_viewmodel_offset;
-
-float autocvar_g_balance_nexball_primary_animtime;
-float autocvar_g_balance_nexball_primary_refire;
-float autocvar_g_balance_nexball_primary_speed;
-float autocvar_g_balance_nexball_secondary_animtime;
-float autocvar_g_balance_nexball_secondary_force;
-float autocvar_g_balance_nexball_secondary_lifetime;
-float autocvar_g_balance_nexball_secondary_refire;
-float autocvar_g_balance_nexball_secondary_speed;
-
-void basketball_touch(entity this, entity toucher);
-void football_touch(entity this, entity toucher);
-void ResetBall(entity this);
-const int NBM_NONE = 0;
-const int NBM_FOOTBALL = 2;
-const int NBM_BASKETBALL = 4;
-float nexball_mode;
-
-float OtherTeam(float t) //works only if there are two teams on the map!
-{
- entity e;
- e = find(NULL, classname, "nexball_team");
- if(e.team == t)
- e = find(e, classname, "nexball_team");
- return e.team;
-}
-
-const int ST_NEXBALL_GOALS = 1;
-void nb_ScoreRules(int teams)
-{
- GameRules_scoring(teams, 0, 0, {
- field_team(ST_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
- field(SP_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
- field(SP_NEXBALL_FAULTS, "faults", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER);
- });
-}
-
-void LogNB(string mode, entity actor)
-{
- string s;
- if(!autocvar_sv_eventlog)
- return;
- s = strcat(":nexball:", mode);
- if(actor != NULL)
- s = strcat(s, ":", ftos(actor.playerid));
- GameLogEcho(s);
-}
-
-void ball_restart(entity this)
-{
- if(this.owner)
- DropBall(this, this.owner.origin, '0 0 0');
- ResetBall(this);
-}
-
-void nexball_setstatus(entity this)
-{
- this.items &= ~IT_KEY1;
- if(this.ballcarried)
- {
- if(this.ballcarried.teamtime && (this.ballcarried.teamtime < time))
- {
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_NEXBALL_RETURN_HELD));
- entity e = this.ballcarried;
- DropBall(this.ballcarried, this.ballcarried.owner.origin, '0 0 0');
- ResetBall(e);
- }
- else
- this.items |= IT_KEY1;
- }
-}
-
-void relocate_nexball(entity this)
-{
- tracebox(this.origin, BALL_MINS, BALL_MAXS, this.origin, true, this);
- if(trace_startsolid)
- {
- vector o = this.origin;
- if (!move_out_of_solid(this)) {
- objerror(this, "could not get out of solid at all!");
- }
- LOG_INFOF(
- "^1NOTE: this map needs FIXING. %s at %s needs to be moved out of solid, e.g. by %s",
- this.classname,
- vtos(o - '0 0 1'),
- vtos(this.origin - o)
- );
- this.origin = o;
- }
-}
-
-void DropOwner(entity this)
-{
- entity ownr;
- ownr = this.owner;
- DropBall(this, ownr.origin, ownr.velocity);
- makevectors(ownr.v_angle.y * '0 1 0');
- ownr.velocity += ('0 0 0.75' - v_forward) * 1000;
- UNSET_ONGROUND(ownr);
-}
-
-void GiveBall(entity plyr, entity ball)
-{
- .entity weaponentity = weaponentities[0]; // TODO: find ballstealer
- entity ownr = ball.owner;
- if(ownr)
- {
- ownr.effects &= ~autocvar_g_nexball_basketball_effects_default;
- ownr.ballcarried = NULL;
- GameRules_scoring_vip(ownr, false);
- if(STAT(NB_METERSTART, ownr))
- {
- STAT(NB_METERSTART, ownr) = 0;
- ownr.(weaponentity).state = WS_READY;
- }
- WaypointSprite_Kill(ownr.waypointsprite_attachedforcarrier);
- }
- else
- {
- WaypointSprite_Kill(ball.waypointsprite_attachedforcarrier);
- }
-
- //setattachment(ball, plyr, "");
- setorigin(ball, plyr.origin + plyr.view_ofs);
-
- if(ball.team != plyr.team)
- ball.teamtime = time + autocvar_g_nexball_basketball_delay_hold_forteam;
-
- ball.owner = ball.pusher = plyr; //"owner" is set to the player carrying, "pusher" to the last player who touched it
- ball.weaponentity_fld = weaponentity;
- ball.team = plyr.team;
- plyr.ballcarried = ball;
- GameRules_scoring_vip(plyr, true);
- ball.nb_dropper = plyr;
-
- plyr.effects |= autocvar_g_nexball_basketball_effects_default;
- ball.effects &= ~autocvar_g_nexball_basketball_effects_default;
-
- ball.velocity = '0 0 0';
- set_movetype(ball, MOVETYPE_NONE);
- settouch(ball, func_null);
- ball.effects |= EF_NOSHADOW;
- ball.scale = 1; // scale down.
-
- WaypointSprite_AttachCarrier(WP_NbBall, plyr, RADARICON_FLAGCARRIER);
- WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
-
- if(autocvar_g_nexball_basketball_delay_hold)
- {
- setthink(ball, DropOwner);
- ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold;
- }
-
- STAT(WEAPONS, plyr.(weaponentity)) = STAT(WEAPONS, plyr);
- plyr.m_switchweapon = plyr.(weaponentity).m_weapon;
- STAT(WEAPONS, plyr) = WEPSET(NEXBALL);
- Weapon w = WEP_NEXBALL;
- w.wr_resetplayer(w, plyr);
- plyr.(weaponentity).m_switchweapon = WEP_NEXBALL;
- W_SwitchWeapon(plyr, WEP_NEXBALL, weaponentity);
-}
-
-void DropBall(entity ball, vector org, vector vel)
-{
- ball.effects |= autocvar_g_nexball_basketball_effects_default;
- ball.effects &= ~EF_NOSHADOW;
- ball.owner.effects &= ~autocvar_g_nexball_basketball_effects_default;
-
- setattachment(ball, NULL, "");
- setorigin(ball, org);
- set_movetype(ball, MOVETYPE_BOUNCE);
- UNSET_ONGROUND(ball);
- ball.scale = ball_scale;
- ball.velocity = vel;
- ball.nb_droptime = time;
- settouch(ball, basketball_touch);
- setthink(ball, ResetBall);
- ball.nextthink = min(time + autocvar_g_nexball_delay_idle, ball.teamtime);
-
- if(STAT(NB_METERSTART, ball.owner))
- {
- STAT(NB_METERSTART, ball.owner) = 0;
- .entity weaponentity = ball.weaponentity_fld;
- ball.owner.(weaponentity).state = WS_READY;
- }
-
- WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier);
- WaypointSprite_Spawn(WP_NbBall, 0, 0, ball, '0 0 64', NULL, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); // no health bar please
- WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
-
- entity e = ball.owner; ball.owner = NULL;
- e.ballcarried = NULL;
- GameRules_scoring_vip(e, false);
-}
-
-void InitBall(entity this)
-{
- if(game_stopped) return;
- UNSET_ONGROUND(this);
- set_movetype(this, MOVETYPE_BOUNCE);
- if(this.classname == "nexball_basketball")
- settouch(this, basketball_touch);
- else if(this.classname == "nexball_football")
- settouch(this, football_touch);
- this.cnt = 0;
- setthink(this, ResetBall);
- this.nextthink = time + autocvar_g_nexball_delay_idle + 3;
- this.teamtime = 0;
- this.pusher = NULL;
- this.team = false;
- _sound(this, CH_TRIGGER, this.noise1, VOL_BASE, ATTEN_NORM);
- WaypointSprite_Ping(this.waypointsprite_attachedforcarrier);
- LogNB("init", NULL);
-}
-
-void ResetBall(entity this)
-{
- if(this.cnt < 2) // step 1
- {
- if(time == this.teamtime)
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_NEXBALL_RETURN_HELD));
-
- settouch(this, func_null);
- set_movetype(this, MOVETYPE_NOCLIP);
- this.velocity = '0 0 0'; // just in case?
- if(!this.cnt)
- LogNB("resetidle", NULL);
- this.cnt = 2;
- this.nextthink = time;
- }
- else if(this.cnt < 4) // step 2 and 3
- {
-// dprint("Step ", ftos(this.cnt), ": Calculated velocity: ", vtos(this.spawnorigin - this.origin), ", time: ", ftos(time), "\n");
- this.velocity = (this.spawnorigin - this.origin) * (this.cnt - 1); // 1 or 0.5 second movement
- this.nextthink = time + 0.5;
- this.cnt += 1;
- }
- else // step 4
- {
-// dprint("Step 4: time: ", ftos(time), "\n");
- if(vdist(this.origin - this.spawnorigin, >, 10)) // should not happen anymore
- LOG_TRACE("The ball moved too far away from its spawn origin.\nOffset: ",
- vtos(this.origin - this.spawnorigin), " Velocity: ", vtos(this.velocity), "\n");
- this.velocity = '0 0 0';
- setorigin(this, this.spawnorigin); // make sure it's positioned correctly anyway
- set_movetype(this, MOVETYPE_NONE);
- setthink(this, InitBall);
- this.nextthink = max(time, game_starttime) + autocvar_g_nexball_delay_start;
- }
-}
-
-void football_touch(entity this, entity toucher)
-{
- if(toucher.solid == SOLID_BSP)
- {
- if(time > this.lastground + 0.1)
- {
- _sound(this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
- this.lastground = time;
- }
- if(this.velocity && !this.cnt)
- this.nextthink = time + autocvar_g_nexball_delay_idle;
- return;
- }
- if (!IS_PLAYER(toucher) && !IS_VEHICLE(toucher))
- return;
- if(GetResource(toucher, RES_HEALTH) < 1)
- return;
- if(!this.cnt)
- this.nextthink = time + autocvar_g_nexball_delay_idle;
-
- this.pusher = toucher;
- this.team = toucher.team;
-
- if(autocvar_g_nexball_football_physics == -1) // MrBougo try 1, before decompiling Rev's original
- {
- if(toucher.velocity)
- this.velocity = toucher.velocity * 1.5 + '0 0 1' * autocvar_g_nexball_football_boost_up;
- }
- else if(autocvar_g_nexball_football_physics == 1) // MrBougo's modded Rev style: partially independant of the height of the aiming point
- {
- makevectors(toucher.v_angle);
- this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + '0 0 1' * autocvar_g_nexball_football_boost_up;
- }
- else if(autocvar_g_nexball_football_physics == 2) // 2nd mod try: totally independant. Really playable!
- {
- makevectors(toucher.v_angle.y * '0 1 0');
- this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
- }
- else // Revenant's original style (from the original mod's disassembly, acknowledged by Revenant)
- {
- makevectors(toucher.v_angle);
- this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
- }
- this.avelocity = -250 * v_forward; // maybe there is a way to make it look better?
-}
-
-void basketball_touch(entity this, entity toucher)
-{
- if(toucher.ballcarried)
- {
- football_touch(this, toucher);
- return;
- }
- if(!this.cnt && IS_PLAYER(toucher) && !STAT(FROZEN, toucher) && !IS_DEAD(toucher) && (toucher != this.nb_dropper || time > this.nb_droptime + autocvar_g_nexball_delay_collect))
- {
- if(GetResource(toucher, RES_HEALTH) < 1)
- return;
- LogNB("caught", toucher);
- GiveBall(toucher, this);
- }
- else if(toucher.solid == SOLID_BSP)
- {
- _sound(this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
- if(this.velocity && !this.cnt)
- this.nextthink = min(time + autocvar_g_nexball_delay_idle, this.teamtime);
- }
-}
-
-void GoalTouch(entity this, entity toucher)
-{
- entity ball;
- float isclient, pscore, otherteam;
- string pname;
-
- if(game_stopped) return;
- if((this.spawnflags & GOAL_TOUCHPLAYER) && toucher.ballcarried)
- ball = toucher.ballcarried;
- else
- ball = toucher;
- if(ball.classname != "nexball_basketball")
- if(ball.classname != "nexball_football")
- return;
- if((!ball.pusher && this.team != GOAL_OUT) || ball.cnt)
- return;
- EXACTTRIGGER_TOUCH(this, toucher);
-
-
- if(NumTeams(nb_teams) == 2)
- otherteam = OtherTeam(ball.team);
- else
- otherteam = 0;
-
- if((isclient = IS_CLIENT(ball.pusher)))
- pname = ball.pusher.netname;
- else
- pname = "Someone (?)";
-
- if(ball.team == this.team) //owngoal (regular goals)
- {
- LogNB("owngoal", ball.pusher);
- bprint("Boo! ", pname, "^7 scored a goal against their own team!\n");
- pscore = -1;
- }
- else if(this.team == GOAL_FAULT)
- {
- LogNB("fault", ball.pusher);
- if(NumTeams(nb_teams) == 2)
- bprint(Team_ColoredFullName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
- else
- bprint(Team_ColoredFullName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
- pscore = -1;
- }
- else if(this.team == GOAL_OUT)
- {
- LogNB("out", ball.pusher);
- if((this.spawnflags & GOAL_TOUCHPLAYER) && ball.owner)
- bprint(pname, "^7 went out of bounds.\n");
- else
- bprint("The ball was returned.\n");
- pscore = 0;
- }
- else //score
- {
- LogNB(strcat("goal:", ftos(this.team)), ball.pusher);
- bprint("Goaaaaal! ", pname, "^7 scored a point for the ", Team_ColoredFullName(ball.team), ".\n");
- pscore = 1;
- }
-
- _sound(ball, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NONE);
-
- if(ball.team && pscore)
- {
- if(NumTeams(nb_teams) == 2 && pscore < 0)
- TeamScore_AddToTeam(otherteam, ST_NEXBALL_GOALS, -pscore);
- else
- TeamScore_AddToTeam(ball.team, ST_NEXBALL_GOALS, pscore);
- }
- if(isclient)
- {
- if(pscore > 0)
- GameRules_scoring_add(ball.pusher, NEXBALL_GOALS, pscore);
- else if(pscore < 0)
- GameRules_scoring_add(ball.pusher, NEXBALL_FAULTS, -pscore);
- }
-
- if(ball.owner) // Happens on spawnflag GOAL_TOUCHPLAYER
- DropBall(ball, ball.owner.origin, ball.owner.velocity);
-
- WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier);
-
- ball.cnt = 1;
- setthink(ball, ResetBall);
- if(ball.classname == "nexball_basketball")
- settouch(ball, football_touch); // better than func_null: football control until the ball gets reset
- ball.nextthink = time + autocvar_g_nexball_delay_goal * (this.team != GOAL_OUT);
-}
-
-//=======================//
-// team ents //
-//=======================//
-spawnfunc(nexball_team)
-{
- if(!g_nexball)
- {
- delete(this);
- return;
- }
- this.team = this.cnt + 1;
-}
-
-void nb_spawnteam(string teamname, float teamcolor)
-{
- LOG_TRACE("^2spawned team ", teamname);
- entity e = new(nexball_team);
- e.netname = teamname;
- e.cnt = teamcolor;
- e.team = e.cnt + 1;
- //nb_teams += 1;
-}
-
-void nb_spawnteams()
-{
- bool t_red = false, t_blue = false, t_yellow = false, t_pink = false;
- entity e;
- for(e = NULL; (e = find(e, classname, "nexball_goal"));)
- {
- switch(e.team)
- {
- case NUM_TEAM_1:
- if(!t_red)
- {
- nb_spawnteam("Red", e.team-1) ;
- nb_teams |= BIT(0);
- t_red = true;
- }
- break;
- case NUM_TEAM_2:
- if(!t_blue)
- {
- nb_spawnteam("Blue", e.team-1) ;
- t_blue = true;
- nb_teams |= BIT(1);
- }
- break;
- case NUM_TEAM_3:
- if(!t_yellow)
- {
- nb_spawnteam("Yellow", e.team-1);
- t_yellow = true;
- nb_teams |= BIT(2);
- }
- break;
- case NUM_TEAM_4:
- if(!t_pink)
- {
- nb_spawnteam("Pink", e.team-1) ;
- t_pink = true;
- nb_teams |= BIT(3);
- }
- break;
- }
- }
-}
-
-void nb_delayedinit(entity this)
-{
- if(find(NULL, classname, "nexball_team") == NULL)
- nb_spawnteams();
- nb_ScoreRules(nb_teams);
-}
-
-
-//=======================//
-// spawnfuncs //
-//=======================//
-
-void SpawnBall(entity this)
-{
- if(!g_nexball) { delete(this); return; }
-
-// balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
-
- if(this.model == "")
- {
- this.model = "models/nexball/ball.md3";
- this.scale = 1.3;
- }
-
- precache_model(this.model);
- _setmodel(this, this.model);
- setsize(this, BALL_MINS, BALL_MAXS);
- ball_scale = this.scale;
-
- relocate_nexball(this);
- this.spawnorigin = this.origin;
-
- this.effects = this.effects | EF_LOWPRECISION;
-
- if(cvar(strcat("g_", this.classname, "_trail"))) //nexball_basketball :p
- {
- this.glow_color = autocvar_g_nexball_trail_color;
- this.glow_trail = true;
- }
-
- set_movetype(this, MOVETYPE_FLY);
-
- if(autocvar_g_nexball_playerclip_collisions)
- this.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP;
-
- if(!autocvar_g_nexball_sound_bounce)
- this.noise = "";
- else if(this.noise == "")
- this.noise = strzone(SND(NB_BOUNCE));
- //bounce sound placeholder (FIXME)
- if(this.noise1 == "")
- this.noise1 = strzone(SND(NB_DROP));
- //ball drop sound placeholder (FIXME)
- if(this.noise2 == "")
- this.noise2 = strzone(SND(NB_STEAL));
- //stealing sound placeholder (FIXME)
- if(this.noise) precache_sound(this.noise);
- precache_sound(this.noise1);
- precache_sound(this.noise2);
-
- WaypointSprite_AttachCarrier(WP_NbBall, this, RADARICON_FLAGCARRIER); // the ball's team is not set yet, no rule update needed
-
- this.reset = ball_restart;
- setthink(this, InitBall);
- this.nextthink = game_starttime + autocvar_g_nexball_delay_start;
-}
-
-spawnfunc(nexball_basketball)
-{
- nexball_mode |= NBM_BASKETBALL;
- this.classname = "nexball_basketball";
- if (!(balls & BALL_BASKET))
- {
- /*
- CVTOV(g_nexball_basketball_effects_default);
- CVTOV(g_nexball_basketball_delay_hold);
- CVTOV(g_nexball_basketball_delay_hold_forteam);
- CVTOV(g_nexball_basketball_teamsteal);
- */
- autocvar_g_nexball_basketball_effects_default = autocvar_g_nexball_basketball_effects_default & BALL_EFFECTMASK;
- }
- if(!this.effects)
- this.effects = autocvar_g_nexball_basketball_effects_default;
- this.solid = SOLID_TRIGGER;
- this.pushable = autocvar_g_nexball_basketball_jumppad;
- balls |= BALL_BASKET;
- this.bouncefactor = autocvar_g_nexball_basketball_bouncefactor;
- this.bouncestop = autocvar_g_nexball_basketball_bouncestop;
- SpawnBall(this);
-}
-
-spawnfunc(nexball_football)
-{
- nexball_mode |= NBM_FOOTBALL;
- this.classname = "nexball_football";
- this.solid = SOLID_TRIGGER;
- balls |= BALL_FOOT;
- this.pushable = autocvar_g_nexball_football_jumppad;
- this.bouncefactor = autocvar_g_nexball_football_bouncefactor;
- this.bouncestop = autocvar_g_nexball_football_bouncestop;
- SpawnBall(this);
-}
-
-bool nb_Goal_Customize(entity this, entity client)
-{
- entity e = WaypointSprite_getviewentity(client);
- entity wp_owner = this.owner;
- if(SAME_TEAM(e, wp_owner)) { return false; }
-
- return true;
-}
-
-void SpawnGoal(entity this)
-{
- if(!g_nexball) { delete(this); return; }
-
- EXACTTRIGGER_INIT;
-
- if(this.team != GOAL_OUT && Team_IsValidTeam(this.team))
- {
- entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (this.absmin + this.absmax) * 0.5, this, sprite, RADARICON_NONE);
- wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 0.5 0');
- setcefc(this.sprite, nb_Goal_Customize);
- }
-
- this.classname = "nexball_goal";
- if(this.noise == "")
- this.noise = "ctf/respawn.wav";
- precache_sound(this.noise);
- settouch(this, GoalTouch);
-}
-
-spawnfunc(nexball_redgoal)
-{
- this.team = NUM_TEAM_1;
- SpawnGoal(this);
-}
-spawnfunc(nexball_bluegoal)
-{
- this.team = NUM_TEAM_2;
- SpawnGoal(this);
-}
-spawnfunc(nexball_yellowgoal)
-{
- this.team = NUM_TEAM_3;
- SpawnGoal(this);
-}
-spawnfunc(nexball_pinkgoal)
-{
- this.team = NUM_TEAM_4;
- SpawnGoal(this);
-}
-
-spawnfunc(nexball_fault)
-{
- this.team = GOAL_FAULT;
- if(this.noise == "")
- this.noise = strzone(SND(TYPEHIT));
- SpawnGoal(this);
-}
-
-spawnfunc(nexball_out)
-{
- this.team = GOAL_OUT;
- if(this.noise == "")
- this.noise = strzone(SND(TYPEHIT));
- SpawnGoal(this);
-}
-
-//
-//Spawnfuncs preserved for compatibility
-//
-
-spawnfunc(ball)
-{
- spawnfunc_nexball_football(this);
-}
-spawnfunc(ball_football)
-{
- spawnfunc_nexball_football(this);
-}
-spawnfunc(ball_basketball)
-{
- spawnfunc_nexball_basketball(this);
-}
-// The "red goal" is defended by blue team. A ball in there counts as a point for red.
-spawnfunc(ball_redgoal)
-{
- spawnfunc_nexball_bluegoal(this); // I blame Revenant
-}
-spawnfunc(ball_bluegoal)
-{
- spawnfunc_nexball_redgoal(this); // but he didn't mean to cause trouble :p
-}
-spawnfunc(ball_fault)
-{
- spawnfunc_nexball_fault(this);
-}
-spawnfunc(ball_bound)
-{
- spawnfunc_nexball_out(this);
-}
-
-bool ball_customize(entity this, entity client)
-{
- if(!this.owner)
- {
- this.effects &= ~EF_FLAME;
- this.scale = 1;
- setcefc(this, func_null);
- return true;
- }
-
- if(client == this.owner)
- {
- this.scale = autocvar_g_nexball_viewmodel_scale;
- if(this.enemy)
- this.effects |= EF_FLAME;
- else
- this.effects &= ~EF_FLAME;
- }
- else
- {
- this.effects &= ~EF_FLAME;
- this.scale = 1;
- }
-
- return true;
-}
-
-void nb_DropBall(entity player)
-{
- if(player.ballcarried && g_nexball)
- DropBall(player.ballcarried, player.origin, player.velocity);
-}
-
-MUTATOR_HOOKFUNCTION(nb, ClientDisconnect)
-{
- entity player = M_ARGV(0, entity);
-
- nb_DropBall(player);
-}
-
-MUTATOR_HOOKFUNCTION(nb, PlayerDies)
-{
- entity frag_target = M_ARGV(2, entity);
-
- nb_DropBall(frag_target);
-}
-
-MUTATOR_HOOKFUNCTION(nb, MakePlayerObserver)
-{
- entity player = M_ARGV(0, entity);
-
- nb_DropBall(player);
- return false;
-}
-
-MUTATOR_HOOKFUNCTION(nb, PlayerPreThink)
-{
- entity player = M_ARGV(0, entity);
-
- makevectors(player.v_angle);
- if(nexball_mode & NBM_BASKETBALL)
- {
- if(player.ballcarried)
- {
- // 'view ball'
- player.ballcarried.velocity = player.velocity;
- setcefc(player.ballcarried, ball_customize);
-
- vector org = player.origin + player.view_ofs +
- v_forward * autocvar_g_nexball_viewmodel_offset.x +
- v_right * autocvar_g_nexball_viewmodel_offset.y +
- v_up * autocvar_g_nexball_viewmodel_offset.z;
- setorigin(player.ballcarried, org);
-
- // 'safe passing'
- if(autocvar_g_nexball_safepass_maxdist)
- {
- if(player.ballcarried.wait < time && player.ballcarried.enemy)
- {
- //centerprint(player, sprintf("Lost lock on %s", player.ballcarried.enemy.netname));
- player.ballcarried.enemy = NULL;
- }
-
-
- //tracebox(player.origin + player.view_ofs, '-2 -2 -2', '2 2 2', player.origin + player.view_ofs + v_forward * autocvar_g_nexball_safepass_maxdist);
- crosshair_trace(player);
- if( trace_ent &&
- IS_CLIENT(trace_ent) &&
- !IS_DEAD(trace_ent) &&
- trace_ent.team == player.team &&
- vdist(trace_ent.origin - player.origin, <=, autocvar_g_nexball_safepass_maxdist) )
- {
-
- //if(player.ballcarried.enemy != trace_ent)
- // centerprint(player, sprintf("Locked to %s", trace_ent.netname));
- player.ballcarried.enemy = trace_ent;
- player.ballcarried.wait = time + autocvar_g_nexball_safepass_holdtime;
-
-
- }
- }
- }
- else
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
-
- if(STAT(WEAPONS, player.(weaponentity)))
- {
- STAT(WEAPONS, player) = STAT(WEAPONS, player.(weaponentity));
- Weapon w = WEP_NEXBALL;
- w.wr_resetplayer(w, player);
- player.(weaponentity).m_switchweapon = player.m_switchweapon;
- W_SwitchWeapon(player, player.(weaponentity).m_switchweapon, weaponentity);
-
- STAT(WEAPONS, player.(weaponentity)) = '0 0 0';
- }
- }
- }
-
- }
-
- nexball_setstatus(player);
-}
-
-MUTATOR_HOOKFUNCTION(nb, SpectateCopy)
-{
- entity spectatee = M_ARGV(0, entity);
- entity client = M_ARGV(1, entity);
-
- STAT(NB_METERSTART, client) = STAT(NB_METERSTART, spectatee);
-}
-
-MUTATOR_HOOKFUNCTION(nb, PlayerSpawn)
-{
- entity player = M_ARGV(0, entity);
-
- STAT(NB_METERSTART, player) = 0;
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- STAT(WEAPONS, player.(weaponentity)) = '0 0 0';
- }
-
- if (nexball_mode & NBM_BASKETBALL)
- STAT(WEAPONS, player) |= WEPSET(NEXBALL);
- else
- STAT(WEAPONS, player) = '0 0 0';
-
- return false;
-}
-
-MUTATOR_HOOKFUNCTION(nb, PlayerPhysics_UpdateStats)
-{
- entity player = M_ARGV(0, entity);
- // these automatically reset, no need to worry
-
- if(player.ballcarried)
- STAT(MOVEVARS_HIGHSPEED, player) *= autocvar_g_nexball_basketball_carrier_highspeed;
-}
-
-MUTATOR_HOOKFUNCTION(nb, ForbidThrowCurrentWeapon)
-{
- //entity player = M_ARGV(0, entity);
- entity wepent = M_ARGV(1, entity);
-
- return wepent.m_weapon == WEP_NEXBALL;
-}
-
-MUTATOR_HOOKFUNCTION(nb, ForbidDropCurrentWeapon)
-{
- //entity player = M_ARGV(0, entity);
- int wep = M_ARGV(1, int);
-
- return wep == WEP_MORTAR.m_id; // TODO: what is this for?
-}
-
-MUTATOR_HOOKFUNCTION(nb, FilterItem)
-{
- entity item = M_ARGV(0, entity);
-
- if(Item_IsLoot(item))
- if(item.weapon == WEP_NEXBALL.m_id)
- return true;
-
- return false;
-}
-
-MUTATOR_HOOKFUNCTION(nb, ItemTouch)
-{
- entity item = M_ARGV(0, entity);
- entity toucher = M_ARGV(1, entity);
-
- if(item.weapon && toucher.ballcarried)
- return MUT_ITEMTOUCH_RETURN; // no new weapons for you, mister!
-
- return MUT_ITEMTOUCH_CONTINUE;
-}
-
-MUTATOR_HOOKFUNCTION(nb, TeamBalance_CheckAllowedTeams)
-{
- M_ARGV(1, string) = "nexball_team";
- return true;
-}
-
-MUTATOR_HOOKFUNCTION(nb, WantWeapon)
-{
- M_ARGV(1, float) = 0; // weapon is set a few lines later, apparently
- return true;
-}
-
-MUTATOR_HOOKFUNCTION(nb, DropSpecialItems)
-{
- entity frag_target = M_ARGV(0, entity);
-
- if(frag_target.ballcarried)
- DropBall(frag_target.ballcarried, frag_target.origin, frag_target.velocity);
-
- return false;
-}
-
-MUTATOR_HOOKFUNCTION(nb, SendWaypoint)
-{
- M_ARGV(2, int) &= ~0x80;
-}
-
-REGISTER_MUTATOR(nb, false)
-{
- MUTATOR_STATIC();
- MUTATOR_ONADD
- {
- g_nexball_meter_period = autocvar_g_nexball_meter_period;
- if(g_nexball_meter_period <= 0)
- g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
- g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
-
- // General settings
- /*
- CVTOV(g_nexball_football_boost_forward); //100
- CVTOV(g_nexball_football_boost_up); //200
- CVTOV(g_nexball_delay_idle); //10
- CVTOV(g_nexball_football_physics); //0
- */
- radar_showennemies = autocvar_g_nexball_radar_showallplayers;
-
- InitializeEntity(NULL, nb_delayedinit, INITPRIO_GAMETYPE);
- WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
-
- GameRules_teams(true);
- GameRules_limit_score(autocvar_g_nexball_goallimit);
- GameRules_limit_lead(autocvar_g_nexball_goalleadlimit);
- }
-
- MUTATOR_ONROLLBACK_OR_REMOVE
- {
- WEP_NEXBALL.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
- }
- return 0;
-}
-
-#endif
+++ /dev/null
-#pragma once
-
-#ifdef SVQC
-//EF_BRIGHTFIELD|EF_BRIGHTLIGHT|EF_DIMLIGHT|EF_BLUE|EF_RED|EF_FLAME
-const float BALL_EFFECTMASK = 1229;
-const vector BALL_MINS = '-16 -16 -16'; // The model is 24*24*24
-const vector BALL_MAXS = '16 16 16';
-const vector BALL_ATTACHORG = '3 0 16';
-const float BALL_FOOT = 1;
-const float BALL_BASKET = 2;
-//spawnflags
-const float GOAL_TOUCHPLAYER = 1;
-//goal types
-const float GOAL_FAULT = -1;
-const float GOAL_OUT = -2;
-
-void DropBall(entity ball, vector org, vector vel);
-float autocvar_g_nexball_football_boost_forward;
-float autocvar_g_nexball_football_boost_up;
-float autocvar_g_nexball_football_physics;
-float autocvar_g_nexball_delay_idle;
-float autocvar_g_nexball_basketball_delay_hold;
-float autocvar_g_nexball_basketball_delay_hold_forteam;
-float autocvar_g_nexball_basketball_effects_default;
-float autocvar_g_nexball_basketball_teamsteal;
-float autocvar_g_nexball_meter_period;
-
-float balls;
-float ball_scale;
-float nb_teams;
-
-.entity nb_dropper;
-.float nb_droptime;
-
-.float teamtime;
-#endif
--- /dev/null
+#include "sv_nexball.qh"
+
+.entity ballcarried;
+
+int autocvar_g_nexball_goalleadlimit;
+#define autocvar_g_nexball_goallimit cvar("g_nexball_goallimit")
+
+bool autocvar_g_nexball_basketball_jumppad = true;
+float autocvar_g_nexball_basketball_bouncefactor;
+float autocvar_g_nexball_basketball_bouncestop;
+float autocvar_g_nexball_basketball_carrier_highspeed;
+bool autocvar_g_nexball_basketball_meter;
+float autocvar_g_nexball_basketball_meter_maxpower;
+float autocvar_g_nexball_basketball_meter_minpower;
+float autocvar_g_nexball_delay_collect;
+float autocvar_g_nexball_delay_goal;
+float autocvar_g_nexball_delay_start;
+bool autocvar_g_nexball_football_jumppad = true;
+float autocvar_g_nexball_football_bouncefactor;
+float autocvar_g_nexball_football_bouncestop;
+bool autocvar_g_nexball_radar_showallplayers;
+bool autocvar_g_nexball_sound_bounce;
+int autocvar_g_nexball_trail_color;
+bool autocvar_g_nexball_playerclip_collisions = true;
+
+float autocvar_g_nexball_safepass_turnrate;
+float autocvar_g_nexball_safepass_maxdist;
+float autocvar_g_nexball_safepass_holdtime;
+float autocvar_g_nexball_viewmodel_scale;
+float autocvar_g_nexball_tackling;
+vector autocvar_g_nexball_viewmodel_offset;
+
+float autocvar_g_balance_nexball_primary_animtime;
+float autocvar_g_balance_nexball_primary_refire;
+float autocvar_g_balance_nexball_primary_speed;
+float autocvar_g_balance_nexball_secondary_animtime;
+float autocvar_g_balance_nexball_secondary_force;
+float autocvar_g_balance_nexball_secondary_lifetime;
+float autocvar_g_balance_nexball_secondary_refire;
+float autocvar_g_balance_nexball_secondary_speed;
+
+void basketball_touch(entity this, entity toucher);
+void football_touch(entity this, entity toucher);
+void ResetBall(entity this);
+const int NBM_NONE = 0;
+const int NBM_FOOTBALL = 2;
+const int NBM_BASKETBALL = 4;
+float nexball_mode;
+
+float OtherTeam(float t) //works only if there are two teams on the map!
+{
+ entity e;
+ e = find(NULL, classname, "nexball_team");
+ if(e.team == t)
+ e = find(e, classname, "nexball_team");
+ return e.team;
+}
+
+const int ST_NEXBALL_GOALS = 1;
+void nb_ScoreRules(int teams)
+{
+ GameRules_scoring(teams, 0, 0, {
+ field_team(ST_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
+ field(SP_NEXBALL_GOALS, "goals", SFL_SORT_PRIO_PRIMARY);
+ field(SP_NEXBALL_FAULTS, "faults", SFL_SORT_PRIO_SECONDARY | SFL_LOWER_IS_BETTER);
+ });
+}
+
+void LogNB(string mode, entity actor)
+{
+ string s;
+ if(!autocvar_sv_eventlog)
+ return;
+ s = strcat(":nexball:", mode);
+ if(actor != NULL)
+ s = strcat(s, ":", ftos(actor.playerid));
+ GameLogEcho(s);
+}
+
+void ball_restart(entity this)
+{
+ if(this.owner)
+ DropBall(this, this.owner.origin, '0 0 0');
+ ResetBall(this);
+}
+
+void nexball_setstatus(entity this)
+{
+ this.items &= ~IT_KEY1;
+ if(this.ballcarried)
+ {
+ if(this.ballcarried.teamtime && (this.ballcarried.teamtime < time))
+ {
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_NEXBALL_RETURN_HELD));
+ entity e = this.ballcarried;
+ DropBall(this.ballcarried, this.ballcarried.owner.origin, '0 0 0');
+ ResetBall(e);
+ }
+ else
+ this.items |= IT_KEY1;
+ }
+}
+
+void relocate_nexball(entity this)
+{
+ tracebox(this.origin, BALL_MINS, BALL_MAXS, this.origin, true, this);
+ if(trace_startsolid)
+ {
+ vector o = this.origin;
+ if (!move_out_of_solid(this)) {
+ objerror(this, "could not get out of solid at all!");
+ }
+ LOG_INFOF(
+ "^1NOTE: this map needs FIXING. %s at %s needs to be moved out of solid, e.g. by %s",
+ this.classname,
+ vtos(o - '0 0 1'),
+ vtos(this.origin - o)
+ );
+ this.origin = o;
+ }
+}
+
+void DropOwner(entity this)
+{
+ entity ownr;
+ ownr = this.owner;
+ DropBall(this, ownr.origin, ownr.velocity);
+ makevectors(ownr.v_angle.y * '0 1 0');
+ ownr.velocity += ('0 0 0.75' - v_forward) * 1000;
+ UNSET_ONGROUND(ownr);
+}
+
+void GiveBall(entity plyr, entity ball)
+{
+ .entity weaponentity = weaponentities[0]; // TODO: find ballstealer
+ entity ownr = ball.owner;
+ if(ownr)
+ {
+ ownr.effects &= ~autocvar_g_nexball_basketball_effects_default;
+ ownr.ballcarried = NULL;
+ GameRules_scoring_vip(ownr, false);
+ if(STAT(NB_METERSTART, ownr))
+ {
+ STAT(NB_METERSTART, ownr) = 0;
+ ownr.(weaponentity).state = WS_READY;
+ }
+ WaypointSprite_Kill(ownr.waypointsprite_attachedforcarrier);
+ }
+ else
+ {
+ WaypointSprite_Kill(ball.waypointsprite_attachedforcarrier);
+ }
+
+ //setattachment(ball, plyr, "");
+ setorigin(ball, plyr.origin + plyr.view_ofs);
+
+ if(ball.team != plyr.team)
+ ball.teamtime = time + autocvar_g_nexball_basketball_delay_hold_forteam;
+
+ ball.owner = ball.pusher = plyr; //"owner" is set to the player carrying, "pusher" to the last player who touched it
+ ball.weaponentity_fld = weaponentity;
+ ball.team = plyr.team;
+ plyr.ballcarried = ball;
+ GameRules_scoring_vip(plyr, true);
+ ball.nb_dropper = plyr;
+
+ plyr.effects |= autocvar_g_nexball_basketball_effects_default;
+ ball.effects &= ~autocvar_g_nexball_basketball_effects_default;
+
+ ball.velocity = '0 0 0';
+ set_movetype(ball, MOVETYPE_NONE);
+ settouch(ball, func_null);
+ ball.effects |= EF_NOSHADOW;
+ ball.scale = 1; // scale down.
+
+ WaypointSprite_AttachCarrier(WP_NbBall, plyr, RADARICON_FLAGCARRIER);
+ WaypointSprite_UpdateRule(plyr.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
+
+ if(autocvar_g_nexball_basketball_delay_hold)
+ {
+ setthink(ball, DropOwner);
+ ball.nextthink = time + autocvar_g_nexball_basketball_delay_hold;
+ }
+
+ STAT(WEAPONS, plyr.(weaponentity)) = STAT(WEAPONS, plyr);
+ plyr.m_switchweapon = plyr.(weaponentity).m_weapon;
+ STAT(WEAPONS, plyr) = WEPSET(NEXBALL);
+ Weapon w = WEP_NEXBALL;
+ w.wr_resetplayer(w, plyr);
+ plyr.(weaponentity).m_switchweapon = WEP_NEXBALL;
+ W_SwitchWeapon(plyr, WEP_NEXBALL, weaponentity);
+}
+
+void DropBall(entity ball, vector org, vector vel)
+{
+ ball.effects |= autocvar_g_nexball_basketball_effects_default;
+ ball.effects &= ~EF_NOSHADOW;
+ ball.owner.effects &= ~autocvar_g_nexball_basketball_effects_default;
+
+ setattachment(ball, NULL, "");
+ setorigin(ball, org);
+ set_movetype(ball, MOVETYPE_BOUNCE);
+ UNSET_ONGROUND(ball);
+ ball.scale = ball_scale;
+ ball.velocity = vel;
+ ball.nb_droptime = time;
+ settouch(ball, basketball_touch);
+ setthink(ball, ResetBall);
+ ball.nextthink = min(time + autocvar_g_nexball_delay_idle, ball.teamtime);
+
+ if(STAT(NB_METERSTART, ball.owner))
+ {
+ STAT(NB_METERSTART, ball.owner) = 0;
+ .entity weaponentity = ball.weaponentity_fld;
+ ball.owner.(weaponentity).state = WS_READY;
+ }
+
+ WaypointSprite_Kill(ball.owner.waypointsprite_attachedforcarrier);
+ WaypointSprite_Spawn(WP_NbBall, 0, 0, ball, '0 0 64', NULL, ball.team, ball, waypointsprite_attachedforcarrier, false, RADARICON_FLAGCARRIER); // no health bar please
+ WaypointSprite_UpdateRule(ball.waypointsprite_attachedforcarrier, 0, SPRITERULE_DEFAULT);
+
+ entity e = ball.owner; ball.owner = NULL;
+ e.ballcarried = NULL;
+ GameRules_scoring_vip(e, false);
+}
+
+void InitBall(entity this)
+{
+ if(game_stopped) return;
+ UNSET_ONGROUND(this);
+ set_movetype(this, MOVETYPE_BOUNCE);
+ if(this.classname == "nexball_basketball")
+ settouch(this, basketball_touch);
+ else if(this.classname == "nexball_football")
+ settouch(this, football_touch);
+ this.cnt = 0;
+ setthink(this, ResetBall);
+ this.nextthink = time + autocvar_g_nexball_delay_idle + 3;
+ this.teamtime = 0;
+ this.pusher = NULL;
+ this.team = false;
+ _sound(this, CH_TRIGGER, this.noise1, VOL_BASE, ATTEN_NORM);
+ WaypointSprite_Ping(this.waypointsprite_attachedforcarrier);
+ LogNB("init", NULL);
+}
+
+void ResetBall(entity this)
+{
+ if(this.cnt < 2) // step 1
+ {
+ if(time == this.teamtime)
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_NEXBALL_RETURN_HELD));
+
+ settouch(this, func_null);
+ set_movetype(this, MOVETYPE_NOCLIP);
+ this.velocity = '0 0 0'; // just in case?
+ if(!this.cnt)
+ LogNB("resetidle", NULL);
+ this.cnt = 2;
+ this.nextthink = time;
+ }
+ else if(this.cnt < 4) // step 2 and 3
+ {
+// dprint("Step ", ftos(this.cnt), ": Calculated velocity: ", vtos(this.spawnorigin - this.origin), ", time: ", ftos(time), "\n");
+ this.velocity = (this.spawnorigin - this.origin) * (this.cnt - 1); // 1 or 0.5 second movement
+ this.nextthink = time + 0.5;
+ this.cnt += 1;
+ }
+ else // step 4
+ {
+// dprint("Step 4: time: ", ftos(time), "\n");
+ if(vdist(this.origin - this.spawnorigin, >, 10)) // should not happen anymore
+ LOG_TRACE("The ball moved too far away from its spawn origin.\nOffset: ",
+ vtos(this.origin - this.spawnorigin), " Velocity: ", vtos(this.velocity), "\n");
+ this.velocity = '0 0 0';
+ setorigin(this, this.spawnorigin); // make sure it's positioned correctly anyway
+ set_movetype(this, MOVETYPE_NONE);
+ setthink(this, InitBall);
+ this.nextthink = max(time, game_starttime) + autocvar_g_nexball_delay_start;
+ }
+}
+
+void football_touch(entity this, entity toucher)
+{
+ if(toucher.solid == SOLID_BSP)
+ {
+ if(time > this.lastground + 0.1)
+ {
+ _sound(this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
+ this.lastground = time;
+ }
+ if(this.velocity && !this.cnt)
+ this.nextthink = time + autocvar_g_nexball_delay_idle;
+ return;
+ }
+ if (!IS_PLAYER(toucher) && !IS_VEHICLE(toucher))
+ return;
+ if(GetResource(toucher, RES_HEALTH) < 1)
+ return;
+ if(!this.cnt)
+ this.nextthink = time + autocvar_g_nexball_delay_idle;
+
+ this.pusher = toucher;
+ this.team = toucher.team;
+
+ if(autocvar_g_nexball_football_physics == -1) // MrBougo try 1, before decompiling Rev's original
+ {
+ if(toucher.velocity)
+ this.velocity = toucher.velocity * 1.5 + '0 0 1' * autocvar_g_nexball_football_boost_up;
+ }
+ else if(autocvar_g_nexball_football_physics == 1) // MrBougo's modded Rev style: partially independant of the height of the aiming point
+ {
+ makevectors(toucher.v_angle);
+ this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + '0 0 1' * autocvar_g_nexball_football_boost_up;
+ }
+ else if(autocvar_g_nexball_football_physics == 2) // 2nd mod try: totally independant. Really playable!
+ {
+ makevectors(toucher.v_angle.y * '0 1 0');
+ this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
+ }
+ else // Revenant's original style (from the original mod's disassembly, acknowledged by Revenant)
+ {
+ makevectors(toucher.v_angle);
+ this.velocity = toucher.velocity + v_forward * autocvar_g_nexball_football_boost_forward + v_up * autocvar_g_nexball_football_boost_up;
+ }
+ this.avelocity = -250 * v_forward; // maybe there is a way to make it look better?
+}
+
+void basketball_touch(entity this, entity toucher)
+{
+ if(toucher.ballcarried)
+ {
+ football_touch(this, toucher);
+ return;
+ }
+ if(!this.cnt && IS_PLAYER(toucher) && !STAT(FROZEN, toucher) && !IS_DEAD(toucher) && (toucher != this.nb_dropper || time > this.nb_droptime + autocvar_g_nexball_delay_collect))
+ {
+ if(GetResource(toucher, RES_HEALTH) < 1)
+ return;
+ LogNB("caught", toucher);
+ GiveBall(toucher, this);
+ }
+ else if(toucher.solid == SOLID_BSP)
+ {
+ _sound(this, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
+ if(this.velocity && !this.cnt)
+ this.nextthink = min(time + autocvar_g_nexball_delay_idle, this.teamtime);
+ }
+}
+
+void GoalTouch(entity this, entity toucher)
+{
+ entity ball;
+ float isclient, pscore, otherteam;
+ string pname;
+
+ if(game_stopped) return;
+ if((this.spawnflags & GOAL_TOUCHPLAYER) && toucher.ballcarried)
+ ball = toucher.ballcarried;
+ else
+ ball = toucher;
+ if(ball.classname != "nexball_basketball")
+ if(ball.classname != "nexball_football")
+ return;
+ if((!ball.pusher && this.team != GOAL_OUT) || ball.cnt)
+ return;
+ EXACTTRIGGER_TOUCH(this, toucher);
+
+
+ if(NumTeams(nb_teams) == 2)
+ otherteam = OtherTeam(ball.team);
+ else
+ otherteam = 0;
+
+ if((isclient = IS_CLIENT(ball.pusher)))
+ pname = ball.pusher.netname;
+ else
+ pname = "Someone (?)";
+
+ if(ball.team == this.team) //owngoal (regular goals)
+ {
+ LogNB("owngoal", ball.pusher);
+ bprint("Boo! ", pname, "^7 scored a goal against their own team!\n");
+ pscore = -1;
+ }
+ else if(this.team == GOAL_FAULT)
+ {
+ LogNB("fault", ball.pusher);
+ if(NumTeams(nb_teams) == 2)
+ bprint(Team_ColoredFullName(otherteam), " gets a point due to ", pname, "^7's silliness.\n");
+ else
+ bprint(Team_ColoredFullName(ball.team), " loses a point due to ", pname, "^7's silliness.\n");
+ pscore = -1;
+ }
+ else if(this.team == GOAL_OUT)
+ {
+ LogNB("out", ball.pusher);
+ if((this.spawnflags & GOAL_TOUCHPLAYER) && ball.owner)
+ bprint(pname, "^7 went out of bounds.\n");
+ else
+ bprint("The ball was returned.\n");
+ pscore = 0;
+ }
+ else //score
+ {
+ LogNB(strcat("goal:", ftos(this.team)), ball.pusher);
+ bprint("Goaaaaal! ", pname, "^7 scored a point for the ", Team_ColoredFullName(ball.team), ".\n");
+ pscore = 1;
+ }
+
+ _sound(ball, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NONE);
+
+ if(ball.team && pscore)
+ {
+ if(NumTeams(nb_teams) == 2 && pscore < 0)
+ TeamScore_AddToTeam(otherteam, ST_NEXBALL_GOALS, -pscore);
+ else
+ TeamScore_AddToTeam(ball.team, ST_NEXBALL_GOALS, pscore);
+ }
+ if(isclient)
+ {
+ if(pscore > 0)
+ GameRules_scoring_add(ball.pusher, NEXBALL_GOALS, pscore);
+ else if(pscore < 0)
+ GameRules_scoring_add(ball.pusher, NEXBALL_FAULTS, -pscore);
+ }
+
+ if(ball.owner) // Happens on spawnflag GOAL_TOUCHPLAYER
+ DropBall(ball, ball.owner.origin, ball.owner.velocity);
+
+ WaypointSprite_Ping(ball.waypointsprite_attachedforcarrier);
+
+ ball.cnt = 1;
+ setthink(ball, ResetBall);
+ if(ball.classname == "nexball_basketball")
+ settouch(ball, football_touch); // better than func_null: football control until the ball gets reset
+ ball.nextthink = time + autocvar_g_nexball_delay_goal * (this.team != GOAL_OUT);
+}
+
+//=======================//
+// team ents //
+//=======================//
+spawnfunc(nexball_team)
+{
+ if(!g_nexball)
+ {
+ delete(this);
+ return;
+ }
+ this.team = this.cnt + 1;
+}
+
+void nb_spawnteam(string teamname, float teamcolor)
+{
+ LOG_TRACE("^2spawned team ", teamname);
+ entity e = new(nexball_team);
+ e.netname = teamname;
+ e.cnt = teamcolor;
+ e.team = e.cnt + 1;
+ //nb_teams += 1;
+}
+
+void nb_spawnteams()
+{
+ bool t_red = false, t_blue = false, t_yellow = false, t_pink = false;
+ entity e;
+ for(e = NULL; (e = find(e, classname, "nexball_goal"));)
+ {
+ switch(e.team)
+ {
+ case NUM_TEAM_1:
+ if(!t_red)
+ {
+ nb_spawnteam("Red", e.team-1) ;
+ nb_teams |= BIT(0);
+ t_red = true;
+ }
+ break;
+ case NUM_TEAM_2:
+ if(!t_blue)
+ {
+ nb_spawnteam("Blue", e.team-1) ;
+ t_blue = true;
+ nb_teams |= BIT(1);
+ }
+ break;
+ case NUM_TEAM_3:
+ if(!t_yellow)
+ {
+ nb_spawnteam("Yellow", e.team-1);
+ t_yellow = true;
+ nb_teams |= BIT(2);
+ }
+ break;
+ case NUM_TEAM_4:
+ if(!t_pink)
+ {
+ nb_spawnteam("Pink", e.team-1) ;
+ t_pink = true;
+ nb_teams |= BIT(3);
+ }
+ break;
+ }
+ }
+}
+
+void nb_delayedinit(entity this)
+{
+ if(find(NULL, classname, "nexball_team") == NULL)
+ nb_spawnteams();
+ nb_ScoreRules(nb_teams);
+}
+
+
+//=======================//
+// spawnfuncs //
+//=======================//
+
+void SpawnBall(entity this)
+{
+ if(!g_nexball) { delete(this); return; }
+
+// balls += 4; // using the remaining bits to count balls will leave more than the max edict count, so it's fine
+
+ if(this.model == "")
+ {
+ this.model = "models/nexball/ball.md3";
+ this.scale = 1.3;
+ }
+
+ precache_model(this.model);
+ _setmodel(this, this.model);
+ setsize(this, BALL_MINS, BALL_MAXS);
+ ball_scale = this.scale;
+
+ relocate_nexball(this);
+ this.spawnorigin = this.origin;
+
+ this.effects = this.effects | EF_LOWPRECISION;
+
+ if(cvar(strcat("g_", this.classname, "_trail"))) //nexball_basketball :p
+ {
+ this.glow_color = autocvar_g_nexball_trail_color;
+ this.glow_trail = true;
+ }
+
+ set_movetype(this, MOVETYPE_FLY);
+
+ if(autocvar_g_nexball_playerclip_collisions)
+ this.dphitcontentsmask = DPCONTENTS_BODY | DPCONTENTS_SOLID | DPCONTENTS_PLAYERCLIP;
+
+ if(!autocvar_g_nexball_sound_bounce)
+ this.noise = "";
+ else if(this.noise == "")
+ this.noise = strzone(SND(NB_BOUNCE));
+ //bounce sound placeholder (FIXME)
+ if(this.noise1 == "")
+ this.noise1 = strzone(SND(NB_DROP));
+ //ball drop sound placeholder (FIXME)
+ if(this.noise2 == "")
+ this.noise2 = strzone(SND(NB_STEAL));
+ //stealing sound placeholder (FIXME)
+ if(this.noise) precache_sound(this.noise);
+ precache_sound(this.noise1);
+ precache_sound(this.noise2);
+
+ WaypointSprite_AttachCarrier(WP_NbBall, this, RADARICON_FLAGCARRIER); // the ball's team is not set yet, no rule update needed
+
+ this.reset = ball_restart;
+ setthink(this, InitBall);
+ this.nextthink = game_starttime + autocvar_g_nexball_delay_start;
+}
+
+spawnfunc(nexball_basketball)
+{
+ nexball_mode |= NBM_BASKETBALL;
+ this.classname = "nexball_basketball";
+ if (!(balls & BALL_BASKET))
+ {
+ /*
+ CVTOV(g_nexball_basketball_effects_default);
+ CVTOV(g_nexball_basketball_delay_hold);
+ CVTOV(g_nexball_basketball_delay_hold_forteam);
+ CVTOV(g_nexball_basketball_teamsteal);
+ */
+ autocvar_g_nexball_basketball_effects_default = autocvar_g_nexball_basketball_effects_default & BALL_EFFECTMASK;
+ }
+ if(!this.effects)
+ this.effects = autocvar_g_nexball_basketball_effects_default;
+ this.solid = SOLID_TRIGGER;
+ this.pushable = autocvar_g_nexball_basketball_jumppad;
+ balls |= BALL_BASKET;
+ this.bouncefactor = autocvar_g_nexball_basketball_bouncefactor;
+ this.bouncestop = autocvar_g_nexball_basketball_bouncestop;
+ SpawnBall(this);
+}
+
+spawnfunc(nexball_football)
+{
+ nexball_mode |= NBM_FOOTBALL;
+ this.classname = "nexball_football";
+ this.solid = SOLID_TRIGGER;
+ balls |= BALL_FOOT;
+ this.pushable = autocvar_g_nexball_football_jumppad;
+ this.bouncefactor = autocvar_g_nexball_football_bouncefactor;
+ this.bouncestop = autocvar_g_nexball_football_bouncestop;
+ SpawnBall(this);
+}
+
+bool nb_Goal_Customize(entity this, entity client)
+{
+ entity e = WaypointSprite_getviewentity(client);
+ entity wp_owner = this.owner;
+ if(SAME_TEAM(e, wp_owner)) { return false; }
+
+ return true;
+}
+
+void SpawnGoal(entity this)
+{
+ if(!g_nexball) { delete(this); return; }
+
+ EXACTTRIGGER_INIT;
+
+ if(this.team != GOAL_OUT && Team_IsValidTeam(this.team))
+ {
+ entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (this.absmin + this.absmax) * 0.5, this, sprite, RADARICON_NONE);
+ wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 0.5 0');
+ setcefc(this.sprite, nb_Goal_Customize);
+ }
+
+ this.classname = "nexball_goal";
+ if(this.noise == "")
+ this.noise = "ctf/respawn.wav";
+ precache_sound(this.noise);
+ settouch(this, GoalTouch);
+}
+
+spawnfunc(nexball_redgoal)
+{
+ this.team = NUM_TEAM_1;
+ SpawnGoal(this);
+}
+spawnfunc(nexball_bluegoal)
+{
+ this.team = NUM_TEAM_2;
+ SpawnGoal(this);
+}
+spawnfunc(nexball_yellowgoal)
+{
+ this.team = NUM_TEAM_3;
+ SpawnGoal(this);
+}
+spawnfunc(nexball_pinkgoal)
+{
+ this.team = NUM_TEAM_4;
+ SpawnGoal(this);
+}
+
+spawnfunc(nexball_fault)
+{
+ this.team = GOAL_FAULT;
+ if(this.noise == "")
+ this.noise = strzone(SND(TYPEHIT));
+ SpawnGoal(this);
+}
+
+spawnfunc(nexball_out)
+{
+ this.team = GOAL_OUT;
+ if(this.noise == "")
+ this.noise = strzone(SND(TYPEHIT));
+ SpawnGoal(this);
+}
+
+//
+//Spawnfuncs preserved for compatibility
+//
+
+spawnfunc(ball)
+{
+ spawnfunc_nexball_football(this);
+}
+spawnfunc(ball_football)
+{
+ spawnfunc_nexball_football(this);
+}
+spawnfunc(ball_basketball)
+{
+ spawnfunc_nexball_basketball(this);
+}
+// The "red goal" is defended by blue team. A ball in there counts as a point for red.
+spawnfunc(ball_redgoal)
+{
+ spawnfunc_nexball_bluegoal(this); // I blame Revenant
+}
+spawnfunc(ball_bluegoal)
+{
+ spawnfunc_nexball_redgoal(this); // but he didn't mean to cause trouble :p
+}
+spawnfunc(ball_fault)
+{
+ spawnfunc_nexball_fault(this);
+}
+spawnfunc(ball_bound)
+{
+ spawnfunc_nexball_out(this);
+}
+
+bool ball_customize(entity this, entity client)
+{
+ if(!this.owner)
+ {
+ this.effects &= ~EF_FLAME;
+ this.scale = 1;
+ setcefc(this, func_null);
+ return true;
+ }
+
+ if(client == this.owner)
+ {
+ this.scale = autocvar_g_nexball_viewmodel_scale;
+ if(this.enemy)
+ this.effects |= EF_FLAME;
+ else
+ this.effects &= ~EF_FLAME;
+ }
+ else
+ {
+ this.effects &= ~EF_FLAME;
+ this.scale = 1;
+ }
+
+ return true;
+}
+
+void nb_DropBall(entity player)
+{
+ if(player.ballcarried && g_nexball)
+ DropBall(player.ballcarried, player.origin, player.velocity);
+}
+
+MUTATOR_HOOKFUNCTION(nb, ClientDisconnect)
+{
+ entity player = M_ARGV(0, entity);
+
+ nb_DropBall(player);
+}
+
+MUTATOR_HOOKFUNCTION(nb, PlayerDies)
+{
+ entity frag_target = M_ARGV(2, entity);
+
+ nb_DropBall(frag_target);
+}
+
+MUTATOR_HOOKFUNCTION(nb, MakePlayerObserver)
+{
+ entity player = M_ARGV(0, entity);
+
+ nb_DropBall(player);
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(nb, PlayerPreThink)
+{
+ entity player = M_ARGV(0, entity);
+
+ makevectors(player.v_angle);
+ if(nexball_mode & NBM_BASKETBALL)
+ {
+ if(player.ballcarried)
+ {
+ // 'view ball'
+ player.ballcarried.velocity = player.velocity;
+ setcefc(player.ballcarried, ball_customize);
+
+ vector org = player.origin + player.view_ofs +
+ v_forward * autocvar_g_nexball_viewmodel_offset.x +
+ v_right * autocvar_g_nexball_viewmodel_offset.y +
+ v_up * autocvar_g_nexball_viewmodel_offset.z;
+ setorigin(player.ballcarried, org);
+
+ // 'safe passing'
+ if(autocvar_g_nexball_safepass_maxdist)
+ {
+ if(player.ballcarried.wait < time && player.ballcarried.enemy)
+ {
+ //centerprint(player, sprintf("Lost lock on %s", player.ballcarried.enemy.netname));
+ player.ballcarried.enemy = NULL;
+ }
+
+
+ //tracebox(player.origin + player.view_ofs, '-2 -2 -2', '2 2 2', player.origin + player.view_ofs + v_forward * autocvar_g_nexball_safepass_maxdist);
+ crosshair_trace(player);
+ if( trace_ent &&
+ IS_CLIENT(trace_ent) &&
+ !IS_DEAD(trace_ent) &&
+ trace_ent.team == player.team &&
+ vdist(trace_ent.origin - player.origin, <=, autocvar_g_nexball_safepass_maxdist) )
+ {
+
+ //if(player.ballcarried.enemy != trace_ent)
+ // centerprint(player, sprintf("Locked to %s", trace_ent.netname));
+ player.ballcarried.enemy = trace_ent;
+ player.ballcarried.wait = time + autocvar_g_nexball_safepass_holdtime;
+
+
+ }
+ }
+ }
+ else
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+
+ if(STAT(WEAPONS, player.(weaponentity)))
+ {
+ STAT(WEAPONS, player) = STAT(WEAPONS, player.(weaponentity));
+ Weapon w = WEP_NEXBALL;
+ w.wr_resetplayer(w, player);
+ player.(weaponentity).m_switchweapon = player.m_switchweapon;
+ W_SwitchWeapon(player, player.(weaponentity).m_switchweapon, weaponentity);
+
+ STAT(WEAPONS, player.(weaponentity)) = '0 0 0';
+ }
+ }
+ }
+
+ }
+
+ nexball_setstatus(player);
+}
+
+MUTATOR_HOOKFUNCTION(nb, SpectateCopy)
+{
+ entity spectatee = M_ARGV(0, entity);
+ entity client = M_ARGV(1, entity);
+
+ STAT(NB_METERSTART, client) = STAT(NB_METERSTART, spectatee);
+}
+
+MUTATOR_HOOKFUNCTION(nb, PlayerSpawn)
+{
+ entity player = M_ARGV(0, entity);
+
+ STAT(NB_METERSTART, player) = 0;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ STAT(WEAPONS, player.(weaponentity)) = '0 0 0';
+ }
+
+ if (nexball_mode & NBM_BASKETBALL)
+ STAT(WEAPONS, player) |= WEPSET(NEXBALL);
+ else
+ STAT(WEAPONS, player) = '0 0 0';
+
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(nb, PlayerPhysics_UpdateStats)
+{
+ entity player = M_ARGV(0, entity);
+ // these automatically reset, no need to worry
+
+ if(player.ballcarried)
+ STAT(MOVEVARS_HIGHSPEED, player) *= autocvar_g_nexball_basketball_carrier_highspeed;
+}
+
+MUTATOR_HOOKFUNCTION(nb, ForbidThrowCurrentWeapon)
+{
+ //entity player = M_ARGV(0, entity);
+ entity wepent = M_ARGV(1, entity);
+
+ return wepent.m_weapon == WEP_NEXBALL;
+}
+
+MUTATOR_HOOKFUNCTION(nb, ForbidDropCurrentWeapon)
+{
+ //entity player = M_ARGV(0, entity);
+ int wep = M_ARGV(1, int);
+
+ return wep == WEP_MORTAR.m_id; // TODO: what is this for?
+}
+
+MUTATOR_HOOKFUNCTION(nb, FilterItem)
+{
+ entity item = M_ARGV(0, entity);
+
+ if(Item_IsLoot(item))
+ if(item.weapon == WEP_NEXBALL.m_id)
+ return true;
+
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(nb, ItemTouch)
+{
+ entity item = M_ARGV(0, entity);
+ entity toucher = M_ARGV(1, entity);
+
+ if(item.weapon && toucher.ballcarried)
+ return MUT_ITEMTOUCH_RETURN; // no new weapons for you, mister!
+
+ return MUT_ITEMTOUCH_CONTINUE;
+}
+
+MUTATOR_HOOKFUNCTION(nb, TeamBalance_CheckAllowedTeams)
+{
+ M_ARGV(1, string) = "nexball_team";
+ return true;
+}
+
+MUTATOR_HOOKFUNCTION(nb, WantWeapon)
+{
+ M_ARGV(1, float) = 0; // weapon is set a few lines later, apparently
+ return true;
+}
+
+MUTATOR_HOOKFUNCTION(nb, DropSpecialItems)
+{
+ entity frag_target = M_ARGV(0, entity);
+
+ if(frag_target.ballcarried)
+ DropBall(frag_target.ballcarried, frag_target.origin, frag_target.velocity);
+
+ return false;
+}
+
+MUTATOR_HOOKFUNCTION(nb, SendWaypoint)
+{
+ M_ARGV(2, int) &= ~0x80;
+}
+
+REGISTER_MUTATOR(nb, false)
+{
+ MUTATOR_STATIC();
+ MUTATOR_ONADD
+ {
+ g_nexball_meter_period = autocvar_g_nexball_meter_period;
+ if(g_nexball_meter_period <= 0)
+ g_nexball_meter_period = 2; // avoid division by zero etc. due to silly users
+ g_nexball_meter_period = rint(g_nexball_meter_period * 32) / 32; //Round to 1/32ths to send as a byte multiplied by 32
+
+ // General settings
+ /*
+ CVTOV(g_nexball_football_boost_forward); //100
+ CVTOV(g_nexball_football_boost_up); //200
+ CVTOV(g_nexball_delay_idle); //10
+ CVTOV(g_nexball_football_physics); //0
+ */
+ radar_showennemies = autocvar_g_nexball_radar_showallplayers;
+
+ InitializeEntity(NULL, nb_delayedinit, INITPRIO_GAMETYPE);
+ WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
+
+ GameRules_teams(true);
+ GameRules_limit_score(autocvar_g_nexball_goallimit);
+ GameRules_limit_lead(autocvar_g_nexball_goalleadlimit);
+ }
+
+ MUTATOR_ONROLLBACK_OR_REMOVE
+ {
+ WEP_NEXBALL.spawnflags |= WEP_FLAG_MUTATORBLOCKED;
+ }
+ return 0;
+}
--- /dev/null
+#pragma once
+
+//EF_BRIGHTFIELD|EF_BRIGHTLIGHT|EF_DIMLIGHT|EF_BLUE|EF_RED|EF_FLAME
+const float BALL_EFFECTMASK = 1229;
+const vector BALL_MINS = '-16 -16 -16'; // The model is 24*24*24
+const vector BALL_MAXS = '16 16 16';
+const vector BALL_ATTACHORG = '3 0 16';
+const float BALL_FOOT = 1;
+const float BALL_BASKET = 2;
+//spawnflags
+const float GOAL_TOUCHPLAYER = 1;
+//goal types
+const float GOAL_FAULT = -1;
+const float GOAL_OUT = -2;
+
+void DropBall(entity ball, vector org, vector vel);
+float autocvar_g_nexball_football_boost_forward;
+float autocvar_g_nexball_football_boost_up;
+float autocvar_g_nexball_football_physics;
+float autocvar_g_nexball_delay_idle;
+float autocvar_g_nexball_basketball_delay_hold;
+float autocvar_g_nexball_basketball_delay_hold_forteam;
+float autocvar_g_nexball_basketball_effects_default;
+float autocvar_g_nexball_basketball_teamsteal;
+float autocvar_g_nexball_meter_period;
+
+float balls;
+float ball_scale;
+float nb_teams;
+
+.entity nb_dropper;
+.float nb_droptime;
+
+.float teamtime;
#pragma once
CLASS(BallStealer, PortoLaunch)
-/* flags */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_NOTRUEAIM);
+/* flags */ ATTRIB(BallStealer, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_SPECIALATTACK | WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_NOTRUEAIM);
/* impulse */ ATTRIB(BallStealer, impulse, int, 0);
/* refname */ ATTRIB(BallStealer, netname, string, "ballstealer");
/* wepname */ ATTRIB(BallStealer, m_name, string, _("Ball Stealer"));
{
Send_Notification(NOTIF_ONE, it, MSG_CENTER, CENTER_ONS_NOTSHIELDED_TEAM);
msg_entity = it;
- soundto(MSG_ONE, this, CHAN_AUTO, SND(KH_ALARM), VOL_BASE, ATTEN_NONE); // FIXME: unique sound?
+ soundto(MSG_ONE, this, CHAN_AUTO, SND(ONS_GENERATOR_ALARM), VOL_BASE, ATTEN_NONE);
}
else
Send_Notification(NOTIF_ONE, it, MSG_CENTER, APP_TEAM_NUM(this.team, CENTER_ONS_NOTSHIELDED));
WriteVector(MSG_ENTITY, this.origin);
- WriteString(MSG_ENTITY, this.target);
- WriteString(MSG_ENTITY, this.target2);
- WriteString(MSG_ENTITY, this.target3);
- WriteString(MSG_ENTITY, this.target4);
- WriteString(MSG_ENTITY, this.targetname);
- WriteByte(MSG_ENTITY, this.target_random);
+ sf = 0;
+ sf = BITSET(sf, BIT(0), this.target_random);
+
+ sf = BITSET(sf, BIT(1), this.target && this.target != "");
+ sf = BITSET(sf, BIT(2), this.target2 && this.target2 != "");
+ sf = BITSET(sf, BIT(3), this.target3 && this.target3 != "");
+ sf = BITSET(sf, BIT(4), this.target4 && this.target4 != "");
+ sf = BITSET(sf, BIT(5), this.targetname && this.targetname != "");
+
+ WriteByte(MSG_ENTITY, sf);
+ if(sf & BIT(1))
+ WriteString(MSG_ENTITY, this.target);
+ if(sf & BIT(2))
+ WriteString(MSG_ENTITY, this.target2);
+ if(sf & BIT(3))
+ WriteString(MSG_ENTITY, this.target3);
+ if(sf & BIT(4))
+ WriteString(MSG_ENTITY, this.target4);
+ if(sf & BIT(5))
+ WriteString(MSG_ENTITY, this.targetname);
WriteByte(MSG_ENTITY, this.wait);
this.origin = ReadVector();
setorigin(this, this.origin);
- this.target = strzone(ReadString());
- this.target2 = strzone(ReadString());
- this.target3 = strzone(ReadString());
- this.target4 = strzone(ReadString());
- this.targetname = strzone(ReadString());
- this.target_random = ReadByte();
+ int targbits = ReadByte();
+ this.target_random = (targbits & BIT(0));
+
+ this.target = ((targbits & BIT(1)) ? strzone(ReadString()) : string_null);
+ this.target2 = ((targbits & BIT(2)) ? strzone(ReadString()) : string_null);
+ this.target3 = ((targbits & BIT(3)) ? strzone(ReadString()) : string_null);
+ this.target4 = ((targbits & BIT(4)) ? strzone(ReadString()) : string_null);
+ this.targetname = ((targbits & BIT(5)) ? strzone(ReadString()) : string_null);
this.wait = ReadByte();
void dynlight_find_aiment(entity this)
{
entity targ;
- if (!this.target)
+ if (!this.target || this.target == "")
objerror (this, "dynlight: no target to follow");
targ = find(NULL, targetname, this.target);
void dynlight_find_path(entity this)
{
entity targ;
- if (!this.target)
+ if (!this.target || this.target == "")
objerror (this, "dynlight: no target to follow");
targ = find(NULL, targetname, this.target);
void dynlight_find_target(entity this)
{
entity targ;
- if (!this.target)
+ if (!this.target || this.target == "")
objerror (this, "dynlight: no target to follow");
targ = find(NULL, targetname, this.target);
void Ent_TriggerMusic_Think(entity this)
{
- if(this.active == ACTIVE_NOT)
+ if(this.active == ACTIVE_NOT || intermission)
{
return;
}
void counter_use(entity this, entity actor, entity trigger)
{
entity store = this;
- if(this.spawnflags & COUNTER_PER_PLAYER)
+ if(this.spawnflags & COUNTER_PER_PLAYER) // FIXME: multiple counters in the map will not function correctly, and upon trigger reset the player won't be able to use it again!
{
if(!IS_PLAYER(actor))
return;
toucher.triggerhealtime = time + this.delay;
bool playthesound = (this.spawnflags & HEAL_SOUND_ALWAYS);
- bool healed = Heal(toucher, this, GetResource(this, RES_HEALTH), this.max_health);
+ bool healed = Heal(toucher, this, this.health, this.max_health);
if(playthesound || healed)
_sound (toucher, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
this.active = ACTIVE_ACTIVE;
if(!this.delay)
this.delay = 1;
- if(!GetResource(this, RES_HEALTH))
- SetResourceExplicit(this, RES_HEALTH, 10); // TODO: use a special field for this, it doesn't have actual health!
+ if(!this.health)
+ this.health = 10;
if(!this.max_health)
this.max_health = 200; // max health topoff for field
if(this.noise == "")
#include "magicear.qh"
#ifdef SVQC
-float magicear_matched;
-float W_Tuba_HasPlayed(entity pl, .entity weaponentity, string melody, float instrument, float ignorepitch, float mintempo, float maxtempo);
+#include <common/weapons/weapon/tuba.qh>
+bool magicear_matched;
string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin)
{
float domatch, dotrigger, matchstart, l;
/*
* t_swamp.c
-* Adds spawnfunc_trigger_swamp and suppoart routines for xonotic 1.2.1+
+* Adds spawnfunc_trigger_swamp and support routines for nexuiz 1.2.1+ and xonotic
* Author tZork (Jakob MG)
* jakob@games43.se
* 2005 11 29
*/
-.float swamp_interval; //Hurt players in swamp with this interval
-.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
-.float swamp_lifetime; // holds the points remaining until slug dies (not quite health!)
-.entity swampslug;
-
-#ifdef SVQC
-spawnfunc(trigger_swamp);
-#endif
-void swamp_touch(entity this, entity toucher);
-void swampslug_think(entity this);
-
/*
* Uses a entity calld swampslug to handle players in the swamp
//Slug dead? then remove curses.
if(GetResource(this, RES_HEALTH) <= 0)
{
- this.owner.in_swamp = 0;
+ if(this.owner.swampslug == this)
+ {
+ this.owner.in_swamp = false;
+ this.owner.swampslug = NULL;
+ }
delete(this);
//centerprint(this.owner,"Killing slug...\n");
return;
EXACTTRIGGER_TOUCH(this, toucher);
// Chech if player alredy got a swampslug.
- if(toucher.in_swamp != 1)
+ if(!toucher.in_swamp)
{
// If not attach one.
//centerprint(toucher,"Entering swamp!\n");
- toucher.swampslug = spawn();
+ if(!toucher.swampslug) // just incase
+ toucher.swampslug = spawn();
toucher.swampslug.swamp_lifetime = 2;
setthink(toucher.swampslug, swampslug_think);
toucher.swampslug.nextthink = time;
toucher.swampslug.dmg = this.dmg;
toucher.swampslug.swamp_interval = this.swamp_interval;
toucher.swamp_slowdown = this.swamp_slowdown;
- toucher.in_swamp = 1;
+ toucher.in_swamp = true;
return;
}
- //toucher.in_swamp = 1;
+ //toucher.in_swamp = true;
//Revitalize players swampslug
toucher.swampslug.swamp_lifetime = 2;
}
/*QUAKED spawnfunc_trigger_swamp (.5 .5 .5) ?
-Players gettin into the swamp will
-get slowd down and damaged
+Players in the swamp will be
+slowed down and damaged over time
*/
spawnfunc(trigger_swamp)
{
.float swamp_interval; //Hurt players in swamp with this interval
.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
-.entity swampslug;
-.float in_swamp; // bool
+.bool in_swamp;
.entity swampslug; // Uses this to release from swamp ("untouch" fix)
+
+.float swamp_interval; //Hurt players in swamp with this interval
+.float swamp_slowdown; //Players in swamp get slowd down by this mutch 0-1 is slowdown 1-~ is speedup (!?)
+.float swamp_lifetime; // holds the points remaining until slug dies (not quite health!)
+
+#ifdef SVQC
+spawnfunc(trigger_swamp);
+#endif
+void swamp_touch(entity this, entity toucher);
+void swampslug_think(entity this);
{
for ( e = HUD_MinigameMenu_entries; e != NULL; e = e.list_next )
{
- if ( e.flags & 2 && e.origin_x == this.origin_x)
+ if ( (e.flags & 2) && e.origin_x == this.origin_x)
HUD_MinigameMenu_Click(e);
}
LOG_WARNF("Missing model: \"%s\"", s);
return;
}
- profile(sprintf("precache_model(\"%s\")", s));
+ //profile(sprintf("precache_model(\"%s\")", s));
precache_model(s);
strcpy(this.model_str_, s);
}
#include <common/items/_mod.qh>
CLASS(MageSpike, PortoLaunch)
-/* flags */ ATTRIB(MageSpike, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(MageSpike, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(MageSpike, impulse, int, 9);
/* refname */ ATTRIB(MageSpike, netname, string, "magespike");
/* wepname */ ATTRIB(MageSpike, m_name, string, _("Mage spike"));
#include <common/weapons/_all.qh>
CLASS(SpiderAttack, PortoLaunch)
-/* flags */ ATTRIB(SpiderAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(SpiderAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(SpiderAttack, impulse, int, 9);
/* refname */ ATTRIB(SpiderAttack, netname, string, "spider");
/* wepname */ ATTRIB(SpiderAttack, m_name, string, _("Spider attack"));
#include <common/weapons/_all.qh>
CLASS(WyvernAttack, PortoLaunch)
-/* flags */ ATTRIB(WyvernAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(WyvernAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(WyvernAttack, impulse, int, 9);
/* refname */ ATTRIB(WyvernAttack, netname, string, "wyvern");
/* wepname */ ATTRIB(WyvernAttack, m_name, string, _("Wyvern attack"));
if(trace_ent && IS_MONSTER(trace_ent))
reverse = true;
- // TODO: fix this... tracing is broken if the floor is thin
- /*
- if(!allow_jumpoff)
+ if(!allow_jumpoff && IS_ONGROUND(this))
{
- a = b - '0 0 32';
- traceline(b, a, MOVE_WORLDONLY, this);
+ traceline(b, b - '0 0 32', MOVE_NORMAL, this);
if(trace_fraction == 1.0)
reverse = true;
- } */
+ }
if(reverse)
{
e.noalign = this.noalign;
e.angles = this.angles;
e.monster_skill = this.monster_skill;
+ e.skin = this.skin;
e = spawnmonster(e, this.spawnmob, 0, this, this, this.origin, false, true, this.monster_moveflags);
}
#include <common/teams.qh>
#include <common/util.qh>
+#ifdef GAMEQC
+#include <common/mutators/mutator/waypoints/all.qh>
+#endif
+
#ifdef GAMEQC
REGISTER_WAYPOINT(Buff, _("Buff"), "", '1 0.5 0', 1);
REGISTER_RADARICON(Buff, 1);
{
if (CS(toucher).cvar_cl_buffs_autoreplace && STAT(BUFFS, toucher) != STAT(BUFFS, this))
{
+ // TODO: lost-gained notification for this case
int buffid = buff_FirstFromFlags(STAT(BUFFS, toucher)).m_id;
- //Send_Notification(NOTIF_ONE, toucher, MSG_MULTI, ITEM_BUFF_DROP, STAT(BUFFS, toucher));
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_ITEM_BUFF_LOST, toucher.netname, buffid);
+ Send_Notification(NOTIF_ONE, toucher, MSG_INFO, INFO_ITEM_BUFF_LOST, toucher.netname, buffid);
+ if(!IS_INDEPENDENT_PLAYER(toucher))
+ Send_Notification(NOTIF_ALL_EXCEPT, toucher, MSG_INFO, INFO_ITEM_BUFF_LOST, toucher.netname, buffid);
STAT(BUFFS, toucher) = 0;
//sound(toucher, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
this.owner = toucher;
this.buff_active = false;
this.lifetime = 0;
- int buffid = buff_FirstFromFlags(STAT(BUFFS, this)).m_id;
- Send_Notification(NOTIF_ONE, toucher, MSG_MULTI, ITEM_BUFF_GOT, buffid);
- Send_Notification(NOTIF_ALL_EXCEPT, toucher, MSG_INFO, INFO_ITEM_BUFF, toucher.netname, buffid);
+ entity thebuff = buff_FirstFromFlags(STAT(BUFFS, this));
+ Send_Notification(NOTIF_ONE, toucher, MSG_MULTI, ITEM_BUFF_GOT, thebuff.m_id);
+ if(!IS_INDEPENDENT_PLAYER(toucher))
+ Send_Notification(NOTIF_ALL_EXCEPT, toucher, MSG_INFO, INFO_ITEM_BUFF, toucher.netname, thebuff.m_id);
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
sound(toucher, CH_TRIGGER, SND_SHIELD_RESPAWN, VOL_BASE, ATTN_NORM);
STAT(BUFFS, toucher) |= (STAT(BUFFS, this));
+ float bufftime = ((this.count) ? this.count : thebuff.m_time(thebuff));
+ if(bufftime)
+ STAT(BUFF_TIME, toucher) = min(time + bufftime, max(STAT(BUFF_TIME, toucher), time) + bufftime);
}
float buff_Available(entity buff)
return true;
}
+void buff_Delete(entity this)
+{
+ WaypointSprite_Kill(this.buff_waypoint);
+ delete_fn(this);
+}
+
void buff_Init(entity this)
{
if(!cvar("g_buffs")) { delete(this); return; }
buff_SetCooldown(this, autocvar_g_buffs_cooldown_activate + max(0, game_starttime - time));
this.buff_active = !this.buff_activetime;
this.pflags = PFLAGS_FULLDYNAMIC;
+ this.dtor = buff_Delete;
if(this.spawnflags & 1)
this.noalign = true;
{
entity player = M_ARGV(0, entity);
- STAT(BUFFS, player) = 0;
- STAT(BUFF_TIME, player) = 0;
+ player.oldbuffs = 0;
PS(player).buff_shield = time + 0.5; // prevent picking up buffs immediately
// reset timers here to prevent them continuing after re-spawn
player.buff_disability_time = 0;
if(STAT(BUFFS, frag_target))
{
int buffid = buff_FirstFromFlags(STAT(BUFFS, frag_target)).m_id;
- Send_Notification(NOTIF_ALL_EXCEPT, frag_target, MSG_INFO, INFO_ITEM_BUFF_LOST, frag_target.netname, buffid);
+ if(!IS_INDEPENDENT_PLAYER(frag_target))
+ Send_Notification(NOTIF_ALL_EXCEPT, frag_target, MSG_INFO, INFO_ITEM_BUFF_LOST, frag_target.netname, buffid);
STAT(BUFFS, frag_target) = 0;
+ STAT(BUFF_TIME, frag_target) = 0;
if(frag_target.buff_model)
{
{
int buffid = buff_FirstFromFlags(STAT(BUFFS, player)).m_id;
Send_Notification(NOTIF_ONE, player, MSG_MULTI, ITEM_BUFF_DROP, buffid);
- Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid);
+ if(!IS_INDEPENDENT_PLAYER(player))
+ Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid);
STAT(BUFFS, player) = 0;
+ STAT(BUFF_TIME, player) = 0;
PS(player).buff_shield = time + max(0, autocvar_g_buffs_pickup_delay);
- //STAT(BUFF_TIME, player) = 0; // already notified
sound(player, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
return true;
}
Send_Notification(NOTIF_ONE, player, MSG_MULTI, ITEM_BUFF_DROP, buffid); // TODO: special timeout message?
sound(player, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
}
- else
+ else if(!IS_INDEPENDENT_PLAYER(player))
Send_Notification(NOTIF_ALL_EXCEPT, player, MSG_INFO, INFO_ITEM_BUFF_LOST, player.netname, buffid);
STAT(BUFFS, player) = 0;
PS(player).buff_shield = time + max(0, autocvar_g_buffs_pickup_delay); // always put in a delay, even if small
{
entity buff = buff_FirstFromFlags(STAT(BUFFS, player));
float bufftime = buff != BUFF_Null ? buff.m_time(buff) : 0;
- STAT(BUFF_TIME, player) = (bufftime) ? time + bufftime : 0;
+ if(STAT(BUFF_TIME, player) <= time) // if the player still has a buff countdown, don't reset it!
+ STAT(BUFF_TIME, player) = (bufftime) ? time + bufftime : 0;
BUFF_ONADD(BUFF_AMMO)
{
if ( STAT(NADE_BONUS_SCORE, player) >= 1 )
{
Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_NADE_BONUS);
- play2(player, SND(KH_ALARM));
+ play2(player, SND(NADE_BONUS));
STAT(NADE_BONUS, player)++;
STAT(NADE_BONUS_SCORE, player) -= 1;
}
-> This will spawn as Rifle in this mutator ONLY, and as Vortex otherwise.
{
-"classname" "weapon_vortext"
+"classname" "weapon_vortex"
"new_toys" "vortex rifle"
}
-> This will spawn as either Vortex or Rifle in this mutator ONLY, and as Vortex otherwise.
/* spawnfunc */ ATTRIB(OverkillHeavyMachineGun, m_canonical_spawnfunc, string, "weapon_okhmg");
/* ammotype */ ATTRIB(OverkillHeavyMachineGun, ammo_type, int, RES_BULLETS);
/* impulse */ ATTRIB(OverkillHeavyMachineGun, impulse, int, 3);
-/* flags */ ATTRIB(OverkillHeavyMachineGun, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_SUPERWEAPON);
+/* flags */ ATTRIB(OverkillHeavyMachineGun, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_RELOADABLE | WEP_TYPE_HITSCAN | WEP_FLAG_SUPERWEAPON | WEP_FLAG_PENETRATEWALLS);
/* rating */ ATTRIB(OverkillHeavyMachineGun, bot_pickupbasevalue, float, 10000);
/* color */ ATTRIB(OverkillHeavyMachineGun, wpcolor, vector, '0.5 0.5 0');
/* modelname */ ATTRIB(OverkillHeavyMachineGun, mdl, string, "ok_hmg");
P(class, prefix, delay, float, SEC) \
P(class, prefix, edgedamage, float, SEC) \
P(class, prefix, force, float, SEC) \
+ P(class, prefix, force_zscale, float, SEC) \
P(class, prefix, lifetime, float, SEC) \
P(class, prefix, radius, float, SEC) \
P(class, prefix, refire, float, SEC) \
P(class, prefix, delay, float, SEC) \
P(class, prefix, edgedamage, float, SEC) \
P(class, prefix, force, float, SEC) \
+ P(class, prefix, force_zscale, float, SEC) \
P(class, prefix, lifetime, float, SEC) \
P(class, prefix, radius, float, SEC) \
P(class, prefix, refire, float, SEC) \
P(class, prefix, delay, float, SEC) \
P(class, prefix, edgedamage, float, SEC) \
P(class, prefix, force, float, SEC) \
+ P(class, prefix, force_zscale, float, SEC) \
P(class, prefix, lifetime, float, SEC) \
P(class, prefix, radius, float, SEC) \
P(class, prefix, refire, float, SEC) \
/* spawnfunc */ ATTRIB(OverkillRocketPropelledChainsaw, m_canonical_spawnfunc, string, "weapon_okrpc");
/* ammotype */ ATTRIB(OverkillRocketPropelledChainsaw, ammo_type, int, RES_ROCKETS);
/* impulse */ ATTRIB(OverkillRocketPropelledChainsaw, impulse, int, 9);
-/* flags */ ATTRIB(OverkillRocketPropelledChainsaw, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_NORMAL | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON);
+/* flags */ ATTRIB(OverkillRocketPropelledChainsaw, spawnflags, int, WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_CANCLIMB | WEP_FLAG_RELOADABLE | WEP_TYPE_SPLASH | WEP_FLAG_SUPERWEAPON);
/* rating */ ATTRIB(OverkillRocketPropelledChainsaw, bot_pickupbasevalue, float, 10000);
/* color */ ATTRIB(OverkillRocketPropelledChainsaw, wpcolor, vector, '0.5 0.5 0');
/* modelname */ ATTRIB(OverkillRocketPropelledChainsaw, mdl, string, "ok_rl");
P(class, prefix, delay, float, SEC) \
P(class, prefix, edgedamage, float, SEC) \
P(class, prefix, force, float, SEC) \
+ P(class, prefix, force_zscale, float, SEC) \
P(class, prefix, lifetime, float, SEC) \
P(class, prefix, radius, float, SEC) \
P(class, prefix, refire, float, SEC) \
P(class, prefix, delay, float, SEC) \
P(class, prefix, edgedamage, float, SEC) \
P(class, prefix, force, float, SEC) \
+ P(class, prefix, force_zscale, float, SEC) \
P(class, prefix, lifetime, float, SEC) \
P(class, prefix, radius, float, SEC) \
P(class, prefix, refire, float, SEC) \
if(WEP_OVERKILL_RPC.weaponstart > 0) { ok_start_items |= WEPSET(OVERKILL_RPC); }
if(WEP_OVERKILL_HMG.weaponstart > 0) { ok_start_items |= WEPSET(OVERKILL_HMG); }
- start_items |= IT_UNLIMITED_WEAPON_AMMO;
start_weapons = warmup_start_weapons = ok_start_items;
}
string autocvar_g_overkill;
bool autocvar_g_overkill_filter_healthmega;
-bool autocvar_g_overkill_filter_armormedium;
-bool autocvar_g_overkill_filter_armorbig;
+bool autocvar_g_overkill_filter_armormedium = true;
+bool autocvar_g_overkill_filter_armorbig = true;
bool autocvar_g_overkill_filter_armormega;
.float ok_item;
if (autocvar_cl_hidewaypoints >= 2)
return;
- if (this.hideflags & 1 && autocvar_cl_hidewaypoints)
+ if ((this.hideflags & 1) && autocvar_cl_hidewaypoints)
return; // fixed waypoint
InterpolateOrigin_Do(this);
bool autocvar_g_waypointsprite_turrets = true;
float autocvar_g_waypointsprite_turrets_maxdist = 5000;
bool autocvar_g_waypointsprite_turrets_text = false;
+bool autocvar_g_waypointsprite_turrets_onlyhurt = false;
bool autocvar_g_waypointsprite_uppercase;
bool autocvar_g_waypointsprite_text;
float autocvar_g_waypointsprite_iconsize = 32;
trace_plane_normal = '0 0 1';
trace_plane_dist = 0;
trace_ent = this;
+ trace_dpstartcontents = 0;
+ trace_dphitcontents = 0;
+ trace_dphitq3surfaceflags = 0;
+ trace_dphittexturename = string_null;
gettouch(it)(it, this);
}
SOUND(ONS_CONTROLPOINT_UNDERATTACK, "onslaught/controlpoint_underattack");
SOUND(ONS_DAMAGEBLOCKEDBYSHIELD, "onslaught/damageblockedbyshield");
SOUND(ONS_ELECTRICITY_EXPLODE, "onslaught/electricity_explode");
+SOUND(ONS_GENERATOR_ALARM, "kh/alarm"); // FIXME: unique sound
SOUND(ONS_GENERATOR_DECAY, "onslaught/generator_decay");
SOUND(ONS_GENERATOR_UNDERATTACK, "onslaught/generator_underattack");
SOUND(ONS_HIT1, "onslaught/ons_hit1");
SOUND(VEH_SPIDERBOT_WALK, "vehicles/spiderbot_walk");
SOUND(NADE_BEEP, "overkill/grenadebip");
+SOUND(NADE_BONUS, "kh/alarm"); // FIXME: unique sound
SOUND(BUFF_LOST, "relics/relic_effect");
TC(Sound, this);
string s = _Sound_fixpath(this.sound_str());
if (!s) return;
- profile(sprintf("precache_sound(\"%s\")", s));
+ //profile(sprintf("precache_sound(\"%s\")", s));
precache_sound(s);
strcpy(this.sound_str_, s);
}
LABEL(pickup)
+ if(this.target && this.target != "" && this.target != "###item###") // defrag support
+ SUB_UseTargets(this, toucher, NULL);
+
STAT(LAST_PICKUP, toucher) = time;
Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
|| (def.instanceOfHealth && def != ITEM_HealthSmall)
|| (def.instanceOfArmor && def != ITEM_ArmorSmall)
|| (itemid & (IT_KEY1 | IT_KEY2))
- ) this.target = "###item###"; // for finding the nearest item using findnearest
+ )
+ {
+ if(!this.target || this.target == "")
+ this.target = "###item###"; // for finding the nearest item using findnearest
+ }
Item_ItemsTime_SetTime(this, 0);
}
FOREACH(Buffs, it != BUFF_Null,
{
s = Buff_UndeprecateName(argv(j));
- if(s == it.m_name)
+ if(s == it.netname)
{
STAT(BUFFS, this) |= (it.m_itemid);
+ if(!STAT(BUFF_TIME, this))
+ STAT(BUFF_TIME, this) = it.m_time(it);
break;
}
});
if(GetResource(this, RES_FUEL) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_FUEL)), "fuel");
if(GetResource(this, RES_HEALTH) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_HEALTH)), "health");
if(GetResource(this, RES_ARMOR) != 0) this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, GetResource(this, RES_ARMOR)), "armor");
- FOREACH(Buffs, it != BUFF_Null, this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, !!(STAT(BUFFS, this) & (it.m_itemid)), it.m_name));
+ FOREACH(Buffs, it != BUFF_Null && (STAT(BUFFS, this) & it.m_itemid), this.netname = sprintf("%s %s%d %s", this.netname, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
FOREACH(Weapons, it != WEP_Null, this.netname = sprintf("%s %s%d %s", this.netname, itemprefix, !!(STAT(WEAPONS, this) & (it.m_wepset)), it.netname));
}
this.netname = strzone(this.netname);
bool GiveBuff(entity e, Buff thebuff, int op, int val)
{
bool had_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
- switch(op)
+ switch (op)
{
case OP_SET:
- if(val > 0)
- STAT(BUFFS, e) |= thebuff.m_itemid;
- else
- STAT(BUFFS, e) &= ~thebuff.m_itemid;
+ STAT(BUFF_TIME, e) = val;
break;
case OP_MIN:
- case OP_PLUS:
- if(val > 0)
- STAT(BUFFS, e) |= thebuff.m_itemid;
+ STAT(BUFF_TIME, e) = max(STAT(BUFF_TIME, e), val);
break;
case OP_MAX:
- if(val <= 0)
- STAT(BUFFS, e) &= ~thebuff.m_itemid;
+ STAT(BUFF_TIME, e) = min(STAT(BUFF_TIME, e), val);
+ break;
+ case OP_PLUS:
+ STAT(BUFF_TIME, e) += val;
break;
case OP_MINUS:
- if(val > 0)
- STAT(BUFFS, e) &= ~thebuff.m_itemid;
+ STAT(BUFF_TIME, e) -= val;
break;
}
+ if(STAT(BUFF_TIME, e) <= 0)
+ STAT(BUFFS, e) &= ~thebuff.m_itemid;
+ else
+ STAT(BUFFS, e) = thebuff.m_itemid; // NOTE: replaces any existing buffs on the player!
bool have_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
return (had_buff != have_buff);
}
e.strength_finished = max(0, e.strength_finished - time);
e.invincible_finished = max(0, e.invincible_finished - time);
e.superweapons_finished = max(0, e.superweapons_finished - time);
+ STAT(BUFF_TIME, e) = max(0, STAT(BUFF_TIME, e) - time);
PREGIVE(e, items);
PREGIVE_WEAPONS(e);
got += GiveResourceValue(e, RES_HEALTH, op, val);
got += GiveResourceValue(e, RES_ARMOR, op, val);
case "allweapons":
- FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & WEP_FLAG_MUTATORBLOCKED), got += GiveWeapon(e, it.m_id, op, val));
+ FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)), got += GiveWeapon(e, it.m_id, op, val));
//case "allbuffs": // all buffs makes a player god, do not want!
//FOREACH(Buffs, it != BUFF_Null, got += GiveBuff(e, it.m_itemid, op, val));
case "allammo":
got += GiveResourceValue(e, RES_FUEL, op, val);
break;
default:
- FOREACH(Buffs, it != BUFF_Null && Buff_UndeprecateName(cmd) == it.m_name,
+ FOREACH(Buffs, it != BUFF_Null && Buff_UndeprecateName(cmd) == it.netname,
{
got += GiveBuff(e, it, op, val);
break;
POSTGIVE_RES_ROT(e, RES_HEALTH, 1, pauserothealth_finished, autocvar_g_balance_pause_health_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND_MEGAHEALTH, SND_Null);
if(e.superweapons_finished <= 0)
- if(!g_weaponarena && STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS)
+ if(!g_weaponarena && (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
e.superweapons_finished = autocvar_g_balance_superweapons_time;
if(e.strength_finished <= 0)
e.superweapons_finished = 0;
else
e.superweapons_finished += time;
+ if(STAT(BUFF_TIME, e) <= 0)
+ STAT(BUFF_TIME, e) = 0;
+ else
+ STAT(BUFF_TIME, e) += time;
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
#ifdef SVQC
-/**
- turret_checkpoint
-**/
-
-
-//.entity checkpoint_target;
-
-/*
-#define checkpoint_cache_who flagcarried
-#define checkpoint_cache_from lastrocket
-#define checkpoint_cache_to selected_player
-*/
-
-/*
-entity path_makeorcache(entity forwho,entity start, entity end)
-{
- entity pth;
-
- //pth = pathlib_makepath(forwho, start.origin,end.origin,PFL_GROUNDSNAP,500,1.5,PT_QUICKSTAR);
-
- return pth;
-}
-*/
-
-void turret_checkpoint_use()
-{
-}
-
-#if 0
-void turret_checkpoint_think(entity this)
-{
- if(this.enemy)
- te_lightning1(this,this.origin, this.enemy.origin);
-
- this.nextthink = time + 0.25;
-}
-#endif
/*QUAKED turret_checkpoint (1 0 1) (-32 -32 -32) (32 32 32)
-----------KEYS------------
target: .targetname of next waypoint in chain.
-----------SPAWNFLAGS-----------
---------NOTES----------
If a loop is of targets are formed, any unit entering this loop will patrol it indefinitly.
-If the checkpoint chain in not looped, the unit will go "Roaming" when the last point is reached.
+If the checkpoint chain is not looped, the unit will go "Roaming" when the last point is reached.
*/
-//float tc_acum;
void turret_checkpoint_init(entity this)
{
traceline(this.origin + '0 0 16', this.origin - '0 0 1024', MOVE_WORLDONLY, this);
setorigin(this, trace_endpos + '0 0 32');
- if(this.target != "")
+ if(this.target && this.target != "")
{
this.enemy = find(NULL, targetname, this.target);
- if(this.enemy == NULL)
- LOG_TRACE("A turret_checkpoint faild to find its target!");
+ if(!this.enemy)
+ LOG_TRACE("A turret_checkpoint failed to find its target!");
}
- //setthink(this, turret_checkpoint_think);
- //this.nextthink = time + tc_acum + 0.25;
- //tc_acum += 0.25;
}
spawnfunc(turret_checkpoint)
{
setorigin(this, this.origin);
- setthink(this, turret_checkpoint_init);
- this.nextthink = time + 0.2;
+ InitializeEntity(this, turret_checkpoint_init, INITPRIO_FINDTARGET);
}
// Compat.
t = t * (1 - (1 - waypointsprite_crosshairfadescale) * (1 - bound(0, crosshairdistance/waypointsprite_crosshairfadedistance, 1)));
}
- o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
- if(autocvar_g_waypointsprite_turrets_text)
+ bool draw_healthbar = ((this.helpme && time < this.helpme) || !autocvar_g_waypointsprite_turrets_onlyhurt || hud != HUD_NORMAL);
+ bool draw_text = autocvar_g_waypointsprite_turrets_text;
+
+ if(draw_healthbar || draw_text) // make sure it's actually being drawn
+ {
+ o = drawspritearrow(o, M_PI, rgb, a, SPRITE_ARROW_SCALE * t);
+ }
+ if(draw_text)
{
o = drawsprite_TextOrIcon(true, o, M_PI, (SPRITE_HEALTHBAR_WIDTH + 2 * SPRITE_HEALTHBAR_BORDER) * t, rgb, a, waypointsprite_fontsize * '1 1 0', txt);
}
- drawhealthbar(
- o,
- 0,
- GetResource(this, RES_HEALTH) / 255,
- '0 0 0',
- '0 0 0',
- 0.5 * SPRITE_HEALTHBAR_WIDTH * t,
- 0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
- SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
- SPRITE_HEALTHBAR_BORDER * t,
- 0,
- rgb,
- a * SPRITE_HEALTHBAR_BORDERALPHA,
- rgb,
- a * SPRITE_HEALTHBAR_HEALTHALPHA,
- DRAWFLAG_NORMAL
- );
+ if(draw_healthbar)
+ {
+ drawhealthbar(
+ o,
+ 0,
+ GetResource(this, RES_HEALTH) / 255,
+ '0 0 0',
+ '0 0 0',
+ 0.5 * SPRITE_HEALTHBAR_WIDTH * t,
+ 0.5 * SPRITE_HEALTHBAR_HEIGHT * t,
+ SPRITE_HEALTHBAR_MARGIN * t + 0.5 * waypointsprite_fontsize,
+ SPRITE_HEALTHBAR_BORDER * t,
+ 0,
+ rgb,
+ a * SPRITE_HEALTHBAR_BORDERALPHA,
+ rgb,
+ a * SPRITE_HEALTHBAR_HEALTHALPHA,
+ DRAWFLAG_NORMAL
+ );
+ }
}
void turret_construct(entity this, bool isnew)
tvt_thadv = angleofs3(e_turret.tur_head.origin, e_turret.angles + e_turret.tur_head.angles, e_target.origin);
tvt_tadv = shortangle_vxy(angleofs(e_turret, e_target), e_turret.angles);
tvt_thadf = vlen(tvt_thadv);
- tvt_tadf = vlen(tvt_tadv);
/*
if(validate_flags & TFL_TARGETSELECT_FOV)
vector tvt_thadv; // turret head angle diff vector, updated by a successful call to turret_validate_target
vector tvt_tadv; // turret angle diff vector, updated by a successful call to turret_validate_target
float tvt_thadf; // turret head angle diff float, updated by a successful call to turret_validate_target
-float tvt_tadf; // turret angle diff float, updated by a successful call to turret_validate_target
float tvt_dist; // turret distance, updated by a successful call to turret_validate_target
#pragma once
CLASS(EWheelAttack, PortoLaunch)
-/* flags */ ATTRIB(EWheelAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(EWheelAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(EWheelAttack, impulse, int, 5);
/* refname */ ATTRIB(EWheelAttack, netname, string, "turret_ewheel");
/* wepname */ ATTRIB(EWheelAttack, m_name, string, _("eWheel"));
#pragma once
-// TODO: WEP_TYPE_OTHER?
-
CLASS(FlacAttack, PortoLaunch)
-/* flags */ ATTRIB(FlacAttack, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(FlacAttack, spawnflags, int, WEP_FLAG_SPECIALATTACK | WEP_FLAG_HIDDEN);
/* impulse */ ATTRIB(FlacAttack, impulse, int, 5);
/* refname */ ATTRIB(FlacAttack, netname, string, "turret_flac");
/* wepname */ ATTRIB(FlacAttack, m_name, string, _("FLAC"));
#pragma once
CLASS(HellionAttack, PortoLaunch)
-/* flags */ ATTRIB(HellionAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(HellionAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(HellionAttack, impulse, int, 9);
/* refname */ ATTRIB(HellionAttack, netname, string, "turret_hellion");
/* wepname */ ATTRIB(HellionAttack, m_name, string, _("Hellion"));
#pragma once
CLASS(HunterKillerAttack, PortoLaunch)
-/* flags */ ATTRIB(HunterKillerAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(HunterKillerAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(HunterKillerAttack, impulse, int, 9);
/* refname */ ATTRIB(HunterKillerAttack, netname, string, "turret_hk");
/* wepname */ ATTRIB(HunterKillerAttack, m_name, string, _("Hunter-Killer"));
#pragma once
CLASS(MachineGunTurretAttack, PortoLaunch)
-/* flags */ ATTRIB(MachineGunTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(MachineGunTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(MachineGunTurretAttack, impulse, int, 9);
/* refname */ ATTRIB(MachineGunTurretAttack, netname, string, "turret_machinegun");
/* wepname */ ATTRIB(MachineGunTurretAttack, m_name, string, _("Machinegun"));
#pragma once
CLASS(MLRSTurretAttack, PortoLaunch)
-/* flags */ ATTRIB(MLRSTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(MLRSTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(MLRSTurretAttack, impulse, int, 9);
/* refname */ ATTRIB(MLRSTurretAttack, netname, string, "turret_mlrs");
/* wepname */ ATTRIB(MLRSTurretAttack, m_name, string, _("MLRS"));
#pragma once
CLASS(PhaserTurretAttack, PortoLaunch)
-/* flags */ ATTRIB(PhaserTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(PhaserTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(PhaserTurretAttack, impulse, int, 9);
/* refname */ ATTRIB(PhaserTurretAttack, netname, string, "turret_phaser");
/* wepname */ ATTRIB(PhaserTurretAttack, m_name, string, _("Phaser"));
#include "plasma_weapon.qh"
CLASS(PlasmaDualAttack, PlasmaAttack)
-/* flags */ ATTRIB(PlasmaDualAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(PlasmaDualAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* refname */ ATTRIB(PlasmaDualAttack, netname, string, "turret_plasma_dual");
/* wepname */ ATTRIB(PlasmaDualAttack, m_name, string, _("Dual plasma"));
ENDCLASS(PlasmaDualAttack)
#pragma once
CLASS(PlasmaAttack, PortoLaunch)
-/* flags */ ATTRIB(PlasmaAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(PlasmaAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(PlasmaAttack, impulse, int, 5);
/* refname */ ATTRIB(PlasmaAttack, netname, string, "turret_plasma");
/* wepname */ ATTRIB(PlasmaAttack, m_name, string, _("Plasma"));
#pragma once
CLASS(TeslaCoilTurretAttack, PortoLaunch)
-/* flags */ ATTRIB(TeslaCoilTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(TeslaCoilTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(TeslaCoilTurretAttack, impulse, int, 9);
/* refname */ ATTRIB(TeslaCoilTurretAttack, netname, string, "turret_tesla");
/* wepname */ ATTRIB(TeslaCoilTurretAttack, m_name, string, _("Tesla Coil"));
#pragma once
CLASS(WalkerTurretAttack, PortoLaunch)
-/* flags */ ATTRIB(WalkerTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(WalkerTurretAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(WalkerTurretAttack, impulse, int, 5);
/* refname */ ATTRIB(WalkerTurretAttack, netname, string, "turret_walker");
/* wepname */ ATTRIB(WalkerTurretAttack, m_name, string, _("Walker"));
for(w = to; w >= from; --w)
{
int wflags = Weapons_from(w).spawnflags;
- if((wflags & WEP_FLAG_HIDDEN) && (wflags & WEP_FLAG_MUTATORBLOCKED) && !(wflags & WEP_FLAG_NORMAL))
+ if(wflags & WEP_FLAG_SPECIALATTACK)
continue;
for(i = 0; i < n; ++i)
if(stof(argv(i)) == w)
#include <common/weapons/_all.qh>
CLASS(RacerAttack, PortoLaunch)
-/* flags */ ATTRIB(RacerAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(RacerAttack, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(RacerAttack, impulse, int, 3);
/* refname */ ATTRIB(RacerAttack, netname, string, "racercannon");
/* wepname */ ATTRIB(RacerAttack, m_name, string, _("Racer cannon"));
#include <common/weapons/_all.qh>
CLASS(RaptorCannon, PortoLaunch)
-/* flags */ ATTRIB(RaptorCannon, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(RaptorCannon, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(RaptorCannon, impulse, int, 3);
/* refname */ ATTRIB(RaptorCannon, netname, string, "raptorcannon");
/* wepname */ ATTRIB(RaptorCannon, m_name, string, _("Raptor cannon"));
REGISTER_WEAPON(RAPTOR, NEW(RaptorCannon));
CLASS(RaptorBomb, PortoLaunch)
-/* flags */ ATTRIB(RaptorBomb, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(RaptorBomb, spawnflags, int, WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(RaptorBomb, impulse, int, 3);
/* refname */ ATTRIB(RaptorBomb, netname, string, "raptorbomb");
/* wepname */ ATTRIB(RaptorBomb, m_name, string, _("Raptor bomb"));
REGISTER_WEAPON(RAPTOR_BOMB, NEW(RaptorBomb));
CLASS(RaptorFlare, PortoLaunch)
-/* flags */ ATTRIB(RaptorFlare, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_MUTATORBLOCKED);
+/* flags */ ATTRIB(RaptorFlare, spawnflags, int, WEP_TYPE_OTHER | WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK);
/* impulse */ ATTRIB(RaptorFlare, impulse, int, 3);
/* refname */ ATTRIB(RaptorFlare, netname, string, "raptorflare");
/* wepname */ ATTRIB(RaptorFlare, m_name, string, _("Raptor flare"));
FOREACH(Weapons, true, {
WepSet set = it.m_wepset = _WepSet_FromWeapon(it.m_id = i);
WEPSET_ALL |= set;
- if ((it.spawnflags) & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
+ if (it.spawnflags & WEP_FLAG_SUPERWEAPON) WEPSET_SUPERWEAPONS |= set;
if (it == WEP_Null) continue;
int imp = WEP_IMPULSE_BEGIN + it.m_id - 1;
if (imp <= WEP_IMPULSE_END)
int wepcount = 1;
#define WEP_CONFIG_WRITETOFILE(str) write_String_To_File(wep_config_file, str, wep_config_alsoprint)
FOREACH(Weapons, it != WEP_Null, {
- if((it.spawnflags & WEP_FLAG_HIDDEN) && (it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_NORMAL))
+ if(it.spawnflags & WEP_FLAG_SPECIALATTACK)
continue; // never include the attacks
// step 1: clear the queue
WEP_CONFIG_COUNT = 0;
const int WEP_FLAG_PENETRATEWALLS = BIT(13); // weapon has high calibur bullets that can penetrate thick walls (WEAPONTODO)
const int WEP_FLAG_BLEED = BIT(14); // weapon pierces and causes bleeding (used for damage effects)
const int WEP_FLAG_NOTRUEAIM = BIT(15); // weapon doesn't aim directly at targets
+const int WEP_FLAG_SPECIALATTACK = BIT(16); // marked as a special attack (not a true weapon), hidden from most weapon lists
// variables:
string weaponorder_byid;
this.event_damage = func_null;
- RadiusDamage(
+ RadiusDamageForSource(
this,
+ (this.origin + (this.mins + this.maxs) * 0.5),
+ this.velocity,
this.realowner,
this.blaster_damage,
this.blaster_edgedamage,
this.blaster_radius,
NULL,
NULL,
+ false,
this.blaster_force,
+ this.blaster_force_zscale,
this.projectiledeathtype,
this.weaponentity_fld,
toucher
float atk_edgedamage,
float atk_radius,
float atk_force,
+ float atk_force_zscale,
float atk_speed,
float atk_spread,
float atk_delay,
missile.blaster_edgedamage = atk_edgedamage;
missile.blaster_radius = atk_radius;
missile.blaster_force = atk_force;
+ missile.blaster_force_zscale = atk_force_zscale;
missile.blaster_lifetime = atk_lifetime;
setorigin(missile, w_shotorg);
WEP_CVAR_PRI(blaster, edgedamage),
WEP_CVAR_PRI(blaster, radius),
WEP_CVAR_PRI(blaster, force),
+ WEP_CVAR_PRI(blaster, force_zscale),
WEP_CVAR_PRI(blaster, speed),
WEP_CVAR_PRI(blaster, spread),
WEP_CVAR_PRI(blaster, delay),
WEP_CVAR_SEC(blaster, edgedamage),
WEP_CVAR_SEC(blaster, radius),
WEP_CVAR_SEC(blaster, force),
+ WEP_CVAR_SEC(blaster, force_zscale),
WEP_CVAR_SEC(blaster, speed),
WEP_CVAR_SEC(blaster, spread),
WEP_CVAR_SEC(blaster, delay),
.float blaster_edgedamage;
.float blaster_radius;
.float blaster_force;
+.float blaster_force_zscale;
.float blaster_lifetime;
// Will be demacroed after WEP_CVAR macros are also demacroed.
WEP_CVAR_SEC(weapon_name, edgedamage), \
WEP_CVAR_SEC(weapon_name, radius), \
WEP_CVAR_SEC(weapon_name, force), \
+ WEP_CVAR_SEC(weapon_name, force_zscale), \
WEP_CVAR_SEC(weapon_name, speed), \
WEP_CVAR_SEC(weapon_name, spread), \
WEP_CVAR_SEC(weapon_name, delay), \
actor.punchangle_y = random() - 0.5;
}
- fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_speed), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), thiswep.m_id, EFFECT_BULLET);
+ fireBullet(actor, weaponentity, w_shotorg, w_shotdir, WEP_CVAR(machinegun, burst_spread), WEP_CVAR(machinegun, solidpenetration), WEP_CVAR(machinegun, sustained_damage), WEP_CVAR(machinegun, sustained_force), thiswep.m_id, EFFECT_BULLET);
Send_Effect(EFFECT_MACHINEGUN_MUZZLEFLASH, w_shotorg, w_shotdir * 1000, 1);
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, burst_spread, float, NONE) \
P(class, prefix, first, float, NONE) \
P(class, prefix, first_ammo, float, NONE) \
P(class, prefix, first_damage, float, NONE) \
/* spawnfunc */ ATTRIB(Shockwave, m_canonical_spawnfunc, string, "weapon_shockwave");
/* ammotype */ //ATTRIB(Shockwave, ammo_type, int, RES_NONE);
/* impulse */ ATTRIB(Shockwave, impulse, int, 2);
-/* flags */ ATTRIB(Shockwave, spawnflags, int, WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_TYPE_MELEE_SEC);
+/* flags */ ATTRIB(Shockwave, spawnflags, int, WEP_FLAG_HIDDEN | WEP_TYPE_HITSCAN | WEP_FLAG_CANCLIMB | WEP_TYPE_MELEE_SEC);
/* rating */ ATTRIB(Shockwave, bot_pickupbasevalue, float, 3000);
/* color */ ATTRIB(Shockwave, wpcolor, vector, '0.5 0.25 0');
/* modelname */ ATTRIB(Shockwave, mdl, string, "shotgun");
classfield(Tuba) .float tuba_volume_initial;
classfield(Tuba) .int tuba_instrument;
#endif
+
+#ifdef SVQC
+bool W_Tuba_HasPlayed(entity pl, .entity weaponentity, string melody, int instrument, bool ignorepitch, float mintempo, float maxtempo);
+#endif
P(class, prefix, delay, float, SEC) \
P(class, prefix, edgedamage, float, SEC) \
P(class, prefix, force, float, SEC) \
+ P(class, prefix, force_zscale, float, SEC) \
P(class, prefix, lifetime, float, SEC) \
P(class, prefix, radius, float, SEC) \
P(class, prefix, refire, float, SEC) \
.float vortex_chargepool_pauseregen_finished;
+void W_Vortex_Charge(entity actor, .entity weaponentity, float dt)
+{
+ if(WEP_CVAR(vortex, charge) && actor.(weaponentity).vortex_charge < WEP_CVAR(vortex, charge_limit))
+ actor.(weaponentity).vortex_charge = min(1, actor.(weaponentity).vortex_charge + WEP_CVAR(vortex, charge_rate) * dt / W_TICSPERFRAME);
+}
+
METHOD(Vortex, wr_aim, void(entity thiswep, entity actor, .entity weaponentity))
{
if(bot_aim(actor, weaponentity, 1000000, 0, 1, false))
}
METHOD(Vortex, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
{
- if(WEP_CVAR(vortex, charge) && actor.(weaponentity).vortex_charge < WEP_CVAR(vortex, charge_limit))
- actor.(weaponentity).vortex_charge = min(1, actor.(weaponentity).vortex_charge + WEP_CVAR(vortex, charge_rate) * frametime / W_TICSPERFRAME);
+ if(!WEP_CVAR(vortex, charge_always))
+ W_Vortex_Charge(actor, weaponentity, frametime);
if(WEP_CVAR_SEC(vortex, chargepool))
if(actor.(weaponentity).vortex_chargepool_ammo < 1)
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_always, float, NONE) \
P(class, prefix, charge_animlimit, float, NONE) \
P(class, prefix, charge_limit, float, NONE) \
P(class, prefix, charge_maxspeed, float, NONE) \
#ifdef SVQC
.float vortex_lasthit;
+
+void W_Vortex_Charge(entity actor, .entity weaponentity, float dt);
#endif
_("CI_THI^%d seconds"), /* third */ \
_("CI_MUL^%d seconds")) /* multi */
+// returns 1st, 2nd, 3rd, nth ordinal number from a cardinal number (integer)
ERASEABLE
string count_ordinal(int interval)
{
// to accomodate all languages unless we do a specific function for each one...
// and since that's not technically feasible/practical, this is all we've got folks.
- // Basically, it just allows you to represent a number or count in different ways
- // depending on the number... like, with count_ordinal you can provide integers
- // and retrieve 1st, 2nd, 3rd, nth ordinal numbers in a clean and simple way.
- if (floor((interval % 100) / 10) * 10 != 10) // examples: 12th, 111th, 213th will not execute this block
+ int last2digits = interval % 100;
+
+ // numbers ending with 11, 12 and 13 don't follow the standard pattern
+ if (last2digits < 4 || last2digits > 20)
{
- // otherwise, check normally for 1st,2nd,3rd insertions
- switch (interval % 10)
+ switch (last2digits % 10)
{
case 1: return sprintf(_("%dst"), interval);
case 2: return sprintf(_("%dnd"), interval);
case 3: return sprintf(_("%drd"), interval);
- default: return sprintf(_("%dth"), interval);
}
}
- else { return sprintf(_("%dth"), interval); }
- return "";
+ return sprintf(_("%dth"), interval);
}
ERASEABLE
FIELD_SCALAR(fld, health) \
FIELD_SCALAR(fld, height) \
FIELD_SCALAR(fld, impulse) \
+ FIELD_SCALAR(fld, item_pickupsound) \
FIELD_SCALAR(fld, killtarget) \
FIELD_SCALAR(fld, lerpfrac) \
FIELD_SCALAR(fld, light_lev) \
FIELD_SCALAR(fld, lip) \
FIELD_SCALAR(fld, loddistance1) \
FIELD_SCALAR(fld, lodmodel1) \
+ FIELD_SCALAR(fld, lodmodel2) \
FIELD_SCALAR(fld, ltime) \
FIELD_SCALAR(fld, map) \
FIELD_SCALAR(fld, max_health) \
NET_HANDLE(ENT_CLIENT_WARPZONE, bool isnew)
{
if(!warpzone_warpzones_exist)
+ {
cvar_settemp("r_water", "1"); // HACK for DarkPlaces: always enable reflections when a map has warpzones
+ cvar_settemp("r_water_resolutionmultiplier", "1"); // HACK for DarkPlaces: enforce full quality so entities can be seen clearly through warpzones
+ }
warpzone_warpzones_exist = 1;
if (!this.enemy)
{
NET_HANDLE(ENT_CLIENT_WARPZONE_CAMERA, bool isnew)
{
if(!warpzone_cameras_exist)
+ {
cvar_settemp("r_water", "1"); // HACK for DarkPlaces: always enable reflections when a map has cameras
+ cvar_settemp("r_water_resolutionmultiplier", "1"); // HACK for DarkPlaces: enforce full quality so entities can be seen clearly through warpzones
+ }
warpzone_cameras_exist = 1;
this.classname = "func_warpzone_camera";
void WarpZoneLib_MoveOutOfSolid_Expand(entity e, vector by)
{
- float eps = 0.0625;
+ const float eps = 0.0625;
tracebox(e.origin, e.mins - '1 1 1' * eps, e.maxs + '1 1 1' * eps, e.origin + by, MOVE_WORLDONLY, e);
if (trace_startsolid)
return;
for(i = WEP_FIRST, j = 0; i <= WEP_LAST; ++i)
{
w = Weapons_from(i);
- if(w.spawnflags & WEP_FLAG_HIDDEN)
+ if (w.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK))
continue;
if ((j % 3) == 0)
{
for(int imp = 1; imp <= 9; ++imp)
{
string w_list = "";
- ADD_TO_W_LIST(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_HIDDEN) && !(it.spawnflags & WEP_FLAG_SUPERWEAPON));
+ ADD_TO_W_LIST(!(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK | WEP_FLAG_SUPERWEAPON)));
ADD_TO_W_LIST((it.spawnflags & WEP_FLAG_SUPERWEAPON) && !(it.spawnflags & WEP_FLAG_HIDDEN));
- ADD_TO_W_LIST((it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & WEP_FLAG_HIDDEN));
+ ADD_TO_W_LIST((it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && !(it.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK)));
if(w_list)
KEYBIND_DEF(strcat("weapon_group_", itos(imp)), substring(w_list, 0, -4));
if(imp == 0)
int autocvar_g_pickup_items;
float autocvar_g_player_alpha;
float autocvar_g_player_brightness;
+float autocvar_g_player_damageforcescale = 2;
bool autocvar_g_playerclip_collisions;
int autocvar_g_powerups;
int autocvar_g_projectiles_damage;
const int WAYPOINTFLAG_NORELINK__DEPRECATED = BIT(20);
const int WPFLAGMASK_NORELINK = (WAYPOINTFLAG_TELEPORT | WAYPOINTFLAG_LADDER | WAYPOINTFLAG_JUMP | WAYPOINTFLAG_CUSTOM_JP | WAYPOINTFLAG_SUPPORT);
-entity kh_worldkeylist;
-.entity kh_worldkeynext;
-
float bot_custom_weapon;
float bot_weapons_close[Weapons_MAX];
float bot_weapons_far[Weapons_MAX];
#include "havocbot.qh"
+#include "roles.qh"
+
#include <server/defs.qh>
#include <server/miscfunctions.qh>
#include "../cvars.qh"
#include <lib/warpzone/common.qh>
-.float speed;
-
void havocbot_ai(entity this)
{
if(this.draggedby)
void havocbot_keyboard_movement(entity this, vector destorg)
{
- vector keyboard;
+ if(time <= this.havocbot_keyboardtime)
+ return;
- if (time > this.havocbot_keyboardtime)
+ float sk = skill + this.bot_moveskill;
+ this.havocbot_keyboardtime =
+ max(
+ this.havocbot_keyboardtime
+ + 0.05 / max(1, sk + this.havocbot_keyboardskill)
+ + random() * 0.025 / max(0.00025, skill + this.havocbot_keyboardskill)
+ , time);
+ vector keyboard = CS(this).movement / autocvar_sv_maxspeed;
+
+ float trigger = autocvar_bot_ai_keyboard_threshold;
+
+ // categorize forward movement
+ // at skill < 1.5 only forward
+ // at skill < 2.5 only individual directions
+ // at skill < 4.5 only individual directions, and forward diagonals
+ // at skill >= 4.5, all cases allowed
+ if (keyboard.x > trigger)
{
- float sk = skill + this.bot_moveskill;
- this.havocbot_keyboardtime =
- max(
- this.havocbot_keyboardtime
- + 0.05 / max(1, sk + this.havocbot_keyboardskill)
- + random() * 0.025 / max(0.00025, skill + this.havocbot_keyboardskill)
- , time);
- keyboard = CS(this).movement / autocvar_sv_maxspeed;
-
- float trigger = autocvar_bot_ai_keyboard_threshold;
-
- // categorize forward movement
- // at skill < 1.5 only forward
- // at skill < 2.5 only individual directions
- // at skill < 4.5 only individual directions, and forward diagonals
- // at skill >= 4.5, all cases allowed
- if (keyboard.x > trigger)
- {
- keyboard.x = 1;
- if (sk < 2.5)
- keyboard.y = 0;
- }
- else if (keyboard.x < -trigger && sk > 1.5)
- {
- keyboard.x = -1;
- if (sk < 4.5)
- keyboard.y = 0;
- }
- else
- {
- keyboard.x = 0;
- if (sk < 1.5)
- keyboard.y = 0;
- }
+ keyboard.x = 1;
+ if (sk < 2.5)
+ keyboard.y = 0;
+ }
+ else if (keyboard.x < -trigger && sk > 1.5)
+ {
+ keyboard.x = -1;
if (sk < 4.5)
- keyboard.z = 0;
-
- if (keyboard.y > trigger)
- keyboard.y = 1;
- else if (keyboard.y < -trigger)
- keyboard.y = -1;
- else
keyboard.y = 0;
+ }
+ else
+ {
+ keyboard.x = 0;
+ if (sk < 1.5)
+ keyboard.y = 0;
+ }
+ if (sk < 4.5)
+ keyboard.z = 0;
- if (keyboard.z > trigger)
- keyboard.z = 1;
- else if (keyboard.z < -trigger)
- keyboard.z = -1;
- else
- keyboard.z = 0;
+ if (keyboard.y > trigger)
+ keyboard.y = 1;
+ else if (keyboard.y < -trigger)
+ keyboard.y = -1;
+ else
+ keyboard.y = 0;
- // make sure bots don't get stuck if havocbot_keyboardtime is very high
- if (keyboard == '0 0 0')
- this.havocbot_keyboardtime = min(this.havocbot_keyboardtime, time + 0.2);
+ if (keyboard.z > trigger)
+ keyboard.z = 1;
+ else if (keyboard.z < -trigger)
+ keyboard.z = -1;
+ else
+ keyboard.z = 0;
- this.havocbot_keyboard = keyboard * autocvar_sv_maxspeed;
- if (this.havocbot_ducktime > time)
- PHYS_INPUT_BUTTON_CROUCH(this) = true;
+ // make sure bots don't get stuck if havocbot_keyboardtime is very high
+ if (keyboard == '0 0 0')
+ this.havocbot_keyboardtime = min(this.havocbot_keyboardtime, time + 0.2);
- keyboard = this.havocbot_keyboard;
- float blend = bound(0, vlen(destorg - this.origin) / autocvar_bot_ai_keyboard_distance, 1); // When getting close move with 360 degree
- //dprint("movement ", vtos(CS(this).movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
- CS(this).movement = CS(this).movement + (keyboard - CS(this).movement) * blend;
- }
+ this.havocbot_keyboard = keyboard * autocvar_sv_maxspeed;
+ if (this.havocbot_ducktime > time)
+ PHYS_INPUT_BUTTON_CROUCH(this) = true;
+
+ keyboard = this.havocbot_keyboard;
+ float blend = bound(0, vlen(destorg - this.origin) / autocvar_bot_ai_keyboard_distance, 1); // When getting close move with 360 degree
+ //dprint("movement ", vtos(CS(this).movement), " keyboard ", vtos(keyboard), " blend ", ftos(blend), "\n");
+ CS(this).movement = CS(this).movement + (keyboard - CS(this).movement) * blend;
}
void havocbot_bunnyhop(entity this, vector dir)
{
- float bunnyhopdistance;
- vector deviation;
- float maxspeed;
-
// Don't jump when attacking
if(this.aistatus & AI_STATUS_ATTACKING)
return;
if(IS_PLAYER(this.goalcurrent))
return;
- maxspeed = autocvar_sv_maxspeed;
-
- if(this.aistatus & AI_STATUS_RUNNING && vdist(this.velocity, <, autocvar_sv_maxspeed * 0.75)
- || this.aistatus & AI_STATUS_DANGER_AHEAD)
+ if((this.aistatus & AI_STATUS_RUNNING) && vdist(this.velocity, <, autocvar_sv_maxspeed * 0.75)
+ || (this.aistatus & AI_STATUS_DANGER_AHEAD))
{
this.aistatus &= ~AI_STATUS_RUNNING;
PHYS_INPUT_BUTTON_JUMP(this) = false;
}
vector gco = get_closer_dest(this.goalcurrent, this.origin);
- bunnyhopdistance = vlen(this.origin - gco);
// Run only to visible goals
if(IS_ONGROUND(this))
- if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed)) // if -really- running
+ if(vdist(vec2(this.velocity), >=, autocvar_sv_maxspeed))
if(checkpvs(this.origin + this.view_ofs, this.goalcurrent))
{
- this.bot_lastseengoal = this.goalcurrent;
+ this.bot_lastseengoal = this.goalcurrent;
- // seen it before
- if(this.bot_timelastseengoal)
+ // seen it before
+ if(this.bot_timelastseengoal)
+ {
+ // for a period of time
+ if(time - this.bot_timelastseengoal > autocvar_bot_ai_bunnyhop_firstjumpdelay)
{
- // for a period of time
- if(time - this.bot_timelastseengoal > autocvar_bot_ai_bunnyhop_firstjumpdelay)
- {
- float checkdistance;
- checkdistance = true;
+ bool checkdistance = true;
- // don't run if it is too close
- if(this.bot_canruntogoal==0)
- {
- if(bunnyhopdistance > autocvar_bot_ai_bunnyhop_startdistance)
- this.bot_canruntogoal = 1;
- else
- this.bot_canruntogoal = -1;
- }
+ // don't run if it is too close
+ if(this.bot_canruntogoal==0)
+ {
+ if(vdist(this.origin - gco, >, autocvar_bot_ai_bunnyhop_startdistance))
+ this.bot_canruntogoal = 1;
+ else
+ this.bot_canruntogoal = -1;
+ }
- if(this.bot_canruntogoal != 1)
- return;
+ if(this.bot_canruntogoal != 1)
+ return;
- if(this.aistatus & AI_STATUS_ROAMING)
- if(this.goalcurrent.classname=="waypoint")
- if (!(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL))
- if(fabs(gco.z - this.origin.z) < this.maxs.z - this.mins.z)
- if(this.goalstack01 && !wasfreed(this.goalstack01))
- if (!(this.goalstack01.wpflags & WAYPOINTFLAG_JUMP))
+ if(this.aistatus & AI_STATUS_ROAMING)
+ if(this.goalcurrent.classname == "waypoint")
+ if (!(this.goalcurrent.wpflags & WAYPOINTFLAG_PERSONAL))
+ if(fabs(gco.z - this.origin.z) < this.maxs.z - this.mins.z)
+ if (this.goalstack01 && !wasfreed(this.goalstack01))
+ if (!(this.goalstack01.wpflags & WAYPOINTFLAG_JUMP))
+ {
+ vector gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
+ vector deviation = vectoangles(gno - this.origin) - vectoangles(gco - this.origin);
+ while (deviation.y < -180) deviation.y = deviation.y + 360;
+ while (deviation.y > 180) deviation.y = deviation.y - 360;
+
+ if(fabs(deviation.y) < 20)
+ if(vlen2(this.origin - gco) < vlen2(this.origin - gno))
+ if(fabs(gno.z - gco.z) < this.maxs.z - this.mins.z)
{
- vector gno = (this.goalstack01.absmin + this.goalstack01.absmax) * 0.5;
- deviation = vectoangles(gno - this.origin) - vectoangles(gco - this.origin);
- while (deviation.y < -180) deviation.y = deviation.y + 360;
- while (deviation.y > 180) deviation.y = deviation.y - 360;
-
- if(fabs(deviation.y) < 20)
- if(bunnyhopdistance < vlen(this.origin - gno))
- if(fabs(gno.z - gco.z) < this.maxs.z - this.mins.z)
+ if(vdist(gco - gno, >, autocvar_bot_ai_bunnyhop_startdistance))
+ if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
{
- if(vdist(gco - gno, >, autocvar_bot_ai_bunnyhop_startdistance))
- if(checkpvs(this.origin + this.view_ofs, this.goalstack01))
- {
- checkdistance = false;
- }
+ checkdistance = false;
}
}
+ }
- if(checkdistance)
- {
- this.aistatus &= ~AI_STATUS_RUNNING;
- // increase stop distance in case the goal is on a slope or a lower platform
- if(bunnyhopdistance > autocvar_bot_ai_bunnyhop_stopdistance + (this.origin.z - gco.z))
- PHYS_INPUT_BUTTON_JUMP(this) = true;
- }
- else
- {
- this.aistatus |= AI_STATUS_RUNNING;
+ if(checkdistance)
+ {
+ this.aistatus &= ~AI_STATUS_RUNNING;
+ // increase stop distance in case the goal is on a slope or a lower platform
+ if(vdist(this.origin - gco, >, autocvar_bot_ai_bunnyhop_stopdistance + (this.origin.z - gco.z)))
PHYS_INPUT_BUTTON_JUMP(this) = true;
- }
+ }
+ else
+ {
+ this.aistatus |= AI_STATUS_RUNNING;
+ PHYS_INPUT_BUTTON_JUMP(this) = true;
}
}
- else
- {
- this.bot_timelastseengoal = time;
- }
+ }
+ else
+ {
+ this.bot_timelastseengoal = time;
+ }
}
else
{
this.bot_timelastseengoal = 0;
}
-
-#if 0
- // Release jump button
- if(!cvar("sv_pogostick"))
- if((IS_ONGROUND(this)) == 0)
- {
- if(this.velocity.z < 0 || vlen(this.velocity)<maxspeed)
- PHYS_INPUT_BUTTON_JUMP(this) = false;
-
- // Strafe
- if(this.aistatus & AI_STATUS_RUNNING)
- if(vlen(this.velocity)>maxspeed)
- {
- deviation = vectoangles(dir) - vectoangles(this.velocity);
- while (deviation.y < -180) deviation.y = deviation.y + 360;
- while (deviation.y > 180) deviation.y = deviation.y - 360;
-
- if(fabs(deviation.y)>10)
- CS(this).movement_x = 0;
-
- if(deviation.y>10)
- CS(this).movement_y = maxspeed * -1;
- else if(deviation.y<10)
- CS(this).movement_y = maxspeed;
-
- }
- }
-#endif
}
// return true when bot isn't getting closer to the current goal
vector havocbot_dodge(entity this);
-.void(entity this) havocbot_role;
-.void(entity this) havocbot_previous_role;
-
void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_items;
void(entity this, float ratingscale, vector org, float sradius) havocbot_goalrating_enemyplayers;
#include "../bot.qh"
#include "../navigation.qh"
-.float bot_ratingscale;
-.float bot_ratingscale_time;
-.float max_armorvalue;
-.float havocbot_role_timeout;
-
-.void(entity this) havocbot_previous_role;
-.void(entity this) havocbot_role;
-
void havocbot_goalrating_waypoints(entity this, float ratingscale, vector org, float sradius)
{
// rate waypoints only if there's no alternative goal
if(!teamplay)
return true;
- // actually these variables hold the squared distances in order to optimize code
- float friend_distance = FLOAT_MAX;
- float enemy_distance = FLOAT_MAX;
- float dist;
+ // these variables hold squared distances in order to optimize code
+ float friend_dist2 = FLOAT_MAX;
+ float enemy_dist2 = FLOAT_MAX;
+ float dist2;
FOREACH_CLIENT(IS_PLAYER(it) && it != this && !(IS_DEAD(it) || STAT(FROZEN, it)),
{
if (!IS_REAL_CLIENT(it))
continue;
- dist = vlen2(it.origin - item_org);
- if(dist > friend_distance)
+ dist2 = vlen2(it.origin - item_org);
+ if (dist2 > friend_dist2)
continue;
if(havocbot_goalrating_item_can_be_left_to_teammate(this, it, item))
{
- friend_distance = dist;
+ friend_dist2 = dist2;
continue;
}
}
{
// If enemy only track distances
// TODO: track only if visible ?
- dist = vlen2(it.origin - item_org);
- if(dist < enemy_distance)
- enemy_distance = dist;
+ dist2 = vlen2(it.origin - item_org);
+ if (dist2 < enemy_dist2)
+ enemy_dist2 = dist2;
}
});
// Rate the item only if no one needs it, or if an enemy is closer to it
- dist = vlen2(item_org - org);
- if ((enemy_distance < friend_distance && dist < enemy_distance) ||
- (friend_distance > autocvar_bot_ai_friends_aware_pickup_radius ** 2) ||
- (dist < friend_distance && dist < 200 ** 2))
+ dist2 = vlen2(item_org - org);
+ if ((enemy_dist2 < friend_dist2 && dist2 < enemy_dist2)
+ || (friend_dist2 > autocvar_bot_ai_friends_aware_pickup_radius ** 2)
+ || (dist2 < friend_dist2 && dist2 < 200 ** 2))
return true;
return false;
};
void havocbot_goalrating_items(entity this, float ratingscale, vector org, float sradius)
{
- float rating;
- vector o;
ratingscale = ratingscale * 0.0001;
IL_EACH(g_items, it.bot_pickup,
it.bot_pickup_respawning = true;
}
- o = (it.absmin + it.absmax) * 0.5;
+ vector o = (it.absmin + it.absmax) * 0.5;
if(vdist(o - org, >, sradius) || (it == this.ignoregoal && time < this.ignoregoaltime) )
continue;
it.bot_ratingscale_time = time;
it.bot_ratingscale = ratingscale;
- rating = it.bot_pickupevalfunc(this, it);
+ float rating = it.bot_pickupevalfunc(this, it);
if(rating > 0)
navigation_routerating(this, it, rating * ratingscale, 2000);
});
}
-#define BOT_RATING_ENEMY 2500
void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org, float sradius)
{
if (autocvar_bot_nofire)
return;
// don't chase players if we're under water
- if(this.waterlevel>WATERLEVEL_WETFEET)
+ if(this.waterlevel > WATERLEVEL_WETFEET)
return;
ratingscale = ratingscale * 0.0001;
- float t;
FOREACH_CLIENT(IS_PLAYER(it) && bot_shouldattack(this, it), {
// TODO: Merge this logic with the bot_shouldattack function
if(vdist(it.origin - org, <, 100) || vdist(it.origin - org, >, sradius))
continue;
*/
- t = ((GetResource(this, RES_HEALTH) + GetResource(this, RES_ARMOR)) - (GetResource(it, RES_HEALTH) + GetResource(it, RES_ARMOR))) / 150;
+ float t = ((GetResource(this, RES_HEALTH) + GetResource(this, RES_ARMOR)) - (GetResource(it, RES_HEALTH) + GetResource(it, RES_ARMOR))) / 150;
t = bound(0, 1 + t, 3);
if (skill > 3)
{
#pragma once
+
+const float BOT_RATING_ENEMY = 2500;
+
+.float bot_ratingscale;
+.float bot_ratingscale_time;
+.float havocbot_role_timeout;
+
+.void(entity this) havocbot_previous_role;
+.void(entity this) havocbot_role;
if (autocvar_g_waypointeditor && autocvar_g_waypointeditor_symmetrical_allowload)
{
+ string sym_str = "";
cvar_set("g_waypointeditor_symmetrical", ftos(sym));
if (sym == 1 && sym_param3 < 2)
cvar_set("g_waypointeditor_symmetrical_order", "0"); // make sure this is reset if not loaded
cvar_set("g_waypointeditor_symmetrical_origin", params);
}
cvar_set("g_waypointeditor_symmetrical_order", ftos(sym_param3));
- LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with origin ", params, " and order ", ftos(sym_param3));
+ sym_str = strcat(ftos(sym), " with origin ", params, " and order ", ftos(sym_param3));
}
else if (sym == -2)
{
string params = strcat(ftos(sym_param1), " ", ftos(sym_param2));
cvar_set("g_waypointeditor_symmetrical_axis", params);
- LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with axis ", params);
+ sym_str = strcat(ftos(sym), " with axis ", params);
}
else
- LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym));
+ sym_str = ftos(sym);
+ if (sym_str != "")
+ LOG_INFO("Waypoint editor: loaded symmetry ", sym_str);
LOG_INFO(strcat("g_waypointeditor_symmetrical", " has been set to ", cvar_string("g_waypointeditor_symmetrical")));
}
SetResource(this.personal, RES_HEALTH, max(1, GetResource(this, RES_HEALTH)));
SetResource(this.personal, RES_ARMOR, GetResource(this, RES_ARMOR));
STAT(WEAPONS, this.personal) = STAT(WEAPONS, this);
+ STAT(BUFFS, this.personal) = STAT(BUFFS, this);
+ STAT(BUFF_TIME, this.personal) = STAT(BUFF_TIME, this);
this.personal.items = this.items;
this.personal.pauserotarmor_finished = this.pauserotarmor_finished;
this.personal.pauserothealth_finished = this.pauserothealth_finished;
SetResource(this, RES_HEALTH, GetResource(this.personal, RES_HEALTH));
SetResource(this, RES_ARMOR, GetResource(this.personal, RES_ARMOR));
STAT(WEAPONS, this) = STAT(WEAPONS, this.personal);
+ STAT(BUFFS, this) = STAT(BUFFS, this.personal);
+ STAT(BUFF_TIME, this) = STAT(BUFF_TIME, this.personal);
this.items = this.personal.items;
this.pauserotarmor_finished = time + this.personal.pauserotarmor_finished - this.personal.teleport_time;
this.pauserothealth_finished = time + this.personal.pauserothealth_finished - this.personal.teleport_time;
#include "../common/mapobjects/teleporters.qh"
#include "../common/mapobjects/target/spawnpoint.qh"
#include <common/mapobjects/trigger/counter.qh>
+#include <common/mapobjects/trigger/swamp.qh>
#include "../common/vehicles/all.qh"
this.pauseregen_finished += f;
}
- this.damageforcescale = 2;
+ this.damageforcescale = autocvar_g_player_damageforcescale;
this.death_time = 0;
this.respawn_flags = 0;
this.respawn_time = 0;
STAT(REVIVE_PROGRESS, this) = 0;
this.revival_time = 0;
+ // TODO: we can't set these in the PlayerSpawn hook since the target code is called before it!
+ STAT(BUFFS, this) = 0;
+ STAT(BUFF_TIME, this) = 0;
+
this.air_finished = time + 12;
this.waterlevel = WATERLEVEL_NONE;
this.watertype = CONTENT_EMPTY;
if(this.conveyor)
IL_REMOVE(g_conveyed, this);
this.conveyor = NULL; // prevent conveyors at the previous location from moving a freshly spawned player
+ if(this.swampslug)
+ delete(this.swampslug);
+ this.in_swamp = false;
STAT(HUD, this) = HUD_NORMAL;
this.event_damage = PlayerDamage;
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
.entity weaponentity = weaponentities[slot];
+ if(WEP_CVAR(vortex, charge_always))
+ W_Vortex_Charge(this, weaponentity, frametime);
W_WeaponFrame(this, weaponentity);
}
ATTRIB(Client, cvar_cl_weaponimpulsemode, int, this.cvar_cl_weaponimpulsemode);
ATTRIB(Client, cvar_g_xonoticversion, string, this.cvar_g_xonoticversion);
ATTRIB(Client, autoswitch, bool, this.autoswitch);
+ ATTRIB(Client, cvar_cl_casings, bool, this.cvar_cl_casings);
ATTRIB(Client, cvar_cl_dodging_timeout, float, this.cvar_cl_dodging_timeout);
ATTRIB(Client, cvar_cl_multijump, bool, this.cvar_cl_multijump);
ATTRIB(Client, cvar_cl_accuracy_data_share, bool, this.cvar_cl_accuracy_data_share);
}
}
+void shuffleteams()
+{
+ if (!teamplay)
+ {
+ LOG_INFO("Can't shuffle teams when currently not playing a team game.");
+ return;
+ }
+
+ FOREACH_CLIENT(IS_PLAYER(it) || it.caplayer, {
+ if (Player_HasRealForcedTeam(it)) {
+ // we could theoretically assign forced players to their teams
+ // and shuffle the rest to fill the empty spots but in practise
+ // either all players or none are gonna have forced teams
+ LOG_INFO("Can't shuffle teams because at least one player has a forced team.");
+ return;
+ }
+ });
+
+ int number_of_teams = 0;
+ entity balance = TeamBalance_CheckAllowedTeams(NULL);
+ for (int i = 1; i <= NUM_TEAMS; ++i)
+ {
+ if (TeamBalance_IsTeamAllowed(balance, i))
+ {
+ number_of_teams = max(i, number_of_teams);
+ }
+ }
+ TeamBalance_Destroy(balance);
+
+ int team_index = 0;
+ FOREACH_CLIENT_RANDOM(IS_PLAYER(it) || it.caplayer, {
+ int target_team_index = team_index + 1;
+ if (Entity_GetTeamIndex(it) != target_team_index)
+ {
+ MoveToTeam(it, target_team_index, 6);
+ }
+ team_index = (team_index + 1) % number_of_teams;
+ });
+
+ bprint("Successfully shuffled the players around randomly.\n");
+}
+
void GameCommand_shuffleteams(int request)
{
switch (request)
{
case CMD_REQUEST_COMMAND:
{
- if (!teamplay)
+ if (shuffleteams_on_reset_map)
{
- LOG_INFO("Can't shuffle teams when currently not playing a team game.");
- return;
+ bprint("Players will be shuffled when this round is over.\n");
+ shuffleteams_on_reset_map = true;
}
-
- FOREACH_CLIENT(IS_PLAYER(it) || it.caplayer, {
- if (Player_HasRealForcedTeam(it)) {
- // we could theoretically assign forced players to their teams
- // and shuffle the rest to fill the empty spots but in practise
- // either all players or none are gonna have forced teams
- LOG_INFO("Can't shuffle teams because at least one player has a forced team.");
- return;
- }
- });
-
- int number_of_teams = 0;
- entity balance = TeamBalance_CheckAllowedTeams(NULL);
- for (int i = 1; i <= NUM_TEAMS; ++i)
- {
- if (TeamBalance_IsTeamAllowed(balance, i))
- {
- number_of_teams = max(i, number_of_teams);
- }
- }
- TeamBalance_Destroy(balance);
-
- int team_index = 0;
- FOREACH_CLIENT_RANDOM(IS_PLAYER(it) || it.caplayer, {
- int target_team_index = team_index + 1;
- if (Entity_GetTeamIndex(it) != target_team_index)
- {
- MoveToTeam(it, target_team_index, 6);
- }
- team_index = (team_index + 1) % number_of_teams;
- });
-
- bprint("Successfully shuffled the players around randomly.\n");
+ else
+ shuffleteams();
return;
}
// Declarations for server side game commands
// =================================================
+bool shuffleteams_on_reset_map;
+void shuffleteams();
+
string GotoMap(string m);
void race_deleteTime(string map, float pos);
round_handler_Reset(game_starttime);
}
+ if (shuffleteams_on_reset_map)
+ {
+ shuffleteams();
+ shuffleteams_on_reset_map = false;
+ }
MUTATOR_CALLHOOK(reset_map_global);
FOREACH_ENTITY_FLOAT_ORDERED(pure_data, false,
#include <common/t_items.qh>
#include <common/mapobjects/triggers.qh>
#include <common/mapobjects/trigger/counter.qh>
+#include <common/mutators/mutator/buffs/buffs.qh>
+#include <common/notifications/all.qh>
#include <common/weapons/_all.qh>
//***********************
{
actor.strength_finished = 0;
actor.invincible_finished = 0;
- STAT(BUFFS, actor) = 0;
+ if(STAT(BUFFS, actor)) // TODO: make a dropbuffs function to handle this
+ {
+ int buffid = buff_FirstFromFlags(STAT(BUFFS, actor)).m_id;
+ Send_Notification(NOTIF_ONE, actor, MSG_MULTI, ITEM_BUFF_DROP, buffid);
+ sound(actor, CH_TRIGGER, SND_BUFF_LOST, VOL_BASE, ATTN_NORM);
+ if(!IS_INDEPENDENT_PLAYER(actor))
+ Send_Notification(NOTIF_ALL_EXCEPT, actor, MSG_INFO, INFO_ITEM_BUFF_LOST, actor.netname, buffid);
+ STAT(BUFFS, actor) = 0;
+ STAT(BUFF_TIME, actor) = 0;
+ }
}
if (!(this.spawnflags & 16))
SetResourceExplicit(this, RES_ARMOR, 100);
else if (it.classname == "item_health_mega")
SetResourceExplicit(this, RES_HEALTH, 200);
+ else if (it.classname == "item_buff") {
+ entity buff = buff_FirstFromFlags(STAT(BUFFS, it));
+ this.netname = cons(this.netname, buff.netname);
+ STAT(BUFF_TIME, this) = it.count;
+ }
+
//remove(it); // removing ents in init functions causes havoc, workaround:
setthink(it, SUB_Remove);
it.nextthink = time;
const int SVC_SETVIEW = 5;
-const int RESPAWN_FORCE = 1;
-const int RESPAWN_SILENT = 2;
-const int RESPAWN_DENY = 4;
+const int RESPAWN_FORCE = BIT(0);
+const int RESPAWN_SILENT = BIT(1);
+const int RESPAWN_DENY = BIT(2);
#define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT)
bool radar_showennemies;
-#ifdef PROFILING
-float client_cefc_accumulator;
-float client_cefc_accumulatortime;
-#endif
-
.float weapon_load[Weapons_MAX];
.int ammo_none; // used by the reloading system, must always be 0
.int clip_load;
UpdateFrags(attacker, f);
}
-.entity kh_next;
-
string AppendItemcodes(string s, entity player)
{
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
s = strcat(s, "S");
if(time < player.invincible_finished)
s = strcat(s, "I");
- if(player.flagcarried != NULL)
- s = strcat(s, "F");
if(PHYS_INPUT_BUTTON_CHAT(player))
s = strcat(s, "T");
- if(player.kh_next)
- s = strcat(s, "K");
+ // TODO: include these codes as a flag on the item itself
+ MUTATOR_CALLHOOK(LogDeath_AppendItemCodes, player, s);
+ s = M_ARGV(1, string);
return s;
}
}
float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe,
- float inflictorselfdamage, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity)
+ float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype, .entity weaponentity, entity directhitentity)
// Returns total damage applies to creatures
{
entity targ;
force = force * (finaldmg / coredamage) * forceintensity;
hitloc = nearest;
- if(deathtype & WEP_BLASTER.m_id)
- force *= WEP_CVAR_BOTH(blaster, !(deathtype & HITTYPE_SECONDARY), force_zscale);
+ // apply special scaling along the z axis if set
+ // NOTE: 0 value is not allowed for compatibility, in the case of weapon cvars not being set
+ if(forcezscale)
+ force.z *= forcezscale;
if(targ != directhitentity)
{
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity)
{
- return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, false, forceintensity, deathtype, weaponentity, directhitentity);
+ return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad,
+ cantbe, mustbe, false, forceintensity, 1, deathtype, weaponentity, directhitentity);
}
bool Heal(entity targ, entity inflictor, float amount, float limit)
void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
float RadiusDamage_running;
-float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity);
+float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype, .entity weaponentity, entity directhitentity);
// Returns total damage applies to creatures
float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity);
#include "../lib/warpzone/common.qh"
#include "../lib/warpzone/server.qh"
-.int state;
-
/*============================================
Wazat's Xonotic Grappling Hook
============================================*/
-.float hook_length;
-
void RemoveGrapplingHooks(entity pl)
{
if(pl.move_movetype == MOVETYPE_FLY)
// (note: you can change the hook impulse #'s to whatever you please)
.float hook_time;
+.float hook_length;
+
const float HOOK_FIRING = BIT(0);
const float HOOK_REMOVING = BIT(1);
const float HOOK_PULLING = BIT(2);
const float HOOK_RELEASING = BIT(3);
const float HOOK_WAITING_FOR_RELEASE = BIT(4);
.float hook_state;
+.int state;
void GrappleHookInit();
vector hook_shotorigin[4];
+
continue;
if(argv(0) == "cd")
{
+ string trackname = argv(2);
LOG_INFO("Found ^1UNSUPPORTED^7 cd loop command in .cfg file; put this line in mapinfo instead:");
- LOG_INFO(" cdtrack ", argv(2));
+ LOG_INFO(" cdtrack ", trackname);
+ if (cvar_value_issafe(trackname))
+ {
+ string newstuff = strcat(clientstuff, "cd loop \"", trackname, "\"\n");
+ strcpy(clientstuff, newstuff);
+ }
}
else if(argv(0) == "fog")
{
string Map_Current_Name;
// NOTE: this now expects the map list to be already tokenized and the count in Map_Count
-float GetMaplistPosition()
+int GetMaplistPosition()
{
- float pos, idx;
- string map;
-
- map = GetMapname();
- idx = autocvar_g_maplist_index;
+ string map = GetMapname();
+ int idx = autocvar_g_maplist_index;
if(idx >= 0)
+ {
if(idx < Map_Count)
+ {
if(map == argv(idx))
+ {
return idx;
+ }
+ }
+ }
- for(pos = 0; pos < Map_Count; ++pos)
+ for(int pos = 0; pos < Map_Count; ++pos)
+ {
if(map == argv(pos))
return pos;
+ }
// resume normal maplist rotation if current map is not in g_maplist
return idx;
void Maplist_Init()
{
- Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
- float i;
- for (i = 0; i < Map_Count; ++i)
- if (Map_Check(i, 2))
- break;
+ float i = Map_Count = 0;
+ if(autocvar_g_maplist != "")
+ {
+ Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
+ for (i = 0; i < Map_Count; ++i)
+ {
+ if (Map_Check(i, 2))
+ break;
+ }
+ }
+
if (i == Map_Count)
{
bprint( "Maplist contains no usable maps! Resetting it to default map list.\n" );
cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags() | MAPINFO_FLAG_NOAUTOMAPLIST));
if(autocvar_g_maplist_shuffle)
ShuffleMaplist();
- localcmd("\nmenu_cmd sync\n");
+ if(!server_is_dedicated)
+ localcmd("\nmenu_cmd sync\n");
Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
}
if(Map_Count == 0)
string GetNextMap()
{
- float nextMap;
-
Maplist_Init();
- nextMap = -1;
+ float nextMap = -1;
if(nextMap == -1)
if(autocvar_g_maplist_shuffle > 0)
return;
alreadychangedlevel = true;
- string nextMap;
-
- nextMap = GetNextMap();
+ string nextMap = GetNextMap();
if(nextMap == "")
error("Everything is broken - cannot find a next map. Please report this to the developers.");
Map_Goto(reinit);
IMPULSE(waypoint_here_crosshair)
{
- WarpZone_crosshair_trace(this);
+ WarpZone_crosshair_trace_plusvisibletriggers(this);
entity wp = WaypointSprite_DeployFixed(WP_Here, false, this, trace_endpos, RADARICON_HERE);
if (wp) WaypointSprite_Ping(wp);
sprint(this, "HERE spawned at crosshair\n");
allow_mutatorblocked = M_ARGV(3, bool);
if(allguns)
- d = boolean(weaponinfo.spawnflags & WEP_FLAG_NORMAL);
+ d = boolean((weaponinfo.spawnflags & WEP_FLAG_NORMAL) && !(weaponinfo.spawnflags & (WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK)));
else if(!mutator_returnvalue)
d = !(!weaponinfo.weaponstart);
g_weaponarena = 1;
g_weaponarena_list = "All Weapons";
FOREACH(Weapons, it != WEP_Null, {
- if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED))
+ if(!(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)))
g_weaponarena_weapons |= (it.m_wepset);
});
}
g_weaponarena = 1;
g_weaponarena_list = "Most Weapons";
FOREACH(Weapons, it != WEP_Null, {
- if(!(it.spawnflags & WEP_FLAG_MUTATORBLOCKED) && (it.spawnflags & WEP_FLAG_NORMAL) && !(it.spawnflags & WEP_FLAG_HIDDEN))
+ if ((it.spawnflags & WEP_FLAG_NORMAL) && !(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_HIDDEN | WEP_FLAG_SPECIALATTACK)))
g_weaponarena_weapons |= (it.m_wepset);
});
}
/**/ o(int, MUTATOR_ARGV_0_int) \
/**/
MUTATOR_HOOKABLE(GetPlayerLimit, EV_GetPlayerLimit);
+
+/** include special item codes for a death to the game log */
+#define EV_LogDeath_AppendItemCodes(i, o) \
+ /** player */ i(entity, MUTATOR_ARGV_0_entity) \
+ /** item codes */ i(string, MUTATOR_ARGV_1_string) \
+ /**/ o(string, MUTATOR_ARGV_1_string) \
+ /**/
+MUTATOR_HOOKABLE(LogDeath_AppendItemCodes, EV_LogDeath_AppendItemCodes);
#include "../common/constants.qh"
#include <common/net_linked.qh>
#include "../common/teams.qh"
+#include <common/mapinfo.qh>
#include "../common/mapobjects/subs.qh"
#include "../common/mapobjects/target/spawnpoint.qh"
#include "../common/util.qh"
}
}
- if(!found)
+ if(!found && !g_cts)
{
LOG_TRACE("WARNING: spawnpoint at ", vtos(spot.origin), " could not find its target ", spot.target);
return '-1 0 0';
/**
Uniform push from a point
**/
-#define steerlib_push(ent,point) normalize(ent.origin - point)
+#define steerlib_push(ent,point) normalize((ent).origin - point)
/*
vector steerlib_push(entity this, vector point)
{
**/
vector steerlib_arrive(entity this, vector point, float maximal_distance)
{
- float distance = bound(0.001,vlen(this.origin - point),maximal_distance);
+ float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
vector direction = normalize(point - this.origin);
return direction * (distance / maximal_distance);
}
**/
vector steerlib_attract(entity this, vector point, float maximal_distance)
{
- float distance = bound(0.001,vlen(this.origin - point),maximal_distance);
+ float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
vector direction = normalize(point - this.origin);
- return direction * (1-(distance / maximal_distance));
+ return direction * (1 - (distance / maximal_distance));
}
-vector steerlib_attract2(entity this, vector point, float min_influense,float max_distance,float max_influense)
+vector steerlib_attract2(entity this, vector point, float min_influense, float max_distance, float max_influense)
{
- float distance = bound(0.00001,vlen(this.origin - point),max_distance);
+ float distance = bound(0.00001, vlen(this.origin - point), max_distance);
vector direction = normalize(point - this.origin);
float influense = 1 - (distance / max_distance);
influense = min_influense + (influense * (max_influense - min_influense));
- return direction * influense;
+ return direction * influense;
}
/*
/**
Move away from a point.
**/
-vector steerlib_repell(entity this, vector point,float maximal_distance)
+vector steerlib_repel(entity this, vector point, float maximal_distance)
{
- float distance;
- vector direction;
-
- distance = bound(0.001,vlen(this.origin - point),maximal_distance);
- direction = normalize(this.origin - point);
+ float distance = bound(0.001, vlen(this.origin - point), maximal_distance);
+ vector direction = normalize(this.origin - point);
- return direction * (1-(distance / maximal_distance));
+ return direction * (1 - (distance / maximal_distance));
}
/**
Try to keep at ideal_distance away from point
**/
-vector steerlib_standoff(entity this, vector point,float ideal_distance)
+vector steerlib_standoff(entity this, vector point, float ideal_distance)
{
- float distance;
vector direction;
-
- distance = vlen(this.origin - point);
-
+ float distance = vlen(this.origin - point);
if(distance < ideal_distance)
{
}
/**
- A random heading in a forward halfcicrle
+ A random heading in a forward semicircle
- use like:
- this.target = steerlib_wander(256,32,this.target)
+ usage:
+ this.target = steerlib_wander(256, 32, this.target)
- where range is the cicrle radius and tresh is how close we need to be to pick a new heading.
+ where range is the circle radius and threshold is how close we need to be to pick a new heading.
+ Assumes v_forward is set by makevectors
**/
-vector steerlib_wander(entity this, float range, float tresh, vector oldpoint)
+vector steerlib_wander(entity this, float range, float threshold, vector oldpoint)
{
- vector wander_point;
- wander_point = v_forward - oldpoint;
+ vector wander_point = v_forward - oldpoint;
- if (vdist(wander_point, >, tresh))
+ if (vdist(wander_point, >, threshold))
return oldpoint;
- range = bound(0,range,1);
+ range = bound(0, range, 1);
wander_point = this.origin + v_forward * 128;
wander_point = wander_point + randomvec() * (range * 128) - randomvec() * (range * 128);
}
/**
- Dodge a point. dont work to well.
+ Dodge a point NOTE: doesn't work well
**/
vector steerlib_dodge(entity this, vector point, vector dodge_dir, float min_distance)
{
- float distance;
-
- distance = max(vlen(this.origin - point),min_distance);
+ float distance = max(vlen(this.origin - point), min_distance);
if (min_distance < distance)
return '0 0 0';
- return dodge_dir * (min_distance/distance);
+ return dodge_dir * (min_distance / distance);
}
/**
Group will move towards the unified direction while keeping close to eachother.
**/
.float flock_id;
-vector steerlib_flock(entity this, float _radius, float standoff,float separation_force,float flock_force)
+vector steerlib_flock(entity this, float _radius, float standoff, float separation_force, float flock_force)
{
- entity flock_member;
vector push = '0 0 0', pull = '0 0 0';
- float ccount = 0;
+ int ccount = 0;
- flock_member = findradius(this.origin, _radius);
+ entity flock_member = findradius(this.origin, _radius);
while(flock_member)
{
if(flock_member != this)
if(flock_member.flock_id == this.flock_id)
{
++ccount;
- push = push + (steerlib_repell(this, flock_member.origin,standoff) * separation_force);
+ push = push + (steerlib_repel(this, flock_member.origin,standoff) * separation_force);
pull = pull + (steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force);
}
flock_member = flock_member.chain;
Group will move towards the unified direction while keeping close to eachother.
xy only version (for ground movers).
**/
-vector steerlib_flock2d(entity this, float _radius, float standoff,float separation_force,float flock_force)
+vector steerlib_flock2d(entity this, float _radius, float standoff, float separation_force, float flock_force)
{
- entity flock_member;
vector push = '0 0 0', pull = '0 0 0';
- float ccount = 0;
+ int ccount = 0;
- flock_member = findradius(this.origin,_radius);
+ entity flock_member = findradius(this.origin,_radius);
while(flock_member)
{
if(flock_member != this)
if(flock_member.flock_id == this.flock_id)
{
++ccount;
- push = push + (steerlib_repell(this, flock_member.origin, standoff) * separation_force);
+ push = push + (steerlib_repel(this, flock_member.origin, standoff) * separation_force);
pull = pull + (steerlib_arrive(this, flock_member.origin + flock_member.velocity, _radius) * flock_force);
}
flock_member = flock_member.chain;
/**
All members want to be in the center, and keep away from eachother.
- The furtehr form the center the more they want to be there.
+ The further from the center the more they want to be there.
This results in a aligned movement (?!) much like flocking.
**/
-vector steerlib_swarm(entity this, float _radius, float standoff,float separation_force,float swarm_force)
+vector steerlib_swarm(entity this, float _radius, float standoff, float separation_force, float swarm_force)
{
- entity swarm_member;
vector force = '0 0 0', center = '0 0 0';
- float ccount = 0;
-
- swarm_member = findradius(this.origin,_radius);
+ int ccount = 0;
+ entity swarm_member = findradius(this.origin,_radius);
while(swarm_member)
{
if(swarm_member.flock_id == this.flock_id)
{
++ccount;
center = center + swarm_member.origin;
- force = force + (steerlib_repell(this, swarm_member.origin,standoff) * separation_force);
+ force = force + (steerlib_repel(this, swarm_member.origin,standoff) * separation_force);
}
swarm_member = swarm_member.chain;
}
Run four tracelines in a forward funnel, bias each diretion negative if something is found there.
You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
**/
-vector steerlib_traceavoid(entity this, float pitch,float length)
+vector steerlib_traceavoid(entity this, float pitch, float length)
{
- vector vup_left,vup_right,vdown_left,vdown_right;
- float fup_left,fup_right,fdown_left,fdown_right;
- vector upwish,downwish,leftwish,rightwish;
- vector v_left,v_down;
-
+ vector v_left = v_right * -1;
+ vector v_down = v_up * -1;
- v_left = v_right * -1;
- v_down = v_up * -1;
-
- vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
- traceline(this.origin, this.origin + vup_left,MOVE_NOMONSTERS,this);
- fup_left = trace_fraction;
+ vector vup_left = (v_forward + (v_left * pitch + v_up * pitch)) * length;
+ traceline(this.origin, this.origin + vup_left, MOVE_NOMONSTERS, this);
+ float fup_left = trace_fraction;
//te_lightning1(NULL,this.origin, trace_endpos);
- vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
- traceline(this.origin,this.origin + vup_right ,MOVE_NOMONSTERS,this);
- fup_right = trace_fraction;
+ vector vup_right = (v_forward + (v_right * pitch + v_up * pitch)) * length;
+ traceline(this.origin, this.origin + vup_right, MOVE_NOMONSTERS, this);
+ float fup_right = trace_fraction;
//te_lightning1(NULL,this.origin, trace_endpos);
- vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
- traceline(this.origin,this.origin + vdown_left,MOVE_NOMONSTERS,this);
- fdown_left = trace_fraction;
+ vector vdown_left = (v_forward + (v_left * pitch + v_down * pitch)) * length;
+ traceline(this.origin, this.origin + vdown_left, MOVE_NOMONSTERS, this);
+ float fdown_left = trace_fraction;
//te_lightning1(NULL,this.origin, trace_endpos);
- vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
- traceline(this.origin,this.origin + vdown_right,MOVE_NOMONSTERS,this);
- fdown_right = trace_fraction;
+ vector vdown_right = (v_forward + (v_right * pitch + v_down * pitch)) * length;
+ traceline(this.origin, this.origin + vdown_right, MOVE_NOMONSTERS, this);
+ float fdown_right = trace_fraction;
//te_lightning1(NULL,this.origin, trace_endpos);
- upwish = v_up * (fup_left + fup_right);
- downwish = v_down * (fdown_left + fdown_right);
- leftwish = v_left * (fup_left + fdown_left);
- rightwish = v_right * (fup_right + fdown_right);
+ vector upwish = v_up * (fup_left + fup_right);
+ vector downwish = v_down * (fdown_left + fdown_right);
+ vector leftwish = v_left * (fup_left + fdown_left);
+ vector rightwish = v_right * (fup_right + fdown_right);
- return (upwish+leftwish+downwish+rightwish) * 0.25;
+ return (upwish + leftwish + downwish + rightwish) * 0.25;
}
/**
Steer towards the direction least obstructed.
Run tracelines in a forward trident, bias each direction negative if something is found there.
+ You need to call makevectors() (or equivalent) before this function to set v_forward and v_right
**/
vector steerlib_traceavoid_flat(entity this, float pitch, float length, vector vofs)
{
- vector vt_left, vt_right,vt_front;
- float f_left, f_right,f_front;
- vector leftwish, rightwish,frontwish, v_left;
+ vector v_left = v_right * -1;
- v_left = v_right * -1;
-
-
- vt_front = v_forward * length;
+ vector vt_front = v_forward * length;
traceline(this.origin + vofs, this.origin + vofs + vt_front,MOVE_NOMONSTERS,this);
- f_front = trace_fraction;
+ float f_front = trace_fraction;
- vt_left = (v_forward + (v_left * pitch)) * length;
+ vector vt_left = (v_forward + (v_left * pitch)) * length;
traceline(this.origin + vofs, this.origin + vofs + vt_left,MOVE_NOMONSTERS,this);
- f_left = trace_fraction;
+ float f_left = trace_fraction;
//te_lightning1(NULL,this.origin, trace_endpos);
- vt_right = (v_forward + (v_right * pitch)) * length;
+ vector vt_right = (v_forward + (v_right * pitch)) * length;
traceline(this.origin + vofs, this.origin + vofs + vt_right ,MOVE_NOMONSTERS,this);
- f_right = trace_fraction;
+ float f_right = trace_fraction;
//te_lightning1(NULL,this.origin, trace_endpos);
- leftwish = v_left * f_left;
- rightwish = v_right * f_right;
- frontwish = v_forward * f_front;
+ vector leftwish = v_left * f_left;
+ vector rightwish = v_right * f_right;
+ vector frontwish = v_forward * f_front;
return normalize(leftwish + rightwish + frontwish);
}
//#define BEAMSTEER_VISUAL
-float beamsweep(entity this, vector from, vector dir,float length, float step,float step_up, float step_down)
+float beamsweep(entity this, vector from, vector dir, float length, float step, float step_up, float step_down)
{
- float i;
- vector a, b, u, d;
-
- u = '0 0 1' * step_up;
- d = '0 0 1' * step_down;
+ vector u = '0 0 1' * step_up;
+ vector d = '0 0 1' * step_down;
traceline(from + u, from - d,MOVE_NORMAL,this);
if(trace_fraction == 1.0)
if(!location_isok(trace_endpos, false, false))
return 0;
- a = trace_endpos;
- for(i = 0; i < length; i += step)
+ vector a = trace_endpos;
+ for(int i = 0; i < length; i += step)
{
- b = a + dir * step;
+ vector b = a + dir * step;
tracebox(a + u,'-4 -4 -4','4 4 4', b + u,MOVE_NORMAL,this);
if(trace_fraction != 1.0)
return i / length;
vector steerlib_beamsteer(entity this, vector dir, float length, float step, float step_up, float step_down)
{
- float bm_forward, bm_right, bm_left,p;
- vector vr,vl;
-
dir.z *= 0.15;
- vr = vectoangles(dir);
- //vr_x *= -1;
+ vector vr = vectoangles(dir);
+ //vr.x *= -1;
tracebox(this.origin + '0 0 1' * step_up, this.mins, this.maxs, ('0 0 1' * step_up) + this.origin + (dir * length), MOVE_NOMONSTERS, this);
if(trace_fraction == 1.0)
{
- //te_lightning1(this,this.origin,this.origin + (dir * length));
+ //te_lightning1(this,this.origin,this.origin + (dir * length));
return dir;
}
makevectors(vr);
- bm_forward = beamsweep(this, this.origin, v_forward, length, step, step_up, step_down);
+ float bm_forward = beamsweep(this, this.origin, v_forward, length, step, step_up, step_down);
vr = normalize(v_forward + v_right * 0.125);
- vl = normalize(v_forward - v_right * 0.125);
+ vector vl = normalize(v_forward - v_right * 0.125);
- bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
- bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
+ float bm_right = beamsweep(this, this.origin, vr, length, step, step_up, step_down);
+ float bm_left = beamsweep(this, this.origin, vl, length, step, step_up, step_down);
-
- p = bm_left + bm_right;
+ float p = bm_left + bm_right;
if(p == 2)
{
//te_lightning1(this,this.origin + '0 0 32',this.origin + '0 0 32' + vr * length);
vl = vl * bm_left;
return normalize(vr + vl);
-
}
#include "../lib/warpzone/common.qh"
#include "../lib/warpzone/server.qh"
-.float lastground;
-.int state;
-
void CreatureFrame_hotliquids(entity this)
{
- if (this.dmgtime < time)
+ if (this.dmgtime >= time)
{
- this.dmgtime = time + autocvar_g_balance_contents_damagerate;
+ return;
+ }
- if (this.flags & FL_PROJECTILE)
- {
- if (this.watertype == CONTENT_LAVA)
- Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
- else if (this.watertype == CONTENT_SLIME)
- Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
- }
- else
+ this.dmgtime = time + autocvar_g_balance_contents_damagerate;
+
+ if (this.flags & FL_PROJECTILE)
+ {
+ if (this.watertype == CONTENT_LAVA)
+ Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ else if (this.watertype == CONTENT_SLIME)
+ Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ }
+ else
+ {
+ if (this.watertype == CONTENT_LAVA)
{
- if (this.watertype == CONTENT_LAVA)
+ if (this.watersound_finished < time)
{
- if (this.watersound_finished < time)
- {
- this.watersound_finished = time + 0.5;
- sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
- }
- Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
- if(autocvar_g_balance_contents_playerdamage_lava_burn)
- Fire_AddDamage(this, NULL, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
+ this.watersound_finished = time + 0.5;
+ sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
}
- else if (this.watertype == CONTENT_SLIME)
+ Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ if(autocvar_g_balance_contents_playerdamage_lava_burn)
+ Fire_AddDamage(this, NULL, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
+ }
+ else if (this.watertype == CONTENT_SLIME)
+ {
+ if (this.watersound_finished < time)
{
- if (this.watersound_finished < time)
- {
- this.watersound_finished = time + 0.5;
- sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
- }
- Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ this.watersound_finished = time + 0.5;
+ sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
}
+ Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
}
}
}
void CreatureFrame_FallDamage(entity this)
{
- if(!IS_VEHICLE(this) && !(this.flags & FL_PROJECTILE)) // vehicles don't get falling damage
- if(this.velocity || this.oldvelocity) // moving or has moved
+ if(IS_VEHICLE(this) || (this.flags & FL_PROJECTILE))
+ return; // vehicles and projectiles don't receive fall damage
+ if(!(this.velocity || this.oldvelocity))
+ return; // if the entity hasn't moved and isn't moving, then don't do anything
+
+ // check for falling damage
+ float velocity_len = vlen(this.velocity);
+ bool have_hook = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
- // check for falling damage
- float velocity_len = vlen(this.velocity);
- bool have_hook = false;
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).hook && this.(weaponentity).hook.state)
{
- .entity weaponentity = weaponentities[slot];
- if(this.(weaponentity).hook && this.(weaponentity).hook.state)
- {
- have_hook = true;
- break;
- }
+ have_hook = true;
+ break;
}
- if(!have_hook)
- {
- float dm = vlen(this.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
- if (IS_DEAD(this))
- dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
- else
- dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
- if (dm > 0)
- Damage (this, NULL, NULL, dm, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
- }
-
- if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
- Damage (this, NULL, NULL, 100000, DEATH_SHOOTING_STAR.m_id, DMG_NOWEP, this.origin, '0 0 0');
}
+ if(!have_hook)
+ {
+ float dm = vlen(this.oldvelocity) - velocity_len; // dm is now the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
+ if (IS_DEAD(this))
+ dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
+ else
+ dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
+ if (dm > 0)
+ Damage (this, NULL, NULL, dm, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ }
+
+ if(autocvar_g_maxspeed > 0 && velocity_len > autocvar_g_maxspeed)
+ Damage (this, NULL, NULL, 100000, DEATH_SHOOTING_STAR.m_id, DMG_NOWEP, this.origin, '0 0 0');
}
void CreatureFrame_All()
bool expr_evaluate(string s);
+#ifdef PROFILING
+float client_cefc_accumulator;
+float client_cefc_accumulatortime;
+#endif
+
/*
==================
main
void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector end, float bdamage, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype)
{
- entity pseudoprojectile = NULL;
-
vector dir = normalize(end - start);
- //float max_length = vlen(end - start);
vector force = dir * bforce;
// go a little bit into the wall because we need to hit this wall later
it.solid = it.railgunhitsolidbackup;
});
- // spawn a temporary explosion entity for RadiusDamage calls
- //explosion = spawn();
+ // Find all players the beam passed close by (even those hit)
+ float length = vlen(endpoint - start);
+ entity pseudoprojectile = NULL;
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != this, {
+ // not when spectating the shooter
+ if (IS_SPEC(it) && it.enemy == this) continue;
- // Find all non-hit players the beam passed close by
- float length = vlen(trace_endpos - start);
- if(deathtype == WEP_VAPORIZER.m_id || deathtype == WEP_VORTEX.m_id) // WEAPONTODO
- {
- FOREACH_CLIENT(IS_REAL_CLIENT(it) && it != this, {
- if (!it.railgunhit && !(IS_SPEC(it) && it.enemy == this))
- {
- // nearest point on the beam
- vector beampos = start + dir * bound(0, (it.origin - start) * dir, length);
+ // nearest point on the beam
+ vector beampos = start + dir * bound(0, (it.origin - start) * dir, length);
- float f = bound(0, 1 - vlen(beampos - it.origin) / 512, 1);
- if(f <= 0)
- continue;
+ if(!pseudoprojectile)
+ pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume
- if(!pseudoprojectile)
- pseudoprojectile = spawn(); // we need this so the sound uses the "entchannel4" volume
- msg_entity = it;
- soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, SND(NEXWHOOSH_RANDOM()), VOL_BASE * f, ATTEN_NONE);
- }
- });
-
- if(pseudoprojectile)
- delete(pseudoprojectile);
- }
+ msg_entity = it;
+ // we want this to be very loud when close but fall off quickly -> using max base volume and high attenuation
+ soundtoat(MSG_ONE, pseudoprojectile, beampos, CH_SHOTS, SND(NEXWHOOSH_RANDOM()), VOL_BASEVOICE, ATTEN_IDLE);
+ });
+ if(pseudoprojectile)
+ delete(pseudoprojectile);
// find all the entities the railgun hit and hurt them
IL_EACH(g_railgunhit, it.railgunhit,
{
// removal from the list is handled below
- // get the details we need to call the damage function
- vector hitloc = it.railgunhitloc;
-
float foff = ExponentialFalloff(mindist, maxdist, halflifedist, it.railgundistance);
float ffs = ExponentialFalloff(mindist, maxdist, forcehalflifedist, it.railgundistance);
// apply the damage
if (it.takedamage)
- Damage (it, this, this, bdamage * foff, deathtype, weaponentity, hitloc, it.railgunforce * ffs);
-
- // create a small explosion to throw gibs around (if applicable)
- //setorigin(explosion, hitloc);
- //RadiusDamage (explosion, this, 10, 0, 50, NULL, NULL, 300, deathtype);
+ Damage(it, this, this, bdamage * foff, deathtype, weaponentity, it.railgunhitloc, it.railgunforce * ffs);
it.railgunhitloc = '0 0 0';
it.railgunhitsolidbackup = SOLID_NOT;
exec physicsXDF.cfg
// general gameplay
-// set g_jump_grunt 1 // just no
-set g_shootfromcenter 1 // hit where you point at with the crosshair (almost so, no shooteye because it's really ugly)
-set g_balance_kill_antispam 0
-set g_forced_respawn 1
+// g_jump_grunt 1 // just no
+g_shootfromcenter 1 // hit where you point at with the crosshair (almost so, no shooteye because it's really ugly)
+g_balance_kill_antispam 0
+g_forced_respawn 1
// g_playerclip_collisions 0 // do not check playerclips
-set g_powerups 0 // set to -1 or patch xonotic
-set g_spawnpoints_auto_move_out_of_solid 1
-set g_start_delay 3
-set g_use_ammunition 0 "if set to 0 all weapons have unlimited ammunition"
-set g_weapon_stay 1 "1: ghost weapons can be picked up too but give no ammo, 2: ghost weapons refill ammo to one pickup size, thrown guns have no ammo"
-set teamplay_mode 2 // friendly fire and self damage
-set sv_vote_nospectators 1
-set timelimit_override 20
-set g_buffs_cooldown_respawn 0.1
+g_powerups 0 // set to -1 or patch xonotic
+g_spawnpoints_auto_move_out_of_solid 1
+g_start_delay 3
+g_use_ammunition 0 "if set to 0 all weapons have unlimited ammunition"
+g_weapon_stay 1 "1: ghost weapons can be picked up too but give no ammo, 2: ghost weapons refill ammo to one pickup size, thrown guns have no ammo"
+teamplay_mode 2 // friendly fire and self damage
+sv_vote_nospectators 1
+timelimit_override 20
+g_buffs_cooldown_respawn 0.1
+g_buffs_randomize 0
// game mode settings
-set g_cts_finish_kill_delay 2
-set g_cts_respawn_delay 0
-set g_cts_selfdamage 0
+g_cts_finish_kill_delay 2
+g_cts_selfdamage 0
exec balance-xpm.cfg
// general gameplay
-set g_norecoil 1
-set g_shootfromeye 1 // hit where you point at with the crosshair (promoders don't care about ugliness)
-set g_balance_kill_antispam 0
-set g_forced_respawn 1
-set teamplay_mode 2 // friendly fire and self damage
-set sv_vote_nospectators 1
-set g_chat_nospectators 2
-set g_warmup 1
-set g_warmup_limit 0
-set g_balance_teams 0
-set g_spawnshieldtime 0
-set g_spawn_furthest 1
-set sv_autoscreenshot 1
-set sv_ready_restart 1
-set sv_ready_restart_after_countdown 1
-set g_monsters 0
-set g_turrets 0
-set g_vehicles 0
-set sv_showspectators 0
-set sv_taunt 0
+g_norecoil 1
+g_shootfromeye 1 // hit where you point at with the crosshair (promoders don't care about ugliness)
+g_balance_kill_antispam 0
+g_forced_respawn 1
+teamplay_mode 2 // friendly fire and self damage
+sv_vote_nospectators 1
+g_chat_nospectators 2
+g_warmup 1
+g_warmup_limit 0
+g_balance_teams 0
+g_spawnshieldtime 0
+g_spawn_furthest 1
+sv_autoscreenshot 1
+sv_ready_restart 1
+sv_ready_restart_after_countdown 1
+g_monsters 0
+g_turrets 0
+g_vehicles 0
+sv_showspectators 0
+sv_taunt 0
exec randomitems-overkill.cfg
if_dedicated exec help-overkill.cfg
-// general gameplay
-set g_overkill 1
+g_overkill 1
+
+g_use_ammunition 0
// hack - eventually, we should be able to choose overkill models in menu like for vanilla
-set sv_defaultcharacter 1
-set sv_defaultplayermodel "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
-set sv_defaultplayermodel_red "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
-set sv_defaultplayermodel_blue "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
-set sv_defaultplayermodel_yellow "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
-set sv_defaultplayermodel_pink "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
-
-set g_respawn_ghosts 0
-
-set g_nades 1
-set g_nades_nade_small 1
-set g_nades_spread 0
-set g_nades_nade_refire 10
-set g_nades_nade_newton_style 2
-
-set g_dodging 1
-set sv_dodging_wall_dodging 1
-
-set g_spawn_near_teammate "!g_assault !g_freezetag"
-set g_spawn_near_teammate_ignore_spawnpoint 1
-set g_spawnshieldtime 0.5
-set g_respawn_delay_forced 2
-
-set g_lms_start_armor 100
+sv_defaultcharacter 1
+sv_defaultplayermodel "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
+sv_defaultplayermodel_red "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
+sv_defaultplayermodel_blue "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
+sv_defaultplayermodel_yellow "models/ok_player/okrobot1.dpm models/ok_player/okrobot2.dpm models/ok_player/okrobot3.dpm models/ok_player/okrobot4.dpm"
+sv_defaultplayermodel_pink "models/ok_player/okmale1.dpm models/ok_player/okmale2.dpm models/ok_player/okmale3.dpm models/ok_player/okmale4.dpm"
+
+g_fullbrightplayers 1
+g_respawn_ghosts 0
+
+g_nades 1
+g_nades_nade_small 1
+g_nades_spread 0
+g_nades_nade_refire 10
+g_nades_nade_newton_style 2
+
+g_dodging 1
+sv_dodging_wall_dodging 1
+
+g_spawn_near_teammate "!g_assault !g_freezetag"
+g_spawn_near_teammate_ignore_spawnpoint 1
+g_spawnshieldtime 0.5
+g_respawn_delay_forced 2
+
+g_buffs_resistance_blockpercent 0.5
seta g_waypointsprite_turrets 1 "disable turret waypoints"
seta g_waypointsprite_turrets_maxdist 5000 "max distance for turret waypoints"
seta g_waypointsprite_turrets_text 0 "show the turret's name in the waypoint"
+seta g_waypointsprite_turrets_onlyhurt 0 "only show the turret waypoint for a short period after being hurt"
seta g_waypointsprite_uppercase 1
seta g_waypointsprite_text 0 "Always show text instead of icons, setting this to 0 will still use text if the icon is unavailable"
seta g_waypointsprite_iconsize 32
set g_cloaked 0 "display all players mostly invisible"
set g_player_alpha 1 "default opacity of players"
set g_player_brightness 0 "set to 2 for brighter players"
+set g_player_damageforcescale 2 "push multiplier of attacks against players"
set g_balance_cloaked_alpha 0.25 "opacity of cloaked players"
set g_playerclip_collisions 1 "0 = disable collision testing against playerclips, might be useful on some defrag maps"