From: Mario Date: Tue, 21 Jan 2020 19:24:22 +0000 (+1000) Subject: Merge branch 'master' into Mario/qcphysics X-Git-Tag: xonotic-v0.8.5~1161^2^2~1 X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=b8880819e333ef558143ae80afcdb339b907a439;hp=bac31b218e747443d2e4c1f8d6b26b2bb71dddb8 Merge branch 'master' into Mario/qcphysics --- diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8724d06617..3e56730463 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -29,7 +29,7 @@ test_sv_game: - wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints - wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache - make - - EXPECT=892e447048e051e51f30cff2affc729a + - EXPECT=d5bda479d65190330f6ee23c6f9aa5e7 - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg | tee /dev/stderr | grep '^:' diff --git a/.tx/merge-base b/.tx/merge-base index df5f27c1ba..7a7217d257 100644 --- a/.tx/merge-base +++ b/.tx/merge-base @@ -1 +1 @@ -Sat Dec 28 07:24:50 CET 2019 +Wed Jan 15 07:24:54 CET 2020 diff --git a/_hud_common.cfg b/_hud_common.cfg index c860be99ce..0479f389be 100644 --- a/_hud_common.cfg +++ b/_hud_common.cfg @@ -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" diff --git a/_hud_descriptions.cfg b/_hud_descriptions.cfg index 6e393e6a57..30e5a8bee9 100644 --- a/_hud_descriptions.cfg +++ b/_hud_descriptions.cfg @@ -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" diff --git a/bal-wep-mario.cfg b/bal-wep-mario.cfg index d3270acc83..5cfa34882b 100644 --- a/bal-wep-mario.cfg +++ b/bal-wep-mario.cfg @@ -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 diff --git a/bal-wep-nexuiz25.cfg b/bal-wep-nexuiz25.cfg index c9d87fd057..f9659814b3 100644 --- a/bal-wep-nexuiz25.cfg +++ b/bal-wep-nexuiz25.cfg @@ -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 diff --git a/bal-wep-samual.cfg b/bal-wep-samual.cfg index e32b54ff4b..6896f5f5e0 100644 --- a/bal-wep-samual.cfg +++ b/bal-wep-samual.cfg @@ -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 diff --git a/bal-wep-testing.cfg b/bal-wep-testing.cfg index ff90629489..abee0b6df7 100644 --- a/bal-wep-testing.cfg +++ b/bal-wep-testing.cfg @@ -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 diff --git a/bal-wep-xdf.cfg b/bal-wep-xdf.cfg index 1fe4044cab..ec8029c74b 100644 --- a/bal-wep-xdf.cfg +++ b/bal-wep-xdf.cfg @@ -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 diff --git a/bal-wep-xonotic.cfg b/bal-wep-xonotic.cfg index 52d63dfa2b..c38ea832f3 100644 --- a/bal-wep-xonotic.cfg +++ b/bal-wep-xonotic.cfg @@ -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 diff --git a/common.ru.po b/common.ru.po index d281638658..4c19cfd4e3 100644 --- a/common.ru.po +++ b/common.ru.po @@ -6,7 +6,7 @@ # adem4ik, 2014 # Alex Talker , 2014-2015 # Andrei Stepanov, 2014 -# Andrei Stepanov , 2014-2019 +# Andrei Stepanov , 2014-2020 # Andrey P , 2016 # Artem Vorotnikov , 2015 # Lord Canistra , 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 \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 "Секунд осталось: %d" +msgstr "Осталось секунд: %d" #: qcsrc/client/mapvoting.qc:505 msgid "mv_mapdownload: ^3You're not supposed to use this command on your own!" diff --git a/gamemodes-server.cfg b/gamemodes-server.cfg index cd71ecec0e..501f07f035 100644 --- a/gamemodes-server.cfg +++ b/gamemodes-server.cfg @@ -247,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 @@ -309,7 +311,7 @@ set g_ctf_flag_neutral_model "models/ctf/flags.md3" set g_ctf_flag_neutral_skin 4 set g_ctf_flag_glowtrails 1 set g_ctf_fullbrightflags 0 -set g_ctf_dynamiclights 0 +set g_ctf_dynamiclights 0 "flags (not flag carriers) cast light of their team's colour" set g_ctf_ignore_frags 0 "1: regular frags give no points" exec ctfscoring-samual.cfg diff --git a/hud_luma.cfg b/hud_luma.cfg index d815142512..813ecbaef0 100644 --- a/hud_luma.cfg +++ b/hud_luma.cfg @@ -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" diff --git a/hud_luminos.cfg b/hud_luminos.cfg index 8766bcb248..c5cfe4ac54 100644 --- a/hud_luminos.cfg +++ b/hud_luminos.cfg @@ -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" diff --git a/hud_luminos_minimal.cfg b/hud_luminos_minimal.cfg index 02940f8d3a..b728258463 100644 --- a/hud_luminos_minimal.cfg +++ b/hud_luminos_minimal.cfg @@ -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" diff --git a/hud_luminos_minimal_xhair.cfg b/hud_luminos_minimal_xhair.cfg index 41a47d7ab2..3bfd694b19 100644 --- a/hud_luminos_minimal_xhair.cfg +++ b/hud_luminos_minimal_xhair.cfg @@ -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" diff --git a/hud_luminos_old.cfg b/hud_luminos_old.cfg index f4a5e0441b..c808f62fb5 100644 --- a/hud_luminos_old.cfg +++ b/hud_luminos_old.cfg @@ -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" diff --git a/hud_nexuiz.cfg b/hud_nexuiz.cfg index ea5dc69a24..b0b02d080c 100644 --- a/hud_nexuiz.cfg +++ b/hud_nexuiz.cfg @@ -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" diff --git a/mutators.cfg b/mutators.cfg index 14289d8c85..b6ad3468e0 100644 --- a/mutators.cfg +++ b/mutators.cfg @@ -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" diff --git a/qcsrc/client/autocvars.qh b/qcsrc/client/autocvars.qh index 5793cd5a7b..f87b94e8e3 100644 --- a/qcsrc/client/autocvars.qh +++ b/qcsrc/client/autocvars.qh @@ -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; diff --git a/qcsrc/client/defs.qh b/qcsrc/client/defs.qh index db1a5afaca..0cf71294a7 100644 --- a/qcsrc/client/defs.qh +++ b/qcsrc/client/defs.qh @@ -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; diff --git a/qcsrc/client/hud/panel/quickmenu.qc b/qcsrc/client/hud/panel/quickmenu.qc index 3e61f9b5a6..c58fb2a675 100644 --- a/qcsrc/client/hud/panel/quickmenu.qc +++ b/qcsrc/client/hud/panel/quickmenu.qc @@ -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); diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc index e11a134558..a6d1cc9417 100644 --- a/qcsrc/client/hud/panel/scoreboard.qc +++ b/qcsrc/client/hud/panel/scoreboard.qc @@ -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)))); } } diff --git a/qcsrc/client/hud/panel/weapons.qc b/qcsrc/client/hud/panel/weapons.qc index 832ffad0b3..8668886a91 100644 --- a/qcsrc/client/hud/panel/weapons.qc +++ b/qcsrc/client/hud/panel/weapons.qc @@ -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; diff --git a/qcsrc/client/miscfunctions.qc b/qcsrc/client/miscfunctions.qc index 360305601a..bb0bfe12c7 100644 --- a/qcsrc/client/miscfunctions.qc +++ b/qcsrc/client/miscfunctions.qc @@ -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); diff --git a/qcsrc/client/teamradar.qc b/qcsrc/client/teamradar.qc index c565651d4a..cdb8894a8d 100644 --- a/qcsrc/client/teamradar.qc +++ b/qcsrc/client/teamradar.qc @@ -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); diff --git a/qcsrc/client/view.qc b/qcsrc/client/view.qc index 1b1e8ebdc4..eb341d58cd 100644 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@ -1120,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; } @@ -1722,7 +1722,7 @@ void View_NightVision() 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_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); @@ -1736,7 +1736,7 @@ void View_NightVision() 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_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); @@ -2329,6 +2329,8 @@ void CSQC_UpdateView(entity this, float w, float h) vid_width = vf_size.x; vid_height = vf_size.y; + ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE); + WaypointSprite_Load(); CSQCPlayer_SetCamera(); @@ -2339,8 +2341,6 @@ void CSQC_UpdateView(entity this, float w, float h) current_player = player_localnum; myteam = entcs_GetTeam(current_player); - ticrate = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE); - // abused multiple places below entity local_player = ((csqcplayer) ? csqcplayer : CSQCModel_server2csqc(player_localentnum - 1)); if(!local_player) @@ -2445,10 +2445,7 @@ 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); + // Now the the scene has been rendered, begin with the 2D drawing functions View_NightVision(); DrawReticle(local_player); diff --git a/qcsrc/common/campaign_common.qh b/qcsrc/common/campaign_common.qh index 25c008d260..088aefea09 100644 --- a/qcsrc/common/campaign_common.qh +++ b/qcsrc/common/campaign_common.qh @@ -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]; diff --git a/qcsrc/common/campaign_file.qc b/qcsrc/common/campaign_file.qc index 4f099b5330..8bac6f35ee 100644 --- a/qcsrc/common/campaign_file.qc +++ b/qcsrc/common/campaign_file.qc @@ -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]); diff --git a/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc b/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc index aa05ea337b..11bbaea6fb 100644 --- a/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc +++ b/qcsrc/common/gamemodes/gamemode/ctf/sv_ctf.qc @@ -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); diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc index 54f6268e36..89060694a6 100644 --- a/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc +++ b/qcsrc/common/gamemodes/gamemode/freezetag/sv_freezetag.qc @@ -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 diff --git a/qcsrc/common/items/item/pickup.qh b/qcsrc/common/items/item/pickup.qh index 0f09901af2..7e31994075 100644 --- a/qcsrc/common/items/item/pickup.qh +++ b/qcsrc/common/items/item/pickup.qh @@ -34,7 +34,7 @@ CLASS(Pickup, GameItem) ATTRIB(Pickup, m_itemid, int, 0); #ifdef SVQC ATTRIB(Pickup, m_mins, vector, '-16 -16 0'); - ATTRIB(Pickup, m_maxs, vector, '16 16 32'); + ATTRIB(Pickup, m_maxs, vector, '16 16 48'); ATTRIB(Pickup, m_botvalue, int, 0); ATTRIB(Pickup, m_itemflags, int, 0); float generic_pickupevalfunc(entity player, entity item); diff --git a/qcsrc/common/mapinfo.qc b/qcsrc/common/mapinfo.qc index 1d6f4897b8..257e5e40f1 100644 --- a/qcsrc/common/mapinfo.qc +++ b/qcsrc/common/mapinfo.qc @@ -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; } diff --git a/qcsrc/common/mapobjects/func/button.qc b/qcsrc/common/mapobjects/func/button.qc index a9c0fa7261..423ac5e7b6 100644 --- a/qcsrc/common/mapobjects/func/button.qc +++ b/qcsrc/common/mapobjects/func/button.qc @@ -206,7 +206,7 @@ spawnfunc(func_button) if (!this.lip) this.lip = 4; - if(this.wait == -1 && autocvar_sv_vq3compat) + if(this.wait == -1 && autocvar_sv_q3defragcompat) this.wait = 0.1; // compatibility for q3df: "instant" return if(this.noise != "") diff --git a/qcsrc/common/mapobjects/func/rainsnow.qc b/qcsrc/common/mapobjects/func/rainsnow.qc index 644194c354..4f4d4d0aca 100644 --- a/qcsrc/common/mapobjects/func/rainsnow.qc +++ b/qcsrc/common/mapobjects/func/rainsnow.qc @@ -13,6 +13,7 @@ bool rainsnow_SendEntity(entity this, entity to, float sf) WriteShort(MSG_ENTITY, compressShortVector(this.dest)); WriteShort(MSG_ENTITY, this.count); WriteByte(MSG_ENTITY, this.cnt); + WriteShort(MSG_ENTITY, bound(0, this.fade_end, 65535)); return true; } @@ -44,7 +45,7 @@ spawnfunc(func_rain) if (!this.count) this.count = 2000; // relative to absolute particle count - this.count = 0.1 * this.count * (this.size_x / 1024) * (this.size_y / 1024); + //this.count = 0.1 * this.count * (this.size_x / 1024) * (this.size_y / 1024); if (this.count < 1) this.count = 1; if(this.count > 65535) @@ -84,7 +85,7 @@ spawnfunc(func_snow) if (!this.count) this.count = 2000; // relative to absolute particle count - this.count = 0.1 * this.count * (this.size_x / 1024) * (this.size_y / 1024); + //this.count = 0.1 * this.count * (this.size_x / 1024) * (this.size_y / 1024); if (this.count < 1) this.count = 1; if(this.count > 65535) @@ -95,24 +96,26 @@ spawnfunc(func_snow) Net_LinkEntity(this, false, 0, rainsnow_SendEntity); } #elif defined(CSQC) -float autocvar_cl_rainsnow_maxdrawdist = 2048; +float autocvar_cl_rainsnow_maxdrawdist = 1000; -void Draw_Rain(entity this) +void Draw_RainSnow(entity this) { - vector maxdist = '1 1 0' * autocvar_cl_rainsnow_maxdrawdist; - maxdist.z = 5; - if(boxesoverlap(vec2(view_origin) - maxdist, vec2(view_origin) + maxdist, vec2(this.absmin) - '0 0 5', vec2(this.absmax) + '0 0 5')) - //if(autocvar_cl_rainsnow_maxdrawdist <= 0 || vdist(vec2(this.origin) - vec2(this.absmin + this.absmax * 0.5), <=, autocvar_cl_rainsnow_maxdrawdist)) - te_particlerain(this.origin + this.mins, this.origin + this.maxs, this.velocity, floor(this.count * drawframetime + random()), this.glow_color); -} + float drawdist = ((this.fade_end) ? this.fade_end : autocvar_cl_rainsnow_maxdrawdist); + vector maxdist = '1 1 1' * drawdist; -void Draw_Snow(entity this) -{ - vector maxdist = '1 1 0' * autocvar_cl_rainsnow_maxdrawdist; - maxdist.z = 5; - if(boxesoverlap(vec2(view_origin) - maxdist, vec2(view_origin) + maxdist, vec2(this.absmin) - '0 0 5', vec2(this.absmax) + '0 0 5')) - //if(autocvar_cl_rainsnow_maxdrawdist <= 0 || vdist(vec2(this.origin) - vec2(this.absmin + this.absmax * 0.5), <=, autocvar_cl_rainsnow_maxdrawdist)) - te_particlesnow(this.origin + this.mins, this.origin + this.maxs, this.velocity, floor(this.count * drawframetime + random()), this.glow_color); + vector effbox_min = vec_to_max(view_origin - maxdist, this.origin + this.mins); + vector effbox_max = vec_to_min(view_origin + maxdist, this.origin + this.maxs); + + vector mysize = effbox_max - effbox_min; + float mycount = bound(1, 0.1 * this.count * (mysize.x / 1024) * (mysize.y / 1024), 65535); + + if(boxesoverlap(view_origin - maxdist, view_origin + maxdist, this.absmin, this.absmax)) // optimisation: don't render any rain if the player is outside the view distance + { + if(this.state == RAINSNOW_RAIN) + te_particlerain(effbox_min, effbox_max, this.velocity, floor(mycount * drawframetime + random()), this.glow_color); + else + te_particlesnow(effbox_min, effbox_max, this.velocity, floor(mycount * drawframetime + random()), this.glow_color); + } } NET_HANDLE(ENT_CLIENT_RAINSNOW, bool isnew) @@ -123,6 +126,7 @@ NET_HANDLE(ENT_CLIENT_RAINSNOW, bool isnew) this.velocity = decompressShortVector(ReadShort()); this.count = ReadShort(); this.glow_color = ReadByte(); // color + this.fade_end = ReadShort(); return = true; @@ -134,9 +138,6 @@ NET_HANDLE(ENT_CLIENT_RAINSNOW, bool isnew) setsize(this, this.mins, this.maxs); this.solid = SOLID_NOT; if (isnew) IL_PUSH(g_drawables, this); - if(this.state == RAINSNOW_RAIN) - this.draw = Draw_Rain; - else - this.draw = Draw_Snow; + this.draw = Draw_RainSnow; } #endif diff --git a/qcsrc/common/mapobjects/trigger/hurt.qc b/qcsrc/common/mapobjects/trigger/hurt.qc index ccdf2c7d0b..8c21c509c5 100644 --- a/qcsrc/common/mapobjects/trigger/hurt.qc +++ b/qcsrc/common/mapobjects/trigger/hurt.qc @@ -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 == "") diff --git a/qcsrc/common/mapobjects/trigger/jumppads.qc b/qcsrc/common/mapobjects/trigger/jumppads.qc index f4b3e455a1..2c160eae95 100644 --- a/qcsrc/common/mapobjects/trigger/jumppads.qc +++ b/qcsrc/common/mapobjects/trigger/jumppads.qc @@ -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; diff --git a/qcsrc/common/mapobjects/trigger/multi.qc b/qcsrc/common/mapobjects/trigger/multi.qc index 1fef1ffb35..df915a6496 100644 --- a/qcsrc/common/mapobjects/trigger/multi.qc +++ b/qcsrc/common/mapobjects/trigger/multi.qc @@ -176,7 +176,7 @@ spawnfunc(trigger_multiple) this.wait = 0; this.use = multi_use; - if(this.wait == -1 && autocvar_sv_vq3compat) + if(this.wait == -1 && autocvar_sv_q3defragcompat) this.wait = 0.1; // compatibility for q3df: "instant" return EXACTTRIGGER_INIT; diff --git a/qcsrc/common/mapobjects/triggers.qc b/qcsrc/common/mapobjects/triggers.qc index 9a7181d3a2..27ffead9c7 100644 --- a/qcsrc/common/mapobjects/triggers.qc +++ b/qcsrc/common/mapobjects/triggers.qc @@ -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); } diff --git a/qcsrc/common/mapobjects/triggers.qh b/qcsrc/common/mapobjects/triggers.qh index b9baf63f1c..797c9767f6 100644 --- a/qcsrc/common/mapobjects/triggers.qh +++ b/qcsrc/common/mapobjects/triggers.qh @@ -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); diff --git a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc index 5789b6e4c4..f1a1491661 100644 --- a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc +++ b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qc @@ -272,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)) @@ -316,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); diff --git a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qh b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qh index 671a524f9e..88efc94ebb 100644 --- a/qcsrc/common/mutators/mutator/buffs/sv_buffs.qh +++ b/qcsrc/common/mutators/mutator/buffs/sv_buffs.qh @@ -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; diff --git a/qcsrc/common/mutators/mutator/nades/nades.qc b/qcsrc/common/mutators/mutator/nades/nades.qc index 67e3d4ad1c..510fcf92e1 100644 --- a/qcsrc/common/mutators/mutator/nades/nades.qc +++ b/qcsrc/common/mutators/mutator/nades/nades.qc @@ -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) diff --git a/qcsrc/common/mutators/mutator/overkill/okhmg.qc b/qcsrc/common/mutators/mutator/overkill/okhmg.qc index df55fb88c4..a0a8962a7d 100644 --- a/qcsrc/common/mutators/mutator/overkill/okhmg.qc +++ b/qcsrc/common/mutators/mutator/overkill/okhmg.qc @@ -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); diff --git a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc index 768e364a78..17e71f06f8 100644 --- a/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc +++ b/qcsrc/common/mutators/mutator/overkill/okmachinegun.qc @@ -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); diff --git a/qcsrc/common/mutators/mutator/overkill/oknex.qc b/qcsrc/common/mutators/mutator/overkill/oknex.qc index 83a3a3cc05..ca44a070a0 100644 --- a/qcsrc/common/mutators/mutator/overkill/oknex.qc +++ b/qcsrc/common/mutators/mutator/overkill/oknex.qc @@ -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); diff --git a/qcsrc/common/mutators/mutator/overkill/okrpc.qc b/qcsrc/common/mutators/mutator/overkill/okrpc.qc index fa4ffc4b5e..362f14846f 100644 --- a/qcsrc/common/mutators/mutator/overkill/okrpc.qc +++ b/qcsrc/common/mutators/mutator/overkill/okrpc.qc @@ -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); diff --git a/qcsrc/common/mutators/mutator/overkill/okshotgun.qc b/qcsrc/common/mutators/mutator/overkill/okshotgun.qc index 784d1c37b7..da4c4749d0 100644 --- a/qcsrc/common/mutators/mutator/overkill/okshotgun.qc +++ b/qcsrc/common/mutators/mutator/overkill/okshotgun.qc @@ -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); diff --git a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc index a9e1c5f57d..0b4fe28ff3 100644 --- a/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc +++ b/qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc @@ -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); diff --git a/qcsrc/common/physics/movetypes/movetypes.qc b/qcsrc/common/physics/movetypes/movetypes.qc index bbd86d62e3..68d4c36601 100644 --- a/qcsrc/common/physics/movetypes/movetypes.qc +++ b/qcsrc/common/physics/movetypes/movetypes.qc @@ -7,6 +7,8 @@ void set_movetype(entity this, int mt) if (mt == MOVETYPE_PHYSICS || mt == MOVETYPE_PUSH || mt == MOVETYPE_FAKEPUSH) { this.move_qcphysics = false; } + if(!IL_CONTAINS(g_moveables, this)) + IL_PUSH(g_moveables, this); // add it to the moveable entities list (even if it doesn't move!) logic: if an object never sets its movetype, we assume it never does anything notable this.movetype = (this.move_qcphysics) ? MOVETYPE_NONE : mt; } #elif defined(CSQC) @@ -701,11 +703,11 @@ void Movetype_Physics_MatchTicrate(entity this, float tr, bool sloppy) // SV_Ph { Movetype_Physics_NoMatchServer(this); - 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; } diff --git a/qcsrc/common/physics/player.qc b/qcsrc/common/physics/player.qc index 9f7ddab502..16cb27aeca 100644 --- a/qcsrc/common/physics/player.qc +++ b/qcsrc/common/physics/player.qc @@ -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 @@ -690,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 diff --git a/qcsrc/common/stats.qh b/qcsrc/common/stats.qh index 8b769538e9..7d2aae5f42 100644 --- a/qcsrc/common/stats.qh +++ b/qcsrc/common/stats.qh @@ -319,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" diff --git a/qcsrc/common/t_items.qc b/qcsrc/common/t_items.qc index 1029f78656..df3bb9b521 100644 --- a/qcsrc/common/t_items.qc +++ b/qcsrc/common/t_items.qc @@ -174,8 +174,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew) if(sf & ISF_SIZE) { - float use_bigsize = ReadByte(); - setsize(this, '-16 -16 0', (use_bigsize) ? '16 16 48' : '16 16 32'); + setsize(this, '-16 -16 0', '16 16 48'); } if(sf & ISF_STATUS) // need to read/write status first so model can handle simple, fb etc. @@ -205,8 +204,6 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew) this.solid = SOLID_TRIGGER; //this.flags |= FL_ITEM; - bool use_bigsize = ReadByte(); - this.fade_end = ReadShort(); this.fade_start = ReadShort(); if(!warpzone_warpzones_exist && this.fade_start && !autocvar_cl_items_nofade) @@ -257,7 +254,7 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew) precache_model(this.mdl); _setmodel(this, this.mdl); - setsize(this, '-16 -16 0', (use_bigsize) ? '16 16 48' : '16 16 32'); + setsize(this, '-16 -16 0', '16 16 48'); } if(sf & ISF_COLORMAP) @@ -326,19 +323,14 @@ bool ItemSend(entity this, entity to, int sf) WriteAngle(MSG_ENTITY, this.angles_z); } - if(sf & ISF_SIZE) - { - Pickup p = this.itemdef; - WriteByte(MSG_ENTITY, p.instanceOfPowerup || p.instanceOfHealth || p.instanceOfArmor); - } + // sets size on the client, unused on server + //if(sf & ISF_SIZE) if(sf & ISF_STATUS) WriteByte(MSG_ENTITY, this.ItemStatus); if(sf & ISF_MODEL) { - Pickup p = this.itemdef; - WriteByte(MSG_ENTITY, p.instanceOfPowerup || p.instanceOfHealth || p.instanceOfArmor); WriteShort(MSG_ENTITY, this.fade_end); WriteShort(MSG_ENTITY, this.fade_start); diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index 6785a9f215..111c7e7956 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -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); diff --git a/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc b/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc index 9299e938d0..81fd93aa02 100644 --- a/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/bumblebee_weapons.qc @@ -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); diff --git a/qcsrc/common/vehicles/vehicle/racer.qc b/qcsrc/common/vehicles/vehicle/racer.qc index e2a2593948..87804586a2 100644 --- a/qcsrc/common/vehicles/vehicle/racer.qc +++ b/qcsrc/common/vehicles/vehicle/racer.qc @@ -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); } diff --git a/qcsrc/common/vehicles/vehicle/racer_weapon.qc b/qcsrc/common/vehicles/vehicle/racer_weapon.qc index 0e7222eb24..f7253d8d8e 100644 --- a/qcsrc/common/vehicles/vehicle/racer_weapon.qc +++ b/qcsrc/common/vehicles/vehicle/racer_weapon.qc @@ -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); diff --git a/qcsrc/common/vehicles/vehicle/raptor.qc b/qcsrc/common/vehicles/vehicle/raptor.qc index e9f7f7333d..f0c4dc1ec7 100644 --- a/qcsrc/common/vehicles/vehicle/raptor.qc +++ b/qcsrc/common/vehicles/vehicle/raptor.qc @@ -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; diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc index 66b5bec883..7d4a250f41 100644 --- a/qcsrc/common/vehicles/vehicle/raptor_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/raptor_weapons.qc @@ -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; diff --git a/qcsrc/common/vehicles/vehicle/raptor_weapons.qh b/qcsrc/common/vehicles/vehicle/raptor_weapons.qh index 37b87bbada..c762acfa23 100644 --- a/qcsrc/common/vehicles/vehicle/raptor_weapons.qh +++ b/qcsrc/common/vehicles/vehicle/raptor_weapons.qh @@ -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; diff --git a/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc b/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc index 308a92fd87..fdeddc47bf 100644 --- a/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc +++ b/qcsrc/common/vehicles/vehicle/spiderbot_weapons.qc @@ -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); diff --git a/qcsrc/common/weapons/all.qc b/qcsrc/common/weapons/all.qc index f2fdf4407f..b8d2428f3f 100644 --- a/qcsrc/common/weapons/all.qc +++ b/qcsrc/common/weapons/all.qc @@ -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); diff --git a/qcsrc/common/weapons/all.qh b/qcsrc/common/weapons/all.qh index 131e7b49ef..26b40084bf 100644 --- a/qcsrc/common/weapons/all.qh +++ b/qcsrc/common/weapons/all.qh @@ -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 diff --git a/qcsrc/common/weapons/weapon.qh b/qcsrc/common/weapons/weapon.qh index 3dd2a8048a..02fbdb536c 100644 --- a/qcsrc/common/weapons/weapon.qh +++ b/qcsrc/common/weapons/weapon.qh @@ -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); diff --git a/qcsrc/common/weapons/weapon/arc.qc b/qcsrc/common/weapons/weapon/arc.qc index fba52d31de..ae2dbf07df 100644 --- a/qcsrc/common/weapons/weapon/arc.qc +++ b/qcsrc/common/weapons/weapon/arc.qc @@ -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)), diff --git a/qcsrc/common/weapons/weapon/electro.qc b/qcsrc/common/weapons/weapon/electro.qc index 2ba6b5da18..69ccc4251b 100644 --- a/qcsrc/common/weapons/weapon/electro.qc +++ b/qcsrc/common/weapons/weapon/electro.qc @@ -154,27 +154,46 @@ void W_Electro_Bolt_Think(entity this) { if(e.classname == "electro_orb") { - // change owner to whoever caused the combo explosion - e.realowner = this.realowner; - e.takedamage = DAMAGE_NO; - e.classname = "electro_orb_chain"; - - // now set the next one to trigger as well - setthink(e, W_Electro_ExplodeCombo); + bool explode; + if (this.owner == e.owner) + { + explode = WEP_CVAR_PRI(electro, midaircombo_own); + } + else if (SAME_TEAM(this.owner, e.owner)) + { + explode = WEP_CVAR_PRI(electro, midaircombo_teammate); + } + else + { + explode = WEP_CVAR_PRI(electro, midaircombo_enemy); + } - // delay combo chains, looks cooler - e.nextthink = + if (explode) + { + // change owner to whoever caused the combo explosion + e.realowner = this.realowner; + e.takedamage = DAMAGE_NO; + e.classname = "electro_orb_chain"; + + // Only first orb explosion uses midaircombo_speed, others use the normal combo_speed. + // This allows to avoid the delay on the first explosion which looks better + // (the bolt and orb should explode together because they interacted together) + // while keeping the chaining delay. + setthink(e, W_Electro_ExplodeCombo); + e.nextthink = ( time + - (WEP_CVAR(electro, combo_speed) ? - (vlen(e.WarpZone_findradius_dist) / WEP_CVAR(electro, combo_speed)) + (WEP_CVAR_PRI(electro, midaircombo_speed) ? + (vlen(e.WarpZone_findradius_dist) / WEP_CVAR_PRI(electro, midaircombo_speed)) : 0 ) ); - ++found; + + ++found; + } } e = e.chain; } diff --git a/qcsrc/common/weapons/weapon/electro.qh b/qcsrc/common/weapons/weapon/electro.qh index 7dbed189b0..4480812207 100644 --- a/qcsrc/common/weapons/weapon/electro.qh +++ b/qcsrc/common/weapons/weapon/electro.qh @@ -40,9 +40,13 @@ CLASS(Electro, Weapon) P(class, prefix, force, float, BOTH) \ P(class, prefix, health, float, SEC) \ P(class, prefix, lifetime, float, BOTH) \ + P(class, prefix, midaircombo_enemy, bool, PRI) \ P(class, prefix, midaircombo_explode, float, PRI) \ P(class, prefix, midaircombo_interval, float, PRI) \ + P(class, prefix, midaircombo_own, bool, PRI) \ P(class, prefix, midaircombo_radius, float, PRI) \ + P(class, prefix, midaircombo_speed, float, PRI) \ + P(class, prefix, midaircombo_teammate, float, PRI) \ P(class, prefix, radius, float, BOTH) \ P(class, prefix, refire2, float, SEC) \ P(class, prefix, refire, float, BOTH) \ diff --git a/qcsrc/common/weapons/weapon/porto.qc b/qcsrc/common/weapons/weapon/porto.qc index 44b73fb05a..fd33dacded 100644 --- a/qcsrc/common/weapons/weapon/porto.qc +++ b/qcsrc/common/weapons/weapon/porto.qc @@ -118,7 +118,7 @@ void W_Porto_Fail(entity this, float failhard) if(this.cnt < 0 && !failhard && this.realowner.playerid == this.playerid && !IS_DEAD(this.realowner) && !(STAT(WEAPONS, this.realowner) & WEPSET(PORTO))) { - setsize(this, '-16 -16 0', '16 16 32'); + setsize(this, '-16 -16 0', '16 16 48'); setorigin(this, this.origin + trace_plane_normal); if(move_out_of_solid(this)) { diff --git a/qcsrc/common/weapons/weapon/shockwave.qc b/qcsrc/common/weapons/weapon/shockwave.qc index 74986f9cc9..f38c34b197 100644 --- a/qcsrc/common/weapons/weapon/shockwave.qc +++ b/qcsrc/common/weapons/weapon/shockwave.qc @@ -712,14 +712,14 @@ void Draw_Shockwave(entity this) if(counter >= 1) { // draw from shot origin to min spread radius - R_BeginPolygon("", DRAWFLAG_NORMAL); + R_BeginPolygon("", DRAWFLAG_NORMAL, false); R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a); R_PolygonVertex(new_min_end, '0 0 0', sw_color, a); R_PolygonVertex(this.sw_shotorg, '0 0 0', sw_color, a); R_EndPolygon(); // draw from min spread radius to max spread radius - R_BeginPolygon("", DRAWFLAG_NORMAL); + R_BeginPolygon("", DRAWFLAG_NORMAL, false); R_PolygonVertex(new_min_end, '0 0 0', sw_color, a); R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a); R_PolygonVertex(prev_max_end, '0 0 0', sw_color, a); @@ -734,14 +734,14 @@ void Draw_Shockwave(entity this) if((counter + 1) == divisions) { // draw from shot origin to min spread radius - R_BeginPolygon("", DRAWFLAG_NORMAL); + R_BeginPolygon("", DRAWFLAG_NORMAL, false); R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a); R_PolygonVertex(first_min_end, '0 0 0', sw_color, a); R_PolygonVertex(this.sw_shotorg, '0 0 0', sw_color, a); R_EndPolygon(); // draw from min spread radius to max spread radius - R_BeginPolygon("", DRAWFLAG_NORMAL); + R_BeginPolygon("", DRAWFLAG_NORMAL, false); R_PolygonVertex(first_min_end, '0 0 0', sw_color, a); R_PolygonVertex(prev_min_end, '0 0 0', sw_color, a); R_PolygonVertex(prev_max_end, '0 0 0', sw_color, a); diff --git a/qcsrc/common/weapons/weapon/shotgun.qc b/qcsrc/common/weapons/weapon/shotgun.qc index e2f4b640aa..b8cae5fd5d 100644 --- a/qcsrc/common/weapons/weapon/shotgun.qc +++ b/qcsrc/common/weapons/weapon/shotgun.qc @@ -2,6 +2,9 @@ #ifdef SVQC +// enable to debug melee range +//#define SHOTGUN_MELEEDEBUG + METHOD(Shotgun, m_spawnfunc_hookreplace, Weapon(Shotgun this, entity e)) { if (autocvar_sv_q3acompat_machineshotgunswap && !Item_IsLoot(e)) @@ -89,8 +92,10 @@ void W_Shotgun_Melee_Think(entity this) WarpZone_traceline_antilag(this.realowner, this.realowner.origin + this.realowner.view_ofs, targpos, false, this.realowner, ((IS_CLIENT(this.realowner)) ? ANTILAG_LATENCY(this.realowner) : 0)); // draw lightning beams for debugging - //te_lightning2(NULL, targpos, this.realowner.origin + this.realowner.view_ofs + v_forward * 5 - v_up * 5); - //te_customflash(targpos, 40, 2, '1 1 1'); + #ifdef SHOTGUN_MELEEDEBUG + te_lightning2(NULL, targpos, this.realowner.origin + this.realowner.view_ofs + v_forward * 5 - v_up * 5); + te_customflash(targpos, 40, 2, '1 1 1'); + #endif is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || IS_MONSTER(trace_ent)); @@ -116,7 +121,9 @@ void W_Shotgun_Melee_Think(entity this) if(accuracy_isgooddamage(this.realowner, target_victim)) { accuracy_add(this.realowner, WEP_SHOTGUN, 0, swing_damage); } // draw large red flash for debugging - //te_customflash(targpos, 200, 2, '15 0 0'); + #ifdef SHOTGUN_MELEEDEBUG + te_customflash(targpos, 200, 2, '15 0 0'); + #endif if(WEP_CVAR_SEC(shotgun, melee_multihit)) // allow multiple hits with one swing, but not against the same player twice. { diff --git a/qcsrc/ecs/lib.qh b/qcsrc/ecs/lib.qh index 2d48e577b8..192136b625 100644 --- a/qcsrc/ecs/lib.qh +++ b/qcsrc/ecs/lib.qh @@ -1,24 +1,29 @@ #pragma once +IntrusiveList g_events; +IntrusiveList g_components; +STATIC_INIT(components) { g_events = IL_NEW(); g_components = IL_NEW(); } + /** Components always interpolate from the previous state */ #define COMPONENT(com) \ void com_##com##_interpolate(entity it, float a); \ .bool com_##com -#define FOREACH_COMPONENT(com, body) FOREACH_ENTITY_FLOAT(com_##com, true, body) +#define FOREACH_COMPONENT(com, body) IL_EACH(g_components, it.com_##com, body) #define EVENT(T, args) .bool evt_##T##_listener; .void args evt_##T #define emit(T, ...) \ MACRO_BEGIN \ - FOREACH_ENTITY_FLOAT_ORDERED(evt_##T##_listener, true, it.evt_##T(__VA_ARGS__)); \ + IL_EACH(g_events, it.evt_##T##_listener, it.evt_##T(__VA_ARGS__)); \ MACRO_END #define subscribe(listener, T, fn) \ MACRO_BEGIN \ listener.evt_##T = (fn); \ listener.evt_##T##_listener = true; \ + IL_PUSH(g_events, listener); \ MACRO_END diff --git a/qcsrc/ecs/systems/physics.qc b/qcsrc/ecs/systems/physics.qc index f73ade3d12..a5af98d2ce 100644 --- a/qcsrc/ecs/systems/physics.qc +++ b/qcsrc/ecs/systems/physics.qc @@ -360,11 +360,9 @@ void sys_phys_simulate(entity this, float dt) // apply edge friction const float f2 = vlen2(vec2(this.velocity)); if (f2 > 0) { - trace_dphitq3surfaceflags = 0; - tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this); // TODO: apply edge friction // apply ground friction - const int realfriction = (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SLICK) + const int realfriction = (IS_ONSLICK(this)) ? PHYS_FRICTION_SLICK(this) : PHYS_FRICTION(this); diff --git a/qcsrc/i18n-guide.txt b/qcsrc/i18n-guide.txt index f2677fe3a3..2ada204dbf 100644 --- a/qcsrc/i18n-guide.txt +++ b/qcsrc/i18n-guide.txt @@ -1,3 +1,6 @@ +For more information, see https://gitlab.com/xonotic/xonotic/-/wikis/Translating + + How to make the .po template: find . -type f -not -name \*.po -not -name \*.txt | xgettext -LC -k_ -f- --from-code utf-8 diff --git a/qcsrc/lib/csqcmodel/cl_player.qc b/qcsrc/lib/csqcmodel/cl_player.qc index f49c5f6dbd..04a3c2b740 100644 --- a/qcsrc/lib/csqcmodel/cl_player.qc +++ b/qcsrc/lib/csqcmodel/cl_player.qc @@ -82,7 +82,7 @@ void CSQCPlayer_SetPredictionError(vector o, vector v, float onground_diff) csqcplayer_predictionerroro = CSQCPlayer_GetPredictionErrorO() + o; csqcplayer_predictionerrorv = CSQCPlayer_GetPredictionErrorV() + v; - csqcplayer_predictionerrorfactor = autocvar_cl_movement_errorcompensation / ticrate; + csqcplayer_predictionerrorfactor = autocvar_cl_movement_errorcompensation / ((ticrate) ? ticrate : 1); csqcplayer_predictionerrortime = time + 1.0 / csqcplayer_predictionerrorfactor; } @@ -208,8 +208,8 @@ bool CSQCPlayer_IsLocalPlayer(entity this) } float stairsmoothz; -float autocvar_cl_stairsmoothspeed; -float autocvar_cl_smoothviewheight; +float autocvar_cl_stairsmoothspeed = 200; +float autocvar_cl_smoothviewheight = 0.05; float smooth_prevtime; float viewheightavg; vector CSQCPlayer_ApplySmoothing(entity this, vector v) @@ -262,18 +262,18 @@ void CSQCPlayer_ApplyIdleScaling(entity this) //setproperty(VF_CL_VIEWANGLES, view_angles); // update view angles as well so we can aim } -float autocvar_cl_bob; -float autocvar_cl_bobcycle; -float autocvar_cl_bob_limit; -float autocvar_cl_bob_limit_heightcheck; -float autocvar_cl_bob_velocity_limit; -float autocvar_cl_bobup; -float autocvar_cl_bobfall; -float autocvar_cl_bobfallcycle; -float autocvar_cl_bobfallminspeed; -float autocvar_cl_bob2; -float autocvar_cl_bob2cycle; -float autocvar_cl_bob2smooth; +float autocvar_cl_bob = 0; +float autocvar_cl_bobcycle = 0.5; +float autocvar_cl_bob_limit = 7; +float autocvar_cl_bob_limit_heightcheck = 0; +float autocvar_cl_bob_velocity_limit = 400; +float autocvar_cl_bobup = 0.5; +float autocvar_cl_bobfall = 0.05; +float autocvar_cl_bobfallcycle = 3; +float autocvar_cl_bobfallminspeed = 200; +float autocvar_cl_bob2 = 0; +float autocvar_cl_bob2cycle = 1; +float autocvar_cl_bob2smooth = 0.05; float bobfall_swing; float bobfall_speed; float bob2_smooth; @@ -502,7 +502,7 @@ void CSQCPlayer_CalcRefdef(entity this) setproperty(VF_ANGLES, view_angles); } -bool autocvar_cl_useenginerefdef = true; +bool autocvar_cl_useenginerefdef = false; /** Called once per CSQC_UpdateView() */ void CSQCPlayer_SetCamera() diff --git a/qcsrc/lib/draw.qh b/qcsrc/lib/draw.qh index 2bf480a878..dbac8b8b19 100644 --- a/qcsrc/lib/draw.qh +++ b/qcsrc/lib/draw.qh @@ -26,7 +26,7 @@ C = to + thickdir * (thickness / 2); D = to - thickdir * (thickness / 2); - R_BeginPolygon(texture, drawflag); + R_BeginPolygon(texture, drawflag, false); R_PolygonVertex(A, '0 0 0' + shift * '1 0 0', rgb, theAlpha); R_PolygonVertex(B, '0 1 0' + shift * '1 0 0', rgb, theAlpha); R_PolygonVertex(C, '0 1 0' + (shift + length_tex) * '1 0 0', rgb, theAlpha); diff --git a/qcsrc/lib/warpzone/server.qc b/qcsrc/lib/warpzone/server.qc index 0244b40a9d..66ee6b133c 100644 --- a/qcsrc/lib/warpzone/server.qc +++ b/qcsrc/lib/warpzone/server.qc @@ -13,6 +13,10 @@ #include #endif +#ifdef SVQC +bool autocvar_sv_warpzone_allow_selftarget; +#endif + #ifdef WARPZONELIB_KEEPDEBUG #define WARPZONELIB_REMOVEHACK #endif @@ -213,19 +217,8 @@ void WarpZone_Touch(entity this, entity toucher) if(WarpZone_Teleport(this, toucher, f, 0)) { #ifdef SVQC - string save1, save2; - - save1 = this.target; this.target = string_null; - save2 = this.target3; this.target3 = string_null; - SUB_UseTargets(this, toucher, toucher); // use toucher too? - if (!this.target) this.target = save1; - if (!this.target3) this.target3 = save2; - - save1 = this.target; this.target = string_null; - save2 = this.target2; this.target2 = string_null; - SUB_UseTargets(this.enemy, toucher, toucher); // use toucher too? - if (!this.target) this.target = save1; - if (!this.target2) this.target2 = save2; + SUB_UseTargets_SkipTargets(this, toucher, toucher, BIT(1) | BIT(3)); // use toucher too? + SUB_UseTargets_SkipTargets(this.enemy, toucher, toucher, BIT(1) | BIT(2)); // use toucher too? #endif } else @@ -369,19 +362,8 @@ float WarpZone_CheckProjectileImpact(entity player) player.velocity = player.warpzone_oldvelocity; if(WarpZone_Teleport(wz, player, 0, 1)) { - string save1, save2; - - save1 = wz.target; wz.target = string_null; - save2 = wz.target3; wz.target3 = string_null; - SUB_UseTargets(wz, player, player); - if (!wz.target) wz.target = save1; - if (!wz.target3) wz.target3 = save2; - - save1 = wz.enemy.target; wz.enemy.target = string_null; - save2 = wz.enemy.target2; wz.enemy.target2 = string_null; - SUB_UseTargets(wz.enemy, player, player); - if (!wz.enemy.target) wz.enemy.target = save1; - if (!wz.enemy.target2) wz.enemy.target2 = save2; + SUB_UseTargets_SkipTargets(wz, player, player, BIT(1) | BIT(3)); + SUB_UseTargets_SkipTargets(wz.enemy, player, player, BIT(1) | BIT(2)); } else { @@ -648,7 +630,8 @@ void WarpZone_InitStep_FindTarget(entity this) // this way only one of the two ents needs to target if(this.target != "") { - this.enemy = this; // so the if(!e.enemy) check also skips this, saves one IF + if(!autocvar_sv_warpzone_allow_selftarget) + this.enemy = this; // so the if(!e.enemy) check also skips this, saves one IF e2 = NULL; for(e = NULL, i = 0; (e = find(e, targetname, this.target)); ) diff --git a/qcsrc/server/autocvars.qh b/qcsrc/server/autocvars.qh index 415fedab8e..6aa798afb9 100644 --- a/qcsrc/server/autocvars.qh +++ b/qcsrc/server/autocvars.qh @@ -93,7 +93,7 @@ float autocvar_g_ballistics_density_corpse; float autocvar_g_ballistics_density_player; float autocvar_g_ballistics_mindistance; bool autocvar_g_ballistics_penetrate_clips = true; -float autocvar_g_ballistics_solidpenetration_exponent = 0.25; +float autocvar_g_ballistics_solidpenetration_exponent = 1; float autocvar_g_ban_default_bantime; float autocvar_g_ban_default_masksize; float autocvar_g_ban_sync_interval; @@ -301,6 +301,7 @@ int autocvar_sv_eventlog_files_counter; string autocvar_sv_eventlog_files_nameprefix; string autocvar_sv_eventlog_files_namesuffix; bool autocvar_sv_eventlog_files_timestamps; +bool autocvar_sv_eventlog_ipv6_delimiter = false; float autocvar_sv_friction_on_land; var float autocvar_sv_friction_slick = 0.5; float autocvar_sv_gameplayfix_q2airaccelerate = 1; @@ -529,4 +530,4 @@ bool autocvar_sv_showspectators; bool autocvar_g_weaponswitch_debug; bool autocvar_g_weaponswitch_debug_alternate; bool autocvar_g_allow_checkpoints; -bool autocvar_sv_vq3compat_changehitbox = false; +bool autocvar_sv_q3defragcompat_changehitbox = false; diff --git a/qcsrc/server/campaign.qc b/qcsrc/server/campaign.qc index 6fdb6d3398..f0fcea6abf 100644 --- a/qcsrc/server/campaign.qc +++ b/qcsrc/server/campaign.qc @@ -157,16 +157,28 @@ void CampaignPostInit() if(autocvar__campaign_testrun) { cvar_set("fraglimit", "0"); + cvar_set("leadlimit", "0"); cvar_set("timelimit", "0.01"); cvar_set_normal("fraglimit", "0"); + cvar_set_normal("leadlimit", "0"); cvar_set_normal("timelimit", "0.01"); } else { - cvar_set("fraglimit", ftos(campaign_fraglimit[0])); - cvar_set("timelimit", ftos(campaign_timelimit[0])); - cvar_set_normal("fraglimit", ftos(campaign_fraglimit[0])); - cvar_set_normal("timelimit", ftos(campaign_timelimit[0])); + // "default" uses implicit values, "" or "0" means no limit + tokenizebyseparator(campaign_fraglimit[0], "+"); + if(argv(0) != "default") { + cvar_set("fraglimit", argv(0)); + cvar_set_normal("fraglimit", argv(0)); + } + if(argv(1) != "default") { + cvar_set("leadlimit", argv(1)); + cvar_set_normal("leadlimit", argv(1)); + } + if(campaign_timelimit[0] != "default") { + cvar_set("timelimit", campaign_timelimit[0]); + cvar_set_normal("timelimit", campaign_timelimit[0]); + } } } diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index ceaecd6c4f..887e00c594 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -611,7 +611,8 @@ void PutPlayerInServer(entity this) this.respawn_flags = 0; this.respawn_time = 0; STAT(RESPAWN_TIME, this) = 0; - this.scale = autocvar_sv_player_scale; + bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox; + this.scale = ((q3dfcompat) ? 0.9 : autocvar_sv_player_scale); this.fade_time = 0; this.pain_frame = 0; this.pain_finished = 0; @@ -1107,7 +1108,7 @@ void ClientConnect(entity this) CS(this).allowed_timeouts = autocvar_sv_timeout_number; if (autocvar_sv_eventlog) - GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", playername(this, false))); + GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? GameLog_ProcessIP(this.netaddress) : "bot"), ":", playername(this, false))); CS(this).just_joined = true; // stop spamming the eventlog with additional lines when the client connects @@ -2216,27 +2217,25 @@ bool PlayerThink(entity this) this.items |= this.items_added; } - player_regen(this); - - // WEAPONTODO: Add a weapon request for this - // rot vortex charge to the charge limit - for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + if (frametime) { - .entity weaponentity = weaponentities[slot]; - if (WEP_CVAR(vortex, charge_rot_rate) && this.(weaponentity).vortex_charge > WEP_CVAR(vortex, charge_limit) && this.(weaponentity).vortex_charge_rottime < time) - this.(weaponentity).vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.(weaponentity).vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1); - } + // WEAPONTODO: Add a weapon request for this + // rot vortex charge to the charge limit + for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot) + { + .entity weaponentity = weaponentities[slot]; + if (WEP_CVAR(vortex, charge_rot_rate) && this.(weaponentity).vortex_charge > WEP_CVAR(vortex, charge_limit) && this.(weaponentity).vortex_charge_rottime < time) + this.(weaponentity).vortex_charge = bound(WEP_CVAR(vortex, charge_limit), this.(weaponentity).vortex_charge - WEP_CVAR(vortex, charge_rot_rate) * frametime / W_TICSPERFRAME, 1); + } - if (frametime) player_anim(this); + player_regen(this); + player_anim(this); + this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime); + } - // secret status secrets_setstatus(this); - - // monsters status monsters_setstatus(this); - this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime); - return true; } @@ -2466,7 +2465,7 @@ void PlayerPreThink (entity this) this.max_armorvalue = 0; } - if(IS_PLAYER(this)) + if (frametime && IS_PLAYER(this)) { if (STAT(FROZEN, this) == FROZEN_TEMP_REVIVING) { diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index 6928957d6d..ad9cab8e72 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -635,15 +635,22 @@ void ClientCommand_spectate(entity caller, int request) { if (!intermission_running && IS_CLIENT(caller)) { - if((IS_SPEC(caller) || IS_OBSERVER(caller)) && argv(1) != "") + if(argv(1) != "") { - entity client = GetFilteredEntity(argv(1)); - int spec_accepted = VerifyClientEntity(client, false, false); - if(spec_accepted > 0 && IS_PLAYER(client)) + if(IS_SPEC(caller) || IS_OBSERVER(caller)) { - if(Spectate(caller, client)) - return; // fall back to regular handling + entity client = GetFilteredEntity(argv(1)); + int spec_accepted = VerifyClientEntity(client, false, false); + if(spec_accepted > 0 && IS_PLAYER(client)) + { + Spectate(caller, client); + } + else + sprint(caller, "can't spectate ", argv(1), "^7\n"); } + else + sprint(caller, "cmd spectate client only works when you are spectator/observer\n"); + return; } int mutator_returnvalue = MUTATOR_CALLHOOK(ClientCommand_Spectate, caller); @@ -660,7 +667,7 @@ void ClientCommand_spectate(entity caller, int request) default: case CMD_REQUEST_USAGE: { - sprint(caller, "\nUsage:^3 cmd spectate \n"); + sprint(caller, "\nUsage:^3 cmd spectate [client]\n"); sprint(caller, " Where 'client' can be the player to spectate.\n"); return; } diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index b1d73f6a31..29621f61d8 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -412,6 +412,7 @@ IntrusiveList g_locations; IntrusiveList g_saved_team; IntrusiveList g_monster_targets; IntrusiveList g_pathlib_nodes; +IntrusiveList g_moveables; STATIC_INIT(defs) { g_monsters = IL_NEW(); @@ -433,4 +434,5 @@ STATIC_INIT(defs) g_saved_team = IL_NEW(); g_monster_targets = IL_NEW(); g_pathlib_nodes = IL_NEW(); + g_moveables = IL_NEW(); } diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index f739533fc8..2a3ede6b8d 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -330,11 +330,13 @@ void cvar_changes_init() BADCVAR("g_balance_kill_delay"); BADCVAR("g_buffs_pickup_anyway"); BADCVAR("g_buffs_randomize"); + BADCVAR("g_buffs_randomize_teamplay"); BADCVAR("g_campcheck_distance"); BADCVAR("g_ca_point_leadlimit"); BADCVAR("g_ca_point_limit"); BADCVAR("g_ctf_captimerecord_always"); BADCVAR("g_ctf_flag_glowtrails"); + BADCVAR("g_ctf_dynamiclights"); BADCVAR("g_ctf_flag_pickup_verbosename"); BADCVAR("g_domination_point_leadlimit"); BADCVAR("g_forced_respawn"); @@ -492,6 +494,7 @@ void cvar_changes_init() BADCVAR("g_ca_weaponarena"); BADCVAR("g_freezetag_weaponarena"); BADCVAR("g_lms_weaponarena"); + BADCVAR("g_ctf_stalemate_time"); if(cvar_string("g_mod_balance") == "Testing") { @@ -872,6 +875,12 @@ spawnfunc(worldspawn) MapInfo_Enumerate(); MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1); + if(fexists(strcat("scripts/", mapname, ".arena"))) + cvar_settemp("sv_q3acompat_machineshotgunswap", "1"); + + if(fexists(strcat("scripts/", mapname, ".defi"))) + cvar_settemp("sv_q3defragcompat", "1"); + if(whichpack(strcat("maps/", mapname, ".cfg")) != "") { int fd = fopen(strcat("maps/", mapname, ".cfg"), FILE_READ); @@ -2101,7 +2110,7 @@ void Physics_Frame() if(autocvar_sv_freezenonclients) return; - FOREACH_ENTITY_FLOAT(pure_data, false, + IL_EACH(g_moveables, true, { if(IS_CLIENT(it) || it.classname == "" || it.move_movetype == MOVETYPE_PUSH || it.move_movetype == MOVETYPE_FAKEPUSH || it.move_movetype == MOVETYPE_PHYSICS) continue; @@ -2127,7 +2136,7 @@ void Physics_Frame() if(autocvar_sv_gameplayfix_delayprojectiles >= 0) return; - FOREACH_ENTITY_FLOAT(move_qcphysics, true, + IL_EACH(g_moveables, it.move_qcphysics, { if(IS_CLIENT(it) || is_pure(it) || it.classname == "" || it.move_movetype == MOVETYPE_NONE) continue; diff --git a/qcsrc/server/miscfunctions.qc b/qcsrc/server/miscfunctions.qc index dd14a049e1..6e2bbb8d7c 100644 --- a/qcsrc/server/miscfunctions.qc +++ b/qcsrc/server/miscfunctions.qc @@ -33,6 +33,7 @@ #include "../common/state.qh" #include "../common/effects/qc/globalsound.qh" #include "../common/wepent.qh" +#include #include "../lib/csqcmodel/sv_model.qh" #include "../lib/warpzone/anglestransform.qh" #include "../lib/warpzone/server.qh" @@ -83,6 +84,13 @@ void dedicated_print(string input) if (server_is_dedicated) print(input); } +string GameLog_ProcessIP(string s) +{ + if(!autocvar_sv_eventlog_ipv6_delimiter) + return s; + return strreplace(":", "_", s); +} + void GameLogEcho(string s) { string fn; @@ -214,21 +222,6 @@ string NearestLocation(vector p) return ret; } -string AmmoNameFromWeaponentity(Weapon wep) -{ - string ammoitems = "batteries"; - switch (wep.ammo_type) - { - case RES_SHELLS: ammoitems = ITEM_Shells.m_name; break; - case RES_BULLETS: ammoitems = ITEM_Bullets.m_name; break; - case RES_ROCKETS: ammoitems = ITEM_Rockets.m_name; break; - case RES_CELLS: ammoitems = ITEM_Cells.m_name; break; - case RES_PLASMA: ammoitems = ITEM_Plasma.m_name; break; - case RES_FUEL: ammoitems = ITEM_JetpackFuel.m_name; break; - } - return ammoitems; -} - string PlayerHealth(entity this) { float myhealth = floor(GetResource(this, RES_HEALTH)); @@ -311,7 +304,7 @@ string formatmessage(entity this, string msg) case "y": replacement = NearestLocation(cursor); break; case "d": replacement = NearestLocation(this.death_origin); break; case "w": replacement = WeaponNameFromWeaponentity(this, weaponentity); break; - case "W": replacement = AmmoNameFromWeaponentity(this.(weaponentity).m_weapon); break; + case "W": replacement = GetAmmoName(this.(weaponentity).m_weapon.ammo_type); break; case "x": replacement = ((cursor_ent.netname == "" || !cursor_ent) ? "nothing" : cursor_ent.netname); break; case "s": replacement = ftos(vlen(this.velocity - this.velocity_z * '0 0 1')); break; case "S": replacement = ftos(vlen(this.velocity)); break; @@ -638,8 +631,6 @@ void weaponarena_available_most_update(entity this) void readplayerstartcvars() { - float i, t; - // initialize starting values for players start_weapons = '0 0 0'; start_weapons_default = '0 0 0'; @@ -723,11 +714,11 @@ void readplayerstartcvars() else { g_weaponarena = 1; - t = tokenize_console(s); + float t = tokenize_console(s); g_weaponarena_list = ""; - for (i = 0; i < t; ++i) + for (int j = 0; j < t; ++j) { - s = argv(i); + s = argv(j); Weapon wep = Weapons_fromstr(s); if(wep != WEP_Null) { @@ -1211,11 +1202,10 @@ bool SUB_NoImpactCheck(entity this, entity toucher) return false; } -#define SUB_OwnerCheck(ent,oth) ((oth) && ((oth) == (ent).owner)) - bool WarpZone_Projectile_Touch_ImpactFilter_Callback(entity this, entity toucher) { - if(SUB_OwnerCheck(this, toucher)) + // owner check + if(toucher && toucher == this.owner) return true; if(SUB_NoImpactCheck(this, toucher)) { @@ -1263,9 +1253,9 @@ void URI_Get_Callback(float id, float status, string data) } } -string uid2name(string myuid) { - string s; - s = db_get(ServerProgsDB, strcat("/uid2name/", myuid)); +string uid2name(string myuid) +{ + string s = db_get(ServerProgsDB, strcat("/uid2name/", myuid)); // FIXME remove this later after 0.6 release // convert old style broken records to correct style @@ -1284,20 +1274,18 @@ string uid2name(string myuid) { return s; } -float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance) +bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance) { - float m, i; - vector start, org, delta, end, enddown, mstart; - - m = e.dphitcontentsmask; + float m = e.dphitcontentsmask; e.dphitcontentsmask = goodcontents | badcontents; - org = boundmin; - delta = boundmax - boundmin; + vector org = boundmin; + vector delta = boundmax - boundmin; + vector start, end; start = end = org; - - for (i = 0; i < attempts; ++i) + int j; // used after the loop + for(j = 0; j < attempts; ++j) { start.x = org.x + random() * delta.x; start.y = org.y + random() * delta.y; @@ -1319,13 +1307,13 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma // rule 2: if we are too high, lower the point if (trace_fraction * delta.z > maxaboveground) start = trace_endpos + '0 0 1' * maxaboveground; - enddown = trace_endpos; + vector enddown = trace_endpos; // rule 3: make sure we aren't outside the map. This only works // for somewhat well formed maps. A good rule of thumb is that // the map should have a convex outside hull. // these can be traceLINES as we already verified the starting box - mstart = start + 0.5 * (e.mins + e.maxs); + vector mstart = start + 0.5 * (e.mins + e.maxs); traceline(mstart, mstart + '1 0 0' * delta.x, MOVE_NORMAL, e); if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk") continue; @@ -1342,35 +1330,35 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma if (trace_fraction >= 1 || trace_dphittexturename == "common/caulk") continue; - // rule 4: we must "see" some spawnpoint or item - entity sp = NULL; - IL_EACH(g_spawnpoints, checkpvs(mstart, it), - { - if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1) - { - sp = it; - break; - } - }); - if(!sp) - { - int items_checked = 0; - IL_EACH(g_items, checkpvs(mstart, it), + // rule 4: we must "see" some spawnpoint or item + entity sp = NULL; + IL_EACH(g_spawnpoints, checkpvs(mstart, it), + { + if((traceline(mstart, it.origin, MOVE_NORMAL, e), trace_fraction) >= 1) + { + sp = it; + break; + } + }); + if(!sp) { - if((traceline(mstart, it.origin + (it.mins + it.maxs) * 0.5, MOVE_NORMAL, e), trace_fraction) >= 1) + int items_checked = 0; + IL_EACH(g_items, checkpvs(mstart, it), { - sp = it; - break; - } + if((traceline(mstart, it.origin + (it.mins + it.maxs) * 0.5, MOVE_NORMAL, e), trace_fraction) >= 1) + { + sp = it; + break; + } - ++items_checked; - if(items_checked >= attempts) - break; // sanity - }); + ++items_checked; + if(items_checked >= attempts) + break; // sanity + }); - if(!sp) - continue; - } + if(!sp) + continue; + } // find a random vector to "look at" end.x = org.x + random() * delta.x; @@ -1380,17 +1368,17 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma // rule 4: start TO end must not be too short tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e); - if (trace_startsolid) + if(trace_startsolid) continue; - if (trace_fraction < minviewdistance / vlen(delta)) + if(trace_fraction < minviewdistance / vlen(delta)) continue; // rule 5: don't want to look at sky - if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) + if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY) continue; // rule 6: we must not end up in trigger_hurt - if (tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown)) + if(tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown)) continue; break; @@ -1398,15 +1386,14 @@ float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundma e.dphitcontentsmask = m; - if (i < attempts) + if(j < attempts) { setorigin(e, start); e.angles = vectoangles(end - start); - LOG_DEBUG("Needed ", ftos(i + 1), " attempts"); + LOG_DEBUG("Needed ", ftos(j + 1), " attempts"); return true; } - else - return false; + return false; } float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance) @@ -1488,24 +1475,13 @@ void follow_sameorigin(entity e, entity to) e.v_angle = e.angles - to.angles; // relative angles } +#if 0 +// TODO: unused, likely for a reason, possibly needs extensions (allow setting the new movetype as a parameter?) void unfollow_sameorigin(entity e) { set_movetype(e, MOVETYPE_NONE); } - -entity gettaginfo_relative_ent; -vector gettaginfo_relative(entity e, float tag) -{ - if (!gettaginfo_relative_ent) - { - gettaginfo_relative_ent = spawn(); - gettaginfo_relative_ent.effects = EF_NODRAW; - } - gettaginfo_relative_ent.model = e.model; - gettaginfo_relative_ent.modelindex = e.modelindex; - gettaginfo_relative_ent.frame = e.frame; - return gettaginfo(gettaginfo_relative_ent, tag); -} +#endif .string aiment_classname; .float aiment_deadflag; diff --git a/qcsrc/server/miscfunctions.qh b/qcsrc/server/miscfunctions.qh index 2b85a0476f..aa2f026e6d 100644 --- a/qcsrc/server/miscfunctions.qh +++ b/qcsrc/server/miscfunctions.qh @@ -74,6 +74,8 @@ string formatmessage(entity this, string msg); /** print(), but only print if the server is not local */ void dedicated_print(string input); +string GameLog_ProcessIP(string s); + void GameLogEcho(string s); void GameLogInit(); @@ -90,14 +92,12 @@ float LostMovetypeFollow(entity ent); string uid2name(string myuid); -float MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance); +bool MoveToRandomLocationWithinBounds(entity e, vector boundmin, vector boundmax, float goodcontents, float badcontents, float badsurfaceflags, int attempts, float maxaboveground, float minviewdistance); float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance); string NearestLocation(vector p); -string AmmoNameFromWeaponentity(Weapon wep); - void play2(entity e, string filename); string playername(entity p, bool team_colorize); diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc index 0410c2f9ec..59812425d6 100644 --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@ -374,14 +374,7 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void( restartanim = fr != WFRAME_IDLE; } - vector a = '0 0 0'; this.wframe = fr; - if (fr == WFRAME_IDLE) a = this.anim_idle; - else if (fr == WFRAME_FIRE1) a = this.anim_fire1; - else if (fr == WFRAME_FIRE2) a = this.anim_fire2; - else // if (fr == WFRAME_RELOAD) - a = this.anim_reload; - a.z *= g_weaponratefactor; if (this.weapon_think == w_ready && func != w_ready && this.state == WS_RAISE) backtrace( "Tried to override initial weapon think function - should this really happen?"); @@ -408,7 +401,7 @@ void weapon_thinkf(entity actor, .entity weaponentity, WFRAME fr, float t, void( { FOREACH_CLIENT(true, { if(it == actor || (IS_SPEC(it) && it.enemy == actor)) - wframe_send(it, this, a, restartanim); + wframe_send(it, this, fr, g_weaponratefactor, restartanim); }); } diff --git a/ruleset-overkill.cfg b/ruleset-overkill.cfg index cb39b2a10c..8b3f70a941 100644 --- a/ruleset-overkill.cfg +++ b/ruleset-overkill.cfg @@ -34,3 +34,5 @@ g_spawn_near_teammate "!g_assault !g_freezetag" g_spawn_near_teammate_ignore_spawnpoint 1 g_spawnshieldtime 0.5 g_respawn_delay_forced 2 + +g_ballistics_solidpenetration_exponent 0.25 diff --git a/scripts/electro.shader b/scripts/electro.shader index f87b86c8d9..8901438e85 100644 --- a/scripts/electro.shader +++ b/scripts/electro.shader @@ -10,7 +10,7 @@ electro_plasma_hull { { map textures/electro_plasma_hull.tga - alphaFunc GT0 + alphaFunc GE128 rgbGen Vertex } } @@ -22,4 +22,4 @@ electro map textures/electronew.tga rgbgen lightingDiffuse } -} \ No newline at end of file +} diff --git a/vehicles.cfg b/vehicles.cfg index d3a2c0bc56..7aa6e888f9 100644 --- a/vehicles.cfg +++ b/vehicles.cfg @@ -226,7 +226,7 @@ set g_vehicle_raptor_bouncepain "1 4 1000" set g_vehicle_raptor_cannon_cost 1 set g_vehicle_raptor_cannon_damage 10 set g_vehicle_raptor_cannon_radius 60 -set g_vehicle_raptor_cannon_refire 0.03 +set g_vehicle_raptor_cannon_refire 0.033333 set g_vehicle_raptor_cannon_speed 24000 set g_vehicle_raptor_cannon_spread 0.01 set g_vehicle_raptor_cannon_force 25 diff --git a/xonotic-client.cfg b/xonotic-client.cfg index e940811df0..29a49329a8 100644 --- a/xonotic-client.cfg +++ b/xonotic-client.cfg @@ -200,7 +200,7 @@ seta cl_hitsound_min_pitch 0.75 "minimum pitch of hit sound" seta cl_hitsound_max_pitch 1.5 "maximum pitch of hit sound" seta cl_hitsound_nom_damage 25 "damage amount at which hitsound bases pitch off" -seta cl_eventchase_spectated_change 1 "camera goes into 3rd person mode for a moment when changing spectated player" +seta cl_eventchase_spectated_change 0 "camera goes into 3rd person mode for a moment when changing spectated player" seta cl_eventchase_spectated_change_time 1 "how much time the effect lasts when changing spectated player" seta cl_eventchase_death 1 "camera goes into 3rd person mode when the player is dead; set to 2 to active the effect only when the corpse doesn't move anymore" seta cl_eventchase_frozen 0 "camera goes into 3rd person mode when the player is frozen" @@ -801,7 +801,7 @@ r_fullbright_directed 1 r_water_hideplayer 1 // hide your own feet/player model in refraction views, this way you don't see half of your body under water r_water_refractdistort 0.003 -set cl_rainsnow_maxdrawdist 2048 +set cl_rainsnow_maxdrawdist 1000 // safe font defaults r_font_hinting 1 diff --git a/xonotic-server.cfg b/xonotic-server.cfg index fad9b90f61..87ab27076a 100644 --- a/xonotic-server.cfg +++ b/xonotic-server.cfg @@ -314,6 +314,7 @@ set sv_eventlog_files_timestamps 1 "include timestamps in the log file names" set sv_eventlog_files_counter 0 "internal counter cvar, do not modify" set sv_eventlog_files_nameprefix xonotic "prefix of individual log file names" set sv_eventlog_files_namesuffix .log "suffix of individual log file names" +set sv_eventlog_ipv6_delimiter 0 "use a _ delimiter for IPV6 IPs, so that they can be easily detected in scripts" set nextmap "" "override the maplist when switching to the next map" set lastlevel "" "for singleplayer use, shows the menu once the match has ended" @@ -345,7 +346,7 @@ set g_maplist_votable_timeout 30 "timeout for the map voting; must be below 50 s set g_maplist_votable_suggestions 2 "number of maps a player is allowed to suggest for the map voting screen using 'suggestmap'" set g_maplist_votable_suggestions_override_mostrecent 0 "allow players to suggest maps that have been played recently" set g_maplist_votable_nodetail 0 "hide per-map vote counts (to avoid influential first votes)" -set g_maplist_votable_abstain 0 "offer a "\don't care\" option on the voting screen" +set g_maplist_votable_abstain 0 "offer a \"don't care\" option on the voting screen" set g_maplist_votable_screenshot_dir "maps levelshots" "where to look for map screenshots" set sv_vote_gametype 0 "show a vote screen for gametypes before map vote screen" @@ -430,7 +431,7 @@ set g_ballistics_mindistance 2 "when shooting through walls thinner than this, t set g_ballistics_density_player 0.50 "how hard players are to shoot through compared to walls" set g_ballistics_density_corpse 0.10 "how hard corpses are to shoot through compared to walls" set g_ballistics_penetrate_clips 1 "allow ballistics to pass through weapon clips" -set g_ballistics_solidpenetration_exponent 0.25 "how fast damage falls off when bullets pass through walls - 1 means linear, lower values mean slower initial falloff but faster once there's little solidpenetration left (damage_fraction = solidpen_fraction^exp for solidpen_fraction between 0 and 1)" +set g_ballistics_solidpenetration_exponent 1 "how fast damage falls off when bullets pass through walls - 1 means linear, lower values mean slower initial falloff but faster once there's little solidpenetration left (damage_fraction = solidpen_fraction^exp for solidpen_fraction between 0 and 1)" sv_status_show_qcstatus 1 "Xonotic uses this field instead of frags" set g_full_getstatus_responses 0 "this currently breaks qstat" @@ -487,7 +488,7 @@ sv_gameplayfix_gravityunaffectedbyticrate 1 sv_gameplayfix_nogravityonground 1 set sv_q3acompat_machineshotgunswap 0 "shorthand for swapping machinegun and shotgun (for Q3A map compatibility in mapinfo files)" -set sv_vq3compat 0 "toggle for some compatibility hacks (for VQ3 and CPM map compatibility in mapinfo files)" +set sv_q3defragcompat 0 "toggle for some compatibility hacks (for Q3DF map compatibility)" set g_movement_highspeed 1 "multiplier scale for movement speed (applies to sv_maxspeed and sv_maxairspeed, also applies to air acceleration when g_movement_highspeed_q3_compat is set to 0)" set g_movement_highspeed_q3_compat 0 "apply speed modifiers to air movement in a more Q3-compatible way (only apply speed buffs and g_movement_highspeed to max air speed, not to acceleration)" @@ -569,4 +570,6 @@ set sv_showspectators 1 "Show who's spectating who in the player info panel when set sv_damagetext 2 "<= 0: disabled, >= 1: visible to spectators, >= 2: visible to attacker, >= 3: all players see everyone's damage" set sv_showfps 5 "Show player's FPS counters in the scoreboard. This setting acts as a delay in seconds between updates" -set autocvar_sv_doors_always_open 0 "If set to 1 don't close doors which after they were open" +set sv_doors_always_open 0 "If set to 1 don't close doors which after they were open" + +set sv_warpzone_allow_selftarget 0 "do not touch"