Merge branch 'master' into Mario/rain_fix
authorMario <mario.mario@y7mail.com>
Sat, 18 Jan 2020 22:36:44 +0000 (08:36 +1000)
committerMario <mario.mario@y7mail.com>
Sat, 18 Jan 2020 22:36:44 +0000 (08:36 +1000)
171 files changed:
.gitlab-ci.yml
.tx/merge-base
_hud_common.cfg
_hud_descriptions.cfg
bal-wep-mario.cfg
bal-wep-nexuiz25.cfg
bal-wep-samual.cfg
bal-wep-testing.cfg
bal-wep-xdf.cfg
bal-wep-xonotic.cfg
balance-mario.cfg
balance-nexuiz25.cfg
balance-overkill.cfg
balance-samual.cfg
balance-testing.cfg
balance-testingxpm.cfg
balance-xdf.cfg
balance-xonotic.cfg
balance-xpm.cfg
common.el.po
common.ru.po
crosshairs.cfg
effects-high.cfg
effects-low.cfg
effects-med.cfg
effects-normal.cfg
effects-omg.cfg
gamemodes-server.cfg
hud_luma.cfg
hud_luminos.cfg
hud_luminos_minimal.cfg
hud_luminos_minimal_xhair.cfg
hud_luminos_old.cfg
hud_nexuiz.cfg
mutators.cfg
qcsrc/Makefile
qcsrc/client/autocvars.qh
qcsrc/client/defs.qh
qcsrc/client/hud/hud.qc
qcsrc/client/hud/panel/quickmenu.qc
qcsrc/client/hud/panel/scoreboard.qc
qcsrc/client/hud/panel/weapons.qc
qcsrc/client/main.qc
qcsrc/client/miscfunctions.qc
qcsrc/client/teamradar.qc
qcsrc/client/view.qc
qcsrc/client/view.qh
qcsrc/common/campaign_common.qh
qcsrc/common/campaign_file.qc
qcsrc/common/command/generic.qc
qcsrc/common/command/reg.qh
qcsrc/common/command/rpn.qc
qcsrc/common/debug.qh
qcsrc/common/effects/effectinfo.qc
qcsrc/common/effects/qc/casings.qc
qcsrc/common/effects/qc/globalsound.qc
qcsrc/common/effects/qc/globalsound.qh
qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc
qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc
qcsrc/common/gamemodes/gamemode/keepaway/sv_keepaway.qc
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qh
qcsrc/common/items/all.qh
qcsrc/common/items/inventory.qh
qcsrc/common/mapinfo.qc
qcsrc/common/mapobjects/func/breakable.qc
qcsrc/common/mapobjects/func/button.qc
qcsrc/common/mapobjects/func/rainsnow.qc
qcsrc/common/mapobjects/models.qc
qcsrc/common/mapobjects/subs.qc
qcsrc/common/mapobjects/subs.qh
qcsrc/common/mapobjects/trigger/hurt.qc
qcsrc/common/mapobjects/trigger/jumppads.qc
qcsrc/common/mapobjects/trigger/multi.qc
qcsrc/common/mapobjects/triggers.qc
qcsrc/common/mapobjects/triggers.qh
qcsrc/common/monsters/monster/spider.qc
qcsrc/common/monsters/monster/wyvern.qc
qcsrc/common/mutators/events.qh
qcsrc/common/mutators/mutator/bloodloss/_mod.inc
qcsrc/common/mutators/mutator/bloodloss/_mod.qh
qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc [new file with mode: 0644]
qcsrc/common/mutators/mutator/bloodloss/bloodloss.qh [new file with mode: 0644]
qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qc [deleted file]
qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qh [deleted file]
qcsrc/common/mutators/mutator/buffs/all.inc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/buffs/sv_buffs.qh
qcsrc/common/mutators/mutator/nades/nades.qc
qcsrc/common/mutators/mutator/overkill/okhmg.qc
qcsrc/common/mutators/mutator/overkill/okmachinegun.qc
qcsrc/common/mutators/mutator/overkill/oknex.qc
qcsrc/common/mutators/mutator/overkill/okrpc.qc
qcsrc/common/mutators/mutator/overkill/okshotgun.qc
qcsrc/common/mutators/mutator/walljump/walljump.qc
qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc
qcsrc/common/notifications/all.qh
qcsrc/common/physics/movetypes/movetypes.qc
qcsrc/common/physics/movetypes/movetypes.qh
qcsrc/common/physics/movetypes/toss.qc
qcsrc/common/physics/player.qc
qcsrc/common/playerstats.qc
qcsrc/common/playerstats.qh
qcsrc/common/stats.qh
qcsrc/common/turrets/all.qh
qcsrc/common/util.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc
qcsrc/common/vehicles/vehicle/racer.qc
qcsrc/common/vehicles/vehicle/racer_weapon.qc
qcsrc/common/vehicles/vehicle/raptor.qc
qcsrc/common/vehicles/vehicle/raptor_weapons.qc
qcsrc/common/vehicles/vehicle/raptor_weapons.qh
qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc
qcsrc/common/weapons/all.qc
qcsrc/common/weapons/all.qh
qcsrc/common/weapons/weapon.qh
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/electro.qc
qcsrc/common/weapons/weapon/electro.qh
qcsrc/common/weapons/weapon/porto.qc
qcsrc/common/weapons/weapon/shockwave.qc
qcsrc/ecs/systems/physics.qc
qcsrc/i18n-guide.txt
qcsrc/lib/csqcmodel/cl_player.qc
qcsrc/lib/draw.qh
qcsrc/lib/i18n.qh
qcsrc/lib/log.qh
qcsrc/lib/matrix/command.qc
qcsrc/lib/oo.qh
qcsrc/lib/replicate.qh
qcsrc/lib/static.qh
qcsrc/lib/stats.qh
qcsrc/lib/warpzone/server.qc
qcsrc/menu/menu.qc
qcsrc/menu/xonotic/campaign.qc
qcsrc/menu/xonotic/campaign.qh
qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc
qcsrc/menu/xonotic/dialog_quit.qc
qcsrc/menu/xonotic/dialog_settings_audio.qc
qcsrc/menu/xonotic/dialog_settings_effects.qc
qcsrc/menu/xonotic/dialog_settings_game_view.qc
qcsrc/menu/xonotic/dialog_settings_game_weapons.qc
qcsrc/menu/xonotic/dialog_settings_misc.qc
qcsrc/menu/xonotic/dialog_settings_video.qc
qcsrc/menu/xonotic/dialog_singleplayer.qc
qcsrc/menu/xonotic/slider_particles.qc
qcsrc/menu/xonotic/util.qc
qcsrc/server/autocvars.qh
qcsrc/server/bot/default/bot.qc
qcsrc/server/bot/default/waypoints.qc
qcsrc/server/campaign.qc
qcsrc/server/client.qc
qcsrc/server/command/cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/compat/quake3.qc
qcsrc/server/g_hook.qc
qcsrc/server/g_world.qc
qcsrc/server/miscfunctions.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/player.qc
qcsrc/server/portals.qc
qcsrc/server/sv_main.qc
qcsrc/server/weapons/weaponsystem.qc
qcsrc/server/weapons/weaponsystem.qh
ruleset-overkill.cfg
scripts/electro.shader
vehicles.cfg
xonotic-client.cfg
xonotic-common.cfg
xonotic-server.cfg

index 8724d06..3e56730 100644 (file)
@@ -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=892e447048e051e51f30cff2affc729a
+    - EXPECT=d5bda479d65190330f6ee23c6f9aa5e7
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index 249da91..7a7217d 100644 (file)
@@ -1 +1 @@
-Thu Dec 19 07:25:06 CET 2019
+Wed Jan 15 07:24:54 CET 2020
index c860be9..0479f38 100644 (file)
@@ -74,6 +74,7 @@ seta hud_panel_weapons_ammo_full_plasma 180 "show 100% of the status bar at this
 seta hud_panel_weapons_ammo_full_rockets 160 "show 100% of the status bar at this ammo count"
 seta hud_panel_weapons_ammo_full_fuel 100 "show 100% of the status bar at this ammo count"
 seta hud_panel_weapons_hide_ondeath 0 "hide this panel when dead"
+seta hud_panel_weapons_orderbyimpulse "1" "List weapons in their impulse order instead of priority"
 
 seta hud_panel_ammo_maxammo "40" "when you have this much ammo, the ammo status bar is full"
 seta hud_panel_ammo_hide_ondeath 0 "hide this panel when dead"
index 6e393e6..30e5a8b 100644 (file)
@@ -63,7 +63,6 @@ seta hud_panel_weapons_label_scale "" "scale of the weapon text label"
 seta hud_panel_weapons_accuracy "" "show accuracy color as the weapon icon background; colors can be configured with accuracy_color* cvars"
 seta hud_panel_weapons_ammo "" "show ammo as a status bar"
 seta hud_panel_weapons_onlyowned "" "show only owned weapons, set it to 2 to show only the held weapon"
-seta hud_panel_weapons_orderbyimpulse "" "List weapons in their impulse order instead of priority"
 seta hud_panel_weapons_noncurrent_alpha "" "alpha of noncurrent weapons"
 seta hud_panel_weapons_noncurrent_scale "" "scale of noncurrent weapons, relative to the current weapon"
 seta hud_panel_weapons_selection_radius "" "number of weapons that get partially highlighted on each side of the currently selected weapon"
index d3270ac..5cfa348 100644 (file)
@@ -191,9 +191,13 @@ set g_balance_electro_primary_damage 40
 set g_balance_electro_primary_edgedamage 20
 set g_balance_electro_primary_force 200
 set g_balance_electro_primary_lifetime 5
+set g_balance_electro_primary_midaircombo_enemy 1
 set g_balance_electro_primary_midaircombo_explode 1
 set g_balance_electro_primary_midaircombo_interval 0.1
+set g_balance_electro_primary_midaircombo_own 1
 set g_balance_electro_primary_midaircombo_radius 0
+set g_balance_electro_primary_midaircombo_speed 2000
+set g_balance_electro_primary_midaircombo_teammate 1
 set g_balance_electro_primary_radius 100
 set g_balance_electro_primary_refire 0.6
 set g_balance_electro_primary_speed 2500
index c9d87fd..f965981 100644 (file)
@@ -191,9 +191,13 @@ set g_balance_electro_primary_damage 65
 set g_balance_electro_primary_edgedamage 0
 set g_balance_electro_primary_force 200
 set g_balance_electro_primary_lifetime 30
+set g_balance_electro_primary_midaircombo_enemy 1
 set g_balance_electro_primary_midaircombo_explode 0
 set g_balance_electro_primary_midaircombo_interval 0
+set g_balance_electro_primary_midaircombo_own 1
 set g_balance_electro_primary_midaircombo_radius 0
+set g_balance_electro_primary_midaircombo_speed 2000
+set g_balance_electro_primary_midaircombo_teammate 1
 set g_balance_electro_primary_radius 150
 set g_balance_electro_primary_refire 0.6
 set g_balance_electro_primary_speed 2000
index e32b54f..6896f5f 100644 (file)
@@ -191,9 +191,13 @@ set g_balance_electro_primary_damage 40
 set g_balance_electro_primary_edgedamage 20
 set g_balance_electro_primary_force 200
 set g_balance_electro_primary_lifetime 5
+set g_balance_electro_primary_midaircombo_enemy 1
 set g_balance_electro_primary_midaircombo_explode 1
 set g_balance_electro_primary_midaircombo_interval 0.1
+set g_balance_electro_primary_midaircombo_own 1
 set g_balance_electro_primary_midaircombo_radius 100
+set g_balance_electro_primary_midaircombo_speed 2000
+set g_balance_electro_primary_midaircombo_teammate 1
 set g_balance_electro_primary_radius 100
 set g_balance_electro_primary_refire 0.6
 set g_balance_electro_primary_speed 2500
index ff90629..abee0b6 100644 (file)
@@ -191,9 +191,13 @@ set g_balance_electro_primary_damage 40
 set g_balance_electro_primary_edgedamage 20
 set g_balance_electro_primary_force 200
 set g_balance_electro_primary_lifetime 5
+set g_balance_electro_primary_midaircombo_enemy 1
 set g_balance_electro_primary_midaircombo_explode 1
 set g_balance_electro_primary_midaircombo_interval 0.1
+set g_balance_electro_primary_midaircombo_own 1
 set g_balance_electro_primary_midaircombo_radius 0
+set g_balance_electro_primary_midaircombo_speed 2000
+set g_balance_electro_primary_midaircombo_teammate 1
 set g_balance_electro_primary_radius 100
 set g_balance_electro_primary_refire 0.6
 set g_balance_electro_primary_speed 2500
@@ -289,7 +293,7 @@ set g_balance_crylink_weaponstartoverride -1
 set g_balance_crylink_weaponthrowable 1
 // }}}
 // {{{ #8: Vortex
-set g_balance_vortex_charge 0
+set g_balance_vortex_charge 1
 set g_balance_vortex_charge_always 0
 set g_balance_vortex_charge_animlimit 0.5
 set g_balance_vortex_charge_limit 1
@@ -305,7 +309,7 @@ set g_balance_vortex_charge_velocity_rate 0
 set g_balance_vortex_primary_ammo 6
 set g_balance_vortex_primary_animtime 0.4
 set g_balance_vortex_primary_armorpierce 0
-set g_balance_vortex_primary_damage 65
+set g_balance_vortex_primary_damage 80
 set g_balance_vortex_primary_damagefalloff_forcehalflife 0
 set g_balance_vortex_primary_damagefalloff_halflife 0
 set g_balance_vortex_primary_damagefalloff_maxdist 0
index 1fe4044..ec8029c 100644 (file)
@@ -191,9 +191,13 @@ set g_balance_electro_primary_damage 40
 set g_balance_electro_primary_edgedamage 20
 set g_balance_electro_primary_force 200
 set g_balance_electro_primary_lifetime 5
+set g_balance_electro_primary_midaircombo_enemy 1
 set g_balance_electro_primary_midaircombo_explode 1
 set g_balance_electro_primary_midaircombo_interval 0.1
+set g_balance_electro_primary_midaircombo_own 1
 set g_balance_electro_primary_midaircombo_radius 100
+set g_balance_electro_primary_midaircombo_speed 2000
+set g_balance_electro_primary_midaircombo_teammate 1
 set g_balance_electro_primary_radius 100
 set g_balance_electro_primary_refire 0.6
 set g_balance_electro_primary_speed 2500
index 52d63df..c38ea83 100644 (file)
@@ -191,9 +191,13 @@ set g_balance_electro_primary_damage 40
 set g_balance_electro_primary_edgedamage 20
 set g_balance_electro_primary_force 200
 set g_balance_electro_primary_lifetime 5
+set g_balance_electro_primary_midaircombo_enemy 1
 set g_balance_electro_primary_midaircombo_explode 1
 set g_balance_electro_primary_midaircombo_interval 0.1
+set g_balance_electro_primary_midaircombo_own 1
 set g_balance_electro_primary_midaircombo_radius 0
+set g_balance_electro_primary_midaircombo_speed 2000
+set g_balance_electro_primary_midaircombo_teammate 1
 set g_balance_electro_primary_radius 100
 set g_balance_electro_primary_refire 0.6
 set g_balance_electro_primary_speed 2500
@@ -243,7 +247,7 @@ set g_balance_crylink_primary_joinexplode_edgedamage 0
 set g_balance_crylink_primary_joinexplode_force 0
 set g_balance_crylink_primary_joinexplode_radius 0
 set g_balance_crylink_primary_joinspread 0.2
-set g_balance_crylink_primary_linkexplode 0
+set g_balance_crylink_primary_linkexplode 1
 set g_balance_crylink_primary_middle_fadetime 5
 set g_balance_crylink_primary_middle_lifetime 5
 set g_balance_crylink_primary_other_fadetime 5
index 1974ad6..de22d1f 100644 (file)
@@ -185,6 +185,7 @@ set g_balance_falldamage_deadminspeed 250
 set g_balance_falldamage_minspeed 900
 set g_balance_falldamage_factor 0.20
 set g_balance_falldamage_maxdamage 40
+set g_balance_falldamage_onlyvertical 0
 set g_balance_damagepush_speedfactor 2.5
 set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
 set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
index 73c63df..81c786e 100644 (file)
@@ -185,6 +185,7 @@ set g_balance_falldamage_deadminspeed 150
 set g_balance_falldamage_minspeed 1400
 set g_balance_falldamage_factor 0.15
 set g_balance_falldamage_maxdamage 25
+set g_balance_falldamage_onlyvertical 0
 set g_balance_damagepush_speedfactor 0
 set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
 set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
index 0e929ee..28f8f17 100644 (file)
@@ -185,6 +185,7 @@ set g_balance_falldamage_deadminspeed 250
 set g_balance_falldamage_minspeed 900
 set g_balance_falldamage_factor 0.20
 set g_balance_falldamage_maxdamage 40
+set g_balance_falldamage_onlyvertical 0
 set g_balance_damagepush_speedfactor 2.5
 set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
 set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
index 9bcb976..f98731e 100644 (file)
@@ -185,6 +185,7 @@ set g_balance_falldamage_deadminspeed 250
 set g_balance_falldamage_minspeed 900
 set g_balance_falldamage_factor 0.20
 set g_balance_falldamage_maxdamage 40
+set g_balance_falldamage_onlyvertical 0
 set g_balance_damagepush_speedfactor 2.5
 set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
 set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
index 96426aa..9602116 100644 (file)
@@ -185,6 +185,7 @@ set g_balance_falldamage_deadminspeed 250
 set g_balance_falldamage_minspeed 900
 set g_balance_falldamage_factor 0.20
 set g_balance_falldamage_maxdamage 40
+set g_balance_falldamage_onlyvertical 0
 set g_balance_damagepush_speedfactor 2.5
 set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
 set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
index 4fa3130..4ee3f36 100644 (file)
@@ -185,6 +185,7 @@ set g_balance_falldamage_deadminspeed 250
 set g_balance_falldamage_minspeed 900
 set g_balance_falldamage_factor 0.20
 set g_balance_falldamage_maxdamage 40
+set g_balance_falldamage_onlyvertical 0
 set g_balance_damagepush_speedfactor 2.5
 set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
 set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
index 6a1622c..e866bd1 100644 (file)
@@ -185,6 +185,7 @@ set g_balance_falldamage_deadminspeed 250
 set g_balance_falldamage_minspeed 900
 set g_balance_falldamage_factor 0.20
 set g_balance_falldamage_maxdamage 40
+set g_balance_falldamage_onlyvertical 0
 set g_balance_damagepush_speedfactor 2.5
 set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
 set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
index e198724..2666108 100644 (file)
@@ -185,6 +185,7 @@ set g_balance_falldamage_deadminspeed 250
 set g_balance_falldamage_minspeed 900
 set g_balance_falldamage_factor 0.20
 set g_balance_falldamage_maxdamage 40
+set g_balance_falldamage_onlyvertical 0
 set g_balance_damagepush_speedfactor 2.5
 set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
 set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
index c722638..bcd5848 100644 (file)
@@ -185,6 +185,7 @@ set g_balance_falldamage_deadminspeed 250
 set g_balance_falldamage_minspeed 900
 set g_balance_falldamage_factor 0.20
 set g_balance_falldamage_maxdamage 40
+set g_balance_falldamage_onlyvertical 0
 set g_balance_damagepush_speedfactor 2.5
 set g_balance_contents_damagerate 0.2 // ticrate interval for applying damage with playerdamage/projectiledamage
 set g_balance_contents_drowndelay 10 // time under water before a player begins drowning
index c32867d..f7b0135 100644 (file)
@@ -12,7 +12,7 @@
 # MasterWord, 2016
 # Mensious Mensious <ektoras@tutanota.com>, 2018-2019
 # Vindex <kon14.inside@gmail.com>, 2014
-# Γιάννης Ανθυμίδης, 2011-2012
+# Yannis Anthymidis, 2011-2012
 msgid ""
 msgstr ""
 "Project-Id-Version: Xonotic\n"
index d281638..4c19cfd 100644 (file)
@@ -6,7 +6,7 @@
 # adem4ik, 2014
 # Alex Talker <alextalker7@gmail.com>, 2014-2015
 # Andrei Stepanov, 2014
-# Andrei Stepanov <adem4ik@gmail.com>, 2014-2019
+# Andrei Stepanov <adem4ik@gmail.com>, 2014-2020
 # Andrey P <andrey.pyntikov@gmail.com>, 2016
 # Artem Vorotnikov <artem@vorotnikov.me>, 2015
 # Lord Canistra <lordcanistra@gmail.com>, 2011
@@ -19,7 +19,7 @@ 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-11-21 19:30+0000\n"
+"PO-Revision-Date: 2020-01-14 18:19+0000\n"
 "Last-Translator: Andrei Stepanov <adem4ik@gmail.com>\n"
 "Language-Team: Russian (http://www.transifex.com/team-xonotic/xonotic/"
 "language/ru/)\n"
@@ -1202,7 +1202,7 @@ msgstr "Голосование за карту"
 #: qcsrc/client/mapvoting.qc:392
 #, c-format
 msgid "%d seconds left"
-msgstr "СекÑ\83нд Ð¾Ñ\81Ñ\82алоÑ\81Ñ\8c: %d"
+msgstr "Ð\9eÑ\81Ñ\82алоÑ\81Ñ\8c Ñ\81екÑ\83нд: %d"
 
 #: qcsrc/client/mapvoting.qc:505
 msgid "mv_mapdownload: ^3You're not supposed to use this command on your own!"
index 47631f0..ae3fec0 100644 (file)
@@ -32,10 +32,10 @@ seta crosshair_hitindication_speed 5
 
 // hit testing/tracing for special effects for the crosshair
 set g_trueaim_minrange 44 "TrueAim minimum range (TrueAim adjusts shots so they hit the crosshair point even though the gun is not at the screen center)"
-seta crosshair_hittest 1 "do a crosshair hit evaluation, applying effects from the _blur, _scale, and _showipact cvars"
+seta crosshair_hittest 1 "do a crosshair hit evaluation, applying effects from the _blur and _scale cvars"
 seta crosshair_hittest_blur 1 "blur the crosshair if the shot is obstructed"
 seta crosshair_hittest_scale 1.25 "shrink crosshair if shot is obstructed or aiming at a teammate"
-seta crosshair_hittest_showimpact 0 "move the crosshair to the actual impact location if obstructed"
+seta crosshair_hittest_showimpact 0 "move the crosshair to the actual impact location if obstructed (debug setting, very glitchy!)"
 
 // change color based on special case
 seta crosshair_color_special 1 "special color handling for crosshair... 1 = per-weapon crosshair color (see crosshair_per_weapon), 2 = crosshair changes color based on health, 3 = rainbow/random color selection"
index 597bb46..b935b03 100644 (file)
@@ -31,6 +31,7 @@ r_shadow_realtime_world_shadows 0
 r_shadow_shadowmapping 0
 r_shadow_usenormalmap 1
 r_showsurfaces 0
+r_sky 1
 r_subdivisions_tolerance 3
 r_texture_dds_load 1
 r_water 1
index c954958..7c9921a 100644 (file)
@@ -31,6 +31,7 @@ r_shadow_realtime_world_shadows 0
 r_shadow_shadowmapping 0
 r_shadow_usenormalmap 0
 r_showsurfaces 0
+r_sky 1
 r_subdivisions_tolerance 8
 r_texture_dds_load 1
 r_water 0
index 4ea20a1..b701674 100644 (file)
@@ -31,6 +31,7 @@ r_shadow_realtime_world_shadows 0
 r_shadow_shadowmapping 0
 r_shadow_usenormalmap 0
 r_showsurfaces 0
+r_sky 1
 r_subdivisions_tolerance 4
 r_texture_dds_load 1
 r_water 0
index ba708cb..c519617 100644 (file)
@@ -31,6 +31,7 @@ r_shadow_realtime_world_shadows 0
 r_shadow_shadowmapping 0
 r_shadow_usenormalmap 1
 r_showsurfaces 0
+r_sky 1
 r_subdivisions_tolerance 3
 r_texture_dds_load 1
 r_water 0
index 7614417..7b05a1e 100644 (file)
@@ -31,6 +31,7 @@ r_shadow_realtime_world_shadows 0
 r_shadow_shadowmapping 0
 r_shadow_usenormalmap 0
 r_showsurfaces 3
+r_sky 0
 r_subdivisions_tolerance 16
 r_texture_dds_load 1
 r_water 0
index 6d8ee6f..28b434d 100644 (file)
@@ -29,7 +29,9 @@ alias sv_hook_gamestart_ka
 alias sv_hook_gamestart_ft
 alias sv_hook_gamestart_inv
 alias sv_hook_gamestart_duel
-alias sv_hook_gamerestart
+// there is currently no hook for when the match is restarted
+// see sv_hook_readyrestart for previous uses of this hook
+//alias sv_hook_gamerestart
 alias sv_hook_gameend
 
 
@@ -245,6 +247,8 @@ set g_ctf_flag_return_dropped 100 "automatically return the flag to base if drop
 set g_ctf_flag_return_damage 0 "allow the flag to be damaged, reducing time needed to automatically return to base"
 set g_ctf_flag_return_damage_delay 0 "how much time the flag takes to automatically return to base if it falls into lava/slime/trigger hurt"
 set g_ctf_flag_return_when_unreachable 1 "automatically return the flag if it falls into lava/slime/trigger hurt"
+set g_ctf_flag_waypoint 1 "show a waypoint at the flag for easy discovery and directions"
+set g_ctf_flag_waypoint_maxdistance 0 "maximum distance from a flag from which their waypoint is shown, a value of 0 means no limit"
 set g_ctf_flagcarrier_auto_helpme_damage 100 "automatically place a helpme notification on flag carrier waypointsprite if they get hit and their health dips below this value"
 set g_ctf_flagcarrier_auto_helpme_time 2 "antispam time for the helpme notification"
 set g_ctf_flagcarrier_selfdamagefactor 1
index d815142..813ecba 100644 (file)
@@ -64,7 +64,6 @@ seta hud_panel_weapons_timeout_fadefgmin "0.4"
 seta hud_panel_weapons_timeout_speed_in "0.25"
 seta hud_panel_weapons_timeout_speed_out "0.75"
 seta hud_panel_weapons_onlyowned "1"
-seta hud_panel_weapons_orderbyimpulse "1"
 seta hud_panel_weapons_noncurrent_alpha "0.8"
 seta hud_panel_weapons_noncurrent_scale "0.9"
 seta hud_panel_weapons_selection_radius "0"
index 8766bcb..c5cfe4a 100644 (file)
@@ -64,7 +64,6 @@ seta hud_panel_weapons_timeout_fadefgmin "0.4"
 seta hud_panel_weapons_timeout_speed_in "0.25"
 seta hud_panel_weapons_timeout_speed_out "0.75"
 seta hud_panel_weapons_onlyowned "1"
-seta hud_panel_weapons_orderbyimpulse "1"
 seta hud_panel_weapons_noncurrent_alpha "1"
 seta hud_panel_weapons_noncurrent_scale "1"
 seta hud_panel_weapons_selection_radius "0"
index 02940f8..b728258 100644 (file)
@@ -64,7 +64,6 @@ seta hud_panel_weapons_timeout_fadefgmin "0"
 seta hud_panel_weapons_timeout_speed_in "0.25"
 seta hud_panel_weapons_timeout_speed_out "0.75"
 seta hud_panel_weapons_onlyowned "1"
-seta hud_panel_weapons_orderbyimpulse "1"
 seta hud_panel_weapons_noncurrent_alpha "1"
 seta hud_panel_weapons_noncurrent_scale "1"
 seta hud_panel_weapons_selection_radius "0"
