- 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 '^:'
-Wed Jun 20 07:24:25 CEST 2018
+Mon Jul 23 07:24:17 CEST 2018
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
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
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
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
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
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
// 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
// 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"
// ==========================================================
// 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
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
// 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
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
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
# 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
"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"
#: 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
#: 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."
#: 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
#: 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)"
#: 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"
#: 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)"
#: 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)"
#: 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)"
#: 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)"
#: 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)"
#: 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)"
#: 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
#: 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)"
#: 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)"
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"
#: 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"
#: 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
#: 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"
#: 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"
#: 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"
#: 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
#: 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"
#: 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
#: 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"
#: 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
#: 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..."
#: 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"
#: 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"
#: 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:"
#: 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"
#: 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"
#: 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
#: 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"
#: 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:"
#: 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"
#: 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"
"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"
#: 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"
#: 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"
#: 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)"
#: 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"
#: 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"
#: 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"
#: 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"
#: 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"
#: 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:"
#: 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"
#: 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:"
#: 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"
#: 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"
#: qcsrc/menu/xonotic/util.qc:780
msgid "Use default"
-msgstr "Standard verwenden"
+msgstr "Standard"
#: qcsrc/menu/xonotic/util.qc:800
msgid "Team Color:"
# 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
"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"
#: 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
#: 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."
#: 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
#: 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)"
#: 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"
#: 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)"
#: 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)"
#: 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)"
#: 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)"
#: 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)"
#: 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)"
#: 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
#: 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)"
#: 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)"
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"
#: 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"
#: 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
#: 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"
#: 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"
#: 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"
#: 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
#: 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"
#: 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
#: 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"
#: 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
#: 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..."
#: 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"
#: 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"
#: 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:"
#: 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"
#: 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"
#: 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
#: 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"
#: 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:"
#: 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"
#: 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"
"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"
#: 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"
#: 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"
#: 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)"
#: 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"
#: 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"
#: 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"
#: 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"
#: 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"
#: 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:"
#: 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"
#: 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:"
#: 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"
#: 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"
#: qcsrc/menu/xonotic/util.qc:780
msgid "Use default"
-msgstr "Standard verwenden"
+msgstr "Standard"
#: qcsrc/menu/xonotic/util.qc:800
msgid "Team Color:"
# 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"
#: 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
#: qcsrc/common/weapons/weapon/machinegun.qc:17
msgid "MachineGun"
-msgstr "Mitrailleuse"
+msgstr "Mitraillette"
#: qcsrc/common/weapons/weapon/minelayer.qc:17
msgid "Mine Layer"
# 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"
#: 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
#: 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"
#: 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
#: 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:"
#: 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
#: 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
#: 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
#: 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"
#: qcsrc/client/hud/panel/weapons.qc:538
msgid "Unavailable"
-msgstr ""
+msgstr "לא זמין"
#: qcsrc/client/main.qc:1014
msgid " qu/s"
#: qcsrc/client/mapvoting.qc:365
msgid "Vote for a map"
-msgstr ""
+msgstr "הצבע למפה"
#: qcsrc/client/mapvoting.qc:382
#, c-format
#: 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"
#: qcsrc/common/mapinfo.qh:220
msgid "Capture the Flag"
-msgstr ""
+msgstr "תפוס את הדגל"
#: qcsrc/common/mapinfo.qh:220
msgid ""
#: 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
#: qcsrc/common/minigames/cl_minigames_hud.qc:418
msgid "Join"
-msgstr ""
+msgstr "הצטרף"
#: qcsrc/common/minigames/cl_minigames_hud.qc:489
msgid "Minigames"
#: qcsrc/common/minigames/minigame/bd.qc:1404
msgid "Next Level"
-msgstr ""
+msgstr "שלב הבא"
#: qcsrc/common/minigames/minigame/bd.qc:1405
msgid "Restart"
#: 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
#: 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
#: 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
#: 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"
#: 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"
#: 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"
#: 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"
#: 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"
#: 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"
#: qcsrc/common/mutators/mutator/nades/nades.qh:32
msgid "Grenade"
-msgstr ""
+msgstr "רימון"
#: qcsrc/common/mutators/mutator/overkill/hmg.qh:17
msgid "Heavy Machine Gun"
#: 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"
#: 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"
#: 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"
#: 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
#: qcsrc/common/weapons/weapon/shotgun.qc:17
msgid "Shotgun"
-msgstr ""
+msgstr "שוטגן"
#: qcsrc/common/weapons/weapon/tuba.qc:17
#, no-c-format
#: 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"
#: qcsrc/menu/xonotic/credits.qc:48
msgid "Website"
-msgstr ""
+msgstr "אתר"
#: qcsrc/menu/xonotic/credits.qc:53
msgid "Stats"
#: qcsrc/menu/xonotic/cvarlist.qc:93
msgid "private"
-msgstr ""
+msgstr "פרטי"
#: qcsrc/menu/xonotic/cvarlist.qc:95
msgid "engine setting"
#: qcsrc/menu/xonotic/dialog_credits.qh:7
msgid "Credits"
-msgstr ""
+msgstr "קרדיטים"
#: qcsrc/menu/xonotic/dialog_credits.qh:8
msgid "The Xonotic credits"
#: 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
#: 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:"
#: 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
#: 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"
#: 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:"
#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:18
msgid "Chat size:"
-msgstr ""
+msgstr "גודל צ'אט:"
#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:22
msgid "Chat lifetime:"
#: 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"
#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:57
msgid "Show"
-msgstr ""
+msgstr "הצג"
#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:60
msgid "Top speed"
#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:15
msgid "Score:"
-msgstr ""
+msgstr "ניקוד:"
#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:18
msgid "Rankings:"
#: 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
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:54
msgid "Number"
-msgstr ""
+msgstr "מספר"
#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:55
msgid "Bind"
#: 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
#: 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
#: 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
#: 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:"
#: 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
#: qcsrc/menu/xonotic/dialog_multiplayer.qc:14
msgid "Servers"
-msgstr ""
+msgstr "שרתים"
#: qcsrc/menu/xonotic/dialog_multiplayer.qc:15
msgid "Find servers to play on"
#: 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
#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:70
msgid "Lives:"
-msgstr ""
+msgstr "חיים:"
#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:71
msgid "Laps:"
#: 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"
#: 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"
#: 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:"
#: 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"
#: 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..."
#: 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"
#: 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"
#: 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"
#: 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
#: 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
#: 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 ""
#: 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:"
#: 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"
#: 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
#: 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)"
#: 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)"
#: 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:"
#: 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:"
#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qh:7
msgid "Server Information"
-msgstr ""
+msgstr "מידע על השרת"
#: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:25
msgid "Demos"
#: 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."
#: 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"
#: 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
#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:48
msgid "Name"
-msgstr ""
+msgstr "שם"
#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:77
msgid "Model"
#: 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!"
#: qcsrc/menu/xonotic/dialog_quit.qh:7
msgid "Quit the game"
-msgstr ""
+msgstr "צא מהמשחק"
#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:15
msgid "Model:"
#: 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:"
#: 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"
#: 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
#: 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:"
#: qcsrc/menu/xonotic/dialog_settings_audio.qc:35
msgid "Music:"
-msgstr ""
+msgstr "מוזיקה:"
#: qcsrc/menu/xonotic/dialog_settings_audio.qc:43
msgid "VOL^Ambient:"
#: qcsrc/menu/xonotic/dialog_settings_audio.qc:50
msgid "Info:"
-msgstr ""
+msgstr "מידע:"
#: qcsrc/menu/xonotic/dialog_settings_audio.qc:57
msgid "Items:"
#: qcsrc/menu/xonotic/dialog_settings_audio.qc:71
msgid "Player:"
-msgstr ""
+msgstr "שחקן:"
#: qcsrc/menu/xonotic/dialog_settings_audio.qc:78
msgid "Shots:"
#: 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"
#: qcsrc/menu/xonotic/dialog_settings_audio.qc:123
msgid "Stereo"
-msgstr ""
+msgstr "סטראו"
#: qcsrc/menu/xonotic/dialog_settings_audio.qc:124
msgid "2.1"
#: 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"
#: 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"
#: 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"
#: 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)"
#: 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)"
#: 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)"
#: qcsrc/menu/xonotic/dialog_settings_effects.qc:239
msgid "Particles"
-msgstr ""
+msgstr "חלקיקים"
#: qcsrc/menu/xonotic/dialog_settings_effects.qc:240
msgid "Spawnpoint effects"
#: qcsrc/menu/xonotic/dialog_settings_effects.qc:246
msgid "Quality:"
-msgstr ""
+msgstr "איכות:"
#: qcsrc/menu/xonotic/dialog_settings_effects.qc:249
msgid ""
#: 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"
#: 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:"
#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:94
msgid "Damage"
-msgstr ""
+msgstr "נזק"
#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:96
msgid "Overlay:"
#: 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:"
#: 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"
#: 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"
#: qcsrc/menu/xonotic/dialog_settings_game_messages.qh:7
msgid "Messages"
-msgstr ""
+msgstr "הודעות"
#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:30
msgid "Items"
#: 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"
#: 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"
#: 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"
#: 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"
#: 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:"
#: 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:"
#: 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"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:27
msgid "Network"
-msgstr ""
+msgstr "רשת"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:29
msgid "Client UDP port:"
#: 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"
#: 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"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:56
msgid "Download speed:"
-msgstr ""
+msgstr "מהירות הורדה:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:69
msgid "Local latency:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:102
msgid "Target:"
-msgstr ""
+msgstr "מטרה:"
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:104
msgid "TRGT^Disabled"
#: 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"
#: 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..."
#: 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"
#: 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"
#: 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"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:59
msgid "Full screen"
-msgstr ""
+msgstr "מסך מלא"
#: qcsrc/menu/xonotic/dialog_settings_video.qc:61
msgid "Vertical Synchronization"
#: 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)"
#: 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)"
#: 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)"
#: 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?"
#: qcsrc/menu/xonotic/keybinder.qc:30
msgid "forward"
-msgstr ""
+msgstr "קדימה"
#: qcsrc/menu/xonotic/keybinder.qc:31
msgid "backpedal"
#: qcsrc/menu/xonotic/keybinder.qc:80
msgid "screen shot"
-msgstr ""
+msgstr "צילום מסך"
#: qcsrc/menu/xonotic/keybinder.qc:81
msgid "maximize radar"
#: 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"
#: 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"
#: qcsrc/menu/xonotic/serverlist.qc:763
msgid "Ping"
-msgstr ""
+msgstr "פינג"
#: qcsrc/menu/xonotic/serverlist.qc:764
msgid "Hostname"
#: 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
"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"
#: 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:"
#: qcsrc/menu/xonotic/statslist.qc:103
msgid "Last_Seen:"
-msgstr ""
+msgstr "נראה_לאחרונה:"
#: qcsrc/menu/xonotic/statslist.qc:110
msgid "Time_Played:"
#: qcsrc/menu/xonotic/util.qc:780
msgid "Use default"
-msgstr ""
+msgstr "השתמש בברירת מחדל"
#: qcsrc/menu/xonotic/util.qc:800
msgid "Team Color:"
"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"
#: 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
#: 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
#: 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:"
#: 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."
#: 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."
#: 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"
#: 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
#: 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"
#: 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"
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"
#: 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"
#: 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"
#: 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"
#: 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"
#: 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"
#: 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"
#: 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 ""
#: 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"
#: 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
#: 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
#: 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"
#: 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:"
#: 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"
#: 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"
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
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
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
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
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
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
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
-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%
bone_aim2 0.35 bip01 r hand
bone_weapon bip01 r hand
fixbone 1
+hidden 1
-name Gak Masked
+name Gak
species alien
sex Male
weight 87
bone_aim3 0.35 bip01 r hand
bone_weapon bip01 r hand
fixbone 1
+hidden 1
bone_aim2 0.35 bip01 r hand
bone_weapon bip01 r hand
fixbone 1
+hidden 1
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)"
g_mod_physics Xonotic
-// current Xonotic physics
+// Xonotic 0.7 physics
sv_gravity 800
sv_maxspeed 360
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.
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:
void LocalCommand_create_scrshot_ent(int request)
{
- TC(int, request);
+ TC(int, request);
switch (request)
{
case CMD_REQUEST_COMMAND:
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:
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:
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:
case "clickradar":
{
- HUD_Radar_Show_Maximized(!hud_panel_radar_mouse, 1);
+ if(!isdemo())
+ HUD_Radar_Show_Maximized(!hud_panel_radar_mouse, 1);
return;
}
}
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:
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:
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:
}
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)
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;
//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)
void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, int drawflag)
{
- TC(int, drawflag);
+ TC(int, drawflag);
if(!theAlpha)
return;
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;
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);
}
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;
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;
void centerprint_kill(int id)
{
- TC(int, id);
+ TC(int, id);
centerprint_generic(id, "", 0, 0);
}
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';
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';
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;
// 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);
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;
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);
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)
bool QuickMenu_ActionForNumber(int num)
{
- TC(int, num);
+ TC(int, num);
if (!QuickMenu_IsLastPage)
{
if (num < 0 || num >= QUICKMENU_MAXLINES)
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])
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;
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;
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;
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;
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)
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;
string Scoreboard_FixColumnWidth(int i, string str)
{
- TC(int, i);
+ TC(int, i);
float f;
vector sz;
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);
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;
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)
.float has_team;
float SetTeam(entity o, int Team)
{
- TC(int, Team);
+ TC(int, Team);
devassert_once(Team);
entity tm;
if(teamplay)
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)
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)
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))
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;
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;
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)
void Cmd_MapVote_MapDownload(int argc)
{
- TC(int, argc);
+ TC(int, argc);
entity pak;
if(argc != 2 || !mv_pk3list)
void MapVote_CheckPK3(string pic, string pk3, int id)
{
- TC(int, id);
+ TC(int, id);
entity pak;
pak = spawn();
pak.netname = pk3;
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;
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);
void GameTypeVote_ReadOption(int i)
{
- TC(int, i);
+ TC(int, i);
string gt = strzone(ReadString());
mv_maps[i] = gt;
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;
}
int MapVote_MoveRight(int pos)
{
- TC(int, pos);
+ TC(int, pos);
int imp;
if ( pos < 0 )
imp = 0;
}
int MapVote_MoveUp(int pos)
{
- TC(int, pos);
+ TC(int, pos);
int imp;
if ( pos < 0 )
imp = mv_num_maps - 1;
}
int MapVote_MoveDown(int pos)
{
- TC(int, pos);
+ TC(int, pos);
int imp;
if ( pos < 0 )
imp = 0;
float MapVote_InputEvent(int bInputType, float nPrimary, float nSecondary)
{
- TC(int, bInputType);
+ TC(int, bInputType);
float imp;
if (!mv_active)
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];
/** 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
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));
void skeleton_from_frames(entity e, bool is_dead)
{
- TC(bool, is_dead);
+ TC(bool, is_dead);
float m = e.modelindex;
if(!e.skeletonindex)
{
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));
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;
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);
}
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)
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;
void loopsound(entity e, int ch, Sound samp, float vol, float attn)
{
- TC(int, ch);
+ TC(int, ch);
if (e.silent)
return;
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);
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)
}
}
-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)
{
#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.");
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;
}
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;
}
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);
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);
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;
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;
}
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)
}
CA_count_alive_players();
- if(CA_ALIVE_TEAMS() > 1)
+ if (Team_GetNumberOfAliveTeams() > 1)
+ {
return 0;
+ }
int winner_team = CA_GetWinnerTeam();
if(winner_team > 0)
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);
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)
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)
// 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);
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)
}
}
-MUTATOR_HOOKFUNCTION(dom, CheckAllowedTeams)
+MUTATOR_HOOKFUNCTION(dom, TeamBalance_CheckAllowedTeams)
{
// fallback?
M_ARGV(0, float) = domination_teams;
{
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);
}
}
}
// 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;
// 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)
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;
// TODO: sv_freezetag
#ifdef SVQC
+
#include <server/resources.qh>
float autocvar_g_freezetag_frozen_maxtime;
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()
{
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);
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
}
return 1;
}
- if(FREEZETAG_ALIVE_TEAMS() > 1)
+ if (Team_GetNumberOfAliveTeams() > 1)
+ {
return 0;
+ }
int winner_team = freezetag_getWinnerTeam();
if(winner_team > 0)
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;
}
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)
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;
}
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);
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)
void invasion_ScoreRules(int inv_teams)
{
- if(inv_teams) { CheckAllowedTeams(NULL); }
GameRules_score_enabled(false);
GameRules_scoring(inv_teams, 0, 0, {
if (inv_teams) {
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)
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');
return MUT_ITEMTOUCH_CONTINUE;
}
-MUTATOR_HOOKFUNCTION(nb, CheckAllowedTeams)
+MUTATOR_HOOKFUNCTION(nb, TeamBalance_CheckAllowedTeams)
{
M_ARGV(1, string) = "nexball_team";
return true;
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;
}
}
}
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
{
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;
}
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))
Onslaught_count_generators();
- if(ONS_OWNED_GENERATORS_OK())
+ if (Team_GetNumberOfTeamsWithControlPoints() > 1)
+ {
return 0;
+ }
int winner_team = Onslaught_GetWinnerTeam();
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);
}
}
// 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);
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)
}
}
-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)
// 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);
.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
{
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__)
#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);
}
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));
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);
}
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, "; ");
// 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);
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
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?!
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);
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)
}
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));
entcs_attach(this);
anticheat_init(this);
W_HitPlotOpen(this);
-
- bot_clientconnect(this);
}
void bot_clientdisconnect(entity this);
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 {
#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
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:
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:
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))
#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))
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);
void vehicle_alarm(entity e, int ch, Sound s0und)
{
- TC(Sound, s0und);
+ TC(Sound, s0und);
if(!autocvar_cl_vehicles_alarm)
return;
int _deahtype, float _projtype, float _health,
bool _cull, bool _clianim, entity _owner)
{
- TC(Sound, _mzlsound);
+ TC(Sound, _mzlsound);
entity proj;
proj = spawn();
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);
}
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);
// 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);
+ (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);
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)))
{
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;
}
#define remove(this) delete(this)
METHOD(Object, describe, string(Object this))
{
- TC(Object, this);
+ TC(Object, this);
string s = _("No description");
if (cvar("developer"))
{
}
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)
}
}
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;
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;
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;
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"), "-"));
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;
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;
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;
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
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;
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;
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;
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;
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
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;
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
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;
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)
best = it;
}
});
+ TeamBalance_Destroy(balance);
if(!bcount)
return; // no bots to remove
currentbots = currentbots - 1;
{
// 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;
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
{
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;
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))
bool parse_comments = true;
float ver = 0;
+ string links_time = string_null;
while ((s = fgets(file)))
{
{
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");
}
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,
// (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,
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
// 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;
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
}
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;
}
accuracy_resend(this);
if (this.team < 0)
- JoinBestTeam(this, true);
+ TeamBalance_JoinBestTeam(this);
entity spot = SelectSpawnPoint(this, false);
if (!spot) {
MUTATOR_CALLHOOK(PlayerWeaponSelect, this);
+ if (CS(this).impulse) ImpulseCommands(this);
+
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
.entity weaponentity = weaponentities[slot];
{
if(this.killindicator_teamchange == -1)
{
- JoinBestTeam( this, true );
+ TeamBalance_JoinBestTeam(this);
}
else if(this.killindicator_teamchange == -2)
{
}
#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
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)
{
}
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));
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?
// 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
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)
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);
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;
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;
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))
#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") \
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)
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;
}
// 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
}
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.");
});
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;
});
#include "../g_damage.qh"
#include "../g_world.qh"
+#include "../teamplay.qh"
#include "../race.qh"
#include "../round_handler.qh"
#include "../scores.qh"
//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)
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;
// WEAPONTODO
#define DMG_NOWEP (weaponentities[0])
-float lockteams;
-
float sv_maxidle;
float sv_maxidle_spectatorsareidle;
int sv_maxidle_slots;
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;
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;
}
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);
}
}
}
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)
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);
#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"
}
}
+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)
{
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();
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;
{
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);
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
/** 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) \
* 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);
* 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);
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);
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));
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:
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);
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
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, {});
}
#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)
#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;
}
}
-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)
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;
}
// 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);
}
#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);
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;
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);
}
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;
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));
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;
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
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"