]> de.git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/commitdiff
Merge branch 'master' into Mario/cursor
authorterencehill <piuntn@gmail.com>
Tue, 7 Aug 2018 12:08:16 +0000 (14:08 +0200)
committerterencehill <piuntn@gmail.com>
Tue, 7 Aug 2018 12:08:16 +0000 (14:08 +0200)
127 files changed:
.gitlab-ci.yml
.tx/merge-base
bal-wep-samual.cfg
bal-wep-xdf.cfg
bal-wep-xonotic.cfg
bal-wep-xpm.cfg
check-translations.sh
commands.cfg
common.de.po
common.de_CH.po
common.fr.po
common.he.po
common.pt_BR.po
effects-high.cfg
effects-low.cfg
effects-med.cfg
effects-normal.cfg
effects-omg.cfg
effects-ultimate.cfg
effects-ultra.cfg
gfx/hud/default/as_defend.tga [new file with mode: 0644]
gfx/hud/default/as_destroy.tga [new file with mode: 0644]
gfx/hud/luma/as_defend.tga [new file with mode: 0644]
gfx/hud/luma/as_destroy.tga [new file with mode: 0644]
gfx/hud/luma/ok_weapon_rail.tga
gfx/hud/luma/ok_weapon_shotgun.tga
gfx/hud/luma/ok_weapon_smg.tga
gfx/hud/luma/weaponhmg.tga
gfx/hud/luma/weaponrpc.tga
languages.txt
models/player/gak.iqm_0.txt
models/player/gakmasked.iqm_0.txt
models/player/ignismasked.iqm_0.txt
models/player/seraphinamasked.iqm_0.txt
notifications.cfg
physicsX07.cfg
qcsrc/client/commands/cl_cmd.qc
qcsrc/client/csqcmodel_hooks.qc
qcsrc/client/hud/hud.qc
qcsrc/client/hud/panel/ammo.qc
qcsrc/client/hud/panel/centerprint.qc
qcsrc/client/hud/panel/modicons.qc
qcsrc/client/hud/panel/powerups.qc
qcsrc/client/hud/panel/quickmenu.qc
qcsrc/client/hud/panel/radar.qc
qcsrc/client/hud/panel/scoreboard.qc
qcsrc/client/hud/panel/weapons.qc
qcsrc/client/main.qc
qcsrc/client/mapvoting.qc
qcsrc/client/miscfunctions.qc
qcsrc/client/player_skeleton.qc
qcsrc/client/teamradar.qc
qcsrc/client/view.qc
qcsrc/client/weapons/projectile.qc
qcsrc/common/campaign_file.qc
qcsrc/common/command/command.qh
qcsrc/common/command/generic.qc
qcsrc/common/effects/all.inc
qcsrc/common/gamemodes/gamemode/assault/assault.qc
qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qc
qcsrc/common/gamemodes/gamemode/ctf/ctf.qc
qcsrc/common/gamemodes/gamemode/domination/domination.qc
qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qc
qcsrc/common/gamemodes/gamemode/invasion/invasion.qc
qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qc
qcsrc/common/gamemodes/gamemode/nexball/nexball.qc
qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc
qcsrc/common/gamemodes/gamemode/race/race.qc
qcsrc/common/gamemodes/gamemode/tdm/tdm.qc
qcsrc/common/gamemodes/sv_rules.qh
qcsrc/common/items/item.qh
qcsrc/common/mutators/mutator/overkill/okrpc.qc
qcsrc/common/mutators/mutator/sandbox/sv_sandbox.qc
qcsrc/common/mutators/mutator/vampirehook/sv_vampirehook.qc
qcsrc/common/mutators/mutator/waypoints/all.inc
qcsrc/common/notifications/all.inc
qcsrc/common/sounds/sound.qh
qcsrc/common/state.qc
qcsrc/common/t_items.qc
qcsrc/common/teams.qh
qcsrc/common/turrets/sv_turrets.qc
qcsrc/common/vehicles/cl_vehicles.qc
qcsrc/common/vehicles/sv_vehicles.qc
qcsrc/common/weapons/weapon/arc.qc
qcsrc/common/weapons/weapon/hagar.qc
qcsrc/common/weapons/weapon/shotgun.qc
qcsrc/lib/i18n.qh
qcsrc/lib/oo.qh
qcsrc/menu/item/listbox.qc
qcsrc/menu/xonotic/campaign.qc
qcsrc/menu/xonotic/demolist.qc
qcsrc/menu/xonotic/dialog_settings_game_messages.qc
qcsrc/menu/xonotic/gametypelist.qc
qcsrc/menu/xonotic/hudskinlist.qc
qcsrc/menu/xonotic/maplist.qc
qcsrc/menu/xonotic/playerlist.qc
qcsrc/menu/xonotic/playlist.qc
qcsrc/menu/xonotic/screenshotlist.qc
qcsrc/menu/xonotic/skinlist.qc
qcsrc/menu/xonotic/soundlist.qc
qcsrc/menu/xonotic/statslist.qc
qcsrc/server/bot/default/bot.qc
qcsrc/server/bot/default/havocbot/havocbot.qc
qcsrc/server/bot/default/waypoints.qc
qcsrc/server/bot/default/waypoints.qh
qcsrc/server/client.qc
qcsrc/server/command/cmd.qc
qcsrc/server/command/common.qc
qcsrc/server/command/sv_cmd.qc
qcsrc/server/command/vote.qc
qcsrc/server/compat/quake.qc
qcsrc/server/defs.qh
qcsrc/server/g_damage.qc
qcsrc/server/g_hook.qc
qcsrc/server/g_world.qc
qcsrc/server/g_world.qh
qcsrc/server/mutators/events.qh
qcsrc/server/player.qc
qcsrc/server/player.qh
qcsrc/server/scores_rules.qc
qcsrc/server/teamplay.qc
qcsrc/server/teamplay.qh
qcsrc/server/weapons/selection.qc
qcsrc/server/weapons/tracing.qc
qcsrc/server/weapons/weaponsystem.qc
xonotic-client.cfg
xonotic-server.cfg

index 844e70c6ad615aa1b1d32b9cdcedf27b6b4cf924..5cac3f8c08dc965f771822bd809b4b3bc23354fb 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=242ab47092837a05ba09f041b32bddb1
+    - EXPECT=7b0c010fc46bd46c70223fdf25f91c9c
     - HASH=$(${ENGINE} -noconfig -nohome +exec serverbench.cfg
       | tee /dev/stderr
       | grep '^:'
index ca7140deb4f39043ced90c760624d498c0f1b2a1..d15698b68730a588bc9947b1ab0d36958f1fe1c1 100644 (file)
@@ -1 +1 @@
-Wed Jun 20 07:24:25 CEST 2018
+Mon Jul 23 07:24:17 CEST 2018
index 380d93ed47acc76f5aae18c560b77962a49ad531..1816f3f2e921ce4de93ceabcc2bad978861fcdd4 100644 (file)
@@ -322,7 +322,7 @@ set g_balance_crylink_primary_spread 0.08
 set g_balance_crylink_reload_ammo 0
 set g_balance_crylink_reload_time 2
 set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_ammo 2
+set g_balance_crylink_secondary_ammo 3
 set g_balance_crylink_secondary_animtime 0.2
 set g_balance_crylink_secondary_bouncedamagefactor 0.5
 set g_balance_crylink_secondary_bounces 0
index fa40bbf7fb57bb7bc7e670cd078d9e5fa580b030..2e0e74aa3d7a993b7a97f1ac1b43f9ead3bbc797 100644 (file)
@@ -256,7 +256,7 @@ set g_balance_crylink_primary_spread 0.08
 set g_balance_crylink_reload_ammo 0
 set g_balance_crylink_reload_time 2
 set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_ammo 2
+set g_balance_crylink_secondary_ammo 3
 set g_balance_crylink_secondary_animtime 0.2
 set g_balance_crylink_secondary_bouncedamagefactor 0
 set g_balance_crylink_secondary_bounces 0
index e55e860773424fdad08857e6b3c121c3b686c407..5c6ace7abd7c6649f82b9998570e562154431a8e 100644 (file)
@@ -256,7 +256,7 @@ set g_balance_crylink_primary_spread 0.08
 set g_balance_crylink_reload_ammo 0
 set g_balance_crylink_reload_time 2
 set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_ammo 2
+set g_balance_crylink_secondary_ammo 3
 set g_balance_crylink_secondary_animtime 0.2
 set g_balance_crylink_secondary_bouncedamagefactor 0.5
 set g_balance_crylink_secondary_bounces 0
@@ -883,7 +883,7 @@ set g_balance_okmachinegun_primary_ammo 1
 set g_balance_okmachinegun_primary_damage 25
 set g_balance_okmachinegun_primary_force 5
 set g_balance_okmachinegun_primary_refire 0.1
-set g_balance_okmachinegun_primary_solidpenetration 13.1
+set g_balance_okmachinegun_primary_solidpenetration 63
 set g_balance_okmachinegun_primary_spread_add 0.012
 set g_balance_okmachinegun_primary_spread_max 0.05
 set g_balance_okmachinegun_primary_spread_min 0
index b16e787f5e5a95c029e1c679405b6b7d37d00a08..a5438d1b7c65a39ebe33f27da62dfb47e3c5e359 100644 (file)
@@ -256,7 +256,7 @@ set g_balance_crylink_primary_spread 0.08
 set g_balance_crylink_reload_ammo 0
 set g_balance_crylink_reload_time 2
 set g_balance_crylink_secondary 1
-set g_balance_crylink_secondary_ammo 2
+set g_balance_crylink_secondary_ammo 3
 set g_balance_crylink_secondary_animtime 0.2
 set g_balance_crylink_secondary_bouncedamagefactor 0.5
 set g_balance_crylink_secondary_bounces 0
index 5e2ad5a54a1e099e1c33e88261fe1bf45857db8d..6a55b5ef732f3dff77418a4c06ead7660a8b2a6b 100755 (executable)
@@ -101,11 +101,11 @@ if [ x"$mode" = x"txt" ]; then
                                if [ "$p" -lt 50 ]; then
                                        continue
                                fi
-                               item="$l $l \"$l\" 0%"
+                               item="$l \"$l\" \"$l\" 0%"
                        fi
                        printf "%s\n" "$item" | sed -e "s/[0-9][0-9]*%/$p%/"
                done
-       } | tr '"' '\t' | sort -k3 | tr '\t' '"'
+       } | LC_ALL=C sort -t '"' -k4,4
 fi
 
 if [ x"$mode" = x"po" ]; then
index b2edf84788332b7da31d681a318c19d6fd2e807d..3e5e78e0ef5d5581404ff021824f3bb741013776 100644 (file)
@@ -40,6 +40,7 @@ if_client    "alias" help "cl_cmd help; cmd help"
 // networked/server common commands
 alias cvar_changes         "qc_cmd_svcmd  cvar_changes         ${* ?}" // Prints a list of all changed server cvars
 alias cvar_purechanges     "qc_cmd_svcmd  cvar_purechanges     ${* ?}" // Prints a list of all changed gameplay cvars
+alias editmob              "qc_cmd_svcmd  editmob              ${* ?}" // Modifies a monster or all monsters
 alias info                 "qc_cmd_svcmd  info                 ${* ?}" // Request for unique server information set up by admin
 alias ladder               "qc_cmd_svcmd  ladder               ${* ?}" // Get information about top players if supported
 alias lsmaps               "qc_cmd_svcmd  lsmaps               ${* ?}" // List maps which can be used with the current game mode
@@ -55,16 +56,26 @@ alias who                  "qc_cmd_svcmd  who                  ${* ?}" // Displa
 
 // generic commands (across all programs)
 alias addtolist            "qc_cmd_svmenu addtolist            ${* ?}" // Add a string to a cvar
+alias bufstr_get           "qc_cmd_svmenu bufstr_get           ${* ?}" // Examine a string buffer object
+alias cvar_localchanges    "qc_cmd_svmenu cvar_localchanges    ${* ?}" // Print locally changed cvars
 alias dumpcommands         "qc_cmd_svmenu dumpcommands         ${* ?}" // Dump all commands on the program to *_cmd_dump.txt
-alias dumpnotifs           "qc_cmd_svcl   dumpnotifs           ${* ?}" // Dump all notifications into notifications_dump.txt
+alias dumpnotifs           "qc_cmd_svmenu dumpnotifs           ${* ?}" // Dump all notifications into notifications_dump.txt
+alias dumpitems            "qc_cmd_svmenu dumpitems            ${* ?}" // Dump all items to the console
+alias dumpturrets          "qc_cmd_svmenu dumpturrets          ${* ?}" // Dump all turrets into turrets_dump.txt
+alias dumpweapons          "qc_cmd_svmenu dumpweapons          ${* ?}" // Dump all weapons into weapons_dump.txt
+alias find                 "qc_cmd_svmenu find                 ${* ?}" // Search through entities for matching classname
+alias findat               "qc_cmd_svmenu findat               ${* ?}" // Search through entities for matching origin
 alias maplist              "qc_cmd_svmenu maplist              ${* ?}" // Automatic control of maplist
+alias mx                   "qc_cmd_svmenu mx                   ${* ?}" // Send a matrix command
 alias nextframe            "qc_cmd_svmenu nextframe            ${* ?}" // Execute the given command next frame of this VM
 alias qc_curl              "qc_cmd_svmenu qc_curl              ${* ?}" // Queries a URL
 alias removefromlist       "qc_cmd_svmenu removefromlist       ${* ?}" // Remove a string from a cvar
-alias restartnotifs        "qc_cmd_svcl   restartnotifs        ${* ?}" // Re-initialize all notifications
+alias restartnotifs        "qc_cmd_svmenu restartnotifs        ${* ?}" // Re-initialize all notifications
 alias rpn                  "qc_cmd_svmenu rpn                  ${* ?}" // RPN calculator
+alias runtest              "qc_cmd_svmenu runtest              ${* ?}" // Run unit tests
 //alias settemp            "qc_cmd_svmenu settemp              ${* ?}" // Temporarily set a value to a cvar which is restored later
 //alias settemp_restore    "qc_cmd_svmenu settemp_restore      ${* ?}" // Restore all cvars set by settemp command
+alias version              "qc_cmd_svmenu version              ${* ?}" // Print the current version
 
 // other aliases for common commands
 alias g_hitplots_add "qc_cmd_svmenu rpn /g_hitplots_individuals g_hitplots_individuals ${1 !} union def"
@@ -116,6 +127,7 @@ alias menu_loadmap_prepare "disconnect; wait; g_campaign 0; menu_cmd rpn /_menu_
 // ==========================================================
 // commented out commands are really only intended for internal use
 alias blurtest             "qc_cmd_cl     blurtest             ${* ?}" // Feature for testing blur postprocessing
+alias boxparticles         "qc_cmd_cl     boxparticles         ${* ?}" // Spawn particles manually
 alias create_scrshot_ent   "qc_cmd_cl     create_scrshot_ent   ${* ?}" // Create an entity at this location for automatic screenshots
 alias debugmodel           "qc_cmd_cl     debugmodel           ${* ?}" // Spawn a debug model manually
 //alias handlevote         "qc_cmd_cl     handlevote           ${* ?}" // System to handle selecting a vote or option
@@ -123,6 +135,8 @@ alias hud                  "qc_cmd_cl     hud                  ${* ?}" // Comman
 alias localprint           "qc_cmd_cl     localprint           ${* ?}" // Create your own centerprint sent to yourself
 //alias mv_download        "qc_cmd_cl     mv_download          ${* ?}" // Retrieve mapshot picture from the server
 alias sendcvar             "qc_cmd_cl     sendcvar             ${* ?}" // Send a cvar to the server (like weaponpriority)
+alias weapon_find          "qc_cmd_cl     weapon_find          ${* ?}" // Show spawn locations of a weapon
+
 alias exit                 "quit"
 
 // other aliases for local commands
@@ -147,17 +161,16 @@ seta cl_autoswitch 1 "automatically switch to newly picked up weapons if they ar
 // commented out commands are really only intended for internal use, or already have declaration in the engine
 alias autoswitch           "qc_cmd_cmd    autoswitch           ${* ?}" // Whether or not to switch automatically when getting a better weapon
 alias clientversion        "qc_cmd_cmd    clientversion        ${* ?}" // Release version of the game
-//alias mv_getpicture      "qc_cmd_cmd    mv_getpicture        ${* ?}" // Retrieve mapshot picture from the server
 alias join                 "qc_cmd_cmd    join                 ${* ?}" // Become a player in the game
+alias minigame             "qc_cmd_cmd    minigame             ${* ?}" // Start a minigame
+//alias mv_getpicture      "qc_cmd_cmd    mv_getpicture        ${* ?}" // Retrieve mapshot picture from the server
+alias physics              "qc_cmd_cmd    physics              ${* ?}" // Change physics set
 alias ready                "qc_cmd_cmd    ready                ${* ?}" // Qualify as ready to end warmup stage (or restart server if allowed)
-alias reportcvar           "qc_cmd_cmd    reportcvar           ${* ?}" // Old system for sending a client cvar to the server
 //alias say                "qc_cmd_cmd    say                  ${* ?}" // Print a message to chat to all players
 //alias say_team           "qc_cmd_cmd    say_team             ${* ?}" // Print a message to chat to all team mates
 alias selectteam           "qc_cmd_cmd    selectteam           ${* ?}" // Attempt to choose a team to join into
 alias selfstuff            "qc_cmd_cmd    selfstuff            ${* ?}" // Stuffcmd a command to your own client
 alias sentcvar             "qc_cmd_cmd    sentcvar             ${* ?}" // New system for sending a client cvar to the server
-alias editmob              "qc_cmd_cmd    editmob              ${* ?}" // Edit a monster's properties
-alias physics              "qc_cmd_cmd    physics              ${* ?}" // Change physics set
 alias spectate             "qc_cmd_cmd    spectate             ${* ?}" // Become an observer
 alias suggestmap           "qc_cmd_cmd    suggestmap           ${* ?}" // Suggest a map to the mapvote at match end
 //alias tell               "qc_cmd_cmd    tell                 ${* ?}" // Send a message directly to a player
@@ -194,6 +207,7 @@ alias mobbutcher "editmob butcher ${* ?}"
 alias adminmsg             "qc_cmd_sv     adminmsg             ${* ?}" // Send an admin message to a client directly
 alias allready             "qc_cmd_sv     allready             ${* ?}" // Restart the server and reset the players
 alias allspec              "qc_cmd_sv     allspec              ${* ?}" // Force all players to spectate
+alias animbench            "qc_cmd_sv     animbench            ${* ?}" // Benchmark model animation (LAGS)
 alias anticheat            "qc_cmd_sv     anticheat            ${* ?}" // Create an anticheat report for a client
 alias bbox                 "qc_cmd_sv     bbox                 ${* ?}" // Print detailed information about world size
 alias bot_cmd              "qc_cmd_sv     bot_cmd              ${* ?}" // Control and send commands to bots
@@ -204,7 +218,6 @@ alias defer_clear_all      "qc_cmd_sv     defer_clear_all      ${* ?}" // Clear
 alias delrec               "qc_cmd_sv     delrec               ${* ?}" // Delete race time record for a map
 alias effectindexdump      "qc_cmd_sv     effectindexdump      ${* ?}" // Dump list of effects from code and effectinfo.txt
 alias extendmatchtime      "qc_cmd_sv     extendmatchtime      ${* ?}" // Increase the timelimit value incrementally
-alias find                 "qc_cmd_sv     find                 ${* ?}" // Search through entities for matching classname
 alias gametype             "qc_cmd_sv     gametype             ${* ?}" // Simple command to change the active gametype
 alias gettaginfo           "qc_cmd_sv     gettaginfo           ${* ?}" // Get specific information about a weapon model
 alias gotomap              "qc_cmd_sv     gotomap              ${* ?}" // Simple command to switch to another map
index f248daf3c81d93d5dc60c1ff11f49083d0c378a0..2423e3782526671792bb23d8d4049a07e7971f1f 100644 (file)
@@ -3,7 +3,7 @@
 # This file is distributed under the same license as the PACKAGE package.
 #
 # Translators:
-# Wuzzy <almikes@aol.com>, 2016-2017
+# Wuzzy <almikes@aol.com>, 2016-2018
 # Brot Brot <noah.schluessel@gmail.com>, 2015
 # cvcxc <hans.andersen72@yahoo.com>, 2013
 # divVerent <divVerent@xonotic.org>, 2011,2013
@@ -24,7 +24,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-09-23 19:12+0000\n"
+"PO-Revision-Date: 2018-07-13 16:04+0000\n"
 "Last-Translator: Wuzzy <almikes@aol.com>\n"
 "Language-Team: German (http://www.transifex.com/team-xonotic/xonotic/"
 "language/de/)\n"
@@ -48,7 +48,7 @@ msgstr "^1Konnte nicht nach %s schreiben\n"
 
 #: qcsrc/client/hud/panel/chat.qc:82
 msgid "^3Player^7: This is the chat area."
-msgstr "^3Player^7: Dies ist der Chat-Bereich."
+msgstr "^3Spieler^7: Dies ist der Chat-Bereich."
 
 #: qcsrc/client/hud/panel/engineinfo.qc:69
 #, c-format
@@ -210,7 +210,7 @@ msgstr "^3Doppelklicke ^7ein Panel für Panel-spezifische Optionen."
 
 #: qcsrc/client/hud/panel/infomessages.qc:227
 msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"
-msgstr "^3STRG^7, um Kollisionstests zu deaktivieren, ^3SHIFT ^7und"
+msgstr "^3CTRL^7, um Kollisionstests zu deaktivieren, ^3SHIFT ^7und"
 
 #: qcsrc/client/hud/panel/infomessages.qc:228
 msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."
@@ -222,7 +222,7 @@ msgstr "Persönliche Bestzeit"
 
 #: qcsrc/client/hud/panel/modicons.qc:576
 msgid "Server best"
-msgstr "Server Bestzeit"
+msgstr "Server-Bestzeit"
 
 #: qcsrc/client/hud/panel/notify.qc:115 qcsrc/client/hud/panel/notify.qc:116
 #: qcsrc/client/hud/panel/score.qc:59
@@ -285,7 +285,7 @@ msgstr "freier Gegenstand %x^7 (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:804
 msgid "QMCMD^free item, icon"
-msgstr "freier Gegenstand, icon"
+msgstr "freier Gegenstand, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:805
 msgid "QMCMD^took item (l:%l^7)"
@@ -293,7 +293,7 @@ msgstr "Gegenstand genommen (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:805
 msgid "QMCMD^took item, icon"
-msgstr "Gegenstand genommen, icon"
+msgstr "Gegenstand genommen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:806
 msgid "QMCMD^negative"
@@ -309,7 +309,7 @@ msgstr "brauche Hilfe (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:808
 msgid "QMCMD^need help, icon"
-msgstr "brauche Hilfe, icon"
+msgstr "brauche Hilfe, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:809
 msgid "QMCMD^enemy seen (l:%y^7)"
@@ -317,7 +317,7 @@ msgstr "Gegner gesehen (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:809
 msgid "QMCMD^enemy seen, icon"
-msgstr "Gegner gesehen, icon"
+msgstr "Gegner gesehen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:810
 msgid "QMCMD^flag seen (l:%y^7)"
@@ -325,7 +325,7 @@ msgstr "Flagge gesehen (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:810
 msgid "QMCMD^flag seen, icon"
-msgstr "Flagge gesehen, icon"
+msgstr "Flagge gesehen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:811
 msgid "QMCMD^defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
@@ -333,7 +333,7 @@ msgstr "verteidigen (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:811
 msgid "QMCMD^defending, icon"
-msgstr "verteidigen, icon"
+msgstr "verteidigen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:812
 msgid "QMCMD^roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
@@ -341,7 +341,7 @@ msgstr "wandernd (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:812
 msgid "QMCMD^roaming, icon"
-msgstr "wandernd, icon"
+msgstr "wandernd, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:813
 msgid "QMCMD^attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
@@ -349,7 +349,7 @@ msgstr "angreifen (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:813
 msgid "QMCMD^attacking, icon"
-msgstr "angreifen, Iion"
+msgstr "angreifen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:814
 msgid "QMCMD^killed flagcarrier (l:%y^7)"
@@ -357,7 +357,7 @@ msgstr "Flaggenträger getötet (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:814
 msgid "QMCMD^killed flagcarrier, icon"
-msgstr "Flaggenträger getötet, icon"
+msgstr "Flaggenträger getötet, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:815
 #, c-format
@@ -366,11 +366,11 @@ msgstr "Flagge fallen gelassen (l:%d^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:815
 msgid "QMCMD^dropped flag, icon"
-msgstr "Flagge fallen gelassen, icon"
+msgstr "Flagge fallen gelassen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:816
 msgid "QMCMD^drop weapon, icon"
-msgstr "Waffe wegwerfen, icon"
+msgstr "Waffe wegwerfen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:816
 msgid "QMCMD^dropped weapon %w^7 (l:%l^7)"
@@ -378,7 +378,7 @@ msgstr "Waffe fallen gelassen %w^7 (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:817
 msgid "QMCMD^drop flag/key, icon"
-msgstr "Flagge/Schlüssel fallen gelassen, icon"
+msgstr "Flagge/Schlüssel fallen gelassen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:817
 msgid "QMCMD^dropped flag/key %w^7 (l:%l^7)"
@@ -694,7 +694,7 @@ msgstr "ticks"
 msgid ""
 "You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"
 msgstr ""
-"Du kannst die Tabelle mit dem ^2scoreboard_columns_set-Befehl ändern.\n"
+"Du kannst die Punktetafel mit dem ^2scoreboard_columns_set-Befehl ändern.\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:296
 msgid "^3|---------------------------------------------------------------|\n"
@@ -792,7 +792,7 @@ msgstr "^3capzeit^7                  Zeit des schnellsten Captures (CTF)\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:319
 msgid "^3fckills^7                  Number of flag carrier kills\n"
-msgstr "^3fckills^7                  Anzahl der getöteten Flaggen-Träger\n"
+msgstr "^3fckills^7                  Anzahl der getöteten Flaggenträger\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:320
 msgid "^3returns^7                  Number of flag returns\n"
@@ -950,7 +950,7 @@ msgstr "Platzierungen"
 #: qcsrc/client/hud/panel/scoreboard.qc:1519
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:43
 msgid "Scoreboard"
-msgstr "Tabelle"
+msgstr "Punktetafel"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1584
 #, c-format
@@ -1022,7 +1022,7 @@ msgstr "Du bist tot, warte ^3%s^7 bis zum Respawn"
 #: qcsrc/client/hud/panel/scoreboard.qc:1707
 #, c-format
 msgid "You are dead, press ^2%s^7 to respawn"
-msgstr "Du bist tot, drücke ^2%s^7 um neu zu spawnen"
+msgstr "Du bist tot, drücke ^2%s^7, um neu zu spawnen"
 
 #: qcsrc/client/hud/panel/vote.qc:24
 msgid "^1You must answer before entering hud configure mode\n"
@@ -1070,11 +1070,11 @@ msgstr "Keine Munition mehr"
 
 #: qcsrc/client/hud/panel/weapons.qc:534
 msgid "Don't have"
-msgstr "Nicht vorhanden"
+msgstr "Hast du nicht"
 
 #: qcsrc/client/hud/panel/weapons.qc:538
 msgid "Unavailable"
-msgstr "Nicht verfügbar"
+msgstr "Fehlend"
 
 #: qcsrc/client/main.qc:1014
 msgid " qu/s"
@@ -1384,11 +1384,11 @@ msgstr "Vielleicht klappt es beim nächsten Mal!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1172
 msgid "Tubular! Press \"Next Level\" to continue!"
-msgstr "Großartig! Drücke „Nächter Level“ zum Fortfahren!"
+msgstr "Großartig! Drücke „Nächstes Level“ zum Fortfahren!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1174
 msgid "Wicked! Press \"Next Level\" to continue!"
-msgstr "Wahnsinn! Klicke \"Nächstes Level\" um weiter zu spielen!"
+msgstr "Wahnsinn! Drücke „Nächstes Level“ zum Fortfahren!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1177
 msgid "Press the space bar to change your currently selected tile"
@@ -1419,7 +1419,7 @@ msgstr "Speichern"
 #: qcsrc/common/minigames/minigame/pp.qc:438
 #: qcsrc/common/minigames/minigame/ttt.qc:319
 msgid "Draw"
-msgstr "Zeichnen"
+msgstr "Unentschieden"
 
 #: qcsrc/common/minigames/minigame/c4.qc:378
 #: qcsrc/common/minigames/minigame/nmm.qc:601
@@ -1521,7 +1521,7 @@ msgstr "Nächstes Spiel"
 #: qcsrc/common/minigames/minigame/ps.qc:478
 #, c-format
 msgid "Pieces left: %s"
-msgstr "Verbleibende Spielfiguren: %s"
+msgstr "Figuren: %s"
 
 #: qcsrc/common/minigames/minigame/ps.qc:488
 msgid "No more valid moves"
@@ -2626,7 +2626,7 @@ msgstr "^BGDu hast ^F1%s^BG%s fallengelassen"
 #: qcsrc/common/notifications/all.inc:698
 #, c-format
 msgid "^BGYou got the ^F1%s"
-msgstr "^BG^F1%s^K1 erhalten"
+msgstr "^F1%s^BG erhalten"
 
 #: qcsrc/common/notifications/all.inc:385
 #: qcsrc/common/notifications/all.inc:699
@@ -2734,12 +2734,12 @@ msgstr "^BGTeam ^TC^TT^BG hielt den Ball zu lange fest"
 #: qcsrc/common/notifications/all.inc:412
 #, c-format
 msgid "^BG%s^BG captured %s^BG control point"
-msgstr "^BG%s^BG hat den Kontrollpunkt von %s^BG erobert"
+msgstr "^BG%s^BG hat einen Kontrollpunkt erobert: %s^BG"
 
 #: qcsrc/common/notifications/all.inc:413
 #, c-format
 msgid "^TC^TT^BG team %s^BG control point has been destroyed by %s"
-msgstr "^TC^TT^BGDer Kontrollpunkt vom Team %s^BG wurde von %s zerstört"
+msgstr "^TC^TT^BGEin Kontrollpunkt vom Team %s^BG wurde von %s zerstört"
 
 #: qcsrc/common/notifications/all.inc:414
 msgid "^TC^TT^BG generator has been destroyed"
@@ -2759,7 +2759,7 @@ msgstr "^BG%s^K1 hat Unsichtbarkeit aufgesammelt"
 #: qcsrc/common/notifications/all.inc:418
 #, c-format
 msgid "^BG%s^K1 picked up Shield"
-msgstr "^BG%s^K1 hat das Schild aufgenommen"
+msgstr "^BG%s^K1 hat den Schild aufgenommen"
 
 #: qcsrc/common/notifications/all.inc:419
 #, c-format
@@ -3596,7 +3596,7 @@ msgstr "^K1Deine Medizin-Granate ist ein wenig defekt"
 
 #: qcsrc/common/notifications/all.inc:644
 msgid "^K1You are respawning for running out of ammo..."
-msgstr "^K1Du wirst wiederbelebt weil du keine Munition mehr hast …"
+msgstr "^K1Du wirst wiederbelebt, weil du keine Munition mehr hast …"
 
 #: qcsrc/common/notifications/all.inc:644
 msgid "^K1You were killed for running out of ammo..."
@@ -3913,12 +3913,12 @@ msgstr "^F2Aktive Waffe: ^F1%s"
 #: qcsrc/common/notifications/all.inc:733
 #, c-format
 msgid "^BGYou captured %s^BG control point"
-msgstr "^BGDu hast den Kontrollpunkt von %s^BG erobert"
+msgstr "^BGDu hast einen Kontrollpunkt erobert: %s^BG"
 
 #: qcsrc/common/notifications/all.inc:734
 #, c-format
 msgid "^TC^TT^BG team captured %s^BG control point"
-msgstr "Team ^TC^TT^BG hat %ss^BG Kontrollpunkt erobert"
+msgstr "Team ^TC^TT^BG hat einen Kontrollpunkt erobert: %s^BG"
 
 #: qcsrc/common/notifications/all.inc:735
 msgid "^BGThis control point currently cannot be captured"
@@ -4019,7 +4019,7 @@ msgstr "^F2Ein Schild umgibt dich"
 
 #: qcsrc/common/notifications/all.inc:754
 msgid "^F2Shield has worn off"
-msgstr "^F2Das Schild ist wieder verschwunden"
+msgstr "^F2Der Schild ist wieder verschwunden"
 
 #: qcsrc/common/notifications/all.inc:756
 msgid "^F2You are on speed"
@@ -5257,7 +5257,7 @@ msgstr "Schriftgröße:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qh:6
 msgid "Centerprint Panel"
-msgstr "Nachrichten-Panel"
+msgstr "Zentralanzeigen-Panel"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:15
 msgid "Chat entries:"
@@ -5355,7 +5355,7 @@ msgstr "Beim Zuschauen zeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:18
 msgid "PNL^Enabled even playing in warmup"
-msgstr "Auch in der Aufwärmphase zeigen"
+msgstr "Auch in Aufwärmphase zeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:29
 msgid "Reduced"
@@ -5363,7 +5363,7 @@ msgstr "Reduziert"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:32
 msgid "Text/icon ratio:"
-msgstr "Text/Icon-Verhältnis:"
+msgstr "Text-/Icon-Verhältnis:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:35
 msgid "Hide spawned items"
@@ -5407,7 +5407,7 @@ msgstr "Eintrags-Ausblendung:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_notification.qh:6
 msgid "Notification Panel"
-msgstr "Anzeige-Panel"
+msgstr "Nachrichten-Panel"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:15
 #: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:14
@@ -5421,11 +5421,11 @@ msgstr "Panel anzeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:17
 msgid "Panel enabled even observing"
-msgstr "Panel auch beim Zuschauen anzeigen"
+msgstr "Auch beim Zuschauen zeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:18
 msgid "Panel enabled only in Race/CTS"
-msgstr "Panel nur in Rennen und CTS-Rennen anzeigen"
+msgstr "Nur in Rennen und CTS-Rennen zeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:24
 msgid "Status bar"
@@ -5536,7 +5536,7 @@ msgstr "Rundenzeit-Panel"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:16
 msgid "Panel enabled in teamgames"
-msgstr "Panel in Team-Spieltypen aktivieren"
+msgstr "Panel in Teamspielen aktivieren"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:23
 msgid "Radar:"
@@ -6317,13 +6317,11 @@ msgstr "Spielmechanik-Mutatoren:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:160
 msgid "Enable dodging"
-msgstr ""
-"Ausweichmodus: Es ist möglich rasch zur Seite zu springen (spezielle "
-"Bewegung)"
+msgstr "Ausweichmanöver aktivieren"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:167
 msgid "All players are almost invisible"
-msgstr "Tarnmodus: Alle Spieler sind fast unsichtbar"
+msgstr "Alle Spieler sind fast unsichtbar"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:174
 msgid "Only possible to inflict damage on your enemy while he's airborne"
@@ -6333,15 +6331,15 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:178
 msgid "Damage done to your enemy gets added to your own health"
 msgstr ""
-"Vampirmodus: Der Schaden, dem du anderen Spielern zufügst, wird deiner "
-"eigenen Lebensenergie hinzugefügt"
+"Der Schaden, dem du anderen Spielern zufügst, wird deiner eigenen "
+"Lebensenergie hinzugefügt"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:183
 msgid ""
 "Amount of health below which your player gets stunned because of blood loss"
 msgstr ""
-"Blutverlust: Aktiviere diesen Modus und stelle den Wert der Lebensenergie, "
-"bei der Spieler auf Grund von Blutverlust betäubt wirken, ein"
+"Aktiviere diesen Modus und stelle den Wert der Lebensenergie, bei der "
+"Spieler auf Grund von Blutverlust betäubt wirken, ein"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:192
 msgid "Make things fall to the ground slower, lower value means lower gravity"
@@ -6390,10 +6388,9 @@ msgid ""
 "Selecting a weapon arena will give all players that weapon at spawn as well "
 "as unlimited ammo, and disable all other weapon pickups."
 msgstr ""
-"Waffen-Arenen: Die Auswahl einer Waffen-Arena führt dazu, dass jeder Spieler "
-"mit der gewählten Waffe startet. Diese hat unendlich viel Munition, andere "
-"Waffen sind nicht vorhanden – Spezielle Waffen-Arenen: Spieler starten mit "
-"allen Waffen und unendlich viel Munition"
+"Die Auswahl einer Waffen-Arena führt dazu, dass jeder Spieler mit der "
+"gewählten Waffe startet. Diese hat unendlich viel Munition, andere Waffen "
+"sind nicht vorhanden."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:255
 msgid "Most weapons"
@@ -6617,7 +6614,7 @@ msgstr "Musikplayer"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:48
 msgid "Auto record demos"
-msgstr "Wiederholungen automatisch aufzeichnen"
+msgstr "Wiederholungen autom. aufzeichnen"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:57
 msgid "Timedemo"
@@ -6708,7 +6705,7 @@ msgstr "Alle entfernen"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:43
 msgid "Auto screenshot scoreboard"
-msgstr "Screenshot der Tabelle automatisch anfertigen"
+msgstr "Auto-Screenshot der Punktetafel"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:63
 msgid "Open in the viewer"
@@ -7419,7 +7416,7 @@ msgstr "Scharf"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:163
 msgid "Decals"
-msgstr "Einschusslöcher"
+msgstr "Dekore"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:164
 msgid "Enable decals (bullet holes and blood) (default: enabled)"
@@ -7717,7 +7714,7 @@ msgstr "Dezimalstellen im Respawn-Countdown anzeigen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:57
 msgid "Show accuracy underneath scoreboard"
-msgstr "Trefferquote unter Tabelle anzeigen"
+msgstr "Trefferquote unter Punktetafel anzeigen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:61
 msgid "Waypoints"
@@ -7824,7 +7821,7 @@ msgstr "Um den HUD-Editor zu starten, muss ein Spiel gestartet werden."
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:23
 msgid "Do you wish to start a local game to set up the HUD?"
-msgstr "Willst du ein lokales Spiel starten, um das HUD zu editieren?"
+msgstr "Willst du ein lokales Spiel starten, um das HUD zu bearbeiten?"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:24
 msgid "Frag Information"
@@ -7840,7 +7837,7 @@ msgstr "Amokläufe nur anzeigen, wenn sie Achievements sind"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:34
 msgid "Show spree information in centerprints"
-msgstr "Amoklauf-Informationen in Centerprints anzeigen"
+msgstr "Amoklauf-Infos in Zentralanzeige zeigen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:38
 msgid "Show spree information in death messages"
@@ -7872,7 +7869,7 @@ msgstr "In separater Zeile anzeigen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:58
 msgid "Add extra frag information to centerprint when available"
-msgstr "Zusätzliche Frag-Informationen in Centerprint anzeigen, wenn verfügbar"
+msgstr "Zusätzliche Frag-Infos in Zentralanzeige zeigen, wenn verfügbar"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:62
 msgid "Add frag location to death messages when available"
@@ -7914,7 +7911,7 @@ msgstr "Powerup-Nachrichten"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:89
 msgid "Weapon centerprint notifications"
-msgstr "Waffen-Centerprint-Nachrichten"
+msgstr "Waffen-Zentralanzeigen-Nachrichten"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:92
 msgid "Weapon info message notifications"
@@ -7995,7 +7992,7 @@ msgstr "Nur in Nicht-Teamspielen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:60
 msgid "Body fading:"
-msgstr "Ausblenden von Leichen:"
+msgstr "Leichenausblendung:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:63
 msgid "Gibs:"
@@ -8290,7 +8287,7 @@ msgstr "Auto-Springen"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:99
 msgid "Jetpack on jump:"
-msgstr "Jetpack aktiveren durch Springen:"
+msgstr "Jetpack bei Sprung:"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:101
 msgid "JPJUMP^Disabled"
@@ -8395,7 +8392,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:48
 msgid "Server queries/s:"
-msgstr "Server Anfragen/Sekunde:"
+msgstr "Serveranfragen/s:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:52
 msgid "Downloads:"
@@ -8589,11 +8586,12 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:10
 msgid "While connected language changes will be applied only to the menu,"
 msgstr ""
-"Während du verbunden bist, werden Sprachänderungen nur auf das Menü angewandt"
+"Während du verbunden bist, werden Sprachänderungen nur auf das Menü "
+"angewandt;"
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:12
 msgid "full language changes will take effect starting from the next game"
-msgstr "Volle Sprachänderungen finden erst nach dem Neustart des Spiels statt"
+msgstr "volle Sprachänderungen finden erst nach dem Neustart des Spiels statt."
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:16
 msgid "Disconnect now"
@@ -8940,7 +8938,7 @@ msgstr "Einzelspieler"
 #: qcsrc/menu/xonotic/dialog_singleplayer.qh:7
 msgid "Play the singleplayer campaign or instant action matches against bots"
 msgstr ""
-"Spiele die Einzelspieler-Kampagne oder habe Instant-Action Spiele gegen Bots"
+"Spiele die Einzelspieler-Kampagne oder spiele ein Schnellspiel gegen Bots"
 
 #: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7
 msgid "Winner"
@@ -9492,7 +9490,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/util.qc:780
 msgid "Use default"
-msgstr "Standard verwenden"
+msgstr "Standard"
 
 #: qcsrc/menu/xonotic/util.qc:800
 msgid "Team Color:"
index d5c87645f5f5fca211aba727c93dcf7eaa11a7e5..2c2c96b5dace8b9b653ec744dc4139c7baba613c 100644 (file)
@@ -3,7 +3,7 @@
 # This file is distributed under the same license as the PACKAGE package.
 #
 # Translators:
-# Wuzzy <almikes@aol.com>, 2016-2017
+# Wuzzy <almikes@aol.com>, 2016-2018
 # Brot Brot <noah.schluessel@gmail.com>, 2015
 # cvcxc <hans.andersen72@yahoo.com>, 2013
 # divVerent <divVerent@xonotic.org>, 2011,2013
@@ -24,7 +24,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-09-23 19:12+0000\n"
+"PO-Revision-Date: 2018-07-13 16:04+0000\n"
 "Last-Translator: Wuzzy <almikes@aol.com>\n"
 "Language-Team: German (http://www.transifex.com/team-xonotic/xonotic/"
 "language/de/)\n"
@@ -48,7 +48,7 @@ msgstr "^1Konnte nicht nach %s schreiben\n"
 
 #: qcsrc/client/hud/panel/chat.qc:82
 msgid "^3Player^7: This is the chat area."
-msgstr "^3Player^7: Dies ist der Chat-Bereich."
+msgstr "^3Spieler^7: Dies ist der Chat-Bereich."
 
 #: qcsrc/client/hud/panel/engineinfo.qc:69
 #, c-format
@@ -210,7 +210,7 @@ msgstr "^3Doppelklicke ^7ein Panel für Panel-spezifische Optionen."
 
 #: qcsrc/client/hud/panel/infomessages.qc:227
 msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"
-msgstr "^3STRG^7, um Kollisionstests zu deaktivieren, ^3SHIFT ^7und"
+msgstr "^3CTRL^7, um Kollisionstests zu deaktivieren, ^3SHIFT ^7und"
 
 #: qcsrc/client/hud/panel/infomessages.qc:228
 msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."
@@ -222,7 +222,7 @@ msgstr "Persönliche Bestzeit"
 
 #: qcsrc/client/hud/panel/modicons.qc:576
 msgid "Server best"
-msgstr "Server Bestzeit"
+msgstr "Server-Bestzeit"
 
 #: qcsrc/client/hud/panel/notify.qc:115 qcsrc/client/hud/panel/notify.qc:116
 #: qcsrc/client/hud/panel/score.qc:59
@@ -285,7 +285,7 @@ msgstr "freier Gegenstand %x^7 (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:804
 msgid "QMCMD^free item, icon"
-msgstr "freier Gegenstand, icon"
+msgstr "freier Gegenstand, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:805
 msgid "QMCMD^took item (l:%l^7)"
@@ -293,7 +293,7 @@ msgstr "Gegenstand genommen (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:805
 msgid "QMCMD^took item, icon"
-msgstr "Gegenstand genommen, icon"
+msgstr "Gegenstand genommen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:806
 msgid "QMCMD^negative"
@@ -309,7 +309,7 @@ msgstr "brauche Hilfe (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:808
 msgid "QMCMD^need help, icon"
-msgstr "brauche Hilfe, icon"
+msgstr "brauche Hilfe, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:809
 msgid "QMCMD^enemy seen (l:%y^7)"
@@ -317,7 +317,7 @@ msgstr "Gegner gesehen (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:809
 msgid "QMCMD^enemy seen, icon"
-msgstr "Gegner gesehen, icon"
+msgstr "Gegner gesehen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:810
 msgid "QMCMD^flag seen (l:%y^7)"
@@ -325,7 +325,7 @@ msgstr "Flagge gesehen (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:810
 msgid "QMCMD^flag seen, icon"
-msgstr "Flagge gesehen, icon"
+msgstr "Flagge gesehen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:811
 msgid "QMCMD^defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
@@ -333,7 +333,7 @@ msgstr "verteidigen (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:811
 msgid "QMCMD^defending, icon"
-msgstr "verteidigen, icon"
+msgstr "verteidigen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:812
 msgid "QMCMD^roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
@@ -341,7 +341,7 @@ msgstr "wandernd (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:812
 msgid "QMCMD^roaming, icon"
-msgstr "wandernd, icon"
+msgstr "wandernd, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:813
 msgid "QMCMD^attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
@@ -349,7 +349,7 @@ msgstr "angreifen (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:813
 msgid "QMCMD^attacking, icon"
-msgstr "angreifen, Iion"
+msgstr "angreifen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:814
 msgid "QMCMD^killed flagcarrier (l:%y^7)"
@@ -357,7 +357,7 @@ msgstr "Flaggenträger getötet (l:%y^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:814
 msgid "QMCMD^killed flagcarrier, icon"
-msgstr "Flaggenträger getötet, icon"
+msgstr "Flaggenträger getötet, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:815
 #, c-format
@@ -366,11 +366,11 @@ msgstr "Flagge fallen gelassen (l:%d^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:815
 msgid "QMCMD^dropped flag, icon"
-msgstr "Flagge fallen gelassen, icon"
+msgstr "Flagge fallen gelassen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:816
 msgid "QMCMD^drop weapon, icon"
-msgstr "Waffe wegwerfen, icon"
+msgstr "Waffe wegwerfen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:816
 msgid "QMCMD^dropped weapon %w^7 (l:%l^7)"
@@ -378,7 +378,7 @@ msgstr "Waffe fallen gelassen %w^7 (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:817
 msgid "QMCMD^drop flag/key, icon"
-msgstr "Flagge/Schlüssel fallen gelassen, icon"
+msgstr "Flagge/Schlüssel fallen gelassen, Icon"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:817
 msgid "QMCMD^dropped flag/key %w^7 (l:%l^7)"
@@ -694,7 +694,7 @@ msgstr "ticks"
 msgid ""
 "You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"
 msgstr ""
-"Du kannst die Tabelle mit dem ^2scoreboard_columns_set-Befehl ändern.\n"
+"Du kannst die Punktetafel mit dem ^2scoreboard_columns_set-Befehl ändern.\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:296
 msgid "^3|---------------------------------------------------------------|\n"
@@ -792,7 +792,7 @@ msgstr "^3capzeit^7                  Zeit des schnellsten Captures (CTF)\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:319
 msgid "^3fckills^7                  Number of flag carrier kills\n"
-msgstr "^3fckills^7                  Anzahl der getöteten Flaggen-Träger\n"
+msgstr "^3fckills^7                  Anzahl der getöteten Flaggenträger\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:320
 msgid "^3returns^7                  Number of flag returns\n"
@@ -950,7 +950,7 @@ msgstr "Platzierungen"
 #: qcsrc/client/hud/panel/scoreboard.qc:1519
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:43
 msgid "Scoreboard"
-msgstr "Tabelle"
+msgstr "Punktetafel"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:1584
 #, c-format
@@ -1022,7 +1022,7 @@ msgstr "Du bist tot, warte ^3%s^7 bis zum Respawn"
 #: qcsrc/client/hud/panel/scoreboard.qc:1707
 #, c-format
 msgid "You are dead, press ^2%s^7 to respawn"
-msgstr "Du bist tot, drücke ^2%s^7 um neu zu spawnen"
+msgstr "Du bist tot, drücke ^2%s^7, um neu zu spawnen"
 
 #: qcsrc/client/hud/panel/vote.qc:24
 msgid "^1You must answer before entering hud configure mode\n"
@@ -1070,11 +1070,11 @@ msgstr "Keine Munition mehr"
 
 #: qcsrc/client/hud/panel/weapons.qc:534
 msgid "Don't have"
-msgstr "Nicht vorhanden"
+msgstr "Hast du nicht"
 
 #: qcsrc/client/hud/panel/weapons.qc:538
 msgid "Unavailable"
-msgstr "Nicht verfügbar"
+msgstr "Fehlend"
 
 #: qcsrc/client/main.qc:1014
 msgid " qu/s"
@@ -1384,11 +1384,11 @@ msgstr "Vielleicht klappt es beim nächsten Mal!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1172
 msgid "Tubular! Press \"Next Level\" to continue!"
-msgstr "Grossartig! Drücke „Nächter Level“ zum Fortfahren!"
+msgstr "Grossartig! Drücke „Nächstes Level“ zum Fortfahren!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1174
 msgid "Wicked! Press \"Next Level\" to continue!"
-msgstr "Wahnsinn! Klicke \"Nächstes Level\" um weiter zu spielen!"
+msgstr "Wahnsinn! Drücke „Nächstes Level“ zum Fortfahren!"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1177
 msgid "Press the space bar to change your currently selected tile"
@@ -1419,7 +1419,7 @@ msgstr "Speichern"
 #: qcsrc/common/minigames/minigame/pp.qc:438
 #: qcsrc/common/minigames/minigame/ttt.qc:319
 msgid "Draw"
-msgstr "Zeichnen"
+msgstr "Unentschieden"
 
 #: qcsrc/common/minigames/minigame/c4.qc:378
 #: qcsrc/common/minigames/minigame/nmm.qc:601
@@ -1521,7 +1521,7 @@ msgstr "Nächstes Spiel"
 #: qcsrc/common/minigames/minigame/ps.qc:478
 #, c-format
 msgid "Pieces left: %s"
-msgstr "Verbleibende Spielfiguren: %s"
+msgstr "Figuren: %s"
 
 #: qcsrc/common/minigames/minigame/ps.qc:488
 msgid "No more valid moves"
@@ -2626,7 +2626,7 @@ msgstr "^BGDu hast ^F1%s^BG%s fallengelassen"
 #: qcsrc/common/notifications/all.inc:698
 #, c-format
 msgid "^BGYou got the ^F1%s"
-msgstr "^BG^F1%s^K1 erhalten"
+msgstr "^F1%s^BG erhalten"
 
 #: qcsrc/common/notifications/all.inc:385
 #: qcsrc/common/notifications/all.inc:699
@@ -2734,12 +2734,12 @@ msgstr "^BGTeam ^TC^TT^BG hielt den Ball zu lange fest"
 #: qcsrc/common/notifications/all.inc:412
 #, c-format
 msgid "^BG%s^BG captured %s^BG control point"
-msgstr "^BG%s^BG hat den Kontrollpunkt von %s^BG erobert"
+msgstr "^BG%s^BG hat einen Kontrollpunkt erobert: %s^BG"
 
 #: qcsrc/common/notifications/all.inc:413
 #, c-format
 msgid "^TC^TT^BG team %s^BG control point has been destroyed by %s"
-msgstr "^TC^TT^BGDer Kontrollpunkt vom Team %s^BG wurde von %s zerstört"
+msgstr "^TC^TT^BGEin Kontrollpunkt vom Team %s^BG wurde von %s zerstört"
 
 #: qcsrc/common/notifications/all.inc:414
 msgid "^TC^TT^BG generator has been destroyed"
@@ -2759,7 +2759,7 @@ msgstr "^BG%s^K1 hat Unsichtbarkeit aufgesammelt"
 #: qcsrc/common/notifications/all.inc:418
 #, c-format
 msgid "^BG%s^K1 picked up Shield"
-msgstr "^BG%s^K1 hat das Schild aufgenommen"
+msgstr "^BG%s^K1 hat den Schild aufgenommen"
 
 #: qcsrc/common/notifications/all.inc:419
 #, c-format
@@ -3597,7 +3597,7 @@ msgstr "^K1Deine Medizin-Granate ist ein wenig defekt"
 
 #: qcsrc/common/notifications/all.inc:644
 msgid "^K1You are respawning for running out of ammo..."
-msgstr "^K1Du wirst wiederbelebt weil du keine Munition mehr hast …"
+msgstr "^K1Du wirst wiederbelebt, weil du keine Munition mehr hast …"
 
 #: qcsrc/common/notifications/all.inc:644
 msgid "^K1You were killed for running out of ammo..."
@@ -3914,12 +3914,12 @@ msgstr "^F2Aktive Waffe: ^F1%s"
 #: qcsrc/common/notifications/all.inc:733
 #, c-format
 msgid "^BGYou captured %s^BG control point"
-msgstr "^BGDu hast den Kontrollpunkt von %s^BG erobert"
+msgstr "^BGDu hast einen Kontrollpunkt erobert: %s^BG"
 
 #: qcsrc/common/notifications/all.inc:734
 #, c-format
 msgid "^TC^TT^BG team captured %s^BG control point"
-msgstr "Team ^TC^TT^BG hat %ss^BG Kontrollpunkt erobert"
+msgstr "Team ^TC^TT^BG hat einen Kontrollpunkt erobert: %s^BG"
 
 #: qcsrc/common/notifications/all.inc:735
 msgid "^BGThis control point currently cannot be captured"
@@ -4020,7 +4020,7 @@ msgstr "^F2Ein Schild umgibt dich"
 
 #: qcsrc/common/notifications/all.inc:754
 msgid "^F2Shield has worn off"
-msgstr "^F2Das Schild ist wieder verschwunden"
+msgstr "^F2Der Schild ist wieder verschwunden"
 
 #: qcsrc/common/notifications/all.inc:756
 msgid "^F2You are on speed"
@@ -5258,7 +5258,7 @@ msgstr "Schriftgrösse:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qh:6
 msgid "Centerprint Panel"
-msgstr "Nachrichten-Panel"
+msgstr "Zentralanzeigen-Panel"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:15
 msgid "Chat entries:"
@@ -5356,7 +5356,7 @@ msgstr "Beim Zuschauen zeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:18
 msgid "PNL^Enabled even playing in warmup"
-msgstr "Auch in der Aufwärmphase zeigen"
+msgstr "Auch in Aufwärmphase zeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:29
 msgid "Reduced"
@@ -5364,7 +5364,7 @@ msgstr "Reduziert"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:32
 msgid "Text/icon ratio:"
-msgstr "Text/Icon-Verhältnis:"
+msgstr "Text-/Icon-Verhältnis:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:35
 msgid "Hide spawned items"
@@ -5408,7 +5408,7 @@ msgstr "Eintrags-Ausblendung:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_notification.qh:6
 msgid "Notification Panel"
-msgstr "Anzeige-Panel"
+msgstr "Nachrichten-Panel"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:15
 #: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:14
@@ -5422,11 +5422,11 @@ msgstr "Panel anzeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:17
 msgid "Panel enabled even observing"
-msgstr "Panel auch beim Zuschauen anzeigen"
+msgstr "Auch beim Zuschauen zeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:18
 msgid "Panel enabled only in Race/CTS"
-msgstr "Panel nur in Rennen und CTS-Rennen anzeigen"
+msgstr "Nur in Rennen und CTS-Rennen zeigen"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:24
 msgid "Status bar"
@@ -5537,7 +5537,7 @@ msgstr "Rundenzeit-Panel"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:16
 msgid "Panel enabled in teamgames"
-msgstr "Panel in Team-Spieltypen aktivieren"
+msgstr "Panel in Teamspielen aktivieren"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:23
 msgid "Radar:"
@@ -6318,13 +6318,11 @@ msgstr "Spielmechanik-Mutatoren:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:160
 msgid "Enable dodging"
-msgstr ""
-"Ausweichmodus: Es ist möglich rasch zur Seite zu springen (spezielle "
-"Bewegung)"
+msgstr "Ausweichmanöver aktivieren"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:167
 msgid "All players are almost invisible"
-msgstr "Tarnmodus: Alle Spieler sind fast unsichtbar"
+msgstr "Alle Spieler sind fast unsichtbar"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:174
 msgid "Only possible to inflict damage on your enemy while he's airborne"
@@ -6334,15 +6332,15 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:178
 msgid "Damage done to your enemy gets added to your own health"
 msgstr ""
-"Vampirmodus: Der Schaden, dem du anderen Spielern zufügst, wird deiner "
-"eigenen Lebensenergie hinzugefügt"
+"Der Schaden, dem du anderen Spielern zufügst, wird deiner eigenen "
+"Lebensenergie hinzugefügt"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:183
 msgid ""
 "Amount of health below which your player gets stunned because of blood loss"
 msgstr ""
-"Blutverlust: Aktiviere diesen Modus und stelle den Wert der Lebensenergie, "
-"bei der Spieler auf Grund von Blutverlust betäubt wirken, ein"
+"Aktiviere diesen Modus und stelle den Wert der Lebensenergie, bei der "
+"Spieler auf Grund von Blutverlust betäubt wirken, ein"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:192
 msgid "Make things fall to the ground slower, lower value means lower gravity"
@@ -6391,10 +6389,9 @@ msgid ""
 "Selecting a weapon arena will give all players that weapon at spawn as well "
 "as unlimited ammo, and disable all other weapon pickups."
 msgstr ""
-"Waffen-Arenen: Die Auswahl einer Waffen-Arena führt dazu, dass jeder Spieler "
-"mit der gewählten Waffe startet. Diese hat unendlich viel Munition, andere "
-"Waffen sind nicht vorhanden – Spezielle Waffen-Arenen: Spieler starten mit "
-"allen Waffen und unendlich viel Munition"
+"Die Auswahl einer Waffen-Arena führt dazu, dass jeder Spieler mit der "
+"gewählten Waffe startet. Diese hat unendlich viel Munition, andere Waffen "
+"sind nicht vorhanden."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:255
 msgid "Most weapons"
@@ -6618,7 +6615,7 @@ msgstr "Musikplayer"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:48
 msgid "Auto record demos"
-msgstr "Wiederholungen automatisch aufzeichnen"
+msgstr "Wiederholungen autom. aufzeichnen"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:57
 msgid "Timedemo"
@@ -6709,7 +6706,7 @@ msgstr "Alle entfernen"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:43
 msgid "Auto screenshot scoreboard"
-msgstr "Screenshot der Tabelle automatisch anfertigen"
+msgstr "Auto-Screenshot der Punktetafel"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:63
 msgid "Open in the viewer"
@@ -7420,7 +7417,7 @@ msgstr "Scharf"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:163
 msgid "Decals"
-msgstr "Einschusslöcher"
+msgstr "Dekore"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:164
 msgid "Enable decals (bullet holes and blood) (default: enabled)"
@@ -7718,7 +7715,7 @@ msgstr "Dezimalstellen im Respawn-Countdown anzeigen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:57
 msgid "Show accuracy underneath scoreboard"
-msgstr "Trefferquote unter Tabelle anzeigen"
+msgstr "Trefferquote unter Punktetafel anzeigen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:61
 msgid "Waypoints"
@@ -7825,7 +7822,7 @@ msgstr "Um den HUD-Editor zu starten, muss ein Spiel gestartet werden."
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:23
 msgid "Do you wish to start a local game to set up the HUD?"
-msgstr "Willst du ein lokales Spiel starten, um das HUD zu editieren?"
+msgstr "Willst du ein lokales Spiel starten, um das HUD zu bearbeiten?"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:24
 msgid "Frag Information"
@@ -7841,7 +7838,7 @@ msgstr "Amokläufe nur anzeigen, wenn sie Achievements sind"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:34
 msgid "Show spree information in centerprints"
-msgstr "Amoklauf-Informationen in Centerprints anzeigen"
+msgstr "Amoklauf-Infos in Zentralanzeige zeigen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:38
 msgid "Show spree information in death messages"
@@ -7873,7 +7870,7 @@ msgstr "In separater Zeile anzeigen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:58
 msgid "Add extra frag information to centerprint when available"
-msgstr "Zusätzliche Frag-Informationen in Centerprint anzeigen, wenn verfügbar"
+msgstr "Zusätzliche Frag-Infos in Zentralanzeige zeigen, wenn verfügbar"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:62
 msgid "Add frag location to death messages when available"
@@ -7915,7 +7912,7 @@ msgstr "Powerup-Nachrichten"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:89
 msgid "Weapon centerprint notifications"
-msgstr "Waffen-Centerprint-Nachrichten"
+msgstr "Waffen-Zentralanzeigen-Nachrichten"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:92
 msgid "Weapon info message notifications"
@@ -7996,7 +7993,7 @@ msgstr "Nur in Nicht-Teamspielen"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:60
 msgid "Body fading:"
-msgstr "Ausblenden von Leichen:"
+msgstr "Leichenausblendung:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:63
 msgid "Gibs:"
@@ -8291,7 +8288,7 @@ msgstr "Auto-Springen"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:99
 msgid "Jetpack on jump:"
-msgstr "Jetpack aktiveren durch Springen:"
+msgstr "Jetpack bei Sprung:"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:101
 msgid "JPJUMP^Disabled"
@@ -8396,7 +8393,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:48
 msgid "Server queries/s:"
-msgstr "Server Anfragen/Sekunde:"
+msgstr "Serveranfragen/s:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:52
 msgid "Downloads:"
@@ -8590,11 +8587,12 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:10
 msgid "While connected language changes will be applied only to the menu,"
 msgstr ""
-"Während du verbunden bist, werden Sprachänderungen nur auf das Menü angewandt"
+"Während du verbunden bist, werden Sprachänderungen nur auf das Menü "
+"angewandt;"
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:12
 msgid "full language changes will take effect starting from the next game"
-msgstr "Volle Sprachänderungen finden erst nach dem Neustart des Spiels statt"
+msgstr "volle Sprachänderungen finden erst nach dem Neustart des Spiels statt."
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:16
 msgid "Disconnect now"
@@ -8941,7 +8939,7 @@ msgstr "Einzelspieler"
 #: qcsrc/menu/xonotic/dialog_singleplayer.qh:7
 msgid "Play the singleplayer campaign or instant action matches against bots"
 msgstr ""
-"Spiele die Einzelspieler-Kampagne oder habe Instant-Action Spiele gegen Bots"
+"Spiele die Einzelspieler-Kampagne oder spiele ein Schnellspiel gegen Bots"
 
 #: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7
 msgid "Winner"
@@ -9493,7 +9491,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/util.qc:780
 msgid "Use default"
-msgstr "Standard verwenden"
+msgstr "Standard"
 
 #: qcsrc/menu/xonotic/util.qc:800
 msgid "Team Color:"
index 84391e6114ea7ba0d9010dd5dee41ed46820185b..4a3b837d1c3bbf8cfff28783d13ac3688d437ee2 100644 (file)
 # RedGuff <domsau2@yahoo.fr>, 2014
 # Yannick Le Guen <leguen.yannick@gmail.com>, 2013
 # Hugo Locurcio, 2013
-# Yannick Le Guen <leguen.yannick@gmail.com>, 2013-2017
+# Yannick Le Guen <leguen.yannick@gmail.com>, 2013-2018
 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-14 13:32+0000\n"
+"PO-Revision-Date: 2018-07-08 09:28+0000\n"
 "Last-Translator: Yannick Le Guen <leguen.yannick@gmail.com>\n"
 "Language-Team: French (http://www.transifex.com/team-xonotic/xonotic/"
 "language/fr/)\n"
@@ -3086,12 +3086,12 @@ msgstr ""
 #: qcsrc/common/notifications/all.inc:484
 #, c-format
 msgid "^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"
-msgstr "^BG%s%s^K1 a été abattu par la Mitrailleuse de ^BG%s^K1%s%s"
+msgstr "^BG%s%s^K1 a été abattu par la Mitraillette de ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:485
 #, c-format
 msgid "^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"
-msgstr "^BG%s%s^K1 a été criblé de balles par la Mitrailleuse de ^BG%s^K1%s%s"
+msgstr "^BG%s%s^K1 a été criblé de balles par la Mitraillette de ^BG%s^K1%s%s"
 
 #: qcsrc/common/notifications/all.inc:486
 #: qcsrc/common/notifications/all.inc:790
@@ -4631,7 +4631,7 @@ msgstr "Grappin"
 
 #: qcsrc/common/weapons/weapon/machinegun.qc:17
 msgid "MachineGun"
-msgstr "Mitrailleuse"
+msgstr "Mitraillette"
 
 #: qcsrc/common/weapons/weapon/minelayer.qc:17
 msgid "Mine Layer"
index 593e684a646c9714c90d90cbf02bf197633a270b..f158cef5b8f5c2a755f0310dc7c1978e4836a448 100644 (file)
@@ -3,13 +3,14 @@
 # This file is distributed under the same license as the PACKAGE package.
 #
 # Translators:
+# nad le <nadavlevi726@gmail.com>, 2018
 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-07-05 15:06+0000\n"
-"Last-Translator: divVerent <divVerent@xonotic.org>\n"
+"PO-Revision-Date: 2018-07-18 12:01+0000\n"
+"Last-Translator: nad le <nadavlevi726@gmail.com>\n"
 "Language-Team: Hebrew (http://www.transifex.com/team-xonotic/xonotic/"
 "language/he/)\n"
 "Language: he\n"
@@ -65,12 +66,12 @@ msgstr ""
 #: qcsrc/client/hud/panel/infomessages.qc:102
 #: qcsrc/client/hud/panel/infomessages.qc:106
 msgid "next weapon"
-msgstr ""
+msgstr "נשק הבא"
 
 #: qcsrc/client/hud/panel/infomessages.qc:102
 #: qcsrc/client/hud/panel/infomessages.qc:106
 msgid "previous weapon"
-msgstr ""
+msgstr "נשק קודם"
 
 #: qcsrc/client/hud/panel/infomessages.qc:106
 #, c-format
@@ -100,7 +101,7 @@ msgstr ""
 #: qcsrc/client/hud/panel/infomessages.qc:111
 #: qcsrc/menu/xonotic/keybinder.qc:94
 msgid "server info"
-msgstr ""
+msgstr "מידע על השרת"
 
 #: qcsrc/client/hud/panel/infomessages.qc:124
 msgid "^1Match has already begun"
@@ -140,7 +141,7 @@ msgstr ""
 #: qcsrc/client/hud/panel/infomessages.qc:175
 #: qcsrc/menu/xonotic/keybinder.qc:91
 msgid "ready"
-msgstr ""
+msgstr "מוכן"
 
 #: qcsrc/client/hud/panel/infomessages.qc:162
 #, c-format
@@ -172,7 +173,7 @@ msgstr ""
 #: qcsrc/client/hud/panel/infomessages.qc:199
 #: qcsrc/menu/xonotic/keybinder.qc:102
 msgid "team menu"
-msgstr ""
+msgstr "תפריט צוות"
 
 #: qcsrc/client/hud/panel/infomessages.qc:209
 msgid "^1Spectating this player:"
@@ -225,7 +226,7 @@ msgstr ""
 
 #: qcsrc/client/hud/panel/quickmenu.qc:636
 msgid "Continue..."
-msgstr ""
+msgstr "המשך..."
 
 #: qcsrc/client/hud/panel/quickmenu.qc:794
 #: qcsrc/client/hud/panel/quickmenu.qc:798
@@ -500,12 +501,12 @@ msgstr ""
 
 #: qcsrc/client/hud/panel/racetimer.qc:61
 msgid "Start line"
-msgstr ""
+msgstr "קו התחלה"
 
 #: qcsrc/client/hud/panel/racetimer.qc:63
 #: qcsrc/client/hud/panel/racetimer.qc:67
 msgid "Finish line"
-msgstr ""
+msgstr "קו סיום"
 
 #: qcsrc/client/hud/panel/racetimer.qc:65
 #, c-format
@@ -1010,7 +1011,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:16
 #: qcsrc/menu/xonotic/dialog_uid2name.qc:15
 msgid "Yes"
-msgstr ""
+msgstr "כן"
 
 #: qcsrc/client/hud/panel/vote.qc:127 qcsrc/menu/xonotic/dialog_firstrun.qc:83
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:21
@@ -1020,7 +1021,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:17
 #: qcsrc/menu/xonotic/dialog_uid2name.qc:17
 msgid "No"
-msgstr ""
+msgstr "לא"
 
 #: qcsrc/client/hud/panel/weapons.qc:530
 msgid "Out of ammo"
@@ -1032,7 +1033,7 @@ msgstr ""
 
 #: qcsrc/client/hud/panel/weapons.qc:538
 msgid "Unavailable"
-msgstr ""
+msgstr "לא זמין"
 
 #: qcsrc/client/main.qc:1014
 msgid " qu/s"
@@ -1078,7 +1079,7 @@ msgstr ""
 
 #: qcsrc/client/mapvoting.qc:365
 msgid "Vote for a map"
-msgstr ""
+msgstr "הצבע למפה"
 
 #: qcsrc/client/mapvoting.qc:382
 #, c-format
@@ -1181,11 +1182,11 @@ msgstr ""
 
 #: qcsrc/common/mapinfo.qh:126
 msgid "Race"
-msgstr ""
+msgstr "מרוץ"
 
 #: qcsrc/common/mapinfo.qh:126
 msgid "Race against other players to the finish line"
-msgstr ""
+msgstr "התחרה נגד שחקנים אחרים לקו הסיום"
 
 #: qcsrc/common/mapinfo.qh:160
 msgid "Race CTS"
@@ -1205,7 +1206,7 @@ msgstr ""
 
 #: qcsrc/common/mapinfo.qh:220
 msgid "Capture the Flag"
-msgstr ""
+msgstr "תפוס את הדגל"
 
 #: qcsrc/common/mapinfo.qh:220
 msgid ""
@@ -1308,7 +1309,7 @@ msgstr ""
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:403
 msgid "Exit Menu"
-msgstr ""
+msgstr "צא מהתפריט"
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:415
 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:16
@@ -1317,7 +1318,7 @@ msgstr ""
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:418
 msgid "Join"
-msgstr ""
+msgstr "הצטרף"
 
 #: qcsrc/common/minigames/cl_minigames_hud.qc:489
 msgid "Minigames"
@@ -1345,7 +1346,7 @@ msgstr ""
 
 #: qcsrc/common/minigames/minigame/bd.qc:1404
 msgid "Next Level"
-msgstr ""
+msgstr "שלב הבא"
 
 #: qcsrc/common/minigames/minigame/bd.qc:1405
 msgid "Restart"
@@ -1358,7 +1359,7 @@ msgstr ""
 #: qcsrc/common/minigames/minigame/bd.qc:1407
 #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:37
 msgid "Save"
-msgstr ""
+msgstr "שמור"
 
 #: qcsrc/common/minigames/minigame/c4.qc:373
 #: qcsrc/common/minigames/minigame/pp.qc:438
@@ -1414,15 +1415,15 @@ msgstr ""
 
 #: qcsrc/common/minigames/minigame/pong.qc:651
 msgid "Start Match"
-msgstr ""
+msgstr "התחל משחק"
 
 #: qcsrc/common/minigames/minigame/pong.qc:652
 msgid "Add AI player"
-msgstr ""
+msgstr "הוסף שחקן מחשב"
 
 #: qcsrc/common/minigames/minigame/pong.qc:653
 msgid "Remove AI player"
-msgstr ""
+msgstr "הסר שחקן מחשב"
 
 #: qcsrc/common/minigames/minigame/pp.qc:443
 #: qcsrc/common/minigames/minigame/ttt.qc:324
@@ -1451,7 +1452,7 @@ msgstr ""
 #: qcsrc/common/minigames/minigame/pp.qc:582
 #: qcsrc/common/minigames/minigame/ttt.qc:665
 msgid "Next Match"
-msgstr ""
+msgstr "משחק הבא"
 
 #: qcsrc/common/minigames/minigame/ps.qc:478
 #, c-format
@@ -1464,7 +1465,7 @@ msgstr ""
 
 #: qcsrc/common/minigames/minigame/ps.qc:491
 msgid "Well done, you win!"
-msgstr ""
+msgstr "כל הכבוד, ניצחת!"
 
 #: qcsrc/common/minigames/minigame/ps.qc:494
 msgid "Jump a piece over another to capture it"
@@ -1477,7 +1478,7 @@ msgstr ""
 #: qcsrc/common/monsters/monster/mage.qh:17
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:18
 msgid "Mage"
-msgstr ""
+msgstr "קוסם"
 
 #: qcsrc/common/monsters/monster/mage.qh:29
 msgid "Mage spike"
@@ -1491,7 +1492,7 @@ msgstr ""
 #: qcsrc/common/monsters/monster/spider.qh:17
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:16
 msgid "Spider"
-msgstr ""
+msgstr "עכביש"
 
 #: qcsrc/common/monsters/monster/spider.qh:28
 msgid "Spider attack"
@@ -1509,11 +1510,11 @@ msgstr ""
 #: qcsrc/common/monsters/monster/zombie.qh:17
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:15
 msgid "Zombie"
-msgstr ""
+msgstr "זומבי"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:15
 msgid "Ammo"
-msgstr ""
+msgstr "תחמושת"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:24
 msgid "Resistance"
@@ -1522,7 +1523,7 @@ msgstr ""
 #: qcsrc/common/mutators/mutator/buffs/all.inc:33
 #: qcsrc/common/mutators/mutator/instagib/items.qh:94
 msgid "Speed"
-msgstr ""
+msgstr "מהירות"
 
 #: qcsrc/common/mutators/mutator/buffs/all.inc:43
 msgid "Medic"
@@ -1610,7 +1611,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:109
 #: qcsrc/menu/xonotic/util.qc:775
 msgid "Color:"
-msgstr ""
+msgstr "צבע:"
 
 #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:47
 msgid "Draw damage numbers for friendly fire"
@@ -1654,7 +1655,7 @@ msgstr ""
 
 #: qcsrc/common/mutators/mutator/nades/nades.qh:32
 msgid "Grenade"
-msgstr ""
+msgstr "רימון"
 
 #: qcsrc/common/mutators/mutator/overkill/hmg.qh:17
 msgid "Heavy Machine Gun"
@@ -1674,15 +1675,15 @@ msgstr ""
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:5
 msgid "Here"
-msgstr ""
+msgstr "כאן"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:6
 msgid "DANGER"
-msgstr ""
+msgstr "סכנה"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:8
 msgid "Frozen!"
-msgstr ""
+msgstr "קפוא!"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:10
 msgid "Item"
@@ -1776,12 +1777,12 @@ msgstr ""
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:39
 msgid "Run here"
-msgstr ""
+msgstr "רוץ לכאן"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:45
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:48
 msgid "Ball"
-msgstr ""
+msgstr "כדור"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:46
 msgid "Ball carrier"
@@ -1798,19 +1799,19 @@ msgstr ""
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:57
 msgid "Weapon"
-msgstr ""
+msgstr "נשק"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:59
 msgid "Monster"
-msgstr ""
+msgstr "מפלצת"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:61
 msgid "Vehicle"
-msgstr ""
+msgstr "רכב"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:62
 msgid "Intruder!"
-msgstr ""
+msgstr "פולש!"
 
 #: qcsrc/common/mutators/mutator/waypoints/all.inc:64
 msgid "Tagged"
@@ -4332,7 +4333,7 @@ msgstr ""
 
 #: qcsrc/common/turrets/turret/plasma_weapon.qh:7
 msgid "Plasma"
-msgstr ""
+msgstr "פלזמה"
 
 #: qcsrc/common/turrets/turret/tesla.qh:13
 #: qcsrc/common/turrets/turret/tesla_weapon.qh:7
@@ -4462,7 +4463,7 @@ msgstr ""
 
 #: qcsrc/common/weapons/weapon/shotgun.qc:17
 msgid "Shotgun"
-msgstr ""
+msgstr "שוטגן"
 
 #: qcsrc/common/weapons/weapon/tuba.qc:17
 #, no-c-format
@@ -4712,7 +4713,7 @@ msgstr ""
 
 #: qcsrc/menu/command/menu_cmd.qc:79
 msgid "Available options:\n"
-msgstr ""
+msgstr "אפשרויות זמינות:\n"
 
 #: qcsrc/menu/command/menu_cmd.qc:128
 msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n"
@@ -4745,7 +4746,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/credits.qc:48
 msgid "Website"
-msgstr ""
+msgstr "אתר"
 
 #: qcsrc/menu/xonotic/credits.qc:53
 msgid "Stats"
@@ -4925,7 +4926,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/cvarlist.qc:93
 msgid "private"
-msgstr ""
+msgstr "פרטי"
 
 #: qcsrc/menu/xonotic/cvarlist.qc:95
 msgid "engine setting"
@@ -4946,7 +4947,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_credits.qh:7
 msgid "Credits"
-msgstr ""
+msgstr "קרדיטים"
 
 #: qcsrc/menu/xonotic/dialog_credits.qh:8
 msgid "The Xonotic credits"
@@ -4962,7 +4963,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_firstrun.qc:45
 #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:28
 msgid "Name:"
-msgstr ""
+msgstr "שם:"
 
 #: qcsrc/menu/xonotic/dialog_firstrun.qc:53
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:60
@@ -4983,11 +4984,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_firstrun.qc:88
 msgid "Save settings"
-msgstr ""
+msgstr "שמור הגדרות"
 
 #: qcsrc/menu/xonotic/dialog_firstrun.qh:6
 msgid "Welcome"
-msgstr ""
+msgstr "ברוך הבא"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:16
 msgid "Ammunition display:"
@@ -5021,7 +5022,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:33
 #: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:18
 msgid "Left"
-msgstr ""
+msgstr "שמאל"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:32
 #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:32
@@ -5032,7 +5033,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:34
 #: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:20
 msgid "Right"
-msgstr ""
+msgstr "ימין"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qh:6
 msgid "Ammo Panel"
@@ -5059,7 +5060,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:19
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:71
 msgid "Center"
-msgstr ""
+msgstr "מרכז"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:35
 msgid "Font scale:"
@@ -5075,7 +5076,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:18
 msgid "Chat size:"
-msgstr ""
+msgstr "גודל צ'אט:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:22
 msgid "Chat lifetime:"
@@ -5265,15 +5266,15 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:37
 msgid "Speed:"
-msgstr ""
+msgstr "מהירות:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:38
 msgid "Include vertical speed"
-msgstr ""
+msgstr "כלול מהירות אנכית"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:49
 msgid "Speed unit:"
-msgstr ""
+msgstr "יחידת מידה למהירות:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:51
 msgid "qu/s"
@@ -5297,7 +5298,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:57
 msgid "Show"
-msgstr ""
+msgstr "הצג"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:60
 msgid "Top speed"
@@ -5419,7 +5420,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:15
 msgid "Score:"
-msgstr ""
+msgstr "ניקוד:"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:18
 msgid "Rankings:"
@@ -5470,7 +5471,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:139
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:55
 msgid "Never"
-msgstr ""
+msgstr "לעולם לא"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:24
 #, c-format
@@ -5515,7 +5516,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:54
 msgid "Number"
-msgstr ""
+msgstr "מספר"
 
 #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:55
 msgid "Bind"
@@ -5556,14 +5557,14 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:25
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:35
 msgid "Filter:"
-msgstr ""
+msgstr "מסנן:"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:30
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:53
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:49
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:44
 msgid "Refresh"
-msgstr ""
+msgstr "רענן"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:33
 #: qcsrc/menu/xonotic/dialog_settings_user.qc:30
@@ -5581,7 +5582,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:48
 #: qcsrc/menu/xonotic/util.qc:767
 msgid "Background:"
-msgstr ""
+msgstr "רקע:"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:50
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:62
@@ -5662,7 +5663,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:13
 msgid "Monster:"
-msgstr ""
+msgstr "מפלצת:"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:22
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:20
@@ -5672,7 +5673,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:23
 #: qcsrc/menu/xonotic/serverlist.qc:268
 msgid "Remove"
-msgstr ""
+msgstr "הסר"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:25
 msgid "Move target:"
@@ -5696,7 +5697,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:31
 msgid "Colors:"
-msgstr ""
+msgstr "צבעים:"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:33
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:39
@@ -5709,7 +5710,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:14
 msgid "Servers"
-msgstr ""
+msgstr "שרתים"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:15
 msgid "Find servers to play on"
@@ -5743,12 +5744,12 @@ msgstr ""
 #: qcsrc/menu/xonotic/util.qc:785 qcsrc/menu/xonotic/util.qc:794
 #: qcsrc/menu/xonotic/util.qc:802 qcsrc/menu/xonotic/util.qc:814
 msgid "Default"
-msgstr ""
+msgstr "ברירת מחדל"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:48
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:64
 msgid "Unlimited"
-msgstr ""
+msgstr "לא מוגבל"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:65
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:66
@@ -5789,7 +5790,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:70
 msgid "Lives:"
-msgstr ""
+msgstr "חיים:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:71
 msgid "Laps:"
@@ -5805,11 +5806,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:97
 msgid "Gametype"
-msgstr ""
+msgstr "סוג משחק"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:102
 msgid "Time limit:"
-msgstr ""
+msgstr "הגבלת זמן:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:104
 msgid "Timelimit in minutes that when hit, will end the match"
@@ -5827,7 +5828,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:107
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:159
 msgid "1 minute"
-msgstr ""
+msgstr "דקה אחת"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:124
 msgid "TIMLIM^Infinite"
@@ -5835,19 +5836,19 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:132
 msgid "Teams:"
-msgstr ""
+msgstr "צוותים:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:135
 msgid "2 teams"
-msgstr ""
+msgstr "2 צוותים"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:136
 msgid "3 teams"
-msgstr ""
+msgstr "3 צוותים"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:137
 msgid "4 teams"
-msgstr ""
+msgstr "4 צוותים"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:140
 msgid "Player slots:"
@@ -5881,15 +5882,15 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:153
 msgid "Beginner"
-msgstr ""
+msgstr "מתחיל"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:154
 msgid "You will win"
-msgstr ""
+msgstr "אתה תנצח"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:155
 msgid "You can win"
-msgstr ""
+msgstr "אתה יכול לנצח"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:156
 msgid "You might win"
@@ -5897,27 +5898,27 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:157
 msgid "Advanced"
-msgstr ""
+msgstr "מתקדם"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:158
 msgid "Expert"
-msgstr ""
+msgstr "מומחה"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:159
 msgid "Pro"
-msgstr ""
+msgstr "מקצוען"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:160
 msgid "Assassin"
-msgstr ""
+msgstr "מתנקש"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:161
 msgid "Unhuman"
-msgstr ""
+msgstr "לא אנושי"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:162
 msgid "Godlike"
-msgstr ""
+msgstr "דמוי אל"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:178
 msgid "Mutators..."
@@ -5955,7 +5956,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:217
 msgid "Add all"
-msgstr ""
+msgstr "הוסף הכל"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:218
 msgid "Add every available map to your selection"
@@ -5963,7 +5964,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:221
 msgid "Remove all"
-msgstr ""
+msgstr "הסר הכל"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:222
 msgid "Remove all the maps from your selection"
@@ -5975,20 +5976,20 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:58
 msgid "Title:"
-msgstr ""
+msgstr "כותרת:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:64
 msgid "Author:"
-msgstr ""
+msgstr "מחבר:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:70
 msgid "Game types:"
-msgstr ""
+msgstr "סוגי משחק:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:93
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:296
 msgid "Close"
-msgstr ""
+msgstr "סגור"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:96
 msgid "MAP^Play"
@@ -6044,7 +6045,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:75
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:282
 msgid "No start weapons"
-msgstr ""
+msgstr "ללא נשקי התחלה"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:77
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:195
@@ -6073,7 +6074,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:89
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:229
 msgid "Weapons stay"
-msgstr ""
+msgstr "נשקים נשארים"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:91
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:184
@@ -6129,7 +6130,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:178
 msgid "Damage done to your enemy gets added to your own health"
-msgstr ""
+msgstr "נזק שנעשה לאויב שלך מתווסף לחיים שלך"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:183
 msgid ""
@@ -6182,11 +6183,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:255
 msgid "Most weapons"
-msgstr ""
+msgstr "רוב הנשקים"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:260
 msgid "All weapons"
-msgstr ""
+msgstr "כל הנשקים"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:264
 msgid "Special arenas:"
@@ -6255,11 +6256,11 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:67
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:223
 msgid "Address:"
-msgstr ""
+msgstr "כתובת:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:78
 msgid "Info..."
-msgstr ""
+msgstr "מידע..."
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:79
 msgid "Show more information about the currently highlighted server"
@@ -6268,7 +6269,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:84
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:303
 msgid "Join!"
-msgstr ""
+msgstr "הצטרף!"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:154
 #: qcsrc/menu/xonotic/serverlist.qc:1061
@@ -6282,7 +6283,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:161
 msgid "Official"
-msgstr ""
+msgstr "רשמי"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:169
 msgid "N/A (auth library missing, can't connect)"
@@ -6294,7 +6295,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:177
 msgid "Not supported (can't connect)"
-msgstr ""
+msgstr "לא נתמך(לא יכול להתחבר)"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:179
 msgid "Not supported (won't encrypt)"
@@ -6330,11 +6331,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:231
 msgid "Gametype:"
-msgstr ""
+msgstr "סוג משחק:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:236
 msgid "Map:"
-msgstr ""
+msgstr "מפה:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:241
 msgid "Mod:"
@@ -6342,16 +6343,16 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:246
 msgid "Version:"
-msgstr ""
+msgstr "גרסה:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:251
 msgid "Settings:"
-msgstr ""
+msgstr "הגדרות:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:258
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:290
 msgid "Players:"
-msgstr ""
+msgstr "שחקנים:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:263
 msgid "Bots:"
@@ -6375,7 +6376,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qh:7
 msgid "Server Information"
-msgstr ""
+msgstr "מידע על השרת"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:25
 msgid "Demos"
@@ -6412,12 +6413,12 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:15
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:15
 msgid "Do you really wish to disconnect now?"
-msgstr ""
+msgstr "אתה באמת רוצה להתנתק עכשיו?"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qh:6
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qh:6
 msgid "Disconnect"
-msgstr ""
+msgstr "התנתק"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:13
 msgid "Timing a demo will disconnect you from the current match."
@@ -6445,7 +6446,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:55
 msgid "Random order"
-msgstr ""
+msgstr "סדר אקראי"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:60
 msgid "MUSICPL^Stop"
@@ -6485,19 +6486,19 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:139
 msgid "Reset"
-msgstr ""
+msgstr "אפס"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:144
 msgid "Previous"
-msgstr ""
+msgstr "קודם"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:147
 msgid "Next"
-msgstr ""
+msgstr "הבא"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:152
 msgid "Slide show"
-msgstr ""
+msgstr "מצגת שקופיות"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:34
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:21
@@ -6510,7 +6511,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:48
 msgid "Name"
-msgstr ""
+msgstr "שם"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:77
 msgid "Model"
@@ -6538,38 +6539,38 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:145
 msgid "Country"
-msgstr ""
+msgstr "מדינה"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:159
 msgid "Gender:"
-msgstr ""
+msgstr "מין:"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:161
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:174
 msgid "Undisclosed"
-msgstr ""
+msgstr "לא ידוע"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:162
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:172
 msgid "Female"
-msgstr ""
+msgstr "נקבה"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:163
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:173
 msgid "Male"
-msgstr ""
+msgstr "זכר"
 
 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:166
 msgid "Gender"
-msgstr ""
+msgstr "מין"
 
 #: qcsrc/menu/xonotic/dialog_quit.qc:11
 msgid "Are you sure you want to quit?"
-msgstr ""
+msgstr "אתה בטוח שברצונך לצאת?"
 
 #: qcsrc/menu/xonotic/dialog_quit.qc:15
 msgid "Back to work..."
-msgstr ""
+msgstr "בחזרה לעבודה..."
 
 #: qcsrc/menu/xonotic/dialog_quit.qc:17
 msgid "I got some more fragging to do!"
@@ -6577,7 +6578,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_quit.qh:7
 msgid "Quit the game"
-msgstr ""
+msgstr "צא מהמשחק"
 
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:15
 msgid "Model:"
@@ -6585,15 +6586,15 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:21
 msgid "Remove *"
-msgstr ""
+msgstr "הסר *"
 
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:23
 msgid "Copy *"
-msgstr ""
+msgstr "העתק *"
 
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:24
 msgid "Paste"
-msgstr ""
+msgstr "הדבק"
 
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:26
 msgid "Bone:"
@@ -6693,7 +6694,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:81
 msgid "Show help"
-msgstr ""
+msgstr "הצג עזרה"
 
 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:82
 msgid "* is the object you are facing"
@@ -6709,23 +6710,23 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings.qc:19
 msgid "Effects"
-msgstr ""
+msgstr "אפקטים"
 
 #: qcsrc/menu/xonotic/dialog_settings.qc:20
 msgid "Audio"
-msgstr ""
+msgstr "שמע"
 
 #: qcsrc/menu/xonotic/dialog_settings.qc:22
 msgid "Game"
-msgstr ""
+msgstr "משחק"
 
 #: qcsrc/menu/xonotic/dialog_settings.qc:23
 msgid "Input"
-msgstr ""
+msgstr "קלט"
 
 #: qcsrc/menu/xonotic/dialog_settings.qc:24
 msgid "User"
-msgstr ""
+msgstr "משתמש"
 
 #: qcsrc/menu/xonotic/dialog_settings.qc:25
 #: qcsrc/menu/xonotic/keybinder.qc:105
@@ -6734,11 +6735,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings.qh:6
 msgid "Settings"
-msgstr ""
+msgstr "הגדרות"
 
 #: qcsrc/menu/xonotic/dialog_settings.qh:7
 msgid "Change the game settings"
-msgstr ""
+msgstr "שנה את הגדרות המשחק"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:29
 msgid "Master:"
@@ -6746,7 +6747,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:35
 msgid "Music:"
-msgstr ""
+msgstr "מוזיקה:"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:43
 msgid "VOL^Ambient:"
@@ -6754,7 +6755,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:50
 msgid "Info:"
-msgstr ""
+msgstr "מידע:"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:57
 msgid "Items:"
@@ -6766,7 +6767,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:71
 msgid "Player:"
-msgstr ""
+msgstr "שחקן:"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:78
 msgid "Shots:"
@@ -6774,11 +6775,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:85
 msgid "Voice:"
-msgstr ""
+msgstr "קול:"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:93
 msgid "Weapons:"
-msgstr ""
+msgstr "נשקים:"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:99
 msgid "New style sound attenuation"
@@ -6842,7 +6843,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:123
 msgid "Stereo"
-msgstr ""
+msgstr "סטראו"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:124
 msgid "2.1"
@@ -6900,7 +6901,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:149
 msgid "Menu sounds"
-msgstr ""
+msgstr "צלילי תפריט"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:150
 msgid "Play sounds when clicking menu items"
@@ -6924,7 +6925,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:160
 msgid "5 minutes"
-msgstr ""
+msgstr "5 דקות"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:161
 msgid "WRN^Both"
@@ -6940,17 +6941,17 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:168
 msgid "Sometimes"
-msgstr ""
+msgstr "לפעמים"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:169
 msgid "Often"
-msgstr ""
+msgstr "לעתים קרובות"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:170
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:141
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:57
 msgid "Always"
-msgstr ""
+msgstr "תמיד"
 
 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:176
 msgid "Debug info about sounds"
@@ -7180,7 +7181,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:169
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:253
 msgid "Distance:"
-msgstr ""
+msgstr "מרחק"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:172
 msgid "Decals further away than this will not be drawn (default: 300)"
@@ -7188,7 +7189,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:176
 msgid "Time:"
-msgstr ""
+msgstr "זמן:"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:179
 msgid "Time in seconds before decals fade away (default: 2)"
@@ -7264,7 +7265,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:212
 msgid "Use normal maps"
-msgstr ""
+msgstr "השתמש במפות רגילות"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:213
 msgid "Enable use of directional shading on textures (default: enabled)"
@@ -7312,7 +7313,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:239
 msgid "Particles"
-msgstr ""
+msgstr "חלקיקים"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:240
 msgid "Spawnpoint effects"
@@ -7324,7 +7325,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:246
 msgid "Quality:"
-msgstr ""
+msgstr "איכות:"
 
 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:249
 msgid ""
@@ -7355,11 +7356,11 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:81
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:97
 msgid "Size:"
-msgstr ""
+msgstr "גודל:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:64
 msgid "By health"
-msgstr ""
+msgstr "לפי חיים"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:76
 msgid "Use rings to indicate weapon status"
@@ -7455,7 +7456,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:74
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:124
 msgid "Fontsize:"
-msgstr ""
+msgstr "גודל גופן:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:80
 msgid "Edge offset:"
@@ -7467,7 +7468,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:94
 msgid "Damage"
-msgstr ""
+msgstr "נזק"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:96
 msgid "Overlay:"
@@ -7487,11 +7488,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:114
 msgid "Show names above players"
-msgstr ""
+msgstr "הצג שמות מעל שחקנים"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:130
 msgid "Max distance:"
-msgstr ""
+msgstr "מרחק מקסימלי:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:136
 msgid "Decolorize:"
@@ -7597,7 +7598,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:65
 msgid "Gamemode Settings"
-msgstr ""
+msgstr "אפשרויות מצב משחק"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:67
 msgid "Display capture times in Capture The Flag"
@@ -7611,7 +7612,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:91
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:133
 msgid "Other"
-msgstr ""
+msgstr "אחר"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:78
 msgid "Display console messages in the top left corner"
@@ -7655,7 +7656,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qh:7
 msgid "Messages"
-msgstr ""
+msgstr "הודעות"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:30
 msgid "Items"
@@ -7696,7 +7697,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:49
 #: qcsrc/menu/xonotic/serverlist.qc:767
 msgid "Players"
-msgstr ""
+msgstr "שחקנים"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:51
 msgid "Force player models to mine"
@@ -7768,7 +7769,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:51
 msgid "3rd person perspective"
-msgstr ""
+msgstr "נקודת מבט מגוף שלישי"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:55
 msgid "Back distance"
@@ -7913,7 +7914,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qh:7
 #: qcsrc/menu/xonotic/keybinder.qc:43
 msgid "Weapons"
-msgstr ""
+msgstr "נשקים"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:33
 msgid "Key Bindings"
@@ -7925,23 +7926,23 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:41
 msgid "Edit..."
-msgstr ""
+msgstr "ערוך..."
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:47
 msgid "Clear"
-msgstr ""
+msgstr "נקה"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:52
 msgid "Reset all"
-msgstr ""
+msgstr "אפס הכל"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:57
 msgid "Mouse"
-msgstr ""
+msgstr "עכבר"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:59
 msgid "Sensitivity:"
-msgstr ""
+msgstr "רגישות:"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:61
 msgid "Mouse speed multiplier"
@@ -7991,7 +7992,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:96
 msgid "Automatically repeat jumping if holding jump"
-msgstr ""
+msgstr "המשך לקפוץ באופן אוטומטי אם מקש קפיצה לחוץ"
 
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:99
 msgid "Jetpack on jump:"
@@ -8013,7 +8014,7 @@ msgstr ""
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:114
 #: qcsrc/menu/xonotic/dialog_settings_input.qc:119
 msgid "Use joystick input"
-msgstr ""
+msgstr "התשתמש בקלט מג'ויסטיק"
 
 #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:31
 msgid "Command when pressed:"
@@ -8025,7 +8026,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:40
 msgid "Cancel"
-msgstr ""
+msgstr "בטל"
 
 #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qh:7
 msgid "User defined key bind"
@@ -8048,7 +8049,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:27
 msgid "Network"
-msgstr ""
+msgstr "רשת"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:29
 msgid "Client UDP port:"
@@ -8060,11 +8061,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:34
 msgid "Bandwidth:"
-msgstr ""
+msgstr "רוחב פס:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:36
 msgid "Specify your network speed"
-msgstr ""
+msgstr "צין את מהירות הרשת שלך"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:37
 msgid "56k"
@@ -8100,7 +8101,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:52
 msgid "Downloads:"
-msgstr ""
+msgstr "הורדות:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:54
 msgid "Maximum number of concurrent HTTP/FTP downloads"
@@ -8108,7 +8109,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:56
 msgid "Download speed:"
-msgstr ""
+msgstr "מהירות הורדה:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:69
 msgid "Local latency:"
@@ -8148,7 +8149,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:102
 msgid "Target:"
-msgstr ""
+msgstr "מטרה:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:104
 msgid "TRGT^Disabled"
@@ -8168,7 +8169,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:129
 msgid "Show frames per second"
-msgstr ""
+msgstr "הצג פריימים לשנייה"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:130
 msgid "Show your rendered frames per second"
@@ -8206,7 +8207,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:147
 msgid "Enable developer mode"
-msgstr ""
+msgstr "אפשר מצב מפתח"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:151
 msgid "Advanced settings..."
@@ -8235,23 +8236,23 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:49
 msgid "Type:"
-msgstr ""
+msgstr "סוג:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:53
 msgid "Value:"
-msgstr ""
+msgstr "ערך:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:70
 msgid "Description:"
-msgstr ""
+msgstr "תיאור:"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qh:7
 msgid "Advanced settings"
-msgstr ""
+msgstr "אפשרויות מתקדמות"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:11
 msgid "Are you sure you want to reset all settings?"
-msgstr ""
+msgstr "האם אתה בטוח שברצונך לאפס את כל ההגדרות?"
 
 #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:13
 msgid "This will create a backup config in your data directory"
@@ -8263,11 +8264,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_user.qc:64
 msgid "Text Language"
-msgstr ""
+msgstr "שפת טקסט"
 
 #: qcsrc/menu/xonotic/dialog_settings_user.qc:69
 msgid "Set language"
-msgstr ""
+msgstr "קבע שפה"
 
 #: qcsrc/menu/xonotic/dialog_settings_user.qc:74
 msgid "Disable gore effects and harsh language"
@@ -8289,11 +8290,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:16
 msgid "Disconnect now"
-msgstr ""
+msgstr "התנתק עכשיו"
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:17
 msgid "Switch language"
-msgstr ""
+msgstr "החלף שפה"
 
 #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qh:6
 msgid "Warning"
@@ -8361,7 +8362,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:59
 msgid "Full screen"
-msgstr ""
+msgstr "מסך מלא"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:61
 msgid "Vertical Synchronization"
@@ -8481,7 +8482,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:119
 msgid "Brightness:"
-msgstr ""
+msgstr "בהירות:"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:121
 msgid "Brightness of black (default: 0)"
@@ -8489,7 +8490,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:123
 msgid "Contrast:"
-msgstr ""
+msgstr "ניגודיות:"
 
 #: qcsrc/menu/xonotic/dialog_settings_video.qc:125
 msgid "Brightness of white (default: 1)"
@@ -8611,7 +8612,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7
 msgid "Winner"
-msgstr ""
+msgstr "מנצח"
 
 #: qcsrc/menu/xonotic/dialog_teamselect.qc:32
 msgid "join 'best' team (auto-select)"
@@ -8623,27 +8624,27 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/dialog_teamselect.qc:37
 msgid "red"
-msgstr ""
+msgstr "אדום"
 
 #: qcsrc/menu/xonotic/dialog_teamselect.qc:38
 msgid "blue"
-msgstr ""
+msgstr "כחול"
 
 #: qcsrc/menu/xonotic/dialog_teamselect.qc:39
 msgid "yellow"
-msgstr ""
+msgstr "צהוב"
 
 #: qcsrc/menu/xonotic/dialog_teamselect.qc:40
 msgid "pink"
-msgstr ""
+msgstr "ורוד"
 
 #: qcsrc/menu/xonotic/dialog_teamselect.qc:43
 msgid "spectate"
-msgstr ""
+msgstr "צפה"
 
 #: qcsrc/menu/xonotic/dialog_teamselect.qh:7
 msgid "Team Selection"
-msgstr ""
+msgstr "בחירת צוות"
 
 #: qcsrc/menu/xonotic/dialog_uid2name.qc:10
 msgid "Allow player statistics to use your nickname?"
@@ -8667,7 +8668,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/keybinder.qc:30
 msgid "forward"
-msgstr ""
+msgstr "קדימה"
 
 #: qcsrc/menu/xonotic/keybinder.qc:31
 msgid "backpedal"
@@ -8739,7 +8740,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/keybinder.qc:80
 msgid "screen shot"
-msgstr ""
+msgstr "צילום מסך"
 
 #: qcsrc/menu/xonotic/keybinder.qc:81
 msgid "maximize radar"
@@ -8771,11 +8772,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/keybinder.qc:89
 msgid "vote YES"
-msgstr ""
+msgstr "הצבע כן"
 
 #: qcsrc/menu/xonotic/keybinder.qc:90
 msgid "vote NO"
-msgstr ""
+msgstr "הצבע לא"
 
 #: qcsrc/menu/xonotic/keybinder.qc:93
 msgid "Client"
@@ -8787,11 +8788,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/keybinder.qc:96
 msgid "disconnect"
-msgstr ""
+msgstr "התנתק"
 
 #: qcsrc/menu/xonotic/keybinder.qc:97
 msgid "quit"
-msgstr ""
+msgstr "צא"
 
 #: qcsrc/menu/xonotic/keybinder.qc:101
 msgid "auto-join team"
@@ -8857,7 +8858,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/serverlist.qc:763
 msgid "Ping"
-msgstr ""
+msgstr "פינג"
 
 #: qcsrc/menu/xonotic/serverlist.qc:764
 msgid "Hostname"
@@ -8865,11 +8866,11 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/serverlist.qc:765
 msgid "Map"
-msgstr ""
+msgstr "מפה"
 
 #: qcsrc/menu/xonotic/serverlist.qc:766
 msgid "Type"
-msgstr ""
+msgstr "סוג"
 
 #: qcsrc/menu/xonotic/serverlist.qc:1060
 #, c-format
@@ -9005,10 +9006,13 @@ msgid ""
 "texture memory usage, but make the textures appear very blurry. (default: "
 "good)"
 msgstr ""
+"שנה את החדות של טקסטורות.\n"
+"הנמכה תגרום לצמצום יעיל של זיכרון שמשומש על ידי טקסטורות, אבל יגרום "
+"לטקסטורות להראות מאוד מטושטשות. (ברירת מחדל: טוב)"
 
 #: qcsrc/menu/xonotic/slider_resolution.qc:115
 msgid "Screen resolution"
-msgstr ""
+msgstr "רזולוציית מסך"
 
 #: qcsrc/menu/xonotic/slider_sbfadetime.qc:13
 msgid "PART^Slow"
@@ -9024,51 +9028,51 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/statslist.qc:29
 msgid "January"
-msgstr ""
+msgstr "ינואר"
 
 #: qcsrc/menu/xonotic/statslist.qc:30
 msgid "February"
-msgstr ""
+msgstr "פברואר"
 
 #: qcsrc/menu/xonotic/statslist.qc:31
 msgid "March"
-msgstr ""
+msgstr "מרץ"
 
 #: qcsrc/menu/xonotic/statslist.qc:32
 msgid "April"
-msgstr ""
+msgstr "אפריל"
 
 #: qcsrc/menu/xonotic/statslist.qc:33
 msgid "May"
-msgstr ""
+msgstr "מאי"
 
 #: qcsrc/menu/xonotic/statslist.qc:34
 msgid "June"
-msgstr ""
+msgstr "יוני"
 
 #: qcsrc/menu/xonotic/statslist.qc:35
 msgid "July"
-msgstr ""
+msgstr "יולי"
 
 #: qcsrc/menu/xonotic/statslist.qc:36
 msgid "August"
-msgstr ""
+msgstr "אוגוסט"
 
 #: qcsrc/menu/xonotic/statslist.qc:37
 msgid "September"
-msgstr ""
+msgstr "ספטמבר"
 
 #: qcsrc/menu/xonotic/statslist.qc:38
 msgid "October"
-msgstr ""
+msgstr "אוקטובר"
 
 #: qcsrc/menu/xonotic/statslist.qc:39
 msgid "November"
-msgstr ""
+msgstr "נובמבר"
 
 #: qcsrc/menu/xonotic/statslist.qc:40
 msgid "December"
-msgstr ""
+msgstr "דצמבר"
 
 #: qcsrc/menu/xonotic/statslist.qc:96
 msgid "Joined:"
@@ -9076,7 +9080,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/statslist.qc:103
 msgid "Last_Seen:"
-msgstr ""
+msgstr "נראה_לאחרונה:"
 
 #: qcsrc/menu/xonotic/statslist.qc:110
 msgid "Time_Played:"
@@ -9145,7 +9149,7 @@ msgstr ""
 
 #: qcsrc/menu/xonotic/util.qc:780
 msgid "Use default"
-msgstr ""
+msgstr "השתמש בברירת מחדל"
 
 #: qcsrc/menu/xonotic/util.qc:800
 msgid "Team Color:"
index c3b8efc999459771b73f37b4db9e59c5e44f3117..7306a0dca6201651fca866d10660c7a7ae5b03c9 100644 (file)
@@ -14,7 +14,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: 2018-05-22 14:42+0000\n"
+"PO-Revision-Date: 2018-07-22 18:03+0000\n"
 "Last-Translator: Jean Trindade Pereira <jean_trindade2@hotmail.com>\n"
 "Language-Team: Portuguese (Brazil) (http://www.transifex.com/team-xonotic/"
 "xonotic/language/pt_BR/)\n"
@@ -27,7 +27,7 @@ msgstr ""
 #: qcsrc/client/hud/hud_config.qc:239
 #, c-format
 msgid "^2Successfully exported to %s! (Note: It's saved in data/data/)\n"
-msgstr "^2Exportado com sucesso para %s! (Nota: Foi salvo em data/data/)\n"
+msgstr "^2Exportado com sucesso para %s! (Nota: foi salvo em data/data/)\n"
 
 #: qcsrc/client/hud/hud_config.qc:243
 #, c-format
@@ -155,12 +155,11 @@ msgstr "%sAperte ^3%s%s assim que estiver pronto"
 #: qcsrc/client/hud/panel/infomessages.qc:167
 msgid "^2Waiting for others to ready up to end warmup..."
 msgstr ""
-"^2Esperando que os outros jogadores estejam prontos para acabar o "
-"aquecimento..."
+"^2Aguardando outros jogadores ficarem prontos para terminar o aquecimento..."
 
 #: qcsrc/client/hud/panel/infomessages.qc:169
 msgid "^2Waiting for others to ready up..."
-msgstr "^2Esperando que os outros jogadores estejam prontos..."
+msgstr "^2Aguardando outros jogadores ficarem prontos..."
 
 #: qcsrc/client/hud/panel/infomessages.qc:175
 #, c-format
@@ -183,7 +182,7 @@ msgstr "menu de equipe"
 
 #: qcsrc/client/hud/panel/infomessages.qc:209
 msgid "^1Spectating this player:"
-msgstr "^1Também estão assistindo a este jogador:"
+msgstr "^1Assistindo a este jogador:"
 
 #: qcsrc/client/hud/panel/infomessages.qc:209
 msgid "^1Spectating you:"
@@ -191,7 +190,7 @@ msgstr "^1Assistindo você:"
 
 #: qcsrc/client/hud/panel/infomessages.qc:225
 msgid "^7Press ^3ESC ^7to show HUD options."
-msgstr "^7Aperte ^3ESC ^7para exibir as opções de HUD."
+msgstr "^7Aperte ^3ESC ^7para exibir as opções de interface."
 
 #: qcsrc/client/hud/panel/infomessages.qc:226
 msgid "^3Doubleclick ^7a panel for panel-specific options."
@@ -201,7 +200,7 @@ msgstr ""
 
 #: qcsrc/client/hud/panel/infomessages.qc:227
 msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"
-msgstr "^3CTRL ^7para desligar teste de colisão, ^3SHIFT ^7e"
+msgstr "Use ^3CTRL ^7para desligar o teste de colisão, e ^3SHIFT ^7e"
 
 #: qcsrc/client/hud/panel/infomessages.qc:228
 msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."
@@ -365,7 +364,7 @@ msgstr "Largar arma, ícone"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:816
 msgid "QMCMD^dropped weapon %w^7 (l:%l^7)"
-msgstr "Arma solta %w^7 (l:%l^7)"
+msgstr "Arma largada %w^7 (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:817
 msgid "QMCMD^drop flag/key, icon"
@@ -377,7 +376,7 @@ msgstr "Bandeira/Chave largada %w^7 (l:%l^7)"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:821
 msgid "QMCMD^Send private message to"
-msgstr "Mandar mensagem privada para"
+msgstr "Enviar mensagem privada para"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:823
 #: qcsrc/client/hud/panel/quickmenu.qc:860
@@ -387,7 +386,7 @@ msgstr "Configurações"
 #: qcsrc/client/hud/panel/quickmenu.qc:824
 #: qcsrc/client/hud/panel/quickmenu.qc:831
 msgid "QMCMD^View/HUD settings"
-msgstr "Configurações de Exibição/HUD"
+msgstr "Configurações de exibição/interface"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:825
 msgid "QMCMD^3rd person view"
@@ -454,7 +453,7 @@ msgstr "Aumentar velocidade"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:851
 msgid "QMCMD^Decrease speed"
-msgstr "Diminuir velocidade"
+msgstr "Reduzir velocidade"
 
 #: qcsrc/client/hud/panel/quickmenu.qc:852
 msgid "QMCMD^Wall collision off"
@@ -685,7 +684,7 @@ msgstr "ticks"
 msgid ""
 "You can modify the scoreboard using the ^2scoreboard_columns_set command.\n"
 msgstr ""
-"Você pode modificar o placar usando o comando ^2scoreboard_columns_set.\n"
+"É possível modificar o placar usando o comando ^2scoreboard_columns_set.\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:296
 msgid "^3|---------------------------------------------------------------|\n"
@@ -701,13 +700,13 @@ msgstr "^2scoreboard_columns_set padrão\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:299
 msgid "^2scoreboard_columns_set ^7field1 field2 ...\n"
-msgstr "^2scoreboard_columns_set ^7campo1 campo2...\n"
+msgstr "^2scoreboard_columns_set ^7field1 field2...\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:300
 msgid "The following field names are recognized (case insensitive):\n"
 msgstr ""
-"Os seguintes nomes de campos são reconhecidos (maiúsculas/minúsculas não são "
-"distintas):\n"
+"Os seguintes nomes de campo são reconhecidos (maiúsculas e minúsculas não "
+"diferem):\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:301
 msgid "You can use a ^3|^7 to start the right-aligned fields.\n"
@@ -731,7 +730,7 @@ msgstr "^3elo^7 ELO do jogador\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:308
 msgid "^3kills^7                    Number of kills\n"
-msgstr "^3vítimas^7 Número de aniquilações\n"
+msgstr "^3vítimas^7 Número de vítimas\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:309
 msgid "^3deaths^7                   Number of deaths\n"
@@ -783,8 +782,7 @@ msgstr "^3tempodecaptura^7 Tempo da captura mais rápida (CTF)\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:319
 msgid "^3fckills^7                  Number of flag carrier kills\n"
-msgstr ""
-"^3pbndvítimas^7 Número de portadores de bandeiras mortos pelo jogador\n"
+msgstr "^3pbndvítimas^7 Número de portadores de bandeiras aniquilados\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:320
 msgid "^3returns^7                  Number of flag returns\n"
@@ -792,7 +790,7 @@ msgstr "^3retornos^7 Número de bandeiras retomadas\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:321
 msgid "^3drops^7                    Number of flag drops\n"
-msgstr "^3quedas^7 Número de bandeiras que foram soltas\n"
+msgstr "^3quedas^7 Número de bandeiras largadas\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:322
 msgid "^3lives^7                    Number of lives (LMS)\n"
@@ -804,18 +802,18 @@ msgstr "^3posição^7 Classificação do jogador\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:324
 msgid "^3pushes^7                   Number of players pushed into void\n"
-msgstr "^3empurrões^7 Número de jogadores empurrados para fora do mapa\n"
+msgstr "^3empurrões^7 Número de jogadores empurrados para o vazio\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:325
 msgid ""
 "^3destroyed^7                Number of keys destroyed by pushing them into "
 "void\n"
 msgstr ""
-"^3destruídas^7 Número de chaves destruídas ao empurrá-las para fora do mapa\n"
+"^3destruídas^7 Número de chaves destruídas ao empurrá-las para o vazio\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:326
 msgid "^3kckills^7                  Number of keys carrier kills\n"
-msgstr "^3pcvítimas^7 Número de portadores de chaves mortos pelo jogador\n"
+msgstr "^3pcvítimas^7 Número de portadores de chaves aniquilados\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:327
 msgid "^3losses^7                   Number of times a key was lost\n"
@@ -827,7 +825,7 @@ msgstr "^3voltas^7 Número de voltas concluídas (corrida/cts)\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:329
 msgid "^3time^7                     Total time raced (race/cts)\n"
-msgstr "^3tempo^7 Tempo total de corrida (corrida/cts)\n"
+msgstr "^3tempo^7 Tempo total em corridas (corrida/cts)\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:330
 msgid "^3fastest^7                  Time of fastest lap (race/cts)\n"
@@ -843,7 +841,7 @@ msgstr "^3tomados^7 Número de pontos de dominação tomados (DOM)\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:333
 msgid "^3bckills^7                  Number of ball carrier kills\n"
-msgstr "^3pblvítimas^7 Número de portadores de bolas mortos pelo jogador\n"
+msgstr "^3pblvítimas^7 Número de portadores de bolas aniquilados\n"
 
 #: qcsrc/client/hud/panel/scoreboard.qc:334
 msgid ""
@@ -1017,7 +1015,8 @@ msgstr "Você morreu. Aperte ^2%s^7 para ressurgir"
 #: qcsrc/client/hud/panel/vote.qc:24
 msgid "^1You must answer before entering hud configure mode\n"
 msgstr ""
-"^1Você tem que responder antes de entrar no modo de configuração do HUD\n"
+"^1Você tem que responder antes de entrar no modo de configuração da "
+"interface\n"
 
 #: qcsrc/client/hud/panel/vote.qc:29
 msgid "^2Name ^7instead of \"^1Anonymous player^7\" in stats"
@@ -1033,7 +1032,7 @@ msgstr "Permitir que servidores armazenem e mostrem o seu nome?"
 
 #: qcsrc/client/hud/panel/vote.qc:121
 msgid "^1Configure the HUD"
-msgstr "^1Configurar o HUD"
+msgstr "^1Configurar a interface"
 
 #: qcsrc/client/hud/panel/vote.qc:125 qcsrc/menu/xonotic/dialog_firstrun.qc:82
 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:18
@@ -5716,7 +5715,7 @@ msgstr "Painel das Armas"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:19
 msgid "HUD skins"
-msgstr "Visuais de HUD"
+msgstr "Visuais de interface"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:22
 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:196
@@ -5783,7 +5782,7 @@ msgstr "Preenchimento:"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:93
 msgid "HUD Dock:"
-msgstr "Camada do HUD:"
+msgstr "Camada da interface:"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:95
 msgid "DOCK^Disabled"
@@ -5827,7 +5826,7 @@ msgstr "Sair da configuração"
 
 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qh:6
 msgid "Panel HUD Setup"
-msgstr "Painel de Configuração do HUD"
+msgstr "Painel de configuração da interface"
 
 #: qcsrc/menu/xonotic/dialog_monstertools.qc:13
 msgid "Monster:"
@@ -7754,32 +7753,33 @@ msgstr "Sobreposição do dano:"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:160
 msgid "Dynamic HUD"
-msgstr "HUD dinâmico"
+msgstr "Interface dinâmica"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:161
 msgid "HUD moves around following player's movement"
-msgstr "O HUD se move de acordo com o movimento do jogador"
+msgstr "A interface se move de acordo com o movimento do jogador"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:163
 msgid "Shake the HUD when hurt"
-msgstr "Vibrar o HUD ao ser atingido"
+msgstr "Vibrar a interface ao receber dano"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:167
 #: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qh:6
 msgid "Enter HUD editor"
-msgstr "Entrar no editor do HUD"
+msgstr "Entrar no editor de interface"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qh:7
 msgid "HUD"
-msgstr "HUD"
+msgstr "Interface"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:21
 msgid "In order for the HUD editor to show, you must first be in game."
-msgstr "Para o editor do HUD aparecer, é necessário estar jogando em um mapa."
+msgstr ""
+"Para abrir o editor de interface, é necessário estar jogando em um mapa."
 
 #: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:23
 msgid "Do you wish to start a local game to set up the HUD?"
-msgstr "Quer iniciar um jogo local para personalizar o HUD?"
+msgstr "Quer iniciar um jogo local para personalizar a interface?"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:24
 msgid "Frag Information"
@@ -7888,7 +7888,7 @@ msgstr "Sons da contagem de ressurgimento"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:101
 msgid "Killstreak sounds"
-msgstr "Sons de sequências de mortes"
+msgstr "Sons de sequência de mortes"
 
 #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:104
 msgid "Achievement sounds"
index 48c8253a3a2146538f1a9dfa6cc388f76b616ba4..597bb4660a9f0e063e6009652c8c0997dbbbd99e 100644 (file)
@@ -8,6 +8,8 @@ cl_spawn_point_particles 1
 cl_playerdetailreduction 4
 gl_flashblend 0
 gl_picmip -1
+gl_texturecompression_2d 0
+gl_texturecompression_sky 0
 mod_q3bsp_nolightmaps 0
 r_bloom 1
 r_coronas 1
index b7e9a98a3a7a78fa396023d1f3fe615cd4cb4c4a..c9549581bddb35ebfc0fa858b347760aed609b13 100644 (file)
@@ -8,6 +8,8 @@ cl_spawn_point_particles 0
 cl_playerdetailreduction 4
 gl_flashblend 1
 gl_picmip 1
+gl_texturecompression_2d 1
+gl_texturecompression_sky 1
 mod_q3bsp_nolightmaps 1
 r_bloom 0
 r_coronas 1
index 66eed5aa5d55dc897c6cd748848cd5ed82cb3efe..4ea20a1699d110c6742eab52260963c581b9ee66 100644 (file)
@@ -8,6 +8,8 @@ cl_spawn_point_particles 0
 cl_playerdetailreduction 4
 gl_flashblend 0
 gl_picmip 0
+gl_texturecompression_2d 0
+gl_texturecompression_sky 1
 mod_q3bsp_nolightmaps 0
 r_bloom 0
 r_coronas 1
index 63dcd134a066f0c4255c4ad380f085249e177d0a..c421e5b325b6925c89b17e2a926fe018e5a170b2 100644 (file)
@@ -8,6 +8,8 @@ cl_spawn_point_particles 1
 cl_playerdetailreduction 4
 gl_flashblend 0
 gl_picmip 0
+gl_texturecompression_2d 0
+gl_texturecompression_sky 1
 mod_q3bsp_nolightmaps 0
 r_bloom 0
 r_coronas 1
index 9018ee2c94375ba8740fa35f3357f55ff1d3cf15..7614417ce2027e42c4d711fce396faaaf7c1cd14 100644 (file)
@@ -8,6 +8,8 @@ cl_spawn_point_particles 0
 cl_playerdetailreduction 4
 gl_flashblend 1
 gl_picmip 1337
+gl_texturecompression_2d 1
+gl_texturecompression_sky 1
 mod_q3bsp_nolightmaps 1
 r_bloom 0
 r_coronas 1
index 0cf3a899cbcebf5fa385a66ffd3fc07f326ca3c0..3ce6f55a7f01483f9a6c94d1c4a9d53405abbe8b 100644 (file)
@@ -8,6 +8,8 @@ cl_spawn_point_particles 1
 cl_playerdetailreduction 0
 gl_flashblend 0
 gl_picmip -1
+gl_texturecompression_2d 0
+gl_texturecompression_sky 0
 mod_q3bsp_nolightmaps 0
 r_bloom 1
 r_coronas 1
index 5909f3b83dc956b18141d4c0111b251c60080813..d42d7c58ba07362f3d95b73bd5a6e8b90dab5835 100644 (file)
@@ -8,6 +8,8 @@ cl_spawn_point_particles 1
 cl_playerdetailreduction 0
 gl_flashblend 0
 gl_picmip -1
+gl_texturecompression_2d 0
+gl_texturecompression_sky 0
 mod_q3bsp_nolightmaps 0
 r_bloom 1
 r_coronas 1
diff --git a/gfx/hud/default/as_defend.tga b/gfx/hud/default/as_defend.tga
new file mode 100644 (file)
index 0000000..5aca85e
Binary files /dev/null and b/gfx/hud/default/as_defend.tga differ
diff --git a/gfx/hud/default/as_destroy.tga b/gfx/hud/default/as_destroy.tga
new file mode 100644 (file)
index 0000000..7c779a1
Binary files /dev/null and b/gfx/hud/default/as_destroy.tga differ
diff --git a/gfx/hud/luma/as_defend.tga b/gfx/hud/luma/as_defend.tga
new file mode 100644 (file)
index 0000000..5aca85e
Binary files /dev/null and b/gfx/hud/luma/as_defend.tga differ
diff --git a/gfx/hud/luma/as_destroy.tga b/gfx/hud/luma/as_destroy.tga
new file mode 100644 (file)
index 0000000..7c779a1
Binary files /dev/null and b/gfx/hud/luma/as_destroy.tga differ
index e2e83ae7588ba17ef77aa1f1278f29a69901111a..b90d291fb40646d6ffdbcd7e5845b3835b63c12c 100644 (file)
Binary files a/gfx/hud/luma/ok_weapon_rail.tga and b/gfx/hud/luma/ok_weapon_rail.tga differ
index f5fb92e13ee7bcc11b2809755883a44531fe0b18..b0e7bf9327d5d95350ed74ec1f7589171882963b 100644 (file)
Binary files a/gfx/hud/luma/ok_weapon_shotgun.tga and b/gfx/hud/luma/ok_weapon_shotgun.tga differ
index 5aee32ab545a47884f50cd00ce4248e8cb35ab3c..cb26a1657dd0f04c2775e9d9323327885a5cc918 100644 (file)
Binary files a/gfx/hud/luma/ok_weapon_smg.tga and b/gfx/hud/luma/ok_weapon_smg.tga differ
index c36c3f5e7e587989e23d5d7db7b0e5039f216d75..cb0414cc1ea32fb1881fa8de3f13bbca501de60f 100644 (file)
Binary files a/gfx/hud/luma/weaponhmg.tga and b/gfx/hud/luma/weaponhmg.tga differ
index 643c5cafee679e92a84f4a60c28849cac75eb62e..74019d86f9ec8d079f59badbb83cd17a2afbd9b9 100644 (file)
Binary files a/gfx/hud/luma/weaponrpc.tga and b/gfx/hud/luma/weaponrpc.tga differ
index 65ce9094219c56f80574f2735befda22cf3c46bd..e16e0b878637b50dd21f71c361f88866b5c54379 100644 (file)
@@ -1,25 +1,25 @@
-ko    Korean "한국의" 33%
-ast   Asturian "Asturianu" 73%
+ast   "Asturian" "Asturianu" 73%
+de    "German" "Deutsch" 99%
+de_CH "German (Switzerland)" "Deutsch (Schweiz)" 99%
+en    "English" "English" 100%
+en_AU "English (Australia)" "English (Australia)" 86%
+es    "Spanish" "Español" 99%
+fr    "French" "Français" 99%
+ga    "Irish" "Irish" 35%
+it    "Italian" "Italiano" 99%
+hu    "Hungarian" "Magyar" 55%
+nl    "Dutch" "Nederlands" 70%
+pl    "Polish" "Polski" 81%
+pt    "Portuguese" "Português" 98%
+pt_BR "Portuguese (Brazil)" "Português (Brasil)" 99%
+ro    "Romanian" "Romana" 83%
+fi    "Finnish" "Suomi" 33%
+el    "Greek" "Ελληνική" 33%
+be    "Belarusian" "Беларуская" 61%
+bg    "Bulgarian" "Български" 68%
+ru    "Russian" "Русский" 99%
+sr    "Serbian" "Српски" 71%
+uk    "Ukrainian" "Українська" 57%
 zh_CN "Chinese (China)" "中文" 62%
-de    German "Deutsch"
-de_CH German "Deutsch (Schweiz)"
-en    English "English"
-en_AU English "English (Australia)" 86%
-es    Spanish "Español" 99%
-fr    French "Français"
-ga    Irish "Irish" 35%
-it    Italian "Italiano"
-hu    Hungarian "Magyar" 55%
-nl    Dutch "Nederlands" 70%
-pl    Polish "Polski" 81%
-pt    Portuguese "Português"
-pt_BR pt_BR "pt_BR" 99%
-ro    Romanian "Romana" 83%
-fi    Finnish "Suomi" 33%
 zh_TW "Chinese (Taiwan)" "國語" 68%
-el    Greek "Ελληνική" 33%
-be    Belarusian "Беларуская" 61%
-bg    Bulgarian "Български" 68%
-ru    Russian "Русский"
-sr    Serbian "Српски" 71%
-uk    Ukrainian "Українська" 57%
+ko    "Korean" "한국의" 33%
index 27b579027f93063f207b8fbf849e538a7ea4dff3..efdb0b2b075859d0ae67937c7dda6b8bf878f752 100644 (file)
@@ -10,3 +10,4 @@ bone_aim1 0.4 spine4
 bone_aim2 0.35 bip01 r hand
 bone_weapon bip01 r hand
 fixbone 1
+hidden 1
index 44843b7058baf5ccd13a0e37c88694b99620f9a1..fbc6b672c39d97411a589b4165d5ef2fc0b43095 100644 (file)
@@ -1,4 +1,4 @@
-name Gak Masked
+name Gak
 species alien
 sex Male
 weight 87
index 2610d2b92db356797a22a0b52605efc304c05f41..4a35d9099e9daff55753fd47e1a2157bbaaa4f0f 100644 (file)
@@ -11,3 +11,4 @@ bone_aim2 0.2 upperarm_L
 bone_aim3 0.35 bip01 r hand
 bone_weapon bip01 r hand
 fixbone 1
+hidden 1
index c997d01f36488d7771766fe38956f883b8bcc9bc..76ca617ba11dde4fba964e2babdaf156df10f5ef 100644 (file)
@@ -10,3 +10,4 @@ bone_aim1 0.4 spine4
 bone_aim2 0.35 bip01 r hand
 bone_weapon bip01 r hand
 fixbone 1
+hidden 1
index feb9b871b0d9170ac4356bcec4480fc3212f3bf7..143b5c0e25d71a270007f14e8864b6a6ad99fd9d 100644 (file)
@@ -235,7 +235,6 @@ seta notification_INFO_ITEM_WEAPON_PRIMORSEC "0" "0 = off, 1 = print to console,
 seta notification_INFO_ITEM_WEAPON_UNAVAILABLE "0" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_JETPACK_NOFUEL "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_JOIN_CONNECT "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
-seta notification_INFO_JOIN_CONNECT_TEAM "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_JOIN_PLAY "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_JOIN_PLAY_TEAM "2" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
 seta notification_INFO_KEEPAWAY_DROPPED "1" "0 = off, 1 = print to console, 2 = print to console and chatbox (if notification_allow_chatboxprint is enabled)"
index 8ae771f1cf468a9ac21ec05d4b94cdc4e2782708..61354633d517a6b9d04acc7a0ec66f0fc0ef199f 100644 (file)
@@ -1,5 +1,5 @@
 g_mod_physics Xonotic
-// current Xonotic physics
+// Xonotic 0.7 physics
 
 sv_gravity 800
 sv_maxspeed 360
index 034bb6336680e7ead16421fcaf5fba0c8f78d69c..c4b1ec041126310346a099b3f6b87546097df94a 100644 (file)
@@ -43,7 +43,7 @@ void DrawDebugModel(entity this)
 
 void LocalCommand_blurtest(int request)
 {
-    TC(int, request);
+       TC(int, request);
        // Simple command to work with postprocessing temporarily... possibly completely pointless, the glsl shader is used for a real feature now...
        // Anyway, to enable it, just compile the client with -DBLURTEST and then you can use the command.
 
@@ -79,7 +79,7 @@ void LocalCommand_blurtest(int request)
 
 void LocalCommand_boxparticles(int request, int argc)
 {
-    TC(int, request); TC(int, argc);
+       TC(int, request); TC(int, argc);
        switch (request)
        {
                case CMD_REQUEST_COMMAND:
@@ -135,7 +135,7 @@ void LocalCommand_boxparticles(int request, int argc)
 
 void LocalCommand_create_scrshot_ent(int request)
 {
-    TC(int, request);
+       TC(int, request);
        switch (request)
        {
                case CMD_REQUEST_COMMAND:
@@ -175,7 +175,7 @@ void LocalCommand_create_scrshot_ent(int request)
 
 void LocalCommand_debugmodel(int request, int argc)
 {
-    TC(int, request); TC(int, argc);
+       TC(int, request); TC(int, argc);
        switch (request)
        {
                case CMD_REQUEST_COMMAND:
@@ -205,7 +205,7 @@ void LocalCommand_debugmodel(int request, int argc)
 
 void LocalCommand_handlevote(int request, int argc)
 {
-    TC(int, request); TC(int, argc);
+       TC(int, request); TC(int, argc);
        switch (request)
        {
                case CMD_REQUEST_COMMAND:
@@ -255,7 +255,7 @@ void LocalCommand_handlevote(int request, int argc)
 
 void LocalCommand_hud(int request, int argc)
 {
-    TC(int, request); TC(int, argc);
+       TC(int, request); TC(int, argc);
        switch (request)
        {
                case CMD_REQUEST_COMMAND:
@@ -325,7 +325,8 @@ void LocalCommand_hud(int request, int argc)
 
                                case "clickradar":
                                {
-                                       HUD_Radar_Show_Maximized(!hud_panel_radar_mouse, 1);
+                                       if(!isdemo())
+                                               HUD_Radar_Show_Maximized(!hud_panel_radar_mouse, 1);
                                        return;
                                }
                        }
@@ -350,7 +351,7 @@ void LocalCommand_hud(int request, int argc)
 
 void LocalCommand_localprint(int request, int argc)
 {
-    TC(int, request); TC(int, argc);
+       TC(int, request); TC(int, argc);
        switch (request)
        {
                case CMD_REQUEST_COMMAND:
@@ -377,7 +378,7 @@ void LocalCommand_localprint(int request, int argc)
 
 void LocalCommand_mv_download(int request, int argc)
 {
-    TC(int, request); TC(int, argc);
+       TC(int, request); TC(int, argc);
        switch (request)
        {
                case CMD_REQUEST_COMMAND:
@@ -404,7 +405,7 @@ void LocalCommand_mv_download(int request, int argc)
 
 void LocalCommand_sendcvar(int request, int argc)
 {
-    TC(int, request); TC(int, argc);
+       TC(int, request); TC(int, argc);
        switch (request)
        {
                case CMD_REQUEST_COMMAND:
index d8f6d26a33895e91fd40fb6a8d1b42e723de8575..035ba2a1647c29a2445ca54d73022670536cfed3 100644 (file)
@@ -362,7 +362,7 @@ void CSQCPlayer_AnimDecide_PostUpdate(entity this, bool isnew)
 }
 int CSQCPlayer_FallbackFrame(entity this, int f)
 {
-    TC(int, f);
+       TC(int, f);
        if(frameduration(this.modelindex, f) > 0)
                return f; // goooooood
        if(frameduration(this.modelindex, 1) <= 0)
index e26b4e2f5b890dc973897e1a980d95ffecce3503..9b5b4699337c971a0fbf2f4117dde2e75a1aa82a 100644 (file)
@@ -75,14 +75,14 @@ vector HUD_Get_Num_Color (float hp, float maxvalue)
 
 float HUD_GetRowCount(int item_count, vector size, float item_aspect)
 {
-    TC(int, item_count);
+       TC(int, item_count);
        float aspect = size_y / size_x;
        return bound(1, floor((sqrt(4 * item_aspect * aspect * item_count + aspect * aspect) + aspect + 0.5) / 2), item_count);
 }
 
 vector HUD_GetTableSize_BestItemAR(int item_count, vector psize, float item_aspect)
 {
-    TC(int, item_count);
+       TC(int, item_count);
        float columns, rows;
        float ratio, best_ratio = 0;
        float best_columns = 1, best_rows = 1;
@@ -180,7 +180,7 @@ void HUD_Panel_LoadCvars()
 //basically the same code of draw_ButtonPicture and draw_VertButtonPicture for the menu
 void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag)
 {
-    TC(bool, vertical); TC(int, drawflag);
+       TC(bool, vertical); TC(int, drawflag);
        if(!length_ratio || !theAlpha)
                return;
        if(length_ratio > 1)
@@ -287,7 +287,7 @@ void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, flo
 
 void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, int drawflag)
 {
-    TC(int, drawflag);
+       TC(int, drawflag);
        if(!theAlpha)
                return;
 
@@ -308,7 +308,7 @@ void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theA
 
 void DrawNumIcon_expanding(vector myPos, vector mySize, float theTime, string icon, bool vertical, int icon_right_align, vector color, float theAlpha, float fadelerp)
 {
-    TC(bool, vertical); TC(int, icon_right_align);
+       TC(bool, vertical); TC(int, icon_right_align);
        vector newPos = '0 0 0', newSize = '0 0 0';
        vector picpos, numpos;
 
@@ -388,7 +388,7 @@ void DrawNumIcon_expanding(vector myPos, vector mySize, float theTime, string ic
 
 void DrawNumIcon(vector myPos, vector mySize, float theTime, string icon, bool vertical, int icon_right_align, vector color, float theAlpha)
 {
-    TC(bool, vertical); TC(int, icon_right_align);
+       TC(bool, vertical); TC(int, icon_right_align);
        DrawNumIcon_expanding(myPos, mySize, theTime, icon, vertical, icon_right_align, color, theAlpha, 0);
 }
 
index 01ce50cdbb6f87e03291c9f57232dc683aff76c9..ce700586caad1efe174acea70a0a85f06b2a0ced 100644 (file)
@@ -22,7 +22,7 @@ void DrawNadeProgressBar(vector myPos, vector mySize, float progress, vector col
 
 void DrawAmmoItem(vector myPos, vector mySize, int ammoType, bool isCurrent, bool isInfinite)
 {
-    TC(bool, isCurrent); TC(bool, isInfinite);
+       TC(bool, isCurrent); TC(bool, isInfinite);
        if(ammoType == RESOURCE_NONE)
                return;
 
index f8f70c8189e671de3cb01fd3d4c4a8aab3e7745a..90a496e0d175962f8dae41d4f75beec0346010b9 100644 (file)
@@ -20,7 +20,7 @@ bool centerprint_showing;
 
 void centerprint_generic(int new_id, string strMessage, float duration, int countdown_num)
 {
-    TC(int, new_id); TC(int, countdown_num);
+       TC(int, new_id); TC(int, countdown_num);
        //printf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num);
        int i, j;
 
@@ -94,7 +94,7 @@ void centerprint_generic(int new_id, string strMessage, float duration, int coun
 
 void centerprint_kill(int id)
 {
-    TC(int, id);
+       TC(int, id);
        centerprint_generic(id, "", 0, 0);
 }
 
index 89b8a8c188b4a981774ed1c173b98e8215c62a78..87e4a7fb251af875266a9ea72c82cdd6449e1f91 100644 (file)
@@ -13,7 +13,7 @@ bool mod_active; // is there any active mod icon?
 
 void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
 {
-    TC(int, layout); TC(int, i);
+       TC(int, layout); TC(int, i);
        int stat = -1;
        string pic = "";
        vector color = '0 0 0';
@@ -626,7 +626,7 @@ void HUD_Mod_Race(vector pos, vector mySize)
 
 void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i)
 {
-    TC(int, layout); TC(int, i);
+       TC(int, layout); TC(int, i);
        float stat = -1;
        string pic = "";
        vector color = '0 0 0';
index dd574cf9b039c4b69d6654792a36525e7c54ba57..947bfd53b3ee1075063b72a489ece3b981811753 100644 (file)
@@ -47,7 +47,7 @@ void addPowerupItem(string name, string icon, vector color, float currentTime, f
 
 int getPowerupItemAlign(int align, int column, int row, int columns, int rows, bool isVertical)
 {
-    TC(int, align); TC(int, column); TC(int, row); TC(int, columns); TC(int, rows); TC(bool, isVertical);
+       TC(int, align); TC(int, column); TC(int, row); TC(int, columns); TC(int, rows); TC(bool, isVertical);
        if(align < 2)
                return align;
 
index a9029b25168394629ad4131dd0ddf33fd58bf0c9..02259f8ee04743acb56fdd359ca0582a5cf7b2af 100644 (file)
@@ -43,7 +43,7 @@ float QuickMenu_TimeOut;
 // if s1 is not empty s will be displayed as command otherwise as submenu
 void QuickMenu_Page_LoadEntry(int i, string s, string s1)
 {
-    TC(int, i);
+       TC(int, i);
        //LOG_INFOF("^xc80 entry %d: %s, %s\n", i, s, s1);
        strcpy(QuickMenu_Page_Description[i], s);
        strcpy(QuickMenu_Page_Command[i], s1);
@@ -51,7 +51,7 @@ void QuickMenu_Page_LoadEntry(int i, string s, string s1)
 
 void QuickMenu_Page_ClearEntry(int i)
 {
-    TC(int, i);
+       TC(int, i);
        strfree(QuickMenu_Page_Description[i]);
        strfree(QuickMenu_Page_Command[i]);
        QuickMenu_Page_Command_Type[i] = 0;
@@ -219,7 +219,7 @@ bool QuickMenu_IsOpened()
 
 bool HUD_Quickmenu_PlayerListEntries_Create(string cmd, int teamplayers, bool without_me)
 {
-    TC(int, teamplayers); TC(bool, without_me);
+       TC(int, teamplayers); TC(bool, without_me);
        int i;
        for(i = 0; i < QUICKMENU_MAXLINES; ++i)
                QuickMenu_Page_ClearEntry(i);
@@ -244,7 +244,7 @@ bool HUD_Quickmenu_PlayerListEntries_Create(string cmd, int teamplayers, bool wi
 int QuickMenu_Buffer_Index_Prev;
 bool QuickMenu_Page_Load(string target_submenu, bool new_page)
 {
-    TC(bool, new_page);
+       TC(bool, new_page);
        string s = string_null, cmd = string_null, z_submenu;
 
        if (new_page == 0)
@@ -355,7 +355,7 @@ bool QuickMenu_Page_Load(string target_submenu, bool new_page)
 
 bool QuickMenu_ActionForNumber(int num)
 {
-    TC(int, num);
+       TC(int, num);
        if (!QuickMenu_IsLastPage)
        {
                if (num < 0 || num >= QUICKMENU_MAXLINES)
@@ -383,7 +383,7 @@ bool QuickMenu_ActionForNumber(int num)
 
 void QuickMenu_Page_ActiveEntry(int entry_num)
 {
-    TC(int, entry_num);
+       TC(int, entry_num);
        QuickMenu_Page_ActivatedEntry = entry_num;
        QuickMenu_Page_ActivatedEntry_Time = time + 0.1;
        if(QuickMenu_Page_Command[QuickMenu_Page_ActivatedEntry])
@@ -401,7 +401,7 @@ void QuickMenu_Page_ActiveEntry(int entry_num)
 
 bool QuickMenu_InputEvent(int bInputType, float nPrimary, float nSecondary)
 {
-    TC(int, bInputType);
+       TC(int, bInputType);
        // we only care for keyboard events
        if(bInputType == 2)
                return false;
@@ -735,7 +735,7 @@ void HUD_QuickMenu()
 
 void HUD_Quickmenu_PlayerListEntries(string cmd, int teamplayers, bool without_me)
 {
-    TC(int, teamplayers); TC(bool, without_me);
+       TC(int, teamplayers); TC(bool, without_me);
        entity pl;
        if(teamplayers && !team_count)
                return;
index 2f0777bb1f481893c9fe146b31dc1ed92f0788b4..9176aa0ff99782b05ed207495bacf5134675ff4c 100644 (file)
@@ -19,7 +19,7 @@ bool HUD_Radar_Clickable()
 
 void HUD_Radar_Show_Maximized(bool doshow, bool clickable)
 {
-    TC(bool, doshow);
+       TC(bool, doshow);
        hud_panel_radar_maximized = doshow;
        hud_panel_radar_temp_hidden = 0;
 
@@ -51,7 +51,7 @@ void HUD_Radar_Hide_Maximized()
 
 float HUD_Radar_InputEvent(int bInputType, float nPrimary, float nSecondary)
 {
-    TC(int, bInputType);
+       TC(int, bInputType);
        if(!hud_panel_radar_maximized || !hud_panel_radar_mouse ||
                autocvar__hud_configure || mv_active)
                return false;
index 91d9f6f70d9757635c97ffe4136d504e325925dd..32ccccfca3355dedfa235c20e96f316ee61ed2b4 100644 (file)
@@ -175,7 +175,7 @@ void Scoreboard_UpdatePlayerTeams()
 
 int Scoreboard_CompareScore(int vl, int vr, int f)
 {
-    TC(int, vl); TC(int, vr); TC(int, f);
+       TC(int, vl); TC(int, vr); TC(int, f);
        if(f & SFL_ZERO_IS_WORST)
        {
                if(vl == 0 && vr != 0)
@@ -381,7 +381,7 @@ void Cmd_Scoreboard_Help()
 
 void Cmd_Scoreboard_SetFields(int argc)
 {
-    TC(int, argc);
+       TC(int, argc);
        int i, slash;
        string str, pattern;
        bool have_name = false, have_primary = false, have_secondary = false, have_separator = false;
@@ -716,7 +716,7 @@ float sbt_fixcolumnwidth_marginlen;
 
 string Scoreboard_FixColumnWidth(int i, string str)
 {
-    TC(int, i);
+       TC(int, i);
        float f;
        vector sz;
 
@@ -840,7 +840,7 @@ vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players)
 
 void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, int pl_number)
 {
-    TC(bool, is_self); TC(int, pl_number);
+       TC(bool, is_self); TC(int, pl_number);
        string str;
        bool is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR);
 
index 5d75c7dd2a4182fe19d9a4ec67d2940a3d877174..8bf11cf1ac93d3994840bb64b96bac5ce993317d 100644 (file)
@@ -11,7 +11,7 @@
 entity weaponorder[Weapons_MAX];
 void weaponorder_swap(int i, int j, entity pass)
 {
-    TC(int, i); TC(int, j);
+       TC(int, i); TC(int, j);
        entity h = weaponorder[i];
        weaponorder[i] = weaponorder[j];
        weaponorder[j] = h;
@@ -20,7 +20,7 @@ void weaponorder_swap(int i, int j, entity pass)
 string weaponorder_cmp_str;
 int weaponorder_cmp(int i, int j, entity pass)
 {
-    TC(int, i); TC(int, j);
+       TC(int, i); TC(int, j);
        int ai = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[i].m_id), 0);
        int aj = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[j].m_id), 0);
        return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string)
index 3a6d60742fb80ec78844047ff09048745195f78a..df13ca7f62fad43879b6ba209b78153d2e4cc9b9 100644 (file)
@@ -230,7 +230,7 @@ void Shutdown()
 .float has_team;
 float SetTeam(entity o, int Team)
 {
-    TC(int, Team);
+       TC(int, Team);
        devassert_once(Team);
        entity tm;
        if(teamplay)
index 8d4d8ba9f6b8900d7e156d1580302bb188e29817..37cb59e082101f645ac197f6c224c12715f62bfd 100644 (file)
@@ -43,7 +43,7 @@ int n_ssdirs;
 
 string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, vector fontsize)
 {
-    TC(int, id);
+       TC(int, id);
        string pre, post;
        pre = sprintf("%d. ", id+1);
        if(mv_detail)
@@ -64,7 +64,7 @@ string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, v
 
 vector MapVote_RGB(int id)
 {
-    TC(int, id);
+       TC(int, id);
        if(!(mv_flags[id] & GTV_AVAILABLE))
                return '1 1 1';
        if(id == mv_ownvote)
@@ -77,7 +77,7 @@ vector MapVote_RGB(int id)
 
 void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float _count, int id)
 {
-    TC(int, id);
+       TC(int, id);
        // Find the correct alpha
        float alpha;
        if(!(mv_flags_start[id] & GTV_AVAILABLE))
@@ -189,7 +189,7 @@ void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string g
 
 void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float _count, int id)
 {
-    TC(int, id);
+       TC(int, id);
        vector img_size = '0 0 0';
        string label;
        float text_size;
@@ -264,7 +264,7 @@ void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, strin
 
 void MapVote_DrawAbstain(vector pos, float isize, float tsize, float _count, int id)
 {
-    TC(int, id);
+       TC(int, id);
        vector rgb;
        float text_size;
        string label;
@@ -281,7 +281,7 @@ void MapVote_DrawAbstain(vector pos, float isize, float tsize, float _count, int
 
 vector MapVote_GridVec(vector gridspec, int i, int m)
 {
-    TC(int, i); TC(int, m);
+       TC(int, i); TC(int, m);
        int r = i % m;
        return
                '1 0 0' * (gridspec.x * r)
@@ -491,7 +491,7 @@ void MapVote_Draw()
 
 void Cmd_MapVote_MapDownload(int argc)
 {
-    TC(int, argc);
+       TC(int, argc);
        entity pak;
 
        if(argc != 2 || !mv_pk3list)
@@ -522,7 +522,7 @@ void Cmd_MapVote_MapDownload(int argc)
 
 void MapVote_CheckPK3(string pic, string pk3, int id)
 {
-    TC(int, id);
+       TC(int, id);
        entity pak;
        pak = spawn();
        pak.netname = pk3;
@@ -544,7 +544,7 @@ void MapVote_CheckPK3(string pic, string pk3, int id)
 
 void MapVote_CheckPic(string pic, string pk3, int id)
 {
-    TC(int, id);
+       TC(int, id);
        // never try to retrieve a pic for the "don't care" 'map'
        if(mv_abstain && id == mv_num_maps - 1)
                return;
@@ -587,7 +587,7 @@ void MapVote_ReadMask()
 
 void MapVote_ReadOption(int i)
 {
-    TC(int, i);
+       TC(int, i);
        string map = strzone(ReadString());
        string pk3 = strzone(ReadString());
        int j = bound(0, ReadByte(), n_ssdirs - 1);
@@ -604,7 +604,7 @@ void MapVote_ReadOption(int i)
 
 void GameTypeVote_ReadOption(int i)
 {
-    TC(int, i);
+       TC(int, i);
        string gt = strzone(ReadString());
 
        mv_maps[i] = gt;
@@ -710,13 +710,13 @@ void MapVote_Init()
 
 void MapVote_SendChoice(int index)
 {
-    TC(int, index);
+       TC(int, index);
        localcmd(strcat("\nimpulse ", ftos(index+1), "\n"));
 }
 
 int MapVote_MoveLeft(int pos)
 {
-    TC(int, pos);
+       TC(int, pos);
        int imp;
        if ( pos < 0 )
                imp = mv_num_maps - 1;
@@ -728,7 +728,7 @@ int MapVote_MoveLeft(int pos)
 }
 int MapVote_MoveRight(int pos)
 {
-    TC(int, pos);
+       TC(int, pos);
        int imp;
        if ( pos < 0 )
                imp = 0;
@@ -740,7 +740,7 @@ int MapVote_MoveRight(int pos)
 }
 int MapVote_MoveUp(int pos)
 {
-    TC(int, pos);
+       TC(int, pos);
        int imp;
        if ( pos < 0 )
                imp = mv_num_maps - 1;
@@ -760,7 +760,7 @@ int MapVote_MoveUp(int pos)
 }
 int MapVote_MoveDown(int pos)
 {
-    TC(int, pos);
+       TC(int, pos);
        int imp;
        if ( pos < 0 )
                imp = 0;
@@ -777,7 +777,7 @@ int MapVote_MoveDown(int pos)
 
 float MapVote_InputEvent(int bInputType, float nPrimary, float nSecondary)
 {
-    TC(int, bInputType);
+       TC(int, bInputType);
        float imp;
 
        if (!mv_active)
index 01409280a4a4c9f535cf18e6c0f7f21b2eb1d8b0..360305601a8b71cfdd345436f213f9eafb5e50ee 100644 (file)
@@ -121,7 +121,7 @@ void RemoveTeam(entity Team)
 
 entity GetTeam(int Team, bool add)
 {
-    TC(int, Team); TC(bool, add);
+       TC(int, Team); TC(bool, add);
        int num = (Team == NUM_SPECTATOR) ? 16 : Team;
        if(teamslots[num])
                return teamslots[num];
@@ -553,7 +553,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector
 /** engine callback */
 void URI_Get_Callback(int id, int status, string data)
 {
-    TC(int, id); TC(int, status);
+       TC(int, id); TC(int, status);
        if(url_URI_Get_Callback(id, status, data))
        {
                // handled
index bb1b6f919b840c78a2bca6d339245e5b057acbc1..d9c9ab14210353a5490d4e9dc5deadde59763577 100644 (file)
@@ -83,7 +83,7 @@ void skeleton_markbones(entity e)
 
 void skel_set_boneabs(float s, int bone, vector absorg)
 {
-    TC(int, bone);
+       TC(int, bone);
        vector absang = fixedvectoangles2(v_forward, v_up);
 
        vector parentorg = skel_get_boneabs(s, skel_get_boneparent(s, bone));
@@ -113,7 +113,7 @@ void free_skeleton_from_frames(entity e)
 
 void skeleton_from_frames(entity e, bool is_dead)
 {
-    TC(bool, is_dead);
+       TC(bool, is_dead);
        float m = e.modelindex;
        if(!e.skeletonindex)
        {
index c5f1c2fb4b1468b1b50bf997f366987ce675c83f..5d40dbe04eeefb986630eb8c0dc0c8e5c09bf712 100644 (file)
@@ -149,7 +149,7 @@ void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb,
 
 void draw_teamradar_link(vector start, vector end, int colors)
 {
-    TC(int, colors);
+       TC(int, colors);
        vector c0, c1, norm;
 
        start = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(start));
index 3a5f1b5e766dd8145ccdae954c3a8cae1b001818..27fa344b39cfa437321a303cfe3f732071e4caac 100644 (file)
@@ -491,9 +491,8 @@ vector GetCurrentFov(float fov)
        if(zoomfactor < 1 || zoomfactor > 30)
                zoomfactor = 2.5;
        zoomspeed = autocvar_cl_zoomspeed;
-       if(zoomspeed >= 0)
-       if(zoomspeed < 0.5 || zoomspeed > 16)
-                       zoomspeed = 3.5;
+       if (zoomspeed >= 0 && (zoomspeed < 0.5 || zoomspeed > 16))
+               zoomspeed = 3.5;
 
        zoomdir = button_zoom;
 
@@ -526,7 +525,11 @@ vector GetCurrentFov(float fov)
 
        if(zoomdir) { zoomin_effect = 0; }
 
-       if(camera_active)
+       if (spectatee_status > 0 && STAT(CAMERA_SPECTATOR) == 2)
+       {
+               current_viewzoom = 1;
+       }
+       else if (camera_active)
        {
                current_viewzoom = min(1, current_viewzoom + drawframetime);
        }
@@ -570,10 +573,10 @@ vector GetCurrentFov(float fov)
 
        if(autocvar_cl_velocityzoom_enabled && autocvar_cl_velocityzoom_type) // _type = 0 disables velocity zoom too
        {
-               if(intermission) { curspeed = 0; }
+               if (intermission || (spectatee_status > 0 && STAT(CAMERA_SPECTATOR) == 2))
+                       curspeed = 0;
                else
                {
-
                        makevectors(view_angles);
                        v = pmove_vel;
                        if(csqcplayer)
@@ -1611,7 +1614,7 @@ int lasthud;
 float vh_notice_time;
 void CSQC_UpdateView(entity this, float w, float h)
 {
-    TC(int, w); TC(int, h);
+       TC(int, w); TC(int, h);
        entity e;
        float fov;
        float f;
index 41b97694496616fa4de17b8f73aa2c163cb2fa6d..f4871e7fc6194803adf7fa2a8b9ec1276abc06c3 100644 (file)
@@ -171,7 +171,7 @@ void Projectile_Draw(entity this)
 
 void loopsound(entity e, int ch, Sound samp, float vol, float attn)
 {
-    TC(int, ch);
+       TC(int, ch);
        if (e.silent)
                return;
 
index bc26203399bf44aace75bcff27b303f2caa738b0..4f099b53301010a383b9efaa5a27d9e2e5ceebaf 100644 (file)
@@ -52,8 +52,6 @@ float CampaignFile_Load(int offset, float n)
                a = ""; \
        else \
                ++i
-// What you're seeing here is what people will do when your compiler supports
-// C-style macros but no line continuations.
 
                                i = -1; // starts at -1 so I don't need postincrement; that is, i points to BEFORE the current arg!
                                CAMPAIGN_GETARG; campaign_gametype[campaign_entries] = strzone(a);
index 349d492da82b4169113ecde8989e764f06690f22..26308b89db807514f60b36ea236b14ccbc32fd9c 100644 (file)
@@ -8,6 +8,6 @@ CLASS(Command, Object)
        ATTRIB(Command, m_description, string);
        METHOD(Command, m_invokecmd, void(Command this, int request, entity caller, int arguments, string command))
        {
-        TC(Command, this);
+               TC(Command, this);
        }
 ENDCLASS(Command)
index c58a3df75a50d83e55731bc5955020f999781007..6a05d01f18519bce89c5e4b1c9a155daa1ec2708 100644 (file)
@@ -169,7 +169,7 @@ void GenericCommand_qc_curl(float request, float argc)
        }
 }
 
-GENERIC_COMMAND(dumpcommands, "Dump all commands on the program to *_cmd_dump.txt")
+GENERIC_COMMAND(dumpcommands, "Dump all commands on the program to <program>_cmd_dump.txt")
 {
        switch(request)
        {
@@ -184,23 +184,28 @@ GENERIC_COMMAND(dumpcommands, "Dump all commands on the program to *_cmd_dump.tx
                                #ifdef SVQC
                                        CMD_Write("dump of server console commands:\n");
                                        GameCommand_macro_write_aliases(fh);
+                                       CMD_Write("\n");
 
-                                       CMD_Write("\ndump of networked client only commands:\n");
+                                       CMD_Write("dump of networked client only commands:\n");
                                        ClientCommand_macro_write_aliases(fh);
+                                       CMD_Write("\n");
 
-                                       CMD_Write("\ndump of common commands:\n");
+                                       CMD_Write("dump of common commands:\n");
                                        CommonCommand_macro_write_aliases(fh);
+                                       CMD_Write("\n");
 
-                                       CMD_Write("\ndump of ban commands:\n");
+                                       CMD_Write("dump of ban commands:\n");
                                        BanCommand_macro_write_aliases(fh);
+                                       CMD_Write("\n");
                                #endif
 
                                #ifdef CSQC
                                        CMD_Write("dump of client commands:\n");
                                        LocalCommand_macro_write_aliases(fh);
+                                       CMD_Write("\n");
                                #endif
 
-                               CMD_Write("\ndump of generic commands:\n");
+                               CMD_Write("dump of generic commands:\n");
                                GenericCommand_macro_write_aliases(fh);
 
                                LOG_INFO("Completed dump of aliases in ^2data/data/", GetProgramCommandPrefix(), "_dump.txt^7.");
index 6439a49bb21ce32c6c64bbc8814f37dbb8f5520d..3b534ab781d0f7d8a4614a4534fe4f208a28899d 100644 (file)
@@ -258,6 +258,6 @@ entity EFFECT_ROCKETMINSTA_LASER(int teamid)
         case NUM_TEAM_4:    e = EFFECT_ROCKETMINSTA_LASER_PINK; break;
         default:            e = EFFECT_ROCKETMINSTA_LASER_NEUTRAL; break;
     }
-    if (particleeffectnum(e) < 0 || Team_TeamToNumber(teamid) == -1) { e = EFFECT_TR_NEXUIZPLASMA; }
+    if (particleeffectnum(e) < 0 || !Team_IsValidTeam(teamid)) { e = EFFECT_TR_NEXUIZPLASMA; }
     return e;
 }
index 9a2d6af1d86f4efbfb300b774d22f0ed6b9dae06..e7134182e497b95facf46c75d680bc5079dd7348 100644 (file)
@@ -31,7 +31,8 @@ void assault_objective_use(entity this, entity actor, entity trigger)
 
 vector target_objective_spawn_evalfunc(entity this, entity player, entity spot, vector current)
 {
-       if(GetResourceAmount(this, RESOURCE_HEALTH) < 0 || GetResourceAmount(this, RESOURCE_HEALTH) >= ASSAULT_VALUE_INACTIVE)
+       float hlth = GetResourceAmount(this, RESOURCE_HEALTH);
+       if (hlth < 0 || hlth >= ASSAULT_VALUE_INACTIVE)
                return '-1 0 0';
        return current;
 }
@@ -61,16 +62,17 @@ void assault_objective_decrease_use(entity this, entity actor, entity trigger)
        else
                return; // already activated! cannot activate again!
 
-       if(GetResourceAmount(this.enemy, RESOURCE_HEALTH) < ASSAULT_VALUE_INACTIVE)
+       float hlth = GetResourceAmount(this.enemy, RESOURCE_HEALTH);
+       if (hlth < ASSAULT_VALUE_INACTIVE)
        {
-               if(GetResourceAmount(this.enemy, RESOURCE_HEALTH) - this.dmg > 0.5)
+               if (hlth - this.dmg > 0.5)
                {
                        GameRules_scoring_add_team(actor, SCORE, this.dmg);
                        TakeResource(this.enemy, RESOURCE_HEALTH, this.dmg);
                }
                else
                {
-                       GameRules_scoring_add_team(actor, SCORE, GetResourceAmount(this.enemy, RESOURCE_HEALTH));
+                       GameRules_scoring_add_team(actor, SCORE, hlth);
                        GameRules_scoring_add_team(actor, ASSAULT_OBJECTIVES, 1);
                        SetResourceAmountExplicit(this.enemy, RESOURCE_HEALTH, -1);
 
@@ -334,7 +336,8 @@ spawnfunc(target_objective_decrease)
 bool destructible_heal(entity targ, entity inflictor, float amount, float limit)
 {
        float true_limit = ((limit != RESOURCE_LIMIT_NONE) ? limit : targ.max_health);
-       if(GetResourceAmount(targ, RESOURCE_HEALTH) <= 0 || GetResourceAmount(targ, RESOURCE_HEALTH) >= true_limit)
+       float hlth = GetResourceAmount(targ, RESOURCE_HEALTH);
+       if (hlth <= 0 || hlth >= true_limit)
                return false;
 
        GiveResourceWithLimit(targ, RESOURCE_HEALTH, amount, true_limit);
@@ -411,7 +414,8 @@ void havocbot_goalrating_ast_targets(entity this, float ratingscale)
                entity destr = it;
                IL_EACH(g_assault_objectivedecreasers, it.targetname == destr.target,
                {
-                       if(GetResourceAmount(it.enemy, RESOURCE_HEALTH) > 0 && GetResourceAmount(it.enemy, RESOURCE_HEALTH) < ASSAULT_VALUE_INACTIVE)
+                       float hlth = GetResourceAmount(it.enemy, RESOURCE_HEALTH);
+                       if (hlth > 0 && hlth < ASSAULT_VALUE_INACTIVE)
                        {
                                found = true;
                                break;
@@ -602,10 +606,10 @@ MUTATOR_HOOKFUNCTION(as, PlayHitsound)
        return (frag_victim.classname == "func_assault_destructible");
 }
 
-MUTATOR_HOOKFUNCTION(as, CheckAllowedTeams)
+MUTATOR_HOOKFUNCTION(as, TeamBalance_CheckAllowedTeams)
 {
        // assault always has 2 teams
-       c1 = c2 = 0;
+       M_ARGV(0, float) = BIT(0) | BIT(1);
        return true;
 }
 
index f4aea4357ddfc3fecd65e3feabafda49890c72e1..a81a23a51cef6363a1b219a49206806fb096fc34 100644 (file)
@@ -7,53 +7,64 @@ bool autocvar_g_ca_spectate_enemies;
 
 void CA_count_alive_players()
 {
-       total_players = redalive = bluealive = yellowalive = pinkalive = 0;
-       FOREACH_CLIENT(IS_PLAYER(it), {
-               switch(it.team)
+       total_players = 0;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               Team_SetNumberOfAlivePlayers(Team_GetTeamFromIndex(i), 0);
+       }
+       FOREACH_CLIENT(IS_PLAYER(it) && Entity_HasValidTeam(it),
+       {
+               ++total_players;
+               if (IS_DEAD(it))
                {
-                       case NUM_TEAM_1: ++total_players; if(!IS_DEAD(it)) ++redalive; break;
-                       case NUM_TEAM_2: ++total_players; if(!IS_DEAD(it)) ++bluealive; break;
-                       case NUM_TEAM_3: ++total_players; if(!IS_DEAD(it)) ++yellowalive; break;
-                       case NUM_TEAM_4: ++total_players; if(!IS_DEAD(it)) ++pinkalive; break;
+                       continue;
                }
+               entity team_ = Entity_GetTeam(it);
+               int num_alive = Team_GetNumberOfAlivePlayers(team_);
+               ++num_alive;
+               Team_SetNumberOfAlivePlayers(team_, num_alive);
        });
-       FOREACH_CLIENT(IS_REAL_CLIENT(it), {
-               STAT(REDALIVE, it) = redalive;
-               STAT(BLUEALIVE, it) = bluealive;
-               STAT(YELLOWALIVE, it) = yellowalive;
-               STAT(PINKALIVE, it) = pinkalive;
+       FOREACH_CLIENT(IS_REAL_CLIENT(it),
+       {
+               STAT(REDALIVE, it) = Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(
+                       1));
+               STAT(BLUEALIVE, it) = Team_GetNumberOfAlivePlayers(
+                       Team_GetTeamFromIndex(2));
+               STAT(YELLOWALIVE, it) = Team_GetNumberOfAlivePlayers(
+                       Team_GetTeamFromIndex(3));
+               STAT(PINKALIVE, it) = Team_GetNumberOfAlivePlayers(
+                       Team_GetTeamFromIndex(4));
        });
 }
 
-float CA_GetWinnerTeam()
+int CA_GetWinnerTeam()
 {
-       float winner_team = 0;
-       if(redalive >= 1)
-               winner_team = NUM_TEAM_1;
-       if(bluealive >= 1)
+       int winner_team = 0;
+       if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(1)) >= 1)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_2;
+               winner_team = NUM_TEAM_1;
        }
-       if(yellowalive >= 1)
+       for (int i = 2; i <= NUM_TEAMS; ++i)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_3;
+               if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) >= 1)
+               {
+                       if (winner_team != 0)
+                       {
+                               return 0;
+                       }
+                       winner_team = Team_IndexToTeam(i);
+               }
        }
-       if(pinkalive >= 1)
+       if (winner_team)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_4;
-       }
-       if(winner_team)
                return winner_team;
+       }
        return -1; // no player left
 }
 
 void nades_Clear(entity player);
 
-#define CA_ALIVE_TEAMS() ((redalive > 0) + (bluealive > 0) + (yellowalive > 0) + (pinkalive > 0))
-#define CA_ALIVE_TEAMS_OK() (CA_ALIVE_TEAMS() == NumTeams(ca_teams))
+#define CA_ALIVE_TEAMS_OK() (Team_GetNumberOfAliveTeams() == NumTeams(ca_teams))
 float CA_CheckWinner()
 {
        if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0)
@@ -69,8 +80,10 @@ float CA_CheckWinner()
        }
 
        CA_count_alive_players();
-       if(CA_ALIVE_TEAMS() > 1)
+       if (Team_GetNumberOfAliveTeams() > 1)
+       {
                return 0;
+       }
 
        int winner_team = CA_GetWinnerTeam();
        if(winner_team > 0)
@@ -119,14 +132,14 @@ bool CA_CheckTeams()
                return false;
        }
        int missing_teams_mask = 0;
-       if(ca_teams & BIT(0))
-               missing_teams_mask += (!redalive) * 1;
-       if(ca_teams & BIT(1))
-               missing_teams_mask += (!bluealive) * 2;
-       if(ca_teams & BIT(2))
-               missing_teams_mask += (!yellowalive) * 4;
-       if(ca_teams & BIT(3))
-               missing_teams_mask += (!pinkalive) * 8;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               if ((ca_teams & Team_IndexToBit(i)) &&
+                       (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) == 0))
+               {
+                       missing_teams_mask |= Team_IndexToBit(i);
+               }
+       }
        if(prev_missing_teams_mask != missing_teams_mask)
        {
                Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_MISSING_TEAMS, missing_teams_mask);
@@ -232,9 +245,10 @@ MUTATOR_HOOKFUNCTION(ca, reset_map_global)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ca, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(ca, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = ca_teams;
+       return true;
 }
 
 entity ca_LastPlayerForTeam(entity this)
index 3f96b41142f162360dac01cf770a52b24391653f..812d5da4ec0321625d09484e9f38daee27533a57 100644 (file)
@@ -2466,11 +2466,9 @@ MUTATOR_HOOKFUNCTION(ctf, HavocBot_ChooseRole)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ctf, CheckAllowedTeams)
+MUTATOR_HOOKFUNCTION(ctf, TeamBalance_CheckAllowedTeams)
 {
-       //M_ARGV(0, float) = ctf_teams;
        M_ARGV(1, string) = "ctf_team";
-       return true;
 }
 
 MUTATOR_HOOKFUNCTION(ctf, SpectateCopy)
@@ -2696,7 +2694,6 @@ spawnfunc(team_CTL_bluelolly)  { spawnfunc_item_flag_team2(this);    }
 // scoreboard setup
 void ctf_ScoreRules(int teams)
 {
-       CheckAllowedTeams(NULL);
        GameRules_scoring(teams, SFL_SORT_PRIO_PRIMARY, 0, {
         field_team(ST_CTF_CAPS, "caps", SFL_SORT_PRIO_PRIMARY);
         field(SP_CTF_CAPS, "caps", SFL_SORT_PRIO_SECONDARY);
index 24a82208cb30c80fc036b5960559906562e59c69..0cea02f2f2aef7325b0c7dc64a5bf13c1573cea2 100644 (file)
@@ -297,47 +297,55 @@ void dom_controlpoint_setup(entity this)
        WaypointSprite_SpawnFixed(WP_DomNeut, this.origin + '0 0 32', this, sprite, RADARICON_DOMPOINT);
 }
 
-float total_controlpoints;
+int total_control_points;
 void Domination_count_controlpoints()
 {
-       total_controlpoints = redowned = blueowned = yellowowned = pinkowned = 0;
+       total_control_points = 0;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               Team_SetNumberOfControlPoints(Team_GetTeamFromIndex(i), 0);
+       }
        IL_EACH(g_dompoints, true,
        {
-               ++total_controlpoints;
-               redowned += (it.goalentity.team == NUM_TEAM_1);
-               blueowned += (it.goalentity.team == NUM_TEAM_2);
-               yellowowned += (it.goalentity.team == NUM_TEAM_3);
-               pinkowned += (it.goalentity.team == NUM_TEAM_4);
+               ++total_control_points;
+               if (!Entity_HasValidTeam(it.goalentity))
+               {
+                       continue;
+               }
+               entity team_ = Entity_GetTeam(it.goalentity);
+               int num_control_points = Team_GetNumberOfControlPoints(team_);
+               ++num_control_points;
+               Team_SetNumberOfControlPoints(team_, num_control_points);
        });
 }
 
-float Domination_GetWinnerTeam()
+int Domination_GetWinnerTeam()
 {
-       float winner_team = 0;
-       if(redowned == total_controlpoints)
-               winner_team = NUM_TEAM_1;
-       if(blueowned == total_controlpoints)
+       int winner_team = 0;
+       if (Team_GetNumberOfControlPoints(Team_GetTeamFromIndex(1)) ==
+               total_control_points)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_2;
+               winner_team = NUM_TEAM_1;
        }
-       if(yellowowned == total_controlpoints)
+       for (int i = 2; i <= NUM_TEAMS; ++i)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_3;
+               if (Team_GetNumberOfControlPoints(Team_GetTeamFromIndex(i)) ==
+                       total_control_points)
+               {
+                       if (winner_team != 0)
+                       {
+                               return 0;
+                       }
+                       winner_team = Team_IndexToTeam(i);
+               }
        }
-       if(pinkowned == total_controlpoints)
+       if (winner_team)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_4;
-       }
-       if(winner_team)
                return winner_team;
+       }
        return -1; // no control points left?
 }
 
-#define DOM_OWNED_CONTROLPOINTS() ((redowned > 0) + (blueowned > 0) + (yellowowned > 0) + (pinkowned > 0))
-#define DOM_OWNED_CONTROLPOINTS_OK() (DOM_OWNED_CONTROLPOINTS() < total_controlpoints)
 float Domination_CheckWinner()
 {
        if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0)
@@ -417,7 +425,7 @@ void havocbot_role_dom(entity this)
        }
 }
 
-MUTATOR_HOOKFUNCTION(dom, CheckAllowedTeams)
+MUTATOR_HOOKFUNCTION(dom, TeamBalance_CheckAllowedTeams)
 {
        // fallback?
        M_ARGV(0, float) = domination_teams;
@@ -428,12 +436,9 @@ MUTATOR_HOOKFUNCTION(dom, CheckAllowedTeams)
        {
                if(head.netname != "")
                {
-                       switch(head.team)
+                       if (Team_IsValidTeam(head.team))
                        {
-                               case NUM_TEAM_1: c1 = 0; break;
-                               case NUM_TEAM_2: c2 = 0; break;
-                               case NUM_TEAM_3: c3 = 0; break;
-                               case NUM_TEAM_4: c4 = 0; break;
+                               M_ARGV(0, float) |= Team_TeamToBit(head.team);
                        }
                }
 
@@ -584,10 +589,10 @@ void ScoreRules_dom(int teams)
 }
 
 // code from here on is just to support maps that don't have control point and team entities
-void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, Sound capsound, string capnarration, string capmessage)
+void dom_spawnteam(string teamname, float teamcolor, string pointmodel, float pointskin, Sound capsound, string capnarration, string capmessage)
 {
-    TC(Sound, capsound);
-    entity e = new_pure(dom_team);
+       TC(Sound, capsound);
+       entity e = new_pure(dom_team);
        e.netname = strzone(teamname);
        e.cnt = teamcolor;
        e.model = pointmodel;
@@ -621,7 +626,7 @@ void dom_spawnpoint(vector org)
 // spawn some default teams if the map is not set up for domination
 void dom_spawnteams(int teams)
 {
-    TC(int, teams);
+       TC(int, teams);
        dom_spawnteam(Team_ColoredFullName(NUM_TEAM_1), NUM_TEAM_1-1, "models/domination/dom_red.md3", 0, SND_DOM_CLAIM, "", "Red team has captured a control point");
        dom_spawnteam(Team_ColoredFullName(NUM_TEAM_2), NUM_TEAM_2-1, "models/domination/dom_blue.md3", 0, SND_DOM_CLAIM, "", "Blue team has captured a control point");
        if(teams >= 3)
@@ -644,14 +649,9 @@ void dom_DelayedInit(entity this) // Do this check with a delay so we can wait f
                dom_spawnteams(domination_teams);
        }
 
-       CheckAllowedTeams(NULL);
-       //domination_teams = ((c4>=0) ? 4 : (c3>=0) ? 3 : 2);
-
-       int teams = 0;
-       if(c1 >= 0) teams |= BIT(0);
-       if(c2 >= 0) teams |= BIT(1);
-       if(c3 >= 0) teams |= BIT(2);
-       if(c4 >= 0) teams |= BIT(3);
+       entity balance = TeamBalance_CheckAllowedTeams(NULL);
+       int teams = TeamBalance_GetAllowedTeams(balance);
+       TeamBalance_Destroy(balance);
        domination_teams = teams;
 
        domination_roundbased = autocvar_g_domination_roundbased;
index 9c508320922aa9285cd7d76f52751b841c63a382..15726ada31d03b5442b12e15e175d34533af9768 100644 (file)
@@ -2,6 +2,7 @@
 
 // TODO: sv_freezetag
 #ifdef SVQC
+
 #include <server/resources.qh>
 
 float autocvar_g_freezetag_frozen_maxtime;
@@ -13,27 +14,40 @@ float autocvar_g_freezetag_warmup;
 
 void freezetag_count_alive_players()
 {
-       total_players = redalive = bluealive = yellowalive = pinkalive = 0;
-       FOREACH_CLIENT(IS_PLAYER(it), {
-               switch(it.team)
+       total_players = 0;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               Team_SetNumberOfAlivePlayers(Team_GetTeamFromIndex(i), 0);
+       }
+       FOREACH_CLIENT(IS_PLAYER(it) && Entity_HasValidTeam(it),
+       {
+               ++total_players;
+               if ((GetResourceAmount(it, RESOURCE_HEALTH) < 1) ||
+                       (STAT(FROZEN, it) == 1))
                {
-                       case NUM_TEAM_1: ++total_players; if(GetResourceAmount(it, RESOURCE_HEALTH) >= 1 && STAT(FROZEN, it) != 1) ++redalive; break;
-                       case NUM_TEAM_2: ++total_players; if(GetResourceAmount(it, RESOURCE_HEALTH) >= 1 && STAT(FROZEN, it) != 1) ++bluealive; break;
-                       case NUM_TEAM_3: ++total_players; if(GetResourceAmount(it, RESOURCE_HEALTH) >= 1 && STAT(FROZEN, it) != 1) ++yellowalive; break;
-                       case NUM_TEAM_4: ++total_players; if(GetResourceAmount(it, RESOURCE_HEALTH) >= 1 && STAT(FROZEN, it) != 1) ++pinkalive; break;
+                       continue;
                }
+               entity team_ = Entity_GetTeam(it);
+               int num_alive = Team_GetNumberOfAlivePlayers(team_);
+               ++num_alive;
+               Team_SetNumberOfAlivePlayers(team_, num_alive);
        });
-       FOREACH_CLIENT(IS_REAL_CLIENT(it), {
-               STAT(REDALIVE, it) = redalive;
-               STAT(BLUEALIVE, it) = bluealive;
-               STAT(YELLOWALIVE, it) = yellowalive;
-               STAT(PINKALIVE, it) = pinkalive;
+       FOREACH_CLIENT(IS_REAL_CLIENT(it),
+       {
+               STAT(REDALIVE, it) = Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(
+                       1));
+               STAT(BLUEALIVE, it) = Team_GetNumberOfAlivePlayers(
+                       Team_GetTeamFromIndex(2));
+               STAT(YELLOWALIVE, it) = Team_GetNumberOfAlivePlayers(
+                       Team_GetTeamFromIndex(3));
+               STAT(PINKALIVE, it) = Team_GetNumberOfAlivePlayers(
+                       Team_GetTeamFromIndex(4));
        });
 
        eliminatedPlayers.SendFlags |= 1;
 }
-#define FREEZETAG_ALIVE_TEAMS() ((redalive > 0) + (bluealive > 0) + (yellowalive > 0) + (pinkalive > 0))
-#define FREEZETAG_ALIVE_TEAMS_OK() (FREEZETAG_ALIVE_TEAMS() == NumTeams(freezetag_teams))
+
+#define FREEZETAG_ALIVE_TEAMS_OK() (Team_GetNumberOfAliveTeams() == NumTeams(freezetag_teams))
 
 float freezetag_CheckTeams()
 {
@@ -53,14 +67,14 @@ float freezetag_CheckTeams()
                return 0;
        }
        int missing_teams_mask = 0;
-       if(freezetag_teams & BIT(0))
-               missing_teams_mask += (!redalive) * 1;
-       if(freezetag_teams & BIT(1))
-               missing_teams_mask += (!bluealive) * 2;
-       if(freezetag_teams & BIT(2))
-               missing_teams_mask += (!yellowalive) * 4;
-       if(freezetag_teams & BIT(3))
-               missing_teams_mask += (!pinkalive) * 8;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               if ((freezetag_teams & Team_IndexToBit(i)) &&
+                       (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) == 0))
+               {
+                       missing_teams_mask |= Team_IndexToBit(i);
+               }
+       }
        if(prev_missing_teams_mask != missing_teams_mask)
        {
                Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_MISSING_TEAMS, missing_teams_mask);
@@ -69,28 +83,28 @@ float freezetag_CheckTeams()
        return 0;
 }
 
-float freezetag_getWinnerTeam()
+int freezetag_getWinnerTeam()
 {
-       float winner_team = 0;
-       if(redalive >= 1)
-               winner_team = NUM_TEAM_1;
-       if(bluealive >= 1)
+       int winner_team = 0;
+       if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(1)) >= 1)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_2;
+               winner_team = NUM_TEAM_1;
        }
-       if(yellowalive >= 1)
+       for (int i = 2; i <= NUM_TEAMS; ++i)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_3;
+               if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) >= 1)
+               {
+                       if (winner_team != 0)
+                       {
+                               return 0;
+                       }
+                       winner_team = Team_IndexToTeam(i);
+               }
        }
-       if(pinkalive >= 1)
+       if (winner_team)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_4;
-       }
-       if(winner_team)
                return winner_team;
+       }
        return -1; // no player left
 }
 
@@ -112,8 +126,10 @@ float freezetag_CheckWinner()
                return 1;
        }
 
-       if(FREEZETAG_ALIVE_TEAMS() > 1)
+       if (Team_GetNumberOfAliveTeams() > 1)
+       {
                return 0;
+       }
 
        int winner_team = freezetag_getWinnerTeam();
        if(winner_team > 0)
@@ -141,14 +157,14 @@ float freezetag_CheckWinner()
 entity freezetag_LastPlayerForTeam(entity this)
 {
        entity last_pl = NULL;
-       FOREACH_CLIENT(IS_PLAYER(it) && it != this, {
-               if(GetResourceAmount(it, RESOURCE_HEALTH) >= 1)
-               if(!STAT(FROZEN, it))
-               if(SAME_TEAM(it, this))
-               if(!last_pl)
-                       last_pl = it;
-               else
-                       return NULL;
+       FOREACH_CLIENT(IS_PLAYER(it) && it != this && SAME_TEAM(it, this), {
+               if (!STAT(FROZEN, it) && GetResourceAmount(it, RESOURCE_HEALTH) >= 1)
+               {
+                       if (!last_pl)
+                               last_pl = it;
+                       else
+                               return NULL;
+               }
        });
        return last_pl;
 }
@@ -544,9 +560,10 @@ MUTATOR_HOOKFUNCTION(ft, HavocBot_ChooseRole)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ft, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(ft, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = freezetag_teams;
+       return true;
 }
 
 MUTATOR_HOOKFUNCTION(ft, SetWeaponArena)
@@ -568,8 +585,8 @@ MUTATOR_HOOKFUNCTION(ft, FragCenterMessage)
                return; // target was already frozen, so this is just pushing them off the cliff
 
        Send_Notification(NOTIF_ONE, frag_attacker, MSG_CHOICE, CHOICE_FRAG_FREEZE, frag_target.netname, kill_count_to_attacker, (IS_BOT_CLIENT(frag_target) ? -1 : CS(frag_target).ping));
-       Send_Notification(NOTIF_ONE, frag_target, MSG_CHOICE, CHOICE_FRAGGED_FREEZE, frag_attacker.netname, kill_count_to_target, 
-                                                                               GetResourceAmount(frag_attacker, RESOURCE_HEALTH), GetResourceAmount(frag_attacker, RESOURCE_ARMOR), (IS_BOT_CLIENT(frag_attacker) ? -1 : CS(frag_attacker).ping));
+       Send_Notification(NOTIF_ONE, frag_target, MSG_CHOICE, CHOICE_FRAGGED_FREEZE, frag_attacker.netname, kill_count_to_target,
+               GetResourceAmount(frag_attacker, RESOURCE_HEALTH), GetResourceAmount(frag_attacker, RESOURCE_ARMOR), (IS_BOT_CLIENT(frag_attacker) ? -1 : CS(frag_attacker).ping));
 
        return true;
 }
@@ -582,7 +599,7 @@ void freezetag_Initialize()
 
        freezetag_teams = BITS(bound(2, freezetag_teams, 4));
        GameRules_scoring(freezetag_teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, {
-           field(SP_FREEZETAG_REVIVALS, "revivals", 0);
+               field(SP_FREEZETAG_REVIVALS, "revivals", 0);
        });
 
        round_handler_Spawn(freezetag_CheckTeams, freezetag_CheckWinner, func_null);
index 3dff701959ef82c11f8f7e205daa3abfeb6af14b..00e2241c6866bf051135f891c3edb9433251b919 100644 (file)
@@ -548,9 +548,10 @@ MUTATOR_HOOKFUNCTION(inv, CheckRules_World)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(inv, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(inv, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = invasion_teams;
+       return true;
 }
 
 MUTATOR_HOOKFUNCTION(inv, AllowMobButcher)
@@ -561,7 +562,6 @@ MUTATOR_HOOKFUNCTION(inv, AllowMobButcher)
 
 void invasion_ScoreRules(int inv_teams)
 {
-       if(inv_teams) { CheckAllowedTeams(NULL); }
        GameRules_score_enabled(false);
        GameRules_scoring(inv_teams, 0, 0, {
            if (inv_teams) {
index 6523612e2336220dadb86f03342aa8fc605980fc..5e0d3fcbbfaa0e475a8b6d0f3f87dc99ae18ac32 100644 (file)
@@ -1264,9 +1264,10 @@ MUTATOR_HOOKFUNCTION(kh, MatchEnd)
        kh_finalize();
 }
 
-MUTATOR_HOOKFUNCTION(kh, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(kh, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = kh_teams;
+       return true;
 }
 
 MUTATOR_HOOKFUNCTION(kh, SpectateCopy)
index 487012aa50902e7a834fdd708a7c0e45bb2928cc..89c53a82abc22eb1b7b4b8fc1a8784e8f5b6ea23 100644 (file)
@@ -635,7 +635,7 @@ void SpawnGoal(entity this)
 
        EXACTTRIGGER_INIT;
 
-       if(this.team != GOAL_OUT && Team_TeamToNumber(this.team) != -1)
+       if(this.team != GOAL_OUT && Team_IsValidTeam(this.team))
        {
                entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (this.absmin + this.absmax) * 0.5, this, sprite, RADARICON_NONE);
                wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 0.5 0');
@@ -920,7 +920,7 @@ MUTATOR_HOOKFUNCTION(nb, ItemTouch)
        return MUT_ITEMTOUCH_CONTINUE;
 }
 
-MUTATOR_HOOKFUNCTION(nb, CheckAllowedTeams)
+MUTATOR_HOOKFUNCTION(nb, TeamBalance_CheckAllowedTeams)
 {
        M_ARGV(1, string) = "nexball_team";
        return true;
index fd050df0a0f541cc0137303fe86ad15ab26ba60b..c20a4fac74a160b62e9d876a35092fd6afc5a2b4 100644 (file)
@@ -449,15 +449,17 @@ void ons_ControlPoint_Icon_Damage(entity this, entity inflictor, entity attacker
 
 bool ons_ControlPoint_Icon_Heal(entity targ, entity inflictor, float amount, float limit)
 {
+       float hlth = GetResourceAmount(targ, RESOURCE_HEALTH);
        float true_limit = ((limit != RESOURCE_LIMIT_NONE) ? limit : targ.max_health);
-       if(GetResourceAmount(targ, RESOURCE_HEALTH) <= 0 || GetResourceAmount(targ, RESOURCE_HEALTH) >= true_limit)
+       if (hlth <= 0 || hlth >= true_limit)
                return false;
 
        GiveResourceWithLimit(targ, RESOURCE_HEALTH, amount, true_limit);
+       hlth = GetResourceAmount(targ, RESOURCE_HEALTH);
        if(targ.owner.iscaptured)
-               WaypointSprite_UpdateHealth(targ.owner.sprite, GetResourceAmount(targ, RESOURCE_HEALTH));
+               WaypointSprite_UpdateHealth(targ.owner.sprite, hlth);
        else
-               WaypointSprite_UpdateBuildFinished(targ.owner.sprite, time + (targ.max_health - GetResourceAmount(targ, RESOURCE_HEALTH)) / (targ.count / ONS_CP_THINKRATE));
+               WaypointSprite_UpdateBuildFinished(targ.owner.sprite, time + (targ.max_health - hlth) / (targ.count / ONS_CP_THINKRATE));
        targ.SendFlags |= CPSF_STATUS;
        return true;
 }
@@ -904,13 +906,14 @@ void ons_GeneratorDamage(entity this, entity inflictor, entity attacker, float d
                }
        }
        TakeResource(this, RESOURCE_HEALTH, damage);
-       WaypointSprite_UpdateHealth(this.sprite, GetResourceAmount(this, RESOURCE_HEALTH));
+       float hlth = GetResourceAmount(this, RESOURCE_HEALTH);
+       WaypointSprite_UpdateHealth(this.sprite, hlth);
        // choose an animation frame based on health
-       this.frame = 10 * bound(0, (1 - GetResourceAmount(this, RESOURCE_HEALTH) / this.max_health), 1);
+       this.frame = 10 * bound(0, (1 - hlth / this.max_health), 1);
        // see if the generator is still functional, or dying
-       if (GetResourceAmount(this, RESOURCE_HEALTH) > 0)
+       if (hlth > 0)
        {
-               this.lasthealth = GetResourceAmount(this, RESOURCE_HEALTH);
+               this.lasthealth = hlth;
        }
        else
        {
@@ -964,13 +967,15 @@ void ons_GeneratorDamage(entity this, entity inflictor, entity attacker, float d
 bool ons_GeneratorHeal(entity targ, entity inflictor, float amount, float limit)
 {
        float true_limit = ((limit != RESOURCE_LIMIT_NONE) ? limit : targ.max_health);
-       if(GetResourceAmount(targ, RESOURCE_HEALTH) <= 0 || GetResourceAmount(targ, RESOURCE_HEALTH) >= true_limit)
+       float hlth = GetResourceAmount(targ, RESOURCE_HEALTH);
+       if (hlth <= 0 || hlth >= true_limit)
                return false;
 
        GiveResourceWithLimit(targ, RESOURCE_HEALTH, amount, true_limit);
-       WaypointSprite_UpdateHealth(targ.sprite, GetResourceAmount(targ, RESOURCE_HEALTH));
-       targ.frame = 10 * bound(0, (1 - GetResourceAmount(targ, RESOURCE_HEALTH) / targ.max_health), 1);
-       targ.lasthealth = GetResourceAmount(targ, RESOURCE_HEALTH);
+       hlth = GetResourceAmount(targ, RESOURCE_HEALTH);
+       WaypointSprite_UpdateHealth(targ.sprite, hlth);
+       targ.frame = 10 * bound(0, (1 - hlth / targ.max_health), 1);
+       targ.lasthealth = hlth;
        targ.SendFlags |= GSF_STATUS;
        return true;
 }
@@ -1108,46 +1113,52 @@ int total_generators;
 void Onslaught_count_generators()
 {
        entity e;
-       total_generators = redowned = blueowned = yellowowned = pinkowned = 0;
+       total_generators = 0;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               Team_SetNumberOfControlPoints(Team_GetTeamFromIndex(i), 0);
+       }
        for(e = ons_worldgeneratorlist; e; e = e.ons_worldgeneratornext)
        {
                ++total_generators;
-               redowned += (e.team == NUM_TEAM_1 && GetResourceAmount(e, RESOURCE_HEALTH) > 0);
-               blueowned += (e.team == NUM_TEAM_2 && GetResourceAmount(e, RESOURCE_HEALTH) > 0);
-               yellowowned += (e.team == NUM_TEAM_3 && GetResourceAmount(e, RESOURCE_HEALTH) > 0);
-               pinkowned += (e.team == NUM_TEAM_4 && GetResourceAmount(e, RESOURCE_HEALTH) > 0);
+               if (GetResourceAmount(e, RESOURCE_HEALTH) < 1)
+               {
+                       continue;
+               }
+               entity team_ = Entity_GetTeam(e);
+               int num_control_points = Team_GetNumberOfControlPoints(team_);
+               ++num_control_points;
+               Team_SetNumberOfControlPoints(team_, num_control_points);
        }
 }
 
 int Onslaught_GetWinnerTeam()
 {
        int winner_team = 0;
-       if(redowned > 0)
-               winner_team = NUM_TEAM_1;
-       if(blueowned > 0)
+       if (Team_GetNumberOfControlPoints(Team_GetTeamFromIndex(1)) >= 1)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_2;
+               winner_team = NUM_TEAM_1;
        }
-       if(yellowowned > 0)
+       for (int i = 2; i <= NUM_TEAMS; ++i)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_3;
+               if (Team_GetNumberOfControlPoints(Team_GetTeamFromIndex(i)) >= 1)
+               {
+                       if (winner_team != 0)
+                       {
+                               return 0;
+                       }
+                       winner_team = Team_IndexToTeam(i);
+               }
        }
-       if(pinkowned > 0)
+       if (winner_team)
        {
-               if(winner_team) return 0;
-               winner_team = NUM_TEAM_4;
-       }
-       if(winner_team)
                return winner_team;
+       }
        return -1; // no generators left?
 }
 
 void nades_Clear(entity e);
 
-#define ONS_OWNED_GENERATORS() ((redowned > 0) + (blueowned > 0) + (yellowowned > 0) + (pinkowned > 0))
-#define ONS_OWNED_GENERATORS_OK() (ONS_OWNED_GENERATORS() > 1)
 bool Onslaught_CheckWinner()
 {
        if ((autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60) || (round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0))
@@ -1193,8 +1204,10 @@ bool Onslaught_CheckWinner()
 
        Onslaught_count_generators();
 
-       if(ONS_OWNED_GENERATORS_OK())
+       if (Team_GetNumberOfTeamsWithControlPoints() > 1)
+       {
                return 0;
+       }
 
        int winner_team = Onslaught_GetWinnerTeam();
 
@@ -1955,17 +1968,14 @@ MUTATOR_HOOKFUNCTION(ons, HavocBot_ChooseRole)
        return true;
 }
 
-MUTATOR_HOOKFUNCTION(ons, CheckAllowedTeams)
+MUTATOR_HOOKFUNCTION(ons, TeamBalance_CheckAllowedTeams)
 {
        // onslaught is special
        for(entity tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext)
        {
-               switch(tmp_entity.team)
+               if (Team_IsValidTeam(tmp_entity.team))
                {
-                       case NUM_TEAM_1: c1 = 0; break;
-                       case NUM_TEAM_2: c2 = 0; break;
-                       case NUM_TEAM_3: c3 = 0; break;
-                       case NUM_TEAM_4: c4 = 0; break;
+                       M_ARGV(0, float) |= Team_TeamToBit(tmp_entity.team);
                }
        }
 
@@ -2195,12 +2205,9 @@ spawnfunc(onslaught_generator)
 // scoreboard setup
 void ons_ScoreRules()
 {
-       CheckAllowedTeams(NULL);
-       int teams = 0;
-       if(c1 >= 0) teams |= BIT(0);
-       if(c2 >= 0) teams |= BIT(1);
-       if(c3 >= 0) teams |= BIT(2);
-       if(c4 >= 0) teams |= BIT(3);
+       entity balance = TeamBalance_CheckAllowedTeams(NULL);
+       int teams = TeamBalance_GetAllowedTeams(balance);
+       TeamBalance_Destroy(balance);
        GameRules_scoring(teams, SFL_SORT_PRIO_PRIMARY, 0, {
            field_team(ST_ONS_CAPS, "destroyed", SFL_SORT_PRIO_PRIMARY);
            field(SP_ONS_CAPS, "caps", SFL_SORT_PRIO_SECONDARY);
index c98e1b6a898ce0a309e69d079b5a43a0a84f883f..aaf83cb39bc9af705a4111bff581efed9b6dc5f6 100644 (file)
@@ -366,9 +366,10 @@ MUTATOR_HOOKFUNCTION(rc, ForbidPlayerScore_Clear)
                return true; // in qualifying, you don't lose score by observing
 }
 
-MUTATOR_HOOKFUNCTION(rc, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(rc, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(0, float) = race_teams;
+       return true;
 }
 
 MUTATOR_HOOKFUNCTION(rc, Scores_CountFragsRemaining)
index 39e5fec1e19cd62fd7783252c3c5d81ea97ba89c..cf328902bf3aa866fef2bfad25846b5adf672605 100644 (file)
@@ -53,10 +53,9 @@ void tdm_DelayedInit(entity this)
        }
 }
 
-MUTATOR_HOOKFUNCTION(tdm, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
+MUTATOR_HOOKFUNCTION(tdm, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE)
 {
        M_ARGV(1, string) = "tdm_team";
-       return true;
 }
 
 MUTATOR_HOOKFUNCTION(tdm, Scores_CountFragsRemaining)
index 979477cbafab6c676c4fdc7cabfeedf43134725b..ca1b6f8e74649e80c2b1ebe8c180871c00cef75e 100644 (file)
@@ -2,7 +2,6 @@
 
 // TODO: find a better location for these?
 float total_players;
-float redalive, bluealive, yellowalive, pinkalive;
 
 // todo: accept the number of teams as a parameter
 void GameRules_teams(bool value);
index 3109e7c92f93c66adc8c0f5d274bef901bf019e3..030b4db1c089f53f06c62a1cb19590ac48b50977 100644 (file)
@@ -51,16 +51,26 @@ const int IT_PICKUPMASK                     = IT_UNLIMITED_AMMO | IT_JETPACK | IT_FU
 .float  strength_finished = _STAT(STRENGTH_FINISHED);
 .float  invincible_finished = _STAT(INVINCIBLE_FINISHED);
 
+#define spawnfunc_body(item) \
+       if (!Item_IsDefinitionAllowed(item)) \
+       { \
+               startitem_failed = true; \
+               delete(this); \
+               return; \
+       } \
+       StartItem(this, item)
+
 #define SPAWNFUNC_ITEM(name, item) \
-    spawnfunc(name) \
+       spawnfunc(name) \
+       { \
+               spawnfunc_body(item); \
+       }
+
+#define SPAWNFUNC_ITEM_COND(name, cond, item1, item2) \
+       spawnfunc(name) \
        { \
-               if (!Item_IsDefinitionAllowed(item)) \
-               { \
-                       startitem_failed = true; \
-                       delete(this); \
-                       return; \
-               } \
-               StartItem(this, item); \
+               entity item = (cond) ? item1 : item2; \
+               spawnfunc_body(item); \
        }
 
 #else
@@ -73,7 +83,7 @@ enum
 {
        ITEM_FLAG_NORMAL = BIT(0), ///< Item is usable during normal gameplay.
        ITEM_FLAG_MUTATORBLOCKED = BIT(1),
-    ITEM_FLAG_RESOURCE = BIT(2) ///< Item is is a resource, not a held item.
+       ITEM_FLAG_RESOURCE = BIT(2) ///< Item is is a resource, not a held item.
 };
 
 #define ITEM_HANDLE(signal, ...) __Item_Send_##signal(__VA_ARGS__)
index 37d82e22ef72d9f1579d4056349bcf39f61d012a..3174fa7ff31ee4006231c4f45fbba5395619fe74 100644 (file)
@@ -2,12 +2,20 @@
 
 #ifdef SVQC
 
+.float m_chainsaw_damage; // accumulated damage of the missile as it passes trough enemies
+
 void W_OverkillRocketPropelledChainsaw_Explode(entity this, entity directhitentity)
 {
        this.event_damage = func_null;
        this.takedamage = DAMAGE_NO;
 
-       RadiusDamage(this, this.realowner, WEP_CVAR_PRI(okrpc, damage), WEP_CVAR_PRI(okrpc, edgedamage), WEP_CVAR_PRI(okrpc, radius), NULL, NULL, WEP_CVAR_PRI(okrpc, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
+       float explosion_damage = RadiusDamage(this, this.realowner, WEP_CVAR_PRI(okrpc, damage), WEP_CVAR_PRI(okrpc, edgedamage), WEP_CVAR_PRI(okrpc, radius), NULL, NULL, WEP_CVAR_PRI(okrpc, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity);
+       if (explosion_damage > 0 && this.m_chainsaw_damage > 0)
+       {
+               // if chainsaw hit something, it removed fired damage (so that direct hit is 100%)
+               // now that we also damaged something by explosion we'd go over 100% so let's add the fired damage back
+               accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype).m_id, WEP_CVAR(okrpc, damage), 0);
+       }
 
        delete(this);
 }
@@ -53,8 +61,22 @@ void W_OverkillRocketPropelledChainsaw_Think(entity this)
        vector mydir = normalize(this.velocity);
 
        tracebox(this.origin, this.mins, this.maxs, this.origin + mydir * (2 * myspeed_accel), MOVE_NORMAL, this);
-       if(IS_PLAYER(trace_ent))
+       if (IS_PLAYER(trace_ent))
+       {
+               if (accuracy_isgooddamage(this.realowner, trace_ent))
+               {
+                       if (this.m_chainsaw_damage == 0) // first hit
+                       {
+                               // The fired damage of the explosion is already counted in the statistics (when launching the chainsaw).
+                               // We remove it here so that a direct hit that passes through and doesn't damage anything by the explosion later is still 100%.
+                               float fired_damage = WEP_CVAR_PRI(okrpc, damage2) - WEP_CVAR_PRI(okrpc, damage);
+                               float hit_damage = WEP_CVAR_PRI(okrpc, damage2);
+                               accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype).m_id, fired_damage, hit_damage);
+                       }
+                       this.m_chainsaw_damage += WEP_CVAR_PRI(okrpc, damage2);
+               }
                Damage(trace_ent, this, this.realowner, WEP_CVAR_PRI(okrpc, damage2), this.projectiledeathtype, this.weaponentity_fld, this.origin, normalize(this.origin - trace_ent.origin) * WEP_CVAR_PRI(okrpc, force));
+       }
 
        this.velocity = mydir * (myspeed + (WEP_CVAR_PRI(okrpc, speedaccel) * sys_frametime));
 
@@ -106,6 +128,7 @@ void W_OverkillRocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .en
        SUB_SetFade (flash, time, 0.1);
        flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION;
        W_AttachToShotorg(actor, weaponentity, flash, '5 0 0');
+       missile.m_chainsaw_damage = 0;
 
        MUTATOR_CALLHOOK(EditProjectile, actor, missile);
 }
index d80b21d5a6e0cec3b4a59f5c403b948eece5cd85..9458189fd0ed20a448b9da906b3f654c12632452 100644 (file)
@@ -312,8 +312,9 @@ string sandbox_ObjectPort_Save(entity e, bool database)
 entity sandbox_ObjectPort_Load(entity this, string s, float database)
 {
        // load object properties, and spawn a new object with them
-       float n, i;
+       int n, i;
        entity e = NULL, parent = NULL;
+       string arg = string_null;
 
        // separate objects between the ; symbols
        n = tokenizebyseparator(s, "; ");
@@ -323,9 +324,10 @@ entity sandbox_ObjectPort_Load(entity this, string s, float database)
        // now separate and apply the properties of each object
        for(i = 0; i < n; ++i)
        {
-               float argv_num;
+               #define SANDBOX_GETARG arg = argv(++argv_num);
+               int argv_num = -1; // starts at -1 so I don't need postincrement
+
                string tagname = string_null;
-               argv_num = 0;
                tokenize_console(port_string[i]);
                e = sandbox_ObjectSpawn(this, database);
 
@@ -333,38 +335,40 @@ entity sandbox_ObjectPort_Load(entity this, string s, float database)
                if(i)
                {
                        // properties stored only for child objects
-                       if(argv(argv_num) != "")        tagname = argv(argv_num);       else tagname = string_null;     ++argv_num;
+                       SANDBOX_GETARG; tagname = (arg != "") ? arg : string_null;
                }
                else
                {
                        // properties stored only for parent objects
                        if(database)
                        {
-                               setorigin(e, stov(argv(argv_num)));     ++argv_num;
-                               e.angles = stov(argv(argv_num));        ++argv_num;
+                               SANDBOX_GETARG; setorigin(e, stov(arg));
+                               SANDBOX_GETARG; e.angles = stov(arg);
                        }
                        parent = e; // mark parent objects as such
                }
                // properties stored for all objects
-               _setmodel(e, argv(argv_num));   ++argv_num;
-               e.skin = stof(argv(argv_num));  ++argv_num;
-               e.alpha = stof(argv(argv_num)); ++argv_num;
-               e.colormod = stov(argv(argv_num));      ++argv_num;
-               e.glowmod = stov(argv(argv_num));       ++argv_num;
-               e.frame = stof(argv(argv_num)); ++argv_num;
-               sandbox_ObjectEdit_Scale(e, stof(argv(argv_num)));      ++argv_num;
-               e.solid = e.old_solid = stof(argv(argv_num));   ++argv_num;
-               e.old_movetype = stof(argv(argv_num));  ++argv_num;
+               SANDBOX_GETARG; _setmodel(e, arg);
+               SANDBOX_GETARG; e.skin = stof(arg);
+               SANDBOX_GETARG; e.alpha = stof(arg);
+               SANDBOX_GETARG; e.colormod = stov(arg);
+               SANDBOX_GETARG; e.glowmod = stov(arg);
+               SANDBOX_GETARG; e.frame = stof(arg);
+               SANDBOX_GETARG; sandbox_ObjectEdit_Scale(e, stof(arg));
+               SANDBOX_GETARG; e.solid = e.old_solid = stof(arg);
+               SANDBOX_GETARG; e.old_movetype = stof(arg);
                set_movetype(e, e.old_movetype);
-               e.damageforcescale = stof(argv(argv_num));      ++argv_num;
-               strfree(e.material);    if(argv(argv_num) != "")        e.material = strzone(argv(argv_num));   else    e.material = string_null;       ++argv_num;
+               SANDBOX_GETARG; e.damageforcescale = stof(arg);
+               strfree(e.material);
+               SANDBOX_GETARG; e.material = (arg != "") ? strzone(arg) : string_null;
                if(database)
                {
                        // properties stored only for the database
-                       strfree(e.crypto_idfp); if(argv(argv_num) != "")        e.crypto_idfp = strzone(argv(argv_num));        else    e.crypto_idfp = string_null;    ++argv_num;
-                       strcpy(e.netname, argv(argv_num));      ++argv_num;
-                       strcpy(e.message, argv(argv_num));      ++argv_num;
-                       strcpy(e.message2, argv(argv_num));     ++argv_num;
+                       strfree(e.crypto_idfp);
+                       SANDBOX_GETARG; e.crypto_idfp = (arg != "") ? strzone(arg) : string_null;
+                       SANDBOX_GETARG; strcpy(e.netname, arg);
+                       SANDBOX_GETARG; strcpy(e.message, arg);
+                       SANDBOX_GETARG; strcpy(e.message2, arg);
                }
 
                // attach last
index 115e6ca9109341fcaa4c61974eaafe416b342f15..e74cfb1152844c485c94e9f72705d7d004f46e54 100644 (file)
@@ -28,7 +28,9 @@ MUTATOR_HOOKFUNCTION(vh, GrappleHookThink)
                thehook.owner.damage_dealt += autocvar_g_vampirehook_damage;
                Damage(dmgent, thehook, thehook.owner, autocvar_g_vampirehook_damage, WEP_HOOK.m_id, DMG_NOWEP, thehook.origin, '0 0 0');
                entity targ = ((SAME_TEAM(thehook.owner, thehook.aiment)) ? thehook.aiment : thehook.owner);
-               Heal(targ, thehook.owner, autocvar_g_vampirehook_health_steal, g_pickup_healthsmall_max);
+               // TODO: we can't do this due to an issue with globals and the mutator arguments
+               //Heal(targ, thehook.owner, autocvar_g_vampirehook_health_steal, g_pickup_healthsmall_max);
+               SetResourceAmountExplicit(targ, RESOURCE_HEALTH, min(GetResourceAmount(targ, RESOURCE_HEALTH) + autocvar_g_vampirehook_health_steal, g_pickup_healthsmall_max));
 
                if(dmgent == thehook.owner)
                        TakeResource(dmgent, RESOURCE_HEALTH, autocvar_g_vampirehook_damage); // FIXME: friendly fire?!
index b527bdc1a84b020088603478e4007db063ce5c75..c8c4db546a71267d4bb86f7e71e0239ba1c7f629 100644 (file)
@@ -14,8 +14,8 @@ REGISTER_WAYPOINT(RaceFinish, _("Finish"), "", '1 0.5 0', 1);
 REGISTER_WAYPOINT(RaceStart, _("Start"), "", '1 0.5 0', 1);
 REGISTER_WAYPOINT(RaceStartFinish, _("Start"), "", '1 0.5 0', 1);
 
-REGISTER_WAYPOINT(AssaultDefend, _("Defend"), "", '1 0.5 0', 1);
-REGISTER_WAYPOINT(AssaultDestroy, _("Destroy"), "", '1 0.5 0', 1);
+REGISTER_WAYPOINT(AssaultDefend, _("Defend"), "as_defend", '1 0.5 0', 1);
+REGISTER_WAYPOINT(AssaultDestroy, _("Destroy"), "as_destroy", '1 0.5 0', 1);
 REGISTER_WAYPOINT(AssaultPush, _("Push"), "", '1 0.5 0', 1);
 
 REGISTER_WAYPOINT(FlagCarrier, _("Flag carrier"), "", '0.8 0.8 0', 1);
index a15ef80d1e7f8feece7b0dc8f7927e3962d50db0..db0e0503f08b75b2fd6ffc14f050d35bbe27e094 100644 (file)
 
     MSG_INFO_NOTIF(CONNECTING,                              N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^BG is connecting..."), "")
     MSG_INFO_NOTIF(JOIN_CONNECT,                            N_CHATCON,  1, 0, "s1", "",         "",     _("^BG%s^F3 connected"), "")
-    MULTITEAM_INFO(JOIN_CONNECT_TEAM, 4,                    N_CHATCON,  1, 0, "s1", "",         "",     _("^BG%s^F3 connected and joined the ^TC^TT team"), "", NAME)
     MSG_INFO_NOTIF(JOIN_PLAY,                               N_CONSOLE,  1, 0, "s1", "",         "",     _("^BG%s^F3 is now playing"), "")
     MULTITEAM_INFO(JOIN_PLAY_TEAM, 4,                       N_CHATCON,  1, 0, "s1", "",         "",     _("^BG%s^F3 is now playing on the ^TC^TT team"), "", NAME)
 
index d46ac9eafc7c36cccbeb07c7d302fe9b25f250d3..49cfb4488c9e478f7bf90dddf95c7787a143d62e 100644 (file)
@@ -128,7 +128,7 @@ CLASS(Sound, Object)
        }
        METHOD(Sound, sound_precache, void(Sound this))
        {
-           TC(Sound, this);
+               TC(Sound, this);
                string s = _Sound_fixpath(this.sound_str());
                if (!s) return;
                profile(sprintf("precache_sound(\"%s\")", s));
index 37813ef716c0bd5f393bc45a1f2fad39036e7b0b..772dbccbd58d870137b69ab4143fc053e3b02e81 100644 (file)
@@ -52,8 +52,6 @@ void ClientState_attach(entity this)
        entcs_attach(this);
        anticheat_init(this);
        W_HitPlotOpen(this);
-
-       bot_clientconnect(this);
 }
 
 void bot_clientdisconnect(entity this);
index 140b619c5ec09cae3f8c62fcf1e87bb6c4b61c2b..28ea1add9f998c8b52f9f463d6e7ca8bc73f50d2 100644 (file)
@@ -613,14 +613,18 @@ float adjust_respawntime(float normal_respawntime) {
                return normal_respawntime;
        }
 
-       CheckAllowedTeams(NULL);
-       GetTeamCounts(NULL);
+       entity balance = TeamBalance_CheckAllowedTeams(NULL);
+       TeamBalance_GetTeamCounts(balance, NULL);
        int players = 0;
-       if (c1 != -1) players += c1;
-       if (c2 != -1) players += c2;
-       if (c3 != -1) players += c3;
-       if (c4 != -1) players += c4;
-
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               if (TeamBalance_IsTeamAllowed(balance, i))
+               {
+                       players += TeamBalance_GetNumberOfPlayers(balance, i);
+               }
+       }
+       TeamBalance_Destroy(balance);
+       
        if (players >= 2) {
                return normal_respawntime * (r / (players + o) + l);
        } else {
index 57d644c0448549e13bff834f7cb6fd289d983cc3..1a2e1b1766febc7cb404dbe5e02f03bf1b2a7e71 100644 (file)
@@ -1,5 +1,7 @@
 #pragma once
 
+const int NUM_TEAMS = 4; ///< Number of teams in the game.
+
 #ifdef TEAMNUMBERS_THAT_ARENT_STUPID
 const int NUM_TEAM_1 = 1;  // red
 const int NUM_TEAM_2 = 2; // blue
@@ -125,12 +127,12 @@ float Team_ColorToTeam(string team_color)
        return -1;
 }
 
-/// \brief Returns whether team is valid.
-/// \param[in] team_ Team to check.
+/// \brief Returns whether team value is valid.
+/// \param[in] team_num Team to check.
 /// \return True if team is valid, false otherwise.
-bool Team_IsValidTeam(int team_)
+bool Team_IsValidTeam(int team_num)
 {
-       switch (team_)
+       switch (team_num)
        {
                case NUM_TEAM_1:
                case NUM_TEAM_2:
@@ -143,12 +145,12 @@ bool Team_IsValidTeam(int team_)
        return false;
 }
 
-/// \brief Returns whether team number is valid.
-/// \param[in] number Team number to check.
-/// \return True if team number is valid, false otherwise.
-bool Team_IsValidNumber(int number)
+/// \brief Returns whether the team index is valid.
+/// \param[in] index Team index to check.
+/// \return True if team index is valid, false otherwise.
+bool Team_IsValidIndex(int index)
 {
-       switch (number)
+       switch (index)
        {
                case 1:
                case 2:
@@ -161,36 +163,60 @@ bool Team_IsValidNumber(int number)
        return false;
 }
 
-float Team_NumberToTeam(float number)
+/// \brief Converts team index into team value.
+/// \param[in] index Team index to convert.
+/// \return Team value.
+int Team_IndexToTeam(int index)
 {
-       switch(number)
+       switch (index)
        {
                case 1: return NUM_TEAM_1;
                case 2: return NUM_TEAM_2;
                case 3: return NUM_TEAM_3;
                case 4: return NUM_TEAM_4;
        }
-
        return -1;
 }
 
-float Team_TeamToNumber(float teamid)
+/// \brief Converts team value into team index.
+/// \param[in] team_num Team value to convert.
+/// \return Team index.
+int Team_TeamToIndex(int team_num)
 {
-       switch(teamid)
+       switch (team_num)
        {
                case NUM_TEAM_1: return 1;
                case NUM_TEAM_2: return 2;
                case NUM_TEAM_3: return 3;
                case NUM_TEAM_4: return 4;
        }
-
        return -1;
 }
 
+/// \brief Converts team value into bit value that is used in team bitmasks.
+/// \param[in] team_num Team value to convert.
+/// \return Team bit.
+int Team_TeamToBit(int team_num)
+{
+       if (!Team_IsValidTeam(team_num))
+       {
+               return 0;
+       }
+       return BIT(Team_TeamToIndex(team_num) - 1);
+}
+
+/// \brief Converts team index into bit value that is used in team bitmasks.
+/// \param[in] index Team index to convert.
+/// \return Team bit.
+int Team_IndexToBit(int index)
+{
+       return BIT(index - 1);
+}
+
 
 // legacy aliases for shitty code
-#define TeamByColor(teamid) (Team_TeamToNumber(teamid) - 1)
-#define ColorByTeam(number) Team_NumberToTeam(number + 1)
+#define TeamByColor(teamid) (Team_TeamToIndex(teamid) - 1)
+#define ColorByTeam(number) Team_IndexToTeam(number + 1)
 
 // useful aliases
 #define Team_ColorName_Lower(teamid) strtolower(Team_ColorName(teamid))
@@ -203,8 +229,8 @@ float Team_TeamToNumber(float teamid)
 #define Team_FullName(teamid) strcat(Team_ColorName(teamid), " ", NAME_TEAM, "^7")
 #define Team_ColoredFullName(teamid) strcat(Team_ColorCode(teamid), Team_ColorName(teamid), " ", NAME_TEAM, "^7")
 
-#define Team_NumberToFullName(number) Team_FullName(Team_NumberToTeam(number))
-#define Team_NumberToColoredFullName(number) Team_ColoredFullName(Team_NumberToTeam(number))
+#define Team_IndexToFullName(index) Team_FullName(Team_IndexToTeam(index))
+#define Team_IndexToColoredFullName(index) Team_ColoredFullName(Team_IndexToTeam(index))
 
 // replace these flags in a string with the strings provided
 #define TCR(input,type,team) strreplace("^TC", COL_TEAM_##team, strreplace("^TT", strtoupper(type##_TEAM_##team), input))
index b68aca16feddd93b6ea01b555b49aa6b17d2c53a..95ee419815a14a0741644b8a84ddcf6bd5ea3b97 100644 (file)
@@ -474,7 +474,7 @@ void turret_projectile_damage(entity this, entity inflictor, entity attacker, fl
 
 entity turret_projectile(entity actor, Sound _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim)
 {
-    TC(Sound, _snd);
+       TC(Sound, _snd);
        entity proj;
 
        sound (actor, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM);
index 51ac4bee45f3e035b19fc9895abfbce066e639e6..06c8484ff8eec45d17be6d3f18e0caaa6d1f2c5b 100644 (file)
@@ -21,7 +21,7 @@ float alarm2time;
 
 void vehicle_alarm(entity e, int ch, Sound s0und)
 {
-    TC(Sound, s0und);
+       TC(Sound, s0und);
        if(!autocvar_cl_vehicles_alarm)
                return;
 
index df0f5d91693946c7230fb95d37f0dfb6b773aecd..716dfe8d0c130225041502345a182873aa7c111f 100644 (file)
@@ -251,7 +251,7 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound,
                                                   int _deahtype, float _projtype, float _health,
                                                   bool _cull, bool _clianim, entity _owner)
 {
-    TC(Sound, _mzlsound);
+       TC(Sound, _mzlsound);
        entity proj;
 
        proj = spawn();
@@ -811,7 +811,6 @@ void vehicles_exit(entity vehic, bool eject)
 
        vehicles_exit_running = true;
 
-       // TODO: this was in an IS_CLIENT check, make sure it isn't actually needed!
        if(vehic.vehicle_flags & VHF_PLAYERSLOT)
        {
                vehic.vehicle_exit(vehic, eject);
index c7066e6fbd34720e16d0852f305c6fa36d426323..e78e10a3641d772427a9c053170db903a70e2fb0 100644 (file)
@@ -633,7 +633,7 @@ METHOD(Arc, wr_think, void(entity thiswep, entity actor, .entity weaponentity, i
     }
     else if(fire & 2)
     {
-        if(weapon_prepareattack(thiswep, actor, weaponentity, false, WEP_CVAR(arc, bolt_refire)))
+        if(weapon_prepareattack(thiswep, actor, weaponentity, true, WEP_CVAR(arc, bolt_refire)))
         {
             W_Arc_Attack_Bolt(thiswep, actor, weaponentity);
             weapon_thinkf(actor, weaponentity, WFRAME_FIRE1, WEP_CVAR(arc, bolt_refire), w_ready);
index 03855e316e7c1c9f4be758095ad057c06fa5c835..861def9c733a12562f001c710e1c2cad254bc664 100644 (file)
@@ -257,6 +257,8 @@ void W_Hagar_Attack2_Load(Weapon thiswep, entity actor, .entity weaponentity)
        // loadable hagar secondary attack, must always run each frame
        if(time < game_starttime || time < actor.race_penalty || timeout_status == TIMEOUT_ACTIVE)
                return;
+       if (round_handler_IsActive() && !round_handler_IsRoundStarted())
+               return;
 
        bool loaded = actor.(weaponentity).hagar_load >= WEP_CVAR_SEC(hagar, load_max);
 
index 057ef3f03a756b6c3d337a7257fada47c88ebd51..4acceed7184c924af8ffca37017fe3b8794191b4 100644 (file)
@@ -69,7 +69,7 @@ void W_Shotgun_Melee_Think(entity this)
                        + (v_up * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_up))
                        + (v_right * swing_factor * WEP_CVAR_SEC(shotgun, melee_swing_side)));
 
-               WarpZone_traceline_antilag(this, this.realowner.origin + this.realowner.view_ofs, targpos, false, this.realowner, ((IS_CLIENT(this.realowner)) ? ANTILAG_LATENCY(this.realowner) : 0));
+               WarpZone_traceline_antilag(this.realowner, this.realowner.origin + this.realowner.view_ofs, targpos, false, this.realowner, ((IS_CLIENT(this.realowner)) ? ANTILAG_LATENCY(this.realowner) : 0));
 
                // draw lightning beams for debugging
                //te_lightning2(NULL, targpos, this.realowner.origin + this.realowner.view_ofs + v_forward * 5 - v_up * 5);
@@ -78,7 +78,7 @@ void W_Shotgun_Melee_Think(entity this)
                is_player = (IS_PLAYER(trace_ent) || trace_ent.classname == "body" || IS_MONSTER(trace_ent));
 
                if((trace_fraction < 1) // if trace is good, apply the damage and remove this
-                       && (trace_ent.takedamage == DAMAGE_AIM)
+                       && (trace_ent.takedamage != DAMAGE_NO)
                        && (trace_ent != this.swing_alreadyhit)
                        && (is_player || WEP_CVAR_SEC(shotgun, melee_nonplayerdamage)))
                {
index 3dfac622464a1144ed74096703108d0e9afa8251..841486f5837a9150cf730d77ef23a7d9c8443ca5 100644 (file)
@@ -45,14 +45,14 @@ ERASEABLE
 string CTX(string s)
 {
 #if CTX_CACHE
-               string c = HM_gets(CTX_cache, s);
-               if (c != "") return c;
+       string c = HM_gets(CTX_cache, s);
+       if (c != "") return c;
 #endif
        int p = strstrofs(s, "^", 0);
        string ret = (p < 0) ? s : substring(s, p + 1, -1);
 #if CTX_CACHE
-        LOG_DEBUGF("CTX(\"%s\")", s);
-               HM_sets(CTX_cache, s, ret);
+       LOG_DEBUGF("CTX(\"%s\")", s);
+       HM_sets(CTX_cache, s, ret);
 #endif
        return ret;
 }
index b22ff791501c9a990c93e5d9c7f3dabc2c35f661..e482d7d9ac9b1afab49ae9279ced927e0aa5ce4e 100644 (file)
@@ -326,7 +326,7 @@ CLASS(Object)
     #define remove(this) delete(this)
        METHOD(Object, describe, string(Object this))
        {
-           TC(Object, this);
+               TC(Object, this);
                string s = _("No description");
                if (cvar("developer"))
                {
@@ -340,7 +340,7 @@ CLASS(Object)
        }
        METHOD(Object, display, void(Object this, void(string name, string icon) returns))
        {
-           TC(Object, this);
+               TC(Object, this);
                returns(sprintf("entity %i", this), "nopreview_map");
        }
 ENDCLASS(Object)
index 97f08c98113e520e6d55457356befca52319f28b..c455d2f5ab6c30cd42eee4d01f8dc39edac24f1d 100644 (file)
                }
        }
        AUTOCVAR(menu_scroll_averaging_time, float, 0.16, "smooth scroll averaging time");
-// scroll faster while dragging the scrollbar
+       // scroll faster while dragging the scrollbar
        AUTOCVAR(menu_scroll_averaging_time_pressed, float, 0.06, "smooth scroll averaging time when dragging the scrollbar");
        void ListBox_draw(entity me)
        {
                if (me.scrollPos != me.scrollPosTarget)
                {
                        float averaging_time = (me.pressed == 1)
-                           ? autocvar_menu_scroll_averaging_time_pressed
+                               ? autocvar_menu_scroll_averaging_time_pressed
                                : autocvar_menu_scroll_averaging_time;
                        // this formula works with whatever framerate
                        float f = averaging_time ? exp(-frametime / averaging_time) : 0;
index 9f953f66f542f9a8b9238d65e813a6b5cdf777c7..90221cdf85a43e2731905fe35664ddd57e2440b5 100644 (file)
@@ -168,8 +168,10 @@ void XonoticCampaignList_resizeNotify(entity me, vector relOrigin, vector relSiz
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticCampaignList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin1 = 0.5 * me.realFontSize.y;
        me.realUpperMargin2 = me.realUpperMargin1 + 2 * me.realFontSize.y;
 
index 16d5370f5d7beeef0487001e7aae4c7ad76bb77c..0addd6cbedda7d2bc2f7402b3f9abff336cbfde6 100644 (file)
@@ -92,8 +92,10 @@ void XonoticDemoList_resizeNotify(entity me, vector relOrigin, vector relSize, v
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticDemoList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
 
        me.columnNameOrigin = me.realFontSize.x;
index 31cc98215d6536745dcea7f5aa153db5b95e53a9..069b22b02d2b3898d691185e597127f77b2c8944 100644 (file)
@@ -80,7 +80,7 @@ void XonoticGameMessageSettingsTab_fill(entity me)
                me.TD(me, 1, 3, e = makeXonoticCheckBoxEx_T(2, 1, "notification_allow_chatboxprint", _("Display all info messages in the chatbox"), "-"));
        me.TR(me);
                me.TD(me, 1, 3, e = makeXonoticCheckBoxEx_T(2, 1, "notification_INFO_QUIT_DISCONNECT", _("Display player statuses in the chatbox"), "-"));
-                       makeMulti(e, "notification_INFO_QUIT_KICK_IDLING notification_INFO_JOIN_CONNECT_TEAM");
+                       makeMulti(e, "notification_INFO_QUIT_KICK_IDLING notification_INFO_JOIN_CONNECT");
        me.TR(me);
        me.TR(me);
                me.TD(me, 1, 3, e = makeXonoticCheckBox_T(0, "notification_CENTER_POWERUP_INVISIBILITY", _("Powerup notifications"), "-"));
index a08e4dbbc5fa13dc4eb51680a1bb551a25780fc0..3703393789eaa1125b6777b170d470612f2bea75 100644 (file)
@@ -101,8 +101,10 @@ void XonoticGametypeList_resizeNotify(entity me, vector relOrigin, vector relSiz
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticGametypeList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
        me.columnIconOrigin = 0;
        me.columnIconSize = me.itemAbsSize.y / me.itemAbsSize.x;
index d97d7131a473b36c0a46e8935b1efba6078c51d9..92dee8d85ef3cea77a92dd4e30596852d925b3a9 100644 (file)
@@ -146,8 +146,10 @@ void XonoticHUDSkinList_resizeNotify(entity me, vector relOrigin, vector relSize
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticHUDSkinList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
 
        me.columnNameOrigin = me.realFontSize.x;
index 73ef8a32ae8cfd738852859b0ccb47fa5bf6bbd0..5184ee1fd546a0f90ad3838462a57c005b7b4a9e 100644 (file)
@@ -88,8 +88,10 @@ void XonoticMapList_resizeNotify(entity me, vector relOrigin, vector relSize, ve
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticMapList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin1 = 0.5 * (1 - 2.5 * me.realFontSize.y);
        me.realUpperMargin2 = me.realUpperMargin1 + 1.5 * me.realFontSize.y;
 
index c6033050ae6f45d9157b042039788773b67afa72..e90eef23d3a11d2c63a2aa33798f49522508a396 100644 (file)
@@ -61,8 +61,10 @@ void XonoticPlayerList_resizeNotify(entity me, vector relOrigin, vector relSize,
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticPlayerList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
 
        // this list does 1 char left and right margin
index c912ba3a72c49bf40ff49c24ee5eaa199a1efb5f..da5fd486eac5265c53a6ccf2b21b2bb291192b89 100644 (file)
@@ -19,8 +19,10 @@ void XonoticPlayList_resizeNotify(entity me, vector relOrigin, vector relSize, v
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticPlayList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
 
        me.columnNumberOrigin = 0;
index de0adc793815796c0e175f32bf1e6e473b2709e1..9f5ba787aae88c83af4a14b7e02dd0b2f367f5aa 100644 (file)
@@ -97,8 +97,10 @@ void XonoticScreenshotList_resizeNotify(entity me, vector relOrigin, vector relS
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticScreenshotList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
 
        me.columnNameOrigin = me.realFontSize.x;
index e72ca12e2409813c024fbca7dc98914a1c56da35..4683c45207a018753df987f7d26f1c98ceda86be 100644 (file)
@@ -111,8 +111,10 @@ void XonoticSkinList_resizeNotify(entity me, vector relOrigin, vector relSize, v
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticSkinList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin1 = 0.5 * (1 - 2.5 * me.realFontSize.y);
        me.realUpperMargin2 = me.realUpperMargin1 + 1.5 * me.realFontSize.y;
 
index 6d77e1adf929c1e94f2aa964c7edb7bff88837da..99094b0af2cb125550f23bf1bb6137faf8401ed3 100644 (file)
@@ -55,8 +55,10 @@ void XonoticSoundList_resizeNotify(entity me, vector relOrigin, vector relSize,
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticSoundList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
 
        me.columnNumberOrigin = 0;
index 401a6eadda0026b5f7e2b6533c40352c597961ea..2c600b6f5289e6d92a03569a0c2dabf03cab3ca7 100644 (file)
@@ -270,8 +270,10 @@ void XonoticStatsList_resizeNotify(entity me, vector relOrigin, vector relSize,
        me.itemAbsSize = '0 0 0';
        SUPER(XonoticStatsList).resizeNotify(me, relOrigin, relSize, absOrigin, absSize);
 
-       me.realFontSize_y = me.fontSize / (me.itemAbsSize_y = (absSize.y * me.itemHeight));
-       me.realFontSize_x = me.fontSize / (me.itemAbsSize_x = (absSize.x * (1 - me.controlWidth)));
+       me.itemAbsSize.y = absSize.y * me.itemHeight;
+       me.itemAbsSize.x = absSize.x * (1 - me.controlWidth);
+       me.realFontSize.y = me.fontSize / me.itemAbsSize.y;
+       me.realFontSize.x = me.fontSize / me.itemAbsSize.x;
        me.realUpperMargin = 0.5 * (1 - me.realFontSize.y);
 
 #if 0
index 2c5627bf63daa7311af2cdcf3e6bd84c7680787c..50c4fd06a775038394b4ce56792b00a11635c39b 100644 (file)
@@ -238,7 +238,7 @@ void bot_setnameandstuff(entity this)
 
        this.bot_config_loaded = true;
 
-       // this is really only a default, JoinBestTeam is called later
+       // this is really only a default, TeamBalance_JoinBestTeam is called later
        setcolor(this, stof(bot_shirt) * 16 + stof(bot_pants));
        this.bot_preferredcolors = this.clientcolors;
 
@@ -249,16 +249,23 @@ void bot_setnameandstuff(entity this)
                name = bot_name;
 
        // number bots with identical names
-       int j = 0;
-       FOREACH_CLIENT(IS_BOT_CLIENT(it), {
-               if(it.cleanname == name)
-                       ++j;
-       });
-       if (j)
-               this.netname = this.netname_freeme = strzone(strcat(prefix, name, "(", ftos(j), ")", suffix));
-       else
+       if (name == "")
+       {
+               name = ftos(etof(this));
                this.netname = this.netname_freeme = strzone(strcat(prefix, name, suffix));
-
+       }
+       else
+       {
+               int j = 0;
+               FOREACH_CLIENT(IS_BOT_CLIENT(it), {
+                       if(it.cleanname == name)
+                               ++j;
+               });
+               if (j)
+                       this.netname = this.netname_freeme = strzone(strcat(prefix, name, "(", ftos(j), ")", suffix));
+               else
+                       this.netname = this.netname_freeme = strzone(strcat(prefix, name, suffix));
+       }
        this.cleanname = strzone(name);
 
        // pick the model and skin
@@ -424,15 +431,15 @@ void bot_clientconnect(entity this)
        else if(this.bot_forced_team==4)
                this.team = NUM_TEAM_4;
        else
-               JoinBestTeam(this, true);
+               TeamBalance_JoinBestTeam(this);
 
        havocbot_setupbot(this);
 }
 
 void bot_removefromlargestteam()
 {
-       CheckAllowedTeams(NULL);
-       GetTeamCounts(NULL);
+       entity balance = TeamBalance_CheckAllowedTeams(NULL);
+       TeamBalance_GetTeamCounts(balance, NULL);
 
        entity best = NULL;
        float besttime = 0;
@@ -451,12 +458,10 @@ void bot_removefromlargestteam()
 
                int thiscount = 0;
 
-               switch(it.team)
+               if (Team_IsValidTeam(it.team))
                {
-                       case NUM_TEAM_1: thiscount = c1; break;
-                       case NUM_TEAM_2: thiscount = c2; break;
-                       case NUM_TEAM_3: thiscount = c3; break;
-                       case NUM_TEAM_4: thiscount = c4; break;
+                       thiscount = TeamBalance_GetNumberOfPlayers(balance,
+                               Team_TeamToIndex(it.team));
                }
 
                if(thiscount > bestcount)
@@ -471,6 +476,7 @@ void bot_removefromlargestteam()
                        best = it;
                }
        });
+       TeamBalance_Destroy(balance);
        if(!bcount)
                return; // no bots to remove
        currentbots = currentbots - 1;
index 13e1c24c363397de6016ac9f81cce909d298af1c..357b37da00337b99e929787cafda0741674ce1e3 100644 (file)
@@ -525,13 +525,13 @@ void havocbot_movetogoal(entity this)
                {
                        // Calculate brake distance in xy
                        float d = vlen(vec2(this.origin - (this.goalcurrent.absmin + this.goalcurrent.absmax) * 0.5));
-                       float v = vlen(vec2(this.velocity));
-                       float db = ((v ** 2) / (autocvar_g_jetpack_acceleration_side * 2)) + 100;
+                       float vel2 = vlen2(vec2(this.velocity));
+                       float db = (vel2 / (autocvar_g_jetpack_acceleration_side * 2)) + 100;
                        //LOG_INFOF("distance %d, velocity %d, brake at %d ", ceil(d), ceil(v), ceil(db));
                        if(d < db || d < 500)
                        {
                                // Brake
-                               if(v > maxspeed * 0.3)
+                               if (vel2 > (maxspeed * 0.3) ** 2)
                                {
                                        CS(this).movement_x = dir * v_forward * -maxspeed;
                                        return;
@@ -748,9 +748,10 @@ void havocbot_movetogoal(entity this)
                else
                        PHYS_INPUT_BUTTON_JUMP(this) = false;
                makevectors(this.v_angle.y * '0 1 0');
-               CS(this).movement_x = dir * v_forward * maxspeed;
-               CS(this).movement_y = dir * v_right * maxspeed;
-               CS(this).movement_z = dir * v_up * maxspeed;
+               vector v = dir * maxspeed;
+               CS(this).movement.x = v * v_forward;
+               CS(this).movement.y = v * v_right;
+               CS(this).movement.z = v * v_up;
        }
 
        // if there is nowhere to go, exit
index 674ab634a1c768889ff3ac4025ea07008221b813..bab99b30479e82bc61d90e4553335eb998e65647 100644 (file)
@@ -260,7 +260,7 @@ void waypoint_spawn_fromeditor(entity pl)
                {
                        vector item_org = (it.absmin + it.absmax) * 0.5;
                        item_org.z = it.absmin.z - PL_MIN_CONST.z;
-                       if(vlen(item_org - org) < 30)
+                       if (vlen(item_org - org) < 20)
                        {
                                org = item_org;
                                break;
@@ -293,7 +293,6 @@ void waypoint_spawn_fromeditor(entity pl)
 
 void waypoint_remove(entity wp)
 {
-       // tell all waypoints linked to wp that they need to relink
        IL_EACH(g_waypoints, it != wp,
        {
                if (waypoint_islinked(it, wp))
@@ -718,6 +717,7 @@ bool waypoint_load_links()
 
        bool parse_comments = true;
        float ver = 0;
+       string links_time = string_null;
 
        while ((s = fgets(file)))
        {
@@ -727,13 +727,18 @@ bool waypoint_load_links()
                        {
                                if(substring(s, 2, 17) == "WAYPOINT_VERSION ")
                                        ver = stof(substring(s, 19, -1));
+                               else if(substring(s, 2, 14) == "WAYPOINT_TIME ")
+                                       links_time = substring(s, 16, -1);
                                continue;
                        }
                        else
                        {
-                               if(ver < WAYPOINT_VERSION)
+                               if(ver < WAYPOINT_VERSION || links_time != waypoint_time)
                                {
-                                       LOG_TRACE("waypoint links for this map are outdated.");
+                                       if (links_time != waypoint_time)
+                                               LOG_TRACE("waypoint links for this map are not made for these waypoints.");
+                                       else
+                                               LOG_TRACE("waypoint links for this map are outdated.");
                                        if (g_assault)
                                        {
                                                LOG_TRACE("Assault waypoint links need to be manually updated in the editor");
@@ -996,6 +1001,8 @@ void waypoint_save_links()
        }
 
        fputs(file, strcat("//", "WAYPOINT_VERSION ", ftos_decimals(WAYPOINT_VERSION, 2), "\n"));
+       if (waypoint_time != "")
+               fputs(file, strcat("//", "WAYPOINT_TIME ", waypoint_time, "\n"));
 
        int c = 0;
        IL_EACH(g_waypoints, true,
@@ -1063,7 +1070,12 @@ void waypoint_saveall()
        // (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("//", "WAYPOINT_SYMMETRY ", sym_str, "\n"));
-       fputs(file, strcat("//", "\n"));
+
+       strcpy(waypoint_time, strftime(true, "%Y-%m-%d %H:%M:%S"));
+       fputs(file, strcat("//", "WAYPOINT_TIME ", waypoint_time, "\n"));
+       //fputs(file, strcat("//", "\n"));
+       //fputs(file, strcat("//", "\n"));
+       //fputs(file, strcat("//", "\n"));
 
        int c = 0;
        IL_EACH(g_waypoints, true,
@@ -1135,6 +1147,8 @@ float waypoint_loadall()
                                        if (tokens > 2) { sym_param2 = stof(argv(2)); }
                                        if (tokens > 3) { sym_param3 = stof(argv(3)); }
                                }
+                               else if(substring(s, 2, 14) == "WAYPOINT_TIME ")
+                                       strcpy(waypoint_time, substring(s, 16, -1));
                                continue;
                        }
                        else
index 595c2d058fcc1cd82fa1a082ffd29096f90adc3b..34372fe9661f535439b4c815cb6ef5c632dac6c8 100644 (file)
@@ -6,7 +6,8 @@
 // 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.01
+const float WAYPOINT_VERSION = 1.01;
+string waypoint_time;
 
 // 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 43174dd5539253a0fbf4ebaaa7c7d0940ef37830..909e89768b866bad6e8516c50ba7e66946301064 100644 (file)
@@ -287,10 +287,8 @@ void PutObserverInServer(entity this)
        if (mutator_returnvalue) {
            // mutator prevents resetting teams+score
        } else {
-               int oldteam = this.team;
-               this.team = -1;  // move this as it is needed to log the player spectating in eventlog
-               MUTATOR_CALLHOOK(Player_ChangedTeam, this, oldteam, this.team);
-        this.frags = FRAGS_SPECTATOR;
+               Player_SetTeamIndex(this, -1);
+               this.frags = FRAGS_SPECTATOR;
         PlayerScore_Clear(this);  // clear scores when needed
     }
 
@@ -302,7 +300,7 @@ void PutObserverInServer(entity this)
                        Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS);
 
                if(!CS(this).just_joined)
-                       LogTeamchange(this.playerid, -1, 4);
+                       LogTeamchange(this.playerid, -1, TEAM_CHANGE_SPECTATOR);
                else
                        CS(this).just_joined = false;
        }
@@ -521,7 +519,7 @@ void PutPlayerInServer(entity this)
        accuracy_resend(this);
 
        if (this.team < 0)
-               JoinBestTeam(this, true);
+               TeamBalance_JoinBestTeam(this);
 
        entity spot = SelectSpawnPoint(this, false);
        if (!spot) {
@@ -754,6 +752,8 @@ void PutPlayerInServer(entity this)
 
        MUTATOR_CALLHOOK(PlayerWeaponSelect, this);
 
+       if (CS(this).impulse) ImpulseCommands(this);
+
        for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
        {
                .entity weaponentity = weaponentities[slot];
@@ -913,7 +913,7 @@ void ClientKill_Now_TeamChange(entity this)
 {
        if(this.killindicator_teamchange == -1)
        {
-               JoinBestTeam( this, true );
+               TeamBalance_JoinBestTeam(this);
        }
        else if(this.killindicator_teamchange == -2)
        {
@@ -1173,6 +1173,76 @@ void ClientPreConnect(entity this)
 }
 #endif
 
+string GetClientVersionMessage(entity this)
+{
+       if (CS(this).version_mismatch) {
+               if(CS(this).version < autocvar_gameversion) {
+                       return strcat("This is Xonotic ", autocvar_g_xonoticversion,
+                               "\n^3Your client version is outdated.\n\n\n### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###\n\n\nPlease update!!!^8");
+               } else {
+                       return strcat("This is Xonotic ", autocvar_g_xonoticversion,
+                               "\n^3This server is using an outdated Xonotic version.\n\n\n ### THIS SERVER IS INCOMPATIBLE AND THUS YOU CANNOT JOIN ###.^8");
+               }
+       } else {
+               return strcat("Welcome to Xonotic ", autocvar_g_xonoticversion);
+       }
+}
+
+string getwelcomemessage(entity this)
+{
+       MUTATOR_CALLHOOK(BuildMutatorsPrettyString, "");
+       string modifications = M_ARGV(0, string);
+
+       if(g_weaponarena)
+       {
+               if(g_weaponarena_random)
+                       modifications = strcat(modifications, ", ", ftos(g_weaponarena_random), " of ", g_weaponarena_list, " Arena");
+               else
+                       modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena");
+       }
+       else if(cvar("g_balance_blaster_weaponstartoverride") == 0)
+               modifications = strcat(modifications, ", No start weapons");
+       if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
+               modifications = strcat(modifications, ", Low gravity");
+       if(g_weapon_stay && !g_cts)
+               modifications = strcat(modifications, ", Weapons stay");
+       if(g_jetpack)
+               modifications = strcat(modifications, ", Jet pack");
+       if(autocvar_g_powerups == 0)
+               modifications = strcat(modifications, ", No powerups");
+       if(autocvar_g_powerups > 0)
+               modifications = strcat(modifications, ", Powerups");
+       modifications = substring(modifications, 2, strlen(modifications) - 2);
+
+       string versionmessage = GetClientVersionMessage(this);
+       string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n");
+
+       if(modifications != "")
+               s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
+
+       if(cache_lastmutatormsg != autocvar_g_mutatormsg)
+       {
+               strcpy(cache_lastmutatormsg, autocvar_g_mutatormsg);
+               strcpy(cache_mutatormsg, cache_lastmutatormsg);
+       }
+
+       if (cache_mutatormsg != "") {
+               s = strcat(s, "\n\n^8special gameplay tips: ^7", cache_mutatormsg);
+       }
+
+       string mutator_msg = "";
+       MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg);
+       mutator_msg = M_ARGV(0, string);
+
+       s = strcat(s, mutator_msg); // trust that the mutator will do proper formatting
+
+       string motd = autocvar_sv_motd;
+       if (motd != "") {
+               s = strcat(s, "\n\n^8MOTD: ^7", strreplace("\\n", "\n", motd));
+       }
+       return s;
+}
+
 /**
 =============
 ClientConnect
@@ -1193,6 +1263,10 @@ void ClientConnect(entity this)
        TRANSMUTE(Client, this);
        CS(this).version_nagtime = time + 10 + random() * 10;
 
+       Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_CONNECT, this.netname);
+
+       bot_clientconnect(this);
+
        // identify the right forced team
        if (autocvar_g_campaign)
        {
@@ -1226,11 +1300,6 @@ void ClientConnect(entity this)
        }
        if (!teamplay && this.team_forced > 0) this.team_forced = 0;
 
-       int playerid_save = this.playerid;
-       this.playerid = 0; // silent
-       JoinBestTeam(this, false); // if the team number is valid, keep it
-       this.playerid = playerid_save;
-
        TRANSMUTE(Observer, this);
 
        PlayerStats_GameReport_AddEvent(sprintf("kills-%d", this.playerid));
@@ -1244,15 +1313,8 @@ void ClientConnect(entity this)
        if (autocvar_sv_eventlog)
                GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", playername(this, false)));
 
-       LogTeamchange(this.playerid, this.team, 1);
-
        CS(this).just_joined = true;  // stop spamming the eventlog with additional lines when the client connects
 
-       if(teamplay && IS_PLAYER(this))
-               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_CONNECT_TEAM), this.netname);
-       else
-               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_CONNECT, this.netname);
-
        stuffcmd(this, clientstuff, "\n");
        stuffcmd(this, "cl_particles_reloadeffects\n"); // TODO do we still need this?
 
@@ -1264,12 +1326,9 @@ void ClientConnect(entity this)
        // notify about available teams
        if (teamplay)
        {
-               CheckAllowedTeams(this);
-               int t = 0;
-               if (c1 >= 0) t |= BIT(0);
-               if (c2 >= 0) t |= BIT(1);
-               if (c3 >= 0) t |= BIT(2);
-               if (c4 >= 0) t |= BIT(3);
+               entity balance = TeamBalance_CheckAllowedTeams(this);
+               int t = TeamBalance_GetAllowedTeams(balance);
+               TeamBalance_Destroy(balance);
                stuffcmd(this, sprintf("set _teams_available %d\n", t));
        }
        else
@@ -1521,7 +1580,7 @@ void DebugPrintToChatTeam(int team_num, string text)
 
 void play_countdown(entity this, float finished, Sound samp)
 {
-    TC(Sound, samp);
+       TC(Sound, samp);
        if(IS_REAL_CLIENT(this))
                if(floor(finished - time - frametime) != floor(finished - time))
                        if(finished - time < 6)
@@ -1801,7 +1860,7 @@ spectate mode routines
 
 void SpectateCopy(entity this, entity spectatee)
 {
-    TC(Client, this); TC(Client, spectatee);
+       TC(Client, this); TC(Client, spectatee);
 
        MUTATOR_CALLHOOK(SpectateCopy, spectatee, this);
        PS(this) = PS(spectatee);
@@ -2054,7 +2113,7 @@ void Join(entity this)
 
        if(!this.team_selected)
        if(autocvar_g_campaign || autocvar_g_balance_teams)
-               JoinBestTeam(this, true);
+               TeamBalance_JoinBestTeam(this);
 
        if(autocvar_g_campaign)
                campaign_bots_may_start = true;
@@ -2065,7 +2124,9 @@ void Join(entity this)
 
        if(IS_PLAYER(this))
        if(teamplay && this.team != -1)
-               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname);
+       {
+               //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname);
+       }
        else
                Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_PLAY, this.netname);
        this.team_selected = false;
index 9b7a0f6574fb78cf3636d8325b4bb7479f59ae47..04fb79d38ce6be8ad1d82911321424f0949aba56 100644 (file)
@@ -394,13 +394,16 @@ void ClientCommand_selectteam(entity caller, float request, float argc)
                        if ((selection != -1) && autocvar_g_balance_teams &&
                                autocvar_g_balance_teams_prevent_imbalance)
                        {
-                               CheckAllowedTeams(caller);
-                               GetTeamCounts(caller);
-                               if ((BIT(Team_TeamToNumber(selection) - 1) & FindBestTeams(caller, false)) == 0)
+                               entity balance = TeamBalance_CheckAllowedTeams(caller);
+                               TeamBalance_GetTeamCounts(balance, caller);
+                               if ((Team_IndexToBit(Team_TeamToIndex(selection)) &
+                                       TeamBalance_FindBestTeams(balance, caller, false)) == 0)
                                {
                                        Send_Notification(NOTIF_ONE, caller, MSG_INFO, INFO_TEAMCHANGE_LARGERTEAM);
+                                       TeamBalance_Destroy(balance);
                                        return;
                                }
+                               TeamBalance_Destroy(balance);
                        }
                        ClientKill_TeamChange(caller, selection);
                        if (!IS_PLAYER(caller))
@@ -667,8 +670,9 @@ void ClientCommand_(entity caller, float request)
 #define CLIENT_COMMANDS(ent, request, arguments, command) \
        CLIENT_COMMAND("autoswitch", ClientCommand_autoswitch(ent, request, arguments), "Whether or not to switch automatically when getting a better weapon") \
        CLIENT_COMMAND("clientversion", ClientCommand_clientversion(ent, request, arguments), "Release version of the game") \
-       CLIENT_COMMAND("mv_getpicture", ClientCommand_mv_getpicture(ent, request, arguments), "Retrieve mapshot picture from the server") \
        CLIENT_COMMAND("join", ClientCommand_join(ent, request), "Become a player in the game") \
+       CLIENT_COMMAND("minigame", ClientCommand_minigame(ent, request, arguments, command), "Start a minigame") \
+       CLIENT_COMMAND("mv_getpicture", ClientCommand_mv_getpicture(ent, request, arguments), "Retrieve mapshot picture from the server") \
        CLIENT_COMMAND("physics", ClientCommand_physics(ent, request, arguments), "Change physics set") \
        CLIENT_COMMAND("ready", ClientCommand_ready(ent, request), "Qualify as ready to end warmup stage (or restart server if allowed)") \
        CLIENT_COMMAND("say", ClientCommand_say(ent, request, arguments, command), "Print a message to chat to all players") \
@@ -680,7 +684,6 @@ void ClientCommand_(entity caller, float request)
        CLIENT_COMMAND("suggestmap", ClientCommand_suggestmap(ent, request, arguments), "Suggest a map to the mapvote at match end") \
        CLIENT_COMMAND("tell", ClientCommand_tell(ent, request, arguments, command), "Send a message directly to a player") \
        CLIENT_COMMAND("voice", ClientCommand_voice(ent, request, arguments, command), "Send voice message via sound") \
-       CLIENT_COMMAND("minigame", ClientCommand_minigame(ent, request, arguments, command), "Start a minigame") \
        /* nothing */
 
 void ClientCommand_macro_help(entity caller)
index cb8ab239fbebd1ac74b4781982d3d93ed14f43ac..eb22080bb7de33a1184acb91d5f2e464509ed5c9 100644 (file)
@@ -632,8 +632,8 @@ void CommonCommand_time(float request, entity caller)
                        print_to(caller, strcat("realtime = ", ftos(gettime(GETTIME_REALTIME))));
                        print_to(caller, strcat("hires = ", ftos(gettime(GETTIME_HIRES))));
                        print_to(caller, strcat("uptime = ", ftos(gettime(GETTIME_UPTIME))));
-                       print_to(caller, strcat("localtime = ", strftime(true, "%a %b %e %H:%M:%S %Z %Y")));
-                       print_to(caller, strcat("gmtime = ", strftime(false, "%a %b %e %H:%M:%S %Z %Y")));
+                       print_to(caller, strcat("localtime = ", strftime(true, "%a %b %d %H:%M:%S %Z %Y")));
+                       print_to(caller, strcat("gmtime = ", strftime(false, "%a %b %d %H:%M:%S %Z %Y")));
                        return;
                }
 
index 1076225d82acaf1e89a00432927c4c95b8593c34..9ba78c32a0546cce999d177a6649adfa8e0f42fb 100644 (file)
@@ -1057,6 +1057,7 @@ void GameCommand_moveplayer(float request, float argc)
 
                                                                // find the team to move the player to
                                                                team_id = Team_ColorToTeam(destination);
+                                                               entity balance;
                                                                if (team_id == client.team)  // already on the destination team
                                                                {
                                                                        // keep the forcing undone
@@ -1065,30 +1066,72 @@ void GameCommand_moveplayer(float request, float argc)
                                                                }
                                                                else if (team_id == 0)  // auto team
                                                                {
-                                                                       CheckAllowedTeams(client);
-                                                                       team_id = Team_NumberToTeam(FindSmallestTeam(client, false));
+                                                                       balance = TeamBalance_CheckAllowedTeams(client);
+                                                                       team_id = Team_IndexToTeam(TeamBalance_FindBestTeam(balance, client, false));
                                                                }
                                                                else
                                                                {
-                                                                       CheckAllowedTeams(client);
+                                                                       balance = TeamBalance_CheckAllowedTeams(client);
                                                                }
                                                                client.team_forced = save;
 
                                                                // Check to see if the destination team is even available
                                                                switch (team_id)
                                                                {
-                                                                       case NUM_TEAM_1: if (c1 == -1) { LOG_INFO("Sorry, can't move player to red team if it doesn't exist."); return; } break;
-                                                                       case NUM_TEAM_2: if (c2 == -1) { LOG_INFO("Sorry, can't move player to blue team if it doesn't exist."); return; } break;
-                                                                       case NUM_TEAM_3: if (c3 == -1) { LOG_INFO("Sorry, can't move player to yellow team if it doesn't exist."); return; } break;
-                                                                       case NUM_TEAM_4: if (c4 == -1) { LOG_INFO("Sorry, can't move player to pink team if it doesn't exist."); return; } break;
-
-                                                                       default: LOG_INFO("Sorry, can't move player here if team ", destination, " doesn't exist.");
+                                                                       case NUM_TEAM_1:
+                                                                       {
+                                                                               if (!TeamBalance_IsTeamAllowed(balance, 1))
+                                                                               {
+                                                                                       LOG_INFO("Sorry, can't move player to red team if it doesn't exist.");
+                                                                                       TeamBalance_Destroy(balance);
+                                                                                       return;
+                                                                               }
+                                                                               TeamBalance_Destroy(balance);
+                                                                               break;
+                                                                       }
+                                                                       case NUM_TEAM_2:
+                                                                       {
+                                                                               if (!TeamBalance_IsTeamAllowed(balance, 2))
+                                                                               {
+                                                                                       LOG_INFO("Sorry, can't move player to blue team if it doesn't exist.");
+                                                                                       TeamBalance_Destroy(balance);
+                                                                                       return;
+                                                                               }
+                                                                               TeamBalance_Destroy(balance);
+                                                                               break;
+                                                                       }
+                                                                       case NUM_TEAM_3:
+                                                                       {
+                                                                               if (!TeamBalance_IsTeamAllowed(balance, 3))
+                                                                               {
+                                                                                       LOG_INFO("Sorry, can't move player to yellow team if it doesn't exist.");
+                                                                                       TeamBalance_Destroy(balance);
+                                                                                       return;
+                                                                               }
+                                                                               TeamBalance_Destroy(balance);
+                                                                               break;
+                                                                       }
+                                                                       case NUM_TEAM_4:
+                                                                       {
+                                                                               if (!TeamBalance_IsTeamAllowed(balance, 4))
+                                                                               {
+                                                                                       LOG_INFO("Sorry, can't move player to pink team if it doesn't exist.");
+                                                                                       TeamBalance_Destroy(balance);
+                                                                                       return;
+                                                                               }
+                                                                               TeamBalance_Destroy(balance);
+                                                                               break;
+                                                                       }
+                                                                       default:
+                                                                       {
+                                                                               LOG_INFO("Sorry, can't move player here if team ", destination, " doesn't exist.");
                                                                                return;
+                                                                       }
                                                                }
 
                                                                // If so, lets continue and finally move the player
                                                                client.team_forced = 0;
-                                                               if (MoveToTeam(client, team_id, 6))
+                                                               if (MoveToTeam(client, Team_TeamToIndex(team_id), 6))
                                                                {
                                                                        successful = strcat(successful, (successful ? ", " : ""), playername(client, false));
                                                                        LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") has been moved to the ", Team_ColoredFullName(team_id), "^7.");
@@ -1279,16 +1322,23 @@ void GameCommand_shuffleteams(float request)
                        });
 
                        int number_of_teams = 0;
-                       CheckAllowedTeams(NULL);
-                       if (c1 >= 0) number_of_teams = max(1, number_of_teams);
-                       if (c2 >= 0) number_of_teams = max(2, number_of_teams);
-                       if (c3 >= 0) number_of_teams = max(3, number_of_teams);
-                       if (c4 >= 0) number_of_teams = max(4, number_of_teams);
+                       entity balance = TeamBalance_CheckAllowedTeams(NULL);
+                       for (int i = 1; i <= NUM_TEAMS; ++i)
+                       {
+                               if (TeamBalance_IsTeamAllowed(balance, i))
+                               {
+                                       number_of_teams = max(i, number_of_teams);
+                               }
+                       }
+                       TeamBalance_Destroy(balance);
 
                        int team_index = 0;
                        FOREACH_CLIENT_RANDOM(IS_PLAYER(it) || it.caplayer, {
-                               int target_team_number = Team_NumberToTeam(team_index + 1);
-                               if (it.team != target_team_number) MoveToTeam(it, target_team_number, 6);
+                               int target_team_index = team_index + 1;
+                               if (Entity_GetTeamIndex(it) != target_team_index)
+                               {
+                                       MoveToTeam(it, target_team_index, 6);
+                               }
                                team_index = (team_index + 1) % number_of_teams;
                        });
 
index 5f034f12f88534e9f644eeba88bed1351246ecb2..b990888e6a1e2fa6e49974e3507067cfe11b3220 100644 (file)
@@ -10,6 +10,7 @@
 
 #include "../g_damage.qh"
 #include "../g_world.qh"
+#include "../teamplay.qh"
 #include "../race.qh"
 #include "../round_handler.qh"
 #include "../scores.qh"
index e830fe6c4fe8ed7caf27748935faa8d41cdd4967..c80da0af3772cf40ddd744cf1c471f0268702e23 100644 (file)
@@ -15,4 +15,4 @@ SPAWNFUNC_ITEM(item_spikes, ITEM_Bullets)
 //spawnfunc(item_armor1) {spawnfunc_item_armor_medium(this);}  // FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
 SPAWNFUNC_ITEM(item_armor2, ITEM_ArmorMega)
 SPAWNFUNC_ITEM(item_armorInv, ITEM_ArmorMega) // TODO: make sure we actually want this
-spawnfunc(item_health) {if (this.spawnflags & 2) StartItem(this, ITEM_HealthMega);else StartItem(this, ITEM_HealthMedium);}
+SPAWNFUNC_ITEM_COND(item_health, (this.spawnflags & 2), ITEM_HealthMega, ITEM_HealthMedium)
index 4c23aaeb3b956f6706b8dcea57db48f1c4231f01..d2a695aeb988c274df6e478527ae09cfbee8f753 100644 (file)
@@ -27,8 +27,6 @@ float bots_would_leave;
 void UpdateFrags(entity player, int f);
 .float totalfrags;
 
-float team1_score, team2_score, team3_score, team4_score;
-
 // flag set on worldspawn so that the code knows if it is dedicated or not
 float server_is_dedicated;
 
@@ -231,8 +229,6 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d
 // WEAPONTODO
 #define DMG_NOWEP (weaponentities[0])
 
-float lockteams;
-
 float sv_maxidle;
 float sv_maxidle_spectatorsareidle;
 int sv_maxidle_slots;
index 38284c30decd8a5b3adae3fbebe9039ef7e560ef..a25ae5bec9f878d9ba5feca5a6bb2f7e7c55bae6 100644 (file)
@@ -35,7 +35,7 @@ void UpdateFrags(entity player, int f)
        GameRules_scoring_add_team(player, SCORE, f);
 }
 
-void GiveFrags (entity attacker, entity targ, float f, int deathtype, .entity weaponentity)
+void GiveFrags(entity attacker, entity targ, float f, int deathtype, .entity weaponentity)
 {
        // TODO route through PlayerScores instead
        if(game_stopped) return;
@@ -566,7 +566,7 @@ void Unfreeze(entity targ)
        MUTATOR_CALLHOOK(Unfreeze, targ);
 }
 
-void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
+void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
 {
        float complainteamdamage = 0;
        float mirrordamage = 0;
@@ -1040,9 +1040,9 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
                                                }
 
                                                if(targ == directhitentity || DEATH_ISSPECIAL(deathtype))
-                                                       Damage (targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force);
+                                                       Damage(targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force);
                                                else
-                                                       Damage (targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, weaponentity, nearest, force);
+                                                       Damage(targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, weaponentity, nearest, force);
                                        }
                                }
                        }
@@ -1058,9 +1058,9 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in
        return total_damage_to_creatures;
 }
 
-float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity)
+float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity)
 {
-       return RadiusDamageForSource (inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, false, forceintensity, deathtype, weaponentity, directhitentity);
+       return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, false, forceintensity, deathtype, weaponentity, directhitentity);
 }
 
 bool Heal(entity targ, entity inflictor, float amount, float limit)
index d482f092d8db8df81741f08e5b8a770bbc0ce32f..68aa7154ecdc3928261ea584bd251be2c86d2c03 100644 (file)
@@ -328,7 +328,6 @@ void GrapplingHookTouch(entity this, entity toucher)
 
        if(toucher)
                //if(toucher.move_movetype != MOVETYPE_NONE)
-               if(!(toucher.flags & FL_PROJECTILE) || toucher.classname == "nade")
                {
                        SetMovetypeFollow(this, toucher);
                        WarpZone_RefSys_BeginAddingIncrementally(this, this.aiment);
index 26a4cfb08685c3d16f58f8acd5416d693ed65b18..038936ee49282bff375700dd76159197aea86d8f 100644 (file)
@@ -16,6 +16,7 @@
 #include <server/mutators/_mod.qh>
 #include "race.qh"
 #include "scores.qh"
+#include "scores_rules.qh"
 #include "teamplay.qh"
 #include "weapons/weaponstats.qh"
 #include "../common/constants.qh"
@@ -578,6 +579,58 @@ STATIC_INIT_EARLY(maxclients)
        }
 }
 
+void default_delayedinit(entity this)
+{
+       if(!scores_initialized)
+               ScoreRules_generic();
+}
+
+void InitGameplayMode()
+{
+       VoteReset();
+
+       // find out good world mins/maxs bounds, either the static bounds found by looking for solid, or the mapinfo specified bounds
+       get_mi_min_max(1);
+       // assign reflectively to avoid "assignment to world" warning
+       int done = 0; for (int i = 0, n = numentityfields(); i < n; ++i) {
+           string k = entityfieldname(i); vector v = (k == "mins") ? mi_min : (k == "maxs") ? mi_max : '0 0 0';
+           if (v) {
+            putentityfieldstring(i, world, sprintf("%v", v));
+            if (++done == 2) break;
+        }
+       }
+       // currently, NetRadiant's limit is 131072 qu for each side
+       // distance from one corner of a 131072qu cube to the opposite corner is approx. 227023 qu
+       // set the distance according to map size but don't go over the limit to avoid issues with float precision
+       // in case somebody makes extremely large maps
+       max_shot_distance = min(230000, vlen(world.maxs - world.mins));
+
+       MapInfo_LoadMapSettings(mapname);
+       GameRules_teams(false);
+
+       if (!cvar_value_issafe(world.fog))
+       {
+               LOG_INFO("The current map contains a potentially harmful fog setting, ignored");
+               world.fog = string_null;
+       }
+       if(MapInfo_Map_fog != "")
+               if(MapInfo_Map_fog == "none")
+                       world.fog = string_null;
+               else
+                       world.fog = strzone(MapInfo_Map_fog);
+       clientstuff = strzone(MapInfo_Map_clientstuff);
+
+       MapInfo_ClearTemps();
+
+       gamemode_name = MapInfo_Type_ToText(MapInfo_LoadedGametype);
+
+       cache_mutatormsg = strzone("");
+       cache_lastmutatormsg = strzone("");
+
+       InitializeEntity(NULL, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK);
+}
+
+void Map_MarkAsRecent(string m);
 float world_already_spawned;
 spawnfunc(worldspawn)
 {
@@ -1646,10 +1699,11 @@ float WinningCondition_Scores(float limit, float leadlimit)
 
        if(teamplay)
        {
-               team1_score = TeamScore_GetCompareValue(NUM_TEAM_1);
-               team2_score = TeamScore_GetCompareValue(NUM_TEAM_2);
-               team3_score = TeamScore_GetCompareValue(NUM_TEAM_3);
-               team4_score = TeamScore_GetCompareValue(NUM_TEAM_4);
+               for (int i = 1; i < 5; ++i)
+               {
+                       Team_SetTeamScore(Team_GetTeamFromIndex(i),
+                               TeamScore_GetCompareValue(Team_IndexToTeam(i)));
+               }
        }
 
        ClearWinners();
@@ -1719,30 +1773,32 @@ float WinningCondition_RanOutOfSpawns()
        if(!some_spawn_has_been_used)
                return WINNING_NO;
 
-       team1_score = team2_score = team3_score = team4_score = 0;
-
-       FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it), {
-               switch(it.team)
+       for (int i = 1; i < 5; ++i)
+       {
+               Team_SetTeamScore(Team_GetTeamFromIndex(i), 0);
+       }
+       
+       FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it),
+       {
+               if (Team_IsValidTeam(it.team))
                {
-                       case NUM_TEAM_1: team1_score = 1; break;
-                       case NUM_TEAM_2: team2_score = 1; break;
-                       case NUM_TEAM_3: team3_score = 1; break;
-                       case NUM_TEAM_4: team4_score = 1; break;
+                       Team_SetTeamScore(Team_GetTeam(it.team), 1);
                }
        });
 
        IL_EACH(g_spawnpoints, true,
        {
-               switch(it.team)
+               if (Team_IsValidTeam(it.team))
                {
-                       case NUM_TEAM_1: team1_score = 1; break;
-                       case NUM_TEAM_2: team2_score = 1; break;
-                       case NUM_TEAM_3: team3_score = 1; break;
-                       case NUM_TEAM_4: team4_score = 1; break;
+                       Team_SetTeamScore(Team_GetTeam(it.team), 1);
                }
        });
 
        ClearWinners();
+       float team1_score = Team_GetTeamScore(Team_GetTeamFromIndex(1));
+       float team2_score = Team_GetTeamScore(Team_GetTeamFromIndex(2));
+       float team3_score = Team_GetTeamScore(Team_GetTeamFromIndex(3));
+       float team4_score = Team_GetTeamScore(Team_GetTeamFromIndex(4));
        if(team1_score + team2_score + team3_score + team4_score == 0)
        {
                checkrules_equality = true;
@@ -1752,20 +1808,28 @@ float WinningCondition_RanOutOfSpawns()
        {
                float t, i;
                if(team1_score)
-                       t = NUM_TEAM_1;
+                       t = 1;
                else if(team2_score)
-                       t = NUM_TEAM_2;
+                       t = 2;
                else if(team3_score)
-                       t = NUM_TEAM_3;
+                       t = 3;
                else // if(team4_score)
-                       t = NUM_TEAM_4;
-               CheckAllowedTeams(NULL);
+                       t = 4;
+               entity balance = TeamBalance_CheckAllowedTeams(NULL);
                for(i = 0; i < MAX_TEAMSCORE; ++i)
                {
-                       if(t != NUM_TEAM_1) if(c1 >= 0) TeamScore_AddToTeam(NUM_TEAM_1, i, -1000);
-                       if(t != NUM_TEAM_2) if(c2 >= 0) TeamScore_AddToTeam(NUM_TEAM_2, i, -1000);
-                       if(t != NUM_TEAM_3) if(c3 >= 0) TeamScore_AddToTeam(NUM_TEAM_3, i, -1000);
-                       if(t != NUM_TEAM_4) if(c4 >= 0) TeamScore_AddToTeam(NUM_TEAM_4, i, -1000);
+                       for (int j = 1; j <= NUM_TEAMS; ++j)
+                       {
+                               if (t == j)
+                               {
+                                       continue;
+                               }
+                               if (!TeamBalance_IsTeamAllowed(balance, j))
+                               {
+                                       continue;
+                               }
+                               TeamScore_AddToTeam(Team_IndexToTeam(j), i, -1000);
+                       }
                }
 
                AddWinners(team, t);
index c0c35589a865f476ea08d006f5f43c2ab7996ac6..da950f18575e28a410fbed9955b90a0a5ced4ed7 100644 (file)
@@ -5,6 +5,9 @@ float checkrules_suddendeathwarning;
 float checkrules_suddendeathend;
 float checkrules_overtimesadded; //how many overtimes have been already added
 
+string cache_mutatormsg;
+string cache_lastmutatormsg;
+
 const int WINNING_NO = 0; // no winner, but time limits may terminate the game
 const int WINNING_YES = 1; // winner found
 const int WINNING_NEVER = 2; // no winner, enter overtime if time limit is reached
index a4cf9df8ef30cc5e6554f4403112a28723a07e84..58e9ca127dabb4fb3183616f7815885fcfafa861 100644 (file)
@@ -137,40 +137,51 @@ MUTATOR_HOOKABLE(GiveFragsForKill, EV_GiveFragsForKill);
 /** called when the match ends */
 MUTATOR_HOOKABLE(MatchEnd, EV_NO_ARGS);
 
-/** allows adjusting allowed teams */
-#define EV_CheckAllowedTeams(i, o) \
+/** Allows adjusting allowed teams. Return true to use the bitmask value and set
+ * non-empty string to use team entity name. Both behaviors can be active at the
+ * same time and will stack allowed teams.
+ */
+#define EV_TeamBalance_CheckAllowedTeams(i, o) \
     /** mask of teams      */ i(float, MUTATOR_ARGV_0_float) \
     /**/                      o(float, MUTATOR_ARGV_0_float) \
     /** team entity name   */ i(string, MUTATOR_ARGV_1_string) \
     /**/                      o(string, MUTATOR_ARGV_1_string) \
     /** player checked     */ i(entity, MUTATOR_ARGV_2_entity) \
     /**/
-MUTATOR_HOOKABLE(CheckAllowedTeams, EV_CheckAllowedTeams);
+MUTATOR_HOOKABLE(TeamBalance_CheckAllowedTeams,
+       EV_TeamBalance_CheckAllowedTeams);
 
 /** return true to manually override team counts */
-MUTATOR_HOOKABLE(GetTeamCounts, EV_NO_ARGS);
+MUTATOR_HOOKABLE(TeamBalance_GetTeamCounts, EV_NO_ARGS);
 
-/** allow overriding of team counts */
-#define EV_GetTeamCount(i, o) \
-    /** team to count                   */ i(float, MUTATOR_ARGV_0_float) \
+/** allows overriding of team counts */
+#define EV_TeamBalance_GetTeamCount(i, o) \
+    /** team index to count             */ i(float, MUTATOR_ARGV_0_float) \
     /** player to ignore                */ i(entity, MUTATOR_ARGV_1_entity) \
-    /** number of players in a team     */ i(float, MUTATOR_ARGV_2_float) \
-    /**/                                   o(float, MUTATOR_ARGV_2_float) \
-    /** number of bots in a team        */ i(float, MUTATOR_ARGV_3_float) \
-    /**/                                   o(float, MUTATOR_ARGV_3_float) \
-    /** lowest scoring human in a team  */ i(entity, MUTATOR_ARGV_4_entity) \
-    /**/                                   o(entity, MUTATOR_ARGV_4_entity) \
-    /** lowest scoring bot in a team    */ i(entity, MUTATOR_ARGV_5_entity) \
-    /**/                                   o(entity, MUTATOR_ARGV_5_entity) \
-    /**/
-MUTATOR_HOOKABLE(GetTeamCount, EV_GetTeamCount);
-
-/** allows overriding best teams */
-#define EV_FindBestTeams(i, o) \
+    /** number of players in a team     */ o(float, MUTATOR_ARGV_2_float) \
+    /** number of bots in a team        */ o(float, MUTATOR_ARGV_3_float) \
+    /**/
+MUTATOR_HOOKABLE(TeamBalance_GetTeamCount, EV_TeamBalance_GetTeamCount);
+
+/** allows overriding the teams that will make the game most balanced if the
+ *  player joins any of them.
+ */
+#define EV_TeamBalance_FindBestTeams(i, o) \
     /** player checked   */ i(entity, MUTATOR_ARGV_0_entity) \
     /** bitmask of teams */ o(float, MUTATOR_ARGV_1_float) \
     /**/
-MUTATOR_HOOKABLE(FindBestTeams, EV_FindBestTeams);
+MUTATOR_HOOKABLE(TeamBalance_FindBestTeams, EV_TeamBalance_FindBestTeams);
+
+/** Called during autobalance. Return true to override the player that will be
+switched. */
+#define EV_TeamBalance_GetPlayerForTeamSwitch(i, o) \
+    /** source team index      */ i(int, MUTATOR_ARGV_0_int) \
+    /** destination team index */ i(int, MUTATOR_ARGV_1_int) \
+    /** is looking for bot     */ i(bool, MUTATOR_ARGV_2_bool) \
+    /** player to switch       */ o(entity, MUTATOR_ARGV_3_entity) \
+    /**/
+MUTATOR_HOOKABLE(TeamBalance_GetPlayerForTeamSwitch,
+       EV_TeamBalance_GetPlayerForTeamSwitch);
 
 /** copies variables for spectating "spectatee" to "this" */
 #define EV_SpectateCopy(i, o) \
@@ -1041,9 +1052,9 @@ MUTATOR_HOOKABLE(MonsterModel, EV_MonsterModel);
  * Called before player changes their team. Return true to block team change.
  */
 #define EV_Player_ChangeTeam(i, o) \
-    /** player */         i(entity, MUTATOR_ARGV_0_entity) \
-       /** current team */   i(float, MUTATOR_ARGV_1_float) \
-       /** new team */       i(float, MUTATOR_ARGV_2_float) \
+    /** player */             i(entity, MUTATOR_ARGV_0_entity) \
+    /** current team index */ i(float, MUTATOR_ARGV_1_float) \
+    /** new team index */     i(float, MUTATOR_ARGV_2_float) \
     /**/
 MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam);
 
@@ -1051,9 +1062,9 @@ MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam);
  * Called after player has changed their team.
  */
 #define EV_Player_ChangedTeam(i, o) \
-    /** player */         i(entity, MUTATOR_ARGV_0_entity) \
-       /** old team */       i(float, MUTATOR_ARGV_1_float) \
-       /** current team */   i(float, MUTATOR_ARGV_2_float) \
+    /** player */             i(entity, MUTATOR_ARGV_0_entity) \
+    /** old team index */     i(float, MUTATOR_ARGV_1_float) \
+    /** current team index */ i(float, MUTATOR_ARGV_2_float) \
     /**/
 MUTATOR_HOOKABLE(Player_ChangedTeam, EV_Player_ChangedTeam);
 
index cc58cdc6d7ca7e2bc493b9c2bd1518a3aaa3bbe2..3755da96386ed98e6b10f9a754185a7f6b487951 100644 (file)
@@ -462,6 +462,16 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
                                this.v_angle_y = this.v_angle.y + (random() * 2 - 1) * shake;
                                this.v_angle_x = bound(-90, this.v_angle.x, 90);
                        }
+
+                       if (this != attacker) {
+                               float realdmg = damage - excess;
+                               if (IS_PLAYER(attacker)) {
+                                       GameRules_scoring_add(attacker, DMG, realdmg);
+                               }
+                               if (IS_PLAYER(this)) {
+                                       GameRules_scoring_add(this, DMGTAKEN, realdmg);
+                               }
+                       }
                }
                else
                        this.max_armorvalue += (save + take);
@@ -470,16 +480,6 @@ void PlayerDamage(entity this, entity inflictor, entity attacker, float damage,
        this.dmg_take = this.dmg_take + take;//max(take - 10, 0);
        this.dmg_inflictor = inflictor;
 
-       if (this != attacker) {
-               float realdmg = damage - excess;
-               if (IS_PLAYER(attacker)) {
-                       GameRules_scoring_add(attacker, DMG, realdmg);
-               }
-               if (IS_PLAYER(this)) {
-                       GameRules_scoring_add(this, DMGTAKEN, realdmg);
-               }
-       }
-
        bool abot = (IS_BOT_CLIENT(attacker));
        bool vbot = (IS_BOT_CLIENT(this));
 
@@ -675,21 +675,6 @@ bool PlayerHeal(entity targ, entity inflictor, float amount, float limit)
        return true;
 }
 
-bool MoveToTeam(entity client, int team_colour, int type)
-{
-       int lockteams_backup = lockteams;  // backup any team lock
-       lockteams = 0;  // disable locked teams
-       TeamchangeFrags(client);  // move the players frags
-       if (!SetPlayerTeamSimple(client, team_colour))
-       {
-               return false;
-       }
-       Damage(client, client, client, 100000, DEATH_AUTOTEAMCHANGE.m_id, DMG_NOWEP, client.origin, '0 0 0');  // kill the player
-       lockteams = lockteams_backup;  // restore the team lock
-       LogTeamchange(client.playerid, client.team, type);
-       return true;
-}
-
 /**
  * message "": do not say, just test flood control
  * return value:
index 8c9bac9b62aaa8e94ea4a594e33f6b680f67d74c..1c38a9fbebf3012b1d87029e26659457d7548a1c 100644 (file)
@@ -30,13 +30,6 @@ void calculate_player_respawn_time(entity this);
 
 void ClientKill_Now_TeamChange(entity this);
 
-/// \brief Moves player to the specified team.
-/// \param[in,out] client Client to move.
-/// \param[in] team_colour Color of the team.
-/// \param[in] type ???
-/// \return True on success, false otherwise.
-bool MoveToTeam(entity client, float team_colour, float type);
-
 void PlayerDamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
 
 bool PlayerHeal(entity targ, entity inflictor, float amount, float limit);
index 160b5df5e4cfb21c279b96c39d28dbe6965b27d4..39dbd49a35ddc630c85c849624330e1785d30d01 100644 (file)
@@ -17,8 +17,6 @@ int NumTeams(int teams)
 int AvailableTeams()
 {
        return NumTeams(ScoreRules_teams);
-       // NOTE: this method is unreliable, as forced teams set the c* globals to weird values
-       //return boolean(c1 >= 0) + boolean(c2 >= 0) + boolean(c3 >= 0) + boolean(c4 >= 0);
 }
 
 // NOTE: ST_constants may not be >= MAX_TEAMSCORE
@@ -64,12 +62,11 @@ void ScoreRules_basics_end()
 void ScoreRules_generic()
 {
     int teams = 0;
-       if (teamplay) {
-               CheckAllowedTeams(NULL);
-               if (c1 >= 0) teams |= BIT(0);
-               if (c2 >= 0) teams |= BIT(1);
-               if (c3 >= 0) teams |= BIT(2);
-               if (c4 >= 0) teams |= BIT(3);
+       if (teamplay)
+       {
+               entity balance = TeamBalance_CheckAllowedTeams(NULL);
+               teams = TeamBalance_GetAllowedTeams(balance);
+               TeamBalance_Destroy(balance);
        }
        GameRules_scoring(teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, {});
 }
index b0d9e0992eb921c204451f24b48877010c082369..2c41ae18bdfc77b22113f5f36f40df8cb5d7ba23 100644 (file)
 #include <common/gamemodes/_mod.qh>
 #include "../common/teams.qh"
 
-void TeamchangeFrags(entity e)
+/// \brief Describes a state of team balance entity.
+enum
 {
-       PlayerScore_Clear(e);
-}
+       TEAM_BALANCE_UNINITIALIZED, ///< The team balance has not been initialized.
+       /// \brief TeamBalance_CheckAllowedTeams has been called.
+       TEAM_BALANCE_TEAMS_CHECKED,
+       /// \brief TeamBalance_GetTeamCounts has been called.
+       TEAM_BALANCE_TEAM_COUNTS_FILLED
+};
 
-void LogTeamchange(float player_id, float team_number, float type)
-{
-       if(!autocvar_sv_eventlog)
-               return;
+/// \brief Indicates that the player is not allowed to join a team.
+const int TEAM_NOT_ALLOWED = -1;
 
-       if(player_id < 1)
-               return;
+.int m_team_balance_state; ///< Holds the state of the team balance entity.
+.entity m_team_balance_team[NUM_TEAMS]; ///< ???
 
-       GameLogEcho(strcat(":team:", ftos(player_id), ":", ftos(team_number), ":", ftos(type)));
-}
+.float m_team_score; ///< The score of the team.
+.int m_num_players; ///< Number of players (both humans and bots) in a team.
+.int m_num_bots; ///< Number of bots in a team.
+.int m_num_players_alive; ///< Number of alive players in a team.
+.int m_num_control_points; ///< Number of control points owned by a team.
+
+entity g_team_entities[NUM_TEAMS]; ///< Holds global team entities.
 
-void default_delayedinit(entity this)
+STATIC_INIT(g_team_entities)
 {
-       if(!scores_initialized)
-               ScoreRules_generic();
+       for (int i = 0; i < NUM_TEAMS; ++i)
+       {
+               g_team_entities[i] = spawn();
+       }
 }
 
-void InitGameplayMode()
+entity Team_GetTeamFromIndex(int index)
 {
-       VoteReset();
-
-       // find out good world mins/maxs bounds, either the static bounds found by looking for solid, or the mapinfo specified bounds
-       get_mi_min_max(1);
-       // assign reflectively to avoid "assignment to world" warning
-       int done = 0; for (int i = 0, n = numentityfields(); i < n; ++i) {
-           string k = entityfieldname(i); vector v = (k == "mins") ? mi_min : (k == "maxs") ? mi_max : '0 0 0';
-           if (v) {
-            putentityfieldstring(i, world, sprintf("%v", v));
-            if (++done == 2) break;
-        }
-       }
-       // currently, NetRadiant's limit is 131072 qu for each side
-       // distance from one corner of a 131072qu cube to the opposite corner is approx. 227023 qu
-       // set the distance according to map size but don't go over the limit to avoid issues with float precision
-       // in case somebody makes extremely large maps
-       max_shot_distance = min(230000, vlen(world.maxs - world.mins));
-
-       MapInfo_LoadMapSettings(mapname);
-       GameRules_teams(false);
-
-       if (!cvar_value_issafe(world.fog))
-       {
-               LOG_INFO("The current map contains a potentially harmful fog setting, ignored");
-               world.fog = string_null;
-       }
-       if(MapInfo_Map_fog != "")
-               if(MapInfo_Map_fog == "none")
-                       world.fog = string_null;
-               else
-                       world.fog = strzone(MapInfo_Map_fog);
-       clientstuff = strzone(MapInfo_Map_clientstuff);
-
-       MapInfo_ClearTemps();
-
-       gamemode_name = MapInfo_Type_ToText(MapInfo_LoadedGametype);
-
-       cache_mutatormsg = strzone("");
-       cache_lastmutatormsg = strzone("");
-
-       InitializeEntity(NULL, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK);
+       if (!Team_IsValidIndex(index))
+       {
+               LOG_FATALF("Team_GetTeamFromIndex: Index is invalid: %f", index);
+       }
+       return g_team_entities[index - 1];
 }
 
-string GetClientVersionMessage(entity this)
+entity Team_GetTeam(int team_num)
 {
-       if (CS(this).version_mismatch) {
-               if(CS(this).version < autocvar_gameversion) {
-                       return strcat("This is Xonotic ", autocvar_g_xonoticversion,
-                               "\n^3Your client version is outdated.\n\n\n### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###\n\n\nPlease update!!!^8");
-               } else {
-                       return strcat("This is Xonotic ", autocvar_g_xonoticversion,
-                               "\n^3This server is using an outdated Xonotic version.\n\n\n ### THIS SERVER IS INCOMPATIBLE AND THUS YOU CANNOT JOIN ###.^8");
-               }
-       } else {
-               return strcat("Welcome to Xonotic ", autocvar_g_xonoticversion);
+       if (!Team_IsValidTeam(team_num))
+       {
+               LOG_FATALF("Team_GetTeam: Value is invalid: %f", team_num);
        }
+       return g_team_entities[Team_TeamToIndex(team_num) - 1];
 }
 
-string getwelcomemessage(entity this)
+float Team_GetTeamScore(entity team_ent)
 {
-       MUTATOR_CALLHOOK(BuildMutatorsPrettyString, "");
-       string modifications = M_ARGV(0, string);
+       return team_ent.m_team_score;
+}
 
-       if(g_weaponarena)
-       {
-               if(g_weaponarena_random)
-                       modifications = strcat(modifications, ", ", ftos(g_weaponarena_random), " of ", g_weaponarena_list, " Arena"); // TODO: somehow get this into the mutator
-               else
-                       modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena");
-       }
-       else if(cvar("g_balance_blaster_weaponstartoverride") == 0)
-               modifications = strcat(modifications, ", No start weapons");
-       if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity")))
-               modifications = strcat(modifications, ", Low gravity");
-       if(g_weapon_stay && !g_cts)
-               modifications = strcat(modifications, ", Weapons stay");
-       if(g_jetpack)
-               modifications = strcat(modifications, ", Jetpack");
-       if(autocvar_g_powerups == 0)
-               modifications = strcat(modifications, ", No powerups");
-       if(autocvar_g_powerups > 0)
-               modifications = strcat(modifications, ", Powerups");
-       modifications = substring(modifications, 2, strlen(modifications) - 2);
+void Team_SetTeamScore(entity team_ent, float score)
+{
+       team_ent.m_team_score = score;
+}
 
-       string versionmessage = GetClientVersionMessage(this);
-       string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n");
+int Team_GetNumberOfAlivePlayers(entity team_ent)
+{
+       return team_ent.m_num_players_alive;
+}
 
-       if(modifications != "")
-               s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n");
+void Team_SetNumberOfAlivePlayers(entity team_ent, int number)
+{
+       team_ent.m_num_players_alive = number;
+}
 
-       if(cache_lastmutatormsg != autocvar_g_mutatormsg)
+int Team_GetNumberOfAliveTeams()
+{
+       int result = 0;
+       for (int i = 0; i < NUM_TEAMS; ++i)
        {
-               strcpy(cache_lastmutatormsg, autocvar_g_mutatormsg);
-               strcpy(cache_mutatormsg, cache_lastmutatormsg);
-       }
-
-       if (cache_mutatormsg != "") {
-               s = strcat(s, "\n\n^8special gameplay tips: ^7", cache_mutatormsg);
+               if (g_team_entities[i].m_num_players_alive > 0)
+               {
+                       ++result;
+               }
        }
+       return result;
+}
 
-       string mutator_msg = "";
-       MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg);
-       mutator_msg = M_ARGV(0, string);
+int Team_GetNumberOfControlPoints(entity team_ent)
+{
+       return team_ent.m_num_control_points;
+}
 
-       s = strcat(s, mutator_msg); // trust that the mutator will do proper formatting
+void Team_SetNumberOfControlPoints(entity team_ent, int number)
+{
+       team_ent.m_num_control_points = number;
+}
 
-       string motd = autocvar_sv_motd;
-       if (motd != "") {
-               s = strcat(s, "\n\n^8MOTD: ^7", strreplace("\\n", "\n", motd));
+int Team_GetNumberOfTeamsWithControlPoints()
+{
+       int result = 0;
+       for (int i = 0; i < NUM_TEAMS; ++i)
+       {
+               if (g_team_entities[i].m_num_control_points > 0)
+               {
+                       ++result;
+               }
        }
-       return s;
+       return result;
 }
 
 void setcolor(entity this, int clr)
@@ -162,6 +131,26 @@ void setcolor(entity this, int clr)
 #endif
 }
 
+bool Entity_HasValidTeam(entity this)
+{
+       return Team_IsValidTeam(this.team);
+}
+
+int Entity_GetTeamIndex(entity this)
+{
+       return Team_TeamToIndex(this.team);
+}
+
+entity Entity_GetTeam(entity this)
+{
+       int index = Entity_GetTeamIndex(this);
+       if (!Team_IsValidIndex(index))
+       {
+               return NULL;
+       }
+       return Team_GetTeamFromIndex(index);
+}
+
 void SetPlayerColors(entity player, float _color)
 {
        float pants = _color & 0x0F;
@@ -176,748 +165,712 @@ void SetPlayerColors(entity player, float _color)
        }
 }
 
-void KillPlayerForTeamChange(entity player)
+bool Player_SetTeamIndex(entity player, int index)
 {
-       if (IS_DEAD(player))
+       int new_team = Team_IndexToTeam(index);
+       if (player.team == new_team)
        {
-               return;
+               if (new_team != -1)
+               {
+                       // This is important when players join the game and one of their
+                       // color matches the team color while other doesn't. For example
+                       // [BOT]Lion.
+                       SetPlayerColors(player, new_team - 1);
+               }
+               return true;
        }
-       if (MUTATOR_CALLHOOK(Player_ChangeTeamKill, player) == true)
+       int old_index = Team_TeamToIndex(player.team);
+       if (MUTATOR_CALLHOOK(Player_ChangeTeam, player, old_index, index) == true)
        {
-               return;
+               // Mutator has blocked team change.
+               return false;
        }
-       Damage(player, player, player, 100000, DEATH_TEAMCHANGE.m_id, DMG_NOWEP, player.origin,
-               '0 0 0');
+       if (new_team == -1)
+       {
+               player.team = -1;
+       }
+       else
+       {
+               SetPlayerColors(player, new_team - 1);
+       }
+       MUTATOR_CALLHOOK(Player_ChangedTeam, player, old_index, index);
+       return true;
 }
 
-bool SetPlayerTeamSimple(entity player, int team_num)
+bool SetPlayerTeam(entity player, int team_index, int type)
 {
-       if (player.team == team_num)
+       int old_team_index = Entity_GetTeamIndex(player);
+       if (!Player_SetTeamIndex(player, team_index))
        {
-               // This is important when players join the game and one of their color
-               // matches the team color while other doesn't. For example [BOT]Lion.
-               SetPlayerColors(player, team_num - 1);
-               return true;
+               return false;
        }
-       if (MUTATOR_CALLHOOK(Player_ChangeTeam, player, Team_TeamToNumber(
-               player.team), Team_TeamToNumber(team_num)) == true)
+       LogTeamchange(player.playerid, player.team, type);
+       if (team_index != old_team_index)
        {
-               // Mutator has blocked team change.
-               return false;
+               Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(player.team,
+                       INFO_JOIN_PLAY_TEAM), player.netname);
+               KillPlayerForTeamChange(player);
        }
-       int old_team = player.team;
-       SetPlayerColors(player, team_num - 1);
-       MUTATOR_CALLHOOK(Player_ChangedTeam, player, old_team, player.team);
        return true;
 }
 
-bool SetPlayerTeam(entity player, int destination_team, int source_team,
-       bool no_print)
+bool MoveToTeam(entity client, int team_index, int type)
 {
-       int team_num = Team_NumberToTeam(destination_team);
-       if (!SetPlayerTeamSimple(player, team_num))
+       //PrintToChatAll(sprintf("MoveToTeam: %s, %f", client.netname, team_index));
+       int lockteams_backup = lockteams;  // backup any team lock
+       lockteams = 0;  // disable locked teams
+       PlayerScore_Clear(client);
+       if (!SetPlayerTeam(client, team_index, type))
        {
+               lockteams = lockteams_backup;  // restore the team lock
                return false;
        }
-       LogTeamchange(player.playerid, player.team, 3);  // log manual team join
-       if (no_print)
+       lockteams = lockteams_backup;  // restore the team lock
+       return true;
+}
+
+void KillPlayerForTeamChange(entity player)
+{
+       if (IS_DEAD(player))
+       {
+               return;
+       }
+       if (MUTATOR_CALLHOOK(Player_ChangeTeamKill, player) == true)
        {
-               return true;
+               return;
        }
-       bprint(playername(player, false), "^7 has changed from ", Team_NumberToColoredFullName(source_team), "^7 to ", Team_NumberToColoredFullName(destination_team), "\n");
-       return true;
+       Damage(player, player, player, 100000, DEATH_TEAMCHANGE.m_id, DMG_NOWEP,
+               player.origin, '0 0 0');
 }
 
-// set c1...c4 to show what teams are allowed
-void CheckAllowedTeams(entity for_whom)
+void LogTeamchange(float player_id, float team_number, int type)
 {
-       int teams_mask = 0;
+       if(!autocvar_sv_eventlog)
+               return;
+
+       if(player_id < 1)
+               return;
 
-       c1 = c2 = c3 = c4 = -1;
-       num_bots_team1 = num_bots_team2 = num_bots_team3 = num_bots_team4 = 0;
+       GameLogEcho(strcat(":team:", ftos(player_id), ":", ftos(team_number), ":", ftos(type)));
+}
 
+entity TeamBalance_CheckAllowedTeams(entity for_whom)
+{
+       entity balance = spawn();
+       for (int i = 0; i < NUM_TEAMS; ++i)
+       {
+               entity team_ent = balance.m_team_balance_team[i] = spawn();
+               team_ent.m_team_score = g_team_entities[i].m_team_score;
+               team_ent.m_num_players = TEAM_NOT_ALLOWED;
+               team_ent.m_num_bots = 0;
+       }
+       setthink(balance, TeamBalance_Destroy);
+       
+       int teams_mask = 0;     
        string teament_name = string_null;
-
-       bool mutator_returnvalue = MUTATOR_CALLHOOK(CheckAllowedTeams, teams_mask, teament_name, for_whom);
+       bool mutator_returnvalue = MUTATOR_CALLHOOK(TeamBalance_CheckAllowedTeams,
+               teams_mask, teament_name, for_whom);
        teams_mask = M_ARGV(0, float);
        teament_name = M_ARGV(1, string);
-
-       if(!mutator_returnvalue)
+       if (mutator_returnvalue)
        {
-               if(teams_mask & BIT(0)) c1 = 0;
-               if(teams_mask & BIT(1)) c2 = 0;
-               if(teams_mask & BIT(2)) c3 = 0;
-               if(teams_mask & BIT(3)) c4 = 0;
+               for (int i = 0; i < NUM_TEAMS; ++i)
+               {
+                       if (teams_mask & BIT(i))
+                       {
+                               balance.m_team_balance_team[i].m_num_players = 0;
+                       }
+               }
        }
 
-       // find out what teams are allowed if necessary
-       if(teament_name)
+       if (teament_name)
        {
                entity head = find(NULL, classname, teament_name);
-               while(head)
+               while (head)
                {
-                       switch(head.team)
+                       if (Team_IsValidTeam(head.team))
                        {
-                               case NUM_TEAM_1: c1 = 0; break;
-                               case NUM_TEAM_2: c2 = 0; break;
-                               case NUM_TEAM_3: c3 = 0; break;
-                               case NUM_TEAM_4: c4 = 0; break;
+                               TeamBalance_GetTeam(balance, head.team).m_num_players = 0;
                        }
-
                        head = find(head, classname, teament_name);
                }
        }
 
        // TODO: Balance quantity of bots across > 2 teams when bot_vs_human is set (and remove next line)
-       if(AvailableTeams() == 2)
-       if(autocvar_bot_vs_human && for_whom)
+       if (AvailableTeams() == 2)
+       if (autocvar_bot_vs_human && for_whom)
        {
-               if(autocvar_bot_vs_human > 0)
+               if (autocvar_bot_vs_human > 0)
                {
                        // find last team available
-
-                       if(IS_BOT_CLIENT(for_whom))
+                       if (IS_BOT_CLIENT(for_whom))
                        {
-                               if(c4 >= 0) { c3 = c2 = c1 = -1; }
-                               else if(c3 >= 0) { c4 = c2 = c1 = -1; }
-                               else { c4 = c3 = c1 = -1; }
+                               if (TeamBalance_IsTeamAllowedInternal(balance, 4))
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 4);
+                               }
+                               else if (TeamBalance_IsTeamAllowedInternal(balance, 3))
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 3);
+                               }
+                               else
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 2);
+                               }
                                // no further cases, we know at least 2 teams exist
                        }
                        else
                        {
-                               if(c1 >= 0) { c2 = c3 = c4 = -1; }
-                               else if(c2 >= 0) { c1 = c3 = c4 = -1; }
-                               else { c1 = c2 = c4 = -1; }
+                               if (TeamBalance_IsTeamAllowedInternal(balance, 1))
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 1);
+                               }
+                               else if (TeamBalance_IsTeamAllowedInternal(balance, 2))
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 2);
+                               }
+                               else
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 3);
+                               }
                                // no further cases, bots have one of the teams
                        }
                }
                else
                {
                        // find first team available
-
-                       if(IS_BOT_CLIENT(for_whom))
+                       if (IS_BOT_CLIENT(for_whom))
                        {
-                               if(c1 >= 0) { c2 = c3 = c4 = -1; }
-                               else if(c2 >= 0) { c1 = c3 = c4 = -1; }
-                               else { c1 = c2 = c4 = -1; }
+                               if (TeamBalance_IsTeamAllowedInternal(balance, 1))
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 1);
+                               }
+                               else if (TeamBalance_IsTeamAllowedInternal(balance, 2))
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 2);
+                               }
+                               else
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 3);
+                               }
                                // no further cases, we know at least 2 teams exist
                        }
                        else
                        {
-                               if(c4 >= 0) { c3 = c2 = c1 = -1; }
-                               else if(c3 >= 0) { c4 = c2 = c1 = -1; }
-                               else { c4 = c3 = c1 = -1; }
+                               if (TeamBalance_IsTeamAllowedInternal(balance, 4))
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 4);
+                               }
+                               else if (TeamBalance_IsTeamAllowedInternal(balance, 3))
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 3);
+                               }
+                               else
+                               {
+                                       TeamBalance_BanTeamsExcept(balance, 2);
+                               }
                                // no further cases, bots have one of the teams
                        }
                }
        }
 
-       if(!for_whom)
-               return;
+       if (!for_whom)
+       {
+               balance.m_team_balance_state = TEAM_BALANCE_TEAMS_CHECKED;
+               return balance;
+       }
 
        // if player has a forced team, ONLY allow that one
-       if(for_whom.team_forced == NUM_TEAM_1 && c1 >= 0)
-               c2 = c3 = c4 = -1;
-       else if(for_whom.team_forced == NUM_TEAM_2 && c2 >= 0)
-               c1 = c3 = c4 = -1;
-       else if(for_whom.team_forced == NUM_TEAM_3 && c3 >= 0)
-               c1 = c2 = c4 = -1;
-       else if(for_whom.team_forced == NUM_TEAM_4 && c4 >= 0)
-               c1 = c2 = c3 = -1;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               if (for_whom.team_forced == Team_IndexToTeam(i) &&
+                       TeamBalance_IsTeamAllowedInternal(balance, i))
+               {
+                       TeamBalance_BanTeamsExcept(balance, i);
+               }
+               break;
+       }
+       balance.m_team_balance_state = TEAM_BALANCE_TEAMS_CHECKED;
+       return balance;
 }
 
-float PlayerValue(entity p)
+void TeamBalance_Destroy(entity balance)
 {
-       return 1;
-       // FIXME: it always returns 1...
+       if (balance == NULL)
+       {
+               return;
+       }
+       for (int i = 0; i < NUM_TEAMS; ++i)
+       {
+               delete(balance.(m_team_balance_team[i]));
+       }
+       delete(balance);
 }
 
-// c1...c4 should be set to -1 (not allowed) or 0 (allowed).
-// teams that are allowed will now have their player counts stored in c1...c4
-void GetTeamCounts(entity ignore)
+int TeamBalance_GetAllowedTeams(entity balance)
 {
-       if (MUTATOR_CALLHOOK(GetTeamCounts) == true)
+       if (balance == NULL)
        {
-               if (c1 >= 0)
-               {
-                       MUTATOR_CALLHOOK(GetTeamCount, NUM_TEAM_1, ignore, c1,
-                               num_bots_team1, lowest_human_team1, lowest_bot_team1);
-                       c1 = M_ARGV(2, float);
-                       num_bots_team1 = M_ARGV(3, float);
-                       lowest_human_team1 = M_ARGV(4, entity);
-                       lowest_bot_team1 = M_ARGV(5, entity);
-               }
-               if (c2 >= 0)
-               {
-                       MUTATOR_CALLHOOK(GetTeamCount, NUM_TEAM_2, ignore, c2,
-                               num_bots_team2, lowest_human_team2, lowest_bot_team2);
-                       c2 = M_ARGV(2, float);
-                       num_bots_team2 = M_ARGV(3, float);
-                       lowest_human_team2 = M_ARGV(4, entity);
-                       lowest_bot_team2 = M_ARGV(5, entity);
-               }
-               if (c3 >= 0)
+               LOG_FATAL("TeamBalance_GetAllowedTeams: Team balance entity is NULL.");
+       }
+       if (balance.m_team_balance_state == TEAM_BALANCE_UNINITIALIZED)
+       {
+               LOG_FATAL("TeamBalance_GetAllowedTeams: "
+                       "Team balance entity is not initialized.");
+       }
+       int result = 0;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
+       {
+               if (TeamBalance_IsTeamAllowedInternal(balance, i))
                {
-                       MUTATOR_CALLHOOK(GetTeamCount, NUM_TEAM_3, ignore, c3,
-                               num_bots_team3, lowest_human_team3, lowest_bot_team3);
-                       c3 = M_ARGV(2, float);
-                       num_bots_team3 = M_ARGV(3, float);
-                       lowest_human_team3 = M_ARGV(4, entity);
-                       lowest_bot_team3 = M_ARGV(5, entity);
+                       result |= Team_IndexToBit(i);
                }
-               if (c4 >= 0)
+       }
+       return result;
+}
+
+bool TeamBalance_IsTeamAllowed(entity balance, int index)
+{
+       if (balance == NULL)
+       {
+               LOG_FATAL("TeamBalance_IsTeamAllowed: Team balance entity is NULL.");
+       }
+       if (balance.m_team_balance_state == TEAM_BALANCE_UNINITIALIZED)
+       {
+               LOG_FATAL("TeamBalance_IsTeamAllowed: "
+                       "Team balance entity is not initialized.");
+       }
+       if (!Team_IsValidIndex(index))
+       {
+               LOG_FATALF("TeamBalance_IsTeamAllowed: Team index is invalid: %f",
+                       index);
+       }
+       return TeamBalance_IsTeamAllowedInternal(balance, index);
+}
+
+void TeamBalance_GetTeamCounts(entity balance, entity ignore)
+{
+       if (balance == NULL)
+       {
+               LOG_FATAL("TeamBalance_GetTeamCounts: Team balance entity is NULL.");
+       }
+       if (balance.m_team_balance_state == TEAM_BALANCE_UNINITIALIZED)
+       {
+               LOG_FATAL("TeamBalance_GetTeamCounts: "
+                       "Team balance entity is not initialized.");
+       }
+       if (MUTATOR_CALLHOOK(TeamBalance_GetTeamCounts) == true)
+       {
+               // Mutator has overriden the configuration.
+               for (int i = 1; i <= NUM_TEAMS; ++i)
                {
-                       MUTATOR_CALLHOOK(GetTeamCount, NUM_TEAM_4, ignore,
-                               c4, num_bots_team4, lowest_human_team4, lowest_bot_team4);
-                       c4 = M_ARGV(2, float);
-                       num_bots_team4 = M_ARGV(3, float);
-                       lowest_human_team4 = M_ARGV(4, entity);
-                       lowest_bot_team4 = M_ARGV(5, entity);
+                       entity team_ent = TeamBalance_GetTeamFromIndex(balance, i);
+                       if (TeamBalanceTeam_IsAllowed(team_ent))
+                       {
+                               MUTATOR_CALLHOOK(TeamBalance_GetTeamCount, i, ignore);
+                               team_ent.m_num_players = M_ARGV(2, float);
+                               team_ent.m_num_bots = M_ARGV(3, float);
+                       }
                }
        }
        else
        {
-               float value, bvalue;
-               // now count how many players are on each team already
-               float lowest_human_score1 = FLOAT_MAX;
-               float lowest_bot_score1 = FLOAT_MAX;
-               float lowest_human_score2 = FLOAT_MAX;
-               float lowest_bot_score2 = FLOAT_MAX;
-               float lowest_human_score3 = FLOAT_MAX;
-               float lowest_bot_score3 = FLOAT_MAX;
-               float lowest_human_score4 = FLOAT_MAX;
-               float lowest_bot_score4 = FLOAT_MAX;
+               // Manually count all players.
                FOREACH_CLIENT(true,
                {
-                       float t;
+                       if (it == ignore)
+                       {
+                               continue;
+                       }
+                       int team_num;
                        if (IS_PLAYER(it) || it.caplayer)
                        {
-                               t = it.team;
+                               team_num = it.team;
                        }
                        else if (it.team_forced > 0)
                        {
-                               t = it.team_forced; // reserve the spot
+                               team_num = it.team_forced; // reserve the spot
                        }
                        else
                        {
                                continue;
                        }
-                       if (it == ignore)
+                       if (!Team_IsValidTeam(team_num))
                        {
                                continue;
                        }
-                       value = PlayerValue(it);
-                       if (IS_BOT_CLIENT(it))
-                       {
-                               bvalue = value;
-                       }
-                       else
-                       {
-                               bvalue = 0;
-                       }
-                       if (value == 0)
+                       entity team_ent = TeamBalance_GetTeam(balance, team_num);
+                       if (!TeamBalanceTeam_IsAllowed(team_ent))
                        {
                                continue;
                        }
-                       switch (t)
+                       ++team_ent.m_num_players;
+                       if (IS_BOT_CLIENT(it))
                        {
-                               case NUM_TEAM_1:
-                               {
-                                       if (c1 < 0)
-                                       {
-                                               break;
-                                       }
-                                       c1 += value;
-                                       num_bots_team1 += bvalue;
-                                       float temp_score = PlayerScore_Get(it, SP_SCORE);
-                                       if (!bvalue)
-                                       {
-                                               if (temp_score < lowest_human_score1)
-                                               {
-                                                       lowest_human_team1 = it;
-                                                       lowest_human_score1 = temp_score;
-                                               }
-                                               break;
-                                       }
-                                       if (temp_score < lowest_bot_score1)
-                                       {
-                                               lowest_bot_team1 = it;
-                                               lowest_bot_score1 = temp_score;
-                                       }
-                                       break;
-                               }
-                               case NUM_TEAM_2:
-                               {
-                                       if (c2 < 0)
-                                       {
-                                               break;
-                                       }
-                                       c2 += value;
-                                       num_bots_team2 += bvalue;
-                                       float temp_score = PlayerScore_Get(it, SP_SCORE);
-                                       if (!bvalue)
-                                       {
-                                               if (temp_score < lowest_human_score2)
-                                               {
-                                                       lowest_human_team2 = it;
-                                                       lowest_human_score2 = temp_score;
-                                               }
-                                               break;
-                                       }
-                                       if (temp_score < lowest_bot_score2)
-                                       {
-                                               lowest_bot_team2 = it;
-                                               lowest_bot_score2 = temp_score;
-                                       }
-                                       break;
-                               }
-                               case NUM_TEAM_3:
-                               {
-                                       if (c3 < 0)
-                                       {
-                                               break;
-                                       }
-                                       c3 += value;
-                                       num_bots_team3 += bvalue;
-                                       float temp_score = PlayerScore_Get(it, SP_SCORE);
-                                       if (!bvalue)
-                                       {
-                                               if (temp_score < lowest_human_score3)
-                                               {
-                                                       lowest_human_team3 = it;
-                                                       lowest_human_score3 = temp_score;
-                                               }
-                                               break;
-                                       }
-                                       if (temp_score < lowest_bot_score3)
-                                       {
-                                               lowest_bot_team3 = it;
-                                               lowest_bot_score3 = temp_score;
-                                       }
-                                       break;
-                               }
-                               case NUM_TEAM_4:
-                               {
-                                       if (c4 < 0)
-                                       {
-                                               break;
-                                       }
-                                       c4 += value;
-                                       num_bots_team4 += bvalue;
-                                       float temp_score = PlayerScore_Get(it, SP_SCORE);
-                                       if (!bvalue)
-                                       {
-                                               if (temp_score < lowest_human_score4)
-                                               {
-                                                       lowest_human_team4 = it;
-                                                       lowest_human_score4 = temp_score;
-                                               }
-                                               break;
-                                       }
-                                       if (temp_score < lowest_bot_score4)
-                                       {
-                                               lowest_bot_team4 = it;
-                                               lowest_bot_score4 = temp_score;
-                                       }
-                                       break;
-                               }
+                               ++team_ent.m_num_bots;
                        }
                });
        }
 
        // if the player who has a forced team has not joined yet, reserve the spot
-       if(autocvar_g_campaign)
+       if (autocvar_g_campaign)
        {
-               switch(autocvar_g_campaign_forceteam)
+               if (Team_IsValidIndex(autocvar_g_campaign_forceteam))
                {
-                       case 1: if(c1 == num_bots_team1) ++c1; break;
-                       case 2: if(c2 == num_bots_team2) ++c2; break;
-                       case 3: if(c3 == num_bots_team3) ++c3; break;
-                       case 4: if(c4 == num_bots_team4) ++c4; break;
+                       entity team_ent = TeamBalance_GetTeamFromIndex(balance,
+                               autocvar_g_campaign_forceteam);
+                       if (team_ent.m_num_players == team_ent.m_num_bots)
+                       {
+                               ++team_ent.m_num_players;
+                       }
                }
        }
+       balance.m_team_balance_state = TEAM_BALANCE_TEAM_COUNTS_FILLED;
 }
 
-bool IsTeamSmallerThanTeam(int team_a, int team_b, entity player,
-       bool use_score)
+int TeamBalance_GetNumberOfPlayers(entity balance, int index)
 {
-       if (!Team_IsValidNumber(team_a))
+       if (balance == NULL)
        {
-               LOG_FATALF("IsTeamSmallerThanTeam: team_a is invalid: %f", team_a);
+               LOG_FATAL("TeamBalance_GetNumberOfPlayers: "
+                       "Team balance entity is NULL.");
        }
-       if (!Team_IsValidNumber(team_b))
+       if (balance.m_team_balance_state != TEAM_BALANCE_TEAM_COUNTS_FILLED)
        {
-               LOG_FATALF("IsTeamSmallerThanTeam: team_b is invalid: %f", team_b);
+               LOG_FATAL("TeamBalance_GetNumberOfPlayers: "
+                       "TeamBalance_GetTeamCounts has not been called.");
        }
-       if (team_a == team_b)
+       if (!Team_IsValidIndex(index))
        {
-               return false;
+               LOG_FATALF("TeamBalance_GetNumberOfPlayers: Team index is invalid: %f",
+                       index);
        }
-       // we assume that CheckAllowedTeams and GetTeamCounts have already been called
-       int num_players_team_a = -1, num_players_team_b = -1;
-       int num_bots_team_a = 0, num_bots_team_b = 0;
-       float score_team_a = 0, score_team_b = 0;
-       switch (team_a)
-       {
-               case 1:
-               {
-                       num_players_team_a = c1;
-                       num_bots_team_a = num_bots_team1;
-                       score_team_a = team1_score;
-                       break;
-               }
-               case 2:
-               {
-                       num_players_team_a = c2;
-                       num_bots_team_a = num_bots_team2;
-                       score_team_a = team2_score;
-                       break;
-               }
-               case 3:
-               {
-                       num_players_team_a = c3;
-                       num_bots_team_a = num_bots_team3;
-                       score_team_a = team3_score;
-                       break;
-               }
-               case 4:
-               {
-                       num_players_team_a = c4;
-                       num_bots_team_a = num_bots_team4;
-                       score_team_a = team4_score;
-                       break;
-               }
-       }
-       switch (team_b)
+       return balance.m_team_balance_team[index - 1].m_num_players;
+}
+
+int TeamBalance_FindBestTeam(entity balance, entity player, bool ignore_player)
+{
+       if (balance == NULL)
        {
-               case 1:
-               {
-                       num_players_team_b = c1;
-                       num_bots_team_b = num_bots_team1;
-                       score_team_b = team1_score;
-                       break;
-               }
-               case 2:
-               {
-                       num_players_team_b = c2;
-                       num_bots_team_b = num_bots_team2;
-                       score_team_b = team2_score;
-                       break;
-               }
-               case 3:
-               {
-                       num_players_team_b = c3;
-                       num_bots_team_b = num_bots_team3;
-                       score_team_b = team3_score;
-                       break;
-               }
-               case 4:
-               {
-                       num_players_team_b = c4;
-                       num_bots_team_b = num_bots_team4;
-                       score_team_b = team4_score;
-                       break;
-               }
+               LOG_FATAL("TeamBalance_FindBestTeam: Team balance entity is NULL.");
        }
-       // invalid
-       if (num_players_team_a < 0 || num_players_team_b < 0)
+       if (balance.m_team_balance_state == TEAM_BALANCE_UNINITIALIZED)
        {
-               return false;
+               LOG_FATAL("TeamBalance_FindBestTeam: "
+                       "Team balance entity is not initialized.");
        }
-       if (IS_REAL_CLIENT(player) && bots_would_leave)
+       // count how many players are in each team
+       if (ignore_player)
        {
-               num_players_team_a -= num_bots_team_a;
-               num_players_team_b -= num_bots_team_b;
+               TeamBalance_GetTeamCounts(balance, player);
        }
-       if (!use_score)
+       else
        {
-               return num_players_team_a < num_players_team_b;
+               TeamBalance_GetTeamCounts(balance, NULL);
        }
-       if (num_players_team_a < num_players_team_b)
+       int team_bits = TeamBalance_FindBestTeams(balance, player, true);
+       if (team_bits == 0)
        {
-               return true;
+               LOG_FATALF("TeamBalance_FindBestTeam: No teams available for %s\n",
+                       MapInfo_Type_ToString(MapInfo_CurrentGametype()));
        }
-       if (num_players_team_a > num_players_team_b)
+       RandomSelection_Init();
+       for (int i = 1; i <= NUM_TEAMS; ++i)
        {
-               return false;
+               if (team_bits & Team_IndexToBit(i))
+               {
+                       RandomSelection_AddFloat(i, 1, 1);
+               }
        }
-       return score_team_a < score_team_b;
+       return RandomSelection_chosen_float;
 }
 
-bool IsTeamEqualToTeam(int team_a, int team_b, entity player, bool use_score)
+int TeamBalance_FindBestTeams(entity balance, entity player, bool use_score)
 {
-       if (!Team_IsValidNumber(team_a))
+       if (balance == NULL)
        {
-               LOG_FATALF("IsTeamEqualToTeam: team_a is invalid: %f", team_a);
+               LOG_FATAL("TeamBalance_FindBestTeams: Team balance entity is NULL.");
        }
-       if (!Team_IsValidNumber(team_b))
+       if (balance.m_team_balance_state != TEAM_BALANCE_TEAM_COUNTS_FILLED)
        {
-               LOG_FATALF("IsTeamEqualToTeam: team_b is invalid: %f", team_b);
+               LOG_FATAL("TeamBalance_FindBestTeams: "
+                       "TeamBalance_GetTeamCounts has not been called.");
        }
-       if (team_a == team_b)
+       if (MUTATOR_CALLHOOK(TeamBalance_FindBestTeams, player) == true)
        {
-               return true;
+               return M_ARGV(1, float);
        }
-       // we assume that CheckAllowedTeams and GetTeamCounts have already been called
-       int num_players_team_a = -1, num_players_team_b = -1;
-       int num_bots_team_a = 0, num_bots_team_b = 0;
-       float score_team_a = 0, score_team_b = 0;
-       switch (team_a)
+       int team_bits = 0;
+       int previous_team = 0;
+       for (int i = 1; i <= NUM_TEAMS; ++i)
        {
-               case 1:
+               if (!TeamBalance_IsTeamAllowedInternal(balance, i))
                {
-                       num_players_team_a = c1;
-                       num_bots_team_a = num_bots_team1;
-                       score_team_a = team1_score;
-                       break;
+                       continue;
                }
-               case 2:
+               if (previous_team == 0)
                {
-                       num_players_team_a = c2;
-                       num_bots_team_a = num_bots_team2;
-                       score_team_a = team2_score;
-                       break;
+                       team_bits = Team_IndexToBit(i);
+                       previous_team = i;
+                       continue;
                }
-               case 3:
+               int compare = TeamBalance_CompareTeams(balance, i, previous_team,
+                       player, use_score);
+               if (compare == TEAMS_COMPARE_LESS)
                {
-                       num_players_team_a = c3;
-                       num_bots_team_a = num_bots_team3;
-                       score_team_a = team3_score;
-                       break;
+                       team_bits = Team_IndexToBit(i);
+                       previous_team = i;
+                       continue;
                }
-               case 4:
+               if (compare == TEAMS_COMPARE_EQUAL)
                {
-                       num_players_team_a = c4;
-                       num_bots_team_a = num_bots_team4;
-                       score_team_a = team4_score;
-                       break;
+                       team_bits |= Team_IndexToBit(i);
+                       previous_team = i;
                }
        }
-       switch (team_b)
+       return team_bits;
+}
+
+void TeamBalance_JoinBestTeam(entity this)
+{
+       //PrintToChatAll(sprintf("JoinBestTeam: %s", this.netname));
+       if (!teamplay)
        {
-               case 1:
-               {
-                       num_players_team_b = c1;
-                       num_bots_team_b = num_bots_team1;
-                       score_team_b = team1_score;
-                       break;
-               }
-               case 2:
+               return;
+       }
+       if (this.bot_forced_team)
+       {
+               return;
+       }
+       int old_team_index = Team_TeamToIndex(this.team);
+       entity balance = TeamBalance_CheckAllowedTeams(this);
+       if (this.team_forced > 0)
+       {
+               int forced_team_index = Team_TeamToIndex(this.team_forced);
+               bool is_team_allowed = TeamBalance_IsTeamAllowedInternal(balance,
+                       forced_team_index);
+               TeamBalance_Destroy(balance);
+               if (!is_team_allowed)
                {
-                       num_players_team_b = c2;
-                       num_bots_team_b = num_bots_team2;
-                       score_team_b = team2_score;
-                       break;
+                       return;
                }
-               case 3:
+               if (!SetPlayerTeam(this, forced_team_index, TEAM_CHANGE_AUTO))
                {
-                       num_players_team_b = c3;
-                       num_bots_team_b = num_bots_team3;
-                       score_team_b = team3_score;
-                       break;
+                       return;
                }
-               case 4:
+               if ((old_team_index != -1) && !IS_BOT_CLIENT(this))
                {
-                       num_players_team_b = c4;
-                       num_bots_team_b = num_bots_team4;
-                       score_team_b = team4_score;
-                       break;
+                       TeamBalance_AutoBalanceBots(forced_team_index, old_team_index);
                }
+               return;
        }
-       // invalid
-       if (num_players_team_a < 0 || num_players_team_b < 0)
-               return false;
-
-       if (IS_REAL_CLIENT(player) && bots_would_leave)
+       int best_team_index = TeamBalance_FindBestTeam(balance, this, true);
+       TeamBalance_Destroy(balance);
+       PlayerScore_Clear(this);
+       if (!SetPlayerTeam(this, best_team_index, TEAM_CHANGE_AUTO))
        {
-               num_players_team_a -= num_bots_team_a;
-               num_players_team_b -= num_bots_team_b;
-       }
-       if (!use_score)
-       {
-               return num_players_team_a == num_players_team_b;
+               return;
        }
-       if (num_players_team_a != num_players_team_b)
+       if ((old_team_index != -1) && !IS_BOT_CLIENT(this))
        {
-               return false;
+               TeamBalance_AutoBalanceBots(best_team_index, old_team_index);
        }
-       return score_team_a == score_team_b;
 }
 
-int FindBestTeams(entity player, bool use_score)
+int TeamBalance_CompareTeams(entity balance, int team_index_a, int team_index_b,
+       entity player, bool use_score)
 {
-       if (MUTATOR_CALLHOOK(FindBestTeams, player) == true)
+       if (balance == NULL)
        {
-               return M_ARGV(1, float);
+               LOG_FATAL("TeamBalance_CompareTeams: Team balance entity is NULL.");
        }
-       int team_bits = 0;
-       int previous_team = 0;
-       if (c1 >= 0)
+       if (balance.m_team_balance_state != TEAM_BALANCE_TEAM_COUNTS_FILLED)
        {
-               team_bits = BIT(0);
-               previous_team = 1;
+               LOG_FATAL("TeamBalance_CompareTeams: "
+                       "TeamBalance_GetTeamCounts has not been called.");
        }
-       if (c2 >= 0)
+       if (!Team_IsValidIndex(team_index_a))
        {
-               if (previous_team == 0)
-               {
-                       team_bits = BIT(1);
-                       previous_team = 2;
-               }
-               else if (IsTeamSmallerThanTeam(2, previous_team, player, use_score))
-               {
-                       team_bits = BIT(1);
-                       previous_team = 2;
-               }
-               else if (IsTeamEqualToTeam(2, previous_team, player, use_score))
-               {
-                       team_bits |= BIT(1);
-                       previous_team = 2;
-               }
+               LOG_FATALF("TeamBalance_CompareTeams: team_index_a is invalid: %f",
+                       team_index_a);
        }
-       if (c3 >= 0)
+       if (!Team_IsValidIndex(team_index_b))
        {
-               if (previous_team == 0)
-               {
-                       team_bits = BIT(2);
-                       previous_team = 3;
-               }
-               else if (IsTeamSmallerThanTeam(3, previous_team, player, use_score))
-               {
-                       team_bits = BIT(2);
-                       previous_team = 3;
-               }
-               else if (IsTeamEqualToTeam(3, previous_team, player, use_score))
-               {
-                       team_bits |= BIT(2);
-                       previous_team = 3;
-               }
+               LOG_FATALF("TeamBalance_CompareTeams: team_index_b is invalid: %f",
+                       team_index_b);
        }
-       if (c4 >= 0)
+       if (team_index_a == team_index_b)
        {
-               if (previous_team == 0)
-               {
-                       team_bits = BIT(3);
-               }
-               else if (IsTeamSmallerThanTeam(4, previous_team, player, use_score))
-               {
-                       team_bits = BIT(3);
-               }
-               else if (IsTeamEqualToTeam(4, previous_team, player, use_score))
-               {
-                       team_bits |= BIT(3);
-               }
+               return TEAMS_COMPARE_EQUAL;
        }
-       return team_bits;
+       entity team_a = TeamBalance_GetTeamFromIndex(balance, team_index_a);
+       entity team_b = TeamBalance_GetTeamFromIndex(balance, team_index_b);
+       return TeamBalance_CompareTeamsInternal(team_a, team_b, player, use_score);
 }
 
-// returns # of smallest team (1, 2, 3, 4)
-// NOTE: Assumes CheckAllowedTeams has already been called!
-int FindSmallestTeam(entity player, float ignore_player)
+void TeamBalance_AutoBalanceBots(int source_team_index,
+       int destination_team_index)
 {
-       // count how many players are in each team
-       if (ignore_player)
+       if (!Team_IsValidIndex(source_team_index))
        {
-               GetTeamCounts(player);
+               LOG_WARNF("TeamBalance_AutoBalanceBots: "
+                       "Source team index is invalid: %f", source_team_index);
+               return;
        }
-       else
+       if (!Team_IsValidIndex(destination_team_index))
        {
-               GetTeamCounts(NULL);
+               LOG_WARNF("TeamBalance_AutoBalanceBots: "
+                       "Destination team index is invalid: %f", destination_team_index);
+               return;
        }
-       int team_bits = FindBestTeams(player, true);
-       if (team_bits == 0)
+       if (!autocvar_g_balance_teams ||
+               !autocvar_g_balance_teams_prevent_imbalance)
        {
-               error(sprintf("No teams available for %s\n", MapInfo_Type_ToString(MapInfo_CurrentGametype())));
+               return;
        }
-       RandomSelection_Init();
-       if ((team_bits & BIT(0)) != 0)
+       entity balance = TeamBalance_CheckAllowedTeams(NULL);
+       TeamBalance_GetTeamCounts(balance, NULL);
+       entity source_team = TeamBalance_GetTeamFromIndex(balance,
+               source_team_index);
+       entity destination_team = TeamBalance_GetTeamFromIndex(balance,
+               destination_team_index);
+       if ((source_team.m_num_bots == 0) || (source_team.m_num_players <=
+               destination_team.m_num_players))
        {
-               RandomSelection_AddFloat(1, 1, 1);
+               TeamBalance_Destroy(balance);
+               return;
        }
-       if ((team_bits & BIT(1)) != 0)
+       TeamBalance_Destroy(balance);
+       entity lowest_bot = NULL;
+       if (MUTATOR_CALLHOOK(TeamBalance_GetPlayerForTeamSwitch, source_team_index,
+               destination_team_index, true))
        {
-               RandomSelection_AddFloat(2, 1, 1);
+               lowest_bot = M_ARGV(3, entity);
        }
-       if ((team_bits & BIT(2)) != 0)
+       else
        {
-               RandomSelection_AddFloat(3, 1, 1);
+               float lowest_score = FLOAT_MAX;
+               FOREACH_CLIENT(IS_BOT_CLIENT(it) && (Entity_GetTeamIndex(it) ==
+                       source_team_index),
+               {
+                       float temp_score = PlayerScore_Get(it, SP_SCORE);
+                       if (temp_score >= lowest_score)
+                       {
+                               continue;
+                       }
+                       balance = TeamBalance_CheckAllowedTeams(it);
+                       if (TeamBalance_IsTeamAllowed(balance, destination_team_index))
+                       {
+                               lowest_bot = it;
+                               lowest_score = temp_score;
+                       }
+                       TeamBalance_Destroy(balance);
+               });
        }
-       if ((team_bits & BIT(3)) != 0)
+       if (lowest_bot == NULL)
        {
-               RandomSelection_AddFloat(4, 1, 1);
+               return;
        }
-       return RandomSelection_chosen_float;
-}
-
-void JoinBestTeam(entity this, bool force_best_team)
-{
-       // don't join a team if we're not playing a team game
-       if (!teamplay)
+       if (!Player_SetTeamIndex(lowest_bot, destination_team_index))
        {
                return;
        }
+       KillPlayerForTeamChange(lowest_bot);
+}
 
-       // find out what teams are available
-       CheckAllowedTeams(this);
+bool TeamBalance_IsTeamAllowedInternal(entity balance, int index)
+{
+       return balance.m_team_balance_team[index - 1].m_num_players !=
+               TEAM_NOT_ALLOWED;
+}
 
-       // if we don't care what team they end up on, put them on whatever team they entered as.
-       // if they're not on a valid team, then let other code put them on the smallest team
-       if (!force_best_team)
+void TeamBalance_BanTeamsExcept(entity balance, int index)
+{
+       for (int i = 1; i <= NUM_TEAMS; ++i)
        {
-               int selected_team;
-               if ((c1 >= 0) && (this.team == NUM_TEAM_1))
-               {
-                       selected_team = this.team;
-               }
-               else if ((c2 >= 0) && (this.team == NUM_TEAM_2))
-               {
-                       selected_team = this.team;
-               }
-               else if ((c3 >= 0) && (this.team == NUM_TEAM_3))
-               {
-                       selected_team = this.team;
-               }
-               else if ((c4 >= 0) && (this.team == NUM_TEAM_4))
-               {
-                       selected_team = this.team;
-               }
-               else
+               if (i != index)
                {
-                       selected_team = -1;
+                       balance.m_team_balance_team[i - 1].m_num_players = TEAM_NOT_ALLOWED;
                }
+       }
+}
 
-               if (selected_team > 0)
-               {
-                       SetPlayerTeamSimple(this, selected_team);
-                       LogTeamchange(this.playerid, this.team, 99);
-                       return;
-               }
+entity TeamBalance_GetTeamFromIndex(entity balance, int index)
+{
+       if (!Team_IsValidIndex(index))
+       {
+               LOG_FATALF("TeamBalance_GetTeamFromIndex: Index is invalid: %f", index);
        }
-       // otherwise end up on the smallest team (handled below)
-       if (this.bot_forced_team)
+       return balance.m_team_balance_team[index - 1];
+}
+
+entity TeamBalance_GetTeam(entity balance, int team_num)
+{
+       return TeamBalance_GetTeamFromIndex(balance, Team_TeamToIndex(team_num));
+}
+
+bool TeamBalanceTeam_IsAllowed(entity team_ent)
+{
+       return team_ent.m_num_players != TEAM_NOT_ALLOWED;
+}
+
+int TeamBalanceTeam_GetNumberOfPlayers(entity team_ent)
+{
+       return team_ent.m_num_players;
+}
+
+int TeamBalanceTeam_GetNumberOfBots(entity team_ent)
+{
+       return team_ent.m_num_bots;
+}
+
+int TeamBalance_CompareTeamsInternal(entity team_a, entity team_b,
+       entity player, bool use_score)
+{
+       if (team_a == team_b)
        {
-               return;
+               return TEAMS_COMPARE_EQUAL;
+       }
+       if (!TeamBalanceTeam_IsAllowed(team_a) ||
+               !TeamBalanceTeam_IsAllowed(team_b))
+       {
+               return TEAMS_COMPARE_INVALID;
        }
-       int best_team = FindSmallestTeam(this, true);
-       best_team = Team_NumberToTeam(best_team);
-       if (best_team == -1)
+       int num_players_team_a = team_a.m_num_players;
+       int num_players_team_b = team_b.m_num_players;
+       if (IS_REAL_CLIENT(player) && bots_would_leave)
+       {
+               num_players_team_a -= team_a.m_num_bots;
+               num_players_team_b -= team_b.m_num_bots;
+       }
+       if (num_players_team_a < num_players_team_b)
+       {
+               return TEAMS_COMPARE_LESS;
+       }
+       if (num_players_team_a > num_players_team_b)
+       {
+               return TEAMS_COMPARE_GREATER;
+       }
+       if (!use_score)
        {
-               error("JoinBestTeam: invalid team\n");
+               return TEAMS_COMPARE_EQUAL;
        }
-       int old_team = Team_TeamToNumber(this.team);
-       TeamchangeFrags(this);
-       SetPlayerTeamSimple(this, best_team);
-       LogTeamchange(this.playerid, this.team, 2); // log auto join
-       if ((old_team != -1) && !IS_BOT_CLIENT(this))
+       if (team_a.m_team_score < team_b.m_team_score)
        {
-               AutoBalanceBots(old_team, Team_TeamToNumber(best_team));
+               return TEAMS_COMPARE_LESS;
        }
-       KillPlayerForTeamChange(this);
+       if (team_a.m_team_score > team_b.m_team_score)
+       {
+               return TEAMS_COMPARE_GREATER;
+       }
+       return TEAMS_COMPARE_EQUAL;
 }
 
+// Called when the player connects or when they change their color with "color"
+// command.
 void SV_ChangeTeam(entity this, float _color)
 {
-       float source_color, destination_color, source_team, destination_team;
+       //PrintToChatAll(sprintf("SV_ChangeTeam: %s, %f", this.netname, _color));
 
        // in normal deathmatch we can just apply the color and we're done
        if(!teamplay)
@@ -933,28 +886,48 @@ void SV_ChangeTeam(entity this, float _color)
        if(!teamplay)
                return;
 
+       int source_color, destination_color;
+       int source_team_index, destination_team_index;
+
        source_color = this.clientcolors & 0x0F;
        destination_color = _color & 0x0F;
 
-       source_team = Team_TeamToNumber(source_color + 1);
-       destination_team = Team_TeamToNumber(destination_color + 1);
+       source_team_index = Team_TeamToIndex(source_color + 1);
+       destination_team_index = Team_TeamToIndex(destination_color + 1);
 
-       if (destination_team == -1)
+       if (destination_team_index == -1)
        {
                return;
        }
 
-       CheckAllowedTeams(this);
+       entity balance = TeamBalance_CheckAllowedTeams(this);
 
-       if (destination_team == 1 && c1 < 0) destination_team = 4;
-       if (destination_team == 4 && c4 < 0) destination_team = 3;
-       if (destination_team == 3 && c3 < 0) destination_team = 2;
-       if (destination_team == 2 && c2 < 0) destination_team = 1;
+       if (destination_team_index == 1 && !TeamBalance_IsTeamAllowedInternal(
+               balance, 1))
+       {
+               destination_team_index = 4;
+       }
+       if (destination_team_index == 4 && !TeamBalance_IsTeamAllowedInternal(
+               balance, 4))
+       {
+               destination_team_index = 3;
+       }
+       if (destination_team_index == 3 && !TeamBalance_IsTeamAllowedInternal(
+               balance, 3))
+       {
+               destination_team_index = 2;
+       }
+       if (destination_team_index == 2 && !TeamBalance_IsTeamAllowedInternal(
+               balance, 2))
+       {
+               destination_team_index = 1;
+       }
 
        // not changing teams
        if (source_color == destination_color)
        {
-               SetPlayerTeam(this, destination_team, source_team, true);
+               SetPlayerTeam(this, destination_team_index, TEAM_CHANGE_MANUAL);
+               TeamBalance_Destroy(balance);
                return;
        }
 
@@ -966,111 +939,28 @@ void SV_ChangeTeam(entity this, float _color)
        // autocvar_g_balance_teams_prevent_imbalance only makes sense if autocvar_g_balance_teams is on, as it makes the team selection dialog pointless
        if (autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance)
        {
-               GetTeamCounts(this);
-               if ((BIT(destination_team - 1) & FindBestTeams(this, false)) == 0)
+               TeamBalance_GetTeamCounts(balance, this);
+               if ((Team_IndexToBit(destination_team_index) &
+                       TeamBalance_FindBestTeams(balance, this, false)) == 0)
                {
                        Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_TEAMCHANGE_LARGERTEAM);
+                       TeamBalance_Destroy(balance);
                        return;
                }
        }
-       if(IS_PLAYER(this) && source_team != destination_team)
+       TeamBalance_Destroy(balance);
+       if (IS_PLAYER(this) && source_team_index != destination_team_index)
        {
                // reduce frags during a team change
-               TeamchangeFrags(this);
-       }
-       if (!SetPlayerTeam(this, destination_team, source_team, !IS_CLIENT(this)))
-       {
-               return;
-       }
-       AutoBalanceBots(source_team, destination_team);
-       if (!IS_PLAYER(this) || (source_team == destination_team))
-       {
-               return;
+               PlayerScore_Clear(this);
        }
-       KillPlayerForTeamChange(this);
-}
-
-void AutoBalanceBots(int source_team, int destination_team)
-{
-       if (!Team_IsValidNumber(source_team))
+       if (!SetPlayerTeam(this, destination_team_index, TEAM_CHANGE_MANUAL))
        {
-               LOG_WARNF("AutoBalanceBots: Source team is invalid: %f", source_team);
                return;
        }
-       if (!Team_IsValidNumber(destination_team))
-       {
-               LOG_WARNF("AutoBalanceBots: Destination team is invalid: %f",
-                       destination_team);
-               return;
-       }
-       if (!autocvar_g_balance_teams ||
-               !autocvar_g_balance_teams_prevent_imbalance)
-       {
-               return;
-       }
-       int num_players_source_team = 0;
-       int num_players_destination_team = 0;
-       entity lowest_bot_destination_team = NULL;
-       switch (source_team)
-       {
-               case 1:
-               {
-                       num_players_source_team = c1;
-                       break;
-               }
-               case 2:
-               {
-                       num_players_source_team = c2;
-                       break;
-               }
-               case 3:
-               {
-                       num_players_source_team = c3;
-                       break;
-               }
-               case 4:
-               {
-                       num_players_source_team = c4;
-                       break;
-               }
-       }
-       if (num_players_source_team < 0)
-       {
-               return;
-       }
-       switch (destination_team)
-       {
-               case 1:
-               {
-                       num_players_destination_team = c1;
-                       lowest_bot_destination_team = lowest_bot_team1;
-                       break;
-               }
-               case 2:
-               {
-                       num_players_destination_team = c2;
-                       lowest_bot_destination_team = lowest_bot_team2;
-                       break;
-               }
-               case 3:
-               {
-                       num_players_destination_team = c3;
-                       lowest_bot_destination_team = lowest_bot_team3;
-                       break;
-               }
-               case 4:
-               {
-                       num_players_destination_team = c4;
-                       lowest_bot_destination_team = lowest_bot_team4;
-                       break;
-               }
-       }
-       if ((num_players_destination_team <= num_players_source_team) ||
-               (lowest_bot_destination_team == NULL))
+       if (source_team_index == -1)
        {
                return;
        }
-       SetPlayerTeamSimple(lowest_bot_destination_team,
-               Team_NumberToTeam(source_team));
-       KillPlayerForTeamChange(lowest_bot_destination_team);
+       TeamBalance_AutoBalanceBots(destination_team_index, source_team_index);
 }
index 7c4ebe77b6c2a82a51ae2949999734d5da4022e8..776a80d329cf91d5917f1af4e1ba7275eb18a731 100644 (file)
 #pragma once
 
-string cache_mutatormsg;
-string cache_lastmutatormsg;
+bool lockteams;
 
-// The following variables are used for balancing. They are not updated
-// automatically. You need to call CheckAllowedTeams and GetTeamCounts to get
-// proper values.
+// ========================== Global teams API ================================
 
-// These four have 2 different states. If they are equal to -1, it means that
-// the player can't join the team. Zero or positive value means that player can
-// join the team and means the number of players on that team.
-float c1;
-float c2;
-float c3;
-float c4;
-float num_bots_team1; ///< Number of bots in the first team.
-float num_bots_team2; ///< Number of bots in the second team.
-float num_bots_team3; ///< Number of bots in the third team.
-float num_bots_team4; ///< Number of bots in the fourth team.
-entity lowest_human_team1; ///< Human with the lowest score in the first team.
-entity lowest_human_team2; ///< Human with the lowest score in the second team.
-entity lowest_human_team3; ///< Human with the lowest score in the third team.
-entity lowest_human_team4; ///< Human with the lowest score in the fourth team.
-entity lowest_bot_team1; ///< Bot with the lowest score in the first team.
-entity lowest_bot_team2; ///< Bot with the lowest score in the second team.
-entity lowest_bot_team3; ///< Bot with the lowest score in the third team.
-entity lowest_bot_team4; ///< Bot with the lowest score in the fourth team.
+/// \brief Returns the global team entity at the given index.
+/// \param[in] index Index of the team.
+/// \return Global team entity at the given index.
+entity Team_GetTeamFromIndex(int index);
 
-int redowned, blueowned, yellowowned, pinkowned;
+/// \brief Returns the global team entity that corresponds to the given TEAM_NUM
+/// value.
+/// \param[in] team_num Team value. See TEAM_NUM constants.
+/// \return Global team entity that corresponds to the given TEAM_NUM value.
+entity Team_GetTeam(int team_num);
 
-//float audit_teams_time;
+// ========================= Team specific API ================================
 
-void TeamchangeFrags(entity e);
+/// \brief Returns the score of the team.
+/// \param[in] team_ent Team entity.
+/// \return Score of the team.
+float Team_GetTeamScore(entity team_ent);
 
-void LogTeamchange(float player_id, float team_number, float type);
+/// \brief Sets the score of the team.
+/// \param[in,out] team_ent Team entity.
+/// \param[in] score Score to set.
+void Team_SetTeamScore(entity team_ent, float score);
 
-void default_delayedinit(entity this);
+/// \brief Returns the number of alive players in a team.
+/// \param[in] team_ent Team entity.
+/// \return Number of alive players in a team.
+int Team_GetNumberOfAlivePlayers(entity team_ent);
 
-void InitGameplayMode();
+/// \brief Sets the number of alive players in a team.
+/// \param[in,out] team_ent Team entity.
+/// \param[in] number Number of players to set.
+void Team_SetNumberOfAlivePlayers(entity team_ent, int number);
 
-string GetClientVersionMessage(entity this);
+/// \brief Returns the number of alive teams.
+/// \return Number of alive teams.
+int Team_GetNumberOfAliveTeams();
 
-string getwelcomemessage(entity this);
+/// \brief Returns the number of control points owned by a team.
+/// \param[in] team_ent Team entity.
+/// \return Number of control points owned by a team.
+int Team_GetNumberOfControlPoints(entity team_ent);
 
-void SetPlayerColors(entity player, float _color);
+/// \brief Sets the number of control points owned by a team.
+/// \param[in,out] team_ent Team entity.
+/// \param[in] number Number of control points to set.
+void Team_SetNumberOfControlPoints(entity team_ent, int number);
 
-/// \brief Kills player as a result of team change.
-/// \param[in,out] player Player to kill.
-/// \return No return.
-void KillPlayerForTeamChange(entity player);
+/// \brief Returns the number of teams that own control points.
+/// \return Number of teams that own control points.
+int Team_GetNumberOfTeamsWithControlPoints();
 
-/// \brief Sets the team of the player.
+// ======================= Entity specific API ================================
+
+void setcolor(entity this, int clr);
+
+/// \brief Returns whether the given entity belongs to a valid team.
+/// \param[in] this Entity to check.
+/// \return True if entity belongs to a valid team, false otherwise.
+bool Entity_HasValidTeam(entity this);
+
+/// \brief Returns the team index of the given entity.
+/// \param[in] this Entity to check.
+/// \return Team index of the entity.
+int Entity_GetTeamIndex(entity this);
+
+/// \brief Returns the team entity of the given entity.
+/// \param[in] this Entity to check.
+/// \return Team entity of the given entity or NULL if the entity doesn't belong
+/// to any team.
+entity Entity_GetTeam(entity this);
+
+void SetPlayerColors(entity player, float _color);
+
+/// \brief Sets the team of the player using its index.
 /// \param[in,out] player Player to adjust.
-/// \param[in] team_num Team number to set. See TEAM_NUM constants.
+/// \param[in] index Index of the team to set.
 /// \return True if team switch was successful, false otherwise.
-bool SetPlayerTeamSimple(entity player, int team_num);
+bool Player_SetTeamIndex(entity player, int index);
 
 /// \brief Sets the team of the player.
 /// \param[in,out] player Player to adjust.
-/// \param[in] destination_team Team to set.
-/// \param[in] source_team Previous team of the player.
-/// \param[in] no_print Whether to print this event to players' console.
+/// \param[in] team_index Index of the team to set.
+/// \param[in] type ???
 /// \return True if team switch was successful, false otherwise.
-bool SetPlayerTeam(entity player, int destination_team, int source_team,
-       bool no_print);
+bool SetPlayerTeam(entity player, int team_index, int type);
+
+/// \brief Moves player to the specified team.
+/// \param[in,out] client Client to move.
+/// \param[in] team_index Index of the team.
+/// \param[in] type ???
+/// \return True on success, false otherwise.
+bool MoveToTeam(entity client, int team_index, int type);
+
+/// \brief Kills player as a result of team change.
+/// \param[in,out] player Player to kill.
+void KillPlayerForTeamChange(entity player);
 
-// set c1...c4 to show what teams are allowed
-void CheckAllowedTeams(entity for_whom);
+enum
+{
+       TEAM_CHANGE_AUTO = 2,
+       TEAM_CHANGE_MANUAL = 3,
+       TEAM_CHANGE_SPECTATOR = 4
+};
 
-float PlayerValue(entity p);
+void LogTeamchange(float player_id, float team_number, int type);
 
-// c1...c4 should be set to -1 (not allowed) or 0 (allowed).
-// teams that are allowed will now have their player counts stored in c1...c4
-void GetTeamCounts(entity ignore);
+// ========================= Team balance API =================================
 
-/// \brief Returns whether one team is smaller than the other.
-/// \param[in] team_a First team.
-/// \param[in] team_b Second team.
+/// \brief Checks whether the player can join teams according to global
+/// configuration and mutator settings.
+/// \param[in] for_whom Player to check for. Pass NULL for global rules.
+/// \return Team balance entity that holds information about teams. This entity
+/// will be automatically destroyed on the next frame but you are encouraged to
+/// manually destroy it by calling TeamBalance_Destroy for performance reasons.
+entity TeamBalance_CheckAllowedTeams(entity for_whom);
+
+/// \brief Destroy the team balance entity.
+/// \param[in,out] balance Team balance entity to destroy.
+/// \note Team balance entity is allowed to be NULL.
+void TeamBalance_Destroy(entity balance);
+
+/// \brief Returns the bitmask of allowed teams.
+/// \param[in] balance Team balance entity.
+/// \return Bitmask of allowed teams.
+int TeamBalance_GetAllowedTeams(entity balance);
+
+/// \brief Returns whether the team change to the specified team is allowed.
+/// \param[in] balance Team balance entity.
+/// \param[in] index Index of the team.
+/// \return True if team change to the specified team is allowed, false
+/// otherwise.
+bool TeamBalance_IsTeamAllowed(entity balance, int index);
+
+/// \brief Counts the number of players and various other information about
+/// each team.
+/// \param[in,out] balance Team balance entity.
+/// \param[in] ignore Player to ignore. This is useful if you plan to switch the
+/// player's team. Pass NULL for global information.
+/// \note This function updates the internal state of the team balance entity.
+void TeamBalance_GetTeamCounts(entity balance, entity ignore);
+
+/// \brief Returns the number of players (both humans and bots) in a team.
+/// \param[in] balance Team balance entity.
+/// \param[in] index Index of the team.
+/// \return Number of player (both humans and bots) in a team.
+/// \note You need to call TeamBalance_GetTeamCounts before calling this
+/// function.
+int TeamBalance_GetNumberOfPlayers(entity balance, int index);
+
+/// \brief Finds the team that will make the game most balanced if the player
+/// joins it.
+/// \param[in] balance Team balance entity.
 /// \param[in] player Player to check.
-/// \param[in] use_score Whether to take into account team scores.
-/// \return True if first team is smaller than the second one, false otherwise.
-/// \note This function assumes that CheckAllowedTeams and GetTeamCounts have
-/// been called.
-bool IsTeamSmallerThanTeam(int team_a, int team_b, entity player,
-       bool use_score);
+/// \param[in] ignore_player ???
+/// \return Index of the team that will make the game most balanced if the
+/// player joins it. If there are several equally good teams available, the
+/// function will pick a random one.
+int TeamBalance_FindBestTeam(entity balance, entity player, bool ignore_player);
 
-/// \brief Returns whether one team is equal to the other.
-/// \param[in] team_a First team.
-/// \param[in] team_b Second team.
+/// \brief Returns the bitmask of the teams that will make the game most
+/// balanced if the player joins any of them.
+/// \param[in] balance Team balance entity.
 /// \param[in] player Player to check.
 /// \param[in] use_score Whether to take into account team scores.
-/// \return True if first team is equal to the second one, false otherwise.
-/// \note This function assumes that CheckAllowedTeams and GetTeamCounts have
-/// been called.
-bool IsTeamEqualToTeam(int team_a, int team_b, entity player, bool use_score);
+/// \return Bitmask of the teams that will make the game most balanced if the
+/// player joins any of them.
+/// \note You need to call TeamBalance_GetTeamCounts before calling this
+/// function.
+int TeamBalance_FindBestTeams(entity balance, entity player, bool use_score);
+
+void TeamBalance_JoinBestTeam(entity this);
 
-/// \brief Returns the bitmask of the best teams for the player to join.
+/// \brief Describes the result of comparing teams.
+enum
+{
+       TEAMS_COMPARE_INVALID, ///< One or both teams are invalid.
+       TEAMS_COMPARE_LESS, ///< First team is less than the second one.
+       TEAMS_COMPARE_EQUAL, ///< Both teams are equal.
+       TEAMS_COMPARE_GREATER ///< First team the greater than the second one.
+};
+
+/// \brief Compares two teams for the purposes of game balance.
+/// \param[in] balance Team balance entity.
+/// \param[in] team_index_a Index of the first team.
+/// \param[in] team_index_b Index of the second team.
 /// \param[in] player Player to check.
 /// \param[in] use_score Whether to take into account team scores.
-/// \return Bitmask of the best teams for the player to join.
-/// \note This function assumes that CheckAllowedTeams and GetTeamCounts have
-/// been called.
-int FindBestTeams(entity player, bool use_score);
+/// \return TEAMS_COMPARE value. See above.
+/// \note You need to call TeamBalance_GetTeamCounts before calling this
+/// function.
+int TeamBalance_CompareTeams(entity balance, int team_index_a, int team_index_b,
+       entity player, bool use_score);
 
-// returns # of smallest team (1, 2, 3, 4)
-// NOTE: Assumes CheckAllowedTeams has already been called!
-int FindSmallestTeam(entity player, float ignore_player);
+/// \brief Switches a bot from one team to another if teams are not balanced.
+/// \param[in] source_team_index Index of the team to switch from.
+/// \param[in] destination_team_index Index of the team to switch to.
+void TeamBalance_AutoBalanceBots(int source_team_index,
+       int destination_team_index);
 
-void JoinBestTeam(entity this, bool force_best_team);
+// ============================ Internal API ==================================
 
-/// \brief Auto balances bots in teams after the player has changed team.
-/// \param[in] source_team Previous team of the player (1, 2, 3, 4).
-/// \param[in] destination_team Current team of the player (1, 2, 3, 4).
-/// \return No return.
-/// \note This function assumes that CheckAllowedTeams and GetTeamCounts have
-/// been called.
-void AutoBalanceBots(int source_team, int destination_team);
+/// \brief Returns whether the team change to the specified team is allowed.
+/// \param[in] balance Team balance entity.
+/// \param[in] index Index of the team.
+/// \return True if team change to the specified team is allowed, false
+/// otherwise.
+/// \note This function bypasses all the sanity checks.
+bool TeamBalance_IsTeamAllowedInternal(entity balance, int index);
 
-void setcolor(entity this, int clr);
+/// \brief Bans team change to all teams except the given one.
+/// \param[in,out] balance Team balance entity.
+/// \param[in] index Index of the team.
+void TeamBalance_BanTeamsExcept(entity balance, int index);
+
+/// \brief Returns the team entity of the team balance entity at the given
+/// index.
+/// \param[in] balance Team balance entity.
+/// \param[in] index Index of the team.
+/// \return Team entity of the team balance entity at the given index.
+entity TeamBalance_GetTeamFromIndex(entity balance, int index);
+
+/// \brief Returns the team entity of the team balance entity that corresponds
+/// to the given TEAM_NUM value.
+/// \param[in] balance Team balance entity.
+/// \param[in] team_num Team value. See TEAM_NUM constants.
+/// \return Team entity of the team balance entity that corresponds to the given
+/// TEAM_NUM value.
+entity TeamBalance_GetTeam(entity balance, int team_num);
+
+/// \brief Returns whether the team is allowed.
+/// \param[in] team_ent Team entity.
+/// \return True if team is allowed, false otherwise.
+bool TeamBalanceTeam_IsAllowed(entity team_ent);
+
+/// \brief Returns the number of players (both humans and bots) in a team.
+/// \param[in] team_ent Team entity.
+/// \return Number of player (both humans and bots) in a team.
+/// \note You need to call TeamBalance_GetTeamCounts before calling this
+/// function.
+int TeamBalanceTeam_GetNumberOfPlayers(entity team_ent);
+
+/// \brief Returns the number of bots in a team.
+/// \param[in] team_ent Team entity.
+/// \return Number of bots in a team.
+/// \note You need to call TeamBalance_GetTeamCounts before calling this
+/// function.
+int TeamBalanceTeam_GetNumberOfBots(entity team_ent);
+
+/// \brief Compares two teams for the purposes of game balance.
+/// \param[in] team_a First team.
+/// \param[in] team_b Second team.
+/// \param[in] player Player to check.
+/// \param[in] use_score Whether to take into account team scores.
+/// \return TEAMS_COMPARE value. See above.
+/// \note You need to call TeamBalance_GetTeamCounts before calling this
+/// function.
+int TeamBalance_CompareTeamsInternal(entity team_a, entity team_index_b,
+       entity player, bool use_score);
index c2a9c32acdef778fac3191045753e8ee80032c60..4af13e10228d101f414d61feae9ad9b4adb9b132 100644 (file)
@@ -240,7 +240,7 @@ float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, fl
 
 void W_SwitchWeapon_Force(Player this, Weapon wep, .entity weaponentity)
 {
-    TC(Weapon, wep);
+       TC(Weapon, wep);
        this.(weaponentity).cnt = this.(weaponentity).m_switchweapon.m_id;
        this.(weaponentity).m_switchweapon = wep;
        this.(weaponentity).selectweapon = wep.m_id;
index ddf1ff26248066b0fa719c18ab543802fc866d4b..b023180a138b1a9cca08235f950e8e81d633b17b 100644 (file)
@@ -138,7 +138,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect
                ent.punchangle_x = recoil * -1;
 
        if (snd != SND_Null) {
-               sound (ent, chan, snd, (W_DualWielding(ent) ? VOL_BASE * 0.7 : VOL_BASE), ATTN_NORM);
+               sound(ent, chan, snd, (W_DualWielding(ent) ? VOL_BASE * 0.7 : VOL_BASE), ATTN_NORM);
                W_PlayStrengthSound(ent);
        }
 
index bf81f7044187d3ec532ea0f44ab968c328bf211f..2017e65a760792fd3d8f0db24603729a139e4cc5 100644 (file)
@@ -428,8 +428,8 @@ bool forbidWeaponUse(entity player)
 
 void W_WeaponFrame(Player actor, .entity weaponentity)
 {
-    TC(Player, actor);
-    TC(PlayerState, PS(actor));
+       TC(Player, actor);
+       TC(PlayerState, PS(actor));
        entity this = actor.(weaponentity);
        if (frametime) this.weapon_frametime = frametime;
 
@@ -595,8 +595,8 @@ void W_WeaponFrame(Player actor, .entity weaponentity)
 
                if (!block_weapon)
                {
-            Weapon e = this.m_weapon;
-            TC(Weapon, e);
+                       Weapon e = this.m_weapon;
+                       TC(Weapon, e);
                        if (w != WEP_Null)
                        {
                                e.wr_think(e, actor, weaponentity, button_atck | (button_atck2 << 1));
@@ -731,7 +731,7 @@ void W_ReloadedAndReady(Weapon thiswep, entity actor, .entity weaponentity, int
 
 void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sent_sound)
 {
-    TC(Sound, sent_sound);
+       TC(Sound, sent_sound);
        // set global values to work with
        entity this = actor.(weaponentity);
        Weapon e = this.m_weapon;
index 5ac5a1ec8ddbce6451b641424d456c54db1df56b..8517818d6406c902715a967507f55b6eed28e669 100644 (file)
@@ -771,17 +771,14 @@ r_cullentities_trace 0
 r_shadow_glossexact 1
 r_shadow_glossintensity 1
 
-// use fake light if map has no lightmaps
-r_fakelight 1
+// use slightly better lighting than r_fullbright if map has no lightmaps, and for fullbrightplayers
+r_fullbright_directed 1
 
 r_water_hideplayer 1 // hide your own feet/player model in refraction views, this way you don't see half of your body under water
 r_water_refractdistort 0.019
 
 set cl_rainsnow_maxdrawdist 2048
 
-// equalize looks better than fullbright
-r_equalize_entities_fullbright 1
-
 // safe font defaults
 r_font_hinting 1
 r_font_disable_freetype 0
index 5e508c16bf7d2d6f6334b0611831b7ed05ac28ea..21a94e340f1f643d06b4b86c9fbe3c504679a8cb 100644 (file)
@@ -345,7 +345,7 @@ set g_maplist_votable_screenshot_dir "maps levelshots"      "where to look for map sc
 
 set sv_vote_gametype 1 "show a vote screen for gametypes before map vote screen"
 set sv_vote_gametype_keeptwotime 10 "show only 2 options after this amount of time during gametype vote screen"
-set sv_vote_gametype_options "dm tdm ctf"
+set sv_vote_gametype_options "dm tdm ctf" "Keep the identifiers short, otherwise you'll run into issues with too long alias names (max is 31 characters) when using sv_vote_gametype_hook_*"
 set sv_vote_gametype_timeout 20
 set sv_vote_gametype_default_current 1 "Keep the current gametype if no one votes"