index 41a47d7..3bfd694 100644 (file)
@@ -64,7 +64,6 @@ seta hud_panel_weapons_timeout_fadefgmin "0"
 seta hud_panel_weapons_timeout_speed_in "0.25"
 seta hud_panel_weapons_timeout_speed_out "0.75"
 seta hud_panel_weapons_onlyowned "1"
-seta hud_panel_weapons_orderbyimpulse "1"
 seta hud_panel_weapons_noncurrent_alpha "1"
 seta hud_panel_weapons_noncurrent_scale "1"
 seta hud_panel_weapons_selection_radius "0"
index f4a5e04..c808f62 100644 (file)
@@ -64,7 +64,6 @@ seta hud_panel_weapons_timeout_fadefgmin "0"
 seta hud_panel_weapons_timeout_speed_in "0.25"
 seta hud_panel_weapons_timeout_speed_out "0.75"
 seta hud_panel_weapons_onlyowned "1"
-seta hud_panel_weapons_orderbyimpulse "1"
 seta hud_panel_weapons_noncurrent_alpha "1"
 seta hud_panel_weapons_noncurrent_scale "1"
 seta hud_panel_weapons_selection_radius "0"
index ea5dc69..b0b02d0 100644 (file)
@@ -64,7 +64,6 @@ seta hud_panel_weapons_timeout_fadefgmin "0"
 seta hud_panel_weapons_timeout_speed_in "0.25"
 seta hud_panel_weapons_timeout_speed_out "0.75"
 seta hud_panel_weapons_onlyowned "0"
-seta hud_panel_weapons_orderbyimpulse "1"
 seta hud_panel_weapons_noncurrent_alpha "1"
 seta hud_panel_weapons_noncurrent_scale "1"
 seta hud_panel_weapons_selection_radius "0"
index 0fcbed2..b6ad346 100644 (file)
@@ -6,7 +6,7 @@
 // =========
 //  dodging
 // =========
-set g_dodging 0 "set to 1 to enable dodging in games"
+set g_dodging 0 "set to 1 to enable dodging (quick acceleration in a given direction)"
 
 seta cl_dodging_timeout 0.2 "determines how long apart (in seconds) two taps on the same direction key are considered a dodge. use 0 to disable"
 
@@ -110,7 +110,7 @@ set g_invincible_projectiles 0 "set to 1 to disable any damage to projectiles in
 // ===============
 //  rocket flying
 // ===============
-set g_rocket_flying 0 "set to 1 to enable rocket flying in all balance configs"
+set g_rocket_flying 0 "make rocket jumping easier - use the remote_jump weapon cvars for selfdamage and selfpush force"
 set g_rocket_flying_disabledelays 1 "disable detonation delays on rockets and mines"
 
 
@@ -144,7 +144,7 @@ set g_nix_with_powerups 0 "when 1, powerups still show up in NIX"
 // ================
 set g_physical_items 0 "1 uses ODE physics for dropped weapons, 2 for all items, requires physics_ode to be enabled"
 set g_physical_items_damageforcescale 3 "how affected physical weapons are by damage"
-set g_physical_items_reset 1 "return map items to their original lotation after being picked up"
+set g_physical_items_reset 1 "return map items to their original location after being picked up"
 
 
 // ===============
@@ -152,9 +152,9 @@ set g_physical_items_reset 1 "return map items to their original lotation after
 // ===============
 set g_touchexplode 0 "touching other players causes an explosion"
 set g_touchexplode_radius 50
-set g_touchexplode_damage 10
+set g_touchexplode_damage 20
 set g_touchexplode_edgedamage 0
-set g_touchexplode_force 150
+set g_touchexplode_force 300
 
 
 // ================
@@ -184,7 +184,7 @@ set g_random_gravity_negative 1000 "negative gravity multiplier"
 // =======
 //  Nades
 // =======
-set g_nades 0 "enable off-hand grenades"
+set g_nades 0 "enable off-hand grenades - use the 'dropweapon' (second press throws) or 'hook' (release throws) binds"
 set g_nades_spread 0.04 "random spread offset of throw direction"
 set g_nades_throw_offset "0 -25 0" "nade throwing offset"
 set g_nades_spawn 1 "give nades right away when player spawns rather than delaying entire refire"
@@ -309,7 +309,8 @@ set g_buffs_effects 1 "show particle effects from carried buffs"
 set g_buffs_waypoint_distance 1024 "maximum distance at which buff waypoint can be seen from item"
 set g_buffs_pickup_anyway 0 "instantly respawn the buff when it is picked up, instead of waiting for the player to drop it"
 set g_buffs_pickup_delay 0.7 "cooldown before player can pick up another buff after dropping one"
-set g_buffs_randomize 1 "randomize buff type when player drops buff"
+set g_buffs_randomize 1 "randomize buff type when player drops the buff, only applies to teamplay gamemodes if g_buffs_randomize_teamplay is enabled"
+set g_buffs_randomize_teamplay 1 "in teamplay gamemodes, randomize buff type when player drops the buff, requires g_buffs_randomize"
 set g_buffs_random_lifetime 30 "re-spawn the buff again if it hasn't been touched after this time in seconds"
 set g_buffs_random_location 0 "randomize buff location on start and when reset"
 set g_buffs_random_location_attempts 10 "number of random locations a single buff will attempt to respawn at before giving up"
@@ -387,7 +388,7 @@ set g_buffs_flight_time 60 "flight buff carry time"
 // ================
 //  grappling hook
 // ================
-set g_grappling_hook 0 "let players spawn with the grappling hook which allows them to pull themselves up"
+set g_grappling_hook 0 "let players spawn with the grappling hook which allows them to pull themselves"
 set g_grappling_hook_useammo 0 "use ammunition with the off-hand grappling hook"
 
 
index d09b2c5..7c8e3b8 100644 (file)
@@ -93,8 +93,8 @@ pk3: csprogs-$(VER).pk3
        $(eval DAT=$(PROG)-$(VER).dat)
        $(eval LNO=$(PROG)-$(VER).lno)
        @ echo "http://xonotic.org" > $(TXT)
-       @ ln -f $(PROGS_OUT)/$(PROG).dat $(DAT)
-       @ ln -f $(PROGS_OUT)/$(PROG).lno $(LNO)
+       @ cp -f $(PROGS_OUT)/$(PROG).dat $(DAT)
+       @ cp -f $(PROGS_OUT)/$(PROG).lno $(LNO)
        @ $(RM) *.pk3
        $(ZIP) $(PK3) $(TXT) $(DAT) $(LNO)
        @ $(RM) $(TXT) $(DAT) $(LNO)
index d113556..f87b94e 100644 (file)
@@ -70,8 +70,8 @@ bool autocvar_cl_spawn_event_particles;
 bool autocvar_cl_spawn_event_sound = 1;
 // float autocvar_cl_spawn_point_model;
 bool autocvar_cl_spawn_point_particles;
-float autocvar_cl_spawn_point_dist_min = 1200;
-float autocvar_cl_spawn_point_dist_max = 1600;
+float autocvar_cl_spawn_point_dist_min = 800;
+float autocvar_cl_spawn_point_dist_max = 1200;
 bool autocvar_cl_spawnzoom = 1;
 float autocvar_cl_spawnzoom_speed = 1;
 float autocvar_cl_spawnzoom_factor = 2;
@@ -151,7 +151,7 @@ float autocvar_crosshair_ring_reload_alpha;
 float autocvar_crosshair_ring_reload_size;
 float autocvar_crosshair_size;
 bool autocvar_crosshair_chase = true;
-float crosshair_chase_playeralpha = 0.25;
+float autocvar_crosshair_chase_playeralpha = 0.25;
 int autocvar_ekg;
 float autocvar_fov;
 bool autocvar_hud_cursormode = true;
@@ -413,7 +413,7 @@ float autocvar_cl_hitsound_min_pitch = 0.75;
 float autocvar_cl_hitsound_max_pitch = 1.5;
 float autocvar_cl_hitsound_nom_damage = 25;
 float autocvar_cl_hitsound_antispam_time;
-int autocvar_cl_eventchase_spectated_change = 1;
+bool autocvar_cl_eventchase_spectated_change = false;
 float autocvar_cl_eventchase_spectated_change_time = 1;
 int autocvar_cl_eventchase_death = 1;
 float autocvar_cl_eventchase_distance = 140;
index db1a5af..0cf7129 100644 (file)
@@ -173,10 +173,6 @@ REPLICATE(cvar_cl_weaponpriorities[9], string, "cl_weaponpriority9");
 
 float bgmtime;
 
-string weaponorder_byimpulse; // NOTE: this is a misnomer, weapon order is not always sorted by impulse
-string weaponorder_bypriority;
-bool weapons_orderbyimpulse; // update priority list when toggling this
-
 float vortex_charge_movingavg;
 
 int serverflags;
index 9da25eb..3a13048 100644 (file)
@@ -398,6 +398,8 @@ Main HUD system
 ==================
 */
 
+float lasthud;
+float vh_notice_time;
 void HUD_Vehicle()
 {
        if(autocvar__hud_configure) return;
@@ -409,6 +411,11 @@ void HUD_Vehicle()
                Vehicle info = Vehicles_from(hud);
                info.vr_hud(info);
        }
+
+       if(hud != HUD_NORMAL && lasthud == HUD_NORMAL)
+               vh_notice_time = time + autocvar_cl_vehicles_notify_time;
+
+       lasthud = hud;
 }
 
 void HUD_Panel_Draw(entity panent)
@@ -588,6 +595,7 @@ bool HUD_WouldShowCursor()
        return false;
 }
 
