From: Martin Taibr Date: Sat, 17 Aug 2019 18:30:52 +0000 (+0200) Subject: Merge branch 'master' into martin-t/globals X-Git-Tag: xonotic-v0.8.5~1258^2 X-Git-Url: http://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=8e69041898af22d651b6416745431cbaab84b0d5;hp=bb6fa20d3416affe3876a5a42b289a0d28c22bc1 Merge branch 'master' into martin-t/globals --- diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 83373af9b3..22bfe39d76 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -29,7 +29,7 @@ test_sv_game: - 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 '^:' diff --git a/.tx/merge-base b/.tx/merge-base index c0a2b39ecd..27d0db5ace 100644 --- a/.tx/merge-base +++ b/.tx/merge-base @@ -1 +1 @@ -Mon Jul 15 07:24:31 CEST 2019 +Tue Jul 30 07:24:47 CEST 2019 diff --git a/_hud_common.cfg b/_hud_common.cfg index 9c29d18921..c860be99ce 100644 --- a/_hud_common.cfg +++ b/_hud_common.cfg @@ -117,7 +117,7 @@ seta hud_panel_scoreboard_minwidth 0.6 "minimum width of the scoreboard" seta hud_panel_scoreboard_accuracy_showdelay 2 "how long to delay displaying accuracy below the scoreboard if it's too far down" seta hud_panel_scoreboard_accuracy_showdelay_minpos 0.75 "delay displaying the accuracy panel only if its position is lower than this percentage of the screen height from the top" -seta hud_panel_scoreboard_team_size_position 0 "where to show the team size (0 = do not show, 1 = left of scoreboard, 2 = right of scoreboard, and move team scores to the right)" +seta hud_panel_scoreboard_team_size_position 0 "where to show the team size (0 = do not show, 1 = left of scoreboard, 2 = right of scoreboard), will move team scores to the other side if necessary" // hud panel aliases alias quickmenu "cl_cmd hud quickmenu ${* ?}" diff --git a/bal-wep-mario.cfg b/bal-wep-mario.cfg index 45a75349be..69ea365681 100644 --- a/bal-wep-mario.cfg +++ b/bal-wep-mario.cfg @@ -2,7 +2,7 @@ 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 @@ -43,6 +43,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 70 set g_balance_shotgun_secondary_force 200 @@ -56,8 +58,6 @@ 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 "" @@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1 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 @@ -260,8 +260,8 @@ set g_balance_crylink_secondary_ammo 3 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 @@ -278,7 +278,7 @@ set g_balance_crylink_secondary_other_lifetime 2 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 @@ -448,6 +448,7 @@ set g_balance_vaporizer_secondary_damage 25 set g_balance_vaporizer_secondary_delay 0 set g_balance_vaporizer_secondary_edgedamage 12.5 set g_balance_vaporizer_secondary_force 400 +set g_balance_vaporizer_secondary_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 @@ -678,7 +679,7 @@ set g_balance_seeker_weaponstart 0 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 @@ -745,12 +746,7 @@ set g_balance_arc_beam_healing_amax 0 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 @@ -773,6 +769,11 @@ set g_balance_arc_burst_ammo 15 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 "" @@ -780,7 +781,7 @@ 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 @@ -797,6 +798,7 @@ 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_zscale 1 set g_balance_okhmg_secondary_lifetime 5 set g_balance_okhmg_secondary_radius 70 set g_balance_okhmg_secondary_refire 0.7 @@ -811,74 +813,7 @@ set g_balance_okhmg_weaponstart 0 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 @@ -894,6 +829,7 @@ 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 @@ -908,7 +844,7 @@ set g_balance_okmachinegun_weaponstart 0 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 @@ -943,13 +879,14 @@ 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_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 @@ -960,3 +897,72 @@ 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_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 +// }}} diff --git a/bal-wep-nexuiz25.cfg b/bal-wep-nexuiz25.cfg index b1a83000f6..ccf1a7de96 100644 --- a/bal-wep-nexuiz25.cfg +++ b/bal-wep-nexuiz25.cfg @@ -43,6 +43,8 @@ set g_balance_shotgun_primary_spread 0.07 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 @@ -56,8 +58,6 @@ 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.15 set g_balance_shotgun_switchdelay_raise 0.15 set g_balance_shotgun_weaponreplace "" @@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1 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 set g_balance_machinegun_first 1 set g_balance_machinegun_first_ammo 1 set g_balance_machinegun_first_damage 30 @@ -345,7 +345,7 @@ set g_balance_hagar_primary_lifetime 30 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 @@ -448,6 +448,7 @@ set g_balance_vaporizer_secondary_damage 25 set g_balance_vaporizer_secondary_delay 0 set g_balance_vaporizer_secondary_edgedamage 12.5 set g_balance_vaporizer_secondary_force 400 +set g_balance_vaporizer_secondary_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 @@ -678,7 +679,7 @@ set g_balance_seeker_weaponstart 0 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 @@ -745,12 +746,7 @@ set g_balance_arc_beam_healing_amax 100 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 @@ -773,6 +769,11 @@ set g_balance_arc_burst_ammo 15 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 "" @@ -780,7 +781,7 @@ 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 @@ -797,6 +798,7 @@ 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_zscale 1 set g_balance_okhmg_secondary_lifetime 5 set g_balance_okhmg_secondary_radius 70 set g_balance_okhmg_secondary_refire 0.7 @@ -811,7 +813,91 @@ set g_balance_okhmg_weaponstart 0 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 @@ -833,6 +919,7 @@ 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 @@ -847,3 +934,35 @@ 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 +// }}} diff --git a/bal-wep-overkill-nerfed.cfg b/bal-wep-overkill-nerfed.cfg index e4fb022369..c5300f47bb 100644 --- a/bal-wep-overkill-nerfed.cfg +++ b/bal-wep-overkill-nerfed.cfg @@ -18,6 +18,7 @@ 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 @@ -48,6 +49,7 @@ 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 @@ -98,6 +100,7 @@ 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 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 diff --git a/bal-wep-samual.cfg b/bal-wep-samual.cfg index 1816f3f2e9..4549f99c70 100644 --- a/bal-wep-samual.cfg +++ b/bal-wep-samual.cfg @@ -4,6 +4,7 @@ set g_balance_blaster_primary_damage 25 set g_balance_blaster_primary_delay 0 set g_balance_blaster_primary_edgedamage 12.5 set g_balance_blaster_primary_force 300 +set g_balance_blaster_primary_force_zscale 1 set g_balance_blaster_primary_lifetime 5 set g_balance_blaster_primary_radius 70 set g_balance_blaster_primary_refire 0.7 @@ -16,6 +17,7 @@ set g_balance_blaster_secondary_damage 25 set g_balance_blaster_secondary_delay 0 set g_balance_blaster_secondary_edgedamage 12.5 set g_balance_blaster_secondary_force 300 +set g_balance_blaster_secondary_force_zscale 1 set g_balance_blaster_secondary_lifetime 5 set g_balance_blaster_secondary_radius 70 set g_balance_blaster_secondary_refire 0.7 @@ -29,64 +31,47 @@ set g_balance_blaster_weaponstart 1 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 set g_balance_machinegun_first 1 set g_balance_machinegun_first_ammo 1 set g_balance_machinegun_first_damage 14 @@ -243,58 +228,7 @@ set g_balance_electro_weaponstart 0 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 @@ -354,7 +288,7 @@ set g_balance_crylink_weaponstart 0 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_animlimit 0.5 set g_balance_vortex_charge_limit 1 @@ -400,7 +334,7 @@ set g_balance_vortex_weaponstart 0 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 @@ -444,7 +378,7 @@ set g_balance_hagar_weaponstart 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 @@ -483,7 +417,7 @@ set g_balance_devastator_weaponstart 0 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 @@ -500,7 +434,7 @@ set g_balance_porto_weaponstart 0 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 @@ -514,6 +448,7 @@ set g_balance_vaporizer_secondary_damage 25 set g_balance_vaporizer_secondary_delay 0 set g_balance_vaporizer_secondary_edgedamage 12.5 set g_balance_vaporizer_secondary_force 400 +set g_balance_vaporizer_secondary_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 @@ -527,7 +462,7 @@ set g_balance_vaporizer_weaponstart 0 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 @@ -554,7 +489,7 @@ set g_balance_hook_weaponstart 0 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 @@ -590,7 +525,7 @@ set g_balance_hlac_weaponstart 0 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 @@ -608,7 +543,7 @@ set g_balance_tuba_weaponstart 0 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 @@ -643,7 +578,7 @@ set g_balance_rifle_weaponstart 0 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 @@ -684,7 +619,7 @@ set g_balance_fireball_weaponstart 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 @@ -744,41 +679,109 @@ set g_balance_seeker_weaponstart 0 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 @@ -795,6 +798,7 @@ 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_zscale 1 set g_balance_okhmg_secondary_lifetime 5 set g_balance_okhmg_secondary_radius 70 set g_balance_okhmg_secondary_refire 0.7 @@ -809,7 +813,91 @@ set g_balance_okhmg_weaponstart 0 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 @@ -831,6 +919,7 @@ 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 @@ -845,3 +934,35 @@ 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 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 +// }}} diff --git a/bal-wep-xdf.cfg b/bal-wep-xdf.cfg index 13bdc529a9..62d1cbb44a 100644 --- a/bal-wep-xdf.cfg +++ b/bal-wep-xdf.cfg @@ -43,6 +43,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 70 set g_balance_shotgun_secondary_force 200 @@ -56,8 +58,6 @@ 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 set g_balance_shotgun_switchdelay_raise 0 set g_balance_shotgun_weaponreplace "" @@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1 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 @@ -448,6 +448,7 @@ set g_balance_vaporizer_secondary_damage 25 set g_balance_vaporizer_secondary_delay 0 set g_balance_vaporizer_secondary_edgedamage 12.5 set g_balance_vaporizer_secondary_force 400 +set g_balance_vaporizer_secondary_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 @@ -678,7 +679,7 @@ set g_balance_seeker_weaponstart 0 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 @@ -745,12 +746,7 @@ set g_balance_arc_beam_healing_amax 0 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 @@ -773,6 +769,11 @@ set g_balance_arc_burst_ammo 15 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 "" @@ -780,7 +781,7 @@ 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 @@ -797,6 +798,7 @@ 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_zscale 1 set g_balance_okhmg_secondary_lifetime 5 set g_balance_okhmg_secondary_radius 70 set g_balance_okhmg_secondary_refire 0.7 @@ -811,7 +813,91 @@ set g_balance_okhmg_weaponstart 0 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 @@ -833,6 +919,7 @@ 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 @@ -847,3 +934,35 @@ 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 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 +// }}} diff --git a/bal-wep-xonotic.cfg b/bal-wep-xonotic.cfg index 5c6ace7abd..44ca94b9bd 100644 --- a/bal-wep-xonotic.cfg +++ b/bal-wep-xonotic.cfg @@ -43,6 +43,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 70 set g_balance_shotgun_secondary_force 200 @@ -56,8 +58,6 @@ 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 "" @@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1 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 @@ -448,6 +448,7 @@ set g_balance_vaporizer_secondary_damage 25 set g_balance_vaporizer_secondary_delay 0 set g_balance_vaporizer_secondary_edgedamage 12.5 set g_balance_vaporizer_secondary_force 400 +set g_balance_vaporizer_secondary_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 @@ -678,7 +679,7 @@ set g_balance_seeker_weaponstart 0 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 @@ -745,12 +746,7 @@ set g_balance_arc_beam_healing_amax 0 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 @@ -773,6 +769,11 @@ set g_balance_arc_burst_ammo 15 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 "" @@ -780,7 +781,7 @@ 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 @@ -797,6 +798,7 @@ 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_zscale 1 set g_balance_okhmg_secondary_lifetime 5 set g_balance_okhmg_secondary_radius 70 set g_balance_okhmg_secondary_refire 0.7 @@ -811,74 +813,7 @@ set g_balance_okhmg_weaponstart 0 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 @@ -894,6 +829,7 @@ 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 @@ -908,7 +844,7 @@ set g_balance_okmachinegun_weaponstart 0 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 @@ -943,13 +879,14 @@ 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_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 @@ -960,3 +897,72 @@ 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_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 +// }}} diff --git a/bal-wep-xpm.cfg b/bal-wep-xpm.cfg index a5438d1b7c..5152579ab3 100644 --- a/bal-wep-xpm.cfg +++ b/bal-wep-xpm.cfg @@ -43,6 +43,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 70 set g_balance_shotgun_secondary_force 200 @@ -56,8 +58,6 @@ 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 "" @@ -65,13 +65,13 @@ set g_balance_shotgun_weaponstart 1 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 @@ -448,6 +448,7 @@ set g_balance_vaporizer_secondary_damage 25 set g_balance_vaporizer_secondary_delay 0 set g_balance_vaporizer_secondary_edgedamage 12.5 set g_balance_vaporizer_secondary_force 400 +set g_balance_vaporizer_secondary_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 @@ -678,7 +679,7 @@ set g_balance_seeker_weaponstart 0 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 @@ -745,12 +746,7 @@ set g_balance_arc_beam_healing_amax 0 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 @@ -773,6 +769,11 @@ set g_balance_arc_burst_ammo 15 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 "" @@ -780,7 +781,7 @@ 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 @@ -797,6 +798,7 @@ 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_zscale 1 set g_balance_okhmg_secondary_lifetime 5 set g_balance_okhmg_secondary_radius 70 set g_balance_okhmg_secondary_refire 0.7 @@ -811,7 +813,91 @@ set g_balance_okhmg_weaponstart 0 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 @@ -833,6 +919,7 @@ 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 @@ -847,3 +934,35 @@ 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 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 +// }}} diff --git a/common.zh_CN.po b/common.zh_CN.po index e7d502a567..5ba567a63f 100644 --- a/common.zh_CN.po +++ b/common.zh_CN.po @@ -18,8 +18,8 @@ msgstr "" "Project-Id-Version: Xonotic\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2019-05-19 07:23+0200\n" -"PO-Revision-Date: 2019-06-14 06:43+0000\n" -"Last-Translator: Liang Liu \n" +"PO-Revision-Date: 2019-07-30 05:15+0000\n" +"Last-Translator: 杜茂森 \n" "Language-Team: Chinese (China) (http://www.transifex.com/team-xonotic/" "xonotic/language/zh_CN/)\n" "Language: zh_CN\n" @@ -394,11 +394,11 @@ msgstr "QMCMD^掉落武器, icon" #: qcsrc/client/hud/panel/quickmenu.qc:806 msgid "QMCMD^dropped weapon %w^7 (l:%l^7)" -msgstr "" +msgstr "QMCMD^掉落武器 %w^7 (l:%l^7)" #: qcsrc/client/hud/panel/quickmenu.qc:807 msgid "QMCMD^drop flag/key, icon" -msgstr "" +msgstr "QMCMD^掉落旗帜/钥匙, icon" #: qcsrc/client/hud/panel/quickmenu.qc:807 msgid "QMCMD^dropped flag/key %w^7 (l:%l^7)" diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index 9300293408..59ecb04d23 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -268,7 +268,6 @@ bool autocvar_hud_panel_infomessages_flip; 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; diff --git a/qcsrc/client/hud/panel/modicons.qc b/qcsrc/client/hud/panel/modicons.qc index 306bb6f8a3..18ec37d47e 100644 --- a/qcsrc/client/hud/panel/modicons.qc +++ b/qcsrc/client/hud/panel/modicons.qc @@ -9,8 +9,6 @@ // 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); @@ -84,405 +82,6 @@ void HUD_Mod_CA(vector myPos, vector mySize) } } -// 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 @@ -629,87 +228,6 @@ void HUD_Mod_Race(vector pos, vector mySize) } } -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= rows) - { - row = 0; - ++column; - } - } -} - void HUD_ModIcons_SetFunc() { HUD_ModIcons_GameType = gametype.m_modicons; diff --git a/qcsrc/client/hud/panel/modicons.qh b/qcsrc/client/hud/panel/modicons.qh index 6db88c68b3..c90c0991f5 100644 --- a/qcsrc/client/hud/panel/modicons.qh +++ b/qcsrc/client/hud/panel/modicons.qh @@ -1,2 +1,4 @@ #pragma once #include "../panel.qh" + +bool mod_active; // is there any active mod icon? diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc index 93162f6bcc..e11a134558 100644 --- a/qcsrc/client/hud/panel/scoreboard.qc +++ b/qcsrc/client/hud/panel/scoreboard.qc @@ -1167,7 +1167,7 @@ vector Scoreboard_AccuracyStats_Draw(vector pos, vector rgb, vector bg_size) } 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; diff --git a/qcsrc/client/hud/panel/weapons.qc b/qcsrc/client/hud/panel/weapons.qc index 3f67787020..ac32e23cb9 100644 --- a/qcsrc/client/hud/panel/weapons.qc +++ b/qcsrc/client/hud/panel/weapons.qc @@ -30,7 +30,7 @@ int weaponorder_cmp(int i, int j, entity pass) 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; \ @@ -123,7 +123,7 @@ void HUD_Weapons() { 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; @@ -418,8 +418,11 @@ void HUD_Weapons() } 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 diff --git a/qcsrc/client/view.qc b/qcsrc/client/view.qc index 70111b397f..dadf6069ab 100644 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@ -602,7 +602,7 @@ float TrueAimCheck(entity wepent) { 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; diff --git a/qcsrc/common/gamemodes/gamemode/assault/sv_assault.qc b/qcsrc/common/gamemodes/gamemode/assault/sv_assault.qc index 835073d07d..9a9a654de9 100644 --- a/qcsrc/common/gamemodes/gamemode/assault/sv_assault.qc +++ b/qcsrc/common/gamemodes/gamemode/assault/sv_assault.qc @@ -1,5 +1,7 @@ #include "sv_assault.qh" +#include + .entity sprite; #define AS_ROUND_DELAY 5 @@ -347,7 +349,6 @@ bool destructible_heal(entity targ, entity inflictor, float amount, float limit) return true; } -spawnfunc(func_breakable); spawnfunc(func_assault_destructible) { if (!g_assault) { delete(this); return; } diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc index 4105f7ce8c..0a8370899d 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc +++ b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qc @@ -505,3 +505,9 @@ MUTATOR_HOOKFUNCTION(ca, SetWeaponArena) // most weapons arena if (M_ARGV(0, string) == "0" || M_ARGV(0, string) == "") M_ARGV(0, string) = "most"; } + +MUTATOR_HOOKFUNCTION(ca, SV_ParseServerCommand) +{ + shuffleteams_on_reset_map = !allowed_to_spawn; + return false; +} diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh index c4755feee9..e383687fcf 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh +++ b/qcsrc/common/gamemodes/gamemode/clanarena/sv_clanarena.qh @@ -3,6 +3,7 @@ #include #include #include +#include int autocvar_g_ca_point_limit; int autocvar_g_ca_point_leadlimit; diff --git a/qcsrc/common/gamemodes/gamemode/ctf/_mod.inc b/qcsrc/common/gamemodes/gamemode/ctf/_mod.inc index 7bc5a9679c..c6d756fbb8 100644 --- a/qcsrc/common/gamemodes/gamemode/ctf/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/ctf/_mod.inc @@ -1,4 +1,7 @@ // generated file; do not modify +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/ctf/_mod.qh b/qcsrc/common/gamemodes/gamemode/ctf/_mod.qh index e7fcea7bcf..9a1d181193 100644 --- a/qcsrc/common/gamemodes/gamemode/ctf/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/ctf/_mod.qh @@ -1,5 +1,8 @@ // generated file; do not modify #include +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qc b/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qc new file mode 100644 index 0000000000..c82e0bce93 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qc @@ -0,0 +1,198 @@ +#include "cl_ctf.qh" + +#include + +// 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 +} diff --git a/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qh b/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qh new file mode 100644 index 0000000000..1cf4bcfc26 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/ctf/cl_ctf.qh @@ -0,0 +1,6 @@ +#pragma once + +#include "ctf.qh" + +void HUD_Mod_CTF_Reset(); +void HUD_Mod_CTF(vector pos, vector mySize); diff --git a/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc b/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc index 2484240a26..939c70e29e 100644 --- a/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc +++ b/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc @@ -2593,6 +2593,13 @@ MUTATOR_HOOKFUNCTION(ctf, DropSpecialItems) 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 diff --git a/qcsrc/common/gamemodes/gamemode/domination/_mod.inc b/qcsrc/common/gamemodes/gamemode/domination/_mod.inc index ff9bc11f88..ccaa150df7 100644 --- a/qcsrc/common/gamemodes/gamemode/domination/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/domination/_mod.inc @@ -1,4 +1,7 @@ // generated file; do not modify +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/domination/_mod.qh b/qcsrc/common/gamemodes/gamemode/domination/_mod.qh index 0c5e841214..b48a0a9147 100644 --- a/qcsrc/common/gamemodes/gamemode/domination/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/domination/_mod.qh @@ -1,4 +1,7 @@ // generated file; do not modify +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc new file mode 100644 index 0000000000..418a843d9b --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qc @@ -0,0 +1,86 @@ +#include "cl_domination.qh" + +#include + +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= rows) + { + row = 0; + ++column; + } + } +} diff --git a/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh new file mode 100644 index 0000000000..11ab3daca7 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/domination/cl_domination.qh @@ -0,0 +1,3 @@ +#pragma once + +void HUD_Mod_Dom(vector myPos, vector mySize); diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc index c42c7443ba..2dfcf48112 100644 --- a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc +++ b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc @@ -361,7 +361,9 @@ MUTATOR_HOOKFUNCTION(ft, PlayerDies) 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 @@ -608,6 +610,12 @@ MUTATOR_HOOKFUNCTION(ft, FragCenterMessage) return true; } +MUTATOR_HOOKFUNCTION(ft, SV_ParseServerCommand) +{ + shuffleteams_on_reset_map = !(round_handler_IsActive() && !round_handler_IsRoundStarted()); + return false; +} + void freezetag_Initialize() { freezetag_teams = autocvar_g_freezetag_teams_override; diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh index d637ae46f6..df138a93d8 100644 --- a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh +++ b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qh @@ -1,6 +1,8 @@ #pragma once #include +#include + int autocvar_g_freezetag_point_limit; int autocvar_g_freezetag_point_leadlimit; bool autocvar_g_freezetag_team_spawns; diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/_mod.inc b/qcsrc/common/gamemodes/gamemode/keepaway/_mod.inc index 420f7af78a..2ce6f4493b 100644 --- a/qcsrc/common/gamemodes/gamemode/keepaway/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/keepaway/_mod.inc @@ -1,4 +1,7 @@ // generated file; do not modify +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/_mod.qh b/qcsrc/common/gamemodes/gamemode/keepaway/_mod.qh index 145ca49f0a..8536675f3f 100644 --- a/qcsrc/common/gamemodes/gamemode/keepaway/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/keepaway/_mod.qh @@ -1,4 +1,7 @@ // generated file; do not modify +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qc b/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qc new file mode 100644 index 0000000000..b2d0874285 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qc @@ -0,0 +1,48 @@ +#include "cl_keepaway.qh" + +#include + +// 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); +} diff --git a/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qh b/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qh new file mode 100644 index 0000000000..7bcc289cd9 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/keepaway/cl_keepaway.qh @@ -0,0 +1,3 @@ +#pragma once + +void HUD_Mod_Keepaway(vector pos, vector mySize); diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/_mod.inc b/qcsrc/common/gamemodes/gamemode/keyhunt/_mod.inc index 4f44840c41..14802494b9 100644 --- a/qcsrc/common/gamemodes/gamemode/keyhunt/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/keyhunt/_mod.inc @@ -1,4 +1,7 @@ // generated file; do not modify +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/_mod.qh b/qcsrc/common/gamemodes/gamemode/keyhunt/_mod.qh index e4143fc84c..defda74978 100644 --- a/qcsrc/common/gamemodes/gamemode/keyhunt/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/keyhunt/_mod.qh @@ -1,4 +1,7 @@ // generated file; do not modify +#ifdef CSQC + #include +#endif #ifdef SVQC #include #endif diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qc b/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qc new file mode 100644 index 0000000000..e95275eba9 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qc @@ -0,0 +1,131 @@ +#include "cl_keyhunt.qh" + +#include + +// 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); +} diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qh b/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qh new file mode 100644 index 0000000000..8d650f11d3 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/keyhunt/cl_keyhunt.qh @@ -0,0 +1,3 @@ +#pragma once + +void HUD_Mod_KH(vector pos, vector mySize); diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc b/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc index d33696ad37..21d9208bf9 100644 --- a/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc +++ b/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qc @@ -23,6 +23,7 @@ float autocvar_g_balance_keyhunt_throwvelocity; 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 @@ -61,8 +62,6 @@ int kh_Team_ByID(int t) return 0; } -//entity kh_worldkeylist; -.entity kh_worldkeynext; entity kh_controller; //bool kh_tracking_enabled; int kh_teams; @@ -1293,6 +1292,13 @@ MUTATOR_HOOKFUNCTION(kh, HavocBot_ChooseRole) 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); diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qh b/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qh index 345a3d166e..66321c3d9d 100644 --- a/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qh +++ b/qcsrc/common/gamemodes/gamemode/keyhunt/sv_keyhunt.qh @@ -21,6 +21,9 @@ REGISTER_MUTATOR(kh, false) 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 diff --git a/qcsrc/common/gamemodes/gamemode/nexball/_mod.inc b/qcsrc/common/gamemodes/gamemode/nexball/_mod.inc index 7872767563..b229dcdf50 100644 --- a/qcsrc/common/gamemodes/gamemode/nexball/_mod.inc +++ b/qcsrc/common/gamemodes/gamemode/nexball/_mod.inc @@ -1,5 +1,10 @@ // generated file; do not modify -#include +#ifdef CSQC + #include +#endif +#ifdef SVQC + #include +#endif #include #ifdef SVQC #include diff --git a/qcsrc/common/gamemodes/gamemode/nexball/_mod.qh b/qcsrc/common/gamemodes/gamemode/nexball/_mod.qh index a1cf544371..0a3d1e2383 100644 --- a/qcsrc/common/gamemodes/gamemode/nexball/_mod.qh +++ b/qcsrc/common/gamemodes/gamemode/nexball/_mod.qh @@ -1,5 +1,10 @@ // generated file; do not modify -#include +#ifdef CSQC + #include +#endif +#ifdef SVQC + #include +#endif #include #ifdef SVQC #include diff --git a/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qc b/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qc new file mode 100644 index 0000000000..5a6b42dc46 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qc @@ -0,0 +1,44 @@ +#include "cl_nexball.qh" + +#include + +// 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; +} diff --git a/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qh b/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qh new file mode 100644 index 0000000000..d0b3731bc5 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/nexball/cl_nexball.qh @@ -0,0 +1,3 @@ +#pragma once + +void HUD_Mod_NexBall(vector pos, vector mySize); diff --git a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc deleted file mode 100644 index c841079fb7..0000000000 --- a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc +++ /dev/null @@ -1,984 +0,0 @@ -#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, g_nexball) -{ - 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 diff --git a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qh b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qh deleted file mode 100644 index 53797d2bc6..0000000000 --- a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qh +++ /dev/null @@ -1,36 +0,0 @@ -#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 diff --git a/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qc b/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qc new file mode 100644 index 0000000000..38b7a7f530 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qc @@ -0,0 +1,969 @@ +#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; +} diff --git a/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qh b/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qh new file mode 100644 index 0000000000..d7cde3a734 --- /dev/null +++ b/qcsrc/common/gamemodes/gamemode/nexball/sv_nexball.qh @@ -0,0 +1,34 @@ +#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; diff --git a/qcsrc/common/gamemodes/gamemode/nexball/weapon.qh b/qcsrc/common/gamemodes/gamemode/nexball/weapon.qh index 7790663ace..1e3127eb5f 100644 --- a/qcsrc/common/gamemodes/gamemode/nexball/weapon.qh +++ b/qcsrc/common/gamemodes/gamemode/nexball/weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc b/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc index d4303efbd9..3128bae266 100644 --- a/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc +++ b/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc @@ -988,7 +988,7 @@ void ons_GeneratorThink(entity this) { 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)); diff --git a/qcsrc/common/mapobjects/misc/corner.qc b/qcsrc/common/mapobjects/misc/corner.qc index a0f67b759b..729f7e236e 100644 --- a/qcsrc/common/mapobjects/misc/corner.qc +++ b/qcsrc/common/mapobjects/misc/corner.qc @@ -10,12 +10,26 @@ bool corner_send(entity this, entity to, int sf) 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); @@ -54,12 +68,14 @@ NET_HANDLE(ENT_CLIENT_CORNER, bool isnew) 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(); diff --git a/qcsrc/common/mapobjects/misc/dynlight.qc b/qcsrc/common/mapobjects/misc/dynlight.qc index 7c70b8444e..6e9f02b874 100644 --- a/qcsrc/common/mapobjects/misc/dynlight.qc +++ b/qcsrc/common/mapobjects/misc/dynlight.qc @@ -46,7 +46,7 @@ void dynlight_think(entity this) 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); @@ -62,7 +62,7 @@ void dynlight_find_aiment(entity this) 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); @@ -74,7 +74,7 @@ void dynlight_find_path(entity this) 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); diff --git a/qcsrc/common/mapobjects/target/music.qc b/qcsrc/common/mapobjects/target/music.qc index 5a63872dbd..55ccf41fbf 100644 --- a/qcsrc/common/mapobjects/target/music.qc +++ b/qcsrc/common/mapobjects/target/music.qc @@ -272,7 +272,7 @@ void Net_TargetMusic() void Ent_TriggerMusic_Think(entity this) { - if(this.active == ACTIVE_NOT) + if(this.active == ACTIVE_NOT || intermission) { return; } diff --git a/qcsrc/common/mapobjects/trigger/counter.qc b/qcsrc/common/mapobjects/trigger/counter.qc index 9156439f99..db255ebb7a 100644 --- a/qcsrc/common/mapobjects/trigger/counter.qc +++ b/qcsrc/common/mapobjects/trigger/counter.qc @@ -5,7 +5,7 @@ void counter_reset(entity this); 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; diff --git a/qcsrc/common/mapobjects/trigger/heal.qc b/qcsrc/common/mapobjects/trigger/heal.qc index 94abd4041d..b110d9913f 100644 --- a/qcsrc/common/mapobjects/trigger/heal.qc +++ b/qcsrc/common/mapobjects/trigger/heal.qc @@ -18,7 +18,7 @@ void trigger_heal_touch(entity this, entity toucher) 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); @@ -36,8 +36,8 @@ void trigger_heal_init(entity this) 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 == "") diff --git a/qcsrc/common/mapobjects/trigger/magicear.qc b/qcsrc/common/mapobjects/trigger/magicear.qc index 16118cb9d6..7321fe23f9 100644 --- a/qcsrc/common/mapobjects/trigger/magicear.qc +++ b/qcsrc/common/mapobjects/trigger/magicear.qc @@ -1,7 +1,7 @@ #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 +bool magicear_matched; string trigger_magicear_processmessage(entity ear, entity source, float teamsay, entity privatesay, string msgin) { float domatch, dotrigger, matchstart, l; diff --git a/qcsrc/common/mapobjects/trigger/swamp.qc b/qcsrc/common/mapobjects/trigger/swamp.qc index 0717f4bead..f7d9df2900 100644 --- a/qcsrc/common/mapobjects/trigger/swamp.qc +++ b/qcsrc/common/mapobjects/trigger/swamp.qc @@ -10,23 +10,12 @@ /* * 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 @@ -46,7 +35,11 @@ void swampslug_think(entity this) //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; @@ -72,11 +65,12 @@ void swamp_touch(entity this, entity toucher) 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; @@ -84,11 +78,11 @@ void swamp_touch(entity this, entity toucher) 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; @@ -116,8 +110,8 @@ void swamp_link(entity this) } /*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) { diff --git a/qcsrc/common/mapobjects/trigger/swamp.qh b/qcsrc/common/mapobjects/trigger/swamp.qh index f4df98378d..bfe860ed03 100644 --- a/qcsrc/common/mapobjects/trigger/swamp.qh +++ b/qcsrc/common/mapobjects/trigger/swamp.qh @@ -2,7 +2,16 @@ .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); diff --git a/qcsrc/common/minigames/cl_minigames_hud.qc b/qcsrc/common/minigames/cl_minigames_hud.qc index 1608f471da..fd9e3941e1 100644 --- a/qcsrc/common/minigames/cl_minigames_hud.qc +++ b/qcsrc/common/minigames/cl_minigames_hud.qc @@ -219,7 +219,7 @@ bool HUD_MinigameMenu_Click_ExpandCollapse(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); } diff --git a/qcsrc/common/models/model.qh b/qcsrc/common/models/model.qh index 38aa4e33ad..c6a1c2199b 100644 --- a/qcsrc/common/models/model.qh +++ b/qcsrc/common/models/model.qh @@ -17,7 +17,7 @@ CLASS(Model, Object) 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); } diff --git a/qcsrc/common/monsters/monster/mage.qh b/qcsrc/common/monsters/monster/mage.qh index 18f8f5963f..23de31062c 100644 --- a/qcsrc/common/monsters/monster/mage.qh +++ b/qcsrc/common/monsters/monster/mage.qh @@ -23,7 +23,7 @@ REGISTER_MONSTER(MAGE, NEW(Mage)); #include 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")); diff --git a/qcsrc/common/monsters/monster/spider.qh b/qcsrc/common/monsters/monster/spider.qh index 908f0f9420..679b140494 100644 --- a/qcsrc/common/monsters/monster/spider.qh +++ b/qcsrc/common/monsters/monster/spider.qh @@ -22,7 +22,7 @@ REGISTER_MONSTER(SPIDER, NEW(Spider)); #include 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")); diff --git a/qcsrc/common/monsters/monster/wyvern.qh b/qcsrc/common/monsters/monster/wyvern.qh index 2c5df05646..e54c9a7973 100644 --- a/qcsrc/common/monsters/monster/wyvern.qh +++ b/qcsrc/common/monsters/monster/wyvern.qh @@ -22,7 +22,7 @@ REGISTER_MONSTER(WYVERN, NEW(Wyvern)); #include 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")); diff --git a/qcsrc/common/monsters/sv_monsters.qc b/qcsrc/common/monsters/sv_monsters.qc index 97a68b5f8f..c707f8c38e 100644 --- a/qcsrc/common/monsters/sv_monsters.qc +++ b/qcsrc/common/monsters/sv_monsters.qc @@ -1095,15 +1095,12 @@ void Monster_Move_2D(entity this, float mspeed, bool allow_jumpoff) 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) { diff --git a/qcsrc/common/monsters/sv_spawner.qc b/qcsrc/common/monsters/sv_spawner.qc index d3f4ee740a..13c98e93fa 100644 --- a/qcsrc/common/monsters/sv_spawner.qc +++ b/qcsrc/common/monsters/sv_spawner.qc @@ -16,6 +16,7 @@ void spawner_use(entity this, entity actor, entity trigger) 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); } diff --git a/qcsrc/common/mutators/base.qh b/qcsrc/common/mutators/base.qh index c1d658576e..cc4cc01295 100644 --- a/qcsrc/common/mutators/base.qh +++ b/qcsrc/common/mutators/base.qh @@ -171,7 +171,8 @@ void Mutator_Remove(Mutator mut); bool mutator_log = false; .bool m_added; -#define MUTATOR_IS_ENABLED(this) MUTATOR_##this.mutatorcheck() +#define _MUTATOR_IS_ENABLED(this) this.mutatorcheck() +#define MUTATOR_IS_ENABLED(this) _MUTATOR_IS_ENABLED(MUTATOR_##this) #ifdef GAMEQC /** server mutators activate corresponding client mutators for all clients */ @@ -276,7 +277,7 @@ STATIC_INIT(Mutators) { } STATIC_INIT_LATE(Mutators) { - FOREACH(Mutators, it.mutatorcheck(), Mutator_Add(it)); + FOREACH(Mutators, _MUTATOR_IS_ENABLED(it), Mutator_Add(it)); } #define MUTATOR_ONADD if (mode == MUTATOR_ADDING) diff --git a/qcsrc/common/mutators/mutator/buffs/buffs.qh b/qcsrc/common/mutators/mutator/buffs/buffs.qh index 7d4e583675..b381db4be1 100644 --- a/qcsrc/common/mutators/mutator/buffs/buffs.qh +++ b/qcsrc/common/mutators/mutator/buffs/buffs.qh @@ -3,6 +3,10 @@ #include #include +#ifdef GAMEQC +#include +#endif + #ifdef GAMEQC REGISTER_WAYPOINT(Buff, _("Buff"), "", '1 0.5 0', 1); REGISTER_RADARICON(Buff, 1); @@ -35,10 +39,10 @@ CLASS(Buff, Pickup) ENDCLASS(Buff) STATIC_INIT(REGISTER_BUFFS) { - FOREACH(Buffs, true, { - it.m_itemid = BIT(it.m_id - 1); \ - it.m_sprite = strzone(strcat("buff-", it.netname)); \ - }); + FOREACH(Buffs, true, { + it.m_itemid = BIT(it.m_id - 1); + it.m_sprite = strzone(strcat("buff-", it.netname)); + }); } #ifdef SVQC diff --git a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc index 58663be1ac..97df48106d 100644 --- a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc +++ b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc @@ -180,9 +180,11 @@ void buff_Touch(entity this, entity toucher) { 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); @@ -193,13 +195,17 @@ void buff_Touch(entity this, entity toucher) 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) @@ -339,6 +345,12 @@ bool buff_Customize(entity this, entity client) 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; } @@ -374,6 +386,7 @@ void buff_Init(entity this) 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; @@ -562,8 +575,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerSpawn) { 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; @@ -609,8 +621,10 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerDies) 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) { @@ -630,11 +644,12 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerUseKey, CBC_ORDER_FIRST) { 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; } @@ -846,7 +861,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink) 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 @@ -898,7 +913,8 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink) { 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) { diff --git a/qcsrc/common/mutators/mutator/nades/nades.qc b/qcsrc/common/mutators/mutator/nades/nades.qc index c6a853d0e1..8dc82dbcf9 100644 --- a/qcsrc/common/mutators/mutator/nades/nades.qc +++ b/qcsrc/common/mutators/mutator/nades/nades.qc @@ -1033,7 +1033,7 @@ void nades_GiveBonus(entity player, float score) 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; } diff --git a/qcsrc/common/mutators/mutator/overkill/okhmg.qh b/qcsrc/common/mutators/mutator/overkill/okhmg.qh index 68ddc9d923..77204ae1a3 100644 --- a/qcsrc/common/mutators/mutator/overkill/okhmg.qh +++ b/qcsrc/common/mutators/mutator/overkill/okhmg.qh @@ -6,7 +6,7 @@ CLASS(OverkillHeavyMachineGun, Weapon) /* 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"); @@ -35,6 +35,7 @@ CLASS(OverkillHeavyMachineGun, Weapon) 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) \ diff --git a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qh b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qh index 321d92e226..77082c9621 100644 --- a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qh +++ b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qh @@ -32,6 +32,7 @@ CLASS(OverkillMachineGun, Weapon) 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) \ diff --git a/qcsrc/common/mutators/mutator/overkill/oknex.qh b/qcsrc/common/mutators/mutator/overkill/oknex.qh index d03f40ff2e..1ffaf78b8c 100644 --- a/qcsrc/common/mutators/mutator/overkill/oknex.qh +++ b/qcsrc/common/mutators/mutator/overkill/oknex.qh @@ -59,6 +59,7 @@ CLASS(OverkillNex, Weapon) 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) \ diff --git a/qcsrc/common/mutators/mutator/overkill/okrpc.qh b/qcsrc/common/mutators/mutator/overkill/okrpc.qh index 7d95296f96..928bfc0b9a 100644 --- a/qcsrc/common/mutators/mutator/overkill/okrpc.qh +++ b/qcsrc/common/mutators/mutator/overkill/okrpc.qh @@ -6,7 +6,7 @@ CLASS(OverkillRocketPropelledChainsaw, Weapon) /* 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"); @@ -40,6 +40,7 @@ CLASS(OverkillRocketPropelledChainsaw, Weapon) 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) \ diff --git a/qcsrc/common/mutators/mutator/overkill/okshotgun.qh b/qcsrc/common/mutators/mutator/overkill/okshotgun.qh index a830e6ac46..2c75681d97 100644 --- a/qcsrc/common/mutators/mutator/overkill/okshotgun.qh +++ b/qcsrc/common/mutators/mutator/overkill/okshotgun.qh @@ -33,6 +33,7 @@ CLASS(OverkillShotgun, Weapon) 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) \ diff --git a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc index 4192185dce..a9e1c5f57d 100644 --- a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc +++ b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc @@ -485,7 +485,7 @@ void Draw_WaypointSprite(entity this) 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); diff --git a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh index e2190b66a2..f08e2eceee 100644 --- a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh +++ b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qh @@ -53,6 +53,7 @@ float autocvar_g_waypointsprite_timealphaexponent; 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; diff --git a/qcsrc/common/sounds/all.inc b/qcsrc/common/sounds/all.inc index 31b5ed4873..29f2946b05 100644 --- a/qcsrc/common/sounds/all.inc +++ b/qcsrc/common/sounds/all.inc @@ -198,6 +198,7 @@ SOUND(ONS_CONTROLPOINT_BUILT, "onslaught/controlpoint_built"); 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"); @@ -236,6 +237,7 @@ SOUND(VEH_SPIDERBOT_STRAFE, "vehicles/spiderbot_strafe"); 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"); diff --git a/qcsrc/common/sounds/sound.qh b/qcsrc/common/sounds/sound.qh index af85fa1a33..45cd41f15e 100644 --- a/qcsrc/common/sounds/sound.qh +++ b/qcsrc/common/sounds/sound.qh @@ -130,7 +130,7 @@ CLASS(Sound, Object) 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); } diff --git a/qcsrc/common/t_items.qc b/qcsrc/common/t_items.qc index 466b383112..4a3712a25b 100644 --- a/qcsrc/common/t_items.qc +++ b/qcsrc/common/t_items.qc @@ -927,6 +927,9 @@ void Item_Touch(entity this, entity toucher) 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); @@ -1314,7 +1317,11 @@ void _StartItem(entity this, entity def, float defaultrespawntime, float default || (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); } @@ -1503,9 +1510,11 @@ spawnfunc(target_items) 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; } }); @@ -1565,7 +1574,7 @@ spawnfunc(target_items) 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); @@ -1615,28 +1624,28 @@ float GiveWeapon(entity e, float wpn, float op, float val) 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); } @@ -1706,6 +1715,7 @@ float GiveItems(entity e, float beginarg, float endarg) 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); @@ -1759,7 +1769,7 @@ float GiveItems(entity e, float beginarg, float endarg) 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": @@ -1820,7 +1830,7 @@ float GiveItems(entity e, float beginarg, float endarg) 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; @@ -1858,7 +1868,7 @@ float GiveItems(entity e, float beginarg, float endarg) 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) @@ -1873,6 +1883,10 @@ float GiveItems(entity e, float beginarg, float endarg) 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) { diff --git a/qcsrc/common/turrets/checkpoint.qc b/qcsrc/common/turrets/checkpoint.qc index f5ba714779..25c61b4b67 100644 --- a/qcsrc/common/turrets/checkpoint.qc +++ b/qcsrc/common/turrets/checkpoint.qc @@ -2,43 +2,6 @@ #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. @@ -46,30 +9,25 @@ wait: Pause at this point # seconds. -----------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. diff --git a/qcsrc/common/turrets/cl_turrets.qc b/qcsrc/common/turrets/cl_turrets.qc index f9374497c8..df20e1ad2f 100644 --- a/qcsrc/common/turrets/cl_turrets.qc +++ b/qcsrc/common/turrets/cl_turrets.qc @@ -175,28 +175,37 @@ void turret_draw2d(entity this) 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) diff --git a/qcsrc/common/turrets/sv_turrets.qc b/qcsrc/common/turrets/sv_turrets.qc index 84aae19335..fff1b39915 100644 --- a/qcsrc/common/turrets/sv_turrets.qc +++ b/qcsrc/common/turrets/sv_turrets.qc @@ -788,7 +788,6 @@ float turret_validate_target(entity e_turret, entity e_target, float validate_fl 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) diff --git a/qcsrc/common/turrets/sv_turrets.qh b/qcsrc/common/turrets/sv_turrets.qh index 8273e54dd1..f7b14b0a65 100644 --- a/qcsrc/common/turrets/sv_turrets.qh +++ b/qcsrc/common/turrets/sv_turrets.qh @@ -102,5 +102,4 @@ float turret_count; 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 diff --git a/qcsrc/common/turrets/turret/ewheel_weapon.qh b/qcsrc/common/turrets/turret/ewheel_weapon.qh index cbf7cb30fc..dfce8d3a0b 100644 --- a/qcsrc/common/turrets/turret/ewheel_weapon.qh +++ b/qcsrc/common/turrets/turret/ewheel_weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/turrets/turret/flac_weapon.qh b/qcsrc/common/turrets/turret/flac_weapon.qh index 13965bf513..d27061473a 100644 --- a/qcsrc/common/turrets/turret/flac_weapon.qh +++ b/qcsrc/common/turrets/turret/flac_weapon.qh @@ -1,9 +1,7 @@ #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")); diff --git a/qcsrc/common/turrets/turret/hellion_weapon.qh b/qcsrc/common/turrets/turret/hellion_weapon.qh index 69c67b800b..61896cc3d4 100644 --- a/qcsrc/common/turrets/turret/hellion_weapon.qh +++ b/qcsrc/common/turrets/turret/hellion_weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/turrets/turret/hk_weapon.qh b/qcsrc/common/turrets/turret/hk_weapon.qh index 7d44cfff91..f8acc5d3cf 100644 --- a/qcsrc/common/turrets/turret/hk_weapon.qh +++ b/qcsrc/common/turrets/turret/hk_weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/turrets/turret/machinegun_weapon.qh b/qcsrc/common/turrets/turret/machinegun_weapon.qh index ab8169e6cb..517eef83ab 100644 --- a/qcsrc/common/turrets/turret/machinegun_weapon.qh +++ b/qcsrc/common/turrets/turret/machinegun_weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/turrets/turret/mlrs_weapon.qh b/qcsrc/common/turrets/turret/mlrs_weapon.qh index ccb74771a6..5eb3755a6e 100644 --- a/qcsrc/common/turrets/turret/mlrs_weapon.qh +++ b/qcsrc/common/turrets/turret/mlrs_weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/turrets/turret/phaser_weapon.qh b/qcsrc/common/turrets/turret/phaser_weapon.qh index ea45977d52..7b9dc457fe 100644 --- a/qcsrc/common/turrets/turret/phaser_weapon.qh +++ b/qcsrc/common/turrets/turret/phaser_weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/turrets/turret/plasma_dual.qh b/qcsrc/common/turrets/turret/plasma_dual.qh index c0f63c1039..299475cd08 100644 --- a/qcsrc/common/turrets/turret/plasma_dual.qh +++ b/qcsrc/common/turrets/turret/plasma_dual.qh @@ -3,7 +3,7 @@ #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) diff --git a/qcsrc/common/turrets/turret/plasma_weapon.qh b/qcsrc/common/turrets/turret/plasma_weapon.qh index 3c11fdc003..5ad91c363d 100644 --- a/qcsrc/common/turrets/turret/plasma_weapon.qh +++ b/qcsrc/common/turrets/turret/plasma_weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/turrets/turret/tesla_weapon.qh b/qcsrc/common/turrets/turret/tesla_weapon.qh index a739852660..071f1d1409 100644 --- a/qcsrc/common/turrets/turret/tesla_weapon.qh +++ b/qcsrc/common/turrets/turret/tesla_weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/turrets/turret/walker_weapon.qh b/qcsrc/common/turrets/turret/walker_weapon.qh index 7c4fc0bed0..9f23ffb65a 100644 --- a/qcsrc/common/turrets/turret/walker_weapon.qh +++ b/qcsrc/common/turrets/turret/walker_weapon.qh @@ -1,7 +1,7 @@ #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")); diff --git a/qcsrc/common/util.qc b/qcsrc/common/util.qc index 0366f46048..7713679f3c 100644 --- a/qcsrc/common/util.qc +++ b/qcsrc/common/util.qc @@ -522,7 +522,7 @@ string fixPriorityList(string order, float from, float to, float subtract, float 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) diff --git a/qcsrc/common/vehicles/vehicle/racer_weapon.qh b/qcsrc/common/vehicles/vehicle/racer_weapon.qh index 7e4505ca3e..ede81f6c56 100644 --- a/qcsrc/common/vehicles/vehicle/racer_weapon.qh +++ b/qcsrc/common/vehicles/vehicle/racer_weapon.qh @@ -3,7 +3,7 @@ #include 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")); diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qh b/qcsrc/common/vehicles/vehicle/raptor_weapons.qh index c7ffff7970..37b87bbada 100644 --- a/qcsrc/common/vehicles/vehicle/raptor_weapons.qh +++ b/qcsrc/common/vehicles/vehicle/raptor_weapons.qh @@ -3,7 +3,7 @@ #include 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")); @@ -11,7 +11,7 @@ ENDCLASS(RaptorCannon) 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")); @@ -19,7 +19,7 @@ ENDCLASS(RaptorBomb) 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")); diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh index a65a788ecf..43398e6a5d 100644 --- a/qcsrc/common/weapons/all.qh +++ b/qcsrc/common/weapons/all.qh @@ -319,7 +319,7 @@ STATIC_INIT(register_weapons_done) 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) diff --git a/qcsrc/common/weapons/config.qc b/qcsrc/common/weapons/config.qc index f1cc349ca5..ab0fa0c17f 100644 --- a/qcsrc/common/weapons/config.qc +++ b/qcsrc/common/weapons/config.qc @@ -34,7 +34,7 @@ void Dump_Weapon_Settings() 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; diff --git a/qcsrc/common/weapons/weapon.qh b/qcsrc/common/weapons/weapon.qh index 8c025cb19f..3dd2a8048a 100644 --- a/qcsrc/common/weapons/weapon.qh +++ b/qcsrc/common/weapons/weapon.qh @@ -199,6 +199,7 @@ const int WEP_FLAG_NODUAL = BIT(12); // weapon doesn't work well with d 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; diff --git a/qcsrc/common/weapons/weapon/blaster.qc b/qcsrc/common/weapons/weapon/blaster.qc index e3d713d470..310ea19a1b 100644 --- a/qcsrc/common/weapons/weapon/blaster.qc +++ b/qcsrc/common/weapons/weapon/blaster.qc @@ -8,15 +8,19 @@ void W_Blaster_Touch(entity this, entity toucher) 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 @@ -42,6 +46,7 @@ void W_Blaster_Attack( float atk_edgedamage, float atk_radius, float atk_force, + float atk_force_zscale, float atk_speed, float atk_spread, float atk_delay, @@ -62,6 +67,7 @@ void W_Blaster_Attack( 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); @@ -129,6 +135,7 @@ METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponenti 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), @@ -161,6 +168,7 @@ METHOD(Blaster, wr_think, void(Blaster thiswep, entity actor, .entity weaponenti 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), diff --git a/qcsrc/common/weapons/weapon/blaster.qh b/qcsrc/common/weapons/weapon/blaster.qh index 6297bdf37b..87824310c9 100644 --- a/qcsrc/common/weapons/weapon/blaster.qh +++ b/qcsrc/common/weapons/weapon/blaster.qh @@ -58,6 +58,7 @@ STATIC_INIT(OFFHAND_BLASTER) { OFFHAND_BLASTER = NEW(OffhandBlaster); } .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. @@ -72,6 +73,7 @@ STATIC_INIT(OFFHAND_BLASTER) { OFFHAND_BLASTER = NEW(OffhandBlaster); } 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), \ diff --git a/qcsrc/common/weapons/weapon/machinegun.qc b/qcsrc/common/weapons/weapon/machinegun.qc index 6679f2135f..2d88a9deb2 100644 --- a/qcsrc/common/weapons/weapon/machinegun.qc +++ b/qcsrc/common/weapons/weapon/machinegun.qc @@ -164,7 +164,7 @@ void W_MachineGun_Attack_Burst(Weapon thiswep, entity actor, .entity weaponentit 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); diff --git a/qcsrc/common/weapons/weapon/machinegun.qh b/qcsrc/common/weapons/weapon/machinegun.qh index a53d17a8d9..19bba63a2b 100644 --- a/qcsrc/common/weapons/weapon/machinegun.qh +++ b/qcsrc/common/weapons/weapon/machinegun.qh @@ -24,7 +24,7 @@ CLASS(MachineGun, Weapon) 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) \ diff --git a/qcsrc/common/weapons/weapon/shockwave.qh b/qcsrc/common/weapons/weapon/shockwave.qh index f42eea7d49..8b1cd48efd 100644 --- a/qcsrc/common/weapons/weapon/shockwave.qh +++ b/qcsrc/common/weapons/weapon/shockwave.qh @@ -4,7 +4,7 @@ CLASS(Shockwave, Weapon) /* 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"); diff --git a/qcsrc/common/weapons/weapon/tuba.qh b/qcsrc/common/weapons/weapon/tuba.qh index f0cb6d2493..335326514d 100644 --- a/qcsrc/common/weapons/weapon/tuba.qh +++ b/qcsrc/common/weapons/weapon/tuba.qh @@ -51,3 +51,7 @@ classfield(Tuba) .float tuba_volume; 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 diff --git a/qcsrc/common/weapons/weapon/vaporizer.qh b/qcsrc/common/weapons/weapon/vaporizer.qh index 207ae8e630..f87a800a92 100644 --- a/qcsrc/common/weapons/weapon/vaporizer.qh +++ b/qcsrc/common/weapons/weapon/vaporizer.qh @@ -31,6 +31,7 @@ CLASS(Vaporizer, Weapon) 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) \ diff --git a/qcsrc/lib/counting.qh b/qcsrc/lib/counting.qh index b38ba9d05a..c084b5efe3 100644 --- a/qcsrc/lib/counting.qh +++ b/qcsrc/lib/counting.qh @@ -61,6 +61,7 @@ _("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) { @@ -68,23 +69,20 @@ 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 diff --git a/qcsrc/lib/spawnfunc.qh b/qcsrc/lib/spawnfunc.qh index e2a25cbc76..244665cc5f 100644 --- a/qcsrc/lib/spawnfunc.qh +++ b/qcsrc/lib/spawnfunc.qh @@ -146,12 +146,14 @@ noref bool require_spawnfunc_prefix; 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) \ diff --git a/qcsrc/lib/warpzone/common.qc b/qcsrc/lib/warpzone/common.qc index 25206fca86..3bff39be1f 100644 --- a/qcsrc/lib/warpzone/common.qc +++ b/qcsrc/lib/warpzone/common.qc @@ -792,7 +792,7 @@ bool WarpZoneLib_ExactTrigger_Touch(entity this, entity toucher) 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; diff --git a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc index 8b6dd4b731..33fe3575a8 100644 --- a/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc +++ b/qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc @@ -251,7 +251,7 @@ void XonoticMutatorsDialog_fill(entity me) 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) { diff --git a/qcsrc/menu/xonotic/keybinder.qc b/qcsrc/menu/xonotic/keybinder.qc index 7f6424bfce..6e59b8b1fe 100644 --- a/qcsrc/menu/xonotic/keybinder.qc +++ b/qcsrc/menu/xonotic/keybinder.qc @@ -68,9 +68,9 @@ void KeyBinds_Read() 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) diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index fd5009edca..4b71e28e8b 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -180,6 +180,7 @@ float autocvar_g_items_maxdist; 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; @@ -253,7 +254,6 @@ int autocvar_leadlimit_and_fraglimit; int autocvar_leadlimit_override; int autocvar_minplayers; int autocvar_minplayers_per_team; -int autocvar_name_maxlength; string autocvar_nextmap; string autocvar_quit_and_redirect; float autocvar_quit_and_redirect_timer; @@ -316,6 +316,7 @@ float autocvar_sv_mapchange_delay; float autocvar_sv_maxairspeed; float autocvar_sv_maxspeed; string autocvar_sv_motd; +int autocvar_sv_name_maxlength = 64; bool autocvar_sv_precacheplayermodels; bool autocvar_sv_q3acompat_machineshotgunswap; bool autocvar_sv_servermodelsonly; diff --git a/qcsrc/server/bot/api.qh b/qcsrc/server/bot/api.qh index 3f434dbecc..35b52e3d91 100644 --- a/qcsrc/server/bot/api.qh +++ b/qcsrc/server/bot/api.qh @@ -15,9 +15,6 @@ const int WAYPOINTFLAG_DEAD_END = BIT(16); // Useless WP detection temporary fl const int WAYPOINTFLAG_LADDER = BIT(15); const int WAYPOINTFLAG_JUMP = BIT(14); -entity kh_worldkeylist; -.entity kh_worldkeynext; - float bot_custom_weapon; float bot_weapons_close[Weapons_MAX]; float bot_weapons_far[Weapons_MAX]; diff --git a/qcsrc/server/bot/default/havocbot/havocbot.qc b/qcsrc/server/bot/default/havocbot/havocbot.qc index 57b4c310e3..2b2dfbf3cf 100644 --- a/qcsrc/server/bot/default/havocbot/havocbot.qc +++ b/qcsrc/server/bot/default/havocbot/havocbot.qc @@ -1,5 +1,7 @@ #include "havocbot.qh" +#include "roles.qh" + #include #include #include "../cvars.qh" @@ -24,8 +26,6 @@ #include -.float speed; - void havocbot_ai(entity this) { if(this.draggedby) @@ -193,82 +193,76 @@ void havocbot_ai(entity this) 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; @@ -276,10 +270,8 @@ void havocbot_bunnyhop(entity this, vector dir) 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; @@ -301,110 +293,80 @@ void havocbot_bunnyhop(entity this, vector dir) } 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.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)) + { + 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) - { - 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 diff --git a/qcsrc/server/bot/default/havocbot/havocbot.qh b/qcsrc/server/bot/default/havocbot/havocbot.qh index 2ec6316917..d1a36a1172 100644 --- a/qcsrc/server/bot/default/havocbot/havocbot.qh +++ b/qcsrc/server/bot/default/havocbot/havocbot.qh @@ -51,9 +51,6 @@ float havocbot_moveto_refresh_route(entity this); 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; diff --git a/qcsrc/server/bot/default/havocbot/roles.qc b/qcsrc/server/bot/default/havocbot/roles.qc index b72153c95c..84c597329e 100644 --- a/qcsrc/server/bot/default/havocbot/roles.qc +++ b/qcsrc/server/bot/default/havocbot/roles.qc @@ -11,14 +11,6 @@ #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 @@ -68,10 +60,10 @@ bool havocbot_goalrating_item_pickable_check_players(entity this, vector org, en 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)), { @@ -80,13 +72,13 @@ bool havocbot_goalrating_item_pickable_check_players(entity this, vector org, en 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; } } @@ -94,25 +86,23 @@ bool havocbot_goalrating_item_pickable_check_players(entity this, vector org, en { // 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, @@ -144,7 +134,7 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float 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; @@ -175,25 +165,23 @@ void havocbot_goalrating_items(entity this, float ratingscale, vector org, float 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)) @@ -208,7 +196,7 @@ void havocbot_goalrating_enemyplayers(entity this, float ratingscale, vector org 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) { diff --git a/qcsrc/server/bot/default/havocbot/roles.qh b/qcsrc/server/bot/default/havocbot/roles.qh index 6f70f09bee..23a23759a9 100644 --- a/qcsrc/server/bot/default/havocbot/roles.qh +++ b/qcsrc/server/bot/default/havocbot/roles.qh @@ -1 +1,10 @@ #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; diff --git a/qcsrc/server/bot/default/waypoints.qc b/qcsrc/server/bot/default/waypoints.qc index d69a89400f..6bc9077014 100644 --- a/qcsrc/server/bot/default/waypoints.qc +++ b/qcsrc/server/bot/default/waypoints.qc @@ -1303,6 +1303,7 @@ float waypoint_loadall() 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 @@ -1317,16 +1318,18 @@ float waypoint_loadall() 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"))); } diff --git a/qcsrc/server/cheats.qc b/qcsrc/server/cheats.qc index c2dbb74113..1acab9c005 100644 --- a/qcsrc/server/cheats.qc +++ b/qcsrc/server/cheats.qc @@ -161,6 +161,8 @@ float CheatImpulse(entity this, int imp) 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; @@ -220,6 +222,8 @@ float CheatImpulse(entity this, int imp) 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; diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 639717a901..3a99e31ded 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -40,6 +40,7 @@ #include "../common/mapobjects/teleporters.qh" #include "../common/mapobjects/target/spawnpoint.qh" #include +#include #include "../common/vehicles/all.qh" @@ -604,7 +605,7 @@ void PutPlayerInServer(entity this) 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; @@ -640,6 +641,10 @@ void PutPlayerInServer(entity this) 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; @@ -678,6 +683,9 @@ void PutPlayerInServer(entity this) 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; @@ -1034,7 +1042,6 @@ string getwelcomemessage(entity this) string versionmessage = GetClientVersionMessage(this); string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n"); - s = strcat(s, "^8\nCurrent map: ^2", GetMapname(), "^8\n"); if(modifications != "") s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n"); @@ -2045,12 +2052,21 @@ void PrintWelcomeMessage(entity this) { if(PHYS_INPUT_BUTTON_INFO(this)) // BUTTON_INFO hides initial MOTD CS(this).motd_actived_time = -2; // wait until BUTTON_INFO gets released - else if(CS(this).motd_actived_time == -2 || IS_PLAYER(this) || IS_SPEC(this)) + else if (CS(this).motd_actived_time == -2) { // instantly hide MOTD CS(this).motd_actived_time = 0; Kill_Notification(NOTIF_ONE_ONLY, this, MSG_CENTER, CPID_MOTD); } + else if (IS_PLAYER(this) || IS_SPEC(this)) + { + // FIXME occasionally for some reason MOTD never goes away + // delay MOTD removal a little bit in the hope it fixes this bug + if (CS(this).motd_actived_time == -1) // MOTD marked to fade away as soon as client becomes player or spectator + CS(this).motd_actived_time = -(5 + floor(random() * 10)); // add small delay + else //if (CS(this).motd_actived_time < -2) + CS(this).motd_actived_time++; + } } } @@ -2393,11 +2409,11 @@ void PlayerPreThink (entity this) if (this.netname == "" || this.netname != CS(this).netname_previous) { bool assume_unchanged = (CS(this).netname_previous == ""); - if (autocvar_name_maxlength > 0 && strlennocol(this.netname) > autocvar_name_maxlength) + if (autocvar_sv_name_maxlength > 0 && strlennocol(this.netname) > autocvar_sv_name_maxlength) { - int new_length = textLengthUpToLength(this.netname, autocvar_name_maxlength, strlennocol); + int new_length = textLengthUpToLength(this.netname, autocvar_sv_name_maxlength, strlennocol); this.netname = strzone(strcat(substring(this.netname, 0, new_length), "^7")); - sprint(this, sprintf("Warning: your name is longer than %d characters, it has been truncated.\n", autocvar_name_maxlength)); + sprint(this, sprintf("Warning: your name is longer than %d characters, it has been truncated.\n", autocvar_sv_name_maxlength)); assume_unchanged = false; // stuffcmd(this, strcat("name ", this.netname, "\n")); // maybe? } diff --git a/qcsrc/server/command/sv_cmd.qc b/qcsrc/server/command/sv_cmd.qc index e8fc1b13f1..5ff2d3472a 100644 --- a/qcsrc/server/command/sv_cmd.qc +++ b/qcsrc/server/command/sv_cmd.qc @@ -1274,50 +1274,61 @@ void GameCommand_setbots(int request, int argc) } } +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; } diff --git a/qcsrc/server/command/sv_cmd.qh b/qcsrc/server/command/sv_cmd.qh index 00e216c921..bf0dafa9cf 100644 --- a/qcsrc/server/command/sv_cmd.qh +++ b/qcsrc/server/command/sv_cmd.qh @@ -4,6 +4,9 @@ // Declarations for server side game commands // ================================================= +bool shuffleteams_on_reset_map; +void shuffleteams(); + string GotoMap(string m); void race_deleteTime(string map, float pos); diff --git a/qcsrc/server/command/vote.qc b/qcsrc/server/command/vote.qc index 51cf55ce3a..d79c2418d7 100644 --- a/qcsrc/server/command/vote.qc +++ b/qcsrc/server/command/vote.qc @@ -345,6 +345,11 @@ void reset_map(bool dorespawn) 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, diff --git a/qcsrc/server/compat/quake3.qc b/qcsrc/server/compat/quake3.qc index 112a7f039d..8205b81284 100644 --- a/qcsrc/server/compat/quake3.qc +++ b/qcsrc/server/compat/quake3.qc @@ -7,6 +7,8 @@ #include #include #include +#include +#include #include //*********************** @@ -119,7 +121,16 @@ void target_init_use(entity this, entity actor, entity trigger) { 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)) @@ -169,6 +180,12 @@ void target_give_init(entity this) 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; diff --git a/qcsrc/server/constants.qh b/qcsrc/server/constants.qh index f98d586fb5..62a15f680c 100644 --- a/qcsrc/server/constants.qh +++ b/qcsrc/server/constants.qh @@ -10,9 +10,9 @@ const int FL_PICKUPITEMS = BIT(19); 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) diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index 28a61cf1cd..b52649a34e 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -298,11 +298,6 @@ string matchid; 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; diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index 0901ab4478..e14ecd6ce7 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -74,8 +74,6 @@ void GiveFrags(entity attacker, entity targ, float f, int deathtype, .entity wea UpdateFrags(attacker, f); } -.entity kh_next; - string AppendItemcodes(string s, entity player) { for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) @@ -91,12 +89,11 @@ string AppendItemcodes(string s, entity player) 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; } @@ -865,7 +862,7 @@ void Damage(entity targ, entity inflictor, entity attacker, float damage, int de } 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; @@ -952,8 +949,10 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in 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) { @@ -1056,7 +1055,8 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in 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) diff --git a/qcsrc/server/g_damage.qh b/qcsrc/server/g_damage.qh index efe6b2e1b3..a99846c734 100644 --- a/qcsrc/server/g_damage.qh +++ b/qcsrc/server/g_damage.qh @@ -91,7 +91,7 @@ void Unfreeze(entity targ, bool reset_health); 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); diff --git a/qcsrc/server/g_hook.qc b/qcsrc/server/g_hook.qc index 453cfc1e70..b2b91bc02b 100644 --- a/qcsrc/server/g_hook.qc +++ b/qcsrc/server/g_hook.qc @@ -21,8 +21,6 @@ #include "../lib/warpzone/common.qh" #include "../lib/warpzone/server.qh" -.int state; - /*============================================ Wazat's Xonotic Grappling Hook @@ -72,8 +70,6 @@ And you should be done! ============================================*/ -.float hook_length; - void RemoveGrapplingHooks(entity pl) { if(pl.move_movetype == MOVETYPE_FLY) diff --git a/qcsrc/server/g_hook.qh b/qcsrc/server/g_hook.qh index c0df31662a..1ed78e2745 100644 --- a/qcsrc/server/g_hook.qh +++ b/qcsrc/server/g_hook.qh @@ -8,12 +8,16 @@ void RemoveHook(entity this); // (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]; + diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 07027875ee..8680b83a58 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -860,8 +860,14 @@ spawnfunc(worldspawn) 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") { @@ -984,22 +990,27 @@ float Map_Count, Map_Current; 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; @@ -1202,18 +1213,25 @@ float MaplistMethod_Shuffle(float exponent) // more clever shuffling 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) @@ -1227,10 +1245,8 @@ void Maplist_Init() string GetNextMap() { - float nextMap; - Maplist_Init(); - nextMap = -1; + float nextMap = -1; if(nextMap == -1) if(autocvar_g_maplist_shuffle > 0) @@ -1325,9 +1341,7 @@ void GotoNextMap(float reinit) 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); diff --git a/qcsrc/server/impulse.qc b/qcsrc/server/impulse.qc index 2320eb830e..49685d49d7 100644 --- a/qcsrc/server/impulse.qc +++ b/qcsrc/server/impulse.qc @@ -507,7 +507,7 @@ IMPULSE(waypoint_here_here) 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"); diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index bc0b49ca02..522840e763 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -499,7 +499,7 @@ float want_weapon(entity weaponinfo, float allguns) // WEAPONTODO: what still ne 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); @@ -565,7 +565,7 @@ void readplayerstartcvars() 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); }); } @@ -583,7 +583,7 @@ void readplayerstartcvars() 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); }); } diff --git a/qcsrc/server/mutators/events.qh b/qcsrc/server/mutators/events.qh index f0237b27ee..cd09b1defd 100644 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@ -1222,3 +1222,11 @@ MUTATOR_HOOKABLE(Unfreeze, EV_Unfreeze); /**/ 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); diff --git a/qcsrc/server/spawnpoints.qc b/qcsrc/server/spawnpoints.qc index 9e2565144b..5aa81a2a73 100644 --- a/qcsrc/server/spawnpoints.qc +++ b/qcsrc/server/spawnpoints.qc @@ -7,6 +7,7 @@ #include "../common/constants.qh" #include #include "../common/teams.qh" +#include #include "../common/mapobjects/subs.qh" #include "../common/mapobjects/target/spawnpoint.qh" #include "../common/util.qh" @@ -263,7 +264,7 @@ vector Spawn_Score(entity this, entity spot, float mindist, float teamcheck) } } - 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'; diff --git a/qcsrc/server/steerlib.qc b/qcsrc/server/steerlib.qc index 92c918f00c..310835c5ce 100644 --- a/qcsrc/server/steerlib.qc +++ b/qcsrc/server/steerlib.qc @@ -17,7 +17,7 @@ /** 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) { @@ -29,7 +29,7 @@ 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); } @@ -39,21 +39,21 @@ vector steerlib_arrive(entity this, vector point, float 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; } /* @@ -89,27 +89,21 @@ vector steerlib_attract2(vector point, float maximal_distance,float min_influens /** 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) { @@ -123,22 +117,22 @@ vector steerlib_standoff(entity this, vector point,float 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); @@ -147,17 +141,15 @@ vector steerlib_wander(entity this, float range, float tresh, vector oldpoint) } /** - 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); } /** @@ -165,20 +157,19 @@ vector steerlib_dodge(entity this, vector point, vector dodge_dir, float min_dis 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; @@ -191,20 +182,19 @@ vector steerlib_flock(entity this, float _radius, float standoff,float separatio 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; @@ -218,25 +208,23 @@ vector steerlib_flock2d(entity this, float _radius, float standoff,float separat /** 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; } @@ -252,93 +240,80 @@ vector steerlib_swarm(entity this, float _radius, float standoff,float separatio 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) @@ -347,11 +322,11 @@ float beamsweep(entity this, vector from, vector dir,float length, float step,fl 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; @@ -374,31 +349,27 @@ float beamsweep(entity this, vector from, vector dir,float length, float step,fl 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); @@ -435,5 +406,4 @@ vector steerlib_beamsteer(entity this, vector dir, float length, float step, flo vl = vl * bm_left; return normalize(vr + vl); - } diff --git a/qcsrc/server/sv_main.qc b/qcsrc/server/sv_main.qc index 9be3c18f60..6b5b19d79e 100644 --- a/qcsrc/server/sv_main.qc +++ b/qcsrc/server/sv_main.qc @@ -28,44 +28,43 @@ #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'); } } } @@ -96,35 +95,36 @@ void CreatureFrame_Liquids(entity this) 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() diff --git a/qcsrc/server/sv_main.qh b/qcsrc/server/sv_main.qh index 93480cf282..46284fde2e 100644 --- a/qcsrc/server/sv_main.qh +++ b/qcsrc/server/sv_main.qh @@ -2,6 +2,11 @@ bool expr_evaluate(string s); +#ifdef PROFILING +float client_cefc_accumulator; +float client_cefc_accumulatortime; +#endif + /* ================== main diff --git a/qcsrc/server/weapons/tracing.qc b/qcsrc/server/weapons/tracing.qc index 4f50165080..ef7f1a832b 100644 --- a/qcsrc/server/weapons/tracing.qc +++ b/qcsrc/server/weapons/tracing.qc @@ -213,10 +213,7 @@ void W_SetupProjVelocity_Explicit(entity proj, vector dir, vector upDir, float p 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 @@ -273,42 +270,31 @@ void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector 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); @@ -317,11 +303,7 @@ void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector // 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; diff --git a/ruleset-XDF.cfg b/ruleset-XDF.cfg index 20740d9a86..16cdd100a8 100644 --- a/ruleset-XDF.cfg +++ b/ruleset-XDF.cfg @@ -21,6 +21,7 @@ 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 +set g_buffs_randomize 0 // game mode settings set g_cts_finish_kill_delay 2 diff --git a/textures/erebusfullbright.tga b/textures/erebusfullbright.tga index 5a470f6d64..2ef83416e3 100644 Binary files a/textures/erebusfullbright.tga and b/textures/erebusfullbright.tga differ diff --git a/textures/erebusfullbright_gloss.tga b/textures/erebusfullbright_gloss.tga index 992af7530e..d2f981933f 100644 Binary files a/textures/erebusfullbright_gloss.tga and b/textures/erebusfullbright_gloss.tga differ diff --git a/textures/erebusfullbright_reflect.tga b/textures/erebusfullbright_reflect.tga index e825195ef5..1c26b072cf 100644 Binary files a/textures/erebusfullbright_reflect.tga and b/textures/erebusfullbright_reflect.tga differ diff --git a/textures/erebusfullbright_shirt.tga b/textures/erebusfullbright_shirt.tga index 364bae2d9a..9aee3c18ac 100644 Binary files a/textures/erebusfullbright_shirt.tga and b/textures/erebusfullbright_shirt.tga differ diff --git a/textures/nyxfullbright.tga b/textures/nyxfullbright.tga index 8169f3779f..1eba0fefc7 100644 Binary files a/textures/nyxfullbright.tga and b/textures/nyxfullbright.tga differ diff --git a/textures/nyxfullbright_gloss.tga b/textures/nyxfullbright_gloss.tga index 6b53f91cfe..f3f636dde2 100644 Binary files a/textures/nyxfullbright_gloss.tga and b/textures/nyxfullbright_gloss.tga differ diff --git a/textures/nyxfullbright_glow.tga b/textures/nyxfullbright_glow.tga index a91959d366..ec01e22847 100644 Binary files a/textures/nyxfullbright_glow.tga and b/textures/nyxfullbright_glow.tga differ diff --git a/textures/nyxfullbright_reflect.tga b/textures/nyxfullbright_reflect.tga index e825195ef5..0052c20d69 100644 Binary files a/textures/nyxfullbright_reflect.tga and b/textures/nyxfullbright_reflect.tga differ diff --git a/textures/nyxfullbright_shirt.tga b/textures/nyxfullbright_shirt.tga index 364bae2d9a..9aee3c18ac 100644 Binary files a/textures/nyxfullbright_shirt.tga and b/textures/nyxfullbright_shirt.tga differ diff --git a/xonotic-client.cfg b/xonotic-client.cfg index 61651320af..c9a49f924a 100644 --- a/xonotic-client.cfg +++ b/xonotic-client.cfg @@ -396,6 +396,7 @@ set g_waypointsprite_timealphaexponent 1 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 diff --git a/xonotic-common.cfg b/xonotic-common.cfg index 3a01784c7c..f44d9c96f9 100644 --- a/xonotic-common.cfg +++ b/xonotic-common.cfg @@ -1,3 +1,10 @@ +// most common prefixes (currently not used consistently - especially g_ and sv_): +// cl_ client +// g_ gameplay +// r_ renderer +// sv_ server administration, should not affect gameplay +// _ temporary, private or internal cvar - should not be changed manually, sometimes used in scripts + // Xonotic version (formatted for machines) // used to determine if a client version is compatible // this doesn't have to be bumped with every release diff --git a/xonotic-server.cfg b/xonotic-server.cfg index dadc207b57..d261e262ea 100644 --- a/xonotic-server.cfg +++ b/xonotic-server.cfg @@ -2,7 +2,7 @@ // note that it doesn't reset all server cvars, // some are shared with the client and so are left in xonotic-common.cfg -set name_maxlength 64 "max player name length (not counting color codes) allowed by the server" +set sv_name_maxlength 64 "max player name length (not counting color codes) allowed by the server" // taunts and voices set sv_taunt 1 "allow taunts on the server" @@ -222,6 +222,7 @@ set g_grab_range 200 "distance at which dragable objects can be grabbed" 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"