]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'issue-1618-Add-Disconnect-button' into 'master'
authorMario <zacjardine@y7mail.com>
Thu, 26 Apr 2018 07:35:45 +0000 (07:35 +0000)
committerMario <zacjardine@y7mail.com>
Thu, 26 Apr 2018 07:35:45 +0000 (07:35 +0000)
Issue-1618 : add button to disconnect from server

Closes #1618

See merge request xonotic/xonotic-data.pk3dir!554

109 files changed:
.gitlab-ci.yml
.tx/merge-base
cmake/qcc.sh
common.kw.po
common.pl.po
common.pt.po
mutators.cfg
qcsrc/common/mutators/mutator/buffs/sv_buffs.qc
qcsrc/common/mutators/mutator/cloaked/sv_cloaked.qc
qcsrc/common/mutators/mutator/melee_only/sv_melee_only.qc
qcsrc/common/mutators/mutator/new_toys/sv_new_toys.qc
qcsrc/common/mutators/mutator/nix/sv_nix.qc
qcsrc/common/mutators/mutator/overkill/sv_overkill.qc
qcsrc/common/mutators/mutator/pinata/sv_pinata.qc
qcsrc/common/mutators/mutator/rocketminsta/sv_rocketminsta.qc
qcsrc/common/mutators/mutator/vampire/sv_vampire.qc
qcsrc/common/sounds/sound.qh
qcsrc/common/t_items.qc
qcsrc/common/triggers/defs.qh [new file with mode: 0644]
qcsrc/common/triggers/func/bobbing.qc
qcsrc/common/triggers/func/bobbing.qh
qcsrc/common/triggers/func/breakable.qc
qcsrc/common/triggers/func/breakable.qh
qcsrc/common/triggers/func/button.qc
qcsrc/common/triggers/func/button.qh
qcsrc/common/triggers/func/conveyor.qc
qcsrc/common/triggers/func/conveyor.qh
qcsrc/common/triggers/func/door.qc
qcsrc/common/triggers/func/door.qh
qcsrc/common/triggers/func/door_rotating.qc
qcsrc/common/triggers/func/door_rotating.qh
qcsrc/common/triggers/func/door_secret.qc
qcsrc/common/triggers/func/door_secret.qh
qcsrc/common/triggers/func/plat.qc
qcsrc/common/triggers/func/pointparticles.qc
qcsrc/common/triggers/func/pointparticles.qh
qcsrc/common/triggers/func/rainsnow.qc
qcsrc/common/triggers/func/rainsnow.qh
qcsrc/common/triggers/func/rotating.qc
qcsrc/common/triggers/func/rotating.qh
qcsrc/common/triggers/func/train.qc
qcsrc/common/triggers/func/train.qh
qcsrc/common/triggers/func/vectormamamam.qc
qcsrc/common/triggers/func/vectormamamam.qh
qcsrc/common/triggers/misc/follow.qc
qcsrc/common/triggers/misc/follow.qh
qcsrc/common/triggers/misc/laser.qc
qcsrc/common/triggers/misc/laser.qh
qcsrc/common/triggers/misc/teleport_dest.qc
qcsrc/common/triggers/platforms.qc
qcsrc/common/triggers/platforms.qh
qcsrc/common/triggers/subs.qc
qcsrc/common/triggers/subs.qh
qcsrc/common/triggers/target/changelevel.qc
qcsrc/common/triggers/target/changelevel.qh
qcsrc/common/triggers/target/levelwarp.qc
qcsrc/common/triggers/target/music.qc
qcsrc/common/triggers/target/music.qh
qcsrc/common/triggers/target/spawn.qc
qcsrc/common/triggers/target/speaker.qc
qcsrc/common/triggers/target/speaker.qh
qcsrc/common/triggers/teleporters.qh
qcsrc/common/triggers/trigger/counter.qc
qcsrc/common/triggers/trigger/counter.qh
qcsrc/common/triggers/trigger/flipflop.qc
qcsrc/common/triggers/trigger/gravity.qc
qcsrc/common/triggers/trigger/gravity.qh
qcsrc/common/triggers/trigger/heal.qc
qcsrc/common/triggers/trigger/heal.qh
qcsrc/common/triggers/trigger/hurt.qc
qcsrc/common/triggers/trigger/impulse.qc
qcsrc/common/triggers/trigger/impulse.qh
qcsrc/common/triggers/trigger/jumppads.qc
qcsrc/common/triggers/trigger/jumppads.qh
qcsrc/common/triggers/trigger/magicear.qc
qcsrc/common/triggers/trigger/magicear.qh
qcsrc/common/triggers/trigger/monoflop.qc
qcsrc/common/triggers/trigger/monoflop.qh
qcsrc/common/triggers/trigger/multi.qc
qcsrc/common/triggers/trigger/multivibrator.qc
qcsrc/common/triggers/trigger/relay.qc
qcsrc/common/triggers/trigger/relay_activators.qc
qcsrc/common/triggers/trigger/relay_if.qc
qcsrc/common/triggers/trigger/relay_if.qh
qcsrc/common/triggers/trigger/relay_teamcheck.qc
qcsrc/common/triggers/trigger/relay_teamcheck.qh
qcsrc/common/triggers/trigger/teleport.qc
qcsrc/common/triggers/trigger/viewloc.qc
qcsrc/common/triggers/trigger/viewloc.qh
qcsrc/common/triggers/triggers.qc
qcsrc/common/triggers/triggers.qh
qcsrc/common/turrets/turret/plasma.qc
qcsrc/common/turrets/turret/plasma_dual.qc
qcsrc/common/weapons/weapon/vaporizer.qc
qcsrc/ecs/systems/physics.qc
qcsrc/lib/_all.inc
qcsrc/lib/net.qh
qcsrc/lib/spawnfunc.qh
qcsrc/server/autocvars.qh
qcsrc/server/bot/default/waypoints.qc
qcsrc/server/bot/default/waypoints.qh
qcsrc/server/client.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/miscfunctions.qh
qcsrc/server/sv_main.qc
sound/misc/kill.ogg [deleted file]
sound/misc/kill.wav [new file with mode: 0644]
xonotic-server.cfg

index 4754425bf971689d6df0aaf9cfdad7f13dcd7595..12c3686e76ce1fc8d5b4da57d7e874fe9ec1d0db 100644 (file)
@@ -29,7 +29,7 @@ test_sv_game:
     - wget -O data/maps/stormkeep.waypoints https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints
     - wget -O data/maps/stormkeep.waypoints.cache https://gitlab.com/xonotic/xonotic-maps.pk3dir/raw/master/maps/stormkeep.waypoints.cache
     - make
-    - EXPECT=fb771b180a47f7acf09eb12dddd391f8
+    - EXPECT=b879b7f0d2da1b120211eabde0caab72
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index 431dcbe974dc57728a788a275a92bcbc985444ca..53527f3c728703d8d1aa6e9f5fc126198c7d0dbf 100644 (file)
@@ -1 +1 @@
-Sat Mar 17 07:23:46 CET 2018
+Fri Apr 20 07:23:54 CEST 2018
index 78119a59615bf0dfdabf5473c4f374ce76519bda..a6038dd59131c5df736e0862c8b29086f6833162 100755 (executable)
@@ -3,7 +3,16 @@ CPP=${CPP:-cpp}
 QCC=${QCC:-$PWD/../../gmqcc/gmqcc${CMAKE_EXECUTABLE_SUFFIX}}
 case $1 in
     compile)
-        ${CPP} ${@:3} | sed -E 's/^#(line)? ([[:digit:]]+) "(.*)".*/'$'\\\n''#pragma file(\3)'$'\\\n''#pragma line(\2)/g' > $2
+        for var in "$@"; do case "$var" in
+            -I*)
+                home=${var:2}
+                break
+                ;;
+        esac; done
+        ${CPP} ${@:3} \
+            | sed -E "s|${home}|~|g" \
+            | sed -E 's/^#(line)? ([[:digit:]]+) "(.*)".*/'$'\\\n''#pragma file(\3)'$'\\\n''#pragma line(\2)/g' \
+            > $2
     ;;
     link)
         ${QCC} \
index 33fbaf5be42b6257b4e7a8dd963119c9d8036ff7..9c550db7c1d0f57b30022d4c1c18f8bab346812f 100644 (file)
@@ -3,7 +3,8 @@
 # This file is distributed under the same license as the PACKAGE package.
 #
 # Translators:
-# Nicky Rowe <nickyrowe@gmail.com>, 2016
+# Nicky Rowe <nickyrowe688@gmail.com>, 2016
+# Nicky Rowe <nickyrowe688@gmail.com>, 2016
 msgid ""
 msgstr ""
 "Project-Id-Version: Xonotic\n"
index f8c5ab3bb4e145ab0637ed0f6d8413168984aa90..0b40453da5c9aa0dc5cfe785e3add14ea5e6ba47 100644 (file)
 # Kriss Chr <kriss7475@gmail.com>, 2017
 # Piotr Kozica <koza91@gmail.com>, 2016
 # RafaÅ‚ SzymaÅ„ski <okavasly@gmail.com>, 2017
-# Robert Wolniak <robert.wolniak@gmail.com>, 2015
+# Robert Wolniak <robert.wolniak@gmail.com>, 2015,2018
 # Sertomas, 2014
 msgid ""
 msgstr ""
 "Project-Id-Version: Xonotic\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2017-07-09 00:35+0200\n"
-"PO-Revision-Date: 2017-09-20 00:10+0000\n"
-"Last-Translator: RafaÅ‚ SzymaÅ„ski <okavasly@gmail.com>\n"
+"PO-Revision-Date: 2018-04-19 09:01+0000\n"
+"Last-Translator: Robert Wolniak <robert.wolniak@gmail.com>\n"
 "Language-Team: Polish (http://www.transifex.com/team-xonotic/xonotic/"
 "language/pl/)\n"
 "Language: pl\n"
@@ -1158,7 +1158,7 @@ msgstr ""
 
 #: qcsrc/common/gamemodes/gamemode/nexball/weapon.qh:7
 msgid "Ball Stealer"
-msgstr ""
+msgstr "ZÅ‚odziej Kuli"
 
 #: qcsrc/common/items/item/armor.qh:111
 msgid "Big armor"
@@ -1310,6 +1310,8 @@ msgid ""
 "Kill enemies to freeze them, stand next to frozen teammates to revive them; "
 "freeze all enemies to win"
 msgstr ""
+"Zabijaj przeciwników by ich zamrozić i stój obok czÅ‚onków swojej drużyny by "
+"ich wskrzesić; aby wygrać, zamroź wszystkich wrogów"
 
 #: qcsrc/common/mapinfo.qh:446
 msgid "Hold the ball to get points for kills"
@@ -1468,6 +1470,8 @@ msgid ""
 "You lost the game!\n"
 "Select \"^1Next Match^7\" on the menu for a rematch!"
 msgstr ""
+"Przegrana meczu!\n"
+"Wybierz w menu opcjÄ™ \"^1NastÄ™pny Mecz^7\" po rewanż!"
 
 #: qcsrc/common/minigames/minigame/pp.qc:444
 #: qcsrc/common/minigames/minigame/ttt.qc:325
@@ -1475,16 +1479,18 @@ msgid ""
 "You win!\n"
 "Select \"^1Next Match^7\" on the menu to start a new match!"
 msgstr ""
+"Wygrana!\n"
+"Wybierz w menu opcjÄ™ \"^1NastÄ™pny Mecz^7\" by rozpocząć nowÄ… grÄ™!"
 
 #: qcsrc/common/minigames/minigame/pp.qc:450
 #: qcsrc/common/minigames/minigame/ttt.qc:331
 msgid "Select \"^1Next Match^7\" on the menu to start a new match!"
-msgstr ""
+msgstr "Wybierz w menu opcjÄ™ \"^1NastÄ™pny Mecz^7\" by rozpocząć nowÄ… grÄ™!"
 
 #: qcsrc/common/minigames/minigame/pp.qc:451
 #: qcsrc/common/minigames/minigame/ttt.qc:332
 msgid "Wait for your opponent to confirm the rematch"
-msgstr ""
+msgstr "Poczekaj aż twój przeciwnik potwierdzi rewanż."
 
 #: qcsrc/common/minigames/minigame/pp.qc:582
 #: qcsrc/common/minigames/minigame/ttt.qc:665
index ec526d5e35b64187d305a117a1b2087a16b86cc5..c7f46b867abaea8e99456dd866004e98d4522777 100644 (file)
@@ -4,7 +4,7 @@
 #
 # Translators:
 # Ivan Paulos Tomé <greylica@gmail.com>, 2016
-# Jean Trindade Pereira <jean_trindade2@hotmail.com>, 2015-2017
+# Jean Trindade Pereira <jean_trindade2@hotmail.com>, 2015-2018
 # Mirio <opivy@hotmail.de>, 2017
 # NotThatPrivate Yes <henriqueferreira2009@gmail.com>, 2015
 # Ricardo Manuel da Cruz Coelho da Silva <ricardo.mccs@gmail.com>, 2015
@@ -13,7 +13,7 @@ msgstr ""
 "Project-Id-Version: Xonotic\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2017-07-09 00:35+0200\n"
-"PO-Revision-Date: 2017-12-21 15:23+0000\n"
+"PO-Revision-Date: 2018-04-17 20:43+0000\n"
 "Last-Translator: Jean Trindade Pereira <jean_trindade2@hotmail.com>\n"
 "Language-Team: Portuguese (http://www.transifex.com/team-xonotic/xonotic/"
 "language/pt/)\n"
@@ -765,16 +765,16 @@ msgid ""
 "^3caps^7                     How often a flag (CTF) or a key (KeyHunt) was "
 "captured\n"
 msgstr ""
-"^3capturas^7 Quão frequente uma bandeira (CTF) ou uma chave (KeyHunt) foi "
-"capturada\n"
+"^3capturas^7 Quão frequente uma bandeira (CTF) ou uma chave (Caça a Chaves) "
+"foi capturada\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:317
 msgid ""
 "^3pickups^7                  How often a flag (CTF) or a key (KeyHunt) or a "
 "ball (Keepaway) was picked up\n"
 msgstr ""
-"^3coletas^7. Quão frequente uma bandeira (CTF), uma chave (KeyHunt) ou uma "
-"bola (Keepaway) foi coletada\n"
+"^3coletas^7. Quão frequente uma bandeira (CTF), uma chave (Caça a Chaves) ou "
+"uma bola (Keepaway) foi coletada\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:318
 msgid "^3captime^7                  Time of fastest cap (CTF)\n"
@@ -1207,7 +1207,7 @@ msgstr "Consiga o máximo de execuções que puder"
 
 #: qcsrc/common/mapinfo.qh:111
 msgid "Last Man Standing"
-msgstr "Last Man Standing"
+msgstr "Último Homem de Pé"
 
 #: qcsrc/common/mapinfo.qh:111
 msgid "Survive and kill until the enemies have no lives left"
@@ -1251,7 +1251,7 @@ msgstr ""
 
 #: qcsrc/common/mapinfo.qh:249
 msgid "Clan Arena"
-msgstr "Clan Arena"
+msgstr "Clã Arena"
 
 #: qcsrc/common/mapinfo.qh:249
 msgid "Kill all enemy teammates to win the round"
@@ -1263,7 +1263,7 @@ msgstr "Capture e defenda todos os pontos de controle para vencer"
 
 #: qcsrc/common/mapinfo.qh:287
 msgid "Domination"
-msgstr "Domination"
+msgstr "Dominação"
 
 #: qcsrc/common/mapinfo.qh:319
 msgid "Gather all the keys to win the round"
@@ -1271,11 +1271,11 @@ msgstr "Colete todas as chaves para vencer a rodada"
 
 #: qcsrc/common/mapinfo.qh:319
 msgid "Key Hunt"
-msgstr "Key Hunt"
+msgstr "Caça a Chaves"
 
 #: qcsrc/common/mapinfo.qh:353
 msgid "Assault"
-msgstr "Assault"
+msgstr "Assalto"
 
 #: qcsrc/common/mapinfo.qh:353
 msgid ""
@@ -1291,11 +1291,11 @@ msgstr "Capture pontos de controle para alcançar e destruir o gerador inimigo"
 
 #: qcsrc/common/mapinfo.qh:371
 msgid "Onslaught"
-msgstr "Onslaught"
+msgstr "Massacre"
 
 #: qcsrc/common/mapinfo.qh:387
 msgid "Nexball"
-msgstr "Nexball"
+msgstr "Bola Nex"
 
 #: qcsrc/common/mapinfo.qh:387
 msgid "Shoot and kick the ball into the enemies goal, keep your goal clean"
@@ -1303,7 +1303,7 @@ msgstr "Atire e chute a bola no gol inimigo e mantenha seu gol limpo"
 
 #: qcsrc/common/mapinfo.qh:408
 msgid "Freeze Tag"
-msgstr "Freeze Tag"
+msgstr "Congela"
 
 #: qcsrc/common/mapinfo.qh:408
 msgid ""
@@ -1323,7 +1323,7 @@ msgstr "Keepaway"
 
 #: qcsrc/common/mapinfo.qh:461
 msgid "Invasion"
-msgstr "Invasion"
+msgstr "Invasão"
 
 #: qcsrc/common/mapinfo.qh:461
 msgid "Survive against waves of monsters"
@@ -5217,7 +5217,7 @@ msgstr "Tempo de desaparecimento:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:25
 msgid "Flip messages order"
-msgstr "Trocar ordem de notificações"
+msgstr "Trocar ordem de mensagens"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:27
 #: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:15
@@ -5704,7 +5704,7 @@ msgstr "Exibir munições"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:68
 msgid "Ammo bar alpha:"
-msgstr "Cor da barra de munições:"
+msgstr "Transparência da barra de munições:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:74
 msgid "Ammo bar color:"
@@ -6327,7 +6327,7 @@ msgstr "Modificadores de armas e itens:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:204
 msgid "Grappling hook"
-msgstr "Gancho (grappling hook)"
+msgstr "Gancho de escalada"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:205
 msgid "Players spawn with the grappling hook"
index 32145dd04c8128f7e65b24d7a0c752d2d9b6cc7c..c997a807f459574846fc3de6b11af14ddbe7447b 100644 (file)
@@ -276,7 +276,7 @@ set g_nades_entrap_radius 500
 
 // Veil (9)
 set g_nades_veil_time 8 "Life time of the orb"
-set g_nades_veil_radius 300
+set g_nades_veil_radius 200
 
 
 // ============