+float prev_myteam;
 void HUD_Main()
 {
        int i;
@@ -596,6 +604,13 @@ void HUD_Main()
        else
                hud_fade_alpha = 1 - autocvar__menu_alpha;
 
+       if(myteam != prev_myteam)
+       {
+               myteamcolors = colormapPaletteColor(myteam, 1);
+               FOREACH(hud_panels, true, it.update_time = time);
+               prev_myteam = myteam;
+       }
+
        HUD_Configure_Frame();
 
        if(scoreboard_fade_alpha == 1)
index 3e61f9b..c58fb2a 100644 (file)
@@ -854,6 +854,11 @@ void QuickMenu_Default(string target_submenu)
                QUICKMENU_ENTRY(CTX(_("QMCMD^Shuffle teams")), "vcall shuffleteams")
        QUICKMENU_SMENU(CTX(_("QMCMD^Call a vote")), "Call a vote")
 
+       if(spectatee_status != 0)
+       {
+       QUICKMENU_SMENU_PL(CTX(_("QMCMD^Spectate a player")), "Spectate a player", "spectate \"%s^7\"", 0, 1)
+       }
+
        if(target_submenu != "" && !target_submenu_found)
        {
                LOG_INFOF("Couldn't find submenu \"%s\"", target_submenu);
index e11a134..a6d1cc9 100644 (file)
@@ -1621,14 +1621,14 @@ void Scoreboard_Draw()
                        {
                                str = strcat(str, sprintf(_("^5%s %s"), ScoreString(teamscores_flags(ts_primary), fl),
                                        (teamscores_label(ts_primary) == "score")   ? CTX(_("SCO^points")) :
-                                       (teamscores_label(ts_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       (teamscores_label(ts_primary) == "fastest") ? "" :
                                        TranslateScoresLabel(teamscores_label(ts_primary))));
                        }
                        else
                        {
                                str = strcat(str, sprintf(_("^5%s %s"), ScoreString(scores_flags(ps_primary), fl),
                                        (scores_label(ps_primary) == "score")   ? CTX(_("SCO^points")) :
-                                       (scores_label(ps_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       (scores_label(ps_primary) == "fastest") ? "" :
                                        TranslateScoresLabel(scores_label(ps_primary))));
                        }
                }
@@ -1640,14 +1640,14 @@ void Scoreboard_Draw()
                        {
                                str = strcat(str, sprintf(_("^2+%s %s"), ScoreString(teamscores_flags(ts_primary), ll),
                                        (teamscores_label(ts_primary) == "score")   ? CTX(_("SCO^points")) :
-                                       (teamscores_label(ts_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       (teamscores_label(ts_primary) == "fastest") ? "" :
                                        TranslateScoresLabel(teamscores_label(ts_primary))));
                        }
                        else
                        {
                                str = strcat(str, sprintf(_("^2+%s %s"), ScoreString(scores_flags(ps_primary), ll),
                                        (scores_label(ps_primary) == "score")   ? CTX(_("SCO^points")) :
-                                       (scores_label(ps_primary) == "fastest") ? CTX(_("SCO^is beaten")) :
+                                       (scores_label(ps_primary) == "fastest") ? "" :
                                        TranslateScoresLabel(scores_label(ps_primary))));
                        }
                }
index 832ffad..8668886 100644 (file)
@@ -39,6 +39,8 @@ int weaponorder_cmp(int i, int j, entity pass)
        weapon_size.y = panel_size.y / rows; \
 MACRO_END
 
+string cl_weaponpriority_old;
+bool weapons_orderbyimpulse_old;
 void HUD_Weapons()
 {
        // declarations
@@ -90,19 +92,19 @@ void HUD_Weapons()
        // update generic hud functions
        HUD_Panel_LoadCvars();
 
-       // figure out weapon order (how the weapons are sorted) // TODO make this configurable
-       if(weaponorder_bypriority != autocvar_cl_weaponpriority || autocvar_hud_panel_weapons_orderbyimpulse != weapons_orderbyimpulse || !weaponorder[0])
+       if(cl_weaponpriority_old != autocvar_cl_weaponpriority || weapons_orderbyimpulse_old != autocvar_hud_panel_weapons_orderbyimpulse || weaponorder[0] == NULL)
        {
-               int weapon_cnt;
-               weapons_orderbyimpulse = autocvar_hud_panel_weapons_orderbyimpulse;
-               strcpy(weaponorder_bypriority, autocvar_cl_weaponpriority);
-               string weporder = W_FixWeaponOrder_ForceComplete(W_NumberWeaponOrder(weaponorder_bypriority));
+               weapons_orderbyimpulse_old = autocvar_hud_panel_weapons_orderbyimpulse;
+               strcpy(cl_weaponpriority_old, autocvar_cl_weaponpriority);
+               string weporder = W_FixWeaponOrder_ForceComplete(W_NumberWeaponOrder(cl_weaponpriority_old));
                if(autocvar_hud_panel_weapons_orderbyimpulse)
+               {
                        weporder = W_FixWeaponOrder_BuildImpulseList(weporder);
-               strcpy(weaponorder_byimpulse, weporder);
-               weaponorder_cmp_str = strcat(" ", weaponorder_byimpulse, " ");
+               }
+
+               weaponorder_cmp_str = strcat(" ", weporder, " ");
 
-               weapon_cnt = 0;
+               int weapon_cnt = 0;
                FOREACH(Weapons, it != WEP_Null && it.impulse >= 0, weaponorder[weapon_cnt++] = it);
                for(i = weapon_cnt; i < Weapons_MAX; ++i)
                        weaponorder[i] = NULL;
index b61f425..b7b7e53 100644 (file)
@@ -240,7 +240,7 @@ void Shutdown()
 bool SetTeam(entity o, int Team)
 {
        TC(int, Team);
-       devassert_once(Team);
+       //devassert_once(Team);
        entity tm;
        if(teamplay)
        {
index 3603056..bb0bfe1 100644 (file)
@@ -382,7 +382,7 @@ float PolyDrawModelSurface(entity e, float i_s)
        for(i_t = 0; i_t < n_t; ++i_t)
        {
                tri = getsurfacetriangle(e, i_s, i_t);
-               R_BeginPolygon(tex, 0);
+               R_BeginPolygon(tex, 0, false);
                R_PolygonVertex(getsurfacepoint(e, i_s, tri.x), getsurfacepointattribute(e, i_s, tri.x, SPA_TEXCOORDS0), '1 1 1', 1);
                R_PolygonVertex(getsurfacepoint(e, i_s, tri.y), getsurfacepointattribute(e, i_s, tri.y, SPA_TEXCOORDS0), '1 1 1', 1);
                R_PolygonVertex(getsurfacepoint(e, i_s, tri.z), getsurfacepointattribute(e, i_s, tri.z, SPA_TEXCOORDS0), '1 1 1', 1);
@@ -415,7 +415,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
        if(f >= 1)
        {
                // draw full rectangle
-               R_BeginPolygon(pic, drawflag);
+               R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
@@ -436,7 +436,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                d = q - 1;
                if(d > 0)
                {
-                       R_BeginPolygon(pic, drawflag);
+                       R_BeginPolygon(pic, drawflag, true);
                                v = centre;                     t = '0.5 0.5 0';
                                R_PolygonVertex(v, t, rgb, a);
 
@@ -448,7 +448,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
        else if(f > 0.75)
        {
                // draw upper and first triangle
-               R_BeginPolygon(pic, drawflag);
+               R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
@@ -461,7 +461,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                        v.x -= 0.5 * ringsize.x;        t -= '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
                R_EndPolygon();
-               R_BeginPolygon(pic, drawflag);
+               R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
 
@@ -480,7 +480,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
        else if(f > 0.5)
        {
                // draw upper triangle
-               R_BeginPolygon(pic, drawflag);
+               R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        v.x += 0.5 * ringsize.x;        t += '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
@@ -497,7 +497,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                d = q - 0.5;
                if(d > 0)
                {
-                       R_BeginPolygon(pic, drawflag);
+                       R_BeginPolygon(pic, drawflag, true);
                                v = centre;                     t = '0.5 0.5 0';
                                R_PolygonVertex(v, t, rgb, a);
 
@@ -509,7 +509,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
        else if(f > 0.25)
        {
                // draw first triangle
-               R_BeginPolygon(pic, drawflag);
+               R_BeginPolygon(pic, drawflag, true);
                        v = centre;                     t = '0.5 0.5 0';
                        R_PolygonVertex(v, t, rgb, a);
 
@@ -530,7 +530,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
                d = q;
                if(d > 0)
                {
-                       R_BeginPolygon(pic, drawflag);
+                       R_BeginPolygon(pic, drawflag, true);
                                v = centre;                     t = '0.5 0.5 0';
                                R_PolygonVertex(v, t, rgb, a);
 
index c565651..cdb8894 100644 (file)
@@ -68,7 +68,7 @@ void draw_teamradar_background(float fg)
        {
                fga = 1;
                fgc = '1 1 1' * fg;
-               R_BeginPolygon(minimapname, DRAWFLAG_SCREEN | DRAWFLAG_MIPMAP);
+               R_BeginPolygon(minimapname, DRAWFLAG_SCREEN | DRAWFLAG_MIPMAP, true);
                if(v_flipped)
                {
                        R_PolygonVertex(teamradar_texcoord_to_2dcoord(mi_pictexcoord3), yinvert(mi_pictexcoord3), fgc, fga);
@@ -112,14 +112,14 @@ void draw_teamradar_player(vector coord3d, vector pangles, vector rgb)
        else
                rgb2 = '1 1 1';
 
-       R_BeginPolygon("", 0);
+       R_BeginPolygon("", 0, true);
        R_PolygonVertex(coord+forward*3, '0 0 0', rgb2, panel_fg_alpha);
        R_PolygonVertex(coord+right*4-forward*2.5, '0 1 0', rgb2, panel_fg_alpha);
        R_PolygonVertex(coord-forward*2, '1 0 0', rgb2, panel_fg_alpha);
        R_PolygonVertex(coord-right*4-forward*2.5, '1 1 0', rgb2, panel_fg_alpha);
        R_EndPolygon();
 
-       R_BeginPolygon("", 0);
+       R_BeginPolygon("", 0, true);
        R_PolygonVertex(coord+forward*2, '0 0 0', rgb, panel_fg_alpha);
        R_PolygonVertex(coord+right*3-forward*2, '0 1 0', rgb, panel_fg_alpha);
        R_PolygonVertex(coord-forward, '1 0 0', rgb, panel_fg_alpha);
@@ -164,7 +164,7 @@ void draw_teamradar_link(vector start, vector end, int colors)
        c0 = colormapPaletteColor(colors & 0x0F, false);
        c1 = colormapPaletteColor((colors & 0xF0) / 0x10, false);
 
-       R_BeginPolygon("", 0);
+       R_BeginPolygon("", 0, true);
        R_PolygonVertex(start - norm, '0 0 0', c0, panel_fg_alpha);
        R_PolygonVertex(start + norm, '0 1 0', c0, panel_fg_alpha);
        R_PolygonVertex(end + norm, '1 1 0', c1, panel_fg_alpha);
index 4b8bc48..eb341d5 100644 (file)
@@ -48,7 +48,7 @@
 #define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT)
 
 float autocvar_cl_viewmodel_scale;
-float autocvar_cl_viewmodel_alpha;
+float autocvar_cl_viewmodel_alpha = 1;
 
 bool autocvar_cl_bobmodel;
 float autocvar_cl_bobmodel_speed;
@@ -394,7 +394,6 @@ STATIC_INIT(fpscounter_init)
        showfps_prevfps_time = currentTime; // we must initialize it to avoid an instant low frame sending
 }
 
-float drawtime;
 float avgspeed;
 vector GetCurrentFov(float fov)
 {
@@ -755,6 +754,146 @@ int WantEventchase(entity this, bool want_vehiclechase)
        return 0;
 }
 
+void View_EventChase(entity this)
+{
+       // event chase camera
+       if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
+       {
+               if(STAT(CAMERA_SPECTATOR))
+               {
+                       if(spectatee_status > 0)
+                       {
+                               if(!autocvar_chase_active)
+                               {
+                                       cvar_set("chase_active", "-2");
+                                       return;
+                               }
+                       }
+                       else if(autocvar_chase_active == -2)
+                               cvar_set("chase_active", "0");
+
+                       if(autocvar_chase_active == -2)
+                               return;
+               }
+               else if(autocvar_chase_active == -2)
+                       cvar_set("chase_active", "0");
+
+               bool vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
+
+               float vehicle_viewdist = 0;
+               vector vehicle_viewofs = '0 0 0';
+
+               if(vehicle_chase)
+               {
+                       if(hud != HUD_BUMBLEBEE_GUN)
+                       {
+                               Vehicle info = Vehicles_from(hud);
+                               vehicle_viewdist = info.height;
+                               vehicle_viewofs = info.view_ofs;
+                               if(vehicle_viewdist < 0) // when set below 0, this vehicle doesn't use third person view (gunner slots)
+                                       vehicle_chase = false;
+                       }
+                       else
+                               vehicle_chase = false;
+               }
+
+               int eventchase = WantEventchase(this, vehicle_chase);
+               if (eventchase)
+               {
+                       vector current_view_origin_override = '0 0 0';
+                       vector view_offset_override = '0 0 0';
+                       float chase_distance_override = 0;
+                       bool custom_eventchase = MUTATOR_CALLHOOK(CustomizeEventchase, this);
+                       if(custom_eventchase)
+                       {
+                               current_view_origin_override = M_ARGV(0, vector);
+                               view_offset_override = M_ARGV(1, vector);
+                               chase_distance_override = M_ARGV(0, float);
+                       }
+                       eventchase_running = true;
+
+                       // make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
+                       vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
+                       if (custom_eventchase)
+                               current_view_origin = current_view_origin_override;
+
+                       // detect maximum viewoffset and use it
+                       vector view_offset = autocvar_cl_eventchase_viewoffset;
+                       if(vehicle_chase)
+                       {
+                               if(vehicle_viewofs)
+                                       view_offset = vehicle_viewofs;
+                               else
+                                       view_offset = autocvar_cl_eventchase_vehicle_viewoffset;
+                       }
+                       if (custom_eventchase)
+                               view_offset = view_offset_override;
+
+                       if(view_offset)
+                       {
+                               WarpZone_TraceLine(current_view_origin, current_view_origin + view_offset + ('0 0 1' * autocvar_cl_eventchase_maxs.z), MOVE_WORLDONLY, this);
+                               if(trace_fraction == 1) { current_view_origin += view_offset; }
+                               else { current_view_origin.z += max(0, (trace_endpos.z - current_view_origin.z) - autocvar_cl_eventchase_maxs.z); }
+                       }
+
+                       // We must enable chase_active to get a third person view (weapon viewmodel hidden and own player model showing).
+                       // Ideally, there should be another way to enable third person cameras, such as through setproperty()
+                       // -1 enables chase_active while marking it as set by this code, and not by the user (which would be 1)
+                       if(!autocvar_chase_active) { cvar_set("chase_active", "-1"); }
+
+                       // make the camera smooth back
+                       float chase_distance = autocvar_cl_eventchase_distance;
+                       if(vehicle_chase)
+                       {
+                               if(vehicle_viewofs)
+                                       chase_distance = vehicle_viewdist;
+                               else
+                                       chase_distance = autocvar_cl_eventchase_vehicle_distance;
+                       }
+                       if (custom_eventchase)
+                               chase_distance = chase_distance_override;
+
+                       if(autocvar_cl_eventchase_speed && eventchase_current_distance < chase_distance)
+                               eventchase_current_distance += autocvar_cl_eventchase_speed * (chase_distance - eventchase_current_distance) * frametime; // slow down the further we get
+                       else if(eventchase_current_distance != chase_distance)
+                               eventchase_current_distance = chase_distance;
+
+                       vector forward, right, up;
+                       MAKE_VECTORS(view_angles, forward, right, up);
+
+                       vector eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
+                       WarpZone_TraceBox(current_view_origin, autocvar_cl_eventchase_mins, autocvar_cl_eventchase_maxs, eventchase_target_origin, MOVE_WORLDONLY, this);
+
+                       // If the boxtrace fails, revert back to line tracing.
+                       if(!this.viewloc)
+                       if(trace_startsolid)
+                       {
+                               eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
+                               WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, this);
+                               setproperty(VF_ORIGIN, (trace_endpos - (forward * autocvar_cl_eventchase_mins.z)));
+                       }
+                       else { setproperty(VF_ORIGIN, trace_endpos); }
+
+                       if(!this.viewloc)
+                               setproperty(VF_ANGLES, WarpZone_TransformVAngles(WarpZone_trace_transform, view_angles));
+               }
+
+               if (eventchase <= 0 && autocvar_chase_active < 0) // time to disable chase_active if it was set by this code
+               {
+                       eventchase_running = false;
+                       cvar_set("chase_active", "0");
+                       eventchase_current_distance = 0; // start from 0 next time
+               }
+       }
+       // workaround for camera stuck between player's legs when using chase_active 1
+       // because the engine stops updating the chase_active camera when the game ends
+       else if(intermission)
+       {
+               cvar_settemp("chase_active", "-1");
+               eventchase_current_distance = 0;
+       }
+}
+
 void HUD_Crosshair_Vehicle(entity this)
 {
        if(hud != HUD_BUMBLEBEE_GUN)
@@ -780,7 +919,7 @@ void UpdateDamage()
        if (damage_dealt_time != damage_dealt_time_prev)
        {
                unaccounted_damage += unaccounted_damage_new;
-               LOG_TRACE("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")");
+               //LOG_TRACE("dmg total: ", ftos(unaccounted_damage), " (+", ftos(unaccounted_damage_new), ")");
        }
        damage_dealt_time_prev = damage_dealt_time;
 
@@ -829,7 +968,7 @@ void HitSound()
                                pitch_shift = mirror_value + (mirror_value - pitch_shift);
                        }
 
-                       LOG_TRACE("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift));
+                       //LOG_TRACE("dmg total (dmg): ", ftos(unaccounted_damage), " , pitch shift: ", ftos(pitch_shift));
 
                        // todo: avoid very long and very short sounds from wave stretching using different sound files? seems unnecessary
                        // todo: normalize sound pressure levels? seems unnecessary
@@ -981,12 +1120,12 @@ void HUD_Crosshair(entity this)
                else if(autocvar_chase_active > 0 && autocvar_crosshair_chase)
                {
                        vector player_org = ((csqcplayer) ? csqcplayer.origin + csqcplayer.view_ofs : view_origin);
-                       if(csqcplayer && crosshair_chase_playeralpha && crosshair_chase_playeralpha < 1)
+                       if(csqcplayer && autocvar_crosshair_chase_playeralpha && autocvar_crosshair_chase_playeralpha < 1)
                        {
                                traceline(view_origin, view_origin + max_shot_distance * view_forward, MOVE_NORMAL, NULL);
                                float myalpha = (!csqcplayer.m_alpha) ? 1 : csqcplayer.m_alpha;
                                if(trace_ent == csqcplayer && STAT(HEALTH) > 0)
-                                       csqcplayer.alpha = min(crosshair_chase_playeralpha, myalpha);
+                                       csqcplayer.alpha = min(autocvar_crosshair_chase_playeralpha, myalpha);
                                else
                                        csqcplayer.alpha = csqcplayer.m_alpha;
                        }
@@ -1553,267 +1692,517 @@ void HUD_Mouse(entity player)
        HUD_Cursor_Show();
 }
 
-bool ov_enabled;
-float oldr_nearclip;
-float oldr_farclip_base;
-float oldr_farclip_world;
-float oldr_novis;
-float oldr_useportalculling;
-float oldr_useinfinitefarclip;
-
-float prev_myteam;
-int lasthud;
-float vh_notice_time;
-void CSQC_UpdateView(entity this, float w, float h)
+void View_NightVision()
 {
-       TC(int, w); TC(int, h);
-       entity e;
-       float fov;
-       float f;
-       vector vf_size, vf_min;
+       if(!(autocvar_r_fakelight >= 2 || autocvar_r_fullbright) || (serverflags & SERVERFLAG_ALLOW_FULLBRIGHT))
+               return;
+
+       // apply night vision effect
+       vector tc_00, tc_01, tc_10, tc_11;
+       vector rgb = '0 0 0';
        float a;
 
-       execute_next_frame();
+       if(!nightvision_noise)
+       {
+               nightvision_noise = new(nightvision_noise);
+       }
+       if(!nightvision_noise2)
+       {
+               nightvision_noise2 = new(nightvision_noise2);
+       }
+
+       // color tint in yellow
+       drawfill('0 0 0', autocvar_vid_conwidth * '1 0 0' + autocvar_vid_conheight * '0 1 0', '0.5 1 0.3', 1, DRAWFLAG_MODULATE);
+
+       // draw BG
+       a = Noise_Pink(nightvision_noise, frametime * 1.5) * 0.05 + 0.15;
+       rgb = '1 1 1';
+       tc_00 = '0 0 0' + '0.2 0 0' * sin(time * 0.3) + '0 0.3 0' * cos(time * 0.7);
+       tc_01 = '0 2.25 0' + '0.6 0 0' * cos(time * 1.2) - '0 0.3 0' * sin(time * 2.2);
+       tc_10 = '1.5 0 0' - '0.2 0 0' * sin(time * 0.5) + '0 0.5 0' * cos(time * 1.7);
+       //tc_11 = '1 1 0' + '0.6 0 0' * sin(time * 0.6) + '0 0.3 0' * cos(time * 0.1);
+       tc_11 = tc_01 + tc_10 - tc_00;
+       R_BeginPolygon("gfx/nightvision-bg.tga", DRAWFLAG_ADDITIVE, true);
+       R_PolygonVertex('0 0 0', tc_00, rgb, a);
+       R_PolygonVertex(autocvar_vid_conwidth * '1 0 0', tc_10, rgb, a);
+       R_PolygonVertex(autocvar_vid_conwidth * '1 0 0' + autocvar_vid_conheight * '0 1 0', tc_11, rgb, a);
+       R_PolygonVertex(autocvar_vid_conheight * '0 1 0', tc_01, rgb, a);
+       R_EndPolygon();
+
+       // draw FG
+       a = Noise_Pink(nightvision_noise2, frametime * 0.1) * 0.05 + 0.12;
+       rgb = '0.3 0.6 0.4' + '0.1 0.4 0.2' * Noise_White(nightvision_noise2, frametime);
+       tc_00 = '0 0 0' + '1 0 0' * Noise_White(nightvision_noise2, frametime) + '0 1 0' * Noise_White(nightvision_noise2, frametime);
+       tc_01 = tc_00 + '0 3 0' * (1 + Noise_White(nightvision_noise2, frametime) * 0.2);
+       tc_10 = tc_00 + '2 0 0' * (1 + Noise_White(nightvision_noise2, frametime) * 0.3);
+       tc_11 = tc_01 + tc_10 - tc_00;
+       R_BeginPolygon("gfx/nightvision-fg.tga", DRAWFLAG_ADDITIVE, true);
+       R_PolygonVertex('0 0 0', tc_00, rgb, a);
+       R_PolygonVertex(autocvar_vid_conwidth * '1 0 0', tc_10, rgb, a);
+       R_PolygonVertex(autocvar_vid_conwidth * '1 0 0' + autocvar_vid_conheight * '0 1 0', tc_11, rgb, a);
+       R_PolygonVertex(autocvar_vid_conheight * '0 1 0', tc_01, rgb, a);
+       R_EndPolygon();
+}
 
-       ++framecount;
+void DrawReticle(entity this)
+{
+       if(!autocvar_cl_reticle || MUTATOR_CALLHOOK(DrawReticle))
+       {
+               reticle_type = 0;
+               return;
+       }
 
-       stats_get();
-       hud = STAT(HUD);
+       float is_dead = (STAT(HEALTH) <= 0);
+       string reticle_image = string_null;
+       bool wep_zoomed = false;
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               entity wepe = viewmodels[slot];
+               Weapon wep = wepe.activeweapon;
+               if(wep != WEP_Null && wep.wr_zoom)
+               {
+                       bool do_zoom = wep.wr_zoom(wep, NULL);
+                       if(!reticle_image && wep.w_reticle && wep.w_reticle != "")
+                               reticle_image = wep.w_reticle;
+                       wep_zoomed += do_zoom;
+               }
+       }
+       // Draw the aiming reticle for weapons that use it
+       // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
+       // It must be a persisted float for fading out to work properly (you let go of the zoom button for
+       // the view to go back to normal, so reticle_type would become 0 as we fade out)
+       if(spectatee_status || is_dead || hud != HUD_NORMAL || this.viewloc)
+       {
+               // no zoom reticle while dead
+               reticle_type = 0;
+       }
+       else if(wep_zoomed && autocvar_cl_reticle_weapon)
+       {
+               if(reticle_image) { reticle_type = 2; }
+               else { reticle_type = 0; }
+       }
+       else if(button_zoom || zoomscript_caught)
+       {
+               // normal zoom
+               reticle_type = 1;
+       }
 
-       if(hud != HUD_NORMAL && lasthud == HUD_NORMAL)
-               vh_notice_time = time + autocvar_cl_vehicles_notify_time;
+       if(reticle_type)
+       {
+               vector reticle_pos = '0 0 0', reticle_size = '0 0 0';
+               if(autocvar_cl_reticle_stretch)
+               {
+                       reticle_size.x = vid_conwidth;
+                       reticle_size.y = vid_conheight;
+                       reticle_pos.x = 0;
+                       reticle_pos.y = 0;
+               }
+               else
+               {
+                       reticle_size.x = max(vid_conwidth, vid_conheight);
+                       reticle_size.y = max(vid_conwidth, vid_conheight);
+                       reticle_pos.x = (vid_conwidth - reticle_size.x) / 2;
+                       reticle_pos.y = (vid_conheight - reticle_size.y) / 2;
+               }
 
-       lasthud = hud;
+               float f = (zoomscript_caught) ? 1 : current_zoomfraction;
 
-       ReplicateVars(false);
-       if (ReplicateVars_NOT_SENDING())
-               ReplicateVars_DELAY(0.8 + random() * 0.4); // no need to check cvars every frame
+               if(f)
+               {
+                       switch(reticle_type)
+                       {
+                               case 1: drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_normal_alpha, DRAWFLAG_NORMAL); break;
+                               case 2: if(reticle_image) drawpic(reticle_pos, reticle_image, reticle_size, '1 1 1', f * autocvar_cl_reticle_weapon_alpha, DRAWFLAG_NORMAL); break;
+                       }
+               }
+       }
+}
 
-       HUD_Scale_Disable();
+// visual overlay while in liquids
+// provides some effects to the postprocessing function
+void HUD_Contents()
+{
+       if(!autocvar_hud_contents || MUTATOR_CALLHOOK(HUD_Contents))
+               return;
 
-       if(autocvar__hud_showbinds_reload) // menu can set this one
+       // improved polyblend
+       float contentalpha_temp, incontent, liquidalpha, contentfadetime;
+       vector liquidcolor;
+
+       switch(pointcontents(view_origin))
        {
-               db_close(binddb);
-               binddb = db_create();
-               cvar_set("_hud_showbinds_reload", "0");
+               case CONTENT_WATER:
+                       liquidalpha = autocvar_hud_contents_water_alpha;
+                       liquidcolor = stov(autocvar_hud_contents_water_color);
+                       incontent = 1;
+                       break;
+
+               case CONTENT_LAVA:
+                       liquidalpha = autocvar_hud_contents_lava_alpha;
+                       liquidcolor = stov(autocvar_hud_contents_lava_color);
+                       incontent = 1;
+                       break;
+
+               case CONTENT_SLIME:
+                       liquidalpha = autocvar_hud_contents_slime_alpha;
+                       liquidcolor = stov(autocvar_hud_contents_slime_color);
+                       incontent = 1;
+                       break;
+
+               default:
+                       liquidalpha = 0;
+                       liquidcolor = '0 0 0';
+                       incontent = 0;
+                       break;
        }
 
-       if(checkextension("DP_CSQC_MINFPS_QUALITY"))
-               view_quality = getproperty(VF_MINFPS_QUALITY);
+       if(incontent) // fade in/out at different speeds so you can do e.g. instant fade when entering water and slow when leaving it.
+       { // also lets delcare previous values for blending properties, this way it isn't reset until after you have entered a different content
+               contentfadetime = autocvar_hud_contents_fadeintime;
+               liquidalpha_prev = liquidalpha;
+               liquidcolor_prev = liquidcolor;
+       }
        else
-               view_quality = 1;
+               contentfadetime = autocvar_hud_contents_fadeouttime;
 
-       button_attack2 = PHYS_INPUT_BUTTON_ATCK2(this);
-       button_zoom = PHYS_INPUT_BUTTON_ZOOM(this);
+       contentalpha_temp = bound(0, drawframetime / max(0.0001, contentfadetime), 1);
+       contentavgalpha = contentavgalpha * (1 - contentalpha_temp) + incontent * contentalpha_temp;
 
-       vf_size = getpropertyvec(VF_SIZE);
-       vf_min = getpropertyvec(VF_MIN);
-       vid_width = vf_size.x;
-       vid_height = vf_size.y;
+       if(contentavgalpha)
+               drawfill('0 0 0', vec2(vid_conwidth, vid_conheight), liquidcolor_prev, contentavgalpha * liquidalpha_prev, DRAWFLAG_NORMAL);
+
+       if(autocvar_hud_postprocessing)
+       {
+               if(autocvar_hud_contents_blur && contentavgalpha)
+               {
+                       content_blurpostprocess.x = 1;
+                       content_blurpostprocess.y = contentavgalpha * autocvar_hud_contents_blur;
+                       content_blurpostprocess.z = contentavgalpha * autocvar_hud_contents_blur_alpha;
+               }
+               else
+               {
+                       content_blurpostprocess.x = 0;
+                       content_blurpostprocess.y = 0;
+                       content_blurpostprocess.z = 0;
+               }
+       }
+}
+
+// visual pain effects on the screen
+// provides some effects to the postprocessing function
+void HUD_Damage()
+{
+       if(!autocvar_hud_damage || STAT(FROZEN))
+               return;
 
-       vector reticle_pos = '0 0 0', reticle_size = '0 0 0';
        vector splash_pos = '0 0 0', splash_size = '0 0 0';
+       splash_size.x = max(vid_conwidth, vid_conheight);
+       splash_size.y = max(vid_conwidth, vid_conheight);
+       splash_pos.x = (vid_conwidth - splash_size.x) / 2;
+       splash_pos.y = (vid_conheight - splash_size.y) / 2;
 
-       WaypointSprite_Load();
+       float myhealth_flash_temp;
+       myhealth = STAT(HEALTH);
 
-       CSQCPlayer_SetCamera();
+       // fade out
+       myhealth_flash = max(0, myhealth_flash - autocvar_hud_damage_fade_rate * frametime);
+       // add new damage
+       myhealth_flash = bound(0, myhealth_flash + dmg_take * autocvar_hud_damage_factor, autocvar_hud_damage_maxalpha);
 
-       if(player_localentnum <= maxclients) // is it a client?
-               current_player = player_localentnum - 1;
-       else // then player_localentnum is the vehicle I'm driving
-               current_player = player_localnum;
-       myteam = entcs_GetTeam(current_player);
+       float pain_threshold, pain_threshold_lower, pain_threshold_lower_health;
+       pain_threshold = autocvar_hud_damage_pain_threshold;
+       pain_threshold_lower = autocvar_hud_damage_pain_threshold_lower;
+       pain_threshold_lower_health = autocvar_hud_damage_pain_threshold_lower_health;
 
-       if(myteam != prev_myteam)
+       if(pain_threshold_lower && myhealth < pain_threshold_lower_health)
        {
-               myteamcolors = colormapPaletteColor(myteam, 1);
-               FOREACH(hud_panels, true, it.update_time = time);
-               prev_myteam = myteam;
+               pain_threshold = pain_threshold - max(autocvar_hud_damage_pain_threshold_pulsating_min, fabs(sin(M_PI * time / autocvar_hud_damage_pain_threshold_pulsating_period))) * pain_threshold_lower * (1 - max(0, myhealth)/pain_threshold_lower_health);
        }
 
-       ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
-
-       float is_dead = (STAT(HEALTH) <= 0);
+       myhealth_flash_temp = bound(0, myhealth_flash - pain_threshold, 1);
 
-       // FIXME do we need this hack?
-       if(isdemo())
+       if(myhealth_prev < 1)
        {
-               // in demos, input_buttons do not work
-               button_zoom = (autocvar__togglezoom == "-");
+               if(myhealth >= 1)
+               {
+                       myhealth_flash = 0; // just spawned, clear the flash immediately
+                       myhealth_flash_temp = 0;
+               }
+               else
+               {
+                       myhealth_flash += autocvar_hud_damage_fade_rate * frametime; // dead
+               }
        }
-       else if(button_zoom
-               && autocvar_cl_unpress_zoom_on_death
-               && (spectatee_status >= 0)
-               && (is_dead || intermission))
+
+       if(spectatee_status == -1 || intermission)
        {
-               // no zoom while dead or in intermission please
-               localcmd("-zoom\n");
-               button_zoom = false;
+               myhealth_flash = 0; // observing, or match ended
+               myhealth_flash_temp = 0;
        }
 
-       // abused multiple places below
-       entity local_player = ((csqcplayer) ? csqcplayer : CSQCModel_server2csqc(player_localentnum - 1));
-       if(!local_player)
-               local_player = this; // fall back!
+       myhealth_prev = myhealth;
 
-       // event chase camera
-       if(autocvar_chase_active <= 0) // greater than 0 means it's enabled manually, and this code is skipped
+       // IDEA: change damage color/picture based on player model for robot/alien species?
+       // pro: matches model better
+       // contra: it's not red because blood is red, but because red is an alarming color, so red should stay
+       // maybe different reddish pics?
+       if(autocvar_cl_gentle_damage || autocvar_cl_gentle)
        {
-               if(STAT(CAMERA_SPECTATOR))
+               if(autocvar_cl_gentle_damage == 2)
                {
-                       if(spectatee_status > 0)
-                       {
-                               if(!autocvar_chase_active)
-                               {
-                                       cvar_set("chase_active", "-2");
-                                       goto skip_eventchase_death;
-                               }
-                       }
-                       else if(autocvar_chase_active == -2)
-                               cvar_set("chase_active", "0");
-
-                       if(autocvar_chase_active == -2)
-                               goto skip_eventchase_death;
+                       if(myhealth_flash < pain_threshold) // only randomize when the flash is gone
+                               myhealth_gentlergb = randomvec();
                }
-               else if(autocvar_chase_active == -2)
-                       cvar_set("chase_active", "0");
-
-               bool vehicle_chase = (hud != HUD_NORMAL && (autocvar_cl_eventchase_vehicle || spectatee_status > 0));
+               else
+                       myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color);
 
-               float vehicle_viewdist = 0;
-               vector vehicle_viewofs = '0 0 0';
+               if(myhealth_flash_temp > 0)
+                       drawfill('0 0 0', vec2(vid_conwidth, vid_conheight), myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
+       }
+       else if(myhealth_flash_temp > 0)
+               drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
 
-               if(vehicle_chase)
+       if(autocvar_hud_postprocessing) // we still need to set this anyway even when chase_active is set, this way it doesn't get stuck on.
+       {
+               if(autocvar_hud_damage_blur && myhealth_flash_temp)
                {
-                       if(hud != HUD_BUMBLEBEE_GUN)
-                       {
-                               Vehicle info = Vehicles_from(hud);
-                               vehicle_viewdist = info.height;
-                               vehicle_viewofs = info.view_ofs;
-                               if(vehicle_viewdist < 0) // when set below 0, this vehicle doesn't use third person view (gunner slots)
-                                       vehicle_chase = false;
-                       }
-                       else
-                               vehicle_chase = false;
+                       damage_blurpostprocess.x = 1;
+                       damage_blurpostprocess.y = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur;
+                       damage_blurpostprocess.z = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur_alpha;
                }
+               else
+               {
+                       damage_blurpostprocess.x = 0;
+                       damage_blurpostprocess.y = 0;
+                       damage_blurpostprocess.z = 0;
+               }
+       }
+}
 
-               int eventchase = WantEventchase(this, vehicle_chase);
-               if (eventchase)
+void View_PostProcessing()
+{
+       float e1 = (autocvar_hud_postprocessing_maxbluralpha != 0);
+       float e2 = (autocvar_hud_powerup != 0);
+       if(autocvar_hud_postprocessing && (e1 || e2)) // TODO: Remove this code and re-do the postprocess handling in the engine, where it properly belongs.
+       {
+               // enable or disable rendering types if they are used or not
+               if(cvar("r_glsl_postprocess_uservec1_enable") != e1) { cvar_set("r_glsl_postprocess_uservec1_enable", ftos(e1)); }
+               if(cvar("r_glsl_postprocess_uservec2_enable") != e2) { cvar_set("r_glsl_postprocess_uservec2_enable", ftos(e2)); }
+
+               // blur postprocess handling done first (used by hud_damage and hud_contents)
+               if((damage_blurpostprocess.x || content_blurpostprocess.x))
                {
-                       vector current_view_origin_override = '0 0 0';
-                       vector view_offset_override = '0 0 0';
-                       float chase_distance_override = 0;
-                       bool custom_eventchase = MUTATOR_CALLHOOK(CustomizeEventchase, this);
-                       if(custom_eventchase)
+                       float blurradius = bound(0, damage_blurpostprocess.y + content_blurpostprocess.y, autocvar_hud_postprocessing_maxblurradius);
+                       float bluralpha = bound(0, damage_blurpostprocess.z + content_blurpostprocess.z, autocvar_hud_postprocessing_maxbluralpha);
+                       if(blurradius != old_blurradius || bluralpha != old_bluralpha) // reduce cvar_set spam as much as possible
                        {
-                               current_view_origin_override = M_ARGV(0, vector);
-                               view_offset_override = M_ARGV(1, vector);
-                               chase_distance_override = M_ARGV(0, float);
+                               cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(blurradius), " ", ftos(bluralpha), " 0 0"));
+                               old_blurradius = blurradius;
+                               old_bluralpha = bluralpha;
                        }
-                       eventchase_running = true;
+               }
+               else if(cvar_string("r_glsl_postprocess_uservec1") != "0 0 0 0") // reduce cvar_set spam as much as possible
+               {
+                       cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0");
+                       old_blurradius = 0;
+                       old_bluralpha = 0;
+               }
 
-                       // make special vector since we can't use view_origin (It is one frame old as of this code, it gets set later with the results this code makes.)
-                       vector current_view_origin = (csqcplayer ? csqcplayer.origin : pmove_org);
-                       if (custom_eventchase)
-                               current_view_origin = current_view_origin_override;
+               // edge detection postprocess handling done second (used by hud_powerup)
+               float sharpen_intensity = 0, strength_finished = STAT(STRENGTH_FINISHED), invincible_finished = STAT(INVINCIBLE_FINISHED);
+               if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); }
+               if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); }
 
-                       // detect maximum viewoffset and use it
-                       vector view_offset = autocvar_cl_eventchase_viewoffset;
-                       if(vehicle_chase)
-                       {
-                               if(vehicle_viewofs)
-                                       view_offset = vehicle_viewofs;
-                               else
-                                       view_offset = autocvar_cl_eventchase_vehicle_viewoffset;
-                       }
-                       if (custom_eventchase)
-                               view_offset = view_offset_override;
+               sharpen_intensity = bound(0, ((STAT(HEALTH) > 0) ? sharpen_intensity : 0), 5); // Check to see if player is alive (if not, set 0) - also bound to fade out starting at 5 seconds.
 
-                       if(view_offset)
+               if(autocvar_hud_powerup && sharpen_intensity > 0)
+               {
+                       if(sharpen_intensity != old_sharpen_intensity) // reduce cvar_set spam as much as possible
                        {
-                               WarpZone_TraceLine(current_view_origin, current_view_origin + view_offset + ('0 0 1' * autocvar_cl_eventchase_maxs.z), MOVE_WORLDONLY, this);
-                               if(trace_fraction == 1) { current_view_origin += view_offset; }
-                               else { current_view_origin.z += max(0, (trace_endpos.z - current_view_origin.z) - autocvar_cl_eventchase_maxs.z); }
+                               cvar_set("r_glsl_postprocess_uservec2", strcat(ftos((sharpen_intensity / 5) * autocvar_hud_powerup), " ", ftos(-sharpen_intensity * autocvar_hud_powerup), " 0 0"));
+                               old_sharpen_intensity = sharpen_intensity;
                        }
+               }
+               else if(cvar_string("r_glsl_postprocess_uservec2") != "0 0 0 0") // reduce cvar_set spam as much as possible
+               {
+                       cvar_set("r_glsl_postprocess_uservec2", "0 0 0 0");
+                       old_sharpen_intensity = 0;
+               }
 
-                       // We must enable chase_active to get a third person view (weapon viewmodel hidden and own player model showing).
-                       // Ideally, there should be another way to enable third person cameras, such as through setproperty()
-                       // -1 enables chase_active while marking it as set by this code, and not by the user (which would be 1)
-                       if(!autocvar_chase_active) { cvar_set("chase_active", "-1"); }
+               if(cvar("r_glsl_postprocess") == 0)
+                       cvar_set("r_glsl_postprocess", "2");
+       }
+       else if(cvar("r_glsl_postprocess") == 2)
+               cvar_set("r_glsl_postprocess", "0");
+}
 
-                       // make the camera smooth back
-                       float chase_distance = autocvar_cl_eventchase_distance;
-                       if(vehicle_chase)
-                       {
-                               if(vehicle_viewofs)
-                                       chase_distance = vehicle_viewdist;
-                               else
-                                       chase_distance = autocvar_cl_eventchase_vehicle_distance;
-                       }
-                       if (custom_eventchase)
-                               chase_distance = chase_distance_override;
+void View_Lock()
+{
+       if(autocvar_cl_lockview || (!autocvar_hud_cursormode && (autocvar__hud_configure && spectatee_status <= 0 || intermission > 1 || QuickMenu_IsOpened())))
+       {
+               setproperty(VF_ORIGIN, freeze_org);
+               setproperty(VF_ANGLES, freeze_ang);
+       }
+       else
+       {
+               freeze_org = getpropertyvec(VF_ORIGIN);
+               freeze_ang = getpropertyvec(VF_ANGLES);
+       }
+}
 
-                       if(autocvar_cl_eventchase_speed && eventchase_current_distance < chase_distance)
-                               eventchase_current_distance += autocvar_cl_eventchase_speed * (chase_distance - eventchase_current_distance) * frametime; // slow down the further we get
-                       else if(eventchase_current_distance != chase_distance)
-                               eventchase_current_distance = chase_distance;
+void View_DemoCamera()
+{
+       if(camera_active) // Camera for demo playback
+       {
+               if(autocvar_camera_enable)
+                       CSQC_Demo_Camera();
+               else
+               {
+                       cvar_set("chase_active", ftos(chase_active_backup));
+                       cvar_set("cl_demo_mousegrab", "0");
+                       camera_active = false;
+               }
+       }
+       else
+       {
+#ifdef CAMERATEST
+               if(autocvar_camera_enable)
+#else
+               if(autocvar_camera_enable && isdemo())
+#endif
+               {
+                       // Enable required Darkplaces cvars
+                       chase_active_backup = autocvar_chase_active;
+                       cvar_set("chase_active", "2");
+                       cvar_set("cl_demo_mousegrab", "1");
+                       camera_active = true;
+                       camera_mode = false;
+               }
+       }
+}
 
-                       vector forward, right, up;
-                       MAKE_VECTORS(view_angles, forward, right, up);
+#ifdef BLURTEST
+void View_BlurTest()
+{
+       if(time > blurtest_time0 && time < blurtest_time1)
+       {
+               float t = (time - blurtest_time0) / (blurtest_time1 - blurtest_time0);
+               float r = t * blurtest_radius;
+               float f = 1 / (t ** blurtest_power) - 1;
 
-                       vector eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
-                       WarpZone_TraceBox(current_view_origin, autocvar_cl_eventchase_mins, autocvar_cl_eventchase_maxs, eventchase_target_origin, MOVE_WORLDONLY, this);
+               cvar_set("r_glsl_postprocess", "1");
+               cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(r), " ", ftos(f), " 0 0"));
+       }
+       else
+       {
+               cvar_set("r_glsl_postprocess", "0");
+               cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0");
+       }
+}
+#endif
 
-                       // If the boxtrace fails, revert back to line tracing.
-                       if(!local_player.viewloc)
-                       if(trace_startsolid)
-                       {
-                               eventchase_target_origin = (current_view_origin - (forward * eventchase_current_distance));
-                               WarpZone_TraceLine(current_view_origin, eventchase_target_origin, MOVE_WORLDONLY, this);
-                               setproperty(VF_ORIGIN, (trace_endpos - (forward * autocvar_cl_eventchase_mins.z)));
-                       }
-                       else { setproperty(VF_ORIGIN, trace_endpos); }
+void View_CheckButtonStatus()
+{
+       float is_dead = (STAT(HEALTH) <= 0);
 
-                       if(!local_player.viewloc)
-                               setproperty(VF_ANGLES, WarpZone_TransformVAngles(WarpZone_trace_transform, view_angles));
-               }
+       // FIXME do we need this hack?
+       if(isdemo())
+       {
+               // in demos, input_buttons do not work
+               button_zoom = (autocvar__togglezoom == "-");
+       }
+       else if(button_zoom
+               && autocvar_cl_unpress_zoom_on_death
+               && (spectatee_status >= 0)
+               && (is_dead || intermission))
+       {
+               // no zoom while dead or in intermission please
+               localcmd("-zoom\n");
+               button_zoom = false;
+       }
 
-               if (eventchase <= 0 && autocvar_chase_active < 0) // time to disable chase_active if it was set by this code
+       if(autocvar_fov <= 59.5)
+       {
+               if(!zoomscript_caught)
                {
-                       eventchase_running = false;
-                       cvar_set("chase_active", "0");
-                       eventchase_current_distance = 0; // start from 0 next time
+                       localcmd("+button9\n");
+                       zoomscript_caught = 1;
                }
        }
-       // workaround for camera stuck between player's legs when using chase_active 1
-       // because the engine stops updating the chase_active camera when the game ends
-       else if(intermission)
+       else
        {
-               cvar_settemp("chase_active", "-1");
-               eventchase_current_distance = 0;
+               if(zoomscript_caught)
+               {
+                       localcmd("-button9\n");
+                       zoomscript_caught = 0;
+               }
        }
 
-       LABEL(skip_eventchase_death);
-
-       // do lockview after event chase camera so that it still applies whenever necessary.
-       if(autocvar_cl_lockview || (!autocvar_hud_cursormode && (autocvar__hud_configure && spectatee_status <= 0 || intermission > 1 || QuickMenu_IsOpened())))
+       if(active_minigame && HUD_MinigameMenu_IsOpened())
        {
-               setproperty(VF_ORIGIN, freeze_org);
-               setproperty(VF_ANGLES, freeze_ang);
+               if(!minigame_wasactive)
+               {
+                       localcmd("+button12\n");
+                       minigame_wasactive = true;
+               }
        }
-       else
+       else if(minigame_wasactive)
        {
-               freeze_org = getpropertyvec(VF_ORIGIN);
-               freeze_ang = getpropertyvec(VF_ANGLES);
+               localcmd("-button12\n");
+               minigame_wasactive = false;
        }
 
-       WarpZone_FixView();
-       //WarpZone_FixPMove();
+       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+       {
+               entity wepent = viewmodels[slot];
+
+               if(wepent.last_switchweapon != wepent.switchweapon)
+               {
+                       weapontime = time;
+                       wepent.last_switchweapon = wepent.switchweapon;
+                       if(slot == 0 && button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
+                       {
+                               localcmd("-zoom\n");
+                               button_zoom = false;
+                       }
+                       if(slot == 0 && autocvar_cl_unpress_attack_on_weapon_switch)
+                       {
+                               localcmd("-fire\n");
+                               localcmd("-fire2\n");
+                               button_attack2 = false;
+                       }
+               }
+               if(wepent.last_activeweapon != wepent.activeweapon)
+               {
+                       wepent.last_activeweapon = wepent.activeweapon;
+
+                       entity e = wepent.activeweapon;
+                       if(e.netname != "")
+                               localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
+                       else if(slot == 0)
+                               localcmd("\ncl_hook_activeweapon none\n");
+               }
+       }
+}
 
-       vector ov_org = '0 0 0';
-       vector ov_mid = '0 0 0';
-       vector ov_worldmin = '0 0 0';
-       vector ov_worldmax = '0 0 0';
+bool ov_enabled;
+float oldr_nearclip;
+float oldr_farclip_base;
+float oldr_farclip_world;
+float oldr_novis;
+float oldr_useportalculling;
+float oldr_useinfinitefarclip;
+vector ov_org = '0 0 0';
+vector ov_mid = '0 0 0';
+vector ov_worldmin = '0 0 0';
+vector ov_worldmax = '0 0 0';
+
+void View_Ortho()
+{
+       ov_org = '0 0 0';
+       ov_mid = '0 0 0';
+       ov_worldmin = '0 0 0';
+       ov_worldmax = '0 0 0';
        if(autocvar_cl_orthoview)
        {
                ov_worldmin = mi_picmin;
@@ -1888,6 +2277,84 @@ void CSQC_UpdateView(entity this, float w, float h)
                }
                ov_enabled = false;
        }
+}
+
+void View_UpdateFov()
+{
+       vector fov;
+       if(autocvar_cl_orthoview)
+               fov = GetOrthoviewFOV(ov_worldmin, ov_worldmax, ov_mid, ov_org);
+       else if(csqcplayer.viewloc)
+               fov = GetViewLocationFOV(110); // enforce 110 fov, so things don't look odd
+       else
+               fov = GetCurrentFov(autocvar_fov);
+
+       setproperty(VF_FOV, fov);
+}
+
+void CSQC_UpdateView(entity this, float w, float h)
+{
+       TC(int, w); TC(int, h);
+
+       execute_next_frame();
+
+       ++framecount;
+
+       stats_get();
+       hud = STAT(HUD);
+
+       ReplicateVars(false);
+       if (ReplicateVars_NOT_SENDING())
+               ReplicateVars_DELAY(0.8 + random() * 0.4); // no need to check cvars every frame
+
+       HUD_Scale_Disable();
+
+       if(autocvar__hud_showbinds_reload) // menu can set this one
+       {
+               db_close(binddb);
+               binddb = db_create();
+               cvar_set("_hud_showbinds_reload", "0");
+       }
+
+       if(checkextension("DP_CSQC_MINFPS_QUALITY"))
+               view_quality = getproperty(VF_MINFPS_QUALITY);
+       else
+               view_quality = 1;
+
+       button_attack2 = PHYS_INPUT_BUTTON_ATCK2(this);
+       button_zoom = PHYS_INPUT_BUTTON_ZOOM(this);
+
+       vector vf_size = getpropertyvec(VF_SIZE);
+       vector vf_min = getpropertyvec(VF_MIN);
+       vid_width = vf_size.x;
+       vid_height = vf_size.y;
+
+       ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
+
+       WaypointSprite_Load();
+
+       CSQCPlayer_SetCamera();
+
+       if(player_localentnum <= maxclients) // is it a client?
+               current_player = player_localentnum - 1;
+       else // then player_localentnum is the vehicle I'm driving
+               current_player = player_localnum;
+       myteam = entcs_GetTeam(current_player);
+
+       // abused multiple places below
+       entity local_player = ((csqcplayer) ? csqcplayer : CSQCModel_server2csqc(player_localentnum - 1));
+       if(!local_player)
+               local_player = this; // fall back!
+
+       View_EventChase(local_player);
+
+       // do lockview after event chase camera so that it still applies whenever necessary.
+       View_Lock();
+
+       WarpZone_FixView();
+       //WarpZone_FixPMove();
+
+       View_Ortho();
 
        // run viewmodel_draw before updating view_angles to the angles calculated by WarpZone_FixView
        // viewmodel_draw needs to use the view_angles set by the engine on every CSQC_UpdateView call
@@ -1899,23 +2366,8 @@ void CSQC_UpdateView(entity this, float w, float h)
        view_angles = getpropertyvec(VF_ANGLES);
        MAKE_VECTORS(view_angles, view_forward, view_right, view_up);
 
-#ifdef BLURTEST
-       if(time > blurtest_time0 && time < blurtest_time1)
-       {
-               float r, t;
-
-               t = (time - blurtest_time0) / (blurtest_time1 - blurtest_time0);
-               r = t * blurtest_radius;
-               f = 1 / (t ** blurtest_power) - 1;
-
-               cvar_set("r_glsl_postprocess", "1");
-               cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(r), " ", ftos(f), " 0 0"));
-       }
-       else
-       {
-               cvar_set("r_glsl_postprocess", "0");
-               cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0");
-       }
+#ifdef BLURTEST
+       View_BlurTest();
 #endif
 
        TargetMusic_Advance();
@@ -1948,72 +2400,10 @@ void CSQC_UpdateView(entity this, float w, float h)
 
        Announcer();
 
-       fov = autocvar_fov;
-       if(fov <= 59.5)
-       {
-               if(!zoomscript_caught)
-               {
-                       localcmd("+button9\n");
-                       zoomscript_caught = 1;
-               }
-       }
-       else
-       {
-               if(zoomscript_caught)
-               {
-                       localcmd("-button9\n");
-                       zoomscript_caught = 0;
-               }
-       }
-
-       if(active_minigame && HUD_MinigameMenu_IsOpened())
-       {
-               if(!minigame_wasactive)
-               {
-                       localcmd("+button12\n");
-                       minigame_wasactive = true;
-               }
-       }
-       else if(minigame_wasactive)
-       {
-               localcmd("-button12\n");
-               minigame_wasactive = false;
-       }
+       View_CheckButtonStatus();
 
        ColorTranslateMode = autocvar_cl_stripcolorcodes;
 
-       for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-       {
-               entity wepent = viewmodels[slot];
-
-               if(wepent.last_switchweapon != wepent.switchweapon)
-               {
-                       weapontime = time;
-                       wepent.last_switchweapon = wepent.switchweapon;
-                       if(slot == 0 && button_zoom && autocvar_cl_unpress_zoom_on_weapon_switch)
-                       {
-                               localcmd("-zoom\n");
-                               button_zoom = false;
-                       }
-                       if(slot == 0 && autocvar_cl_unpress_attack_on_weapon_switch)
-                       {
-                               localcmd("-fire\n");
-                               localcmd("-fire2\n");
-                               button_attack2 = false;
-                       }
-               }
-               if(wepent.last_activeweapon != wepent.activeweapon)
-               {
-                       wepent.last_activeweapon = wepent.activeweapon;
-
-                       e = wepent.activeweapon;
-                       if(e.netname != "")
-                               localcmd(strcat("\ncl_hook_activeweapon ", e.netname), "\n");
-                       else if(slot == 0)
-                               localcmd("\ncl_hook_activeweapon none\n");
-               }
-       }
-
        // ALWAYS Clear Current Scene First
        clearscene();
 
@@ -2033,37 +2423,9 @@ void CSQC_UpdateView(entity this, float w, float h)
        vid_conheight = autocvar_vid_conheight;
        vid_pixelheight = autocvar_vid_pixelheight;
 
-       if(autocvar_cl_orthoview) { setproperty(VF_FOV, GetOrthoviewFOV(ov_worldmin, ov_worldmax, ov_mid, ov_org)); }
-       else if(csqcplayer.viewloc) { setproperty(VF_FOV, GetViewLocationFOV(110)); } // enforce 110 fov, so things dont look odd
-       else { setproperty(VF_FOV, GetCurrentFov(fov)); }
+       View_UpdateFov();
 
-       if(camera_active) // Camera for demo playback
-       {
-               if(autocvar_camera_enable)
-                       CSQC_Demo_Camera();
-               else
-               {
-                       cvar_set("chase_active", ftos(chase_active_backup));
-                       cvar_set("cl_demo_mousegrab", "0");
-                       camera_active = false;
-               }
-       }
-       else
-       {
-#ifdef CAMERATEST
-               if(autocvar_camera_enable)
-#else
-               if(autocvar_camera_enable && isdemo())
-#endif
-               {
-                       // Enable required Darkplaces cvars
-                       chase_active_backup = autocvar_chase_active;
-                       cvar_set("chase_active", "2");
-                       cvar_set("cl_demo_mousegrab", "1");
-                       camera_active = true;
-                       camera_mode = false;
-               }
-       }
+       View_DemoCamera();
 
        // Draw the Crosshair
        setproperty(VF_DRAWCROSSHAIR, 0); //Make sure engine crosshairs are always hidden
@@ -2083,342 +2445,13 @@ void CSQC_UpdateView(entity this, float w, float h)
        addentities(MASK_NORMAL | MASK_ENGINE | MASK_ENGINEVIEWMODELS); // TODO: .health is used in cl_deathfade (a feature we have turned off currently)
        renderscene();
 
-       // now switch to 2D drawing mode by calling a 2D drawing function
-       // then polygon drawing will draw as 2D stuff, and NOT get queued until the
-       // next R_RenderScene call
-       drawstring('0 0 0', "", '1 1 0', '1 1 1', 0, 0);
-
-       if(autocvar_r_fakelight >= 2 || autocvar_r_fullbright)
-       if (!(serverflags & SERVERFLAG_ALLOW_FULLBRIGHT))
-       {
-               // apply night vision effect
-               vector tc_00, tc_01, tc_10, tc_11;
-               vector rgb = '0 0 0';
-
-               if(!nightvision_noise)
-               {
-                       nightvision_noise = new(nightvision_noise);
-               }
-               if(!nightvision_noise2)
-               {
-                       nightvision_noise2 = new(nightvision_noise2);
-               }
-
-               // color tint in yellow
-               drawfill('0 0 0', autocvar_vid_conwidth * '1 0 0' + autocvar_vid_conheight * '0 1 0', '0.5 1 0.3', 1, DRAWFLAG_MODULATE);
-
-               // draw BG
-               a = Noise_Pink(nightvision_noise, frametime * 1.5) * 0.05 + 0.15;
-               rgb = '1 1 1';
-               tc_00 = '0 0 0' + '0.2 0 0' * sin(time * 0.3) + '0 0.3 0' * cos(time * 0.7);
-               tc_01 = '0 2.25 0' + '0.6 0 0' * cos(time * 1.2) - '0 0.3 0' * sin(time * 2.2);
-               tc_10 = '1.5 0 0' - '0.2 0 0' * sin(time * 0.5) + '0 0.5 0' * cos(time * 1.7);
-               //tc_11 = '1 1 0' + '0.6 0 0' * sin(time * 0.6) + '0 0.3 0' * cos(time * 0.1);
-               tc_11 = tc_01 + tc_10 - tc_00;
-               R_BeginPolygon("gfx/nightvision-bg.tga", DRAWFLAG_ADDITIVE);
-               R_PolygonVertex('0 0 0', tc_00, rgb, a);
-               R_PolygonVertex(autocvar_vid_conwidth * '1 0 0', tc_10, rgb, a);
-               R_PolygonVertex(autocvar_vid_conwidth * '1 0 0' + autocvar_vid_conheight * '0 1 0', tc_11, rgb, a);
-               R_PolygonVertex(autocvar_vid_conheight * '0 1 0', tc_01, rgb, a);
-               R_EndPolygon();
-
-               // draw FG
-               a = Noise_Pink(nightvision_noise2, frametime * 0.1) * 0.05 + 0.12;
-               rgb = '0.3 0.6 0.4' + '0.1 0.4 0.2' * Noise_White(nightvision_noise2, frametime);
-               tc_00 = '0 0 0' + '1 0 0' * Noise_White(nightvision_noise2, frametime) + '0 1 0' * Noise_White(nightvision_noise2, frametime);
-               tc_01 = tc_00 + '0 3 0' * (1 + Noise_White(nightvision_noise2, frametime) * 0.2);
-               tc_10 = tc_00 + '2 0 0' * (1 + Noise_White(nightvision_noise2, frametime) * 0.3);
-               tc_11 = tc_01 + tc_10 - tc_00;
-               R_BeginPolygon("gfx/nightvision-fg.tga", DRAWFLAG_ADDITIVE);
-               R_PolygonVertex('0 0 0', tc_00, rgb, a);
-               R_PolygonVertex(autocvar_vid_conwidth * '1 0 0', tc_10, rgb, a);
-               R_PolygonVertex(autocvar_vid_conwidth * '1 0 0' + autocvar_vid_conheight * '0 1 0', tc_11, rgb, a);
-               R_PolygonVertex(autocvar_vid_conheight * '0 1 0', tc_01, rgb, a);
-               R_EndPolygon();
-       }
-
-       if(autocvar_cl_reticle && !MUTATOR_CALLHOOK(DrawReticle))
-       {
-               string reticle_image = string_null;
-               bool wep_zoomed = false;
-               for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
-               {
-                       entity wepe = viewmodels[slot];
-                       Weapon wep = wepe.activeweapon;
-                       if(wep != WEP_Null && wep.wr_zoom)
-                       {
-                               bool do_zoom = wep.wr_zoom(wep, NULL);
-                               if(!reticle_image && wep.w_reticle && wep.w_reticle != "")
-                                       reticle_image = wep.w_reticle;
-                               wep_zoomed += do_zoom;
-                       }
-               }
-               // Draw the aiming reticle for weapons that use it
-               // reticle_type is changed to the item we are zooming / aiming with, to decide which reticle to use
-               // It must be a persisted float for fading out to work properly (you let go of the zoom button for
-               // the view to go back to normal, so reticle_type would become 0 as we fade out)
-               if(spectatee_status || is_dead || hud != HUD_NORMAL || local_player.viewloc)
-               {
-                       // no zoom reticle while dead
-                       reticle_type = 0;
-               }
-               else if(wep_zoomed && autocvar_cl_reticle_weapon)
-               {
-                       if(reticle_image) { reticle_type = 2; }
-                       else { reticle_type = 0; }
-               }
-               else if(button_zoom || zoomscript_caught)
-               {
-                       // normal zoom
-                       reticle_type = 1;
-               }
-
-               if(reticle_type)
-               {
-                       if(autocvar_cl_reticle_stretch)
-                       {
-                               reticle_size.x = vid_conwidth;
-                               reticle_size.y = vid_conheight;
-                               reticle_pos.x = 0;
-                               reticle_pos.y = 0;
-                       }
-                       else
-                       {
-                               reticle_size.x = max(vid_conwidth, vid_conheight);
-                               reticle_size.y = max(vid_conwidth, vid_conheight);
-                               reticle_pos.x = (vid_conwidth - reticle_size.x) / 2;
-                               reticle_pos.y = (vid_conheight - reticle_size.y) / 2;
-                       }
-
-                       if(zoomscript_caught)
-                               f = 1;
-                       else
-                               f = current_zoomfraction;
-
-                       if(f)
-                       {
-                               switch(reticle_type)
-                               {
-                                       case 1: drawpic(reticle_pos, "gfx/reticle_normal", reticle_size, '1 1 1', f * autocvar_cl_reticle_normal_alpha, DRAWFLAG_NORMAL); break;
-                                       case 2: if(reticle_image) drawpic(reticle_pos, reticle_image, reticle_size, '1 1 1', f * autocvar_cl_reticle_weapon_alpha, DRAWFLAG_NORMAL); break;
-                               }
-                       }
-               }
-       }
-       else
-       {
-               if(reticle_type != 0) { reticle_type = 0; }
-       }
-
-
-       // improved polyblend
-       if(autocvar_hud_contents && !MUTATOR_CALLHOOK(HUD_Contents))
-       {
-               float contentalpha_temp, incontent, liquidalpha, contentfadetime;
-               vector liquidcolor;
-
-               switch(pointcontents(view_origin))
-               {
-                       case CONTENT_WATER:
-                               liquidalpha = autocvar_hud_contents_water_alpha;
-                               liquidcolor = stov(autocvar_hud_contents_water_color);
-                               incontent = 1;
-                               break;
-
-                       case CONTENT_LAVA:
-                               liquidalpha = autocvar_hud_contents_lava_alpha;
-                               liquidcolor = stov(autocvar_hud_contents_lava_color);
-                               incontent = 1;
-                               break;
-
-                       case CONTENT_SLIME:
-                               liquidalpha = autocvar_hud_contents_slime_alpha;
-                               liquidcolor = stov(autocvar_hud_contents_slime_color);
-                               incontent = 1;
-                               break;
-
-                       default:
-                               liquidalpha = 0;
-                               liquidcolor = '0 0 0';
-                               incontent = 0;
-                               break;
-               }
-
-               if(incontent) // fade in/out at different speeds so you can do e.g. instant fade when entering water and slow when leaving it.
-               { // also lets delcare previous values for blending properties, this way it isn't reset until after you have entered a different content
-                       contentfadetime = autocvar_hud_contents_fadeintime;
-                       liquidalpha_prev = liquidalpha;
-                       liquidcolor_prev = liquidcolor;
-               }
-               else
-                       contentfadetime = autocvar_hud_contents_fadeouttime;
-
-               contentalpha_temp = bound(0, drawframetime / max(0.0001, contentfadetime), 1);
-               contentavgalpha = contentavgalpha * (1 - contentalpha_temp) + incontent * contentalpha_temp;
-
-               if(contentavgalpha)
-                       drawfill('0 0 0', vec2(vid_conwidth, vid_conheight), liquidcolor_prev, contentavgalpha * liquidalpha_prev, DRAWFLAG_NORMAL);
-
-               if(autocvar_hud_postprocessing)
-               {
-                       if(autocvar_hud_contents_blur && contentavgalpha)
-                       {
-                               content_blurpostprocess.x = 1;
-                               content_blurpostprocess.y = contentavgalpha * autocvar_hud_contents_blur;
-                               content_blurpostprocess.z = contentavgalpha * autocvar_hud_contents_blur_alpha;
-                       }
-                       else
-                       {
-                               content_blurpostprocess.x = 0;
-                               content_blurpostprocess.y = 0;
-                               content_blurpostprocess.z = 0;
-                       }
-               }
-       }
-
-       if(autocvar_hud_damage && !STAT(FROZEN))
-       {
-               splash_size.x = max(vid_conwidth, vid_conheight);
-               splash_size.y = max(vid_conwidth, vid_conheight);
-               splash_pos.x = (vid_conwidth - splash_size.x) / 2;
-               splash_pos.y = (vid_conheight - splash_size.y) / 2;
-
-               float myhealth_flash_temp;
-               myhealth = STAT(HEALTH);
-
-               // fade out
-               myhealth_flash = max(0, myhealth_flash - autocvar_hud_damage_fade_rate * frametime);
-               // add new damage
-               myhealth_flash = bound(0, myhealth_flash + dmg_take * autocvar_hud_damage_factor, autocvar_hud_damage_maxalpha);
-
-               float pain_threshold, pain_threshold_lower, pain_threshold_lower_health;
-               pain_threshold = autocvar_hud_damage_pain_threshold;
-               pain_threshold_lower = autocvar_hud_damage_pain_threshold_lower;
-               pain_threshold_lower_health = autocvar_hud_damage_pain_threshold_lower_health;
-
-               if(pain_threshold_lower && myhealth < pain_threshold_lower_health)
-               {
-                       pain_threshold = pain_threshold - max(autocvar_hud_damage_pain_threshold_pulsating_min, fabs(sin(M_PI * time / autocvar_hud_damage_pain_threshold_pulsating_period))) * pain_threshold_lower * (1 - max(0, myhealth)/pain_threshold_lower_health);
-               }
-
-               myhealth_flash_temp = bound(0, myhealth_flash - pain_threshold, 1);
-
-               if(myhealth_prev < 1)
-               {
-                       if(myhealth >= 1)
-                       {
-                               myhealth_flash = 0; // just spawned, clear the flash immediately
-                               myhealth_flash_temp = 0;
-                       }
-                       else
-                       {
-                               myhealth_flash += autocvar_hud_damage_fade_rate * frametime; // dead
-                       }
-               }
-
-               if(spectatee_status == -1 || intermission)
-               {
-                       myhealth_flash = 0; // observing, or match ended
-                       myhealth_flash_temp = 0;
-               }
-
-               myhealth_prev = myhealth;
-
-               // IDEA: change damage color/picture based on player model for robot/alien species?
-               // pro: matches model better
-               // contra: it's not red because blood is red, but because red is an alarming color, so red should stay
-               // maybe different reddish pics?
-               if(autocvar_cl_gentle_damage || autocvar_cl_gentle)
-               {
-                       if(autocvar_cl_gentle_damage == 2)
-                       {
-                               if(myhealth_flash < pain_threshold) // only randomize when the flash is gone
-                                       myhealth_gentlergb = randomvec();
-                       }
-                       else
-                               myhealth_gentlergb = stov(autocvar_hud_damage_gentle_color);
-
-                       if(myhealth_flash_temp > 0)
-                               drawfill('0 0 0', vec2(vid_conwidth, vid_conheight), myhealth_gentlergb, autocvar_hud_damage_gentle_alpha_multiplier * bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
-               }
-               else if(myhealth_flash_temp > 0)
-                       drawpic(splash_pos, "gfx/blood", splash_size, stov(autocvar_hud_damage_color), bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage, DRAWFLAG_NORMAL);
-
-               if(autocvar_hud_postprocessing) // we still need to set this anyway even when chase_active is set, this way it doesn't get stuck on.
-               {
-                       if(autocvar_hud_damage_blur && myhealth_flash_temp)
-                       {
-                               damage_blurpostprocess.x = 1;
-                               damage_blurpostprocess.y = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur;
-                               damage_blurpostprocess.z = bound(0, myhealth_flash_temp, 1) * autocvar_hud_damage_blur_alpha;
-                       }
-                       else
-                       {
-                               damage_blurpostprocess.x = 0;
-                               damage_blurpostprocess.y = 0;
-                               damage_blurpostprocess.z = 0;
-                       }
-               }
-       }
-
-       float e1 = (autocvar_hud_postprocessing_maxbluralpha != 0);
-       float e2 = (autocvar_hud_powerup != 0);
-       if(autocvar_hud_postprocessing && (e1 || e2)) // TODO: Remove this code and re-do the postprocess handling in the engine, where it properly belongs.
-       {
-               // enable or disable rendering types if they are used or not
-               if(cvar("r_glsl_postprocess_uservec1_enable") != e1) { cvar_set("r_glsl_postprocess_uservec1_enable", ftos(e1)); }
-               if(cvar("r_glsl_postprocess_uservec2_enable") != e2) { cvar_set("r_glsl_postprocess_uservec2_enable", ftos(e2)); }
-
-               // blur postprocess handling done first (used by hud_damage and hud_contents)
-               if((damage_blurpostprocess.x || content_blurpostprocess.x))
-               {
-                       float blurradius = bound(0, damage_blurpostprocess.y + content_blurpostprocess.y, autocvar_hud_postprocessing_maxblurradius);
-                       float bluralpha = bound(0, damage_blurpostprocess.z + content_blurpostprocess.z, autocvar_hud_postprocessing_maxbluralpha);
-                       if(blurradius != old_blurradius || bluralpha != old_bluralpha) // reduce cvar_set spam as much as possible
-                       {
-                               cvar_set("r_glsl_postprocess_uservec1", strcat(ftos(blurradius), " ", ftos(bluralpha), " 0 0"));
-                               old_blurradius = blurradius;
-                               old_bluralpha = bluralpha;
-                       }
-               }
-               else if(cvar_string("r_glsl_postprocess_uservec1") != "0 0 0 0") // reduce cvar_set spam as much as possible
-               {
-                       cvar_set("r_glsl_postprocess_uservec1", "0 0 0 0");
-                       old_blurradius = 0;
-                       old_bluralpha = 0;
-               }
-
-               // edge detection postprocess handling done second (used by hud_powerup)
-               float sharpen_intensity = 0, strength_finished = STAT(STRENGTH_FINISHED), invincible_finished = STAT(INVINCIBLE_FINISHED);
-               if (strength_finished - time > 0) { sharpen_intensity += (strength_finished - time); }
-               if (invincible_finished - time > 0) { sharpen_intensity += (invincible_finished - time); }
-
-               sharpen_intensity = bound(0, ((STAT(HEALTH) > 0) ? sharpen_intensity : 0), 5); // Check to see if player is alive (if not, set 0) - also bound to fade out starting at 5 seconds.
-
-               if(autocvar_hud_powerup && sharpen_intensity > 0)
-               {
-                       if(sharpen_intensity != old_sharpen_intensity) // reduce cvar_set spam as much as possible
-                       {
-                               cvar_set("r_glsl_postprocess_uservec2", strcat(ftos((sharpen_intensity / 5) * autocvar_hud_powerup), " ", ftos(-sharpen_intensity * autocvar_hud_powerup), " 0 0"));
-                               old_sharpen_intensity = sharpen_intensity;
-                       }
-               }
-               else if(cvar_string("r_glsl_postprocess_uservec2") != "0 0 0 0") // reduce cvar_set spam as much as possible
-               {
-                       cvar_set("r_glsl_postprocess_uservec2", "0 0 0 0");
-                       old_sharpen_intensity = 0;
-               }
-
-               if(cvar("r_glsl_postprocess") == 0)
-                       cvar_set("r_glsl_postprocess", "2");
-       }
-       else if(cvar("r_glsl_postprocess") == 2)
-               cvar_set("r_glsl_postprocess", "0");
+       // Now the the scene has been rendered, begin with the 2D drawing functions
 
-       /*if(ISGAMETYPE(CTF))
-         {
-         ctf_view();
-         } else */
+       View_NightVision();
+       DrawReticle(local_player);
+       HUD_Contents();
+       HUD_Damage();
+       View_PostProcessing();
 
        // draw 2D entities
        IL_EACH(g_drawables_2d, it.draw2d, it.draw2d(it));
index f3c1f41..448361d 100644 (file)
@@ -20,3 +20,5 @@ const int CURSOR_NORMAL = 0;
 const int CURSOR_MOVE = 1;
 const int CURSOR_RESIZE = 2;
 const int CURSOR_RESIZE2 = 3;
+
+float drawtime;
index 25c008d..088aefe 100644 (file)
@@ -11,8 +11,8 @@ string campaign_gametype[CAMPAIGN_MAX_ENTRIES];
 string campaign_mapname[CAMPAIGN_MAX_ENTRIES];
 float campaign_bots[CAMPAIGN_MAX_ENTRIES];
 float campaign_botskill[CAMPAIGN_MAX_ENTRIES];
-float campaign_fraglimit[CAMPAIGN_MAX_ENTRIES];
-float campaign_timelimit[CAMPAIGN_MAX_ENTRIES];
+string campaign_fraglimit[CAMPAIGN_MAX_ENTRIES];
+string campaign_timelimit[CAMPAIGN_MAX_ENTRIES];
 string campaign_mutators[CAMPAIGN_MAX_ENTRIES];
 string campaign_shortdesc[CAMPAIGN_MAX_ENTRIES];
 string campaign_longdesc[CAMPAIGN_MAX_ENTRIES];
index 4f099b5..8bac6f3 100644 (file)
@@ -58,8 +58,8 @@ float CampaignFile_Load(int offset, float n)
                                CAMPAIGN_GETARG; campaign_mapname[campaign_entries] = strzone(a);
                                CAMPAIGN_GETARG; campaign_bots[campaign_entries] = stof(a);
                                CAMPAIGN_GETARG; campaign_botskill[campaign_entries] = stof(a);
-                               CAMPAIGN_GETARG; campaign_fraglimit[campaign_entries] = stof(a);
-                               CAMPAIGN_GETARG; campaign_timelimit[campaign_entries] = stof(a);
+                               CAMPAIGN_GETARG; campaign_fraglimit[campaign_entries] = strzone(a);
+                               CAMPAIGN_GETARG; campaign_timelimit[campaign_entries] = strzone(a);
                                CAMPAIGN_GETARG; campaign_mutators[campaign_entries] = strzone(a);
                                CAMPAIGN_GETARG; campaign_shortdesc[campaign_entries] = strzone(a);
                                CAMPAIGN_GETARG; campaign_longdesc[campaign_entries] = strzone(strreplace("\\n", "\n", a));
@@ -91,6 +91,8 @@ void CampaignFile_Unload()
                {
                        strfree(campaign_gametype[i]);
                        strfree(campaign_mapname[i]);
+                       strfree(campaign_fraglimit[i]);
+                       strfree(campaign_timelimit[i]);
                        strfree(campaign_mutators[i]);
                        strfree(campaign_shortdesc[i]);
                        strfree(campaign_longdesc[i]);
index dcd8d95..2c34fea 100644 (file)
@@ -169,7 +169,7 @@ void GenericCommand_qc_curl(int request, int argc)
        }
 }
 
-GENERIC_COMMAND(dumpcommands, "Dump all commands on the program to <program>_cmd_dump.txt")
+GENERIC_COMMAND(dumpcommands, "Dump all commands on the program to <program>_cmd_dump.txt", false)
 {
        switch(request)
        {
@@ -532,16 +532,16 @@ void GenericCommand_(int request)
 */
 
 // Do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
-GENERIC_COMMAND(addtolist, "Add a string to a cvar") { GenericCommand_addtolist(request, arguments); }
-GENERIC_COMMAND(maplist, "Automatic control of maplist") { GenericCommand_maplist(request, arguments); }
-GENERIC_COMMAND(nextframe, "Execute the given command next frame of this VM") { GenericCommand_nextframe(request, command); }
-GENERIC_COMMAND(qc_curl, "Queries a URL") { GenericCommand_qc_curl(request, arguments); }
-GENERIC_COMMAND(removefromlist, "Remove a string from a cvar") { GenericCommand_removefromlist(request, arguments); }
-GENERIC_COMMAND(restartnotifs, "Re-initialize all notifications") { GenericCommand_restartnotifs(request); }
-GENERIC_COMMAND(rpn, "RPN calculator") { GenericCommand_rpn(request, arguments, command); }
-GENERIC_COMMAND(settemp, "Temporarily set a value to a cvar which is restored later") { GenericCommand_settemp(request, arguments); }
-GENERIC_COMMAND(settemp_restore, "Restore all cvars set by settemp command") { GenericCommand_settemp_restore(request); }
-GENERIC_COMMAND(runtest, "Run unit tests") { GenericCommand_runtest(request, arguments); }
+GENERIC_COMMAND(addtolist, "Add a string to a cvar", true) { GenericCommand_addtolist(request, arguments); }
+GENERIC_COMMAND(maplist, "Automatic control of maplist", true) { GenericCommand_maplist(request, arguments); }
+GENERIC_COMMAND(nextframe, "Execute the given command next frame of this VM", true) { GenericCommand_nextframe(request, command); }
+GENERIC_COMMAND(qc_curl, "Queries a URL", true) { GenericCommand_qc_curl(request, arguments); }
+GENERIC_COMMAND(removefromlist, "Remove a string from a cvar", true) { GenericCommand_removefromlist(request, arguments); }
+GENERIC_COMMAND(restartnotifs, "Re-initialize all notifications", false) { GenericCommand_restartnotifs(request); }
+GENERIC_COMMAND(rpn, "RPN calculator", true) { GenericCommand_rpn(request, arguments, command); }
+GENERIC_COMMAND(settemp, "Temporarily set a value to a cvar which is restored later", false) { GenericCommand_settemp(request, arguments); }
+GENERIC_COMMAND(settemp_restore, "Restore all cvars set by settemp command", false) { GenericCommand_settemp_restore(request); }
+GENERIC_COMMAND(runtest, "Run unit tests", false) { GenericCommand_runtest(request, arguments); }
 
 void GenericCommand_macro_help()
 {
index 9868e24..a6f669f 100644 (file)
@@ -6,14 +6,17 @@ REGISTRY(GENERIC_COMMANDS, BITS(7))
 REGISTER_REGISTRY(GENERIC_COMMANDS)
 REGISTRY_SORT(GENERIC_COMMANDS)
 
-#define GENERIC_COMMAND(id, description) \
+.bool m_menubased; // switch to tell whether this alias should be registered as a menu or client based command
+
+#define GENERIC_COMMAND(id, description, menubased) \
        CLASS(genericcommand_##id, Command) \
                ATTRIB(genericcommand_##id, m_name, string, #id); \
        ATTRIB(genericcommand_##id, m_description, string, description); \
+       ATTRIB(genericcommand_##id, m_menubased, bool, menubased); \
        ENDCLASS(genericcommand_##id) \
     REGISTER(GENERIC_COMMANDS, CMD_G, id, m_id, NEW(genericcommand_##id)); \
        METHOD(genericcommand_##id, m_invokecmd, void(genericcommand_##id this, int request, entity caller, int arguments, string command))
 
 STATIC_INIT(GENERIC_COMMANDS_aliases) {
-       FOREACH(GENERIC_COMMANDS, true, localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, "qc_cmd_svmenu")));
+       FOREACH(GENERIC_COMMANDS, true, localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, ((it.m_menubased) ? "qc_cmd_svmenu" : "qc_cmd_svcl"))));
 }
index 0998fad..4165d3d 100644 (file)
@@ -53,6 +53,12 @@ float rpn_popf() { return stof(rpn_pop()); }
 void rpn_pushf(float f) { return rpn_push(sprintf("%.9g", f)); }
 void rpn_setf(float f) { return rpn_set(sprintf("%.9g", f)); }
 
+SHUTDOWN(_rpndb)
+{
+       if(rpn_db)
+               db_close(rpn_db);
+}
+
 void GenericCommand_rpn(int request, int argc, string command)
 {
        switch(request)
index 05064ca..c95bb2d 100644 (file)
@@ -197,7 +197,7 @@ bool autocvar_debugdraw;
 #endif
 
 
-GENERIC_COMMAND(bufstr_get, "Examine a string buffer object")
+GENERIC_COMMAND(bufstr_get, "Examine a string buffer object", false)
 {
        switch (request)
        {
@@ -219,7 +219,7 @@ GENERIC_COMMAND(bufstr_get, "Examine a string buffer object")
 }
 
 
-GENERIC_COMMAND(version, "Print the current version")
+GENERIC_COMMAND(version, "Print the current version", false)
 {
        switch (request)
        {
@@ -241,7 +241,7 @@ GENERIC_COMMAND(version, "Print the current version")
 #ifdef CSQC
 void(float bufhandle, string pattern, string antipattern) buf_cvarlist = #517;
 #endif
-GENERIC_COMMAND(cvar_localchanges, "Print locally changed cvars")
+GENERIC_COMMAND(cvar_localchanges, "Print locally changed cvars", false)
 {
        switch (request)
        {
@@ -332,7 +332,7 @@ STATIC_INIT(TRACE_ENT)
 #endif
 
 
-GENERIC_COMMAND(find, "Search through entities for matching classname")
+GENERIC_COMMAND(find, "Search through entities for matching classname", false)
 {
        switch (request)
        {
@@ -363,7 +363,7 @@ GENERIC_COMMAND(find, "Search through entities for matching classname")
 }
 
 
-GENERIC_COMMAND(findat, "Search through entities for matching origin")
+GENERIC_COMMAND(findat, "Search through entities for matching origin", false)
 {
        switch (request)
        {
index 68c245d..79d31eb 100644 (file)
@@ -285,7 +285,7 @@ void effectinfo_dump(int fh, bool alsoprint)
     #undef WRITE
 }
 
-GENERIC_COMMAND(dumpeffectinfo, "Dump all effectinfo to effectinfo_dump.txt")
+GENERIC_COMMAND(dumpeffectinfo, "Dump all effectinfo to effectinfo_dump.txt", false)
 {
     switch (request) {
         case CMD_REQUEST_COMMAND: {
index 589e343..359d3d8 100644 (file)
@@ -19,22 +19,25 @@ REPLICATE(cvar_cl_casings, bool, "cl_casings");
 #ifdef SVQC
 void SpawnCasing(vector vel, float randomvel, vector ang, vector avel, float randomavel, int casingtype, entity casingowner, .entity weaponentity)
 {
-       if (!(CS(casingowner).cvar_cl_casings))
-               return;
-
-    entity wep = casingowner.(weaponentity);
-    vector org = casingowner.origin + casingowner.view_ofs + wep.spawnorigin.x * v_forward - wep.spawnorigin.y * v_right + wep.spawnorigin.z * v_up;
-
-    if (!sound_allowed(MSG_BROADCAST, casingowner))
-        casingtype |= 0x80;
-
-    WriteHeader(MSG_ALL, casings);
-    WriteByte(MSG_ALL, casingtype);
-    WriteVector(MSG_ALL, org);
-    WriteShort(MSG_ALL, compressShortVector(vel)); // actually compressed velocity
-    WriteByte(MSG_ALL, ang.x * 256 / 360);
-    WriteByte(MSG_ALL, ang.y * 256 / 360);
-    WriteByte(MSG_ALL, ang.z * 256 / 360);
+       entity wep = casingowner.(weaponentity);
+       vector org = casingowner.origin + casingowner.view_ofs + wep.spawnorigin.x * v_forward - wep.spawnorigin.y * v_right + wep.spawnorigin.z * v_up;
+
+       FOREACH_CLIENT(true, {
+               if (!(CS(it).cvar_cl_casings))
+                       continue;
+
+               msg_entity = it;
+               if (!sound_allowed(MSG_ONE, it))
+                       casingtype |= 0x80; // silent
+
+               WriteHeader(MSG_ONE, casings);
+               WriteByte(MSG_ONE, casingtype);
+               WriteVector(MSG_ONE, org);
+               WriteShort(MSG_ONE, compressShortVector(vel)); // actually compressed velocity
+               WriteByte(MSG_ONE, ang.x * 256 / 360);
+               WriteByte(MSG_ONE, ang.y * 256 / 360);
+               WriteByte(MSG_ONE, ang.z * 256 / 360);
+       });
 }
 #endif
 
@@ -153,6 +156,7 @@ NET_HANDLE(casings, bool isNew)
     casing.velocity = casing.velocity + 2 * prandomvec();
     casing.avelocity = '0 250 0' + 100 * prandomvec();
     set_movetype(casing, MOVETYPE_BOUNCE);
+    casing.bouncefactor = 0.25;
     settouch(casing, Casing_Touch);
     casing.move_time = time;
     casing.event_damage = Casing_Damage;
index 4653f4a..9fc46ff 100644 (file)
                                if (GetPlayerSoundSampleField_notFound) field = GetVoiceMessageSampleField(key);
                                if (GetPlayerSoundSampleField_notFound)
                                {
-                                       LOG_TRACEF("Invalid sound info field: %s", key);
+                                       LOG_TRACEF("Invalid sound info field in player sound file '%s': %s", f, key);
                                        continue;
                                }
                                string file = argv(1);
index 8b1570f..b5631ed 100644 (file)
@@ -40,11 +40,11 @@ REGISTER_PLAYERSOUND(pain75)
 
 .bool instanceOfVoiceMessage;
 .int m_playersoundvt;
-#define REGISTER_VOICEMSG(id, vt) \
+#define REGISTER_VOICEMSG(id, vt, listed) \
        .string _playersound_##id; \
        REGISTER(PlayerSounds, playersound, id, m_id, new_pure(VoiceMessage)) \
        { \
-               this.instanceOfVoiceMessage = true; \
+               this.instanceOfVoiceMessage = listed; \
                this.m_playersoundstr = #id; \
                this.m_playersoundfld = _playersound_##id; \
                this.m_playersoundvt = vt; \
@@ -57,30 +57,30 @@ const int VOICETYPE_LASTATTACKER_ONLY = 13;
 const int VOICETYPE_AUTOTAUNT = 14;
 const int VOICETYPE_TAUNT = 15;
 
-REGISTER_VOICEMSG(attack, VOICETYPE_TEAMRADIO)
-REGISTER_VOICEMSG(attackinfive, VOICETYPE_TEAMRADIO)
-REGISTER_VOICEMSG(coverme, VOICETYPE_TEAMRADIO)
-REGISTER_VOICEMSG(defend, VOICETYPE_TEAMRADIO)
-REGISTER_VOICEMSG(freelance, VOICETYPE_TEAMRADIO)
-REGISTER_VOICEMSG(incoming, VOICETYPE_TEAMRADIO)
-REGISTER_VOICEMSG(meet, VOICETYPE_TEAMRADIO)
-REGISTER_VOICEMSG(needhelp, VOICETYPE_TEAMRADIO)
-REGISTER_VOICEMSG(seenflag, VOICETYPE_TEAMRADIO)
-REGISTER_VOICEMSG(taunt, VOICETYPE_TAUNT)
-REGISTER_VOICEMSG(teamshoot, VOICETYPE_LASTATTACKER)
-
-// reserved sound names for the future (some models lack sounds for them):
-// _VOICEMSG(flagcarriertakingdamage)
-// _VOICEMSG(getflag)
-// reserved sound names for the future (ALL models lack sounds for them):
-// _VOICEMSG(affirmative)
-// _VOICEMSG(attacking)
-// _VOICEMSG(defending)
-// _VOICEMSG(roaming)
-// _VOICEMSG(onmyway)
-// _VOICEMSG(droppedflag)
-// _VOICEMSG(negative)
-// _VOICEMSG(seenenemy)
+REGISTER_VOICEMSG(attack, VOICETYPE_TEAMRADIO, true)
+REGISTER_VOICEMSG(attackinfive, VOICETYPE_TEAMRADIO, true)
+REGISTER_VOICEMSG(coverme, VOICETYPE_TEAMRADIO, true)
+REGISTER_VOICEMSG(defend, VOICETYPE_TEAMRADIO, true)
+REGISTER_VOICEMSG(freelance, VOICETYPE_TEAMRADIO, true)
+REGISTER_VOICEMSG(incoming, VOICETYPE_TEAMRADIO, true)
+REGISTER_VOICEMSG(meet, VOICETYPE_TEAMRADIO, true)
+REGISTER_VOICEMSG(needhelp, VOICETYPE_TEAMRADIO, true)
+REGISTER_VOICEMSG(seenflag, VOICETYPE_TEAMRADIO, true)
+REGISTER_VOICEMSG(taunt, VOICETYPE_TAUNT, true)
+REGISTER_VOICEMSG(teamshoot, VOICETYPE_LASTATTACKER, true)
+
+//NOTE: some models lack sounds for these:
+REGISTER_VOICEMSG(flagcarriertakingdamage, VOICETYPE_TEAMRADIO, false)
+REGISTER_VOICEMSG(getflag, VOICETYPE_TEAMRADIO, false)
+//NOTE: ALL models lack sounds for these (only available in default sounds currently):
+REGISTER_VOICEMSG(affirmative, VOICETYPE_TEAMRADIO, false)
+REGISTER_VOICEMSG(attacking, VOICETYPE_TEAMRADIO, false)
+REGISTER_VOICEMSG(defending, VOICETYPE_TEAMRADIO, false)
+REGISTER_VOICEMSG(roaming, VOICETYPE_TEAMRADIO, false)
+REGISTER_VOICEMSG(onmyway, VOICETYPE_TEAMRADIO, false)
+REGISTER_VOICEMSG(droppedflag, VOICETYPE_TEAMRADIO, false)
+REGISTER_VOICEMSG(negative, VOICETYPE_TEAMRADIO, false)
+REGISTER_VOICEMSG(seenenemy, VOICETYPE_TEAMRADIO, false)
 
 .string m_globalsoundstr;
 REGISTRY(GlobalSounds, BITS(8) - 1)
index 8ce4d6f..11bbaea 100644 (file)
@@ -48,6 +48,8 @@ bool autocvar_g_ctf_flag_return_when_unreachable;
 float autocvar_g_ctf_flag_return_damage;
 float autocvar_g_ctf_flag_return_damage_delay;
 float autocvar_g_ctf_flag_return_dropped;
+bool autocvar_g_ctf_flag_waypoint = true;
+float autocvar_g_ctf_flag_waypoint_maxdistance;
 float autocvar_g_ctf_flagcarrier_auto_helpme_damage;
 float autocvar_g_ctf_flagcarrier_auto_helpme_time;
 float autocvar_g_ctf_flagcarrier_selfdamagefactor;
@@ -1224,10 +1226,14 @@ void ctf_DelayedFlagSetup(entity this) // called after a flag is placed on a map
                default: basename = WP_FlagBaseNeutral; break;
        }
 
-       entity wp = WaypointSprite_SpawnFixed(basename, this.origin + FLAG_WAYPOINT_OFFSET, this, wps_flagbase, RADARICON_FLAG);
-       wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 1 1');
-       WaypointSprite_UpdateTeamRadar(this.wps_flagbase, RADARICON_FLAG, ((this.team) ? colormapPaletteColor(this.team - 1, false) : '1 1 1'));
-       setcefc(wp, ctf_FlagBase_Customize);
+       if(autocvar_g_ctf_flag_waypoint)
+       {
+               entity wp = WaypointSprite_SpawnFixed(basename, this.origin + FLAG_WAYPOINT_OFFSET, this, wps_flagbase, RADARICON_FLAG);
+               wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 1 1');
+               wp.fade_rate = autocvar_g_ctf_flag_waypoint_maxdistance;
+               WaypointSprite_UpdateTeamRadar(this.wps_flagbase, RADARICON_FLAG, ((this.team) ? colormapPaletteColor(this.team - 1, false) : '1 1 1'));
+               setcefc(wp, ctf_FlagBase_Customize);
+       }
 
        // captureshield setup
        ctf_CaptureShield_Spawn(this);
@@ -1235,7 +1241,7 @@ void ctf_DelayedFlagSetup(entity this) // called after a flag is placed on a map
 
 .bool pushable;
 
-void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag entity on the map as a spawnfunc
+void ctf_FlagSetup(int teamnum, entity flag) // called when spawning a flag entity on the map as a spawnfunc
 {
        // main setup
        flag.ctf_worldflagnext = ctf_worldflaglist; // link flag into ctf_worldflaglist
@@ -1243,8 +1249,8 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
 
        setattachment(flag, NULL, "");
 
-       flag.netname = strzone(sprintf("%s%s^7 flag", Team_ColorCode(teamnumber), Team_ColorName_Upper(teamnumber)));
-       flag.team = teamnumber;
+       flag.netname = strzone(sprintf("%s%s^7 flag", Team_ColorCode(teamnum), Team_ColorName_Upper(teamnum)));
+       flag.team = teamnum;
        flag.classname = "item_flag_team";
        flag.target = "###item###"; // for finding the nearest item using findnearest
        flag.flags = FL_ITEM | FL_NOTARGET;
@@ -1274,24 +1280,24 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        if(autocvar_g_ctf_score_ignore_fields)
                flag.cnt = flag.score_assist = flag.score_team_capture = flag.score_capture = flag.score_drop = flag.score_pickup = flag.score_return = 0;
 
-       string teamname = Static_Team_ColorName_Lower(teamnumber);
+       string teamname = Static_Team_ColorName_Lower(teamnum);
        // appearence
        if(!flag.scale)                         { flag.scale = FLAG_SCALE; }
        if(flag.skin == 0)                      { flag.skin = cvar(sprintf("g_ctf_flag_%s_skin", teamname)); }
        if(flag.model == "")            { flag.model = cvar_string(sprintf("g_ctf_flag_%s_model", teamname)); }
-       if (flag.toucheffect == "") { flag.toucheffect = EFFECT_FLAG_TOUCH(teamnumber).eent_eff_name; }
-       if (flag.passeffect == "")      { flag.passeffect = EFFECT_PASS(teamnumber).eent_eff_name; }
-       if (flag.capeffect == "")       { flag.capeffect = EFFECT_CAP(teamnumber).eent_eff_name; }
+       if (flag.toucheffect == "") { flag.toucheffect = EFFECT_FLAG_TOUCH(teamnum).eent_eff_name; }
+       if (flag.passeffect == "")      { flag.passeffect = EFFECT_PASS(teamnum).eent_eff_name; }
+       if (flag.capeffect == "")       { flag.capeffect = EFFECT_CAP(teamnum).eent_eff_name; }
 
        // sounds
 #define X(s,b) \
                if(flag.s == "") flag.s = b; \
                precache_sound(flag.s);
 
-       X(snd_flag_taken,               strzone(SND(CTF_TAKEN(teamnumber))))
-       X(snd_flag_returned,    strzone(SND(CTF_RETURNED(teamnumber))))
-       X(snd_flag_capture,     strzone(SND(CTF_CAPTURE(teamnumber))))
-       X(snd_flag_dropped,     strzone(SND(CTF_DROPPED(teamnumber))))
+       X(snd_flag_taken,               strzone(SND(CTF_TAKEN(teamnum))))
+       X(snd_flag_returned,    strzone(SND(CTF_RETURNED(teamnum))))
+       X(snd_flag_capture,     strzone(SND(CTF_CAPTURE(teamnum))))
+       X(snd_flag_dropped,     strzone(SND(CTF_DROPPED(teamnum))))
        X(snd_flag_respawn,     strzone(SND(CTF_RESPAWN)))
        X(snd_flag_touch,               strzone(SND(CTF_TOUCH)))
        X(snd_flag_pass,                strzone(SND(CTF_PASS)))
@@ -1309,7 +1315,7 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
 
        if(autocvar_g_ctf_flag_glowtrails)
        {
-               switch(teamnumber)
+               switch(teamnum)
                {
                        case NUM_TEAM_1: flag.glow_color = 251; break;
                        case NUM_TEAM_2: flag.glow_color = 210; break;
@@ -1325,7 +1331,7 @@ void ctf_FlagSetup(int teamnumber, entity flag) // called when spawning a flag e
        if(autocvar_g_ctf_fullbrightflags) { flag.effects |= EF_FULLBRIGHT; }
        if(autocvar_g_ctf_dynamiclights)
        {
-               switch(teamnumber)
+               switch(teamnum)
                {
                        case NUM_TEAM_1: flag.effects |= EF_RED; break;
                        case NUM_TEAM_2: flag.effects |= EF_BLUE; break;
index 54f6268..8906069 100644 (file)
@@ -472,15 +472,18 @@ MUTATOR_HOOKFUNCTION(ft, PlayerPreThink, CBC_ORDER_FIRST)
        if(!round_handler_IsRoundStarted())
                return true;
 
-       int n;
        entity player = M_ARGV(0, entity);
        //if (STAT(FROZEN, player) == FROZEN_NORMAL)
        //if(player.freezetag_frozen_timeout > 0 && time < player.freezetag_frozen_timeout)
                //player.iceblock.alpha = ICE_MIN_ALPHA + (ICE_MAX_ALPHA - ICE_MIN_ALPHA) * (player.freezetag_frozen_timeout - time) / (player.freezetag_frozen_timeout - player.freezetag_frozen_time);
 
+       if (!(frametime && IS_PLAYER(player)))
+               return true;
+
        entity reviving_players_last = NULL;
        entity reviving_players_first = NULL;
 
+       int n;
        if(player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
                n = -1;
        else
index 0b8144d..f3c140f 100644 (file)
@@ -350,6 +350,12 @@ MUTATOR_HOOKFUNCTION(ka, GiveFragsForKill)
        return true; // you deceptive little bugger ;3 This needs to be true in order for this function to even count.
 }
 
+MUTATOR_HOOKFUNCTION(ka, Scores_CountFragsRemaining)
+{
+       // announce remaining frags, but only when timed scoring is off
+       return !autocvar_g_keepaway_score_timepoints;
+}
+
 MUTATOR_HOOKFUNCTION(ka, PlayerPreThink)
 {
        entity player = M_ARGV(0, entity);
index 6f12f3c..9675634 100644 (file)
@@ -313,15 +313,15 @@ void ons_DelayedLinkSetup(entity this)
 // Main Control Point Functions
 // =============================
 
-int ons_ControlPoint_CanBeLinked(entity cp, int teamnumber)
+int ons_ControlPoint_CanBeLinked(entity cp, int teamnum)
 {
-       if(cp.aregensneighbor & BIT(teamnumber)) return 2;
-       if(cp.arecpsneighbor & BIT(teamnumber)) return 1;
+       if(cp.aregensneighbor & BIT(teamnum)) return 2;
+       if(cp.arecpsneighbor & BIT(teamnum)) return 1;
 
        return 0;
 }
 
-int ons_ControlPoint_Attackable(entity cp, int teamnumber)
+int ons_ControlPoint_Attackable(entity cp, int teamnum)
        // -2: SAME TEAM, attackable by enemy!
        // -1: SAME TEAM!
        // 0: off limits
@@ -339,16 +339,16 @@ int ons_ControlPoint_Attackable(entity cp, int teamnumber)
        else if(cp.goalentity)
        {
                // if there's already an icon built, nothing happens
-               if(cp.team == teamnumber)
+               if(cp.team == teamnum)
                {
-                       a = ons_ControlPoint_CanBeLinked(cp, teamnumber);
+                       a = ons_ControlPoint_CanBeLinked(cp, teamnum);
                        if(a) // attackable by enemy?
                                return -2; // EMERGENCY!
                        return -1;
                }
                // we know it can be linked, so no need to check
                // but...
-               a = ons_ControlPoint_CanBeLinked(cp, teamnumber);
+               a = ons_ControlPoint_CanBeLinked(cp, teamnum);
                if(a == 2) // near our generator?
                        return 3; // EMERGENCY!
                return 1;
@@ -356,9 +356,9 @@ int ons_ControlPoint_Attackable(entity cp, int teamnumber)
        else
        {
                // free point
-               if(ons_ControlPoint_CanBeLinked(cp, teamnumber))
+               if(ons_ControlPoint_CanBeLinked(cp, teamnum))
                {
-                       a = ons_ControlPoint_CanBeLinked(cp, teamnumber); // why was this here NUM_TEAM_1 + NUM_TEAM_2 - t
+                       a = ons_ControlPoint_CanBeLinked(cp, teamnum); // why was this here NUM_TEAM_1 + NUM_TEAM_2 - t
                        if(a == 2)
                                return 4; // GET THIS ONE NOW!
                        else
@@ -1063,16 +1063,16 @@ void onslaught_generator_touch(entity this, entity toucher)
 void ons_GeneratorSetup(entity gen) // called when spawning a generator entity on the map as a spawnfunc
 {
        // declarations
-       int teamnumber = gen.team;
+       int teamnum = gen.team;
 
        // main setup
        gen.ons_worldgeneratornext = ons_worldgeneratorlist; // link generator into ons_worldgeneratorlist
        ons_worldgeneratorlist = gen;
 
-       gen.netname = sprintf("%s generator", Team_ColoredFullName(teamnumber));
+       gen.netname = sprintf("%s generator", Team_ColoredFullName(teamnum));
        gen.classname = "onslaught_generator";
        gen.solid = SOLID_BBOX;
-       gen.team_saved = teamnumber;
+       gen.team_saved = teamnum;
        IL_PUSH(g_saved_team, gen);
        set_movetype(gen, MOVETYPE_NONE);
        gen.lasthealth = gen.max_health = autocvar_g_onslaught_gen_health;
@@ -1094,7 +1094,7 @@ void ons_GeneratorSetup(entity gen) // called when spawning a generator entity o
        // model handled by CSQC
        setsize(gen, GENERATOR_MIN, GENERATOR_MAX);
        setorigin(gen, (gen.origin + CPGEN_SPAWN_OFFSET));
-       gen.colormap = 1024 + (teamnumber - 1) * 17;
+       gen.colormap = 1024 + (teamnum - 1) * 17;
 
        // generator placement
        droptofloor(gen);
index 7a9b192..0800ae1 100644 (file)
@@ -67,7 +67,7 @@ float ons_notification_time[17];
 // declarations for functions used outside gamemode_onslaught.qc
 void ons_Generator_UpdateSprite(entity e);
 void ons_ControlPoint_UpdateSprite(entity e);
-bool ons_ControlPoint_Attackable(entity cp, int teamnumber);
+bool ons_ControlPoint_Attackable(entity cp, int teamnum);
 
 // CaptureShield: Prevent capturing or destroying control point/generator if it is not available yet
 float ons_captureshield_force; // push force of the shield
index 3ff4a54..3ae4735 100644 (file)
@@ -19,7 +19,7 @@ STATIC_INIT(Items) { FOREACH(Items, true, it.m_id = i); }
 
 void Dump_Items();
 
-GENERIC_COMMAND(dumpitems, "Dump all items to the console") {
+GENERIC_COMMAND(dumpitems, "Dump all items to the console", false) {
     switch (request) {
         case CMD_REQUEST_COMMAND: {
             Dump_Items();
index 017ada7..9f0a43a 100644 (file)
@@ -42,7 +42,7 @@ NET_HANDLE(ENT_CLIENT_INVENTORY, bool isnew)
             .int fld = inv_items[it.m_id];
             int prev = this.(fld);
             int next = this.(fld) = ReadByte();
-            LOG_TRACEF("%s: %.0f -> %.0f", it.m_name, prev, next);
+            LOG_DEBUGF("%s: %.0f -> %.0f", it.m_name, prev, next);
         }
     }
     return true;
index 1d6f489..257e5e4 100644 (file)
@@ -843,12 +843,6 @@ float MapInfo_Get_ByName_NoFallbacks(string pFilename, int pAllowGenerate, Gamet
                                fputs(fh, sprintf("gametype %s // defaults: %s\n", MapInfo_Type_ToString(it), _MapInfo_GetDefaultEx(it)));
                        });
 
-                       if(fexists(strcat("scripts/", pFilename, ".arena")))
-                               fputs(fh, "settemp_for_type all sv_q3acompat_machineshotgunswap 1\n");
-
-                       if(fexists(strcat("scripts/", pFilename, ".defi")))
-                               fputs(fh, "settemp_for_type all sv_vq3compat 1\n");
-
                        fputs(fh, "// optional: fog density red green blue alpha mindist maxdist\n");
                        fputs(fh, "// optional: settemp_for_type (all|gametypename) cvarname value\n");
                        fputs(fh, "// optional: clientsettemp_for_type (all|gametypename) cvarname value\n");
@@ -1147,7 +1141,9 @@ string MapInfo_FixName(string s)
 int MapInfo_CurrentFeatures()
 {
        int req = 0;
-       if(!(cvar("g_lms") || cvar("g_instagib") || cvar("g_overkill") || cvar("g_nix") || cvar("g_weaponarena") || !cvar("g_pickup_items") || cvar("g_race") || cvar("g_cts") || cvar("g_nexball")))
+    // TODO: find a better way to check if weapons are required on the map
+       if(!(cvar("g_instagib") || cvar("g_overkill") || cvar("g_nix") || cvar("g_weaponarena") || !cvar("g_pickup_items") 
+               || cvar("g_race") || cvar("g_cts") || cvar("g_nexball") || cvar("g_ca") || cvar("g_freezetag") || cvar("g_lms")))
                req |= MAPINFO_FEATURE_WEAPONS;
        return req;
 }
index 32926d4..e92af67 100644 (file)
@@ -343,7 +343,7 @@ spawnfunc(func_breakable)
                this.dmg_force = 200;
 
        this.mdl = this.model;
-       SetBrushEntityModel(this);
+       SetBrushEntityModel(this, true);
 
        if(this.spawnflags & BREAKABLE_NODAMAGE)
                this.use = func_breakable_destroy;
index 56bfd41..423ac5e 100644 (file)
@@ -206,6 +206,9 @@ spawnfunc(func_button)
        if (!this.lip)
                this.lip = 4;
 
+       if(this.wait == -1 && autocvar_sv_q3defragcompat)
+               this.wait = 0.1; // compatibility for q3df: "instant" return
+
     if(this.noise != "")
         precache_sound(this.noise);
 
index 8414700..12dd6d2 100644 (file)
@@ -36,7 +36,7 @@ spawnfunc(func_rain)
        this.angles = '0 0 0';
        set_movetype(this, MOVETYPE_NONE);
        this.solid = SOLID_NOT;
-       SetBrushEntityModel(this);
+       SetBrushEntityModel(this, true);
        if (!this.cnt)
        {
                this.cnt = 12;
@@ -76,7 +76,7 @@ spawnfunc(func_snow)
        this.angles = '0 0 0';
        set_movetype(this, MOVETYPE_NONE);
        this.solid = SOLID_NOT;
-       SetBrushEntityModel(this);
+       SetBrushEntityModel(this, true);
        if (!this.cnt)
        {
                this.cnt = 12;
index 44a1352..18d0336 100644 (file)
@@ -168,7 +168,7 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
 #define G_MODEL_INIT(ent,sol) \
        if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS); \
        if(!ent.scale) ent.scale = ent.modelscale; \
-       SetBrushEntityModel(ent); \
+       SetBrushEntityModel(ent,true); \
        ent.use = g_model_setcolormaptoactivator; \
        InitializeEntity(ent, g_model_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
        if(!ent.solid) ent.solid = (sol); \
@@ -177,7 +177,7 @@ bool g_clientmodel_genericsendentity(entity this, entity to, int sf)
 #define G_CLIENTMODEL_INIT(ent,sol) \
        if(ent.geomtype && autocvar_physics_ode && checkextension("DP_PHYSICS_ODE")) set_movetype(ent, MOVETYPE_PHYSICS); \
        if(!ent.scale) ent.scale = ent.modelscale; \
-       SetBrushEntityModel(ent); \
+       SetBrushEntityModel(ent,true); \
        ent.use = g_clientmodel_use; \
        InitializeEntity(ent, g_clientmodel_dropbyspawnflags, INITPRIO_DROPTOFLOOR); \
        if(!ent.solid) ent.solid = (sol); \
index f9e50dc..9adccb4 100644 (file)
@@ -398,7 +398,7 @@ void ApplyMinMaxScaleAngles(entity e)
                setsize(e, e.mins, e.maxs);
 }
 
-void SetBrushEntityModel(entity this)
+void SetBrushEntityModel(entity this, bool with_lod)
 {
        if(this.model != "")
        {
@@ -412,26 +412,11 @@ void SetBrushEntityModel(entity this)
                }
                else
                        _setmodel(this, this.model); // no precision needed
-               InitializeEntity(this, LODmodel_attach, INITPRIO_FINDTARGET);
-       }
-       setorigin(this, this.origin);
-       ApplyMinMaxScaleAngles(this);
-}
+               if(with_lod)
+                       InitializeEntity(this, LODmodel_attach, INITPRIO_FINDTARGET);
 
-void SetBrushEntityModelNoLOD(entity this)
-{
-       if(this.model != "")
-       {
-               precache_model(this.model);
-               if(this.mins != '0 0 0' || this.maxs != '0 0 0')
-               {
-                       vector mi = this.mins;
-                       vector ma = this.maxs;
-                       _setmodel(this, this.model); // no precision needed
-                       setsize(this, mi, ma);
-               }
-               else
-                       _setmodel(this, this.model); // no precision needed
+               if(endsWith(this.model, ".obj")) // WORKAROUND: darkplaces currently rotates .obj models on entities incorrectly, we need to add 180 degrees to the Y axis
+                       this.angles_y = anglemods(this.angles_y - 180);
        }
        setorigin(this, this.origin);
        ApplyMinMaxScaleAngles(this);
@@ -553,7 +538,7 @@ void InitTrigger(entity this)
 // to mean no restrictions, so use a yaw of 360 instead.
        SetMovedir(this);
        this.solid = SOLID_TRIGGER;
-       SetBrushEntityModelNoLOD(this);
+       SetBrushEntityModel(this, false);
        set_movetype(this, MOVETYPE_NONE);
        this.modelindex = 0;
        this.model = "";
@@ -565,7 +550,7 @@ void InitSolidBSPTrigger(entity this)
 // to mean no restrictions, so use a yaw of 360 instead.
        SetMovedir(this);
        this.solid = SOLID_BSP;
-       SetBrushEntityModelNoLOD(this);
+       SetBrushEntityModel(this, false);
        set_movetype(this, MOVETYPE_NONE); // why was this PUSH? -div0
 //     this.modelindex = 0;
        this.model = "";
@@ -576,7 +561,7 @@ bool InitMovingBrushTrigger(entity this)
 // trigger angles are used for one-way touches.  An angle of 0 is assumed
 // to mean no restrictions, so use a yaw of 360 instead.
        this.solid = SOLID_BSP;
-       SetBrushEntityModel(this);
+       SetBrushEntityModel(this, true);
        set_movetype(this, MOVETYPE_PUSH);
        if(this.modelindex == 0)
        {
index 861d73e..c1d4d06 100644 (file)
@@ -115,9 +115,7 @@ void SUB_CalcMoveEnt (entity ent, vector tdest, float tspeedtype, float tspeed,
 #ifdef SVQC
 void ApplyMinMaxScaleAngles(entity e);
 
-void SetBrushEntityModel(entity this);
-
-void SetBrushEntityModelNoLOD(entity this);
+void SetBrushEntityModel(entity this, bool with_lod);
 
 int autocvar_loddebug;
 .string lodtarget1;
index ccdf2c7..8c21c50 100644 (file)
@@ -25,7 +25,7 @@ void trigger_hurt_touch(entity this, entity toucher)
                if (toucher.triggerhurttime < time)
                {
                        EXACTTRIGGER_TOUCH(this, toucher);
-                       toucher.triggerhurttime = time + ((autocvar_sv_vq3compat && !(this.spawnflags & HURT_SLOW)) ? 0.1 : 1);
+                       toucher.triggerhurttime = time + ((autocvar_sv_q3defragcompat && !(this.spawnflags & HURT_SLOW)) ? 0.1 : 1);
 
                        entity own;
                        own = this.enemy;
@@ -66,7 +66,7 @@ spawnfunc(trigger_hurt)
        this.use = trigger_hurt_use;
        this.enemy = world; // I hate you all
        if (!this.dmg)
-               this.dmg = ((autocvar_sv_vq3compat) ? 5 : 10000);
+               this.dmg = ((autocvar_sv_q3defragcompat) ? 5 : 10000);
        if (this.message == "")
                this.message = "was in the wrong place";
        if (this.message2 == "")
index f438fbf..2c160ea 100644 (file)
@@ -36,8 +36,8 @@ vector trigger_push_calculatevelocity(vector org, entity tgt, float ht, entity p
        torg = tgt.origin + (tgt.mins + tgt.maxs) * 0.5;
 
        grav = PHYS_GRAVITY(NULL);
-       if(pushed_entity && PHYS_ENTGRAVITY(pushed_entity))
-               grav *= PHYS_ENTGRAVITY(pushed_entity);
+       if(pushed_entity && pushed_entity.gravity)
+               grav *= pushed_entity.gravity;
 
        zdist = torg.z - org.z;
        sdist = vlen(torg - org - zdist * '0 0 1');
@@ -135,9 +135,9 @@ bool jumppad_push(entity this, entity targ)
 
        vector org = targ.origin;
 #ifdef SVQC
-       if(autocvar_sv_vq3compat)
+       if(autocvar_sv_q3defragcompat)
 #elif defined(CSQC)
-       if(STAT(VQ3COMPAT))
+       if(STAT(Q3DEFRAGCOMPAT))
 #endif
        {
                org.z += targ.mins_z;
index c71dc37..df915a6 100644 (file)
@@ -176,6 +176,9 @@ spawnfunc(trigger_multiple)
                this.wait = 0;
        this.use = multi_use;
 
+       if(this.wait == -1 && autocvar_sv_q3defragcompat)
+               this.wait = 0.1; // compatibility for q3df: "instant" return
+
        EXACTTRIGGER_INIT;
 
        this.team_saved = this.team;
index 9a7181d..27ffead 100644 (file)
@@ -235,7 +235,7 @@ match (string)this.target and call their .use function
 ==============================
 */
 
-void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse)
+void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventReuse, int skiptargets)
 {
 //
 // check for a delay
@@ -249,10 +249,10 @@ void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventRe
                t.enemy = actor;
                t.message = this.message;
                t.killtarget = this.killtarget;
-               t.target = this.target;
-               t.target2 = this.target2;
-               t.target3 = this.target3;
-               t.target4 = this.target4;
+               if(!(skiptargets & BIT(1))) t.target = this.target;
+               if(!(skiptargets & BIT(2))) t.target2 = this.target2;
+               if(!(skiptargets & BIT(3))) t.target3 = this.target3;
+               if(!(skiptargets & BIT(4))) t.target4 = this.target4;
                t.antiwall_flag = this.antiwall_flag;
                return;
        }
@@ -292,6 +292,8 @@ void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventRe
 
        for(int i = 0; i < 4; ++i)
        {
+               if(skiptargets & BIT(i + 1))
+                       continue;
                switch(i)
                {
                        default:
@@ -329,5 +331,6 @@ void SUB_UseTargets_Ex(entity this, entity actor, entity trigger, bool preventRe
        }
 }
 
-void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false); }
-void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true); }
+void SUB_UseTargets(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, false, 0); }
+void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger) { SUB_UseTargets_Ex(this, actor, trigger, true, 0); }
+void SUB_UseTargets_SkipTargets(entity this, entity actor, entity trigger, int skiptargets) { SUB_UseTargets_Ex(this, actor, trigger, false, skiptargets); }
index b9baf63..797c976 100644 (file)
@@ -26,6 +26,10 @@ void SUB_UseTargets(entity this, entity actor, entity trigger);
 
 void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger);
 
+// allow excluding certain .target* fields without needing to nullify them
+// use BIT(1) through BIT(4)
+void SUB_UseTargets_SkipTargets(entity this, entity actor, entity trigger, int skiptargets);
+
 void generic_setactive(entity this, int act);
 // generic methods for netlinked entities
 void generic_netlinked_reset(entity this);
index b684af1..d9a51c0 100644 (file)
@@ -66,6 +66,7 @@ METHOD(SpiderAttack, wr_think, void(SpiderAttack thiswep, entity actor, .entity
                        actor.anim_finished = time + 1;
                }
         if (isPlayer) actor.enemy = Monster_FindTarget(actor);
+        monster_makevectors(actor, actor.enemy);
         W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_SpiderAttack_FIRE, CH_WEAPON_B, 0, DEATH_MONSTER_SPIDER.m_id);
        if (!isPlayer) w_shotdir = normalize((actor.enemy.origin + '0 0 10') - actor.origin);
                M_Spider_Attack_Web(actor);
index d07669a..4de122e 100644 (file)
@@ -18,6 +18,7 @@ METHOD(WyvernAttack, wr_think, void(WyvernAttack thiswep, entity actor, .entity
     TC(WyvernAttack, thiswep);
     if (fire & 1)
     if (time > actor.attack_finished_single[0] || weapon_prepareattack(thiswep, actor, weaponentity, false, 1.2)) {
+       monster_makevectors(actor, actor.enemy);
         if (IS_PLAYER(actor)) W_SetupShot_Dir(actor, weaponentity, v_forward, false, 0, SND_WyvernAttack_FIRE, CH_WEAPON_B, 0, DEATH_MONSTER_WYVERN.m_id);
                if (IS_MONSTER(actor)) {
                        actor.attack_finished_single[0] = time + 1.2;
index cf85848..6ee9574 100644 (file)
@@ -112,3 +112,11 @@ MUTATOR_HOOKABLE(WeaponSound, EV_WeaponSound);
     /**/          o(string, MUTATOR_ARGV_1_string) \
     /**/
 MUTATOR_HOOKABLE(WeaponModel, EV_WeaponModel);
+
+/** decides whether a player can crouch or not */
+#define EV_PlayerCanCrouch(i, o) \
+    /** player */      i(entity, MUTATOR_ARGV_0_entity) \
+    /** do_crouch */   i(bool, MUTATOR_ARGV_1_bool) \
+    /**/               o(bool, MUTATOR_ARGV_1_bool) \
+    /**/
+MUTATOR_HOOKABLE(PlayerCanCrouch, EV_PlayerCanCrouch);
index 768808d..16e6308 100644 (file)
@@ -1,4 +1,2 @@
 // generated file; do not modify
-#ifdef SVQC
-    #include <common/mutators/mutator/bloodloss/sv_bloodloss.qc>
-#endif
+#include <common/mutators/mutator/bloodloss/bloodloss.qc>
index e6ad248..b1d45e2 100644 (file)
@@ -1,4 +1,2 @@
 // generated file; do not modify
-#ifdef SVQC
-    #include <common/mutators/mutator/bloodloss/sv_bloodloss.qh>
-#endif
+#include <common/mutators/mutator/bloodloss/bloodloss.qh>
diff --git a/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc b/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qc
new file mode 100644 (file)
index 0000000..2a0ebec
--- /dev/null
@@ -0,0 +1,70 @@
+#include "bloodloss.qh"
+
+#ifdef GAMEQC
+#ifdef SVQC
+REGISTER_MUTATOR(bloodloss, autocvar_g_bloodloss);
+#elif defined(CSQC)
+REGISTER_MUTATOR(bloodloss, true);
+#endif
+
+#ifdef SVQC
+.float bloodloss_timer;
+
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerPreThink)
+{
+       entity player = M_ARGV(0, entity);
+
+       if(game_stopped)
+               return; // during intermission, the player's health changes to strange values for the engine, let's not cause damage during this phase!
+
+       if(IS_PLAYER(player))
+       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss && !IS_DEAD(player) && time >= player.bloodloss_timer)
+       {
+               if(player.vehicle)
+                       vehicles_exit(player.vehicle, VHEF_RELEASE); // TODO: boots player out of their vehicle each health rot tick!
+               if(player.event_damage)
+                       player.event_damage(player, player, player, 1, DEATH_ROT.m_id, DMG_NOWEP, player.origin, '0 0 0');
+               player.bloodloss_timer = time + 0.5 + random() * 0.5;
+       }
+}
+
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerCanCrouch)
+{
+       entity player = M_ARGV(0, entity);
+       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss)
+               M_ARGV(1, bool) = true; // do_crouch
+}
+
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerJump)
+{
+       entity player = M_ARGV(0, entity);
+
+       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss)
+               return true;
+}
+
+MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsString)
+{
+       M_ARGV(0, string) = strcat(M_ARGV(0, string), ":bloodloss");
+}
+
+MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsPrettyString)
+{
+       M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Blood loss");
+}
+#endif
+
+#ifdef CSQC
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerCanCrouch)
+{
+       if(STAT(HEALTH) <= STAT(BLOODLOSS))
+               M_ARGV(1, bool) = true; // do_crouch
+}
+MUTATOR_HOOKFUNCTION(bloodloss, PlayerJump)
+{
+       if(STAT(HEALTH) <= STAT(BLOODLOSS))
+               return true;
+}
+#endif
+
+#endif
diff --git a/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qh b/qcsrc/common/mutators/mutator/bloodloss/bloodloss.qh
new file mode 100644 (file)
index 0000000..6f70f09
--- /dev/null
@@ -0,0 +1 @@
+#pragma once
diff --git a/qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qc b/qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qc
deleted file mode 100644 (file)
index a89691d..0000000
+++ /dev/null
@@ -1,44 +0,0 @@
-#include "sv_bloodloss.qh"
-
-float autocvar_g_bloodloss;
-REGISTER_MUTATOR(bloodloss, autocvar_g_bloodloss);
-
-.float bloodloss_timer;
-
-MUTATOR_HOOKFUNCTION(bloodloss, PlayerPreThink)
-{
-       entity player = M_ARGV(0, entity);
-
-       if(IS_PLAYER(player))
-       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss && !IS_DEAD(player))
-       {
-               PHYS_INPUT_BUTTON_CROUCH(player) = true;
-
-               if(time >= player.bloodloss_timer)
-               {
-                       if(player.vehicle)
-                               vehicles_exit(player.vehicle, VHEF_RELEASE);
-                       if(player.event_damage)
-                               player.event_damage(player, player, player, 1, DEATH_ROT.m_id, DMG_NOWEP, player.origin, '0 0 0');
-                       player.bloodloss_timer = time + 0.5 + random() * 0.5;
-               }
-       }
-}
-
-MUTATOR_HOOKFUNCTION(bloodloss, PlayerJump)
-{
-       entity player = M_ARGV(0, entity);
-
-       if(GetResource(player, RES_HEALTH) <= autocvar_g_bloodloss)
-               return true;
-}
-
-MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsString)
-{
-       M_ARGV(0, string) = strcat(M_ARGV(0, string), ":bloodloss");
-}
-
-MUTATOR_HOOKFUNCTION(bloodloss, BuildMutatorsPrettyString)
-{
-       M_ARGV(0, string) = strcat(M_ARGV(0, string), ", Blood loss");
-}
diff --git a/qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qh b/qcsrc/common/mutators/mutator/bloodloss/sv_bloodloss.qh
deleted file mode 100644 (file)
index 6f70f09..0000000
+++ /dev/null
@@ -1 +0,0 @@
-#pragma once
index 0c9b889..a655323 100644 (file)
@@ -57,6 +57,7 @@ REGISTER_BUFF(BASH) {
     this.m_color = '1 0.39 0';
 }
 BUFF_SPAWNFUNCS(bash, BUFF_BASH)
+BUFF_SPAWNFUNC_Q3TA_COMPAT(doubler, BUFF_BASH)
 
 REGISTER_BUFF(VAMPIRE) {
     this.m_name = _("Vampire");
index 256af90..f1a1491 100644 (file)
@@ -227,7 +227,8 @@ void buff_NewType(entity ent)
        FOREACH(Buffs, buff_Available(it),
        {
                // if it's already been chosen, give it a lower priority
-               RandomSelection_AddEnt(it, max(0.2, 1 / it.buff_seencount), 1);
+               float myseencount = (it.buff_seencount > 0) ? it.buff_seencount : 1; // no division by zero please!
+               RandomSelection_AddEnt(it, max(0.2, 1 / myseencount), 1);
        });
        entity newbuff = RandomSelection_chosen_ent;
        newbuff.buff_seencount += 1; // lower chances of seeing this buff again soon
@@ -271,7 +272,7 @@ void buff_Think(entity this)
        {
                buff_SetCooldown(this, autocvar_g_buffs_cooldown_respawn + frametime);
                this.owner = NULL;
-               if(autocvar_g_buffs_randomize)
+               if(autocvar_g_buffs_randomize && (!teamplay || autocvar_g_buffs_randomize_teamplay))
                        buff_NewType(this);
 
                if(autocvar_g_buffs_random_location || (this.spawnflags & 64))
@@ -315,7 +316,7 @@ void buff_Waypoint_Reset(entity this)
 
 void buff_Reset(entity this)
 {
-       if(autocvar_g_buffs_randomize)
+       if(autocvar_g_buffs_randomize && (!teamplay || autocvar_g_buffs_randomize_teamplay))
                buff_NewType(this);
        this.owner = NULL;
        buff_SetCooldown(this, autocvar_g_buffs_cooldown_activate);
index 671a524..88efc94 100644 (file)
@@ -9,6 +9,7 @@ float autocvar_g_buffs_waypoint_distance;
 bool autocvar_g_buffs_pickup_anyway = false;
 float autocvar_g_buffs_pickup_delay = 0.7;
 bool autocvar_g_buffs_randomize;
+bool autocvar_g_buffs_randomize_teamplay = true;
 float autocvar_g_buffs_random_lifetime;
 bool autocvar_g_buffs_random_location;
 int autocvar_g_buffs_random_location_attempts;
index 67e3d4a..510fcf9 100644 (file)
@@ -1347,44 +1347,47 @@ MUTATOR_HOOKFUNCTION(nades, PlayerPreThink)
                }
        }
 
-       int n = 0;
-
-       IntrusiveList reviving_players = NULL;
-
-       if(player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
-               n = -1;
-       else if (STAT(FROZEN, player) == FROZEN_TEMP_DYING)
+       if (frametime && IS_PLAYER(player))
        {
-               vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
-               n = 0;
-               FOREACH_CLIENT(IS_PLAYER(it) && IS_REVIVING(player, it, revive_extra_size), {
-                       if (!reviving_players)
-                               reviving_players = IL_NEW();
-                       IL_PUSH(reviving_players, it);
-                       ++n;
-               });
-       }
+               int n = 0;
 
-       if (n > 0 && STAT(FROZEN, player) == FROZEN_TEMP_DYING) // OK, there is at least one teammate reviving us
-       {
-               STAT(REVIVE_PROGRESS, player) = bound(0, STAT(REVIVE_PROGRESS, player) + frametime * max(1/60, autocvar_g_freezetag_revive_speed), 1);
-               SetResource(player, RES_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * start_health));
+               IntrusiveList reviving_players = NULL;
 
-               if(STAT(REVIVE_PROGRESS, player) >= 1)
+               if(player.freezetag_frozen_timeout > 0 && time >= player.freezetag_frozen_timeout)
+                       n = -1;
+               else if (STAT(FROZEN, player) == FROZEN_TEMP_DYING)
                {
-                       Unfreeze(player, false);
-
-                       entity first = IL_FIRST(reviving_players);
-                       Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, first.netname);
-                       Send_Notification(NOTIF_ONE, first, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
+                       vector revive_extra_size = '1 1 1' * autocvar_g_freezetag_revive_extra_size;
+                       n = 0;
+                       FOREACH_CLIENT(IS_PLAYER(it) && IS_REVIVING(player, it, revive_extra_size), {
+                               if (!reviving_players)
+                                       reviving_players = IL_NEW();
+                               IL_PUSH(reviving_players, it);
+                               ++n;
+                       });
                }
 
-               IL_EACH(reviving_players, true, {
-                       STAT(REVIVE_PROGRESS, it) = STAT(REVIVE_PROGRESS, player);
-               });
+               if (n > 0 && STAT(FROZEN, player) == FROZEN_TEMP_DYING) // OK, there is at least one teammate reviving us
+               {
+                       STAT(REVIVE_PROGRESS, player) = bound(0, STAT(REVIVE_PROGRESS, player) + frametime * max(1/60, autocvar_g_freezetag_revive_speed), 1);
+                       SetResource(player, RES_HEALTH, max(1, STAT(REVIVE_PROGRESS, player) * start_health));
+
+                       if(STAT(REVIVE_PROGRESS, player) >= 1)
+                       {
+                               Unfreeze(player, false);
+
+                               entity first = IL_FIRST(reviving_players);
+                               Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_FREEZETAG_REVIVED, first.netname);
+                               Send_Notification(NOTIF_ONE, first, MSG_CENTER, CENTER_FREEZETAG_REVIVE, player.netname);
+                       }
+
+                       IL_EACH(reviving_players, true, {
+                               STAT(REVIVE_PROGRESS, it) = STAT(REVIVE_PROGRESS, player);
+                       });
+               }
+               if (reviving_players)
+                       IL_DELETE(reviving_players);
        }
-       if (reviving_players)
-               IL_DELETE(reviving_players);
 }
 
 MUTATOR_HOOKFUNCTION(nades, PlayerPhysics_UpdateStats)
index df55fb8..a0a8962 100644 (file)
@@ -74,14 +74,11 @@ METHOD(OverkillHeavyMachineGun, wr_think, void(entity thiswep, entity actor, .en
                        (actor.(weaponentity).wframe == WFRAME_FIRE2))
                {
                        // Set secondary fire animation.
-                       vector a = '0 0 0';
                        actor.(weaponentity).wframe = WFRAME_FIRE2;
-                       a = actor.(weaponentity).anim_fire2;
-                       a.z *= g_weaponratefactor;
                        FOREACH_CLIENT(true, LAMBDA(
                                if (it == actor || (IS_SPEC(it) && it.enemy == actor))
                                {
-                                       wframe_send(it, actor.(weaponentity), a, true);
+                                       wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true);
                                }
                        ));
                        animdecide_setaction(actor, ANIMACTION_SHOOT, true);
index 768e364..17e71f0 100644 (file)
@@ -68,14 +68,11 @@ METHOD(OverkillMachineGun, wr_think, void(entity thiswep, entity actor, .entity
                        (actor.(weaponentity).wframe == WFRAME_FIRE2))
                {
                        // Set secondary fire animation.
-                       vector a = '0 0 0';
                        actor.(weaponentity).wframe = WFRAME_FIRE2;
-                       a = actor.(weaponentity).anim_fire2;
-                       a.z *= g_weaponratefactor;
                        FOREACH_CLIENT(true, LAMBDA(
                                if (it == actor || (IS_SPEC(it) && it.enemy == actor))
                                {
-                                       wframe_send(it, actor.(weaponentity), a, true);
+                                       wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true);
                                }
                        ));
                        animdecide_setaction(actor, ANIMACTION_SHOOT, true);
index 83a3a3c..ca44a07 100644 (file)
@@ -150,14 +150,11 @@ METHOD(OverkillNex, wr_think, void(entity thiswep, entity actor, .entity weapone
                        (actor.(weaponentity).wframe == WFRAME_FIRE2))
                {
                        // Set secondary fire animation.
-                       vector a = '0 0 0';
                        actor.(weaponentity).wframe = WFRAME_FIRE2;
-                       a = actor.(weaponentity).anim_fire2;
-                       a.z *= g_weaponratefactor;
                        FOREACH_CLIENT(true, LAMBDA(
                                if (it == actor || (IS_SPEC(it) && it.enemy == actor))
                                {
-                                       wframe_send(it, actor.(weaponentity), a, true);
+                                       wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true);
                                }
                        ));
                        animdecide_setaction(actor, ANIMACTION_SHOOT, true);
index fa4ffc4..362f148 100644 (file)
@@ -149,14 +149,11 @@ METHOD(OverkillRocketPropelledChainsaw, wr_think, void(entity thiswep, entity ac
                        (actor.(weaponentity).wframe == WFRAME_FIRE2))
                {
                        // Set secondary fire animation.
-                       vector a = '0 0 0';
                        actor.(weaponentity).wframe = WFRAME_FIRE2;
-                       a = actor.(weaponentity).anim_fire2;
-                       a.z *= g_weaponratefactor;
                        FOREACH_CLIENT(true, LAMBDA(
                                if (it == actor || (IS_SPEC(it) && it.enemy == actor))
                                {
-                                       wframe_send(it, actor.(weaponentity), a, true);
+                                       wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true);
                                }
                        ));
                        animdecide_setaction(actor, ANIMACTION_SHOOT, true);
index 784d1c3..da4c474 100644 (file)
@@ -24,14 +24,11 @@ METHOD(OverkillShotgun, wr_think, void(entity thiswep, entity actor, .entity wea
                        (actor.(weaponentity).wframe == WFRAME_FIRE2))
                {
                        // Set secondary fire animation.
-                       vector a = '0 0 0';
                        actor.(weaponentity).wframe = WFRAME_FIRE2;
-                       a = actor.(weaponentity).anim_fire2;
-                       a.z *= g_weaponratefactor;
                        FOREACH_CLIENT(true, LAMBDA(
                                if (it == actor || (IS_SPEC(it) && it.enemy == actor))
                                {
-                                       wframe_send(it, actor.(weaponentity), a, true);
+                                       wframe_send(it, actor.(weaponentity), WFRAME_FIRE2, g_weaponratefactor, true);
                                }
                        ));
                        animdecide_setaction(actor, ANIMACTION_SHOOT, true);
index c462a7e..519159d 100644 (file)
@@ -23,10 +23,12 @@ vector PlayerTouchWall(entity this)
 
        float dist = 10, max_normal = 0.2, scaler = 100;
        vector start = this.origin;
-       TRACE(start + v_forward * scaler)
-       TRACE(start - v_forward * scaler)
-       TRACE(start + v_right * scaler)
-       TRACE(start - v_right * scaler)
+       vector forward, right, _up;
+       MAKE_VECTORS(this.angles, forward, right, _up);
+       TRACE(start + forward * scaler)
+       TRACE(start - forward * scaler)
+       TRACE(start + right * scaler)
+       TRACE(start - right * scaler)
 #undef TRACE
        return '0 0 0';
 }
index a9e1c5f..0b4fe28 100644 (file)
@@ -296,7 +296,7 @@ void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, ve
     v4 = Rotate(v4, rot) + org;
 
     // draw them
-    R_BeginPolygon(pic, f);
+    R_BeginPolygon(pic, f, true);
     R_PolygonVertex(v1, '0 0 0', rgb, a);
     R_PolygonVertex(v2, '1 0 0', rgb, a);
     R_PolygonVertex(v3, '1 1 0', rgb, a);
@@ -306,7 +306,7 @@ void drawrotpic(vector org, float rot, string pic, vector sz, vector hotspot, ve
 
 void drawquad(vector o, vector ri, vector up, string pic, vector rgb, float a, float f)
 {
-    R_BeginPolygon(pic, f);
+    R_BeginPolygon(pic, f, true);
     R_PolygonVertex(o, '0 0 0', rgb, a);
     R_PolygonVertex(o + ri, '1 0 0', rgb, a);
     R_PolygonVertex(o + up + ri, '1 1 0', rgb, a);
@@ -354,7 +354,7 @@ vector drawspritearrow(vector o, float ang, vector rgb, float a, float t)
     vector borderX = eX * (size+borderDiag);
     vector borderY = eY * (size+borderDiag+border);
 
-    R_BeginPolygon("", DRAWFLAG_NORMAL);
+    R_BeginPolygon("", DRAWFLAG_NORMAL, true);
     R_PolygonVertex(o,                                  '0 0 0', '0 0 0', a);
     R_PolygonVertex(o + Rotate(arrowY  - borderX, ang), '0 0 0', '0 0 0', a);
     R_PolygonVertex(o + Rotate(borderY - borderX, ang), '0 0 0', '0 0 0', a);
@@ -362,7 +362,7 @@ vector drawspritearrow(vector o, float ang, vector rgb, float a, float t)
     R_PolygonVertex(o + Rotate(arrowY  + borderX, ang), '0 0 0', '0 0 0', a);
     R_EndPolygon();
 
-    R_BeginPolygon("", DRAWFLAG_ADDITIVE);
+    R_BeginPolygon("", DRAWFLAG_ADDITIVE, true);
     R_PolygonVertex(o + Rotate(eY * borderDiag, ang), '0 0 0', rgb, a);
     R_PolygonVertex(o + Rotate(arrowY - arrowX, ang), '0 0 0', rgb, a);
     R_PolygonVertex(o + Rotate(arrowY + arrowX, ang), '0 0 0', rgb, a);
index ee39b18..7c34129 100644 (file)
@@ -160,7 +160,7 @@ void Create_Notification_Entity_Choice(entity notif,
 
 void Dump_Notifications(int fh, bool alsoprint);
 
-GENERIC_COMMAND(dumpnotifs, "Dump all notifications into notifications_dump.txt")
+GENERIC_COMMAND(dumpnotifs, "Dump all notifications into notifications_dump.txt", false)
 {
        switch (request)
        {
@@ -864,8 +864,8 @@ REGISTRY_END(Notifications)
 void ReplicateVars(bool would_destroy)
 {
        if (!would_destroy)
-               FOREACH(Notifications, it.nent_type == MSG_CHOICE, {
-                       string cvarname = sprintf("notification_%s", Get_Notif_CvarName(it));
+               FOREACH(Notifications, it.nent_type == MSG_CHOICE && (!it.nent_teamnum || it.nent_teamnum == NUM_TEAM_1), {
+                       string cvarname = strcat("notification_", Get_Notif_CvarName(it));
                        // NOTE: REPLICATE_SIMPLE can return;
                        REPLICATE_SIMPLE(it.cvar_value, cvarname);
                });
index 8eb2277..9d32cf3 100644 (file)
@@ -54,7 +54,7 @@ int _Movetype_FlyMove(entity this, float dt, bool applygravity, bool applystepno
        if(applygravity)
        {
                this.move_didgravity = 1;
-               grav = dt * (PHYS_ENTGRAVITY(this) ? PHYS_ENTGRAVITY(this) : 1) * PHYS_GRAVITY(this);
+               grav = dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
 
                if(!GAMEPLAYFIX_NOGRAVITYONGROUND || !IS_ONGROUND(this))
                {
@@ -324,10 +324,13 @@ void _Movetype_CheckWaterTransition(entity ent)  // SV_CheckWaterTransition
 
 void _Movetype_Impact(entity this, entity oth)  // SV_Impact
 {
-       if(gettouch(this))
+       if(!this && !oth)
+               return;
+
+       if(this.solid != SOLID_NOT && gettouch(this))
                gettouch(this)(this, oth);
 
-       if(gettouch(oth))
+       if(oth.solid != SOLID_NOT && gettouch(oth))
                gettouch(oth)(oth, this);
 }
 
@@ -414,16 +417,20 @@ bool _Movetype_TestEntityPosition(vector ofs)  // SV_TestEntityPosition
     entity this = _Movetype_TestEntityPosition_ent;
        vector org = this.origin + ofs;
 
-       int cont = this.dphitcontentsmask;
-       this.dphitcontentsmask = DPCONTENTS_SOLID;
+       //int cont = this.dphitcontentsmask;
+       //this.dphitcontentsmask = DPCONTENTS_SOLID;
        tracebox(org, this.mins, this.maxs, org, ((this.move_movetype == MOVETYPE_FLY_WORLDONLY) ? MOVE_WORLDONLY : MOVE_NOMONSTERS), this);
-       this.dphitcontentsmask = cont;
+       //this.dphitcontentsmask = cont;
 
        if(trace_startsolid)
                return true;
 
        if(vdist(trace_endpos - this.origin, >, 0.0001))
-               this.origin = trace_endpos;
+       {
+               tracebox(trace_endpos, this.mins, this.maxs, trace_endpos, MOVE_NOMONSTERS, this);
+               if(!trace_startsolid)
+                       this.origin = trace_endpos;
+       }
        return false;
 }
 
@@ -434,6 +441,7 @@ int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
            return UNSTICK_FINE;
        }
        #define X(v) if (_Movetype_TestEntityPosition(v))
+       X('0  0  -1') X(' 0  0  1')
        X('-1  0  0') X(' 1  0  0')
        X(' 0 -1  0') X(' 0  1  0')
        X('-1 -1  0') X(' 1 -1  0')
@@ -443,7 +451,7 @@ int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
         #define X(i) \
             if (_Movetype_TestEntityPosition('0 0 -1' * i)) \
             if (_Movetype_TestEntityPosition('0 0 1' * i))
-        X(1) X(2) X(3) X(4) X(5) X(6) X(7) X(8)
+        X(2) X(3) X(4) X(5) X(6) X(7) X(8)
         X(9) X(10) X(11) X(12) X(13) X(14) X(15) X(16)
         X(17)
         #undef X
@@ -455,7 +463,7 @@ int _Movetype_UnstickEntity(entity this)  // SV_UnstickEntity
        }
        LOG_DEBUGF("Sucessfully unstuck an entity (edict: %d, classname: %s, origin: %s)",
                etof(this), this.classname, vtos(this.origin));
-       _Movetype_LinkEdict(this, true);
+       _Movetype_LinkEdict(this, false);
        return UNSTICK_FIXED;
 }
 
@@ -526,12 +534,10 @@ bool _Movetype_PushEntity(entity this, vector push, bool failonstartsolid, bool
 
        vector last_origin = this.origin;
 
-       if(dolink)
-               _Movetype_LinkEdict(this, true);
+       _Movetype_LinkEdict(this, dolink);
 
-       if(trace_fraction < 1)
-               if(this.solid >= SOLID_TRIGGER && trace_ent && (!IS_ONGROUND(this) || (this.groundentity != trace_ent)))
-                       _Movetype_Impact(this, trace_ent);
+       if((this.solid >= SOLID_TRIGGER && trace_fraction < 1 && (!IS_ONGROUND(this) || this.groundentity != trace_ent)))
+               _Movetype_Impact(this, trace_ent);
 
        return (this.origin == last_origin); // false if teleported by touch
 }
@@ -657,12 +663,14 @@ void Movetype_Physics_MatchServer(entity this, bool sloppy)
        Movetype_Physics_MatchTicrate(this, TICRATE, sloppy);
 }
 
+// saved .move_*
 .vector tic_origin;
 .vector tic_velocity;
 .int tic_flags;
 .vector tic_avelocity;
 .vector tic_angles;
 
+// saved .*
 .vector tic_saved_origin;
 .vector tic_saved_velocity;
 .int tic_saved_flags;
@@ -670,6 +678,8 @@ void Movetype_Physics_MatchServer(entity this, bool sloppy)
 .vector tic_saved_angles;
 void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Physics_Entity
 {
+       // this hack exists to contain the physics feature
+       // (so entities can place themselves in the world and not need to update .tic_* themselves)
 #define X(s) \
        if(this.(s) != this.tic_saved_##s) \
                this.tic_##s = this.(s)
@@ -681,25 +691,21 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
        X(angles);
 #undef X
 
+       this.flags = this.tic_flags;
+       this.velocity = this.tic_velocity;
+       setorigin(this, this.tic_origin);
+       this.avelocity = this.tic_avelocity;
+       this.angles = this.tic_angles;
+
        if(tr <= 0)
        {
-               this.flags = this.tic_flags;
-               this.velocity = this.tic_velocity;
-               this.origin = this.tic_origin;
-               this.avelocity = this.tic_avelocity;
-               this.angles = this.tic_angles;
                Movetype_Physics_NoMatchServer(this);
-               this.tic_origin = this.origin;
-               this.tic_velocity = this.velocity;
-               this.tic_avelocity = this.avelocity;
-               this.tic_angles = this.angles;
-               this.tic_flags = this.flags;
-
-               this.tic_saved_flags = this.flags;
-               this.tic_saved_velocity = this.velocity;
-               this.tic_saved_origin = this.origin;
-               this.tic_saved_avelocity = this.avelocity;
-               this.tic_saved_angles = this.angles;
+
+               this.tic_saved_flags = this.tic_flags = this.flags;
+               this.tic_saved_velocity = this.tic_velocity = this.velocity;
+               this.tic_saved_origin = this.tic_origin = this.origin;
+               this.tic_saved_avelocity = this.tic_avelocity = this.avelocity;
+               this.tic_saved_angles = this.tic_angles = this.angles;
                return;
        }
 
@@ -712,23 +718,27 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
        if(!this.move_didgravity)
                this.move_didgravity = ((this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS) && !(this.tic_flags & FL_ONGROUND));
 
-       for (int i = 0; i < n; ++i)
+       for (int j = 0; j < n; ++j)
        {
-               this.flags = this.tic_flags;
-               this.velocity = this.tic_velocity;
-               setorigin(this, this.tic_origin);
-               this.avelocity = this.tic_avelocity;
-               this.angles = this.tic_angles;
                _Movetype_Physics_Frame(this, tr);
-               this.tic_origin = this.origin;
-               this.tic_velocity = this.velocity;
-               this.tic_avelocity = this.avelocity;
-               this.tic_angles = this.angles;
-               this.tic_flags = this.flags;
                if(wasfreed(this))
                        return;
        }
 
+       // update the physics fields
+       this.tic_origin = this.origin;
+       this.tic_velocity = this.velocity;
+       this.tic_avelocity = this.avelocity;
+       this.tic_angles = this.angles;
+       this.tic_flags = this.flags;
+
+       // restore their actual values
+       this.flags = this.tic_saved_flags;
+       this.velocity = this.tic_saved_velocity;
+       setorigin(this, this.tic_saved_origin);
+       //this.avelocity = this.tic_saved_avelocity;
+       this.angles = this.tic_saved_angles;
+
        this.avelocity = this.tic_avelocity;
 
        if(dt > 0 && this.move_movetype != MOVETYPE_NONE && !(this.tic_flags & FL_ONGROUND))
@@ -740,7 +750,7 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
                {
                        this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
                            * dt
-                           * (this.gravity ? this.gravity : 1)
+                           * ((this.gravity) ? this.gravity : 1)
                            * PHYS_GRAVITY(this);
                }
 
@@ -752,16 +762,16 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
                }
                else
                {
-                       vector oldorg = this.origin;
-                       this.origin = this.tic_origin;
+                       setorigin(this, this.tic_origin);
                        _Movetype_PushEntityTrace(this, dt * this.velocity);
-                       this.origin = oldorg;
                        if(!trace_startsolid)
                                setorigin(this, trace_endpos);
+                       else
+                               setorigin(this, this.tic_saved_origin);
                }
 
                if(this.move_didgravity > 0 && GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE)
-                       this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
+                       this.velocity_z -= 0.5 * dt * ((this.gravity) ? this.gravity : 1) * PHYS_GRAVITY(this);
        }
        else
        {
@@ -770,6 +780,8 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy)  // SV_Ph
                setorigin(this, this.tic_origin);
        }
 
+       this.flags = this.tic_flags;
+
        this.tic_saved_flags = this.flags;
        this.tic_saved_velocity = this.velocity;
        this.tic_saved_origin = this.origin;
index 51da5e7..0c8bc69 100644 (file)
@@ -19,8 +19,13 @@ const int WATERLEVEL_SUBMERGED = 3;
 #define GAMEPLAYFIX_STEPMULTIPLETIMES(s)    STAT(GAMEPLAYFIX_STEPMULTIPLETIMES)
 #define GAMEPLAYFIX_UNSTICKPLAYERS(s)       STAT(GAMEPLAYFIX_UNSTICKPLAYERS)
 #define GAMEPLAYFIX_WATERTRANSITION(s)                 STAT(GAMEPLAYFIX_WATERTRANSITION)
+#define GAMEPLAYFIX_SLIDEMOVEPROJECTILES(s) STAT(GAMEPLAYFIX_SLIDEMOVEPROJECTILES)
+#define GAMEPLAYFIX_GRENADEBOUNCESLOPES(s)     STAT(GAMEPLAYFIX_GRENADEBOUNCESLOPES)
+#define GAMEPLAYFIX_NOAIRBORNCORPSE(s)                 STAT(GAMEPLAYFIX_NOAIRBORNCORPSE)
+#define NOAIRBORNCORPSE_ALLOWSUSPENDED(s)      STAT(NOAIRBORNCORPSE_ALLOWSUSPENDED)
 #define UPWARD_VELOCITY_CLEARS_ONGROUND(s)  STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND)
 
+
 #define PHYS_STEPHEIGHT(s)                  STAT(MOVEVARS_STEPHEIGHT)
 #define PHYS_NOSTEP(s)                      STAT(NOSTEP)
 #define PHYS_JUMPSTEP(s)                    STAT(MOVEVARS_JUMPSTEP)
index fc3de08..772eb1b 100644 (file)
@@ -2,19 +2,26 @@
 
 void _Movetype_Physics_Toss(entity this, float dt)  // SV_Physics_Toss
 {
-       if (IS_ONGROUND(this))
+       if(IS_ONGROUND(this))
        {
-               if (this.velocity.z >= 1 / 32 && UPWARD_VELOCITY_CLEARS_ONGROUND(this))
+               if(this.velocity.z >= (1 / 32) && UPWARD_VELOCITY_CLEARS_ONGROUND(this))
                {
+                       // don't stick to ground if onground and moving upward
                        UNSET_ONGROUND(this);
                }
-               else if (!this.groundentity)
+               else if(!this.groundentity || !GAMEPLAYFIX_NOAIRBORNCORPSE(this))
                {
                        return;
                }
-               else if (this.move_suspendedinair && wasfreed(this.groundentity))
+               else if(this.move_suspendedinair && wasfreed(this.groundentity))
                {
                        this.groundentity = NULL;
+                       if(NOAIRBORNCORPSE_ALLOWSUSPENDED(this))
+                               return;
+               }
+               else if(boxesoverlap(this.absmin, this.absmax, this.groundentity.absmin, this.groundentity.absmax))
+               {
+                       // don't slide if still touching the groundentity
                        return;
                }
        }
@@ -23,35 +30,37 @@ void _Movetype_Physics_Toss(entity this, float dt)  // SV_Physics_Toss
 
        _Movetype_CheckVelocity(this);
 
-       /*if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
+       if(this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
        {
-               this.move_didgravity = 1;
+               this.move_didgravity = true;
                this.velocity_z -= (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE ? 0.5 : 1)
                    * dt
-                   * (this.gravity ? this.gravity : 1)
+                   * ((this.gravity) ? this.gravity : 1)
                    * PHYS_GRAVITY(this);
-       }*/
+       }
 
-       if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
+       /*if (this.move_movetype == MOVETYPE_BOUNCE || this.move_movetype == MOVETYPE_TOSS)
        {
                this.move_didgravity = true;
                this.velocity_z -= (((this.gravity) ? this.gravity : 1) * PHYS_GRAVITY(this) * dt);
-       }
+       }*/
 
        this.angles = this.angles + this.avelocity * dt;
 
        float movetime = dt;
-       for (int bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; ++bump)
+       for (int bump = 0; bump < MAX_CLIP_PLANES && movetime > 0; bump++)
        {
                vector move = this.velocity * movetime;
-               _Movetype_PushEntity(this, move, true, false);
+               if(!_Movetype_PushEntity(this, move, true, true))
+                       return;
                if (wasfreed(this))
                        return;
 
                if (trace_startsolid)
                {
                        _Movetype_UnstickEntity(this);
-                       _Movetype_PushEntity(this, move, false, false);
+                       if(!_Movetype_PushEntity(this, move, true, true))
+                               return;
                        if (wasfreed(this))
                                return;
                }
@@ -63,28 +72,36 @@ void _Movetype_Physics_Toss(entity this, float dt)  // SV_Physics_Toss
 
                if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
                {
-                       this.velocity = _Movetype_ClipVelocity(this.velocity, trace_plane_normal, 2.0);
+                       float bouncefac = (!this.bouncefactor) ? 1.0 : this.bouncefactor;
+                       this.velocity = _Movetype_ClipVelocity(this.velocity, trace_plane_normal, 1 + bouncefac);
                        UNSET_ONGROUND(this);
+                       if(!GAMEPLAYFIX_SLIDEMOVEPROJECTILES(this))
+                               movetime = 0;
                }
                else if (this.move_movetype == MOVETYPE_BOUNCE)
                {
-                       float bouncefac = this.bouncefactor;     if (!bouncefac)  bouncefac = 0.5;
-                       float bstop = this.bouncestop; if (!bstop) bstop = 60 / 800;
-                       bstop *= (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
+                       float bouncefac = (!this.bouncefactor) ? 0.5 : this.bouncefactor;
+                       float bstop = (!this.bouncestop) ? (60 / 800) : this.bouncestop;
+                       float grav = ((this.gravity) ? this.gravity : 1);
 
                        this.velocity = _Movetype_ClipVelocity(this.velocity, trace_plane_normal, 1 + bouncefac);
 
                        float d = trace_plane_normal * this.velocity;
-                       if (trace_plane_normal.z > 0.7 && d < bstop && d > -bstop)
+                       if(!GAMEPLAYFIX_GRENADEBOUNCESLOPES(this))
+                               d = this.velocity.z;
+                       if (trace_plane_normal.z > 0.7 && d < PHYS_GRAVITY(this) * bstop * grav)
                        {
                                SET_ONGROUND(this);
                                this.groundentity = trace_ent;
                                this.velocity = '0 0 0';
                                this.avelocity = '0 0 0';
+                               movetime = 0;
                        }
                        else
                        {
                                UNSET_ONGROUND(this);
+                               if(!GAMEPLAYFIX_SLIDEMOVEPROJECTILES(this))
+                                       movetime = 0;
                        }
                }
                else
@@ -98,24 +115,27 @@ void _Movetype_Physics_Toss(entity this, float dt)  // SV_Physics_Toss
                                        this.move_suspendedinair = true;
                                this.velocity = '0 0 0';
                                this.avelocity = '0 0 0';
+                               movetime = 0;
                        }
                        else
                        {
                                UNSET_ONGROUND(this);
+                               if(!GAMEPLAYFIX_SLIDEMOVEPROJECTILES(this))
+                                       movetime = 0;
                        }
                }
 
                // DP revision 8905 (just, WHY...)
-               if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
-                       break;
+               //if (this.move_movetype == MOVETYPE_BOUNCEMISSILE)
+                       //break;
 
                // DP revision 8918 (WHY...)
-               if (IS_ONGROUND(this))
-                       break;
+               //if (IS_ONGROUND(this))
+                       //break;
        }
 
-       //if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE && this.move_didgravity > 0 && !IS_ONGROUND(this))
-       //      this.velocity_z -= 0.5 * dt * (this.gravity ? this.gravity : 1) * PHYS_GRAVITY(this);
+       if (GAMEPLAYFIX_GRAVITYUNAFFECTEDBYTICRATE && this.move_didgravity > 0 && !IS_ONGROUND(this))
+               this.velocity_z -= 0.5 * dt * ((this.gravity) ? this.gravity : 1) * PHYS_GRAVITY(this);
 
        _Movetype_CheckWaterTransition(this);
 }
index 5ba6e82..16cb27a 100644 (file)
@@ -53,13 +53,13 @@ void Physics_UpdateStats(entity this)
             : 0;
           STAT(MOVEVARS_AIRSPEEDLIMIT_NONQW, this) = Physics_ClientOption(this, "airspeedlimit_nonqw", autocvar_sv_airspeedlimit_nonqw) * maxspd_mod;
         }
-       bool vq3compat = autocvar_sv_vq3compat && autocvar_sv_vq3compat_changehitbox; // NOTE: these hitboxes are off by 1 due to engine differences
-       STAT(PL_MIN, this) = (vq3compat) ? '-15 -15 -24' : autocvar_sv_player_mins;
-       STAT(PL_MAX, this) = (vq3compat) ? '15 15 32' : autocvar_sv_player_maxs;
-       STAT(PL_VIEW_OFS, this) = (vq3compat) ? '0 0 26' : autocvar_sv_player_viewoffset;
-       STAT(PL_CROUCH_MIN, this) = (vq3compat) ? '-15 -15 -24' : autocvar_sv_player_crouch_mins;
-       STAT(PL_CROUCH_MAX, this) = (vq3compat) ? '15 15 16' : autocvar_sv_player_crouch_maxs;
-       STAT(PL_CROUCH_VIEW_OFS, this) = (vq3compat) ? '0 0 12' : autocvar_sv_player_crouch_viewoffset;
+       bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox; // NOTE: these hitboxes are off by 1 due to engine differences
+       STAT(PL_MIN, this) = (q3dfcompat) ? '-15 -15 -20' : autocvar_sv_player_mins;
+       STAT(PL_MAX, this) = (q3dfcompat) ? '15 15 36' : autocvar_sv_player_maxs;
+       STAT(PL_VIEW_OFS, this) = (q3dfcompat) ? '0 0 26' : autocvar_sv_player_viewoffset;
+       STAT(PL_CROUCH_MIN, this) = (q3dfcompat) ? '-15 -15 -20' : autocvar_sv_player_crouch_mins;
+       STAT(PL_CROUCH_MAX, this) = (q3dfcompat) ? '15 15 20' : autocvar_sv_player_crouch_maxs;
+       STAT(PL_CROUCH_VIEW_OFS, this) = (q3dfcompat) ? '0 0 12' : autocvar_sv_player_crouch_viewoffset;
 
        // old stats
        // fix some new settings
@@ -145,6 +145,9 @@ void PM_ClientMovement_UpdateStatus(entity this)
                do_crouch = false;
     }
 
+    MUTATOR_CALLHOOK(PlayerCanCrouch, this, do_crouch);
+    do_crouch = M_ARGV(1, bool);
+
        if (do_crouch) {
                if (!IS_DUCKED(this)) {
                        SET_DUCKED(this);
@@ -687,13 +690,12 @@ void PM_check_slick(entity this)
        if(!IS_ONGROUND(this))
                return;
 
-       if(!PHYS_SLICK_APPLYGRAVITY(this))
-               return;
-
+       trace_dphitq3surfaceflags = 0;
        tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
        if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK)
        {
-               UNSET_ONGROUND(this);
+               if(PHYS_SLICK_APPLYGRAVITY(this))
+                       UNSET_ONGROUND(this);
                SET_ONSLICK(this);
        }
        else
index cf272e5..511ac46 100644 (file)
@@ -490,6 +490,21 @@ void PlayerStats_PlayerBasic(entity joiningplayer, float newrequest)
        }
 }
 
+SHUTDOWN(PlayerStats_PlayerBasic_Shutdown)
+{
+       if(PS_B_IN_DB >= 0)
+       {
+               db_close(PS_B_IN_DB);
+               PS_B_IN_DB = -1;
+       }
+
+       if(PS_GR_OUT_DB >= 0)
+       {
+               db_close(PS_GR_OUT_DB);
+               PS_GR_OUT_DB = -1;
+       }
+}
+
 void PlayerStats_PlayerBasic_CheckUpdate(entity joiningplayer)
 {
        // determine whether we should retrieve playerbasic information again
index d27dd0e..d41a097 100644 (file)
@@ -4,7 +4,7 @@
 //float PS_PM_IN_DB = -1;   // playerstats_prematch_in_db      // db for info COLLECTED at the beginning of a match
 int PS_GR_OUT_DB = -1;  // playerstats_gamereport_out_db   // db of info SENT at the end of a match
 //float PS_GR_IN_DB = -1;   // playerstats_gamereport_in_db    // db for info COLLECTED at the end of a match
-int PS_B_IN_DB = -1;    // playerstats_playerbasic_in_db   // db for info COLLECTED for basic player info (ELO)
+float PS_B_IN_DB = -1;    // playerstats_playerbasic_in_db   // db for info COLLECTED for basic player info (ELO)
 #endif
 
 #ifdef MENUQC
index 488d442..7d2aae5 100644 (file)
@@ -193,6 +193,10 @@ int autocvar_sv_gameplayfix_stepdown = 2;
 int autocvar_sv_gameplayfix_stepmultipletimes = 1;
 int autocvar_sv_gameplayfix_unstickplayers = 1;
 int autocvar_sv_gameplayfix_fixedcheckwatertransition = 1;
+int autocvar_sv_gameplayfix_slidemoveprojectiles = 1;
+int autocvar_sv_gameplayfix_grenadebouncedownslopes = 1;
+int autocvar_sv_gameplayfix_noairborncorpse = 1;
+int autocvar_sv_gameplayfix_noairborncorpse_allowsuspendeditems = 1;
 #endif
 REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, autocvar_sv_gameplayfix_downtracesupportsongroundflag)
 REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, autocvar_sv_gameplayfix_easierwaterjump)
@@ -201,6 +205,10 @@ REGISTER_STAT(GAMEPLAYFIX_STEPMULTIPLETIMES, int, autocvar_sv_gameplayfix_stepmu
 REGISTER_STAT(GAMEPLAYFIX_UNSTICKPLAYERS, int, autocvar_sv_gameplayfix_unstickplayers)
 REGISTER_STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND, int, autocvar_sv_gameplayfix_upwardvelocityclearsongroundflag)
 REGISTER_STAT(GAMEPLAYFIX_WATERTRANSITION, int, autocvar_sv_gameplayfix_fixedcheckwatertransition)
+REGISTER_STAT(GAMEPLAYFIX_SLIDEMOVEPROJECTILES, int, autocvar_sv_gameplayfix_slidemoveprojectiles)
+REGISTER_STAT(GAMEPLAYFIX_GRENADEBOUNCESLOPES, int, autocvar_sv_gameplayfix_grenadebouncedownslopes)
+REGISTER_STAT(GAMEPLAYFIX_NOAIRBORNCORPSE, int, autocvar_sv_gameplayfix_noairborncorpse)
+REGISTER_STAT(NOAIRBORNCORPSE_ALLOWSUSPENDED, int, autocvar_sv_gameplayfix_noairborncorpse_allowsuspendeditems)
 
 REGISTER_STAT(MOVEVARS_JUMPSTEP, int, cvar("sv_jumpstep"))
 REGISTER_STAT(NOSTEP, int, cvar("sv_nostep"))
@@ -280,6 +288,11 @@ REGISTER_STAT(WALLJUMP_DELAY, float, autocvar_g_walljump_delay)
 REGISTER_STAT(WALLJUMP_FORCE, float, autocvar_g_walljump_force)
 REGISTER_STAT(LASTWJ, float)
 
+#ifdef SVQC
+float autocvar_g_bloodloss;
+#endif
+REGISTER_STAT(BLOODLOSS, float, autocvar_g_bloodloss)
+
 // freeze tag, clan arena
 REGISTER_STAT(REDALIVE, int)
 REGISTER_STAT(BLUEALIVE, int)
@@ -306,9 +319,9 @@ bool autocvar_sv_slick_applygravity;
 REGISTER_STAT(SLICK_APPLYGRAVITY, bool, autocvar_sv_slick_applygravity)
 
 #ifdef SVQC
-bool autocvar_sv_vq3compat;
+bool autocvar_sv_q3defragcompat;
 #endif
-REGISTER_STAT(VQ3COMPAT, bool, autocvar_sv_vq3compat)
+REGISTER_STAT(Q3DEFRAGCOMPAT, bool, autocvar_sv_q3defragcompat)
 
 #ifdef SVQC
 #include "physics/movetypes/movetypes.qh"
index 3d0528a..9dedc89 100644 (file)
@@ -57,7 +57,7 @@ REGISTRY_CHECK(Turrets)
        #define TR_CONFIG_END()
 #endif
 
-GENERIC_COMMAND(dumpturrets, "Dump all turrets into turrets_dump.txt")
+GENERIC_COMMAND(dumpturrets, "Dump all turrets into turrets_dump.txt", false)
 {
     switch(request)
     {
index d9b9efc..3b75130 100644 (file)
@@ -444,7 +444,7 @@ STATIC_INIT(compressShortVector)
                l *= f;
        }
 
-       if(cvar("developer"))
+       if(cvar("developer") > 0)
        {
                LOG_TRACE("Verifying vector compression table...");
                for(i = 0x0F00; i < 0xFFFF; ++i)
index 6785a9f..111c7e7 100644 (file)
@@ -245,7 +245,7 @@ void vehicles_projectile_explode_use(entity this, entity actor, entity trigger)
        vehicles_projectile_explode(this, trigger);
 }
 
-entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound,
+entity vehicles_projectile(entity this, entity _mzlfx, Sound _mzlsound,
                                                   vector _org, vector _vel,
                                                   float _dmg, float _radi, float _force,  float _size,
                                                   int _deahtype, float _projtype, float _health,
@@ -290,8 +290,8 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound,
        if(_mzlsound != SND_Null)
                sound (this, CH_WEAPON_A, _mzlsound, VOL_BASE, ATTEN_NORM);
 
-       if(_mzlfx)
-               Send_Effect_(_mzlfx, proj.origin, proj.velocity, 1);
+       if(_mzlfx != EFFECT_Null)
+               Send_Effect(_mzlfx, proj.origin, proj.velocity, 1);
 
        setsize (proj, '-1 -1 -1' * _size, '1 1 1' * _size);
 
index 9299e93..81fd93a 100644 (file)
@@ -9,7 +9,7 @@ REGISTER_NET_LINKED(ENT_CLIENT_BUMBLE_RAYGUN)
 void bumblebee_fire_cannon(entity this, entity _gun, string _tagname, entity _owner)
 {
     vector v = gettaginfo(_gun, gettagindex(_gun, _tagname));
-    vehicles_projectile(this, EFFECT_BIGPLASMA_MUZZLEFLASH.eent_eff_name, SND_VEH_BUMBLEBEE_FIRE,
+    vehicles_projectile(this, EFFECT_BIGPLASMA_MUZZLEFLASH, SND_VEH_BUMBLEBEE_FIRE,
                         v, normalize(v_forward + randomvec() * autocvar_g_vehicle_bumblebee_cannon_spread) * autocvar_g_vehicle_bumblebee_cannon_speed,
                         autocvar_g_vehicle_bumblebee_cannon_damage, autocvar_g_vehicle_bumblebee_cannon_radius, autocvar_g_vehicle_bumblebee_cannon_force,  0,
                         DEATH_VH_BUMB_GUN.m_id, PROJECTILE_BUMBLE_GUN, 0, true, true, _owner);
index e2a2593..8780458 100644 (file)
@@ -291,15 +291,6 @@ bool racer_frame(entity this, float dt)
        if (PHYS_INPUT_BUTTON_ATCK(player))
        if (wep1.wr_checkammo1(wep1, vehic, weaponentity))
        {
-               string tagname = (vehic.cnt)
-                   ? (vehic.cnt = 0, "tag_fire1")
-                   : (vehic.cnt = 1, "tag_fire2");
-               vector org = gettaginfo(vehic, gettagindex(vehic, tagname));
-               w_shotorg = org;
-               w_shotdir = v_forward;
-               // Fix z-aim (for chase mode)
-               crosshair_trace(player);
-               w_shotdir.z = normalize(trace_endpos - org).z * 0.5;
                wep1.wr_think(wep1, vehic, weaponentity, 1);
        }
 
index 0e7222e..f7253d8 100644 (file)
@@ -14,10 +14,20 @@ METHOD(RacerAttack, wr_think, void(entity thiswep, entity actor, .entity weapone
             veh.vehicle_energy -= autocvar_g_vehicle_racer_cannon_cost;
             veh.wait = time;
         }
+        string tagname = (veh.cnt)
+            ? (veh.cnt = 0, "tag_fire1")
+            : (veh.cnt = 1, "tag_fire2");
+        vector shotorg = gettaginfo(veh, gettagindex(veh, tagname));
+        w_shotorg = shotorg;
+        w_shotdir = v_forward;
+        // Fix z-aim (for chase mode)
+        crosshair_trace(player);
+        w_shotdir.z = normalize(trace_endpos - shotorg).z * 0.5;
+
         if (isPlayer) W_SetupShot_Dir(player, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0, DEATH_VH_WAKI_GUN.m_id);
         vector org = w_shotorg;
         vector dir = w_shotdir;
-        entity bolt = vehicles_projectile(veh, EFFECT_RACER_MUZZLEFLASH.eent_eff_name, SND_LASERGUN_FIRE,
+        entity bolt = vehicles_projectile(veh, EFFECT_RACER_MUZZLEFLASH, SND_LASERGUN_FIRE,
                                org, normalize(v_forward + randomvec() * autocvar_g_vehicle_racer_cannon_spread) * autocvar_g_vehicle_racer_cannon_speed,
                                autocvar_g_vehicle_racer_cannon_damage, autocvar_g_vehicle_racer_cannon_radius, autocvar_g_vehicle_racer_cannon_force,  0,
                                DEATH_VH_WAKI_GUN.m_id, PROJECTILE_WAKICANNON, 0, true, true, player);
@@ -45,7 +55,7 @@ void racer_rocket_groundhugger(entity this);
 
 void racer_fire_rocket(entity player, vector org, vector dir, entity trg)
 {
-    entity rocket = vehicles_projectile(player.vehicle, EFFECT_RACER_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
+    entity rocket = vehicles_projectile(player.vehicle, EFFECT_RACER_ROCKETLAUNCH, SND_ROCKET_FIRE,
                            org, dir * autocvar_g_vehicle_racer_rocket_speed,
                            autocvar_g_vehicle_racer_rocket_damage, autocvar_g_vehicle_racer_rocket_radius, autocvar_g_vehicle_racer_rocket_force, 3,
                            DEATH_VH_WAKI_ROCKET.m_id, PROJECTILE_WAKIROCKET, 20, false, false, player);
index e9f7f73..f0c4dc1 100644 (file)
@@ -453,7 +453,7 @@ bool raptor_takeoff(entity this, float dt)
        // Takeoff sequense
        if(vehic.frame < 25)
        {
-               vehic.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / PHYS_INPUT_FRAMETIME);
+               vehic.frame += 25 / (autocvar_g_vehicle_raptor_takeofftime / dt);
                vehic.velocity_z = min(vehic.velocity_z * 1.5, 256);
                vehic.bomb1.gun1.avelocity_y = 90 + ((vehic.frame / 25) * 25000);
                vehic.bomb1.gun2.avelocity_y = -vehic.bomb1.gun1.avelocity_y;
index 66b5bec..7d4a250 100644 (file)
@@ -7,7 +7,7 @@ METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, .entity weapon
     entity player = isPlayer ? actor : actor.owner;
     entity veh = player.vehicle;
     // 1 [wait] 1 [wait] 2 [wait] 2 [wait] [wait]
-    float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + veh.misc_bulletcounter == 4);
+    float t = autocvar_g_vehicle_raptor_cannon_refire * (1 + ((veh.misc_bulletcounter + 1) >= 4));
     if (fire & 1)
     if (weapon_prepareattack(thiswep, player, weaponentity, false, t)) {
         if (isPlayer) W_SetupShot_Dir(player, weaponentity, v_forward, false, 0, SND_Null, CH_WEAPON_B, 0, DEATH_VH_RAPT_CANNON.m_id);
@@ -16,12 +16,12 @@ METHOD(RaptorCannon, wr_think, void(entity thiswep, entity actor, .entity weapon
         if (veh) {
             veh.misc_bulletcounter += 1;
             org = (veh.misc_bulletcounter <= 2) ? gettaginfo(veh.gun1, gettagindex(veh.gun1, "fire1"))
-              : (((veh.misc_bulletcounter == 4) ? veh.misc_bulletcounter = 0 : 0), gettaginfo(veh.gun2, gettagindex(veh.gun2, "fire1")));
+              : (((veh.misc_bulletcounter >= 4) ? veh.misc_bulletcounter = 0 : 0), gettaginfo(veh.gun2, gettagindex(veh.gun2, "fire1")));
             dir = v_forward;
             veh.vehicle_energy -= autocvar_g_vehicle_raptor_cannon_cost;
             actor.cnt = time;
         }
-        vehicles_projectile(veh, EFFECT_RAPTOR_MUZZLEFLASH.eent_eff_name, SND_LASERGUN_FIRE,
+        vehicles_projectile(veh, EFFECT_RAPTOR_MUZZLEFLASH, SND_LASERGUN_FIRE,
                                org, normalize(dir + randomvec() * autocvar_g_vehicle_raptor_cannon_spread) * autocvar_g_vehicle_raptor_cannon_speed,
                                autocvar_g_vehicle_raptor_cannon_damage, autocvar_g_vehicle_raptor_cannon_radius, autocvar_g_vehicle_raptor_cannon_force,  0,
                                DEATH_VH_RAPT_CANNON.m_id, PROJECTILE_RAPTORCANNON, 0, true, true, player);
@@ -59,6 +59,8 @@ METHOD(RaptorFlare, wr_think, void(entity thiswep, entity actor, .entity weapone
     entity veh = player.vehicle;
     if (fire & 2)
     if (!isPlayer || weapon_prepareattack(thiswep, player, weaponentity, true, autocvar_g_vehicle_raptor_flare_refire)) {
+        vector forward, right, up;
+        MAKE_VECTORS(player.v_angle, forward, right, up);
         for(int i = 0; i < 3; ++i) {
             entity _flare = spawn();
             setmodel(_flare, MDL_VEH_RAPTOR_FLARE);
@@ -67,7 +69,7 @@ METHOD(RaptorFlare, wr_think, void(entity thiswep, entity actor, .entity weapone
             setorigin(_flare, actor.origin - '0 0 16');
             set_movetype(_flare, MOVETYPE_TOSS);
             _flare.gravity = 0.15;
-            _flare.velocity = 0.25 * actor.velocity + (v_forward + randomvec() * 0.25)* -500;
+            _flare.velocity = 0.25 * actor.velocity + (forward + randomvec() * 0.25)* -500;
             setthink(_flare, raptor_flare_think);
             _flare.nextthink = time;
             _flare.owner = veh ? veh : player;
index 37b87bb..c762acf 100644 (file)
@@ -30,7 +30,7 @@ REGISTER_WEAPON(RAPTOR_FLARE, NEW(RaptorFlare));
 float autocvar_g_vehicle_raptor_cannon_cost = 1;
 float autocvar_g_vehicle_raptor_cannon_damage = 10;
 float autocvar_g_vehicle_raptor_cannon_radius = 60;
-float autocvar_g_vehicle_raptor_cannon_refire = 0.03;
+float autocvar_g_vehicle_raptor_cannon_refire = 0.033333;
 float autocvar_g_vehicle_raptor_cannon_speed = 24000;
 float autocvar_g_vehicle_raptor_cannon_spread = 0.01;
 float autocvar_g_vehicle_raptor_cannon_force = 25;
index 308a92f..fdeddc4 100644 (file)
@@ -183,7 +183,7 @@ void spiderbot_rocket_do(entity this)
     switch(STAT(VEHICLESTAT_W2MODE, this))
     {
         case SBRM_VOLLY:
-            rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
+            rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, SND_ROCKET_FIRE,
                                    v, normalize(randomvec() * autocvar_g_vehicle_spiderbot_rocket_spread + v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
                                    autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
                                    DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner);
@@ -197,7 +197,7 @@ void spiderbot_rocket_do(entity this)
                 this.wait = -10;
             break;
         case SBRM_GUIDE:
-            rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
+            rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, SND_ROCKET_FIRE,
                                    v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
                                    autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
                                    DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, false, this.owner);
@@ -209,7 +209,7 @@ void spiderbot_rocket_do(entity this)
 
         break;
         case SBRM_ARTILLERY:
-            rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH.eent_eff_name, SND_ROCKET_FIRE,
+            rocket = vehicles_projectile(this, EFFECT_SPIDERBOT_ROCKETLAUNCH, SND_ROCKET_FIRE,
                                    v, normalize(v_forward) * autocvar_g_vehicle_spiderbot_rocket_speed,
                                    autocvar_g_vehicle_spiderbot_rocket_damage, autocvar_g_vehicle_spiderbot_rocket_radius, autocvar_g_vehicle_spiderbot_rocket_force, 1,
                                    DEATH_VH_SPID_ROCKET.m_id, PROJECTILE_SPIDERROCKET, autocvar_g_vehicle_spiderbot_rocket_health, false, true, this.owner);
index f2fdf44..b8d2428 100644 (file)
@@ -225,6 +225,20 @@ string GetAmmoPicture(int ammotype)
        }
 }
 
+string GetAmmoName(int ammotype)
+{
+       switch (ammotype)
+       {
+               case RES_SHELLS:  return ITEM_Shells.m_name;
+               case RES_BULLETS: return ITEM_Bullets.m_name;
+               case RES_ROCKETS: return ITEM_Rockets.m_name;
+               case RES_CELLS:   return ITEM_Cells.m_name;
+               case RES_PLASMA:  return ITEM_Plasma.m_name;
+               case RES_FUEL:    return ITEM_JetpackFuel.m_name;
+               default:          return "batteries";
+       }
+}
+
 #ifdef CSQC
 int GetAmmoTypeFromNum(int i)
 {
@@ -551,14 +565,27 @@ REGISTER_NET_TEMP(wframe)
 #ifdef CSQC
 NET_HANDLE(wframe, bool isNew)
 {
-       vector a = ReadVector();
+       int fr = ReadByte();
+       float t = ReadFloat();
     int slot = ReadByte();
        bool restartanim = ReadByte();
        entity wepent = viewmodels[slot];
-       if(a.x == wepent.anim_idle_x) // we don't need to enforce idle animation
-               wepent.animstate_looping = false;
+       if(fr == WFRAME_IDLE)
+               wepent.animstate_looping = false; // we don't need to enforce idle animation
        else
+       {
+               vector a = '0 0 0';
+               switch(fr)
+               {
+                       case WFRAME_IDLE: a = wepent.anim_idle; break;
+                       case WFRAME_FIRE1: a = wepent.anim_fire1; break;
+                       case WFRAME_FIRE2: a = wepent.anim_fire2; break;
+                       default:
+                       case WFRAME_RELOAD: a = wepent.anim_reload; break;
+               }
+               a.z *= t;
                anim_set(wepent, a, !restartanim, restartanim, restartanim);
+       }
        wepent.state = ReadByte();
        wepent.weapon_nextthink = ReadFloat();
        switch (wepent.state)
@@ -578,13 +605,14 @@ NET_HANDLE(wframe, bool isNew)
 #endif
 
 #ifdef SVQC
-void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim)
+void wframe_send(entity actor, entity weaponentity, int wepframe, float attackrate, bool restartanim)
 {
        if (!IS_REAL_CLIENT(actor)) return;
        int channel = MSG_ONE;
        msg_entity = actor;
        WriteHeader(channel, wframe);
-       WriteVector(channel, a);
+       WriteByte(channel, wepframe);
+       WriteFloat(channel, attackrate);
        WriteByte(channel, weaponslot(weaponentity.weaponentity_fld));
        WriteByte(channel, restartanim);
        WriteByte(channel, weaponentity.state);
index 0be413f..26b4008 100644 (file)
@@ -38,7 +38,7 @@ STATIC_INIT(WeaponPickup) { FOREACH(Weapons, true, it.m_pickup = NEW(WeaponPicku
 #define WepSet_FromWeapon(it) ((it).m_wepset)
 WepSet _WepSet_FromWeapon(int i);
 
-GENERIC_COMMAND(dumpweapons, "Dump all weapons into weapons_dump.txt") // WEAPONTODO: make this work with other progs than just server
+GENERIC_COMMAND(dumpweapons, "Dump all weapons into weapons_dump.txt", false) // WEAPONTODO: make this work with other progs than just server
 {
     switch(request)
     {
@@ -392,6 +392,6 @@ REPLICATE(cvar_cl_accuracy_data_receive, bool, "cl_accuracy_data_receive");
 #endif
 
 #ifdef SVQC
-void wframe_send(entity actor, entity weaponentity, vector a, bool restartanim);
+void wframe_send(entity actor, entity weaponentity, int wepframe, float attackrate, bool restartanim);
 #endif
 #endif
index 3dd2a80..02fbdb5 100644 (file)
@@ -216,6 +216,8 @@ WepSet W_RandomWeapons(entity e, WepSet remaining, int n);
 
 string GetAmmoPicture(int ammotype);
 
+string GetAmmoName(int ammotype);
+
 #ifdef CSQC
 int GetAmmoTypeFromNum(int i);
 int GetAmmoStat(int ammotype);
index 5948d6a..ae2dbf0 100644 (file)
@@ -809,7 +809,7 @@ void Draw_ArcBeam_callback(vector start, vector hit, vector end)
                Draw_CylindricLine(start, end, thickness, beam.beam_image, 0.25, -time * 3, beam.beam_color, beam.beam_alpha, DRAWFLAG_NORMAL, transformed_view_org);
        else
        {
-               R_BeginPolygon(beam.beam_image, DRAWFLAG_NORMAL); // DRAWFLAG_ADDITIVE
+               R_BeginPolygon(beam.beam_image, DRAWFLAG_NORMAL, false); // DRAWFLAG_ADDITIVE
                R_PolygonVertex(
                        top,
                        '0 0.5 0' + ('0 0.5 0' * (thickness / beam.beam_thickness)),
@@ -892,10 +892,9 @@ void Draw_ArcBeam(entity this)
                // into a weapon system for client code.
 
                // find where we are aiming
-               makevectors(((autocvar_chase_active) ? warpzone_save_view_angles : view_angles));
-               vector forward = v_forward;
-               vector right = v_right;
-               vector up = v_up;
+               vector myviewangle = ((autocvar_chase_active) ? warpzone_save_view_angles : view_angles);
+               vector forward, right, up;
+               MAKE_VECTORS(myviewangle, forward, right, up);
                entity wepent = viewmodels[this.beam_slot];
 
                if(autocvar_chase_active)
@@ -911,11 +910,6 @@ void Draw_ArcBeam(entity this)
                else
                        { start_pos = this.origin; }
 
-               int v_shot_idx;  // used later
-               (v_shot_idx = gettagindex(wepent, "shot")) || (v_shot_idx = gettagindex(wepent, "tag_shot"));
-               if(v_shot_idx && this.beam_usevieworigin == 2)
-                       start_pos = gettaginfo(wepent, v_shot_idx) - '0 0 2';
-
                // trace forward with an estimation
                WarpZone_TraceLine(
                        start_pos,
@@ -924,6 +918,11 @@ void Draw_ArcBeam(entity this)
                        this
                );
 
+               int v_shot_idx;  // used later
+               (v_shot_idx = gettagindex(wepent, "shot")) || (v_shot_idx = gettagindex(wepent, "tag_shot"));
+               if(v_shot_idx && this.beam_usevieworigin == 2)
+                       start_pos = gettaginfo(wepent, v_shot_idx) - '0 0 2';
+
                // untransform in case our trace went through a warpzone
                vector end_pos = WarpZone_UnTransformOrigin(WarpZone_trace_transform, trace_endpos);
 
@@ -956,6 +955,8 @@ void Draw_ArcBeam(entity this)
                {
                        this.beam_dir = wantdir;
                        this.beam_initialized = true;
+