index 937f4cbde4ba00c19395d58c45dd7e6add6aba03..4a54d8117d24ba4ae80bf772e792d1ec1286464f 100644 (file)
@@ -926,7 +926,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
 
                BUFF_ONADD(BUFF_INVISIBLE)
                {
-                       if(time < player.strength_finished && g_instagib)
+                       if(time < player.strength_finished && autocvar_g_instagib)
                                player.buff_invisible_prev_alpha = default_player_alpha; // we don't want to save the powerup's alpha, as player may lose the powerup while holding the buff
                        else
                                player.buff_invisible_prev_alpha = player.alpha;
@@ -935,7 +935,7 @@ MUTATOR_HOOKFUNCTION(buffs, PlayerPreThink)
 
                BUFF_ONREM(BUFF_INVISIBLE)
                {
-                       if(time < player.strength_finished && g_instagib)
+                       if(time < player.strength_finished && autocvar_g_instagib)
                                player.alpha = autocvar_g_instagib_invis_alpha;
                        else
                                player.alpha = player.buff_invisible_prev_alpha;
index a1fe27a877c3e46e5e4dfe59a15239c583930f0a..5f9de3b7cbfd906461a58d55d5edace06b9f71e6 100644 (file)
@@ -1,7 +1,7 @@
 #include "sv_cloaked.qh"
 
-string autocvar_g_cloaked;
-REGISTER_MUTATOR(cloaked, expr_evaluate(autocvar_g_cloaked));
+//string autocvar_g_cloaked;
+REGISTER_MUTATOR(cloaked, expr_evaluate(cvar_string("g_cloaked")));
 
 float autocvar_g_balance_cloaked_alpha;
 
index 5603dd4901c0601cc8940320acbc1f87b6ab1f3e..2f8b45a99b46f09450ab44c93867b236b4ef4639 100644 (file)
@@ -1,7 +1,7 @@
 #include "sv_melee_only.qh"
 
 string autocvar_g_melee_only;
-REGISTER_MUTATOR(melee_only, expr_evaluate(autocvar_g_melee_only) && !cvar("g_instagib") && !cvar("g_overkill") && !g_nexball);
+REGISTER_MUTATOR(melee_only, expr_evaluate(autocvar_g_melee_only) && !autocvar_g_instagib && !cvar("g_overkill") && !g_nexball);
 
 MUTATOR_HOOKFUNCTION(melee_only, SetStartItems, CBC_ORDER_LAST)
 {
index ec2593215a09b5187abd522608e07dc6f978e141..3ac652d7807df5d1ee4797dad9f16134b25dd756 100644 (file)
@@ -70,11 +70,11 @@ roflsound "New toys, new toys!" sound.
 
 */
 
-string autocvar_g_new_toys;
+//string autocvar_g_new_toys;
 
 bool nt_IsNewToy(int w);
 
-REGISTER_MUTATOR(nt, expr_evaluate(autocvar_g_new_toys) && !cvar("g_instagib") && !cvar("g_overkill"))
+REGISTER_MUTATOR(nt, expr_evaluate(cvar_string("g_new_toys")) && !autocvar_g_instagib && !cvar("g_overkill"))
 {
        MUTATOR_ONADD
        {
index 953321cc0ba5a708bb30d73e0e218b8e4ad67cf0..e88ff9b552984feb7a083932173d64939709ab52 100644 (file)
@@ -1,6 +1,6 @@
 #include "sv_nix.qh"
 
-string autocvar_g_nix;
+//string autocvar_g_nix;
 int autocvar_g_balance_nix_ammo_cells;
 int autocvar_g_balance_nix_ammo_plasma;
 int autocvar_g_balance_nix_ammo_fuel;
@@ -36,7 +36,7 @@ float nix_nextweapon;
 
 bool NIX_CanChooseWeapon(int wpn);
 
-REGISTER_MUTATOR(nix, expr_evaluate(autocvar_g_nix) && !cvar("g_instagib") && !cvar("g_overkill"))
+REGISTER_MUTATOR(nix, expr_evaluate(cvar_string("g_nix")) && !autocvar_g_instagib && !cvar("g_overkill"))
 {
        MUTATOR_ONADD
        {
index e9106239467ffc7432cda21fa887481db192a6cc..582a8d35bcb9cfcd42182f8064312ef4fd3dc449 100644 (file)
@@ -11,7 +11,7 @@ bool autocvar_g_overkill_itemwaypoints = true;
 
 .Weapon ok_lastwep[MAX_WEAPONSLOTS];
 
-REGISTER_MUTATOR(ok, expr_evaluate(autocvar_g_overkill) && !cvar("g_instagib") && !g_nexball && cvar_string("g_mod_balance") == "Overkill")
+REGISTER_MUTATOR(ok, expr_evaluate(autocvar_g_overkill) && !autocvar_g_instagib && !g_nexball && cvar_string("g_mod_balance") == "Overkill")
 {
        MUTATOR_ONADD
        {
index 1084ff77895aa079e2dd9104ffe1159551f54db2..c5bf2262eb35e37523c3ac83caa559d4ef1e8d6d 100644 (file)
@@ -1,7 +1,7 @@
 #include "sv_pinata.qh"
 
 string autocvar_g_pinata;
-REGISTER_MUTATOR(pinata, expr_evaluate(autocvar_g_pinata) && !cvar("g_instagib") && !cvar("g_overkill"));
+REGISTER_MUTATOR(pinata, expr_evaluate(autocvar_g_pinata) && !autocvar_g_instagib && !cvar("g_overkill"));
 
 MUTATOR_HOOKFUNCTION(pinata, PlayerDies)
 {
index 7edef9813de0fd3c13ca1d79d6593674202c32c1..c6def68e1b61f6ddb56f76bdac458ad3ef5db931 100644 (file)
@@ -3,7 +3,7 @@
 #include <common/deathtypes/all.qh>
 #include <server/round_handler.qh>
 
-REGISTER_MUTATOR(rm, cvar("g_instagib"));
+REGISTER_MUTATOR(rm, autocvar_g_instagib);
 
 MUTATOR_HOOKFUNCTION(rm, Damage_Calculate)
 {
index 199b4e202a7351a9b2d25bfb4364ec02119a259d..b599805a45774f6d971087191a259ebffef342c1 100644 (file)
@@ -1,7 +1,7 @@
 #include "sv_vampire.qh"
 
 string autocvar_g_vampire;
-REGISTER_MUTATOR(vampire, expr_evaluate(autocvar_g_vampire) && !cvar("g_instagib"));
+REGISTER_MUTATOR(vampire, expr_evaluate(autocvar_g_vampire) && !autocvar_g_instagib);
 
 MUTATOR_HOOKFUNCTION(vampire, PlayerDamage_SplitHealthArmor)
 {
index 036c0867013124ede9dce8ccbcc677dd9fa69271..d46ac9eafc7c36cccbeb07c7d302fe9b25f250d3 100644 (file)
@@ -22,7 +22,7 @@ const int CH_PLAYER_SINGLE = 7;
 // const int CH_BGM_SINGLE = -8;
 const int CH_BGM_SINGLE = 8;
 const int CH_AMBIENT = -9;
-// const int CH_AMBIENT_SINGLE = 9;
+const int CH_AMBIENT_SINGLE = 9;
 
 const float ATTEN_NONE = 0;
 const float ATTEN_MIN = 0.015625;
index 956b1cbe07e2735166bc8884e73cd9d6589f7070..039d27da351f284a3766d9684a6bbf2c45838b72 100644 (file)
@@ -252,6 +252,8 @@ NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
                                this.item_simple = false;
                 LOG_TRACEF("Simple item requested for %s but no model exists for it", _fn);
                        } while (0);
+                       #undef tryext
+                       #undef extensions
         }
 
         if(!this.item_simple)
diff --git a/qcsrc/common/triggers/defs.qh b/qcsrc/common/triggers/defs.qh
new file mode 100644 (file)
index 0000000..45afb51
--- /dev/null
@@ -0,0 +1,41 @@
+#pragma once
+
+//-----------
+// SPAWNFLAGS
+//-----------
+const int START_ENABLED = BIT(0);
+const int START_DISABLED = BIT(0);
+const int ALL_ENTITIES = BIT(1);
+const int ON_MAPLOAD = BIT(1);
+const int INVERT_TEAMS = BIT(2);
+const int CRUSH = BIT(2);
+const int NOSPLASH = BIT(8); // generic anti-splashdamage spawnflag
+const int ONLY_PLAYERS = BIT(14);
+
+// triggers
+const int SPAWNFLAG_NOMESSAGE = BIT(0);
+const int SPAWNFLAG_NOTOUCH = BIT(0);
+
+//----------
+// SENDFLAGS
+//----------
+const int SF_TRIGGER_INIT = BIT(0);
+const int SF_TRIGGER_UPDATE = BIT(1);
+const int SF_TRIGGER_RESET = BIT(2);
+
+//----------------
+// STATES & ACTIVE
+//----------------
+#ifdef CSQC
+// this stuff is defined in the server side engine VM, so we must define it separately here
+const int STATE_TOP = 0;
+const int STATE_BOTTOM = 1;
+const int STATE_UP = 2;
+const int STATE_DOWN = 3;
+
+const int ACTIVE_NOT = 0;
+const int ACTIVE_ACTIVE = 1;
+const int ACTIVE_IDLE = 2;
+const int ACTIVE_BUSY = 2;
+const int ACTIVE_TOGGLE = 3;
+#endif
index ff8841a570030853d2ce70b1602bc06ba2c31c60..b647e15a826e48164f03db46c5f62114a8e6afc6 100644 (file)
@@ -59,9 +59,9 @@ spawnfunc(func_bobbing)
        this.dmgtime2 = time;
 
        // how far to bob
-       if (this.spawnflags & 1) // X
+       if (this.spawnflags & BOBBING_XAXIS)
                this.movedir = '1 0 0' * this.height;
-       else if (this.spawnflags & 2) // Y
+       else if (this.spawnflags & BOBBING_YAXIS)
                this.movedir = '0 1 0' * this.height;
        else // Z
                this.movedir = '0 0 1' * this.height;
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..58f7bb71456e37eaa43a744d8aeb28a06a877269 100644 (file)
@@ -1 +1,5 @@
 #pragma once
+
+
+const int BOBBING_XAXIS = BIT(0);
+const int BOBBING_YAXIS = BIT(1);
index ec71bc3fc3b044e10888e56a1e8a6d0d4c872c32..d09ccd5e00a8cede8584138723c607d37637ea9c 100644 (file)
 //   target = targets to trigger when broken
 //   health = amount of damage it can take
 //   spawnflags:
-//     1 = start disabled (needs to be triggered to activate)
-//     2 = indicate damage
-//     4 = don't take direct damage (needs to be triggered to 'explode', then triggered again to restore)
+//     START_DISABLED: needs to be triggered to activate
+//     BREAKABLE_INDICATE_DAMAGE: indicate damage
+//     BREAKABLE_NODAMAGE: don't take direct damage (needs to be triggered to 'explode', then triggered again to restore)
+//     NOSPLASH: don't take splash damage
 // notes:
 //   for mdl_dead to work, origin must be set (using a common/origin brush).
 //   Otherwise mdl_dead will be displayed at the map origin, and nobody would
@@ -81,7 +82,7 @@ void LaunchDebris (entity this, string debrisname, vector force)
 void func_breakable_colormod(entity this)
 {
        float h;
-       if (!(this.spawnflags & 2))
+       if (!(this.spawnflags & BREAKABLE_INDICATE_DAMAGE))
                return;
        h = this.health / this.max_health;
        if(h < 0.25)
@@ -135,8 +136,8 @@ void func_breakable_behave_destroyed(entity this)
                IL_REMOVE(g_bot_targets, this);
        this.bot_attack = false;
        this.event_damage = func_null;
-       this.state = 1;
-       if(this.spawnflags & 4)
+       this.state = STATE_BROKEN;
+       if(this.spawnflags & BREAKABLE_NODAMAGE)
                this.use = func_null;
        func_breakable_colormod(this);
        if (this.noise1)
@@ -158,7 +159,7 @@ void func_breakable_behave_restore(entity this)
                WaypointSprite_UpdateMaxHealth(this.sprite, this.max_health);
                WaypointSprite_UpdateHealth(this.sprite, this.health);
        }
-       if(!(this.spawnflags & 4))
+       if(!(this.spawnflags & BREAKABLE_NODAMAGE))
        {
                this.takedamage = DAMAGE_AIM;
                if(!this.bot_attack)
@@ -166,9 +167,9 @@ void func_breakable_behave_restore(entity this)
                this.bot_attack = true;
                this.event_damage = func_breakable_damage;
        }
-       if(this.spawnflags & 4)
+       if(this.spawnflags & BREAKABLE_NODAMAGE)
                this.use = func_breakable_destroy; // don't need to set it usually, as .use isn't reset
-       this.state = 0;
+       this.state = STATE_ALIVE;
        //this.nextthink = 0; // cancel auto respawn
        setthink(this, func_breakable_think);
        this.nextthink = time + 0.1;
@@ -179,7 +180,7 @@ void func_breakable_behave_restore(entity this)
 
 void func_breakable_init_for_player(entity this, entity player)
 {
-       if (this.noise1 && this.state == 0 && IS_REAL_CLIENT(player))
+       if (this.noise1 && this.state == STATE_ALIVE && IS_REAL_CLIENT(player))
        {
                msg_entity = player;
                soundto (MSG_ONE, this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
@@ -248,9 +249,9 @@ void func_breakable_destroy_self(entity this)
 
 void func_breakable_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
 {
-       if(this.state == 1)
+       if(this.state == STATE_BROKEN)
                return;
-       if(this.spawnflags & DOOR_NOSPLASH)
+       if(this.spawnflags & NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
        if(this.team)
@@ -290,7 +291,7 @@ void func_breakable_reset(entity this)
 {
        this.team = this.team_saved;
        func_breakable_look_restore(this);
-       if(this.spawnflags & 1)
+       if(this.spawnflags & START_DISABLED)
                func_breakable_behave_destroyed(this);
        else
                func_breakable_behave_restore(this);
@@ -330,12 +331,12 @@ spawnfunc(func_breakable)
        this.mdl = this.model;
        SetBrushEntityModel(this);
 
-       if(this.spawnflags & 4)
+       if(this.spawnflags & BREAKABLE_NODAMAGE)
                this.use = func_breakable_destroy;
        else
                this.use = func_breakable_restore;
 
-       if(this.spawnflags & 4)
+       if(this.spawnflags & BREAKABLE_NODAMAGE)
        {
                this.takedamage = DAMAGE_NO;
                this.event_damage = func_null;
index 761a2c7a98f350fe53629bc13f74e3874eb19673..0efbcfaed5eb809c544d2f245d02467096b56ba7 100644 (file)
@@ -1,5 +1,12 @@
 #pragma once
 
+
+const int BREAKABLE_INDICATE_DAMAGE = BIT(1);
+const int BREAKABLE_NODAMAGE = BIT(2);
+
+const int STATE_ALIVE = 0;
+const int STATE_BROKEN = 1;
+
 #ifdef SVQC
 spawnfunc(func_breakable);
 #endif
index c51c034f1681caef48773e01172325e19b7848e9..28e6481c880886c18d240fc3cc55719eb80668d6 100644 (file)
@@ -91,7 +91,7 @@ void button_touch(entity this, entity toucher)
 
 void button_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
 {
-       if(this.spawnflags & DOOR_NOSPLASH)
+       if(this.spawnflags & NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
        if (this.spawnflags & BUTTON_DONTACCUMULATEDMG)
@@ -123,11 +123,7 @@ When a button is touched, it moves some distance in the direction of it's angle,
 "wait"         override the default 1 second wait (-1 = never return)
 "lip"          override the default 4 pixel lip remaining at end of move
 "health"       if set, the button must be killed instead of touched. If set to -1, the button will fire on ANY attack, even damageless ones like the InstaGib laser
-"sounds"
-0) steam metal
-1) wooden clunk
-2) metallic click
-3) in-out
+"noise"                sound that is played when the button is activated
 */
 spawnfunc(func_button)
 {
index 75a6006eb5e703e24b79362c9df7b0f39e328376..86a0fc918050846f848a47a981295a292223cf3b 100644 (file)
@@ -1,3 +1,4 @@
 #pragma once
 
-const int BUTTON_DONTACCUMULATEDMG = 128;
+
+const int BUTTON_DONTACCUMULATEDMG = BIT(7);
index 1802a75db4a96a74ab2b56eb9531a748923bfa91..9ad326cfa225f7ef9b0c08151e96f4feeacdff39 100644 (file)
@@ -17,9 +17,9 @@ void conveyor_think(entity this)
                IL_REMOVE(g_conveyed, it);
        });
 
-       if(this.state)
+       if(this.active == ACTIVE_ACTIVE)
        {
-               FOREACH_ENTITY_RADIUS((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1, !it.conveyor.state && isPushable(it),
+               FOREACH_ENTITY_RADIUS((this.absmin + this.absmax) * 0.5, vlen(this.absmax - this.absmin) * 0.5 + 1, it.conveyor.active == ACTIVE_NOT && isPushable(it),
                {
                        vector emin = it.absmin;
                        vector emax = it.absmax;
@@ -63,26 +63,12 @@ void conveyor_think(entity this)
 
 #ifdef SVQC
 
-void conveyor_use(entity this, entity actor, entity trigger)
-{
-       this.state = !this.state;
-
-       this.SendFlags |= 2;
-}
-
-void conveyor_reset(entity this)
-{
-       this.state = (this.spawnflags & 1);
-
-       this.SendFlags |= 2;
-}
-
-bool conveyor_send(entity this, entity to, int sf)
+bool conveyor_send(entity this, entity to, int sendflags)
 {
        WriteHeader(MSG_ENTITY, ENT_CLIENT_CONVEYOR);
-       WriteByte(MSG_ENTITY, sf);
+       WriteByte(MSG_ENTITY, sendflags);
 
-       if(sf & 1)
+       if(sendflags & SF_TRIGGER_INIT)
        {
                WriteByte(MSG_ENTITY, this.warpzone_isboxy);
                WriteVector(MSG_ENTITY, this.origin);
@@ -93,14 +79,14 @@ bool conveyor_send(entity this, entity to, int sf)
                WriteVector(MSG_ENTITY, this.movedir);
 
                WriteByte(MSG_ENTITY, this.speed);
-               WriteByte(MSG_ENTITY, this.state);
+               WriteByte(MSG_ENTITY, this.active);
 
                WriteString(MSG_ENTITY, this.targetname);
                WriteString(MSG_ENTITY, this.target);
        }
 
-       if(sf & 2)
-               WriteByte(MSG_ENTITY, this.state);
+       if(sendflags & SF_TRIGGER_UPDATE)
+               WriteByte(MSG_ENTITY, this.active);
 
        return true;
 }
@@ -111,20 +97,20 @@ void conveyor_init(entity this)
        this.movedir *= this.speed;
        setthink(this, conveyor_think);
        this.nextthink = time;
+       this.setactive = generic_netlinked_setactive;
        IFTARGETED
        {
-               this.use = conveyor_use;
-               this.reset = conveyor_reset;
-               this.reset(this);
+               // backwards compatibility
+               this.use = generic_netlinked_legacy_use;
        }
-       else
-               this.state = 1;
+       this.reset = generic_netlinked_reset;
+       this.reset(this);
 
        FixSize(this);
 
        Net_LinkEntity(this, 0, false, conveyor_send);
 
-       this.SendFlags |= 1;
+       this.SendFlags |= SF_TRIGGER_INIT;
 }
 
 spawnfunc(trigger_conveyor)
@@ -161,9 +147,9 @@ void conveyor_init(entity this, bool isnew)
 
 NET_HANDLE(ENT_CLIENT_CONVEYOR, bool isnew)
 {
-       int sf = ReadByte();
+       int sendflags = ReadByte();
 
-       if(sf & 1)
+       if(sendflags & SF_TRIGGER_INIT)
        {
                this.warpzone_isboxy = ReadByte();
                this.origin = ReadVector();
@@ -176,7 +162,7 @@ NET_HANDLE(ENT_CLIENT_CONVEYOR, bool isnew)
                this.movedir = ReadVector();
 
                this.speed = ReadByte();
-               this.state = ReadByte();
+               this.active = ReadByte();
 
                this.targetname = strzone(ReadString());
                this.target = strzone(ReadString());
@@ -184,8 +170,8 @@ NET_HANDLE(ENT_CLIENT_CONVEYOR, bool isnew)
                conveyor_init(this, isnew);
        }
 
-       if(sf & 2)
-               this.state = ReadByte();
+       if(sendflags & SF_TRIGGER_UPDATE)
+               this.active = ReadByte();
 
        return true;
 }
index c12b52d2dd19118e4d0a7209329796446922cbeb..22b674ff36098192b0c8409a029122e6b88ec4b1 100644 (file)
@@ -1,4 +1,5 @@
 #pragma once
+#include "../defs.qh"
 
 IntrusiveList g_conveyed;
 STATIC_INIT(g_conveyed) { g_conveyed = IL_NEW(); }
index 956114a26b38a95a85d7c2225405eca5b2330bf7..c19041aa0b1b7ad2269597caa1ea93040a26afa6 100644 (file)
@@ -1,4 +1,5 @@
 #include "door.qh"
+#include "door_rotating.qh"
 /*
 
 Doors are similar to buttons, but can spawn a fat trigger field around them
@@ -23,12 +24,10 @@ THINK FUNCTIONS
 
 void door_go_down(entity this);
 void door_go_up(entity this, entity actor, entity trigger);
-void door_rotating_go_down(entity this);
-void door_rotating_go_up(entity this, entity oth);
 
 void door_blocked(entity this, entity blocker)
 {
-       if((this.spawnflags & 8)
+       if((this.spawnflags & DOOR_CRUSH)
 #ifdef SVQC
                && (blocker.takedamage != DAMAGE_NO)
 #elif defined(CSQC)
@@ -177,7 +176,7 @@ bool door_check_keys(entity door, entity player)
        if(!door.itemkeys)
        {
 #ifdef SVQC
-               play2(player, SND(TALK));
+               play2(player, door.noise);
                Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_DOOR_UNLOCKED);
 #endif
                return true;
@@ -238,12 +237,12 @@ void door_fire(entity this, entity actor, entity trigger)
                        door_go_up(e, actor, trigger);
                } else {
                        // if the BIDIR spawnflag (==2) is set and the trigger has set trigger_reverse, reverse the opening direction
-                       if ((e.spawnflags & 2) && trigger.trigger_reverse!=0 && e.lip != 666 && e.state == STATE_BOTTOM) {
+                       if ((e.spawnflags & DOOR_ROTATING_BIDIR) && trigger.trigger_reverse!=0 && e.lip != 666 && e.state == STATE_BOTTOM) {
                                e.lip = 666; // e.lip is used to remember reverse opening direction for door_rotating
                                e.pos2 = '0 0 0' - e.pos2;
                        }
                        // if BIDIR_IN_DOWN (==8) is set, prevent the door from reoping during closing if it is triggered from the wrong side
-                       if (!((e.spawnflags & 2) &&  (e.spawnflags & 8) && e.state == STATE_DOWN
+                       if (!((e.spawnflags & DOOR_ROTATING_BIDIR) &&  (e.spawnflags & DOOR_ROTATING_BIDIR_IN_DOWN) && e.state == STATE_DOWN
                                && (((e.lip == 666) && (trigger.trigger_reverse == 0)) || ((e.lip != 666) && (trigger.trigger_reverse != 0)))))
                        {
                                door_rotating_go_up(e, trigger);
@@ -263,7 +262,7 @@ void door_use(entity this, entity actor, entity trigger)
 
 void door_damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
 {
-       if(this.spawnflags & DOOR_NOSPLASH)
+       if(this.spawnflags & NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
        this.health = this.health - damage;
@@ -313,7 +312,7 @@ void door_touch(entity this, entity toucher)
 
 void door_generic_plat_blocked(entity this, entity blocker)
 {
-       if((this.spawnflags & 8) && (blocker.takedamage != DAMAGE_NO)) { // Kill Kill Kill!!
+       if((this.spawnflags & DOOR_CRUSH) && (blocker.takedamage != DAMAGE_NO)) { // Kill Kill Kill!!
 #ifdef SVQC
                Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, DMG_NOWEP, blocker.origin, '0 0 0');
 #endif
@@ -348,66 +347,6 @@ void door_generic_plat_blocked(entity this, entity blocker)
        }
 }
 
-void door_rotating_hit_top(entity this)
-{
-       if (this.noise1 != "")
-               _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
-       this.state = STATE_TOP;
-       if (this.spawnflags & DOOR_TOGGLE)
-               return;         // don't come down automatically
-       setthink(this, door_rotating_go_down);
-       this.nextthink = this.ltime + this.wait;
-}
-
-void door_rotating_hit_bottom(entity this)
-{
-       if (this.noise1 != "")
-               _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
-       if (this.lip==666) // this.lip is used to remember reverse opening direction for door_rotating
-       {
-               this.pos2 = '0 0 0' - this.pos2;
-               this.lip = 0;
-       }
-       this.state = STATE_BOTTOM;
-}
-
-void door_rotating_go_down(entity this)
-{
-       if (this.noise2 != "")
-               _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
-       if (this.max_health)
-       {
-               this.takedamage = DAMAGE_YES;
-               this.health = this.max_health;
-       }
-
-       this.state = STATE_DOWN;
-       SUB_CalcAngleMove (this, this.pos1, TSPEED_LINEAR, this.speed, door_rotating_hit_bottom);
-}
-
-void door_rotating_go_up(entity this, entity oth)
-{
-       if (this.state == STATE_UP)
-               return;         // already going up
-
-       if (this.state == STATE_TOP)
-       {       // reset top wait time
-               this.nextthink = this.ltime + this.wait;
-               return;
-       }
-       if (this.noise2 != "")
-               _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
-       this.state = STATE_UP;
-       SUB_CalcAngleMove (this, this.pos2, TSPEED_LINEAR, this.speed, door_rotating_hit_top);
-
-       string oldmessage;
-       oldmessage = this.message;
-       this.message = "";
-       SUB_UseTargets(this, NULL, oth); // TODO: is oth needed here?
-       this.message = oldmessage;
-}
-
-
 /*
 =========================================
 door trigger
@@ -465,7 +404,7 @@ LinkDoors
 
 entity LinkDoors_nextent(entity cur, entity near, entity pass)
 {
-       while((cur = find(cur, classname, pass.classname)) && ((cur.spawnflags & 4) || cur.enemy))
+       while((cur = find(cur, classname, pass.classname)) && ((cur.spawnflags & DOOR_DONT_LINK) || cur.enemy))
        {
        }
        return cur;
@@ -498,7 +437,7 @@ void LinkDoors(entity this)
 
        if (this.enemy)
                return;         // already linked by another door
-       if (this.spawnflags & 4)
+       if (this.spawnflags & DOOR_DONT_LINK)
        {
                this.owner = this.enemy = this;
 
@@ -688,53 +627,93 @@ void door_reset(entity this)
 
 #ifdef SVQC
 
-// spawnflags require key (for now only func_door)
-spawnfunc(func_door)
+// common code for func_door and func_door_rotating spawnfuncs
+void door_init_shared(entity this)
 {
-       // Quake 1 keys compatibility
-       if (this.spawnflags & SPAWNFLAGS_GOLD_KEY)
-               this.itemkeys |= ITEM_KEY_BIT(0);
-       if (this.spawnflags & SPAWNFLAGS_SILVER_KEY)
-               this.itemkeys |= ITEM_KEY_BIT(1);
-
-       SetMovedir(this);
-
        this.max_health = this.health;
-       if (!InitMovingBrushTrigger(this))
-               return;
-       this.effects |= EF_LOWPRECISION;
-       this.classname = "door";
 
+       // unlock sound
        if(this.noise == "")
+       {
                this.noise = "misc/talk.wav";
+       }
+       // door still locked sound
        if(this.noise3 == "")
+       {
                this.noise3 = "misc/talk.wav";
+       }
        precache_sound(this.noise);
        precache_sound(this.noise3);
 
-       setblocked(this, door_blocked);
-       this.use = door_use;
-
-       if(this.dmg && (this.message == ""))
+       if((this.dmg || (this.spawnflags & DOOR_CRUSH)) && (this.message == ""))
+       {
                this.message = "was squished";
-       if(this.dmg && (this.message2 == ""))
+       }
+       if((this.dmg || (this.spawnflags & DOOR_CRUSH)) && (this.message2 == ""))
+       {
                this.message2 = "was squished by";
+       }
 
+       // TODO: other soundpacks
        if (this.sounds > 0)
        {
                this.noise2 = "plats/medplat1.wav";
                this.noise1 = "plats/medplat2.wav";
        }
 
-       if(this.noise1 && this.noise1 != "") { precache_sound(this.noise1); }
-       if(this.noise2 && this.noise2 != "") { precache_sound(this.noise2); }
+       // sound when door stops moving
+       if(this.noise1 && this.noise1 != "")
+       {
+               precache_sound(this.noise1);
+       }
+       // sound when door is moving
+       if(this.noise2 && this.noise2 != "")
+       {
+               precache_sound(this.noise2);
+       }
 
-       if (!this.speed)
-               this.speed = 100;
        if (!this.wait)
+       {
                this.wait = 3;
+       }
        if (!this.lip)
+       {
                this.lip = 8;
+       }
+
+       this.state = STATE_BOTTOM;
+
+       if (this.health)
+       {
+               //this.canteamdamage = true; // TODO
+               this.takedamage = DAMAGE_YES;
+               this.event_damage = door_damage;
+       }
+
+       if (this.items)
+       {
+               this.wait = -1;
+       }
+}
+
+// spawnflags require key (for now only func_door)
+spawnfunc(func_door)
+{
+       // Quake 1 keys compatibility
+       if (this.spawnflags & SPAWNFLAGS_GOLD_KEY)
+               this.itemkeys |= ITEM_KEY_BIT(0);
+       if (this.spawnflags & SPAWNFLAGS_SILVER_KEY)
+               this.itemkeys |= ITEM_KEY_BIT(1);
+
+       SetMovedir(this);
+
+       if (!InitMovingBrushTrigger(this))
+               return;
+       this.effects |= EF_LOWPRECISION;
+       this.classname = "door";
+
+       setblocked(this, door_blocked);
+       this.use = door_use;
 
        this.pos1 = this.origin;
        this.pos2 = this.pos1 + this.movedir*(fabs(this.movedir*this.size) - this.lip);
@@ -747,18 +726,13 @@ spawnfunc(func_door)
        if (this.spawnflags & DOOR_START_OPEN)
                InitializeEntity(this, door_init_startopen, INITPRIO_SETLOCATION);
 
-       this.state = STATE_BOTTOM;
+       door_init_shared(this);
 
-       if (this.health)
+       if (!this.speed)
        {
-               //this.canteamdamage = true; // TODO
-               this.takedamage = DAMAGE_YES;
-               this.event_damage = door_damage;
+               this.speed = 100;
        }
 
-       if (this.items)
-               this.wait = -1;
-
        settouch(this, door_touch);
 
 // LinkDoors can't be done until all of the doors have been spawned, so
index 84a9d6aa234224fe3d2d35b6c1640941c73b85f1..181de8b7b829592dc0ce3dcaf426524a824d78d2 100644 (file)
@@ -1,16 +1,15 @@
 #pragma once
 
-// door constants
-const int DOOR_START_OPEN = 1;
-const int DOOR_DONT_LINK = 4;
-const int DOOR_TOGGLE = 32;
 
-const int DOOR_NOSPLASH = 256; // generic anti-splashdamage spawnflag
+const int DOOR_START_OPEN = BIT(0);
+const int DOOR_DONT_LINK = BIT(2);
+const int SPAWNFLAGS_GOLD_KEY = BIT(3); // Quake 1 compat, can only be used with func_door!
+const int SPAWNFLAGS_SILVER_KEY = BIT(4); // Quake 1 compat, can only be used with func_door!
+const int DOOR_TOGGLE = BIT(5);
 
-const int DOOR_NONSOLID = 1024;
+const int DOOR_NONSOLID = BIT(10);
+const int DOOR_CRUSH = BIT(11); // can't use CRUSH cause that is the same as DOOR_DONT_LINK
 
-const int SPAWNFLAGS_GOLD_KEY = 8;
-const int SPAWNFLAGS_SILVER_KEY = 16;
 
 #ifdef CSQC
 // stuff for preload
index c61a02686650eb56ae3a138d3cace85fed2a99b0..41fd05e574af53295a71c6b105c3a76f3ac78e52 100644 (file)
@@ -1,5 +1,4 @@
 #include "door_rotating.qh"
-#ifdef SVQC
 /*QUAKED spawnfunc_func_door_rotating (0 .5 .8) ? START_OPEN BIDIR DOOR_DONT_LINK BIDIR_IN_DOWN x TOGGLE X_AXIS Y_AXIS
 if two doors touch, they are assumed to be connected and operate as a unit.
 
@@ -28,6 +27,68 @@ START_OPEN causes the door to move to its destination when spawned, and operate
 FIXME: only one sound set available at the time being
 */
 
+#ifdef GAMEQC
+void door_rotating_hit_top(entity this)
+{
+       if (this.noise1 != "")
+               _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
+       this.state = STATE_TOP;
+       if (this.spawnflags & DOOR_TOGGLE)
+               return;         // don't come down automatically
+       setthink(this, door_rotating_go_down);
+       this.nextthink = this.ltime + this.wait;
+}
+
+void door_rotating_hit_bottom(entity this)
+{
+       if (this.noise1 != "")
+               _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
+       if (this.lip==666) // this.lip is used to remember reverse opening direction for door_rotating
+       {
+               this.pos2 = '0 0 0' - this.pos2;
+               this.lip = 0;
+       }
+       this.state = STATE_BOTTOM;
+}
+
+void door_rotating_go_down(entity this)
+{
+       if (this.noise2 != "")
+               _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
+       if (this.max_health)
+       {
+               this.takedamage = DAMAGE_YES;
+               this.health = this.max_health;
+       }
+
+       this.state = STATE_DOWN;
+       SUB_CalcAngleMove (this, this.pos1, TSPEED_LINEAR, this.speed, door_rotating_hit_bottom);
+}
+
+void door_rotating_go_up(entity this, entity oth)
+{
+       if (this.state == STATE_UP)
+               return;         // already going up
+
+       if (this.state == STATE_TOP)
+       {       // reset top wait time
+               this.nextthink = this.ltime + this.wait;
+               return;
+       }
+       if (this.noise2 != "")
+               _sound (this, CH_TRIGGER_SINGLE, this.noise2, VOL_BASE, ATTEN_NORM);
+       this.state = STATE_UP;
+       SUB_CalcAngleMove (this, this.pos2, TSPEED_LINEAR, this.speed, door_rotating_hit_top);
+
+       string oldmessage;
+       oldmessage = this.message;
+       this.message = "";
+       SUB_UseTargets(this, NULL, oth); // TODO: is oth needed here?
+       this.message = oldmessage;
+}
+#endif
+
+#ifdef SVQC
 void door_rotating_reset(entity this)
 {
        this.angles = this.pos1;
@@ -44,17 +105,15 @@ void door_rotating_init_startopen(entity this)
        this.pos1 = this.movedir;
 }
 
-
 spawnfunc(func_door_rotating)
 {
-
        //if (!this.deathtype) // map makers can override this
        //      this.deathtype = " got in the way";
 
        // I abuse "movedir" for denoting the axis for now
-       if (this.spawnflags & 64) // X (untested)
+       if (this.spawnflags & DOOR_ROTATING_XAXIS)
                this.movedir = '0 0 1';
-       else if (this.spawnflags & 128) // Y (untested)
+       else if (this.spawnflags & DOOR_ROTATING_YAXIS)
                this.movedir = '1 0 0';
        else // Z
                this.movedir = '0 1 0';
@@ -64,7 +123,6 @@ spawnfunc(func_door_rotating)
        this.movedir = this.movedir * this.angles_y;
        this.angles = '0 0 0';
 
-       this.max_health = this.health;
        this.avelocity = this.movedir;
        if (!InitMovingBrushTrigger(this))
                return;
@@ -75,28 +133,6 @@ spawnfunc(func_door_rotating)
        setblocked(this, door_blocked);
        this.use = door_use;
 
-    if(this.spawnflags & 8)
-        this.dmg = 10000;
-
-    if(this.dmg && (this.message == ""))
-               this.message = "was squished";
-    if(this.dmg && (this.message2 == ""))
-               this.message2 = "was squished by";
-
-    if (this.sounds > 0)
-       {
-               precache_sound ("plats/medplat1.wav");
-               precache_sound ("plats/medplat2.wav");
-               this.noise2 = "plats/medplat1.wav";
-               this.noise1 = "plats/medplat2.wav";
-       }
-
-       if (!this.speed)
-               this.speed = 50;
-       if (!this.wait)
-               this.wait = 1;
-       this.lip = 0; // this.lip is used to remember reverse opening direction for door_rotating
-
        this.pos1 = '0 0 0';
        this.pos2 = this.movedir;
 
@@ -105,17 +141,12 @@ spawnfunc(func_door_rotating)
        if (this.spawnflags & DOOR_START_OPEN)
                InitializeEntity(this, door_rotating_init_startopen, INITPRIO_SETLOCATION);
 
-       this.state = STATE_BOTTOM;
-
-       if (this.health)
+       door_init_shared(this);
+       if (!this.speed)
        {
-               //this.canteamdamage = true; // TODO
-               this.takedamage = DAMAGE_YES;
-               this.event_damage = door_damage;
+               this.speed = 50;
        }
-
-       if (this.items)
-               this.wait = -1;
+       this.lip = 0; // this.lip is used to remember reverse opening direction for door_rotating
 
        settouch(this, door_touch);
 
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..5ff572859b5c1847c32c504cb3b95fac53f7cf40 100644 (file)
@@ -1 +1,14 @@
 #pragma once
+
+
+const int DOOR_ROTATING_BIDIR = BIT(1);
+const int DOOR_ROTATING_BIDIR_IN_DOWN = BIT(3);
+
+const int DOOR_ROTATING_XAXIS = BIT(6);
+const int DOOR_ROTATING_YAXIS = BIT(7);
+
+
+#ifdef GAMEQC
+void door_rotating_go_down(entity this);
+void door_rotating_go_up(entity this, entity oth);
+#endif
index 55582696476e8b543ea80cb6b94a59bdaebae27b..78e0dd64e9cafc275eb55c1a6d1302cdcde2cdd5 100644 (file)
@@ -8,12 +8,6 @@ void fd_secret_move5(entity this);
 void fd_secret_move6(entity this);
 void fd_secret_done(entity this);
 
-const float SECRET_OPEN_ONCE = 1;              // stays open
-const float SECRET_1ST_LEFT = 2;               // 1st move is left of arrow
-const float SECRET_1ST_DOWN = 4;               // 1st move is down from arrow
-const float SECRET_NO_SHOOT = 8;               // only opened by trigger
-const float SECRET_YES_SHOOT = 16;     // shootable even if targeted
-
 void fd_secret_use(entity this, entity actor, entity trigger)
 {
        float temp;
@@ -41,12 +35,12 @@ void fd_secret_use(entity this, entity actor, entity trigger)
                _sound(this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
        this.nextthink = this.ltime + 0.1;
 
-       temp = 1 - (this.spawnflags & SECRET_1ST_LEFT); // 1 or -1
+       temp = 1 - (this.spawnflags & DOOR_SECRET_1ST_LEFT);    // 1 or -1
        makevectors(this.mangle);
 
        if (!this.t_width)
        {
-               if (this.spawnflags & SECRET_1ST_DOWN)
+               if (this.spawnflags & DOOR_SECRET_1ST_DOWN)
                        this.t_width = fabs(v_up * this.size);
                else
                        this.t_width = fabs(v_right * this.size);
@@ -55,7 +49,7 @@ void fd_secret_use(entity this, entity actor, entity trigger)
        if (!this.t_length)
                this.t_length = fabs(v_forward * this.size);
 
-       if (this.spawnflags & SECRET_1ST_DOWN)
+       if (this.spawnflags & DOOR_SECRET_1ST_DOWN)
                this.dest1 = this.origin - v_up * this.t_width;
        else
                this.dest1 = this.origin + v_right * (this.t_width * temp);
@@ -93,7 +87,7 @@ void fd_secret_move3(entity this)
 {
        if (this.noise3 != "")
                _sound(this, CH_TRIGGER_SINGLE, this.noise3, VOL_BASE, ATTEN_NORM);
-       if (!(this.spawnflags & SECRET_OPEN_ONCE))
+       if (!(this.spawnflags & DOOR_SECRET_OPEN_ONCE) && this.wait >= 0)
        {
                this.nextthink = this.ltime + this.wait;
                setthink(this, fd_secret_move4);
@@ -126,7 +120,7 @@ void fd_secret_move6(entity this)
 
 void fd_secret_done(entity this)
 {
-       if (this.spawnflags&SECRET_YES_SHOOT)
+       if (this.spawnflags&DOOR_SECRET_YES_SHOOT)
        {
                this.health = 10000;
                this.takedamage = DAMAGE_YES;
@@ -172,7 +166,7 @@ void secret_touch(entity this, entity toucher)
 
 void secret_reset(entity this)
 {
-       if (this.spawnflags & SECRET_YES_SHOOT)
+       if (this.spawnflags & DOOR_SECRET_YES_SHOOT)
        {
                this.health = 10000;
                this.takedamage = DAMAGE_YES;
@@ -204,7 +198,10 @@ spawnfunc(func_door_secret)
        /*if (!this.deathtype) // map makers can override this
                this.deathtype = " got in the way";*/
 
-       if (!this.dmg) this.dmg = 2;
+       if (!this.dmg)
+       {
+               this.dmg = 2;
+       }
 
        // Magic formula...
        this.mangle = this.angles;
@@ -213,8 +210,35 @@ spawnfunc(func_door_secret)
        if (!InitMovingBrushTrigger(this)) return;
        this.effects |= EF_LOWPRECISION;
 
-       if (this.noise == "") this.noise = "misc/talk.wav";
+       // TODO: other soundpacks
+       if (this.sounds > 0)
+       {
+               this.noise1 = "plats/medplat1.wav";
+               this.noise2 = "plats/medplat1.wav";
+               this.noise3 = "plats/medplat2.wav";
+       }
+
+       // sound on touch
+       if (this.noise == "")
+       {
+               this.noise = "misc/talk.wav";
+       }
        precache_sound(this.noise);
+       // sound while moving backwards
+       if (this.noise1 && this.noise1 != "")
+       {
+               precache_sound(this.noise1);
+       }
+       // sound while moving sideways
+       if (this.noise2 && this.noise2 != "")
+       {
+               precache_sound(this.noise2);
+       }
+       // sound when door stops moving
+       if (this.noise3 && this.noise3 != "")
+       {
+               precache_sound(this.noise3);
+       }
 
        settouch(this, secret_touch);
        setblocked(this, secret_blocked);
@@ -224,9 +248,9 @@ spawnfunc(func_door_secret)
        {
        }
        else
-               this.spawnflags |= SECRET_YES_SHOOT;
+               this.spawnflags |= DOOR_SECRET_YES_SHOOT;
 
-       if (this.spawnflags & SECRET_YES_SHOOT)
+       if (this.spawnflags & DOOR_SECRET_YES_SHOOT)
        {
                //this.canteamdamage = true; // TODO
                this.health = 10000;
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..ee575bc424c2aa8bdc98da839badc986f362dd6e 100644 (file)
@@ -1 +1,8 @@
 #pragma once
+
+
+const int DOOR_SECRET_OPEN_ONCE = BIT(0); // stays open - LEGACY, set wait to -1 instead
+const int DOOR_SECRET_1ST_LEFT = BIT(1); // 1st move is left of arrow
+const int DOOR_SECRET_1ST_DOWN = BIT(2); // 1st move is down from arrow
+const int DOOR_SECRET_NO_SHOOT = BIT(3); // only opened by trigger
+const int DOOR_SECRET_YES_SHOOT = BIT(4); // shootable even if targeted
index 9f97a1cea09b764d2021900fb011be0978254541..b052336217990a32a646d852679bc3c0d1d83c20 100644 (file)
@@ -58,12 +58,19 @@ void plat_link(entity this)
 
 spawnfunc(func_plat)
 {
-       if (this.sounds == 0) this.sounds = 2;
-
-    if (this.spawnflags & 4) this.dmg = 10000;
+       if (this.spawnflags & CRUSH)
+       {
+               this.dmg = 10000;
+       }
 
-    if (this.dmg && (this.message == "")) this.message = "was squished";
-    if (this.dmg && (this.message2 == "")) this.message2 = "was squished by";
+    if (this.dmg && (this.message == ""))
+       {
+               this.message = "was squished";
+       }
+    if (this.dmg && (this.message2 == ""))
+       {
+               this.message2 = "was squished by";
+       }
 
        if (this.sounds == 1)
        {
@@ -77,13 +84,20 @@ spawnfunc(func_plat)
                this.noise1 = "plats/medplat2.wav";
        }
 
+       // WARNING: backwards compatibility because people don't use already existing fields :(
        if (this.sound1)
                this.noise = this.sound1;
        if (this.sound2)
                this.noise1 = this.sound2;
 
-       if(this.noise && this.noise != "") { precache_sound(this.noise); }
-       if(this.noise1 && this.noise1 != "") { precache_sound(this.noise1); }
+       if(this.noise && this.noise != "")
+       {
+               precache_sound(this.noise);
+       }
+       if(this.noise1 && this.noise1 != "")
+       {
+               precache_sound(this.noise1);
+       }
 
        this.mangle = this.angles;
        this.angles = '0 0 0';
index e028b4c837d7b20bddc47223b060dcff0ff40c9e..7de5a03ef8171e905ea0d7eff538580ad7e22f5e 100644 (file)
@@ -4,39 +4,39 @@ REGISTER_NET_LINKED(ENT_CLIENT_POINTPARTICLES)
 #ifdef SVQC
 // NOTE: also contains func_sparks
 
-bool pointparticles_SendEntity(entity this, entity to, float fl)
+bool pointparticles_SendEntity(entity this, entity to, float sendflags)
 {
        WriteHeader(MSG_ENTITY, ENT_CLIENT_POINTPARTICLES);
 
        // optional features to save space
-       fl = fl & 0x0F;
-       if(this.spawnflags & 2)
-               fl |= 0x10; // absolute count on toggle-on
+       sendflags = sendflags & 0x0F;
+       if(this.spawnflags & PARTICLES_IMPULSE)
+               sendflags |= SF_POINTPARTICLES_IMPULSE; // absolute count on toggle-on
        if(this.movedir != '0 0 0' || this.velocity != '0 0 0')
-               fl |= 0x20; // 4 bytes - saves CPU
+               sendflags |= SF_POINTPARTICLES_MOVING; // 4 bytes - saves CPU
        if(this.waterlevel || this.count != 1)
-               fl |= 0x40; // 4 bytes - obscure features almost never used
+               sendflags |= SF_POINTPARTICLES_JITTER_AND_COUNT; // 4 bytes - obscure features almost never used
        if(this.mins != '0 0 0' || this.maxs != '0 0 0')
-               fl |= 0x80; // 14 bytes - saves lots of space
+               sendflags |= SF_POINTPARTICLES_BOUNDS; // 14 bytes - saves lots of space
 
-       WriteByte(MSG_ENTITY, fl);
-       if(fl & 2)
+       WriteByte(MSG_ENTITY, sendflags);
+       if(sendflags & SF_TRIGGER_UPDATE)
        {
-               if(this.state)
+               if(this.active == ACTIVE_ACTIVE)
                        WriteCoord(MSG_ENTITY, this.impulse);
                else
                        WriteCoord(MSG_ENTITY, 0); // off
        }
-       if(fl & 4)
+       if(sendflags & SF_TRIGGER_RESET)
        {
                WriteVector(MSG_ENTITY, this.origin);
        }
-       if(fl & 1)
+       if(sendflags & SF_TRIGGER_INIT)
        {
                if(this.model != "null")
                {
                        WriteShort(MSG_ENTITY, this.modelindex);
-                       if(fl & 0x80)
+                       if(sendflags & SF_POINTPARTICLES_BOUNDS)
                        {
                                WriteVector(MSG_ENTITY, this.mins);
                                WriteVector(MSG_ENTITY, this.maxs);
@@ -45,19 +45,19 @@ bool pointparticles_SendEntity(entity this, entity to, float fl)
                else
                {
                        WriteShort(MSG_ENTITY, 0);
-                       if(fl & 0x80)
+                       if(sendflags & SF_POINTPARTICLES_BOUNDS)
                        {
                                WriteVector(MSG_ENTITY, this.maxs);
                        }
                }
                WriteShort(MSG_ENTITY, this.cnt);
                WriteString(MSG_ENTITY, this.mdl);
-               if(fl & 0x20)
+               if(sendflags & SF_POINTPARTICLES_MOVING)
                {
                        WriteShort(MSG_ENTITY, compressShortVector(this.velocity));
                        WriteShort(MSG_ENTITY, compressShortVector(this.movedir));
                }
-               if(fl & 0x40)
+               if(sendflags & SF_POINTPARTICLES_JITTER_AND_COUNT)
                {
                        WriteShort(MSG_ENTITY, this.waterlevel * 16.0);
                        WriteByte(MSG_ENTITY, this.count * 16.0);
@@ -80,30 +80,16 @@ bool pointparticles_SendEntity(entity this, entity to, float fl)
        return 1;
 }
 
-void pointparticles_use(entity this, entity actor, entity trigger)
-{
-       this.state = !this.state;
-       this.SendFlags |= 2;
-}
-
 void pointparticles_think(entity this)
 {
        if(this.origin != this.oldorigin)
        {
-               this.SendFlags |= 4;
+               this.SendFlags |= SF_TRIGGER_RESET;
                this.oldorigin = this.origin;
        }
        this.nextthink = time;
 }
 
-void pointparticles_reset(entity this)
-{
-       if(this.spawnflags & 1)
-               this.state = 1;
-       else
-               this.state = 0;
-}
-
 spawnfunc(func_pointparticles)
 {
        if(this.model != "") { precache_model(this.model); _setmodel(this, this.model); }
@@ -125,41 +111,35 @@ spawnfunc(func_pointparticles)
                setsize(this, '0 0 0', this.maxs - this.mins);
        }
        //if(!this.cnt) this.cnt = _particleeffectnum(this.mdl);
+       this.setactive = generic_netlinked_setactive;
 
-       Net_LinkEntity(this, (this.spawnflags & 4), 0, pointparticles_SendEntity);
+       Net_LinkEntity(this, (this.spawnflags & PARTICLES_VISCULLING), 0, pointparticles_SendEntity);
 
        IFTARGETED
        {
-               this.use = pointparticles_use;
-               this.reset = pointparticles_reset;
-               this.reset(this);
+               // backwards compatibility
+               this.use = generic_netlinked_legacy_use;
        }
-       else
-               this.state = 1;
+       this.reset = generic_netlinked_reset;
+       this.reset(this);
        setthink(this, pointparticles_think);
        this.nextthink = time;
 }
 
 spawnfunc(func_sparks)
 {
-       // this.cnt is the amount of sparks that one burst will spawn
-       if(this.cnt < 1) {
-               this.cnt = 25.0; // nice default value
+       if(this.count < 1) {
+               this.count = 25.0; // nice default value
        }
 
-       // this.wait is the probability that a sparkthink will spawn a spark shower
-       // range: 0 - 1, but 0 makes little sense, so...
-       if(this.wait < 0.05) {
-               this.wait = 0.25; // nice default value
+       if(this.impulse < 0.5) {
+               this.impulse = 2.5; // nice default value
        }
 
-       this.count = this.cnt;
        this.mins = '0 0 0';
        this.maxs = '0 0 0';
        this.velocity = '0 0 -1';
        this.mdl = "TE_SPARK";
-       this.impulse = 10 * this.wait; // by default 2.5/sec
-       this.wait = 0;
        this.cnt = 0; // use mdl
 
        spawnfunc_func_pointparticles(this);
@@ -177,10 +157,12 @@ classfield(PointParticles) .int impulse; // density
 classfield(PointParticles) .string noise; // sound
 classfield(PointParticles) .float atten;
 classfield(PointParticles) .float volume;
-classfield(PointParticles) .float absolute; // 1 = count per second is absolute, 2 = only spawn at toggle
+classfield(PointParticles) .float absolute; // 1 = count per second is absolute, ABSOLUTE_ONLY_SPAWN_AT_TOGGLE = only spawn at toggle
 classfield(PointParticles) .vector movedir; // trace direction
 classfield(PointParticles) .float glow_color; // palette index
 
+const int ABSOLUTE_ONLY_SPAWN_AT_TOGGLE = 2;
+
 void Draw_PointParticles(entity this)
 {
        float n, i, fail;
@@ -190,7 +172,7 @@ void Draw_PointParticles(entity this)
        o = this.origin;
        sz = this.maxs - this.mins;
        n = doBGMScript(this);
-       if(this.absolute == 2)
+       if(this.absolute == ABSOLUTE_ONLY_SPAWN_AT_TOGGLE)
        {
                if(n >= 0)
                        n = this.just_toggled ? this.impulse : 0;
@@ -262,22 +244,22 @@ NET_HANDLE(ENT_CLIENT_POINTPARTICLES, bool isnew)
 {
        float i;
        vector v;
-       int f = ReadByte();
-       if(f & 2)
+       int sendflags = ReadByte();
+       if(sendflags & SF_TRIGGER_UPDATE)
        {
                i = ReadCoord(); // density (<0: point, >0: volume)
                if(i && !this.impulse && (this.cnt || this.mdl)) // this.cnt check is so it only happens if the ent already existed
                        this.just_toggled = 1;
                this.impulse = i;
        }
-       if(f & 4)
+       if(sendflags & SF_TRIGGER_RESET)
        {
                this.origin = ReadVector();
        }
-       if(f & 1)
+       if(sendflags & SF_TRIGGER_INIT)
        {
                this.modelindex = ReadShort();
-               if(f & 0x80)
+               if(sendflags & SF_POINTPARTICLES_BOUNDS)
                {
                        if(this.modelindex)
                        {
@@ -298,7 +280,7 @@ NET_HANDLE(ENT_CLIENT_POINTPARTICLES, bool isnew)
                this.cnt = ReadShort(); // effect number
                this.mdl = strzone(ReadString()); // effect string
 
-               if(f & 0x20)
+               if(sendflags & SF_POINTPARTICLES_MOVING)
                {
                        this.velocity = decompressShortVector(ReadShort());
                        this.movedir = decompressShortVector(ReadShort());
@@ -307,7 +289,7 @@ NET_HANDLE(ENT_CLIENT_POINTPARTICLES, bool isnew)
                {
                        this.velocity = this.movedir = '0 0 0';
                }
-               if(f & 0x40)
+               if(sendflags & SF_POINTPARTICLES_JITTER_AND_COUNT)
                {
                        this.waterlevel = ReadShort() / 16.0;
                        this.count = ReadByte() / 16.0;
@@ -336,18 +318,18 @@ NET_HANDLE(ENT_CLIENT_POINTPARTICLES, bool isnew)
 
        return = true;
 
-       if(f & 2)
+       if(sendflags & SF_TRIGGER_UPDATE)
        {
                this.absolute = (this.impulse >= 0);
                if(!this.absolute)
                {
                        v = this.maxs - this.mins;
-                       this.impulse *= -v.x * v.y * v.z / 262144; // relative: particles per 64^3 cube
+                       this.impulse *= -v.x * v.y * v.z / (64**3); // relative: particles per 64^3 cube
                }
        }
 
-       if(f & 0x10)
-               this.absolute = 2;
+       if(sendflags & SF_POINTPARTICLES_IMPULSE)
+               this.absolute = ABSOLUTE_ONLY_SPAWN_AT_TOGGLE;
 
        setorigin(this, this.origin);
        setsize(this, this.mins, this.maxs);
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..b167527bc813d91c0da4341704b2802048baa28d 100644 (file)
@@ -1 +1,11 @@
 #pragma once
+
+// spawnflags
+const int PARTICLES_IMPULSE = BIT(1);
+const int PARTICLES_VISCULLING = BIT(2);
+
+// sendflags
+const int SF_POINTPARTICLES_IMPULSE = BIT(4);
+const int SF_POINTPARTICLES_MOVING = BIT(5); // Send velocity and movedir
+const int SF_POINTPARTICLES_JITTER_AND_COUNT = BIT(6); // Send waterlevel (=jitter) and count
+const int SF_POINTPARTICLES_BOUNDS = BIT(7); // Send min and max of the brush
index 1817a9ce9a1e4d658b0b1f8411bc790734e62721..ff49eca2c0176c899cdaf1ccd02d9669e0fd851b 100644 (file)
@@ -38,17 +38,19 @@ spawnfunc(func_rain)
        this.solid = SOLID_NOT;
        SetBrushEntityModel(this);
        if (!this.cnt)
+       {
                this.cnt = 12;
+       }
        if (!this.count)
                this.count = 2000;
-       this.count = 0.01 * this.count * (this.size_x / 1024) * (this.size_y / 1024);
+       // relative to absolute particle count
+       this.count = this.count * (this.size_x / 1024) * (this.size_y / 1024);
        if (this.count < 1)
                this.count = 1;
        if(this.count > 65535)
                this.count = 65535;
 
-       this.state = 1; // 1 is rain, 0 is snow
-       this.Version = 1;
+       this.state = RAINSNOW_RAIN;
 
        Net_LinkEntity(this, false, 0, rainsnow_SendEntity);
 }
@@ -76,17 +78,19 @@ spawnfunc(func_snow)
        this.solid = SOLID_NOT;
        SetBrushEntityModel(this);
        if (!this.cnt)
+       {
                this.cnt = 12;
+       }
        if (!this.count)
                this.count = 2000;
-       this.count = 0.01 * this.count * (this.size_x / 1024) * (this.size_y / 1024);
+       // relative to absolute particle count
+       this.count = this.count * (this.size_x / 1024) * (this.size_y / 1024);
        if (this.count < 1)
                this.count = 1;
        if(this.count > 65535)
                this.count = 65535;
 
-       this.state = 0; // 1 is rain, 0 is snow
-       this.Version = 1;
+       this.state = RAINSNOW_SNOW;
 
        Net_LinkEntity(this, false, 0, rainsnow_SendEntity);
 }
@@ -113,11 +117,11 @@ void Draw_Snow(entity this)
 
 NET_HANDLE(ENT_CLIENT_RAINSNOW, bool isnew)
 {
-       this.impulse = ReadByte(); // Rain, Snow, or Whatever
+       this.state = ReadByte(); // Rain, Snow, or Whatever
        this.origin = ReadVector();
        this.maxs = ReadVector();
        this.velocity = decompressShortVector(ReadShort());
-       this.count = ReadShort() * 10;
+       this.count = ReadShort();
        this.glow_color = ReadByte(); // color
 
        return = true;
@@ -130,7 +134,7 @@ 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.impulse)
+       if(this.state == RAINSNOW_RAIN)
                this.draw = Draw_Rain;
        else
                this.draw = Draw_Snow;
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..d60eb4f481ea3bd764aa87325b9a2a125e2cb959 100644 (file)
@@ -1 +1,5 @@
 #pragma once
+
+
+const int RAINSNOW_SNOW = 0;
+const int RAINSNOW_RAIN = 1;
index 6268dcfeb86ea6f5fc7d9b981b7e22dd34240bc9..35351ee08e0a69a882a90ed7043ae18d8072c7e0 100644 (file)
@@ -1,6 +1,5 @@
 #include "rotating.qh"
 #ifdef SVQC
-const int FUNC_ROTATING_STARTOFF = BIT(4);
 
 void func_rotating_setactive(entity this, int astate)
 {
@@ -15,9 +14,18 @@ void func_rotating_setactive(entity this, int astate)
                this.active = astate;
 
        if(this.active  == ACTIVE_NOT)
+       {
                this.avelocity = '0 0 0';
+               stopsound(this, CH_AMBIENT_SINGLE);
+       }
        else
+       {
                this.avelocity = this.pos1;
+               if(this.noise && this.noise != "")
+               {
+                       _sound(this, CH_AMBIENT_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
+               }
+       }
 }
 
 void func_rotating_reset(entity this)
@@ -26,13 +34,20 @@ void func_rotating_reset(entity this)
 
        if(this.spawnflags & FUNC_ROTATING_STARTOFF)
        {
-               this.avelocity = '0 0 0';
-               this.active = ACTIVE_NOT;
+               this.setactive(this, ACTIVE_NOT);
        }
        else
        {
-               this.avelocity = this.pos1;
-               this.active = ACTIVE_ACTIVE;
+               this.setactive(this, ACTIVE_ACTIVE);
+       }
+}
+
+void func_rotating_init_for_player(entity this, entity player)
+{
+       if (this.noise && this.noise != "" && this.active == ACTIVE_ACTIVE && IS_REAL_CLIENT(player))
+       {
+               msg_entity = player;
+               soundto (MSG_ONE, this, CH_AMBIENT_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
        }
 }
 
@@ -46,37 +61,24 @@ dmgtime : See above.
 
 spawnfunc(func_rotating)
 {
-       if (this.noise != "")
+       if (this.noise && this.noise != "")
        {
                precache_sound(this.noise);
-               ambientsound(this.origin, this.noise, VOL_BASE, ATTEN_IDLE);
        }
 
        this.setactive = func_rotating_setactive;
 
        if (!this.speed)
                this.speed = 100;
-       // FIXME: test if this turns the right way, then remove this comment (negate as needed)
-       if (this.spawnflags & BIT(2)) // X (untested)
+       if (this.spawnflags & FUNC_ROTATING_XAXIS)
                this.avelocity = '0 0 1' * this.speed;
-       // FIXME: test if this turns the right way, then remove this comment (negate as needed)
-       else if (this.spawnflags & BIT(3)) // Y (untested)
+       else if (this.spawnflags & FUNC_ROTATING_YAXIS)
                this.avelocity = '1 0 0' * this.speed;
-       // FIXME: test if this turns the right way, then remove this comment (negate as needed)
        else // Z
                this.avelocity = '0 1 0' * this.speed;
 
        this.pos1 = this.avelocity;
 
-       // do this after setting pos1, so we can safely reactivate the func_rotating
-       if(this.spawnflags & FUNC_ROTATING_STARTOFF)
-       {
-               this.avelocity = '0 0 0';
-               this.active = ACTIVE_NOT;
-       }
-       else
-               this.active = ACTIVE_ACTIVE;
-
     if(this.dmg && (this.message == ""))
         this.message = " was squished";
     if(this.dmg && (this.message2 == ""))
@@ -99,5 +101,10 @@ spawnfunc(func_rotating)
        setthink(this, SUB_NullThink); // for PushMove
 
        this.reset = func_rotating_reset;
+       this.reset(this);
+
+       // maybe send sound to new players
+       IL_PUSH(g_initforplayer, this);
+       this.init_for_player = func_rotating_init_for_player;
 }
 #endif
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..ad1b6ec920a2a319c99552ca051021984e9ffc64 100644 (file)
@@ -1 +1,6 @@
 #pragma once
+
+
+const int FUNC_ROTATING_XAXIS = BIT(2);
+const int FUNC_ROTATING_YAXIS = BIT(3);
+const int FUNC_ROTATING_STARTOFF = BIT(4);
index ead086708196889075c18ae958df185dccb02606..4e9c334562c97cc1bad305ccb2abf279a3d20fa4 100644 (file)
@@ -16,7 +16,7 @@ void train_wait(entity this)
                entity targ, cp;
                vector ang;
                targ = this.future_target;
-               if((this.spawnflags & 1) && targ.curvetarget)
+               if((this.spawnflags & TRAIN_CURVE) && targ.curvetarget)
                        cp = find(NULL, targetname, targ.curvetarget);
                else
                        cp = NULL;
@@ -43,7 +43,7 @@ void train_wait(entity this)
 
 #ifdef SVQC
        entity tg = this.future_target;
-       if(tg.spawnflags & 4)
+       if(tg.spawnflags & TRAIN_NEEDACTIVATION)
        {
                this.use = train_use;
                setthink(this, func_null);
@@ -91,7 +91,7 @@ void train_next(entity this)
        this.target_random = targ.target_random;
        this.future_target = train_next_find(targ);
 
-       if (this.spawnflags & 1)
+       if (this.spawnflags & TRAIN_CURVE)
        {
                if(targ.curvetarget)
                {
@@ -195,7 +195,7 @@ void train_use(entity this, entity actor, entity trigger)
 {
        this.nextthink = this.ltime + 1;
        setthink(this, train_next);
-       this.use = func_null; // not again
+       this.use = func_null; // not again, next target can set it again if needed
        if(trigger.target2 && trigger.target2 != "")
                this.future_target = find(NULL, targetname, trigger.target2);
 }
@@ -211,7 +211,7 @@ void func_train_find(entity this)
                objerror(this, "func_train_find: no next target");
        setorigin(this, targ.origin - this.view_ofs);
 
-       if(!(this.spawnflags & 4))
+       if(!(this.spawnflags & TRAIN_NEEDACTIVATION))
        {
                this.nextthink = this.ltime + 1;
                setthink(this, train_next);
@@ -242,10 +242,10 @@ spawnfunc(func_train)
                return;
        this.effects |= EF_LOWPRECISION;
 
-       if(this.spawnflags & 4)
+       if(this.spawnflags & TRAIN_NEEDACTIVATION)
                this.use = train_use;
 
-       if (this.spawnflags & 2)
+       if (this.spawnflags & TRAIN_TURN)
        {
                this.platmovetype_turn = true;
                this.view_ofs = '0 0 0'; // don't offset a rotating train, origin works differently now
index 8b6f7c02da22651e3f44884e76b9968d5a86c874..0b2a099c53576f46aff7a0968965b2dccccaad95 100644 (file)
@@ -1,5 +1,10 @@
 #pragma once
 
+
+const int TRAIN_CURVE = BIT(0);
+const int TRAIN_TURN = BIT(1);
+const int TRAIN_NEEDACTIVATION = BIT(2);
+
 #ifdef CSQC
 .float dmgtime;
 #endif
index 951a740a2024675371cd2e35412f8887adfe188e..61da52acbc483daef7c55c1e9d136000d7ace990 100644 (file)
@@ -6,20 +6,20 @@
 .float targetfactor, target2factor, target3factor, target4factor;
 .vector targetnormal, target2normal, target3normal, target4normal;
 
-vector func_vectormamamam_origin(entity o, float t)
+vector func_vectormamamam_origin(entity o, float timestep)
 {
        vector v, p;
-       float f;
+       float flags;
        entity e;
 
-       f = o.spawnflags;
+       flags = o.spawnflags;
        v = '0 0 0';
 
        e = o.wp00;
        if(e)
        {
-               p = e.origin + t * e.velocity;
-               if(f & 1)
+               p = e.origin + timestep * e.velocity;
+               if(flags & PROJECT_ON_TARGETNORMAL)
                        v = v + (p * o.targetnormal) * o.targetnormal * o.targetfactor;
                else
                        v = v + (p - (p * o.targetnormal) * o.targetnormal) * o.targetfactor;
@@ -28,8 +28,8 @@ vector func_vectormamamam_origin(entity o, float t)
        e = o.wp01;
        if(e)
        {
-               p = e.origin + t * e.velocity;
-               if(f & 2)
+               p = e.origin + timestep * e.velocity;
+               if(flags & PROJECT_ON_TARGET2NORMAL)
                        v = v + (p * o.target2normal) * o.target2normal * o.target2factor;
                else
                        v = v + (p - (p * o.target2normal) * o.target2normal) * o.target2factor;
@@ -38,8 +38,8 @@ vector func_vectormamamam_origin(entity o, float t)
        e = o.wp02;
        if(e)
        {
-               p = e.origin + t * e.velocity;
-               if(f & 4)
+               p = e.origin + timestep * e.velocity;
+               if(flags & PROJECT_ON_TARGET3NORMAL)
                        v = v + (p * o.target3normal) * o.target3normal * o.target3factor;
                else
                        v = v + (p - (p * o.target3normal) * o.target3normal) * o.target3factor;
@@ -48,8 +48,8 @@ vector func_vectormamamam_origin(entity o, float t)
        e = o.wp03;
        if(e)
        {
-               p = e.origin + t * e.velocity;
-               if(f & 8)
+               p = e.origin + timestep * e.velocity;
+               if(flags & PROJECT_ON_TARGET4NORMAL)
                        v = v + (p * o.target4normal) * o.target4normal * o.target4factor;
                else
                        v = v + (p - (p * o.target4normal) * o.target4normal) * o.target4factor;
@@ -60,7 +60,7 @@ vector func_vectormamamam_origin(entity o, float t)
 
 void func_vectormamamam_controller_think(entity this)
 {
-       this.nextthink = time + 0.1;
+       this.nextthink = time + vectormamamam_timestep;
 
        if(this.owner.active != ACTIVE_ACTIVE)
        {
@@ -69,7 +69,7 @@ void func_vectormamamam_controller_think(entity this)
        }
 
        if(this.owner.classname == "func_vectormamamam") // don't brake stuff if the func_vectormamamam was killtarget'ed
-               this.owner.velocity = (this.owner.destvec + func_vectormamamam_origin(this.owner, 0.1) - this.owner.origin) * 10;
+               this.owner.velocity = (this.owner.destvec + func_vectormamamam_origin(this.owner, vectormamamam_timestep) - this.owner.origin) * 10;
 }
 
 void func_vectormamamam_findtarget(entity this)
@@ -98,12 +98,45 @@ void func_vectormamamam_findtarget(entity this)
        setthink(controller, func_vectormamamam_controller_think);
 }
 
+void func_vectormamamam_setactive(entity this, int astate)
+{
+       if (astate == ACTIVE_TOGGLE)
+       {
+               if(this.active == ACTIVE_ACTIVE)
+                       this.active = ACTIVE_NOT;
+               else
+                       this.active = ACTIVE_ACTIVE;
+       }
+       else
+               this.active = astate;
+
+       if(this.active  == ACTIVE_NOT)
+       {
+               stopsound(this, CH_TRIGGER_SINGLE);
+       }
+       else
+       {
+               if(this.noise && this.noise != "")
+               {
+                       _sound(this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
+               }
+       }
+}
+
+void func_vectormamamam_init_for_player(entity this, entity player)
+{
+       if (this.noise && this.noise != "" && this.active == ACTIVE_ACTIVE && IS_REAL_CLIENT(player))
+       {
+               msg_entity = player;
+               soundto(MSG_ONE, this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
+       }
+}
+
 spawnfunc(func_vectormamamam)
 {
        if (this.noise != "")
        {
                precache_sound(this.noise);
-               soundto(MSG_INIT, this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_IDLE);
        }
 
        if(!this.targetfactor)
@@ -139,9 +172,6 @@ spawnfunc(func_vectormamamam)
                this.dmgtime = 0.25;
        this.dmgtime2 = time;
 
-       if(this.netname == "")
-               this.netname = "1 0 0 0 1";
-
        if (!InitMovingBrushTrigger(this))
                return;
 
@@ -152,7 +182,12 @@ spawnfunc(func_vectormamamam)
        // Savage: Reduce bandwith, critical on e.g. nexdm02
        this.effects |= EF_LOWPRECISION;
 
-       this.active = ACTIVE_ACTIVE;
+       this.setactive = func_vectormamamam_setactive;
+       this.setactive(this, ACTIVE_ACTIVE);
+
+       // maybe send sound to new players
+       IL_PUSH(g_initforplayer, this);
+       this.init_for_player = func_vectormamamam_init_for_player;
 
        InitializeEntity(this, func_vectormamamam_findtarget, INITPRIO_FINDTARGET);
 }
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..7eb6b0a63b0f1be400212e81a94c1f41679cb2e5 100644 (file)
@@ -1 +1,9 @@
 #pragma once
+
+
+const int PROJECT_ON_TARGETNORMAL = BIT(0);
+const int PROJECT_ON_TARGET2NORMAL = BIT(1);
+const int PROJECT_ON_TARGET3NORMAL = BIT(2);
+const int PROJECT_ON_TARGET4NORMAL = BIT(3);
+
+const float vectormamamam_timestep = 0.1;
index 63db2c18fa83ac172f62dce5a7b187fccc0c63c4..87619ca711097ff116907c36dc1a34acf0f3ddbd 100644 (file)
@@ -29,10 +29,10 @@ void follow_init(entity this)
                objerror(this, "follow: could not find target/killtarget");
                return;
        }
-       else if(this.spawnflags & 1)
+       else if(this.spawnflags & FOLLOW_ATTACH)
        {
                // attach
-               if(this.spawnflags & 2)
+               if(this.spawnflags & FOLLOW_LOCAL)
                {
                        setattachment(dst, src, this.message);
                }
@@ -46,7 +46,7 @@ void follow_init(entity this)
        }
        else
        {
-               if(this.spawnflags & 2)
+               if(this.spawnflags & FOLLOW_LOCAL)
                {
                        set_movetype(dst, MOVETYPE_FOLLOW);
                        dst.aiment = src;
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..aef491ff323bd00ab55269772d22e27451e5341e 100644 (file)
@@ -1 +1,5 @@
 #pragma once
+
+
+const int FOLLOW_ATTACH = BIT(0);
+const int FOLLOW_LOCAL = BIT(1);
index b7bdede728211a77f0df4adf05211f3e11770ab4..df88b750f245dbc7000deccd0a6785bf5ae1a300 100644 (file)
@@ -16,12 +16,12 @@ void misc_laser_aim(entity this)
        vector a;
        if(this.enemy)
        {
-               if(this.spawnflags & 2)
+               if(this.spawnflags & LASER_FINITE)
                {
                        if(this.enemy.origin != this.mangle)
                        {
                                this.mangle = this.enemy.origin;
-                               this.SendFlags |= 2;
+                               this.SendFlags |= SF_LASER_UPDATE_TARGET;
                        }
                }
                else
@@ -31,7 +31,7 @@ void misc_laser_aim(entity this)
                        if(a != this.mangle)
                        {
                                this.mangle = a;
-                               this.SendFlags |= 2;
+                               this.SendFlags |= SF_LASER_UPDATE_TARGET;
                        }
                }
        }
@@ -40,12 +40,12 @@ void misc_laser_aim(entity this)
                if(this.angles != this.mangle)
                {
                        this.mangle = this.angles;
-                       this.SendFlags |= 2;
+                       this.SendFlags |= SF_LASER_UPDATE_TARGET;
                }
        }
        if(this.origin != this.oldorigin)
        {
-               this.SendFlags |= 1;
+               this.SendFlags |= SF_LASER_UPDATE_ORIGIN;
                this.oldorigin = this.origin;
        }
 }
@@ -65,7 +65,7 @@ void misc_laser_think(entity this)
 
        this.nextthink = time;
 
-       if(!this.state)
+       if(this.active == ACTIVE_NOT)
                return;
 
        misc_laser_aim(this);
@@ -73,13 +73,13 @@ void misc_laser_think(entity this)
        if(this.enemy)
        {
                o = this.enemy.origin;
-               if (!(this.spawnflags & 2))
-                       o = this.origin + normalize(o - this.origin) * 32768;
+               if (!(this.spawnflags & LASER_FINITE))
+                       o = this.origin + normalize(o - this.origin) * LASER_BEAM_MAXLENGTH;
        }
        else
        {
                makevectors(this.mangle);
-               o = this.origin + v_forward * 32768;
+               o = this.origin + v_forward * LASER_BEAM_MAXLENGTH;
        }
 
        if(this.dmg || this.enemy.target != "")
@@ -115,48 +115,48 @@ void misc_laser_think(entity this)
        if(this.dmg)
        {
                if(this.team)
-                       if(((this.spawnflags & 8) == 0) == (this.team != hitent.team))
+                       if(((this.spawnflags & LASER_INVERT_TEAM) == 0) == (this.team != hitent.team))
                                return;
                if(hitent.takedamage)
                        Damage(hitent, this, this, ((this.dmg < 0) ? 100000 : (this.dmg * frametime)), DEATH_HURTTRIGGER.m_id, DMG_NOWEP, hitloc, '0 0 0');
        }
 }
 
-bool laser_SendEntity(entity this, entity to, float fl)
+bool laser_SendEntity(entity this, entity to, float sendflags)
 {
        WriteHeader(MSG_ENTITY, ENT_CLIENT_LASER);
-       fl = fl - (fl & 0xF0); // use that bit to indicate finite length laser
-       if(this.spawnflags & 2)
-               fl |= 0x80;
+       sendflags = sendflags & 0x0F; // use that bit to indicate finite length laser
+       if(this.spawnflags & LASER_FINITE)
+               sendflags |= SF_LASER_FINITE;
        if(this.alpha)
-               fl |= 0x40;
+               sendflags |= SF_LASER_ALPHA;
        if(this.scale != 1 || this.modelscale != 1)
-               fl |= 0x20;
-       if(this.spawnflags & 4)
-               fl |= 0x10;
-       WriteByte(MSG_ENTITY, fl);
-       if(fl & 1)
+               sendflags |= SF_LASER_SCALE;
+       if(this.spawnflags & LASER_NOTRACE)
+               sendflags |= SF_LASER_NOTRACE;
+       WriteByte(MSG_ENTITY, sendflags);
+       if(sendflags & SF_LASER_UPDATE_ORIGIN)
        {
                WriteVector(MSG_ENTITY, this.origin);
        }
-       if(fl & 8)
+       if(sendflags & SF_LASER_UPDATE_EFFECT)
        {
-               WriteByte(MSG_ENTITY, this.colormod_x * 255.0);
-               WriteByte(MSG_ENTITY, this.colormod_y * 255.0);
-               WriteByte(MSG_ENTITY, this.colormod_z * 255.0);
-               if(fl & 0x40)
+               WriteByte(MSG_ENTITY, this.beam_color.x * 255.0);
+               WriteByte(MSG_ENTITY, this.beam_color.y * 255.0);
+               WriteByte(MSG_ENTITY, this.beam_color.z * 255.0);
+               if(sendflags & SF_LASER_ALPHA)
                        WriteByte(MSG_ENTITY, this.alpha * 255.0);
-               if(fl & 0x20)
+               if(sendflags & SF_LASER_SCALE)
                {
                        WriteByte(MSG_ENTITY, bound(0, this.scale * 16.0, 255));
                        WriteByte(MSG_ENTITY, bound(0, this.modelscale * 16.0, 255));
                }
-               if((fl & 0x80) || !(fl & 0x10)) // effect doesn't need sending if the laser is infinite and has collision testing turned off
-                       WriteShort(MSG_ENTITY, this.cnt + 1);
+               if((sendflags & SF_LASER_FINITE) || !(sendflags & SF_LASER_NOTRACE)) // effect doesn't need sending if the laser is infinite and has collision testing turned off
+                       WriteShort(MSG_ENTITY, this.cnt);
        }
-       if(fl & 2)
+       if(sendflags & SF_LASER_UPDATE_TARGET)
        {
-               if(fl & 0x80)
+               if(sendflags & SF_LASER_FINITE)
                {
                        WriteVector(MSG_ENTITY, this.enemy.origin);
                }
@@ -166,9 +166,9 @@ bool laser_SendEntity(entity this, entity to, float fl)
                        WriteAngle(MSG_ENTITY, this.mangle_y);
                }
        }
-       if(fl & 4)
-               WriteByte(MSG_ENTITY, this.state);
-       return 1;
+       if(sendflags & SF_LASER_UPDATE_ACTIVE)
+               WriteByte(MSG_ENTITY, this.active);
+       return true;
 }
 
 /*QUAKED spawnfunc_misc_laser (.5 .5 .5) ? START_ON DEST_IS_FIXED
@@ -178,24 +178,41 @@ Keys:
  spawnfunc_target_position where the laser ends
 "mdl"
  name of beam end effect to use
-"colormod"
+"beam_color"
  color of the beam (default: red)
 "dmg"
  damage per second (-1 for a laser that kills immediately)
 */
-void laser_use(entity this, entity actor, entity trigger)
+
+void laser_setactive(entity this, int act)
 {
-       this.state = !this.state;
-       this.SendFlags |= 4;
-       misc_laser_aim(this);
+       int old_status = this.active;
+       if(act == ACTIVE_TOGGLE)
+       {
+               if(this.active == ACTIVE_ACTIVE)
+               {
+                       this.active = ACTIVE_NOT;
+               }
+               else
+               {
+                       this.active = ACTIVE_ACTIVE;
+               }
+       }
+       else
+       {
+               this.active = act;
+       }
+
+       if (this.active != old_status)
+       {
+               this.SendFlags |= SF_LASER_UPDATE_ACTIVE;
+               misc_laser_aim(this);
+       }
 }
 
-void laser_reset(entity this)
+void laser_use(entity this, entity actor, entity trigger)
 {
-       if(this.spawnflags & 1)
-               this.state = 1;
-       else
-               this.state = 0;
+       this.setactive(this, ACTIVE_TOGGLE);
 }
 
 spawnfunc(misc_laser)
@@ -221,14 +238,38 @@ spawnfunc(misc_laser)
        if(this.cnt < 0)
                this.cnt = -1;
 
-       if(this.colormod == '0 0 0')
+       if(!this.beam_color && this.colormod)
+       {
+               LOG_WARN("misc_laser uses legacy field 'colormod', please use 'beam_color' instead");
+               this.beam_color = this.colormod;
+       }
+
+       if(this.beam_color == '0 0 0')
+       {
                if(!this.alpha)
-                       this.colormod = '1 0 0';
-       if(this.message == "") this.message = "saw the light";
-       if (this.message2 == "") this.message2 = "was pushed into a laser by";
-       if(!this.scale) this.scale = 1;
-       if(!this.modelscale) this.modelscale = 1;
-       else if(this.modelscale < 0) this.modelscale = 0;
+                       this.beam_color = '1 0 0';
+       }
+
+       if(this.message == "")
+       {
+               this.message = "saw the light";
+       }
+       if (this.message2 == "")
+       {
+               this.message2 = "was pushed into a laser by";
+       }
+       if(!this.scale)
+       {
+               this.scale = 1;
+       }
+       if(!this.modelscale)
+       {
+               this.modelscale = 1;
+       }
+       else if(this.modelscale < 0)
+       {
+               this.modelscale = 0;
+       }
        setthink(this, misc_laser_think);
        this.nextthink = time;
        InitializeEntity(this, misc_laser_init, INITPRIO_FINDTARGET);
@@ -237,38 +278,40 @@ spawnfunc(misc_laser)
 
        Net_LinkEntity(this, false, 0, laser_SendEntity);
 
+       this.setactive = laser_setactive;
+
        IFTARGETED
        {
-               this.reset = laser_reset;
-               this.reset(this);
+               // backwards compatibility
                this.use = laser_use;
        }
-       else
-               this.state = 1;
+
+       this.reset = generic_netlinked_reset;
+       this.reset(this);
 }
 #elif defined(CSQC)
 
 // a laser goes from origin in direction angles
-// it has color 'colormod'
+// it has color 'beam_color'
 // and stops when something is in the way
 entityclass(Laser);
 classfield(Laser) .int cnt; // end effect
 classfield(Laser) .vector colormod;
 classfield(Laser) .int state; // on-off
 classfield(Laser) .int count; // flags for the laser
-classfield(Laser) .vector velocity;
+classfield(Laser) .vector velocity; // laser endpoint if it is FINITE
 classfield(Laser) .float alpha;
 classfield(Laser) .float scale; // scaling factor of the thickness
 classfield(Laser) .float modelscale; // scaling factor of the dlight
 
 void Draw_Laser(entity this)
 {
-       if(!this.state)
+       if(this.active == ACTIVE_NOT)
                return;
        InterpolateOrigin_Do(this);
-       if(this.count & 0x80)
+       if(this.count & SF_LASER_FINITE)
        {
-               if(this.count & 0x10)
+               if(this.count & SF_LASER_NOTRACE)
                {
                        trace_endpos = this.velocity;
                        trace_dphitq3surfaceflags = 0;
@@ -278,37 +321,37 @@ void Draw_Laser(entity this)
        }
        else
        {
-               if(this.count & 0x10)
+               if(this.count & SF_LASER_NOTRACE)
                {
                        makevectors(this.angles);
-                       trace_endpos = this.origin + v_forward * 1048576;
+                       trace_endpos = this.origin + v_forward * LASER_BEAM_MAXWORLDSIZE;
                        trace_dphitq3surfaceflags = Q3SURFACEFLAG_SKY;
                }
                else
                {
                        makevectors(this.angles);
-                       traceline(this.origin, this.origin + v_forward * 32768, 0, this);
+                       traceline(this.origin, this.origin + v_forward * LASER_BEAM_MAXLENGTH, 0, this);
                        if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
-                               trace_endpos = this.origin + v_forward * 1048576;
+                               trace_endpos = this.origin + v_forward * LASER_BEAM_MAXWORLDSIZE;
                }
        }
        if(this.scale != 0)
        {
                if(this.alpha)
                {
-                       Draw_CylindricLine(this.origin, trace_endpos, this.scale, "particles/laserbeam", 0, time * 3, this.colormod, this.alpha, DRAWFLAG_NORMAL, view_origin);
+                       Draw_CylindricLine(this.origin, trace_endpos, this.scale, "particles/laserbeam", 0, time * 3, this.beam_color, this.alpha, DRAWFLAG_NORMAL, view_origin);
                }
                else
                {
-                       Draw_CylindricLine(this.origin, trace_endpos, this.scale, "particles/laserbeam", 0, time * 3, this.colormod, 0.5, DRAWFLAG_ADDITIVE, view_origin);
+                       Draw_CylindricLine(this.origin, trace_endpos, this.scale, "particles/laserbeam", 0, time * 3, this.beam_color, 0.5, DRAWFLAG_ADDITIVE, view_origin);
                }
        }
        if (!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
        {
                if(this.cnt >= 0)
                        __pointparticles(this.cnt, trace_endpos, trace_plane_normal, drawframetime * 1000);
-               if(this.colormod != '0 0 0' && this.modelscale != 0)
-                       adddynamiclight(trace_endpos + trace_plane_normal * 1, this.modelscale, this.colormod * 5);
+               if(this.beam_color != '0 0 0' && this.modelscale != 0)
+                       adddynamiclight(trace_endpos + trace_plane_normal * 1, this.modelscale, this.beam_color * 5);
        }
 }
 
@@ -317,43 +360,43 @@ NET_HANDLE(ENT_CLIENT_LASER, bool isnew)
        InterpolateOrigin_Undo(this);
 
        // 30 bytes, or 13 bytes for just moving
-       int f = ReadByte();
-       this.count = (f & 0xF0);
+       int sendflags = ReadByte();
+       this.count = (sendflags & 0xF0);
 
-       if(this.count & 0x80)
+       if(this.count & SF_LASER_FINITE)
                this.iflags = IFLAG_VELOCITY | IFLAG_ORIGIN;
        else
                this.iflags = IFLAG_ANGLES | IFLAG_ORIGIN;
 
-       if(f & 1)
+       if(sendflags & SF_LASER_UPDATE_ORIGIN)
        {
                this.origin = ReadVector();
                setorigin(this, this.origin);
        }
-       if(f & 8)
+       if(sendflags & SF_LASER_UPDATE_EFFECT)
        {
-               this.colormod_x = ReadByte() / 255.0;
-               this.colormod_y = ReadByte() / 255.0;
-               this.colormod_z = ReadByte() / 255.0;
-               if(f & 0x40)
+               this.beam_color.x = ReadByte() / 255.0;
+               this.beam_color.y = ReadByte() / 255.0;
+               this.beam_color.z = ReadByte() / 255.0;
+               if(sendflags & SF_LASER_ALPHA)
                        this.alpha = ReadByte() / 255.0;
                else
                        this.alpha = 0;
-               this.scale = 2;
-               this.modelscale = 50;
-               if(f & 0x20)
+               this.scale = 2; // NOTE: why 2?
+               this.modelscale = 50; // NOTE: why 50?
+               if(sendflags & SF_LASER_SCALE)
                {
                        this.scale *= ReadByte() / 16.0; // beam radius
                        this.modelscale *= ReadByte() / 16.0; // dlight radius
                }
-               if((f & 0x80) || !(f & 0x10))
-                       this.cnt = ReadShort() - 1; // effect number
+               if((sendflags & SF_LASER_FINITE) || !(sendflags & SF_LASER_NOTRACE))
+                       this.cnt = ReadShort(); // effect number
                else
                        this.cnt = 0;
        }
-       if(f & 2)
+       if(sendflags & SF_LASER_UPDATE_TARGET)
        {
-               if(f & 0x80)
+               if(sendflags & SF_LASER_FINITE)
                {
                        this.velocity = ReadVector();
                }
@@ -363,8 +406,8 @@ NET_HANDLE(ENT_CLIENT_LASER, bool isnew)
                        this.angles_y = ReadAngle();
                }
        }
-       if(f & 4)
-               this.state = ReadByte();
+       if(sendflags & SF_LASER_UPDATE_ACTIVE)
+               this.active = ReadByte();
 
        return = true;
 
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..0ff57646ad760e1c3b8b884bec49c4b53b800ea3 100644 (file)
@@ -1 +1,22 @@
 #pragma once
+
+
+const int LASER_FINITE = BIT(1);
+const int LASER_NOTRACE = BIT(2);
+const int LASER_INVERT_TEAM = BIT(3);
+
+const int SF_LASER_UPDATE_ORIGIN = BIT(0);
+const int SF_LASER_UPDATE_TARGET = BIT(1);
+const int SF_LASER_UPDATE_ACTIVE = BIT(2);
+const int SF_LASER_UPDATE_EFFECT = BIT(3);
+
+const int SF_LASER_NOTRACE = BIT(4);
+const int SF_LASER_SCALE = BIT(5);
+const int SF_LASER_ALPHA = BIT(6);
+const int SF_LASER_FINITE = BIT(7);
+
+.vector beam_color;
+
+const float LASER_BEAM_MAXLENGTH = 32768; // maximum length of a beam trace
+// TODO: find a better way to do this
+const float LASER_BEAM_MAXWORLDSIZE = 1048576; // to make sure the endpoint of the beam is not visible inside
index 6d32f3c36b3fdef1c41a7a60c8845226c5b201e0..126a20ea26ec08e254c1ee6e9d9473479b084dda 100644 (file)
@@ -3,12 +3,12 @@ REGISTER_NET_LINKED(ENT_CLIENT_TELEPORT_DEST)
 
 #ifdef SVQC
 
-bool teleport_dest_send(entity this, entity to, int sf)
+bool teleport_dest_send(entity this, entity to, int sendflags)
 {
        WriteHeader(MSG_ENTITY, ENT_CLIENT_TELEPORT_DEST);
-       WriteByte(MSG_ENTITY, sf);
+       WriteByte(MSG_ENTITY, sendflags);
 
-       if(sf & 1)
+       if(sendflags & SF_TRIGGER_INIT)
        {
                WriteByte(MSG_ENTITY, this.cnt);
                WriteCoord(MSG_ENTITY, this.speed);
@@ -26,7 +26,7 @@ bool teleport_dest_send(entity this, entity to, int sf)
 void teleport_dest_link(entity this)
 {
        Net_LinkEntity(this, false, 0, teleport_dest_send);
-       this.SendFlags |= 1; // update
+       this.SendFlags |= SF_TRIGGER_INIT;
 }
 
 spawnfunc(info_teleport_destination)
@@ -63,9 +63,9 @@ void teleport_dest_remove(entity this)
 
 NET_HANDLE(ENT_CLIENT_TELEPORT_DEST, bool isnew)
 {
-       int sf = ReadByte();
+       int sendflags = ReadByte();
 
-       if(sf & 1)
+       if(sendflags & SF_TRIGGER_INIT)
        {
                this.classname = "info_teleport_destination";
                this.cnt = ReadByte();
index 8ea48275d36b8d0f5d5ce9c98aacdfdf1d2a746d..4747877314a3ac52f78c30c06233ec3f63dcf170 100644 (file)
@@ -61,7 +61,7 @@ void plat_spawn_inside_trigger(entity this)
 void plat_hit_top(entity this)
 {
        _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
-       this.state = 1;
+       this.state = STATE_TOP;
 
        setthink(this, plat_go_down);
        this.nextthink = this.ltime + 3;
@@ -70,20 +70,20 @@ void plat_hit_top(entity this)
 void plat_hit_bottom(entity this)
 {
        _sound (this, CH_TRIGGER_SINGLE, this.noise1, VOL_BASE, ATTEN_NORM);
-       this.state = 2;
+       this.state = STATE_BOTTOM;
 }
 
 void plat_go_down(entity this)
 {
        _sound (this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_NORM);
-       this.state = 3;
+       this.state = STATE_DOWN;
        SUB_CalcMove (this, this.pos2, TSPEED_LINEAR, this.speed, plat_hit_bottom);
 }
 
 void plat_go_up(entity this)
 {
        _sound (this, CH_TRIGGER_SINGLE, this.noise, VOL_BASE, ATTEN_NORM);
-       this.state = 4;
+       this.state = STATE_UP;
        SUB_CalcMove (this, this.pos1, TSPEED_LINEAR, this.speed, plat_hit_top);
 }
 
@@ -102,9 +102,9 @@ void plat_center_touch(entity this, entity toucher)
                return;
 #endif
 
-       if (this.enemy.state == 2) {
+       if (this.enemy.state == STATE_BOTTOM) {
                plat_go_up(this.enemy);
-       } else if (this.enemy.state == 1)
+       } else if (this.enemy.state == STATE_TOP)
                this.enemy.nextthink = this.enemy.ltime + 1;
 }
 
@@ -121,7 +121,7 @@ void plat_outside_touch(entity this, entity toucher)
                return;
 #endif
 
-       if (this.enemy.state == 1) {
+       if (this.enemy.state == STATE_TOP) {
            entity e = this.enemy;
                plat_go_down(e);
     }
@@ -137,7 +137,7 @@ void plat_trigger_use(entity this, entity actor, entity trigger)
 
 void plat_crush(entity this, entity blocker)
 {
-       if((this.spawnflags & 4) && (blocker.takedamage != DAMAGE_NO))
+       if((this.spawnflags & CRUSH) && (blocker.takedamage != DAMAGE_NO))
        { // KIll Kill Kill!!
 #ifdef SVQC
                Damage (blocker, this, this, 10000, DEATH_HURTTRIGGER.m_id, DMG_NOWEP, blocker.origin, '0 0 0');
@@ -155,9 +155,9 @@ void plat_crush(entity this, entity blocker)
                }
 #endif
 
-               if (this.state == 4)
+               if (this.state == STATE_UP)
                        plat_go_down (this);
-               else if (this.state == 3)
+               else if (this.state == STATE_DOWN)
                        plat_go_up (this);
        // when in other states, then the plat_crush event came delayed after
        // plat state already had changed
@@ -168,11 +168,13 @@ void plat_crush(entity this, entity blocker)
 void plat_use(entity this, entity actor, entity trigger)
 {
        this.use = func_null;
-       if (this.state != 4)
+       if (this.state != STATE_UP)
                objerror (this, "plat_use: not in up state");
        plat_go_down(this);
 }
 
+// WARNING: backwards compatibility because people don't use already existing fields :(
+// TODO: Check if any maps use these fields and remove these fields if it doesn't break maps
 .string sound1, sound2;
 
 void plat_reset(entity this)
@@ -180,13 +182,13 @@ void plat_reset(entity this)
        IFTARGETED
        {
                setorigin(this, this.pos1);
-               this.state = 4;
+               this.state = STATE_UP;
                this.use = plat_use;
        }
        else
        {
                setorigin(this, this.pos2);
-               this.state = 2;
+               this.state = STATE_BOTTOM;
                this.use = plat_trigger_use;
        }
 
index c40467494f367adf9c68af7390dbd55ee6ec120c..346cebc7163dfade8657cba5caa5e3cc455838c6 100644 (file)
@@ -1,5 +1,8 @@
 #pragma once
 
+
+const int PLAT_LOW_TRIGGER = BIT(0);
+
 .float dmgtime2;
 
 void plat_center_touch(entity this, entity toucher);
@@ -8,6 +11,5 @@ void plat_trigger_use(entity this, entity actor, entity trigger);
 void plat_go_up(entity this);
 void plat_go_down(entity this);
 void plat_crush(entity this, entity blocker);
-const float PLAT_LOW_TRIGGER = 1;
 
 .float dmg;
index 5b6182e0ab8574877e11f8432a316bcf41e94aa3..2a237fdcb79abdb5be234fd7e65b0dd4512134c4 100644 (file)
@@ -145,6 +145,8 @@ void SUB_CalcMove_controller_think (entity this)
                // derivative: delta + 2 * delta2 (e.g. for angle positioning)
                entity own = this.owner;
                setthink(own, this.think1);
+               // set the owner's reference to this entity to NULL
+               own.move_controller = NULL;
                delete(this);
                getthink(own)(own);
        }
@@ -220,8 +222,14 @@ void SUB_CalcMove_Bezier (entity this, vector tcontrol, vector tdest, float tspe
                return;
        }
 
+       // delete the previous controller, otherwise changing movement midway is glitchy
+       if (this.move_controller != NULL)
+       {
+               delete(this.move_controller);
+       }
        controller = new(SUB_CalcMove_controller);
        controller.owner = this;
+       this.move_controller = controller;
        controller.platmovetype = this.platmovetype;
        controller.platmovetype_start = this.platmovetype_start;
        controller.platmovetype_end = this.platmovetype_end;
index 1b3bc5e690d438f6eeb1b0bf228eab6efd7ee75a..8d4e406504cf62eadd2458b01912eb938c5c51bc 100644 (file)
@@ -1,4 +1,5 @@
 #pragma once
+#include "defs.qh"
 
 void SUB_SetFade (entity ent, float when, float fading_time);
 void SUB_VanishOrRemove (entity ent);
@@ -41,17 +42,14 @@ void SUB_VanishOrRemove (entity ent);
 
 .vector dest1, dest2;
 
+.entity move_controller;
+
 #ifdef CSQC
 // this stuff is defined in the server side engine VM, so we must define it separately here
 .float takedamage;
-const float DAMAGE_NO  = 0;
-const float DAMAGE_YES = 1;
-const float DAMAGE_AIM = 2;
-
-float  STATE_TOP               = 0;
-float  STATE_BOTTOM    = 1;
-float  STATE_UP                = 2;
-float  STATE_DOWN              = 3;
+const int DAMAGE_NO = 0;
+const int DAMAGE_YES = 1;
+const int DAMAGE_AIM = 2;
 
 .string                noise, noise1, noise2, noise3;  // contains names of wavs to play
 
index 6c006d42a91610e70cd3984bc076cdc61312885c..114fd871818a14e4ea3df07f52584aa88802ec65 100644 (file)
@@ -5,7 +5,7 @@
 
 void target_changelevel_use(entity this, entity actor, entity trigger)
 {
-       if(this.spawnflags & 2)
+       if(this.spawnflags & CHANGELEVEL_MULTIPLAYER)
        {
                // simply don't react if a non-player triggers it
                if(!IS_PLAYER(actor)) { return; }
@@ -33,10 +33,23 @@ void target_changelevel_use(entity this, entity actor, entity trigger)
                localcmd(strcat("changelevel ", this.chmap, "\n"));
 }
 
+/*target_changelevel
+Target to change/end level
+KEYS:
+chmap: map to switch to, leave empty for endmatch
+gametype: gametype for the next map
+count: fraction of real players that need to trigger this entity for levelchange
+SPAWNFLAGS:
+CHANGELEVEL_MULTIPLAYER: multiplayer support
+*/
+
 spawnfunc(target_changelevel)
 {
        this.use = target_changelevel_use;
 
-       if(!this.count) { this.count = 0.7; }
+       if(!this.count)
+       {
+               this.count = 0.7;
+       }
 }
 #endif
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..f6e206edc9a4f52ecc4b7a0d53ca07764563fd54 100644 (file)
@@ -1 +1,4 @@
 #pragma once
+
+
+const int CHANGELEVEL_MULTIPLAYER = BIT(1);
index 6cef53d6e558c5fe76aaae3bcfa7a9fece1ce90c..21419cf81a1e52c8ae056b02f1f81704d9d12249 100644 (file)
@@ -14,6 +14,8 @@ void target_levelwarp_use(entity this, entity actor, entity trigger)
 
 spawnfunc(target_levelwarp)
 {
+       // this.cnt is index (starting from 1) of the campaign level to warp to
+       // 0 means next level
        this.use = target_levelwarp_use;
 }
 #endif
index 47977f267eff651f01575b1a13fddf01956f9640..5a63872dbd6c46b6742b3534be7b4531c0d38ef2 100644 (file)
@@ -14,7 +14,10 @@ REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_MUSIC)
 #ifdef SVQC
 
 IntrusiveList g_targetmusic_list;
-STATIC_INIT(g_targetmusic_list) { g_targetmusic_list = IL_NEW(); }
+STATIC_INIT(g_targetmusic_list)
+{
+       g_targetmusic_list = IL_NEW();
+}
 
 // values:
 //   volume
@@ -37,7 +40,10 @@ void target_music_sendto(entity this, int to, bool is)
 }
 void target_music_reset(entity this)
 {
-       if (this.targetname == "") target_music_sendto(this, MSG_ALL, 1);
+       if (this.targetname == "")
+       {
+               target_music_sendto(this, MSG_ALL, true);
+       }
 }
 void target_music_kill()
 {
@@ -45,9 +51,9 @@ void target_music_kill()
        {
                it.volume = 0;
         if (it.targetname == "")
-            target_music_sendto(it, MSG_ALL, 1);
+            target_music_sendto(it, MSG_ALL, true);
         else
-            target_music_sendto(it, MSG_ALL, 0);
+            target_music_sendto(it, MSG_ALL, false);
        });
 }
 void target_music_use(entity this, entity actor, entity trigger)
@@ -57,11 +63,11 @@ void target_music_use(entity this, entity actor, entity trigger)
        if(IS_REAL_CLIENT(actor))
        {
                msg_entity = actor;
-               target_music_sendto(this, MSG_ONE, 1);
+               target_music_sendto(this, MSG_ONE, true);
        }
        FOREACH_CLIENT(IS_SPEC(it) && it.enemy == actor, {
                msg_entity = it;
-               target_music_sendto(this, MSG_ONE, 1);
+               target_music_sendto(this, MSG_ONE, true);
        });
 }
 spawnfunc(target_music)
@@ -72,18 +78,18 @@ spawnfunc(target_music)
                this.volume = 1;
        IL_PUSH(g_targetmusic_list, this);
        if(this.targetname == "")
-               target_music_sendto(this, MSG_INIT, 1);
+               target_music_sendto(this, MSG_INIT, true);
        else
-               target_music_sendto(this, MSG_INIT, 0);
+               target_music_sendto(this, MSG_INIT, false);
 }
 void TargetMusic_RestoreGame()
 {
        IL_EACH(g_targetmusic_list, true,
        {
                if(it.targetname == "")
-                       target_music_sendto(it, MSG_INIT, 1);
+                       target_music_sendto(it, MSG_INIT, true);
                else
-                       target_music_sendto(it, MSG_INIT, 0);
+                       target_music_sendto(it, MSG_INIT, false);
        });
 }
 // values:
@@ -92,20 +98,17 @@ void TargetMusic_RestoreGame()
 //   targetname
 //   fade_time
 // spawnflags:
-//   1 = START_OFF
-// when triggered, it is disabled/enabled for everyone
-bool trigger_music_SendEntity(entity this, entity to, float sf)
+//   START_DISABLED
+// can be disabled/enabled for everyone with relays
+bool trigger_music_SendEntity(entity this, entity to, int sendflags)
 {
        WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_MUSIC);
-       sf &= ~0x80;
-       if(this.cnt)
-               sf |= 0x80;
-       WriteByte(MSG_ENTITY, sf);
-       if(sf & 4)
+       WriteByte(MSG_ENTITY, sendflags);
+       if(sendflags & SF_MUSIC_ORIGIN)
        {
                WriteVector(MSG_ENTITY, this.origin);
        }
-       if(sf & 1)
+       if(sendflags & SF_TRIGGER_INIT)
        {
                if(this.model != "null")
                {
@@ -123,31 +126,44 @@ bool trigger_music_SendEntity(entity this, entity to, float sf)
                WriteByte(MSG_ENTITY, this.fade_rate * 16.0);
                WriteString(MSG_ENTITY, this.noise);
        }
-       return 1;
+       if(sendflags & SF_TRIGGER_UPDATE)
+       {
+               WriteByte(MSG_ENTITY, this.active);
+       }
+       return true;
 }
 void trigger_music_reset(entity this)
 {
-       this.cnt = !(this.spawnflags & 1);
-       this.SendFlags |= 0x80;
-}
-void trigger_music_use(entity this, entity actor, entity trigger)
-{
-       this.cnt = !this.cnt;
-       this.SendFlags |= 0x80;
+       if(this.spawnflags & START_DISABLED)
+       {
+               this.setactive(this, ACTIVE_NOT);
+       }
+       else
+       {
+               this.setactive(this, ACTIVE_ACTIVE);
+       }
 }
+
 spawnfunc(trigger_music)
 {
-       if(this.model != "") _setmodel(this, this.model);
-       if(!this.volume) this.volume = 1;
+       if(this.model != "")
+       {
+               _setmodel(this, this.model);
+       }
+       if(!this.volume)
+       {
+               this.volume = 1;
+       }
        if(!this.modelindex)
        {
                setorigin(this, this.origin + this.mins);
                setsize(this, '0 0 0', this.maxs - this.mins);
        }
-       trigger_music_reset(this);
 
-       this.use = trigger_music_use;
+       this.setactive = generic_netlinked_setactive;
+       this.use = generic_netlinked_legacy_use; // backwards compatibility
        this.reset = trigger_music_reset;
+       this.reset(this);
 
        Net_LinkEntity(this, false, 0, trigger_music_SendEntity);
 }
@@ -163,8 +179,14 @@ void TargetMusic_Advance()
 {
        // run AFTER all the thinks!
        entity best = music_default;
-       if (music_target && time < music_target.lifetime) best = music_target;
-       if (music_trigger) best = music_trigger;
+       if (music_target && time < music_target.lifetime)
+       {
+               best = music_target;
+       }
+       if (music_trigger)
+       {
+               best = music_trigger;
+       }
        LL_EACH(TargetMusic_list, it.noise, {
                const float vol0 = (getsoundtime(it, CH_BGM_SINGLE) >= 0) ? it.lastvol : -1;
                if (it == best)
@@ -181,9 +203,9 @@ void TargetMusic_Advance()
                if (vol != vol0)
                {
                        if(vol0 < 0)
-                               _sound(it, CH_BGM_SINGLE, it.noise, vol, ATTEN_NONE); // restart
+                               sound7(it, CH_BGM_SINGLE, it.noise, vol, ATTEN_NONE, 0, BIT(4)); // restart
                        else
-                               _sound(it, CH_BGM_SINGLE, "", vol, ATTEN_NONE);
+                               sound7(it, CH_BGM_SINGLE, "", vol, ATTEN_NONE, 0, BIT(4));
                        it.lastvol = vol;
                }
        });
@@ -250,11 +272,15 @@ void Net_TargetMusic()
 
 void Ent_TriggerMusic_Think(entity this)
 {
-       if(WarpZoneLib_BoxTouchesBrush(view_origin, view_origin, this, NULL))
+       if(this.active == ACTIVE_NOT)
+       {
+               return;
+       }
+       vector org = (csqcplayer) ? csqcplayer.origin : view_origin;
+       if(WarpZoneLib_BoxTouchesBrush(org + STAT(PL_MIN), org + STAT(PL_MAX), this, NULL))
        {
                music_trigger = this;
        }
-       this.nextthink = time;
 }
 
 void Ent_TriggerMusic_Remove(entity this)
@@ -264,12 +290,12 @@ void Ent_TriggerMusic_Remove(entity this)
 
 NET_HANDLE(ENT_CLIENT_TRIGGER_MUSIC, bool isnew)
 {
-       int f = ReadByte();
-       if(f & 4)
+       int sendflags = ReadByte();
+       if(sendflags & SF_MUSIC_ORIGIN)
        {
                this.origin = ReadVector();
        }
-       if(f & 1)
+       if(sendflags & SF_TRIGGER_INIT)
        {
                this.modelindex = ReadShort();
                if(this.modelindex)
@@ -291,20 +317,27 @@ NET_HANDLE(ENT_CLIENT_TRIGGER_MUSIC, bool isnew)
                if(this.noise != s)
                {
                        precache_sound(this.noise);
-                       _sound(this, CH_BGM_SINGLE, this.noise, 0, ATTEN_NONE);
+                       sound7(this, CH_BGM_SINGLE, this.noise, 0, ATTEN_NONE, 0, BIT(4));
                        if(getsoundtime(this, CH_BGM_SINGLE) < 0)
                        {
-                               LOG_TRACEF("Cannot initialize sound %s", this.noise);
+                               LOG_WARNF("Cannot initialize sound %s", this.noise);
                                strfree(this.noise);
                        }
                }
        }
+       if(sendflags & SF_TRIGGER_UPDATE)
+       {
+               this.active = ReadByte();
+       }
 
        setorigin(this, this.origin);
        setsize(this, this.mins, this.maxs);
-       this.cnt = 1;
-       setthink(this, Ent_TriggerMusic_Think);
-       this.nextthink = time;
+       this.draw = Ent_TriggerMusic_Think;
+       if(isnew)
+       {
+               LL_PUSH(TargetMusic_list, this);
+               IL_PUSH(g_drawables, this);
+       }
        return true;
 }
 
index 1cb32ea39c180b4c05f0095a3c58535669248084..ccf3f674e6f069394ec256b6a086df3eb1076aee 100644 (file)
@@ -2,6 +2,8 @@
 
 .float lifetime;
 
+const int SF_MUSIC_ORIGIN = BIT(2);
+
 #ifdef CSQC
 float music_disabled;
 entity music_default;
index 1464da95511260b8ce4592e705b50bf9a62e7c2d..9c999ed4df4758612b9052a34aeb22101b85b905 100644 (file)
@@ -12,8 +12,7 @@
 // "classname" "target_spawn"
 // "message" "fieldname value fieldname value ..."
 // "spawnflags"
-//   1 = call the spawn function
-//   2 = trigger on map load
+//   ON_MAPLOAD = trigger on map load
 
 float target_spawn_initialized;
 .void(entity this) target_spawn_spawnfunc;
@@ -298,7 +297,7 @@ void target_spawn_use(entity this, entity actor, entity trigger)
 void target_spawn_spawnfirst(entity this)
 {
        entity act = this.target_spawn_activator;
-       if(this.spawnflags & 2)
+       if(this.spawnflags & ON_MAPLOAD)
                target_spawn_use(this, act, NULL);
 }
 
index af327b443bc21febb1c8494829bfd10e1fb4543a..11c9ad7baef1d7c682feae42db5fa9162325532a 100644 (file)
@@ -54,7 +54,7 @@ void target_speaker_use_on(entity this, entity actor, entity trigger)
        else
                snd = this.noise;
        _sound(this, CH_TRIGGER_SINGLE, snd, VOL_BASE * this.volume, this.atten);
-       if(this.spawnflags & 3)
+       if(this.spawnflags & (SPEAKER_LOOPED_ON + SPEAKER_LOOPED_OFF))
                this.use = target_speaker_use_off;
 }
 void target_speaker_use_off(entity this, entity actor, entity trigger)
@@ -64,12 +64,12 @@ void target_speaker_use_off(entity this, entity actor, entity trigger)
 }
 void target_speaker_reset(entity this)
 {
-       if(this.spawnflags & 1) // LOOPED_ON
+       if(this.spawnflags & SPEAKER_LOOPED_ON)
        {
                if(this.use == target_speaker_use_on)
                        target_speaker_use_on(this, NULL, NULL);
        }
-       else if(this.spawnflags & 2)
+       else if(this.spawnflags & SPEAKER_LOOPED_OFF)
        {
                if(this.use == target_speaker_use_off)
                        target_speaker_use_off(this, NULL, NULL);
@@ -83,7 +83,13 @@ spawnfunc(target_speaker)
        if(this.noise)
                precache_sound (this.noise);
 
-       if(!this.atten && !(this.spawnflags & 4))
+       if(!this.atten && (this.spawnflags & SPEAKER_GLOBAL))
+       {
+               LOG_WARN("target_speaker uses legacy spawnflag GLOBAL (BIT(2)), please set atten to -1 instead");
+               this.atten = -1;
+       }
+
+       if(!this.atten)
        {
                IFTARGETED
                        this.atten = ATTEN_NORM;
@@ -98,14 +104,14 @@ spawnfunc(target_speaker)
 
        IFTARGETED
        {
-               if(this.spawnflags & 8) // ACTIVATOR
+               if(this.spawnflags & SPEAKER_ACTIVATOR)
                        this.use = target_speaker_use_activator;
-               else if(this.spawnflags & 1) // LOOPED_ON
+               else if(this.spawnflags & SPEAKER_LOOPED_ON)
                {
                        target_speaker_use_on(this, NULL, NULL);
                        this.reset = target_speaker_reset;
                }
-               else if(this.spawnflags & 2) // LOOPED_OFF
+               else if(this.spawnflags & SPEAKER_LOOPED_OFF)
                {
                        this.use = target_speaker_use_on;
                        this.reset = target_speaker_reset;
@@ -113,12 +119,12 @@ spawnfunc(target_speaker)
                else
                        this.use = target_speaker_use_on;
        }
-       else if(this.spawnflags & 1) // LOOPED_ON
+       else if(this.spawnflags & SPEAKER_LOOPED_ON)
        {
                ambientsound (this.origin, this.noise, VOL_BASE * this.volume, this.atten);
                delete(this);
        }
-       else if(this.spawnflags & 2) // LOOPED_OFF
+       else if(this.spawnflags & SPEAKER_LOOPED_OFF)
        {
                objerror(this, "This sound entity can never be activated");
        }
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..53e0194be46b2e38509ab33eed11541c310feed2 100644 (file)
@@ -1 +1,7 @@
 #pragma once
+
+
+const int SPEAKER_LOOPED_ON = BIT(0);
+const int SPEAKER_LOOPED_OFF = BIT(1);
+const int SPEAKER_GLOBAL = BIT(2); // legacy, set speaker atten to -1 instead
+const int SPEAKER_ACTIVATOR = BIT(3);
index 6f5b2b595d8c09a110839cb4aeb3ca3a3ef11f42..68c5114f4d5bbf06d398f27b32584551737e42a8 100644 (file)
@@ -1,21 +1,23 @@
 #pragma once
+#include "defs.qh"
 
 IntrusiveList g_teleporters;
 STATIC_INIT(g_teleporters) { g_teleporters = IL_NEW(); }
 
 .entity pusher;
-const float TELEPORT_FLAG_SOUND = 1;
-const float TELEPORT_FLAG_PARTICLES = 2;
-const float TELEPORT_FLAG_TDEATH = 4;
-const float TELEPORT_FLAG_FORCE_TDEATH = 8;
+
+const int TELEPORT_FLAG_SOUND = BIT(0);
+const int TELEPORT_FLAG_PARTICLES = BIT(1);
+const int TELEPORT_FLAG_TDEATH = BIT(2);
+const int TELEPORT_FLAG_FORCE_TDEATH = BIT(3);
 
 #define TELEPORT_FLAGS_WARPZONE   0
 #define TELEPORT_FLAGS_PORTAL     (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
 #define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
 
 // types for .teleportable entity setting
-const float TELEPORT_NORMAL = 1; // play sounds/effects etc
-const float TELEPORT_SIMPLE = 2; // only do teleport, nothing special
+const int TELEPORT_NORMAL = 1; // play sounds/effects etc
+const int TELEPORT_SIMPLE = 2; // only do teleport, nothing special
 
 entity Simple_TeleportPlayer(entity teleporter, entity player);
 
index 87c046b0dba724fc877ad318b9b95e1be69fb8e1..4c89c4c27ed20efc86f73a678c615d68aa82673b 100644 (file)
@@ -8,7 +8,7 @@ void counter_use(entity this, entity actor, entity trigger)
        if (this.count < 0)
                return;
 
-       bool doactivate = (this.spawnflags & 4);
+       bool doactivate = (this.spawnflags & COUNTER_FIRE_AT_COUNT);
 
        if (this.count == 0)
        {
@@ -45,14 +45,15 @@ void counter_reset(entity this)
        this.count = this.cnt;
 }
 
-/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage
+/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage COUNTER_FIRE_AT_COUNT
 Acts as an intermediary for an action that takes multiple inputs.
 
 If nomessage is not set, it will print "1 more.. " etc when triggered and "sequence complete" when finished.
+If COUNTER_FIRE_AT_COUNT is set, it will also fire all of its targets at countdown, making it behave like trigger_mulitple with limited shots
 
 If respawntime is set, it will re-enable itself after the time once the sequence has been completed
 
-After the counter has been triggered "count" times (default 2), it will fire all of it's targets and remove itself.
+After the counter has been triggered "count" times (default 2), it will fire all of its targets.
 */
 spawnfunc(trigger_counter)
 {
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..394d15472cdbc68f289b9476ec00311e6dd22e09 100644 (file)
@@ -1 +1,4 @@
 #pragma once
+
+
+const int COUNTER_FIRE_AT_COUNT = BIT(2);
index af212ff5a42b7449bea067a2c755d4c86374782f..141f3ea9f19e513dcad6aeaa07e304efaec9dea8 100644 (file)
@@ -12,8 +12,10 @@ void flipflop_use(entity this, entity actor, entity trigger)
 
 spawnfunc(trigger_flipflop)
 {
-    if(this.spawnflags & 1)
-        this.state = 1;
+    if(this.spawnflags & START_ENABLED)
+    {
+        this.state = true;
+    }
     this.use = flipflop_use;
     this.reset = spawnfunc_trigger_flipflop; // perfect resetter
 }
index 3ea1562f084a93e4c73b7fdb0c9a26ac64dad90e..1ac0f8768d5d355b1a4b0d8d7cea8f97935c6cf5 100644 (file)
@@ -33,29 +33,31 @@ void trigger_gravity_check_think(entity this)
        }
 }
 
+// legacy
 void trigger_gravity_use(entity this, entity actor, entity trigger)
 {
-       this.state = !this.state;
+       this.setactive(this, ACTIVE_TOGGLE);
 }
 
 void trigger_gravity_touch(entity this, entity toucher)
 {
        float g;
 
-       if(this.state != true)
+       if(this.active == ACTIVE_NOT)
                return;
 
        EXACTTRIGGER_TOUCH(this, toucher);
 
        g = this.gravity;
 
-       if (!(this.spawnflags & 1))
+       if (!(this.spawnflags & GRAVITY_STICKY))
        {
                if(toucher.trigger_gravity_check)
                {
                        if(this == toucher.trigger_gravity_check.enemy)
                        {
                                // same?
+                               // NOTE: see explanation in trigger_gravity_check_think
                                toucher.trigger_gravity_check.count = 2; // gravity one more frame...
                                return;
                        }
@@ -96,12 +98,14 @@ spawnfunc(trigger_gravity)
        if(this.noise != "")
                precache_sound(this.noise);
 
-       this.state = true;
+       this.active = ACTIVE_ACTIVE;
+       this.setactive = generic_setactive;
        IFTARGETED
        {
+               // legacy use
                this.use = trigger_gravity_use;
-               if(this.spawnflags & 2)
-                       this.state = false;
+               if(this.spawnflags & GRAVITY_START_DISABLED)
+                       this.active = ACTIVE_NOT;
        }
 }
 #endif
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..872f04ad9fdc98e2a9add384d504019e913d109e 100644 (file)
@@ -1 +1,5 @@
 #pragma once
+
+
+const int GRAVITY_STICKY = BIT(0); // keep gravity multiplier even after exiting the trigger_gravity
+const int GRAVITY_START_DISABLED = BIT(1);
index 0f5c69c777f65c0540a41de281622f4af56feb08..cfcd726fcdb8e02c4a8997cf1477b0556f1c54dd 100644 (file)
@@ -9,9 +9,7 @@ void trigger_heal_touch(entity this, entity toucher)
        // only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
        if (toucher.iscreature)
        {
-               if (toucher.takedamage)
-               if (!IS_DEAD(toucher))
-               if (toucher.triggerhealtime < time)
+               if (toucher.takedamage && !IS_DEAD(toucher) && toucher.triggerhealtime < time)
                {
                        bool is_trigger = this.targetname == "";
                        if(is_trigger)
@@ -19,7 +17,7 @@ void trigger_heal_touch(entity this, entity toucher)
                        if(this.delay > 0)
                                toucher.triggerhealtime = time + this.delay;
 
-                       bool playthesound = (this.spawnflags & 4);
+                       bool playthesound = (this.spawnflags & HEAL_SOUND_ALWAYS);
                        if (toucher.health < this.max_health)
                        {
                                playthesound = true;
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..8dbeea54569366ecb08d425ea9fd2337488968fd 100644 (file)
@@ -1 +1,4 @@
 #pragma once
+
+
+const int HEAL_SOUND_ALWAYS = BIT(2);
index 9c09f923bec779ba7495071a113cddcca0011aa3..966e0cfb0fe6657287ee8135c9f9411f732de18d 100644 (file)
@@ -15,7 +15,7 @@ void trigger_hurt_touch(entity this, entity toucher)
                return;
 
        if(this.team)
-               if(((this.spawnflags & 4) == 0) == (this.team != toucher.team))
+               if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != toucher.team))
                        return;
 
        // only do the EXACTTRIGGER_TOUCH checks when really needed (saves some cpu)
@@ -53,7 +53,7 @@ void trigger_hurt_touch(entity this, entity toucher)
 /*QUAKED spawnfunc_trigger_hurt (.5 .5 .5) ?
 Any object touching this will be hurt
 set dmg to damage amount
-defalt dmg = 5
+default dmg = 1000
 */
 .entity trigger_hurt_next;
 entity trigger_hurt_last;
@@ -80,12 +80,12 @@ spawnfunc(trigger_hurt)
        trigger_hurt_last = this;
 }
 
-float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end)
+bool tracebox_hits_trigger_hurt(vector start, vector e_min, vector e_max, vector end)
 {
        entity th;
 
        for(th = trigger_hurt_first; th; th = th.trigger_hurt_next)
-               if(tracebox_hits_box(start, mi, ma, end, th.absmin, th.absmax))
+               if(tracebox_hits_box(start, e_min, e_max, end, th.absmin, th.absmax))
                        return true;
 
        return false;
index 4be6e86bca66c6c02fcf2adbd3c7141721292647..c4e7ae287a8e9a6eda6d79532d0c06684cc38b6b 100644 (file)
@@ -1,6 +1,6 @@
 #include "impulse.qh"
 // targeted (directional) mode
-void trigger_impulse_touch1(entity this, entity toucher)
+void trigger_impulse_touch_directional(entity this, entity toucher)
 {
        entity targ;
        float pushdeltatime;
@@ -22,26 +22,26 @@ void trigger_impulse_touch1(entity this, entity toucher)
                return;
        }
 
-       str = min(this.radius, vlen(this.origin - toucher.origin));
-
-       if(this.falloff == 1)
-               str = (str / this.radius) * this.strength;
-       else if(this.falloff == 2)
-               str = (1 - (str / this.radius)) * this.strength;
-       else
-               str = this.strength;
+       // falloff is not supported because radius is always 0 in directional mode
+       str = this.strength;
 
        pushdeltatime = time - toucher.lastpushtime;
-       if (pushdeltatime > 0.15) pushdeltatime = 0;
+       if (pushdeltatime > IMPULSE_MAX_PUSHDELTATIME)
+       {
+               pushdeltatime = 0;
+       }
        toucher.lastpushtime = time;
-       if(!pushdeltatime) return;
+       if(!pushdeltatime)
+       {
+               return;
+       }
 
-       if(this.spawnflags & 64)
+       if(this.spawnflags & IMPULSE_DIRECTIONAL_SPEEDTARGET)
        {
                float addspeed = str - toucher.velocity * normalize(targ.origin - this.origin);
                if (addspeed > 0)
                {
-                       float accelspeed = min(8 * pushdeltatime * str, addspeed);
+                       float accelspeed = min(IMPULSE_DIRECTIONAL_MAX_ACCEL_FACTOR * pushdeltatime * str, addspeed);
                        toucher.velocity += accelspeed * normalize(targ.origin - this.origin);
                }
        }
@@ -56,7 +56,7 @@ void trigger_impulse_touch1(entity this, entity toucher)
 }
 
 // Directionless (accelerator/decelerator) mode
-void trigger_impulse_touch2(entity this, entity toucher)
+void trigger_impulse_touch_accel(entity this, entity toucher)
 {
        float pushdeltatime;
 
@@ -69,9 +69,15 @@ void trigger_impulse_touch2(entity this, entity toucher)
        EXACTTRIGGER_TOUCH(this, toucher);
 
        pushdeltatime = time - toucher.lastpushtime;
-       if (pushdeltatime > 0.15) pushdeltatime = 0;
+       if (pushdeltatime > IMPULSE_MAX_PUSHDELTATIME)
+       {
+               pushdeltatime = 0;
+       }
        toucher.lastpushtime = time;
-       if(!pushdeltatime) return;
+       if(!pushdeltatime)
+       {
+               return;
+       }
 
        // div0: ticrate independent, 1 = identity (not 20)
        toucher.velocity = toucher.velocity * (this.strength ** pushdeltatime);
@@ -82,7 +88,7 @@ void trigger_impulse_touch2(entity this, entity toucher)
 }
 
 // Spherical (gravity/repulsor) mode
-void trigger_impulse_touch3(entity this, entity toucher)
+void trigger_impulse_touch_radial(entity this, entity toucher)
 {
        float pushdeltatime;
        float str;
@@ -96,17 +102,23 @@ void trigger_impulse_touch3(entity this, entity toucher)
        EXACTTRIGGER_TOUCH(this, toucher);
 
        pushdeltatime = time - toucher.lastpushtime;
-       if (pushdeltatime > 0.15) pushdeltatime = 0;
+       if (pushdeltatime > IMPULSE_MAX_PUSHDELTATIME)
+       {
+               pushdeltatime = 0;
+       }
        toucher.lastpushtime = time;
-       if(!pushdeltatime) return;
+       if(!pushdeltatime)
+       {
+               return;
+       }
 
        setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
 
        str = min(this.radius, vlen(this.origin - toucher.origin));
 
-       if(this.falloff == 1)
+       if(this.falloff == FALLOFF_LINEAR)
                str = (1 - str / this.radius) * this.strength; // 1 in the inside
-       else if(this.falloff == 2)
+       else if(this.falloff == FALLOFF_LINEAR_INV)
                str = (str / this.radius) * this.strength; // 0 in the inside
        else
                str = this.strength;
@@ -121,15 +133,16 @@ void trigger_impulse_touch3(entity this, entity toucher)
 REGISTER_NET_LINKED(ENT_CLIENT_TRIGGER_IMPULSE)
 
 /*QUAKED spawnfunc_trigger_impulse (.5 .5 .5) ?
+Force field
 -------- KEYS --------
 target : If this is set, this points to the spawnfunc_target_position to which the player will get pushed.
                 If not, this trigger acts like a damper/accelerator field.
 
-strength : This is how mutch force to add in the direction of .target each second
-                  when .target is set. If not, this is hoe mutch to slow down/accelerate
-                  someting cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
+strength : This is how much force to add in the direction of .target each second
+                  when .target is set. If not, this is how much to slow down/accelerate
+                  something cought inside this trigger. (1=no change, 0,5 half speed rougthly each tic, 2 = doubble)
 
-radius   : If set, act as a spherical device rather then a liniar one.
+radius   : If set, act as a spherical device rather then a linear one.
 
 falloff : 0 = none, 1 = liniar, 2 = inverted liniar
 
@@ -142,7 +155,7 @@ bool trigger_impulse_send(entity this, entity to, int sf)
 {
        WriteHeader(MSG_ENTITY, ENT_CLIENT_TRIGGER_IMPULSE);
 
-       WriteInt24_t(MSG_ENTITY, this.spawnflags);
+       WriteByte(MSG_ENTITY, this.spawnflags);
        WriteCoord(MSG_ENTITY, this.radius);
        WriteCoord(MSG_ENTITY, this.strength);
        WriteByte(MSG_ENTITY, this.falloff);
@@ -166,23 +179,32 @@ spawnfunc(trigger_impulse)
 
        if(this.radius)
        {
-               if(!this.strength) this.strength = 2000 * autocvar_g_triggerimpulse_radial_multiplier;
+               if(!this.strength)
+               {
+                       this.strength = IMPULSE_DEFAULT_RADIAL_STRENGTH * autocvar_g_triggerimpulse_radial_multiplier;
+               }
                setorigin(this, this.origin);
                setsize(this, '-1 -1 -1' * this.radius,'1 1 1' * this.radius);
-               settouch(this, trigger_impulse_touch3);
+               settouch(this, trigger_impulse_touch_radial);
        }
        else
        {
                if(this.target)
                {
-                       if(!this.strength) this.strength = 950 * autocvar_g_triggerimpulse_directional_multiplier;
-                       settouch(this, trigger_impulse_touch1);
+                       if(!this.strength)
+                       {
+                               this.strength = IMPULSE_DEFAULT_DIRECTIONAL_STRENGTH * autocvar_g_triggerimpulse_directional_multiplier;
+                       }
+                       settouch(this, trigger_impulse_touch_directional);
                }
                else
                {
-                       if(!this.strength) this.strength = 0.9;
+                       if(!this.strength)
+                       {
+                               this.strength = IMPULSE_DEFAULT_ACCEL_STRENGTH;
+                       }
                        this.strength = (this.strength ** autocvar_g_triggerimpulse_accel_power) * autocvar_g_triggerimpulse_accel_multiplier;
-                       settouch(this, trigger_impulse_touch2);
+                       settouch(this, trigger_impulse_touch_accel);
                }
        }
 
@@ -191,7 +213,7 @@ spawnfunc(trigger_impulse)
 #elif defined(CSQC)
 NET_HANDLE(ENT_CLIENT_TRIGGER_IMPULSE, bool isnew)
 {
-       this.spawnflags = ReadInt24_t();
+       this.spawnflags = ReadByte();
        this.radius = ReadCoord();
        this.strength = ReadCoord();
        this.falloff = ReadByte();
@@ -205,8 +227,17 @@ NET_HANDLE(ENT_CLIENT_TRIGGER_IMPULSE, bool isnew)
        this.entremove = trigger_remove_generic;
        this.move_time = time;
 
-       if (this.radius) { settouch(this, trigger_impulse_touch3); }
-       else if (this.target) { settouch(this, trigger_impulse_touch1); }
-       else { settouch(this, trigger_impulse_touch2); }
+       if (this.radius)
+       {
+               settouch(this, trigger_impulse_touch_radial);
+       }
+       else if (this.target)
+       {
+               settouch(this, trigger_impulse_touch_directional);
+       }
+       else
+       {
+               settouch(this, trigger_impulse_touch_accel);
+       }
 }
 #endif
index a6961f5d2e7693920f56dac39df1d78011b88f91..e86de4a4970c58bb75435e570bd73afaef1128eb 100644 (file)
@@ -2,6 +2,20 @@
 
 // tZorks trigger impulse / gravity
 .float radius;
-.float falloff;
+.int falloff;
 .float strength;
 .float lastpushtime;
+
+const int FALLOFF_NO = 0;
+const int FALLOFF_LINEAR = 1;
+const int FALLOFF_LINEAR_INV = 2;
+
+const int IMPULSE_DIRECTIONAL_SPEEDTARGET = BIT(6);
+
+const float IMPULSE_DEFAULT_RADIAL_STRENGTH = 2000;
+const float IMPULSE_DEFAULT_DIRECTIONAL_STRENGTH = 950;
+const float IMPULSE_DEFAULT_ACCEL_STRENGTH = 0.9;
+
+const float IMPULSE_MAX_PUSHDELTATIME = 0.15;
+
+const float IMPULSE_DIRECTIONAL_MAX_ACCEL_FACTOR = 8;
index 10a726391c597bdb6b81f97d1596a2690f52f951..3c5019a5c38b71a1ddddf0433e4c30c3327e9239 100644 (file)
@@ -1,7 +1,6 @@
 #include "jumppads.qh"
 // TODO: split target_push and put it in the target folder
 #ifdef SVQC
-#include "jumppads.qh"
 #include <common/physics/movetypes/movetypes.qh>
 
 void trigger_push_use(entity this, entity actor, entity trigger)
@@ -9,7 +8,7 @@ void trigger_push_use(entity this, entity actor, entity trigger)
        if(teamplay)
        {
                this.team = actor.team;
-               this.SendFlags |= 2;
+               this.SendFlags |= SF_TRIGGER_UPDATE;
        }
 }
 #endif
@@ -254,7 +253,7 @@ void trigger_push_touch(entity this, entity toucher)
                return;
 
        if(this.team)
-               if(((this.spawnflags & 4) == 0) == (DIFF_TEAM(this, toucher)))
+               if(((this.spawnflags & INVERT_TEAMS) == 0) == (DIFF_TEAM(this, toucher)))
                        return;
 
        EXACTTRIGGER_TOUCH(this, toucher);
@@ -317,7 +316,7 @@ bool trigger_push_test(entity this, entity item)
 {
        // first calculate a typical start point for the jump
        vector org = (this.absmin + this.absmax) * 0.5;
-       org.z = this.absmax.z - PL_MIN_CONST.z - 10;
+       org.z = this.absmax.z - PL_MIN_CONST.z - 7;
 
        if (this.target)
        {
@@ -481,7 +480,7 @@ float trigger_push_send(entity this, entity to, float sf)
 
 void trigger_push_updatelink(entity this)
 {
-       this.SendFlags |= 1;
+       this.SendFlags |= SF_TRIGGER_INIT;
 }
 
 void trigger_push_link(entity this)
@@ -577,16 +576,30 @@ void target_push_init2(entity this)
        target_push_init(this); // normal push target behaviour can be combined with a legacy pusher?
 }
 
-spawnfunc(target_push) { target_push_init2(this); }
-spawnfunc(info_notnull) { target_push_init(this); }
-spawnfunc(target_position) { target_push_init(this); }
+spawnfunc(target_push)
+{
+       target_push_init2(this);
+}
+
+spawnfunc(info_notnull)
+{
+       target_push_init(this);
+}
+spawnfunc(target_position)
+{
+       target_push_init(this);
+}
 
 #elif defined(CSQC)
 
 NET_HANDLE(ENT_CLIENT_TRIGGER_PUSH, bool isnew)
 {
        this.classname = "jumppad";
-       int mytm = ReadByte(); if(mytm) { this.team = mytm - 1; }
+       int mytm = ReadByte();
+       if(mytm)
+       {
+               this.team = mytm - 1;
+       }
        this.spawnflags = ReadInt24_t();
        this.active = ReadByte();
        this.height = ReadCoord();
index 50ed0a343c8c86b7cc53e12274ddac7261bead75..07ab441fe5efcf7d61d2fe1c227c97440174b237 100644 (file)
@@ -1,11 +1,12 @@
 #pragma once
 
+
+const int PUSH_ONCE = BIT(0); // legacy, deactivate with relay instead
+const int PUSH_SILENT = BIT(1); // not used?
+
 IntrusiveList g_jumppads;
 STATIC_INIT(g_jumppads) { g_jumppads = IL_NEW(); }
 
-const float PUSH_ONCE          = 1;
-const float PUSH_SILENT                = 2;
-
 .float pushltime;
 .float istypefrag;
 .float height;
index 354ed1bfedd61f284ad76ae0f0fa73107b34abda..16118cb9d6e54906ea35f5634d095ad879f2a96f 100644 (file)
@@ -11,7 +11,7 @@ string trigger_magicear_processmessage(entity ear, entity source, float teamsay,
        magicear_matched = false;
 
        dotrigger = ((IS_PLAYER(source)) && (!IS_DEAD(source)) && ((ear.radius == 0) || (vdist(source.origin - ear.origin, <=, ear.radius))));
-       domatch = ((ear.spawnflags & 32) || dotrigger);
+       domatch = ((ear.spawnflags & MAGICEAR_REPLACE_OUTSIDE) || dotrigger);
 
        if (!domatch)
                return msgin;
@@ -19,13 +19,13 @@ string trigger_magicear_processmessage(entity ear, entity source, float teamsay,
        if (!msgin)
        {
                // we are in TUBA mode!
-               if (!(ear.spawnflags & 256))
+               if (!(ear.spawnflags & MAGICEAR_TUBA))
                        return msgin;
 
                for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
                {
                        .entity weaponentity = weaponentities[slot];
-                       if(!W_Tuba_HasPlayed(source, weaponentity, ear.message, ear.movedir_x, !(ear.spawnflags & 512), ear.movedir_y, ear.movedir_z))
+                       if(!W_Tuba_HasPlayed(source, weaponentity, ear.message, ear.movedir_x, !(ear.spawnflags & MAGICEAR_TUBA_EXACTPITCH), ear.movedir_y, ear.movedir_z))
                                return msgin;
                }
 
@@ -45,31 +45,31 @@ string trigger_magicear_processmessage(entity ear, entity source, float teamsay,
                return msgin;
        }
 
-       if(ear.spawnflags & 256) // ENOTUBA
+       if(ear.spawnflags & MAGICEAR_TUBA) // ENOTUBA
                return msgin;
 
        if(privatesay)
        {
-               if(ear.spawnflags & 4)
+               if(ear.spawnflags & MAGICEAR_IGNORE_TELL)
                        return msgin;
        }
        else
        {
                if(!teamsay)
-                       if(ear.spawnflags & 1)
+                       if(ear.spawnflags & MAGICEAR_IGNORE_SAY)
                                return msgin;
                if(teamsay > 0)
-                       if(ear.spawnflags & 2)
+                       if(ear.spawnflags & MAGICEAR_IGNORE_TEAMSAY)
                                return msgin;
                if(teamsay < 0)
-                       if(ear.spawnflags & 8)
+                       if(ear.spawnflags & MAGICEAR_IGNORE_INVALIDTELL)
                                return msgin;
        }
 
        matchstart = -1;
        l = strlen(ear.message);
 
-       if(ear.spawnflags & 128)
+       if(ear.spawnflags & MAGICEAR_NODECOLORIZE)
                msg = msgin;
        else
                msg = strdecolorize(msgin);
@@ -126,7 +126,7 @@ string trigger_magicear_processmessage(entity ear, entity source, float teamsay,
                ear.message = savemessage;
        }
 
-       if(ear.spawnflags & 16)
+       if(ear.spawnflags & MAGICEAR_REPLACE_WHOLE_MESSAGE)
        {
                return ear.netname;
        }
@@ -153,7 +153,7 @@ string trigger_magicear_processmessage_forallears(entity source, float teamsay,
        for(ear = magicears; ear; ear = ear.enemy)
        {
                msgout = trigger_magicear_processmessage(ear, source, teamsay, privatesay, msgin);
-               if(!(ear.spawnflags & 64))
+               if(!(ear.spawnflags & MAGICEAR_CONTINUE))
                if(magicear_matched)
                        return msgout;
                msgin = msgout;
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..4e705868c3f094881d7175196380b4579f46b092 100644 (file)
@@ -1 +1,13 @@
 #pragma once
+
+
+const int MAGICEAR_IGNORE_SAY = BIT(0);
+const int MAGICEAR_IGNORE_TEAMSAY = BIT(1);
+const int MAGICEAR_IGNORE_TELL = BIT(2);
+const int MAGICEAR_IGNORE_INVALIDTELL = BIT(3);
+const int MAGICEAR_REPLACE_WHOLE_MESSAGE = BIT(4);
+const int MAGICEAR_REPLACE_OUTSIDE = BIT(5);
+const int MAGICEAR_CONTINUE = BIT(6);
+const int MAGICEAR_NODECOLORIZE = BIT(7);
+const int MAGICEAR_TUBA = BIT(8);
+const int MAGICEAR_TUBA_EXACTPITCH = BIT(9);
index a67baca16a2f152d69877823eee144bfd076724a..0c960ba8a16444dc1d3287692de0797846dcf26c 100644 (file)
@@ -38,7 +38,7 @@ spawnfunc(trigger_monoflop)
 {
        if(!this.wait)
                this.wait = 1;
-       if(this.spawnflags & 1)
+       if(this.spawnflags & MONOFLOP_FIXED)
                this.use = monoflop_fixed_use;
        else
                this.use = monoflop_use;
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..c64dffdee86b28265f47129684adc01e0eb6e05b 100644 (file)
@@ -1 +1,4 @@
 #pragma once
+
+
+const int MONOFLOP_FIXED = BIT(0);
index 24b7d5f2acc11419f32f0340462675f9d7fa2a05..accfbe8ac47b057d745a4542cb214ae10a66acbd 100644 (file)
@@ -24,10 +24,12 @@ void multi_trigger(entity this)
                return;         // allready been triggered
        }
 
-       if(this.spawnflags & 16384)
-       if(!IS_PLAYER(this.enemy))
+       if(this.spawnflags & ONLY_PLAYERS && !IS_PLAYER(this.enemy))
+       {
                return; // only players
+       }
 
+       // TODO: restructure this so that trigger_secret is more independent
        if (this.classname == "trigger_secret")
        {
                if (!IS_PLAYER(this.enemy))
@@ -37,9 +39,11 @@ void multi_trigger(entity this)
        }
 
        if (this.noise)
+       {
                _sound (this.enemy, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
+       }
 
-// don't trigger again until reset
+       // don't trigger again until reset
        this.takedamage = DAMAGE_NO;
 
        SUB_UseTargets(this, this.enemy, this.goalentity);
@@ -69,15 +73,20 @@ void multi_use(entity this, entity actor, entity trigger)
 
 void multi_touch(entity this, entity toucher)
 {
-       if(!(this.spawnflags & 2))
-       if(!toucher.iscreature)
-                       return;
+       if(!(this.spawnflags & ALL_ENTITIES) && !toucher.iscreature)
+       {
+               return;
+       }
 
        if(this.team)
-               if(((this.spawnflags & 4) == 0) == (this.team != toucher.team))
+       {
+               if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != toucher.team))
+               {
                        return;
+               }
+       }
 
-// if the trigger has an angles field, check player's facing direction
+       // if the trigger has an angles field, check player's facing direction
        if (this.movedir != '0 0 0')
        {
                makevectors (toucher.angles);
@@ -87,8 +96,12 @@ void multi_touch(entity this, entity toucher)
 
        // if the trigger has pressed keys, check that the player is pressing those keys
        if(this.pressedkeys && IS_PLAYER(toucher)) // only for players
-       if(!(CS(toucher).pressedkeys & this.pressedkeys))
-               return;
+       {
+               if(!(CS(toucher).pressedkeys & this.pressedkeys))
+               {
+                       return;
+               }
+       }
 
        EXACTTRIGGER_TOUCH(this, toucher);
 
@@ -101,11 +114,11 @@ void multi_eventdamage(entity this, entity inflictor, entity attacker, float dam
 {
        if(!this.takedamage)
                return;
-       if(this.spawnflags & DOOR_NOSPLASH)
+       if(this.spawnflags & NOSPLASH)
                if(!(DEATH_ISSPECIAL(deathtype)) && (deathtype & HITTYPE_SPLASH))
                        return;
        if(this.team)
-               if(((this.spawnflags & 4) == 0) == (this.team != attacker.team))
+               if(((this.spawnflags & INVERT_TEAMS) == 0) == (this.team != attacker.team))
                        return;
        this.health = this.health - damage;
        if (this.health <= 0)
index d946efe5f17cc533c2b104b52fb1dc2c2e37ba82..932fda13ca94a5984f9e4d286848430147575158 100644 (file)
@@ -43,13 +43,13 @@ void multivibrator_toggle(entity this, entity actor, entity trigger)
 
 void multivibrator_reset(entity this)
 {
-       if(!(this.spawnflags & 1))
+       if(!(this.spawnflags & START_ENABLED))
                this.nextthink = 0; // wait for a trigger event
        else
                this.nextthink = max(1, time);
 }
 
-/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ON
+/*QUAKED trigger_multivibrator (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ENABLED
 "Multivibrator" trigger gate... repeatedly sends trigger events. When triggered, turns on or off.
 -------- KEYS --------
 target: trigger all entities with this targetname when it goes off
@@ -58,7 +58,7 @@ phase: offset of the timing
 wait: "on" cycle time (default: 1)
 respawntime: "off" cycle time (default: same as wait)
 -------- SPAWNFLAGS --------
-START_ON: assume it is already turned on (when targeted)
+START_ENABLED: assume it is already turned on (when targeted)
 */
 spawnfunc(trigger_multivibrator)
 {
index e5d0018032de0f67c63fc4ce91c5d5eaed56314a..f99d364aec5bdb560d9c1f51f5d92b3f8e77d714 100644 (file)
@@ -19,5 +19,8 @@ spawnfunc(trigger_relay)
        this.reset = spawnfunc_trigger_relay; // this spawnfunc resets fully
 }
 
-spawnfunc(target_relay) { spawnfunc_trigger_relay(this); }
+spawnfunc(target_relay)
+{
+       spawnfunc_trigger_relay(this);
+}
 #endif
index d713a05837728245f18a604f96647b5a300d40ca..18c2a40d01d569bb48cb1ba054484d1e624c4cfc 100644 (file)
@@ -9,13 +9,7 @@ void relay_activators_use(entity this, entity actor, entity trigger)
                else
                {
                        //bprint("Not using setactive\n");
-                       if(this.cnt == ACTIVE_TOGGLE)
-                               if(trg.active == ACTIVE_ACTIVE)
-                                       trg.active = ACTIVE_NOT;
-                               else
-                                       trg.active = ACTIVE_ACTIVE;
-                       else
-                               trg.active = this.cnt;
+                       generic_setactive(trg, this.cnt);
                }
        }
 }
index 728252c70400972a4259b3f49eea02c5100027d2..9adcd666ecc7ab3e73a8416ddfd118c869adce91 100644 (file)
@@ -6,7 +6,7 @@ void trigger_relay_if_use(entity this, entity actor, entity trigger)
 
        // TODO make this generic AND faster than nextent()ing through all, if somehow possible
        n = (cvar_string(this.netname) == cvar_string(this.message));
-       if(this.spawnflags & 1)
+       if(this.spawnflags & RELAYIF_NEGATE)
                n = !n;
 
        if(n)
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..6f37aa71d9e81c59914ef76cc53d5f61a0434666 100644 (file)
@@ -1 +1,4 @@
 #pragma once
+
+
+const int RELAYIF_NEGATE = BIT(0);
index fee28df51af0842986aeed926ee23aad1744f933..bf03b1542f0f957279c80f8f81ed1dbb891c0eaa 100644 (file)
@@ -4,7 +4,7 @@ void trigger_relay_teamcheck_use(entity this, entity actor, entity trigger)
 {
        if(actor.team)
        {
-               if(this.spawnflags & 2)
+               if(this.spawnflags & RELAYTEAMCHECK_INVERT)
                {
                        if(DIFF_TEAM(actor, this))
                                SUB_UseTargets(this, actor, trigger);
@@ -17,7 +17,7 @@ void trigger_relay_teamcheck_use(entity this, entity actor, entity trigger)
        }
        else
        {
-               if(this.spawnflags & 1)
+               if(this.spawnflags & RELAYTEAMCHECK_NOTEAM)
                        SUB_UseTargets(this, actor, trigger);
        }
 }
index 6f70f09beec2219624baeca92e2cd7deaa104fb4..602d2535624437a45b2c0d2cb3b00d6096212c79 100644 (file)
@@ -1 +1,5 @@
 #pragma once
+
+
+const int RELAYTEAMCHECK_NOTEAM = BIT(0);
+const int RELAYTEAMCHECK_INVERT = BIT(1);
index 0330ce8d8cc46b1e9065ff29065ff51f233dadfd..825dd01ddeea559ac5f52d8cbd944904f0a0f0f0 100644 (file)
@@ -36,7 +36,7 @@ bool Teleport_Active(entity this, entity player)
                return false;
 
        if(this.team)
-               if(((this.spawnflags & 4) == 0) == (DIFF_TEAM(this, player)))
+               if(((this.spawnflags & INVERT_TEAMS) == 0) == (DIFF_TEAM(this, player)))
                        return false;
 
        return true;
@@ -83,7 +83,10 @@ void target_teleport_use(entity this, entity actor, entity trigger)
 
        string s = this.target; this.target = string_null;
        SUB_UseTargets(this, player, player); // TODO: should we be using toucher for trigger too?
-       if (!this.target) this.target = s;
+       if (!this.target)
+       {
+               this.target = s;
+       }
 
        SUB_UseTargets(e, player, player);
 }
@@ -157,7 +160,11 @@ NET_HANDLE(ENT_CLIENT_TRIGGER_TELEPORT, bool isnew)
        this.classname = "trigger_teleport";
        if(isnew)
                IL_PUSH(g_teleporters, this);
-       int mytm = ReadByte(); if(mytm) { this.team = mytm - 1; }
+       int mytm = ReadByte();
+       if(mytm)
+       {
+               this.team = mytm - 1;
+       }
        this.spawnflags = ReadInt24_t();
        this.active = ReadByte();
        this.speed = ReadCoord();
index 8b985795da8b8701bb69239f52caa7629df156d9..ba5dcbe443ea4c26e955adfa68b9f997eb0f8d69 100644 (file)
@@ -154,7 +154,10 @@ spawnfunc(target_viewlocation_end)
 }
 
 // compatibility
-spawnfunc(target_viewlocation) { spawnfunc_target_viewlocation_start(this); }
+spawnfunc(target_viewlocation)
+{
+       spawnfunc_target_viewlocation_start(this);
+}
 
 #elif defined(CSQC)
 
index 69c6c821ed7f23cde5c765a3f8bb989f1c2de2c8..3c393afd37bd3fd03bed40ea4f75ca9b5e49b382 100644 (file)
@@ -1,11 +1,12 @@
 #pragma once
 
-.entity viewloc;
 
 const int VIEWLOC_NOSIDESCROLL = BIT(0); // NOTE: currently unimplemented
 const int VIEWLOC_FREEAIM = BIT(1);
 const int VIEWLOC_FREEMOVE = BIT(2);
 
+.entity viewloc;
+
 #ifdef CSQC
 .entity goalentity;
 .entity enemy;
index 0957699b37ad4ef9594e33f930c95b26397030e9..9db38a10b9478a6f9b53272ed21d2dc6e7353dc4 100644 (file)
@@ -21,6 +21,63 @@ void FixSize(entity e)
 }
 
 #ifdef SVQC
+void generic_setactive(entity this, int act)
+{
+       if(act == ACTIVE_TOGGLE)
+       {
+               if(this.active == ACTIVE_ACTIVE)
+               {
+                       this.active = ACTIVE_NOT;
+               }
+               else
+               {
+                       this.active = ACTIVE_ACTIVE;
+               }
+       }
+       else
+       {
+               this.active = act;
+       }
+}
+
+void generic_netlinked_setactive(entity this, int act)
+{
+       int old_status = this.active;
+       generic_setactive(this, act);
+
+       if (this.active != old_status)
+       {
+               this.SendFlags |= SF_TRIGGER_UPDATE;
+       }
+}
+
+void generic_netlinked_reset(entity this)
+{
+       IFTARGETED
+       {
+               if(this.spawnflags & START_ENABLED)
+               {
+                       this.active = ACTIVE_ACTIVE;
+               }
+               else
+               {
+                       this.active = ACTIVE_NOT;
+               }
+       }
+       else
+       {
+               this.active = ACTIVE_ACTIVE;
+       }
+
+       this.SendFlags |= SF_TRIGGER_UPDATE;
+}
+
+// Compatibility with old maps
+void generic_netlinked_legacy_use(entity this, entity actor, entity trigger)
+{
+       LOG_WARNF("Entity %s was (de)activated by a trigger, please update map to use relays", this.targetname);
+       this.setactive(this, ACTIVE_TOGGLE);
+}
 
 bool autocvar_g_triggers_debug = true;
 
index 49cd7be7c252bc74cc106a436c71034bc5dd8843..bfb32696a53e16c94d7c1c3d55d8f38af1b1cb0a 100644 (file)
@@ -1,11 +1,5 @@
 #pragma once
-
-const float SF_TRIGGER_INIT = 1;
-const float SF_TRIGGER_UPDATE = 2;
-const float SF_TRIGGER_RESET = 4;
-
-const float    SPAWNFLAG_NOMESSAGE = 1;
-const float    SPAWNFLAG_NOTOUCH = 1;
+#include "defs.qh"
 
 .bool pushable;
 
@@ -28,6 +22,13 @@ void target_voicescript_next(entity pl);
 void target_voicescript_clear(entity pl);
 
 void SUB_UseTargets_PreventReuse(entity this, entity actor, entity trigger);
+
+void generic_setactive(entity this, int act);
+// generic methods for netlinked entities
+void generic_netlinked_reset(entity this);
+void generic_netlinked_setactive(entity this, int act);
+// WARNING: DON'T USE, ONLY TO KEEP COMPATIBILITY BECAUSE OF SWITCH FROM .state TO .alive!!!!
+void generic_netlinked_legacy_use(entity this, entity actor, entity trigger);
 #endif
 
 .float sub_target_used;
@@ -45,10 +46,4 @@ void trigger_remove_generic(entity this);
 .float active;
 .string target;
 .string targetname;
-
-const int ACTIVE_NOT           = 0;
-const int ACTIVE_ACTIVE        = 1;
-const int ACTIVE_IDLE          = 2;
-const int ACTIVE_BUSY          = 2;
-const int ACTIVE_TOGGLE                = 3;
 #endif
index 96fa81f8eee98cdbbf72ce9761e2f5eaf2c1c717..c4e50a7e71f058be20cd74201a619a5878e20777 100644 (file)
@@ -6,7 +6,7 @@ spawnfunc(turret_plasma) { if (!turret_initialize(this, TUR_PLASMA)) delete(this
 
 METHOD(PlasmaTurret, tr_attack, void(PlasmaTurret this, entity it))
 {
-    if(g_instagib)
+    if(autocvar_g_instagib)
     {
         .entity weaponentity = weaponentities[0]; // TODO: unhardcode
         FireRailgunBullet (it, weaponentity, it.tur_shotorg, it.tur_shotorg + it.tur_shotdir_updated * max_shot_distance, 10000000000,
index 2a6f997cf3f009f533858d9099c0fb3492e2b7c3..8d20da5b6eed40b3c9f66eddffbe3b0c780b228a 100644 (file)
@@ -6,7 +6,7 @@ spawnfunc(turret_plasma_dual) { if (!turret_initialize(this, TUR_PLASMA_DUAL)) d
 
 METHOD(DualPlasmaTurret, tr_attack, void(DualPlasmaTurret thistur, entity it))
 {
-    if (g_instagib) {
+    if (autocvar_g_instagib) {
         .entity weaponentity = weaponentities[0]; // TODO: unhardcode
         FireRailgunBullet (it, weaponentity, it.tur_shotorg, it.tur_shotorg + it.tur_shotdir_updated * max_shot_distance, 10000000000,
                            800, 0, 0, 0, 0, DEATH_TURRET_PLASMA.m_id);
index e46745c2acf4e971e0f0bcfa41a036d9381bfd04..c3baa12127b6c3b39a947aa8fec40524362a1443 100644 (file)
@@ -144,7 +144,7 @@ void W_Vaporizer_Attack(Weapon thiswep, entity actor, .entity weaponentity)
        if(!(trace_dphitq3surfaceflags & (Q3SURFACEFLAG_SKY | Q3SURFACEFLAG_NOIMPACT)))
                W_RocketMinsta_Explosion(actor, weaponentity, trace_endpos);
 
-       W_DecreaseAmmo(thiswep, actor, ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)), weaponentity);
+       W_DecreaseAmmo(thiswep, actor, ((autocvar_g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo)), weaponentity);
 }
 
 void W_RocketMinsta_Laser_Explode (entity this, entity directhitentity)
@@ -288,7 +288,7 @@ METHOD(Vaporizer, wr_aim, void(entity thiswep, entity actor, .entity weaponentit
 }
 METHOD(Vaporizer, wr_think, void(entity thiswep, entity actor, .entity weaponentity, int fire))
 {
-    float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
+    float vaporizer_ammo = ((autocvar_g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
     // if the laser uses load, we also consider its ammo for reloading
     if(WEP_CVAR(vaporizer, reload_ammo) && WEP_CVAR_SEC(vaporizer, ammo) && actor.(weaponentity).clip_load < min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo))) { // forced reload
         thiswep.wr_reload(thiswep, actor, weaponentity);
@@ -349,7 +349,7 @@ METHOD(Vaporizer, wr_setup, void(entity thiswep, entity actor, .entity weaponent
 }
 METHOD(Vaporizer, wr_checkammo1, bool(entity thiswep, entity actor, .entity weaponentity))
 {
-    float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
+    float vaporizer_ammo = ((autocvar_g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
     float ammo_amount = GetResourceAmount(actor, thiswep.ammo_type) >= vaporizer_ammo;
     ammo_amount += actor.(weaponentity).(weapon_load[WEP_VAPORIZER.m_id]) >= vaporizer_ammo;
     return ammo_amount;
@@ -368,7 +368,7 @@ METHOD(Vaporizer, wr_resetplayer, void(entity thiswep, entity actor))
 }
 METHOD(Vaporizer, wr_reload, void(entity thiswep, entity actor, .entity weaponentity))
 {
-    float vaporizer_ammo = ((g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
+    float vaporizer_ammo = ((autocvar_g_instagib) ? 1 : WEP_CVAR_PRI(vaporizer, ammo));
     float used_ammo;
     if(WEP_CVAR_SEC(vaporizer, ammo))
         used_ammo = min(vaporizer_ammo, WEP_CVAR_SEC(vaporizer, ammo));
index c8b459962eb0102247c4f308459d680e2965cf76..8896b5a442ba42d78c4420ee3c0332dacb2956c6 100644 (file)
@@ -43,7 +43,7 @@ void sys_phys_update(entity this, float dt)
        float maxspeed_mod = (!this.in_swamp) ? 1 : this.swamp_slowdown;  // cvar("g_balance_swamp_moverate");
 
 // conveyors: first fix velocity
-       if (this.conveyor.state) { this.velocity -= this.conveyor.movedir; }
+       if (this.conveyor.active) { this.velocity -= this.conveyor.movedir; }
        MUTATOR_CALLHOOK(PlayerPhysics, this, dt);
 
        if (!IS_PLAYER(this)) {
@@ -156,7 +156,7 @@ void sys_phys_update(entity this, float dt)
        LABEL(end)
        if (IS_ONGROUND(this)) { this.lastground = time; }
 // conveyors: then break velocity again
-       if (this.conveyor.state) { this.velocity += this.conveyor.movedir; }
+       if (this.conveyor.active) { this.velocity += this.conveyor.movedir; }
        this.lastflags = this.flags;
 
        this.lastclassname = this.classname;
index d45dc208e0149d24c195bc5bc71bcf5271bad793..addced2b3f0a5d6aa7932f9cc224ed5843047bfd 100644 (file)
@@ -64,7 +64,7 @@
 #ifndef QCC_SUPPORT_POW
     #define pow(a, b) pow(a, b)
 #else
-    #define pow(a, b) (a ** b)
+    #define pow(a, b) ((a) ** (b))
 #endif
 
 #include "self.qh"
index c1edb5cd3a3600dc60dfd15915509aadd1458513..7b3f581b38f059cd4e4252905ae0dcf243983209 100644 (file)
@@ -107,7 +107,6 @@ STATIC_INIT(C2S_Protocol_renumber) { FOREACH(C2S_Protocol, true, it.m_id = i); }
 #ifdef SVQC
        const int MSG_ENTITY = 5;
 
-       .int Version;  // deprecated, use SendFlags
        .int SendFlags;
 
        IntrusiveList g_uncustomizables;
index 614f7efb1b13c246c1679587d4a6bd405b7e7535..d3198b3ce4c7666bf986564916b9d9678b3dc097 100644 (file)
@@ -163,6 +163,7 @@ noref bool require_spawnfunc_prefix;
                FIELD_SCALAR(fld, bgmscriptsustain) \
                FIELD_SCALAR(fld, bgmscript) \
                FIELD_SCALAR(fld, button0) \
+               FIELD_SCALAR(fld, chmap) \
                FIELD_SCALAR(fld, cnt) \
                FIELD_SCALAR(fld, colormap) \
                FIELD_SCALAR(fld, count) \
@@ -182,10 +183,12 @@ noref bool require_spawnfunc_prefix;
                FIELD_SCALAR(fld, dmg_force) \
                FIELD_SCALAR(fld, dmg_radius) \
                FIELD_SCALAR(fld, effects) \
+               FIELD_SCALAR(fld, falloff) \
                FIELD_SCALAR(fld, flags) \
                FIELD_SCALAR(fld, fog) \
                FIELD_SCALAR(fld, frags) \
                FIELD_SCALAR(fld, frame) \
+               FIELD_SCALAR(fld, gametype) \
                FIELD_SCALAR(fld, gametypefilter) \
                FIELD_SCALAR(fld, geomtype) \
                FIELD_SCALAR(fld, gravity) \
@@ -216,6 +219,7 @@ noref bool require_spawnfunc_prefix;
                FIELD_SCALAR(fld, noalign) \
                FIELD_SCALAR(fld, noise1) \
                FIELD_SCALAR(fld, noise2) \
+               FIELD_SCALAR(fld, noise3) \
                FIELD_SCALAR(fld, noise) \
                FIELD_SCALAR(fld, phase) \
                FIELD_SCALAR(fld, platmovetype) \
@@ -243,6 +247,7 @@ noref bool require_spawnfunc_prefix;
                FIELD_SCALAR(fld, target_random) \
                FIELD_SCALAR(fld, target_range) \
                FIELD_SCALAR(fld, team) \
+               FIELD_SCALAR(fld, trigger_reverse) \
                FIELD_SCALAR(fld, turret_scale_health) \
                FIELD_SCALAR(fld, turret_scale_range) \
                FIELD_SCALAR(fld, turret_scale_respawn) \
@@ -256,6 +261,7 @@ noref bool require_spawnfunc_prefix;
                FIELD_VEC(fld, absmin) \
                FIELD_VEC(fld, angles) \
                FIELD_VEC(fld, avelocity) \
+               FIELD_VEC(fld, beam_color)\
                FIELD_VEC(fld, debrisavelocityjitter) \
                FIELD_VEC(fld, debrisvelocity) \
                FIELD_VEC(fld, debrisvelocityjitter) \
index e9bacafa7d1ffd650045e23cded798ce46cbcce5..c1abd004105df81edf5525d4bb705912e3e1ba56 100644 (file)
@@ -167,7 +167,7 @@ int autocvar_g_maxplayers;
 float autocvar_g_maxplayers_spectator_blocktime;
 float autocvar_g_maxpushtime;
 float autocvar_g_maxspeed;
-bool autocvar_g_instagib;
+#define autocvar_g_instagib cvar("g_instagib")
 #define autocvar_g_mirrordamage cvar("g_mirrordamage")
 #define autocvar_g_mirrordamage_virtual cvar("g_mirrordamage_virtual")
 bool autocvar_g_mirrordamage_onlyweapons;
@@ -240,6 +240,7 @@ float autocvar_g_turrets_targetscan_mindelay;
 bool autocvar_g_use_ammunition;
 bool autocvar_g_waypointeditor;
 bool autocvar_g_waypointeditor_symmetrical;
+bool autocvar_g_waypointeditor_symmetrical_allowload = true;
 vector autocvar_g_waypointeditor_symmetrical_origin;
 int autocvar_g_waypointeditor_symmetrical_order;
 vector autocvar_g_waypointeditor_symmetrical_axis;
index fa82d926b63e92776cfd293dbebccf15ba20ad04..384f1e7ce1c87ddebc1d048a8838d69181f051a6 100644 (file)
@@ -1028,10 +1028,33 @@ void waypoint_saveall()
                return;
        }
 
-       // add 3 comments to not break compatibility with older Xonotic versions
+       float sym = autocvar_g_waypointeditor_symmetrical;
+       string sym_str = ftos(sym);
+       if (sym == -1 || (sym == 1 && autocvar_g_waypointeditor_symmetrical_order >= 2))
+       {
+               if (sym == 1)
+               {
+                       sym_str = cons(sym_str, "-");
+                       sym_str = cons(sym_str, "-");
+               }
+               else
+               {
+                       sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_origin.x));
+                       sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_origin.y));
+               }
+               if (autocvar_g_waypointeditor_symmetrical_order >= 2)
+                       sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_order));
+       }
+       else if (autocvar_g_waypointeditor_symmetrical == -2)
+       {
+               sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_axis.x));
+               sym_str = cons(sym_str, ftos(autocvar_g_waypointeditor_symmetrical_axis.y));
+       }
+
+       // a group of 3 comments doesn't break compatibility with older Xonotic versions
        // (they are read as a waypoint with origin '0 0 0' and flag 0 though)
        fputs(file, strcat("//", "WAYPOINT_VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\n"));
-       fputs(file, strcat("//", "\n"));
+       fputs(file, strcat("//", "WAYPOINT_SYMMETRY ", sym_str, "\n"));
        fputs(file, strcat("//", "\n"));
 
        int c = 0;
@@ -1085,6 +1108,8 @@ float waypoint_loadall()
 
        bool parse_comments = true;
        float ver = 0;
+       float sym = 0;
+       float sym_param1 = 0, sym_param2 = 0, sym_param3 = 0;
 
        while ((s = fgets(file)))
        {
@@ -1094,6 +1119,14 @@ float waypoint_loadall()
                        {
                                if(substring(s, 2, 17) == "WAYPOINT_VERSION ")
                                        ver = stof(substring(s, 19, -1));
+                               else if(substring(s, 2, 18) == "WAYPOINT_SYMMETRY ")
+                               {
+                                       int tokens = tokenizebyseparator(substring(s, 20, -1), " ");
+                                       if (tokens) { sym = stof(argv(0)); }
+                                       if (tokens > 1) { sym_param1 = stof(argv(1)); }
+                                       if (tokens > 2) { sym_param2 = stof(argv(2)); }
+                                       if (tokens > 3) { sym_param3 = stof(argv(3)); }
+                               }
                                continue;
                        }
                        else
@@ -1124,6 +1157,35 @@ float waypoint_loadall()
        fclose(file);
        LOG_TRACE("loaded ", ftos(cwp), " waypoints and ", ftos(cwb), " wayboxes from maps/", mapname, ".waypoints");
 
+       if (autocvar_g_waypointeditor && autocvar_g_waypointeditor_symmetrical_allowload)
+       {
+               cvar_set("g_waypointeditor_symmetrical", ftos(sym));
+               if (sym == 1 && sym_param3 < 2)
+                       cvar_set("g_waypointeditor_symmetrical_order", "0"); // make sure this is reset if not loaded
+               if (sym == -1 || (sym == 1 && sym_param3 >= 2))
+               {
+                       string params;
+                       if (sym == 1)
+                               params = cons("-", "-");
+                       else
+                       {
+                               params = cons(ftos(sym_param1), ftos(sym_param2));
+                               cvar_set("g_waypointeditor_symmetrical_origin", params);
+                       }
+                       cvar_set("g_waypointeditor_symmetrical_order", ftos(sym_param3));
+                       LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with origin ", params, " and order ", ftos(sym_param3));
+               }
+               else if (sym == -2)
+               {
+                       string params = strcat(ftos(sym_param1), " ", ftos(sym_param2));
+                       cvar_set("g_waypointeditor_symmetrical_axis", params);
+                       LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym), " with axis ", params);
+               }
+               else
+                       LOG_INFO("Waypoint editor: loaded symmetry ", ftos(sym));
+               LOG_INFO(strcat("g_waypointeditor_symmetrical", " has been set to ", cvar_string("g_waypointeditor_symmetrical")));
+       }
+
        return cwp + cwb;
 }
 
index bea11e9299986ce180765f09a520e37c8295f6de..595c2d058fcc1cd82fa1a082ffd29096f90adc3b 100644 (file)
@@ -6,7 +6,7 @@
 // increase by 0.01 when changes require only waypoint relinking
 // increase by 1 when changes require to manually edit waypoints
 // max 2 decimal places, always specified
-#define WAYPOINT_VERSION 1.00
+#define WAYPOINT_VERSION 1.01
 
 // fields you can query using prvm_global server to get some statistics about waypoint linking culling
 float relink_total, relink_walkculled, relink_pvsculled, relink_lengthculled;
index 663d16ed712f73d995025f28b98d1eba76c29627..d374876d0456441bc59fdf69fe683a643bb8d42a 100644 (file)
@@ -1496,7 +1496,7 @@ void player_powerups(entity this)
        Fire_ApplyDamage(this);
        Fire_ApplyEffect(this);
 
-       if (!g_instagib)
+       if (!autocvar_g_instagib)
        {
                if (this.items & ITEM_Strength.m_itemid)
                {
index f85d6e2b6f22ae53ff521c4e52668c635f5dd5f4..e005d0ca844eca9c9bcbfd0b15db6dd27ad820d2 100644 (file)
@@ -7,7 +7,7 @@
 
 // Globals
 
-float g_footsteps, g_grappling_hook, g_instagib;
+float g_footsteps, g_grappling_hook;
 float g_warmup_allguns;
 float g_warmup_allow_timeout;
 float warmup_stage;
index b5ab77d419e02db58a9ac07cbc744bf998d84999..b36cfc95ac9c4bcf43318ac35d955dc6bb6e90fe 100644 (file)
@@ -779,7 +779,7 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
                        }
                }
 
-               if(!g_instagib)
+               if(!autocvar_g_instagib)
                {
                        // apply strength multiplier
                        if (attacker.items & ITEM_Strength.m_itemid)
index 5538a574428cb4b8cbc5dbbe01dec2aa0f5264c8..41e725946a96cb43c1cd5febd0a04f76deb79359 100644 (file)
@@ -222,8 +222,6 @@ void readlevelcvars()
        if(cvar("sv_allow_fullbright"))
                serverflags |= SERVERFLAG_ALLOW_FULLBRIGHT;
 
-       g_instagib = cvar("g_instagib");
-
        sv_clones = cvar("sv_clones");
        sv_foginterval = cvar("sv_foginterval");
        g_footsteps = cvar("g_footsteps");
index 1130b6a4e5dd349abdf935a81039e0334c22c443..487ab1fc533821590ab49c18fdeffb7cf24dd686 100644 (file)
@@ -360,7 +360,7 @@ void SV_OnEntityPreSpawnFunction(entity this)
        }
        return;
 LABEL(cleanup)
-    builtin_remove(this);
+    delete(this);
 }
 
 void WarpZone_PostInitialize_Callback()
diff --git a/sound/misc/kill.ogg b/sound/misc/kill.ogg
deleted file mode 100644 (file)
index c1d3b8c..0000000
Binary files a/sound/misc/kill.ogg and /dev/null differ
diff --git a/sound/misc/kill.wav b/sound/misc/kill.wav
new file mode 100644 (file)
index 0000000..139ff57
Binary files /dev/null and b/sound/misc/kill.wav differ
index 29d5c2f6754b51442d06df46def79bf1ad2e04e2..a6ecd64dca1afc17c763e14f4a02d9e70c4f49ff 100644 (file)
@@ -170,6 +170,7 @@ set bot_ai_timeitems_minrespawndelay 25 "bots run to items with this minimum res
 set g_waypointeditor 0
 set g_waypointeditor_auto 0 "Automatically create waypoints for bots while playing; BEWARE, this currently creates too many of them"
 set g_waypointeditor_symmetrical 0 "Enable symmetrical editing of waypoints on symmetrical CTF maps (NOTE: it assumes that the map is perfectly symmetrical). 1: automatically determine origin of symmetry; -1: use custom origin (g_waypointeditor_symmetrical_origin); 2: automatically determine axis of symmetry; -2: use custom axis (g_waypointeditor_symmetrical_axis)"
+set g_waypointeditor_symmetrical_allowload 1 "Allow loading symmetry settings from waypoint files into g_waypointeditor_symmetrical* cvars on map start"
 set g_waypointeditor_symmetrical_origin "0 0" "Custom origin of symmetry (x y)"
 set g_waypointeditor_symmetrical_order 0 "if >= 2 apply rotational symmetry (around origin of symmetry) of this order, otherwise apply autodetected order of symmetry"
 set g_waypointeditor_symmetrical_axis "0 0" "Custom axis of symmetry (m q parameters of y = mx + q)"
@@ -179,7 +180,7 @@ set bot_vs_human 0  "Bots and humans play in different teams when set. positive v
 
 set g_spawnshieldtime 1 "number of seconds you are invincible after you spawned, this shield is lost after you fire"
 set g_spawnshield_blockdamage 1 "how much spawn shield protects you from damage (1 = full protection)"
-set g_antilag 2        "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past, 3 = unverified client side hit scan)"
+set g_antilag 2        "AntiLag (0 = no AntiLag, 1 = verified client side hit scan, 2 = server side hit scan in the past)"
 set g_antilag_nudge 0 "don't touch"
 set g_shootfromeye 0 "shots are fired from your eye/crosshair; visual gun position can still be influenced by cl_gunalign 1 and 2"
 set g_shootfromcenter 0 "weapon gets moved to the center, shots still come from the barrel of your weapon; visual gun position can still be influenced by cl_gunalign 1 and 2"