From: terencehill Date: Tue, 17 Jul 2018 15:19:59 +0000 (+0200) Subject: Merge branch 'master' into terencehill/bot_ai X-Git-Tag: xonotic-v0.8.5~1923^2~2 X-Git-Url: https://de.git.xonotic.org/?p=xonotic%2Fxonotic-data.pk3dir.git;a=commitdiff_plain;h=70bba988cd32922d29e40235db6ad1d8149bdc67;hp=d5e34836b0af6685b1c5aad493d6000f38d1ef25 Merge branch 'master' into terencehill/bot_ai --- diff --git a/.tx/merge-base b/.tx/merge-base index ca7140deb..22200e07f 100644 --- a/.tx/merge-base +++ b/.tx/merge-base @@ -1 +1 @@ -Wed Jun 20 07:24:25 CEST 2018 +Sat Jul 14 07:24:18 CEST 2018 diff --git a/check-translations.sh b/check-translations.sh index 5e2ad5a54..6a55b5ef7 100755 --- a/check-translations.sh +++ b/check-translations.sh @@ -101,11 +101,11 @@ if [ x"$mode" = x"txt" ]; then if [ "$p" -lt 50 ]; then continue fi - item="$l $l \"$l\" 0%" + item="$l \"$l\" \"$l\" 0%" fi printf "%s\n" "$item" | sed -e "s/[0-9][0-9]*%/$p%/" done - } | tr '"' '\t' | sort -k3 | tr '\t' '"' + } | LC_ALL=C sort -t '"' -k4,4 fi if [ x"$mode" = x"po" ]; then diff --git a/common.de.po b/common.de.po index f248daf3c..2423e3782 100644 --- a/common.de.po +++ b/common.de.po @@ -3,7 +3,7 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: -# Wuzzy , 2016-2017 +# Wuzzy , 2016-2018 # Brot Brot , 2015 # cvcxc , 2013 # divVerent , 2011,2013 @@ -24,7 +24,7 @@ msgstr "" "Project-Id-Version: Xonotic\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-09 00:35+0200\n" -"PO-Revision-Date: 2017-09-23 19:12+0000\n" +"PO-Revision-Date: 2018-07-13 16:04+0000\n" "Last-Translator: Wuzzy \n" "Language-Team: German (http://www.transifex.com/team-xonotic/xonotic/" "language/de/)\n" @@ -48,7 +48,7 @@ msgstr "^1Konnte nicht nach %s schreiben\n" #: qcsrc/client/hud/panel/chat.qc:82 msgid "^3Player^7: This is the chat area." -msgstr "^3Player^7: Dies ist der Chat-Bereich." +msgstr "^3Spieler^7: Dies ist der Chat-Bereich." #: qcsrc/client/hud/panel/engineinfo.qc:69 #, c-format @@ -210,7 +210,7 @@ msgstr "^3Doppelklicke ^7ein Panel für Panel-spezifische Optionen." #: qcsrc/client/hud/panel/infomessages.qc:227 msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and" -msgstr "^3STRG^7, um Kollisionstests zu deaktivieren, ^3SHIFT ^7und" +msgstr "^3CTRL^7, um Kollisionstests zu deaktivieren, ^3SHIFT ^7und" #: qcsrc/client/hud/panel/infomessages.qc:228 msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments." @@ -222,7 +222,7 @@ msgstr "Persönliche Bestzeit" #: qcsrc/client/hud/panel/modicons.qc:576 msgid "Server best" -msgstr "Server Bestzeit" +msgstr "Server-Bestzeit" #: qcsrc/client/hud/panel/notify.qc:115 qcsrc/client/hud/panel/notify.qc:116 #: qcsrc/client/hud/panel/score.qc:59 @@ -285,7 +285,7 @@ msgstr "freier Gegenstand %x^7 (l:%y^7)" #: qcsrc/client/hud/panel/quickmenu.qc:804 msgid "QMCMD^free item, icon" -msgstr "freier Gegenstand, icon" +msgstr "freier Gegenstand, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:805 msgid "QMCMD^took item (l:%l^7)" @@ -293,7 +293,7 @@ msgstr "Gegenstand genommen (l:%l^7)" #: qcsrc/client/hud/panel/quickmenu.qc:805 msgid "QMCMD^took item, icon" -msgstr "Gegenstand genommen, icon" +msgstr "Gegenstand genommen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:806 msgid "QMCMD^negative" @@ -309,7 +309,7 @@ msgstr "brauche Hilfe (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" #: qcsrc/client/hud/panel/quickmenu.qc:808 msgid "QMCMD^need help, icon" -msgstr "brauche Hilfe, icon" +msgstr "brauche Hilfe, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:809 msgid "QMCMD^enemy seen (l:%y^7)" @@ -317,7 +317,7 @@ msgstr "Gegner gesehen (l:%y^7)" #: qcsrc/client/hud/panel/quickmenu.qc:809 msgid "QMCMD^enemy seen, icon" -msgstr "Gegner gesehen, icon" +msgstr "Gegner gesehen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:810 msgid "QMCMD^flag seen (l:%y^7)" @@ -325,7 +325,7 @@ msgstr "Flagge gesehen (l:%y^7)" #: qcsrc/client/hud/panel/quickmenu.qc:810 msgid "QMCMD^flag seen, icon" -msgstr "Flagge gesehen, icon" +msgstr "Flagge gesehen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:811 msgid "QMCMD^defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" @@ -333,7 +333,7 @@ msgstr "verteidigen (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" #: qcsrc/client/hud/panel/quickmenu.qc:811 msgid "QMCMD^defending, icon" -msgstr "verteidigen, icon" +msgstr "verteidigen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:812 msgid "QMCMD^roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" @@ -341,7 +341,7 @@ msgstr "wandernd (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" #: qcsrc/client/hud/panel/quickmenu.qc:812 msgid "QMCMD^roaming, icon" -msgstr "wandernd, icon" +msgstr "wandernd, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:813 msgid "QMCMD^attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" @@ -349,7 +349,7 @@ msgstr "angreifen (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" #: qcsrc/client/hud/panel/quickmenu.qc:813 msgid "QMCMD^attacking, icon" -msgstr "angreifen, Iion" +msgstr "angreifen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:814 msgid "QMCMD^killed flagcarrier (l:%y^7)" @@ -357,7 +357,7 @@ msgstr "Flaggenträger getötet (l:%y^7)" #: qcsrc/client/hud/panel/quickmenu.qc:814 msgid "QMCMD^killed flagcarrier, icon" -msgstr "Flaggenträger getötet, icon" +msgstr "Flaggenträger getötet, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:815 #, c-format @@ -366,11 +366,11 @@ msgstr "Flagge fallen gelassen (l:%d^7)" #: qcsrc/client/hud/panel/quickmenu.qc:815 msgid "QMCMD^dropped flag, icon" -msgstr "Flagge fallen gelassen, icon" +msgstr "Flagge fallen gelassen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:816 msgid "QMCMD^drop weapon, icon" -msgstr "Waffe wegwerfen, icon" +msgstr "Waffe wegwerfen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:816 msgid "QMCMD^dropped weapon %w^7 (l:%l^7)" @@ -378,7 +378,7 @@ msgstr "Waffe fallen gelassen %w^7 (l:%l^7)" #: qcsrc/client/hud/panel/quickmenu.qc:817 msgid "QMCMD^drop flag/key, icon" -msgstr "Flagge/Schlüssel fallen gelassen, icon" +msgstr "Flagge/Schlüssel fallen gelassen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:817 msgid "QMCMD^dropped flag/key %w^7 (l:%l^7)" @@ -694,7 +694,7 @@ msgstr "ticks" msgid "" "You can modify the scoreboard using the ^2scoreboard_columns_set command.\n" msgstr "" -"Du kannst die Tabelle mit dem ^2scoreboard_columns_set-Befehl ändern.\n" +"Du kannst die Punktetafel mit dem ^2scoreboard_columns_set-Befehl ändern.\n" #: qcsrc/client/hud/panel/scoreboard.qc:296 msgid "^3|---------------------------------------------------------------|\n" @@ -792,7 +792,7 @@ msgstr "^3capzeit^7 Zeit des schnellsten Captures (CTF)\n" #: qcsrc/client/hud/panel/scoreboard.qc:319 msgid "^3fckills^7 Number of flag carrier kills\n" -msgstr "^3fckills^7 Anzahl der getöteten Flaggen-Träger\n" +msgstr "^3fckills^7 Anzahl der getöteten Flaggenträger\n" #: qcsrc/client/hud/panel/scoreboard.qc:320 msgid "^3returns^7 Number of flag returns\n" @@ -950,7 +950,7 @@ msgstr "Platzierungen" #: qcsrc/client/hud/panel/scoreboard.qc:1519 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:43 msgid "Scoreboard" -msgstr "Tabelle" +msgstr "Punktetafel" #: qcsrc/client/hud/panel/scoreboard.qc:1584 #, c-format @@ -1022,7 +1022,7 @@ msgstr "Du bist tot, warte ^3%s^7 bis zum Respawn" #: qcsrc/client/hud/panel/scoreboard.qc:1707 #, c-format msgid "You are dead, press ^2%s^7 to respawn" -msgstr "Du bist tot, drücke ^2%s^7 um neu zu spawnen" +msgstr "Du bist tot, drücke ^2%s^7, um neu zu spawnen" #: qcsrc/client/hud/panel/vote.qc:24 msgid "^1You must answer before entering hud configure mode\n" @@ -1070,11 +1070,11 @@ msgstr "Keine Munition mehr" #: qcsrc/client/hud/panel/weapons.qc:534 msgid "Don't have" -msgstr "Nicht vorhanden" +msgstr "Hast du nicht" #: qcsrc/client/hud/panel/weapons.qc:538 msgid "Unavailable" -msgstr "Nicht verfügbar" +msgstr "Fehlend" #: qcsrc/client/main.qc:1014 msgid " qu/s" @@ -1384,11 +1384,11 @@ msgstr "Vielleicht klappt es beim nächsten Mal!" #: qcsrc/common/minigames/minigame/bd.qc:1172 msgid "Tubular! Press \"Next Level\" to continue!" -msgstr "Großartig! Drücke „Nächter Level“ zum Fortfahren!" +msgstr "Großartig! Drücke „Nächstes Level“ zum Fortfahren!" #: qcsrc/common/minigames/minigame/bd.qc:1174 msgid "Wicked! Press \"Next Level\" to continue!" -msgstr "Wahnsinn! Klicke \"Nächstes Level\" um weiter zu spielen!" +msgstr "Wahnsinn! Drücke „Nächstes Level“ zum Fortfahren!" #: qcsrc/common/minigames/minigame/bd.qc:1177 msgid "Press the space bar to change your currently selected tile" @@ -1419,7 +1419,7 @@ msgstr "Speichern" #: qcsrc/common/minigames/minigame/pp.qc:438 #: qcsrc/common/minigames/minigame/ttt.qc:319 msgid "Draw" -msgstr "Zeichnen" +msgstr "Unentschieden" #: qcsrc/common/minigames/minigame/c4.qc:378 #: qcsrc/common/minigames/minigame/nmm.qc:601 @@ -1521,7 +1521,7 @@ msgstr "Nächstes Spiel" #: qcsrc/common/minigames/minigame/ps.qc:478 #, c-format msgid "Pieces left: %s" -msgstr "Verbleibende Spielfiguren: %s" +msgstr "Figuren: %s" #: qcsrc/common/minigames/minigame/ps.qc:488 msgid "No more valid moves" @@ -2626,7 +2626,7 @@ msgstr "^BGDu hast ^F1%s^BG%s fallengelassen" #: qcsrc/common/notifications/all.inc:698 #, c-format msgid "^BGYou got the ^F1%s" -msgstr "^BG^F1%s^K1 erhalten" +msgstr "^F1%s^BG erhalten" #: qcsrc/common/notifications/all.inc:385 #: qcsrc/common/notifications/all.inc:699 @@ -2734,12 +2734,12 @@ msgstr "^BGTeam ^TC^TT^BG hielt den Ball zu lange fest" #: qcsrc/common/notifications/all.inc:412 #, c-format msgid "^BG%s^BG captured %s^BG control point" -msgstr "^BG%s^BG hat den Kontrollpunkt von %s^BG erobert" +msgstr "^BG%s^BG hat einen Kontrollpunkt erobert: %s^BG" #: qcsrc/common/notifications/all.inc:413 #, c-format msgid "^TC^TT^BG team %s^BG control point has been destroyed by %s" -msgstr "^TC^TT^BGDer Kontrollpunkt vom Team %s^BG wurde von %s zerstört" +msgstr "^TC^TT^BGEin Kontrollpunkt vom Team %s^BG wurde von %s zerstört" #: qcsrc/common/notifications/all.inc:414 msgid "^TC^TT^BG generator has been destroyed" @@ -2759,7 +2759,7 @@ msgstr "^BG%s^K1 hat Unsichtbarkeit aufgesammelt" #: qcsrc/common/notifications/all.inc:418 #, c-format msgid "^BG%s^K1 picked up Shield" -msgstr "^BG%s^K1 hat das Schild aufgenommen" +msgstr "^BG%s^K1 hat den Schild aufgenommen" #: qcsrc/common/notifications/all.inc:419 #, c-format @@ -3596,7 +3596,7 @@ msgstr "^K1Deine Medizin-Granate ist ein wenig defekt" #: qcsrc/common/notifications/all.inc:644 msgid "^K1You are respawning for running out of ammo..." -msgstr "^K1Du wirst wiederbelebt weil du keine Munition mehr hast …" +msgstr "^K1Du wirst wiederbelebt, weil du keine Munition mehr hast …" #: qcsrc/common/notifications/all.inc:644 msgid "^K1You were killed for running out of ammo..." @@ -3913,12 +3913,12 @@ msgstr "^F2Aktive Waffe: ^F1%s" #: qcsrc/common/notifications/all.inc:733 #, c-format msgid "^BGYou captured %s^BG control point" -msgstr "^BGDu hast den Kontrollpunkt von %s^BG erobert" +msgstr "^BGDu hast einen Kontrollpunkt erobert: %s^BG" #: qcsrc/common/notifications/all.inc:734 #, c-format msgid "^TC^TT^BG team captured %s^BG control point" -msgstr "Team ^TC^TT^BG hat %ss^BG Kontrollpunkt erobert" +msgstr "Team ^TC^TT^BG hat einen Kontrollpunkt erobert: %s^BG" #: qcsrc/common/notifications/all.inc:735 msgid "^BGThis control point currently cannot be captured" @@ -4019,7 +4019,7 @@ msgstr "^F2Ein Schild umgibt dich" #: qcsrc/common/notifications/all.inc:754 msgid "^F2Shield has worn off" -msgstr "^F2Das Schild ist wieder verschwunden" +msgstr "^F2Der Schild ist wieder verschwunden" #: qcsrc/common/notifications/all.inc:756 msgid "^F2You are on speed" @@ -5257,7 +5257,7 @@ msgstr "Schriftgröße:" #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qh:6 msgid "Centerprint Panel" -msgstr "Nachrichten-Panel" +msgstr "Zentralanzeigen-Panel" #: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:15 msgid "Chat entries:" @@ -5355,7 +5355,7 @@ msgstr "Beim Zuschauen zeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:18 msgid "PNL^Enabled even playing in warmup" -msgstr "Auch in der Aufwärmphase zeigen" +msgstr "Auch in Aufwärmphase zeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:29 msgid "Reduced" @@ -5363,7 +5363,7 @@ msgstr "Reduziert" #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:32 msgid "Text/icon ratio:" -msgstr "Text/Icon-Verhältnis:" +msgstr "Text-/Icon-Verhältnis:" #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:35 msgid "Hide spawned items" @@ -5407,7 +5407,7 @@ msgstr "Eintrags-Ausblendung:" #: qcsrc/menu/xonotic/dialog_hudpanel_notification.qh:6 msgid "Notification Panel" -msgstr "Anzeige-Panel" +msgstr "Nachrichten-Panel" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:15 #: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:14 @@ -5421,11 +5421,11 @@ msgstr "Panel anzeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:17 msgid "Panel enabled even observing" -msgstr "Panel auch beim Zuschauen anzeigen" +msgstr "Auch beim Zuschauen zeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:18 msgid "Panel enabled only in Race/CTS" -msgstr "Panel nur in Rennen und CTS-Rennen anzeigen" +msgstr "Nur in Rennen und CTS-Rennen zeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:24 msgid "Status bar" @@ -5536,7 +5536,7 @@ msgstr "Rundenzeit-Panel" #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:16 msgid "Panel enabled in teamgames" -msgstr "Panel in Team-Spieltypen aktivieren" +msgstr "Panel in Teamspielen aktivieren" #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:23 msgid "Radar:" @@ -6317,13 +6317,11 @@ msgstr "Spielmechanik-Mutatoren:" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:160 msgid "Enable dodging" -msgstr "" -"Ausweichmodus: Es ist möglich rasch zur Seite zu springen (spezielle " -"Bewegung)" +msgstr "Ausweichmanöver aktivieren" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:167 msgid "All players are almost invisible" -msgstr "Tarnmodus: Alle Spieler sind fast unsichtbar" +msgstr "Alle Spieler sind fast unsichtbar" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:174 msgid "Only possible to inflict damage on your enemy while he's airborne" @@ -6333,15 +6331,15 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:178 msgid "Damage done to your enemy gets added to your own health" msgstr "" -"Vampirmodus: Der Schaden, dem du anderen Spielern zufügst, wird deiner " -"eigenen Lebensenergie hinzugefügt" +"Der Schaden, dem du anderen Spielern zufügst, wird deiner eigenen " +"Lebensenergie hinzugefügt" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:183 msgid "" "Amount of health below which your player gets stunned because of blood loss" msgstr "" -"Blutverlust: Aktiviere diesen Modus und stelle den Wert der Lebensenergie, " -"bei der Spieler auf Grund von Blutverlust betäubt wirken, ein" +"Aktiviere diesen Modus und stelle den Wert der Lebensenergie, bei der " +"Spieler auf Grund von Blutverlust betäubt wirken, ein" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:192 msgid "Make things fall to the ground slower, lower value means lower gravity" @@ -6390,10 +6388,9 @@ msgid "" "Selecting a weapon arena will give all players that weapon at spawn as well " "as unlimited ammo, and disable all other weapon pickups." msgstr "" -"Waffen-Arenen: Die Auswahl einer Waffen-Arena führt dazu, dass jeder Spieler " -"mit der gewählten Waffe startet. Diese hat unendlich viel Munition, andere " -"Waffen sind nicht vorhanden – Spezielle Waffen-Arenen: Spieler starten mit " -"allen Waffen und unendlich viel Munition" +"Die Auswahl einer Waffen-Arena führt dazu, dass jeder Spieler mit der " +"gewählten Waffe startet. Diese hat unendlich viel Munition, andere Waffen " +"sind nicht vorhanden." #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:255 msgid "Most weapons" @@ -6617,7 +6614,7 @@ msgstr "Musikplayer" #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:48 msgid "Auto record demos" -msgstr "Wiederholungen automatisch aufzeichnen" +msgstr "Wiederholungen autom. aufzeichnen" #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:57 msgid "Timedemo" @@ -6708,7 +6705,7 @@ msgstr "Alle entfernen" #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:43 msgid "Auto screenshot scoreboard" -msgstr "Screenshot der Tabelle automatisch anfertigen" +msgstr "Auto-Screenshot der Punktetafel" #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:63 msgid "Open in the viewer" @@ -7419,7 +7416,7 @@ msgstr "Scharf" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:163 msgid "Decals" -msgstr "Einschusslöcher" +msgstr "Dekore" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:164 msgid "Enable decals (bullet holes and blood) (default: enabled)" @@ -7717,7 +7714,7 @@ msgstr "Dezimalstellen im Respawn-Countdown anzeigen" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:57 msgid "Show accuracy underneath scoreboard" -msgstr "Trefferquote unter Tabelle anzeigen" +msgstr "Trefferquote unter Punktetafel anzeigen" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:61 msgid "Waypoints" @@ -7824,7 +7821,7 @@ msgstr "Um den HUD-Editor zu starten, muss ein Spiel gestartet werden." #: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:23 msgid "Do you wish to start a local game to set up the HUD?" -msgstr "Willst du ein lokales Spiel starten, um das HUD zu editieren?" +msgstr "Willst du ein lokales Spiel starten, um das HUD zu bearbeiten?" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:24 msgid "Frag Information" @@ -7840,7 +7837,7 @@ msgstr "Amokläufe nur anzeigen, wenn sie Achievements sind" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:34 msgid "Show spree information in centerprints" -msgstr "Amoklauf-Informationen in Centerprints anzeigen" +msgstr "Amoklauf-Infos in Zentralanzeige zeigen" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:38 msgid "Show spree information in death messages" @@ -7872,7 +7869,7 @@ msgstr "In separater Zeile anzeigen" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:58 msgid "Add extra frag information to centerprint when available" -msgstr "Zusätzliche Frag-Informationen in Centerprint anzeigen, wenn verfügbar" +msgstr "Zusätzliche Frag-Infos in Zentralanzeige zeigen, wenn verfügbar" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:62 msgid "Add frag location to death messages when available" @@ -7914,7 +7911,7 @@ msgstr "Powerup-Nachrichten" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:89 msgid "Weapon centerprint notifications" -msgstr "Waffen-Centerprint-Nachrichten" +msgstr "Waffen-Zentralanzeigen-Nachrichten" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:92 msgid "Weapon info message notifications" @@ -7995,7 +7992,7 @@ msgstr "Nur in Nicht-Teamspielen" #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:60 msgid "Body fading:" -msgstr "Ausblenden von Leichen:" +msgstr "Leichenausblendung:" #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:63 msgid "Gibs:" @@ -8290,7 +8287,7 @@ msgstr "Auto-Springen" #: qcsrc/menu/xonotic/dialog_settings_input.qc:99 msgid "Jetpack on jump:" -msgstr "Jetpack aktiveren durch Springen:" +msgstr "Jetpack bei Sprung:" #: qcsrc/menu/xonotic/dialog_settings_input.qc:101 msgid "JPJUMP^Disabled" @@ -8395,7 +8392,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:48 msgid "Server queries/s:" -msgstr "Server Anfragen/Sekunde:" +msgstr "Serveranfragen/s:" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:52 msgid "Downloads:" @@ -8589,11 +8586,12 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:10 msgid "While connected language changes will be applied only to the menu," msgstr "" -"Während du verbunden bist, werden Sprachänderungen nur auf das Menü angewandt" +"Während du verbunden bist, werden Sprachänderungen nur auf das Menü " +"angewandt;" #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:12 msgid "full language changes will take effect starting from the next game" -msgstr "Volle Sprachänderungen finden erst nach dem Neustart des Spiels statt" +msgstr "volle Sprachänderungen finden erst nach dem Neustart des Spiels statt." #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:16 msgid "Disconnect now" @@ -8940,7 +8938,7 @@ msgstr "Einzelspieler" #: qcsrc/menu/xonotic/dialog_singleplayer.qh:7 msgid "Play the singleplayer campaign or instant action matches against bots" msgstr "" -"Spiele die Einzelspieler-Kampagne oder habe Instant-Action Spiele gegen Bots" +"Spiele die Einzelspieler-Kampagne oder spiele ein Schnellspiel gegen Bots" #: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7 msgid "Winner" @@ -9492,7 +9490,7 @@ msgstr "" #: qcsrc/menu/xonotic/util.qc:780 msgid "Use default" -msgstr "Standard verwenden" +msgstr "Standard" #: qcsrc/menu/xonotic/util.qc:800 msgid "Team Color:" diff --git a/common.de_CH.po b/common.de_CH.po index d5c87645f..2c2c96b5d 100644 --- a/common.de_CH.po +++ b/common.de_CH.po @@ -3,7 +3,7 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: -# Wuzzy , 2016-2017 +# Wuzzy , 2016-2018 # Brot Brot , 2015 # cvcxc , 2013 # divVerent , 2011,2013 @@ -24,7 +24,7 @@ msgstr "" "Project-Id-Version: Xonotic\n" "Report-Msgid-Bugs-To: \n" "POT-Creation-Date: 2017-07-09 00:35+0200\n" -"PO-Revision-Date: 2017-09-23 19:12+0000\n" +"PO-Revision-Date: 2018-07-13 16:04+0000\n" "Last-Translator: Wuzzy \n" "Language-Team: German (http://www.transifex.com/team-xonotic/xonotic/" "language/de/)\n" @@ -48,7 +48,7 @@ msgstr "^1Konnte nicht nach %s schreiben\n" #: qcsrc/client/hud/panel/chat.qc:82 msgid "^3Player^7: This is the chat area." -msgstr "^3Player^7: Dies ist der Chat-Bereich." +msgstr "^3Spieler^7: Dies ist der Chat-Bereich." #: qcsrc/client/hud/panel/engineinfo.qc:69 #, c-format @@ -210,7 +210,7 @@ msgstr "^3Doppelklicke ^7ein Panel für Panel-spezifische Optionen." #: qcsrc/client/hud/panel/infomessages.qc:227 msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and" -msgstr "^3STRG^7, um Kollisionstests zu deaktivieren, ^3SHIFT ^7und" +msgstr "^3CTRL^7, um Kollisionstests zu deaktivieren, ^3SHIFT ^7und" #: qcsrc/client/hud/panel/infomessages.qc:228 msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments." @@ -222,7 +222,7 @@ msgstr "Persönliche Bestzeit" #: qcsrc/client/hud/panel/modicons.qc:576 msgid "Server best" -msgstr "Server Bestzeit" +msgstr "Server-Bestzeit" #: qcsrc/client/hud/panel/notify.qc:115 qcsrc/client/hud/panel/notify.qc:116 #: qcsrc/client/hud/panel/score.qc:59 @@ -285,7 +285,7 @@ msgstr "freier Gegenstand %x^7 (l:%y^7)" #: qcsrc/client/hud/panel/quickmenu.qc:804 msgid "QMCMD^free item, icon" -msgstr "freier Gegenstand, icon" +msgstr "freier Gegenstand, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:805 msgid "QMCMD^took item (l:%l^7)" @@ -293,7 +293,7 @@ msgstr "Gegenstand genommen (l:%l^7)" #: qcsrc/client/hud/panel/quickmenu.qc:805 msgid "QMCMD^took item, icon" -msgstr "Gegenstand genommen, icon" +msgstr "Gegenstand genommen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:806 msgid "QMCMD^negative" @@ -309,7 +309,7 @@ msgstr "brauche Hilfe (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" #: qcsrc/client/hud/panel/quickmenu.qc:808 msgid "QMCMD^need help, icon" -msgstr "brauche Hilfe, icon" +msgstr "brauche Hilfe, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:809 msgid "QMCMD^enemy seen (l:%y^7)" @@ -317,7 +317,7 @@ msgstr "Gegner gesehen (l:%y^7)" #: qcsrc/client/hud/panel/quickmenu.qc:809 msgid "QMCMD^enemy seen, icon" -msgstr "Gegner gesehen, icon" +msgstr "Gegner gesehen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:810 msgid "QMCMD^flag seen (l:%y^7)" @@ -325,7 +325,7 @@ msgstr "Flagge gesehen (l:%y^7)" #: qcsrc/client/hud/panel/quickmenu.qc:810 msgid "QMCMD^flag seen, icon" -msgstr "Flagge gesehen, icon" +msgstr "Flagge gesehen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:811 msgid "QMCMD^defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" @@ -333,7 +333,7 @@ msgstr "verteidigen (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" #: qcsrc/client/hud/panel/quickmenu.qc:811 msgid "QMCMD^defending, icon" -msgstr "verteidigen, icon" +msgstr "verteidigen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:812 msgid "QMCMD^roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" @@ -341,7 +341,7 @@ msgstr "wandernd (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" #: qcsrc/client/hud/panel/quickmenu.qc:812 msgid "QMCMD^roaming, icon" -msgstr "wandernd, icon" +msgstr "wandernd, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:813 msgid "QMCMD^attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" @@ -349,7 +349,7 @@ msgstr "angreifen (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)" #: qcsrc/client/hud/panel/quickmenu.qc:813 msgid "QMCMD^attacking, icon" -msgstr "angreifen, Iion" +msgstr "angreifen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:814 msgid "QMCMD^killed flagcarrier (l:%y^7)" @@ -357,7 +357,7 @@ msgstr "Flaggenträger getötet (l:%y^7)" #: qcsrc/client/hud/panel/quickmenu.qc:814 msgid "QMCMD^killed flagcarrier, icon" -msgstr "Flaggenträger getötet, icon" +msgstr "Flaggenträger getötet, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:815 #, c-format @@ -366,11 +366,11 @@ msgstr "Flagge fallen gelassen (l:%d^7)" #: qcsrc/client/hud/panel/quickmenu.qc:815 msgid "QMCMD^dropped flag, icon" -msgstr "Flagge fallen gelassen, icon" +msgstr "Flagge fallen gelassen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:816 msgid "QMCMD^drop weapon, icon" -msgstr "Waffe wegwerfen, icon" +msgstr "Waffe wegwerfen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:816 msgid "QMCMD^dropped weapon %w^7 (l:%l^7)" @@ -378,7 +378,7 @@ msgstr "Waffe fallen gelassen %w^7 (l:%l^7)" #: qcsrc/client/hud/panel/quickmenu.qc:817 msgid "QMCMD^drop flag/key, icon" -msgstr "Flagge/Schlüssel fallen gelassen, icon" +msgstr "Flagge/Schlüssel fallen gelassen, Icon" #: qcsrc/client/hud/panel/quickmenu.qc:817 msgid "QMCMD^dropped flag/key %w^7 (l:%l^7)" @@ -694,7 +694,7 @@ msgstr "ticks" msgid "" "You can modify the scoreboard using the ^2scoreboard_columns_set command.\n" msgstr "" -"Du kannst die Tabelle mit dem ^2scoreboard_columns_set-Befehl ändern.\n" +"Du kannst die Punktetafel mit dem ^2scoreboard_columns_set-Befehl ändern.\n" #: qcsrc/client/hud/panel/scoreboard.qc:296 msgid "^3|---------------------------------------------------------------|\n" @@ -792,7 +792,7 @@ msgstr "^3capzeit^7 Zeit des schnellsten Captures (CTF)\n" #: qcsrc/client/hud/panel/scoreboard.qc:319 msgid "^3fckills^7 Number of flag carrier kills\n" -msgstr "^3fckills^7 Anzahl der getöteten Flaggen-Träger\n" +msgstr "^3fckills^7 Anzahl der getöteten Flaggenträger\n" #: qcsrc/client/hud/panel/scoreboard.qc:320 msgid "^3returns^7 Number of flag returns\n" @@ -950,7 +950,7 @@ msgstr "Platzierungen" #: qcsrc/client/hud/panel/scoreboard.qc:1519 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:43 msgid "Scoreboard" -msgstr "Tabelle" +msgstr "Punktetafel" #: qcsrc/client/hud/panel/scoreboard.qc:1584 #, c-format @@ -1022,7 +1022,7 @@ msgstr "Du bist tot, warte ^3%s^7 bis zum Respawn" #: qcsrc/client/hud/panel/scoreboard.qc:1707 #, c-format msgid "You are dead, press ^2%s^7 to respawn" -msgstr "Du bist tot, drücke ^2%s^7 um neu zu spawnen" +msgstr "Du bist tot, drücke ^2%s^7, um neu zu spawnen" #: qcsrc/client/hud/panel/vote.qc:24 msgid "^1You must answer before entering hud configure mode\n" @@ -1070,11 +1070,11 @@ msgstr "Keine Munition mehr" #: qcsrc/client/hud/panel/weapons.qc:534 msgid "Don't have" -msgstr "Nicht vorhanden" +msgstr "Hast du nicht" #: qcsrc/client/hud/panel/weapons.qc:538 msgid "Unavailable" -msgstr "Nicht verfügbar" +msgstr "Fehlend" #: qcsrc/client/main.qc:1014 msgid " qu/s" @@ -1384,11 +1384,11 @@ msgstr "Vielleicht klappt es beim nächsten Mal!" #: qcsrc/common/minigames/minigame/bd.qc:1172 msgid "Tubular! Press \"Next Level\" to continue!" -msgstr "Grossartig! Drücke „Nächter Level“ zum Fortfahren!" +msgstr "Grossartig! Drücke „Nächstes Level“ zum Fortfahren!" #: qcsrc/common/minigames/minigame/bd.qc:1174 msgid "Wicked! Press \"Next Level\" to continue!" -msgstr "Wahnsinn! Klicke \"Nächstes Level\" um weiter zu spielen!" +msgstr "Wahnsinn! Drücke „Nächstes Level“ zum Fortfahren!" #: qcsrc/common/minigames/minigame/bd.qc:1177 msgid "Press the space bar to change your currently selected tile" @@ -1419,7 +1419,7 @@ msgstr "Speichern" #: qcsrc/common/minigames/minigame/pp.qc:438 #: qcsrc/common/minigames/minigame/ttt.qc:319 msgid "Draw" -msgstr "Zeichnen" +msgstr "Unentschieden" #: qcsrc/common/minigames/minigame/c4.qc:378 #: qcsrc/common/minigames/minigame/nmm.qc:601 @@ -1521,7 +1521,7 @@ msgstr "Nächstes Spiel" #: qcsrc/common/minigames/minigame/ps.qc:478 #, c-format msgid "Pieces left: %s" -msgstr "Verbleibende Spielfiguren: %s" +msgstr "Figuren: %s" #: qcsrc/common/minigames/minigame/ps.qc:488 msgid "No more valid moves" @@ -2626,7 +2626,7 @@ msgstr "^BGDu hast ^F1%s^BG%s fallengelassen" #: qcsrc/common/notifications/all.inc:698 #, c-format msgid "^BGYou got the ^F1%s" -msgstr "^BG^F1%s^K1 erhalten" +msgstr "^F1%s^BG erhalten" #: qcsrc/common/notifications/all.inc:385 #: qcsrc/common/notifications/all.inc:699 @@ -2734,12 +2734,12 @@ msgstr "^BGTeam ^TC^TT^BG hielt den Ball zu lange fest" #: qcsrc/common/notifications/all.inc:412 #, c-format msgid "^BG%s^BG captured %s^BG control point" -msgstr "^BG%s^BG hat den Kontrollpunkt von %s^BG erobert" +msgstr "^BG%s^BG hat einen Kontrollpunkt erobert: %s^BG" #: qcsrc/common/notifications/all.inc:413 #, c-format msgid "^TC^TT^BG team %s^BG control point has been destroyed by %s" -msgstr "^TC^TT^BGDer Kontrollpunkt vom Team %s^BG wurde von %s zerstört" +msgstr "^TC^TT^BGEin Kontrollpunkt vom Team %s^BG wurde von %s zerstört" #: qcsrc/common/notifications/all.inc:414 msgid "^TC^TT^BG generator has been destroyed" @@ -2759,7 +2759,7 @@ msgstr "^BG%s^K1 hat Unsichtbarkeit aufgesammelt" #: qcsrc/common/notifications/all.inc:418 #, c-format msgid "^BG%s^K1 picked up Shield" -msgstr "^BG%s^K1 hat das Schild aufgenommen" +msgstr "^BG%s^K1 hat den Schild aufgenommen" #: qcsrc/common/notifications/all.inc:419 #, c-format @@ -3597,7 +3597,7 @@ msgstr "^K1Deine Medizin-Granate ist ein wenig defekt" #: qcsrc/common/notifications/all.inc:644 msgid "^K1You are respawning for running out of ammo..." -msgstr "^K1Du wirst wiederbelebt weil du keine Munition mehr hast …" +msgstr "^K1Du wirst wiederbelebt, weil du keine Munition mehr hast …" #: qcsrc/common/notifications/all.inc:644 msgid "^K1You were killed for running out of ammo..." @@ -3914,12 +3914,12 @@ msgstr "^F2Aktive Waffe: ^F1%s" #: qcsrc/common/notifications/all.inc:733 #, c-format msgid "^BGYou captured %s^BG control point" -msgstr "^BGDu hast den Kontrollpunkt von %s^BG erobert" +msgstr "^BGDu hast einen Kontrollpunkt erobert: %s^BG" #: qcsrc/common/notifications/all.inc:734 #, c-format msgid "^TC^TT^BG team captured %s^BG control point" -msgstr "Team ^TC^TT^BG hat %ss^BG Kontrollpunkt erobert" +msgstr "Team ^TC^TT^BG hat einen Kontrollpunkt erobert: %s^BG" #: qcsrc/common/notifications/all.inc:735 msgid "^BGThis control point currently cannot be captured" @@ -4020,7 +4020,7 @@ msgstr "^F2Ein Schild umgibt dich" #: qcsrc/common/notifications/all.inc:754 msgid "^F2Shield has worn off" -msgstr "^F2Das Schild ist wieder verschwunden" +msgstr "^F2Der Schild ist wieder verschwunden" #: qcsrc/common/notifications/all.inc:756 msgid "^F2You are on speed" @@ -5258,7 +5258,7 @@ msgstr "Schriftgrösse:" #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qh:6 msgid "Centerprint Panel" -msgstr "Nachrichten-Panel" +msgstr "Zentralanzeigen-Panel" #: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:15 msgid "Chat entries:" @@ -5356,7 +5356,7 @@ msgstr "Beim Zuschauen zeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:18 msgid "PNL^Enabled even playing in warmup" -msgstr "Auch in der Aufwärmphase zeigen" +msgstr "Auch in Aufwärmphase zeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:29 msgid "Reduced" @@ -5364,7 +5364,7 @@ msgstr "Reduziert" #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:32 msgid "Text/icon ratio:" -msgstr "Text/Icon-Verhältnis:" +msgstr "Text-/Icon-Verhältnis:" #: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:35 msgid "Hide spawned items" @@ -5408,7 +5408,7 @@ msgstr "Eintrags-Ausblendung:" #: qcsrc/menu/xonotic/dialog_hudpanel_notification.qh:6 msgid "Notification Panel" -msgstr "Anzeige-Panel" +msgstr "Nachrichten-Panel" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:15 #: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:14 @@ -5422,11 +5422,11 @@ msgstr "Panel anzeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:17 msgid "Panel enabled even observing" -msgstr "Panel auch beim Zuschauen anzeigen" +msgstr "Auch beim Zuschauen zeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:18 msgid "Panel enabled only in Race/CTS" -msgstr "Panel nur in Rennen und CTS-Rennen anzeigen" +msgstr "Nur in Rennen und CTS-Rennen zeigen" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:24 msgid "Status bar" @@ -5537,7 +5537,7 @@ msgstr "Rundenzeit-Panel" #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:16 msgid "Panel enabled in teamgames" -msgstr "Panel in Team-Spieltypen aktivieren" +msgstr "Panel in Teamspielen aktivieren" #: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:23 msgid "Radar:" @@ -6318,13 +6318,11 @@ msgstr "Spielmechanik-Mutatoren:" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:160 msgid "Enable dodging" -msgstr "" -"Ausweichmodus: Es ist möglich rasch zur Seite zu springen (spezielle " -"Bewegung)" +msgstr "Ausweichmanöver aktivieren" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:167 msgid "All players are almost invisible" -msgstr "Tarnmodus: Alle Spieler sind fast unsichtbar" +msgstr "Alle Spieler sind fast unsichtbar" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:174 msgid "Only possible to inflict damage on your enemy while he's airborne" @@ -6334,15 +6332,15 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:178 msgid "Damage done to your enemy gets added to your own health" msgstr "" -"Vampirmodus: Der Schaden, dem du anderen Spielern zufügst, wird deiner " -"eigenen Lebensenergie hinzugefügt" +"Der Schaden, dem du anderen Spielern zufügst, wird deiner eigenen " +"Lebensenergie hinzugefügt" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:183 msgid "" "Amount of health below which your player gets stunned because of blood loss" msgstr "" -"Blutverlust: Aktiviere diesen Modus und stelle den Wert der Lebensenergie, " -"bei der Spieler auf Grund von Blutverlust betäubt wirken, ein" +"Aktiviere diesen Modus und stelle den Wert der Lebensenergie, bei der " +"Spieler auf Grund von Blutverlust betäubt wirken, ein" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:192 msgid "Make things fall to the ground slower, lower value means lower gravity" @@ -6391,10 +6389,9 @@ msgid "" "Selecting a weapon arena will give all players that weapon at spawn as well " "as unlimited ammo, and disable all other weapon pickups." msgstr "" -"Waffen-Arenen: Die Auswahl einer Waffen-Arena führt dazu, dass jeder Spieler " -"mit der gewählten Waffe startet. Diese hat unendlich viel Munition, andere " -"Waffen sind nicht vorhanden – Spezielle Waffen-Arenen: Spieler starten mit " -"allen Waffen und unendlich viel Munition" +"Die Auswahl einer Waffen-Arena führt dazu, dass jeder Spieler mit der " +"gewählten Waffe startet. Diese hat unendlich viel Munition, andere Waffen " +"sind nicht vorhanden." #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:255 msgid "Most weapons" @@ -6618,7 +6615,7 @@ msgstr "Musikplayer" #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:48 msgid "Auto record demos" -msgstr "Wiederholungen automatisch aufzeichnen" +msgstr "Wiederholungen autom. aufzeichnen" #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:57 msgid "Timedemo" @@ -6709,7 +6706,7 @@ msgstr "Alle entfernen" #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:43 msgid "Auto screenshot scoreboard" -msgstr "Screenshot der Tabelle automatisch anfertigen" +msgstr "Auto-Screenshot der Punktetafel" #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:63 msgid "Open in the viewer" @@ -7420,7 +7417,7 @@ msgstr "Scharf" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:163 msgid "Decals" -msgstr "Einschusslöcher" +msgstr "Dekore" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:164 msgid "Enable decals (bullet holes and blood) (default: enabled)" @@ -7718,7 +7715,7 @@ msgstr "Dezimalstellen im Respawn-Countdown anzeigen" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:57 msgid "Show accuracy underneath scoreboard" -msgstr "Trefferquote unter Tabelle anzeigen" +msgstr "Trefferquote unter Punktetafel anzeigen" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:61 msgid "Waypoints" @@ -7825,7 +7822,7 @@ msgstr "Um den HUD-Editor zu starten, muss ein Spiel gestartet werden." #: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:23 msgid "Do you wish to start a local game to set up the HUD?" -msgstr "Willst du ein lokales Spiel starten, um das HUD zu editieren?" +msgstr "Willst du ein lokales Spiel starten, um das HUD zu bearbeiten?" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:24 msgid "Frag Information" @@ -7841,7 +7838,7 @@ msgstr "Amokläufe nur anzeigen, wenn sie Achievements sind" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:34 msgid "Show spree information in centerprints" -msgstr "Amoklauf-Informationen in Centerprints anzeigen" +msgstr "Amoklauf-Infos in Zentralanzeige zeigen" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:38 msgid "Show spree information in death messages" @@ -7873,7 +7870,7 @@ msgstr "In separater Zeile anzeigen" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:58 msgid "Add extra frag information to centerprint when available" -msgstr "Zusätzliche Frag-Informationen in Centerprint anzeigen, wenn verfügbar" +msgstr "Zusätzliche Frag-Infos in Zentralanzeige zeigen, wenn verfügbar" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:62 msgid "Add frag location to death messages when available" @@ -7915,7 +7912,7 @@ msgstr "Powerup-Nachrichten" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:89 msgid "Weapon centerprint notifications" -msgstr "Waffen-Centerprint-Nachrichten" +msgstr "Waffen-Zentralanzeigen-Nachrichten" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:92 msgid "Weapon info message notifications" @@ -7996,7 +7993,7 @@ msgstr "Nur in Nicht-Teamspielen" #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:60 msgid "Body fading:" -msgstr "Ausblenden von Leichen:" +msgstr "Leichenausblendung:" #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:63 msgid "Gibs:" @@ -8291,7 +8288,7 @@ msgstr "Auto-Springen" #: qcsrc/menu/xonotic/dialog_settings_input.qc:99 msgid "Jetpack on jump:" -msgstr "Jetpack aktiveren durch Springen:" +msgstr "Jetpack bei Sprung:" #: qcsrc/menu/xonotic/dialog_settings_input.qc:101 msgid "JPJUMP^Disabled" @@ -8396,7 +8393,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:48 msgid "Server queries/s:" -msgstr "Server Anfragen/Sekunde:" +msgstr "Serveranfragen/s:" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:52 msgid "Downloads:" @@ -8590,11 +8587,12 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:10 msgid "While connected language changes will be applied only to the menu," msgstr "" -"Während du verbunden bist, werden Sprachänderungen nur auf das Menü angewandt" +"Während du verbunden bist, werden Sprachänderungen nur auf das Menü " +"angewandt;" #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:12 msgid "full language changes will take effect starting from the next game" -msgstr "Volle Sprachänderungen finden erst nach dem Neustart des Spiels statt" +msgstr "volle Sprachänderungen finden erst nach dem Neustart des Spiels statt." #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:16 msgid "Disconnect now" @@ -8941,7 +8939,7 @@ msgstr "Einzelspieler" #: qcsrc/menu/xonotic/dialog_singleplayer.qh:7 msgid "Play the singleplayer campaign or instant action matches against bots" msgstr "" -"Spiele die Einzelspieler-Kampagne oder habe Instant-Action Spiele gegen Bots" +"Spiele die Einzelspieler-Kampagne oder spiele ein Schnellspiel gegen Bots" #: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7 msgid "Winner" @@ -9493,7 +9491,7 @@ msgstr "" #: qcsrc/menu/xonotic/util.qc:780 msgid "Use default" -msgstr "Standard verwenden" +msgstr "Standard" #: qcsrc/menu/xonotic/util.qc:800 msgid "Team Color:" diff --git a/common.fr.po b/common.fr.po index 84391e611..4a3b837d1 100644 --- a/common.fr.po +++ b/common.fr.po @@ -12,13 +12,13 @@ # RedGuff , 2014 # Yannick Le Guen , 2013 # Hugo Locurcio, 2013 -# Yannick Le Guen , 2013-2017 +# Yannick Le Guen , 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 \n" "Language-Team: French (http://www.transifex.com/team-xonotic/xonotic/" "language/fr/)\n" @@ -3086,12 +3086,12 @@ msgstr "" #: qcsrc/common/notifications/all.inc:484 #, c-format msgid "^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s" -msgstr "^BG%s%s^K1 a été abattu par la Mitrailleuse de ^BG%s^K1%s%s" +msgstr "^BG%s%s^K1 a été abattu par la Mitraillette de ^BG%s^K1%s%s" #: qcsrc/common/notifications/all.inc:485 #, c-format msgid "^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s" -msgstr "^BG%s%s^K1 a été criblé de balles par la Mitrailleuse de ^BG%s^K1%s%s" +msgstr "^BG%s%s^K1 a été criblé de balles par la Mitraillette de ^BG%s^K1%s%s" #: qcsrc/common/notifications/all.inc:486 #: qcsrc/common/notifications/all.inc:790 @@ -4631,7 +4631,7 @@ msgstr "Grappin" #: qcsrc/common/weapons/weapon/machinegun.qc:17 msgid "MachineGun" -msgstr "Mitrailleuse" +msgstr "Mitraillette" #: qcsrc/common/weapons/weapon/minelayer.qc:17 msgid "Mine Layer" diff --git a/common.he.po b/common.he.po index 593e684a6..6aa36e081 100644 --- a/common.he.po +++ b/common.he.po @@ -3,13 +3,14 @@ # This file is distributed under the same license as the PACKAGE package. # # Translators: +# nad le , 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 \n" +"PO-Revision-Date: 2018-07-10 10:55+0000\n" +"Last-Translator: nad le \n" "Language-Team: Hebrew (http://www.transifex.com/team-xonotic/xonotic/" "language/he/)\n" "Language: he\n" @@ -65,12 +66,12 @@ msgstr "" #: qcsrc/client/hud/panel/infomessages.qc:102 #: qcsrc/client/hud/panel/infomessages.qc:106 msgid "next weapon" -msgstr "" +msgstr "נשק הבא" #: qcsrc/client/hud/panel/infomessages.qc:102 #: qcsrc/client/hud/panel/infomessages.qc:106 msgid "previous weapon" -msgstr "" +msgstr "נשק קודם" #: qcsrc/client/hud/panel/infomessages.qc:106 #, c-format @@ -100,7 +101,7 @@ msgstr "" #: qcsrc/client/hud/panel/infomessages.qc:111 #: qcsrc/menu/xonotic/keybinder.qc:94 msgid "server info" -msgstr "" +msgstr "מידע על השרת" #: qcsrc/client/hud/panel/infomessages.qc:124 msgid "^1Match has already begun" @@ -140,7 +141,7 @@ msgstr "" #: qcsrc/client/hud/panel/infomessages.qc:175 #: qcsrc/menu/xonotic/keybinder.qc:91 msgid "ready" -msgstr "" +msgstr "מוכן" #: qcsrc/client/hud/panel/infomessages.qc:162 #, c-format @@ -172,7 +173,7 @@ msgstr "" #: qcsrc/client/hud/panel/infomessages.qc:199 #: qcsrc/menu/xonotic/keybinder.qc:102 msgid "team menu" -msgstr "" +msgstr "תפריט צוות" #: qcsrc/client/hud/panel/infomessages.qc:209 msgid "^1Spectating this player:" @@ -225,7 +226,7 @@ msgstr "" #: qcsrc/client/hud/panel/quickmenu.qc:636 msgid "Continue..." -msgstr "" +msgstr "המשך..." #: qcsrc/client/hud/panel/quickmenu.qc:794 #: qcsrc/client/hud/panel/quickmenu.qc:798 @@ -500,12 +501,12 @@ msgstr "" #: qcsrc/client/hud/panel/racetimer.qc:61 msgid "Start line" -msgstr "" +msgstr "קו התחלה" #: qcsrc/client/hud/panel/racetimer.qc:63 #: qcsrc/client/hud/panel/racetimer.qc:67 msgid "Finish line" -msgstr "" +msgstr "קו סיום" #: qcsrc/client/hud/panel/racetimer.qc:65 #, c-format @@ -1010,7 +1011,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:16 #: qcsrc/menu/xonotic/dialog_uid2name.qc:15 msgid "Yes" -msgstr "" +msgstr "כן" #: qcsrc/client/hud/panel/vote.qc:127 qcsrc/menu/xonotic/dialog_firstrun.qc:83 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:21 @@ -1020,7 +1021,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:17 #: qcsrc/menu/xonotic/dialog_uid2name.qc:17 msgid "No" -msgstr "" +msgstr "לא" #: qcsrc/client/hud/panel/weapons.qc:530 msgid "Out of ammo" @@ -1032,7 +1033,7 @@ msgstr "" #: qcsrc/client/hud/panel/weapons.qc:538 msgid "Unavailable" -msgstr "" +msgstr "לא זמין" #: qcsrc/client/main.qc:1014 msgid " qu/s" @@ -1078,7 +1079,7 @@ msgstr "" #: qcsrc/client/mapvoting.qc:365 msgid "Vote for a map" -msgstr "" +msgstr "הצבע למפה" #: qcsrc/client/mapvoting.qc:382 #, c-format @@ -1181,11 +1182,11 @@ msgstr "" #: qcsrc/common/mapinfo.qh:126 msgid "Race" -msgstr "" +msgstr "מרוץ" #: qcsrc/common/mapinfo.qh:126 msgid "Race against other players to the finish line" -msgstr "" +msgstr "התחרה נגד שחקנים אחרים לקו הסיום" #: qcsrc/common/mapinfo.qh:160 msgid "Race CTS" @@ -1205,7 +1206,7 @@ msgstr "" #: qcsrc/common/mapinfo.qh:220 msgid "Capture the Flag" -msgstr "" +msgstr "תפוס את הדגל" #: qcsrc/common/mapinfo.qh:220 msgid "" @@ -1308,7 +1309,7 @@ msgstr "" #: qcsrc/common/minigames/cl_minigames_hud.qc:403 msgid "Exit Menu" -msgstr "" +msgstr "צא מהתפריט" #: qcsrc/common/minigames/cl_minigames_hud.qc:415 #: qcsrc/menu/xonotic/dialog_multiplayer.qc:16 @@ -1317,7 +1318,7 @@ msgstr "" #: qcsrc/common/minigames/cl_minigames_hud.qc:418 msgid "Join" -msgstr "" +msgstr "הצטרף" #: qcsrc/common/minigames/cl_minigames_hud.qc:489 msgid "Minigames" @@ -1345,7 +1346,7 @@ msgstr "" #: qcsrc/common/minigames/minigame/bd.qc:1404 msgid "Next Level" -msgstr "" +msgstr "שלב הבא" #: qcsrc/common/minigames/minigame/bd.qc:1405 msgid "Restart" @@ -1358,7 +1359,7 @@ msgstr "" #: qcsrc/common/minigames/minigame/bd.qc:1407 #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:37 msgid "Save" -msgstr "" +msgstr "שמור" #: qcsrc/common/minigames/minigame/c4.qc:373 #: qcsrc/common/minigames/minigame/pp.qc:438 @@ -1414,15 +1415,15 @@ msgstr "" #: qcsrc/common/minigames/minigame/pong.qc:651 msgid "Start Match" -msgstr "" +msgstr "התחל משחק" #: qcsrc/common/minigames/minigame/pong.qc:652 msgid "Add AI player" -msgstr "" +msgstr "הוסף שחקן מחשב" #: qcsrc/common/minigames/minigame/pong.qc:653 msgid "Remove AI player" -msgstr "" +msgstr "הסר שחקן מחשב" #: qcsrc/common/minigames/minigame/pp.qc:443 #: qcsrc/common/minigames/minigame/ttt.qc:324 @@ -1451,7 +1452,7 @@ msgstr "" #: qcsrc/common/minigames/minigame/pp.qc:582 #: qcsrc/common/minigames/minigame/ttt.qc:665 msgid "Next Match" -msgstr "" +msgstr "משחק הבא" #: qcsrc/common/minigames/minigame/ps.qc:478 #, c-format @@ -1464,7 +1465,7 @@ msgstr "" #: qcsrc/common/minigames/minigame/ps.qc:491 msgid "Well done, you win!" -msgstr "" +msgstr "כל הכבוד, ניצחת!" #: qcsrc/common/minigames/minigame/ps.qc:494 msgid "Jump a piece over another to capture it" @@ -1477,7 +1478,7 @@ msgstr "" #: qcsrc/common/monsters/monster/mage.qh:17 #: qcsrc/menu/xonotic/dialog_monstertools.qc:18 msgid "Mage" -msgstr "" +msgstr "קוסם" #: qcsrc/common/monsters/monster/mage.qh:29 msgid "Mage spike" @@ -1491,7 +1492,7 @@ msgstr "" #: qcsrc/common/monsters/monster/spider.qh:17 #: qcsrc/menu/xonotic/dialog_monstertools.qc:16 msgid "Spider" -msgstr "" +msgstr "עכביש" #: qcsrc/common/monsters/monster/spider.qh:28 msgid "Spider attack" @@ -1509,11 +1510,11 @@ msgstr "" #: qcsrc/common/monsters/monster/zombie.qh:17 #: qcsrc/menu/xonotic/dialog_monstertools.qc:15 msgid "Zombie" -msgstr "" +msgstr "זומבי" #: qcsrc/common/mutators/mutator/buffs/all.inc:15 msgid "Ammo" -msgstr "" +msgstr "תחמושת" #: qcsrc/common/mutators/mutator/buffs/all.inc:24 msgid "Resistance" @@ -1522,7 +1523,7 @@ msgstr "" #: qcsrc/common/mutators/mutator/buffs/all.inc:33 #: qcsrc/common/mutators/mutator/instagib/items.qh:94 msgid "Speed" -msgstr "" +msgstr "מהירות" #: qcsrc/common/mutators/mutator/buffs/all.inc:43 msgid "Medic" @@ -1610,7 +1611,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:109 #: qcsrc/menu/xonotic/util.qc:775 msgid "Color:" -msgstr "" +msgstr "צבע:" #: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:47 msgid "Draw damage numbers for friendly fire" @@ -1781,7 +1782,7 @@ msgstr "" #: qcsrc/common/mutators/mutator/waypoints/all.inc:45 #: qcsrc/common/mutators/mutator/waypoints/all.inc:48 msgid "Ball" -msgstr "" +msgstr "כדור" #: qcsrc/common/mutators/mutator/waypoints/all.inc:46 msgid "Ball carrier" @@ -1798,19 +1799,19 @@ msgstr "" #: qcsrc/common/mutators/mutator/waypoints/all.inc:57 msgid "Weapon" -msgstr "" +msgstr "נשק" #: qcsrc/common/mutators/mutator/waypoints/all.inc:59 msgid "Monster" -msgstr "" +msgstr "מפלצת" #: qcsrc/common/mutators/mutator/waypoints/all.inc:61 msgid "Vehicle" -msgstr "" +msgstr "רכב" #: qcsrc/common/mutators/mutator/waypoints/all.inc:62 msgid "Intruder!" -msgstr "" +msgstr "פולש!" #: qcsrc/common/mutators/mutator/waypoints/all.inc:64 msgid "Tagged" @@ -4332,7 +4333,7 @@ msgstr "" #: qcsrc/common/turrets/turret/plasma_weapon.qh:7 msgid "Plasma" -msgstr "" +msgstr "פלזמה" #: qcsrc/common/turrets/turret/tesla.qh:13 #: qcsrc/common/turrets/turret/tesla_weapon.qh:7 @@ -4462,7 +4463,7 @@ msgstr "" #: qcsrc/common/weapons/weapon/shotgun.qc:17 msgid "Shotgun" -msgstr "" +msgstr "שוטגן" #: qcsrc/common/weapons/weapon/tuba.qc:17 #, no-c-format @@ -4712,7 +4713,7 @@ msgstr "" #: qcsrc/menu/command/menu_cmd.qc:79 msgid "Available options:\n" -msgstr "" +msgstr "אפשרויות זמינות:\n" #: qcsrc/menu/command/menu_cmd.qc:128 msgid "Invalid command. For a list of supported commands, try menu_cmd help.\n" @@ -4745,7 +4746,7 @@ msgstr "" #: qcsrc/menu/xonotic/credits.qc:48 msgid "Website" -msgstr "" +msgstr "אתר" #: qcsrc/menu/xonotic/credits.qc:53 msgid "Stats" @@ -4925,7 +4926,7 @@ msgstr "" #: qcsrc/menu/xonotic/cvarlist.qc:93 msgid "private" -msgstr "" +msgstr "פרטי" #: qcsrc/menu/xonotic/cvarlist.qc:95 msgid "engine setting" @@ -4946,7 +4947,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_credits.qh:7 msgid "Credits" -msgstr "" +msgstr "קרדיטים" #: qcsrc/menu/xonotic/dialog_credits.qh:8 msgid "The Xonotic credits" @@ -4962,7 +4963,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_firstrun.qc:45 #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:28 msgid "Name:" -msgstr "" +msgstr "שם:" #: qcsrc/menu/xonotic/dialog_firstrun.qc:53 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:60 @@ -4983,11 +4984,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_firstrun.qc:88 msgid "Save settings" -msgstr "" +msgstr "שמור הגדרות" #: qcsrc/menu/xonotic/dialog_firstrun.qh:6 msgid "Welcome" -msgstr "" +msgstr "ברוך הבא" #: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:16 msgid "Ammunition display:" @@ -5021,7 +5022,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:33 #: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:18 msgid "Left" -msgstr "" +msgstr "שמאל" #: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:32 #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:32 @@ -5032,7 +5033,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:34 #: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:20 msgid "Right" -msgstr "" +msgstr "ימין" #: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qh:6 msgid "Ammo Panel" @@ -5059,7 +5060,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:19 #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:71 msgid "Center" -msgstr "" +msgstr "מרכז" #: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:35 msgid "Font scale:" @@ -5075,7 +5076,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:18 msgid "Chat size:" -msgstr "" +msgstr "גודל צ'אט:" #: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:22 msgid "Chat lifetime:" @@ -5265,15 +5266,15 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:37 msgid "Speed:" -msgstr "" +msgstr "מהירות:" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:38 msgid "Include vertical speed" -msgstr "" +msgstr "כלול מהירות אנכית" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:49 msgid "Speed unit:" -msgstr "" +msgstr "יחידת מידה למהירות:" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:51 msgid "qu/s" @@ -5297,7 +5298,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:57 msgid "Show" -msgstr "" +msgstr "הצג" #: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:60 msgid "Top speed" @@ -5419,7 +5420,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:15 msgid "Score:" -msgstr "" +msgstr "ניקוד:" #: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:18 msgid "Rankings:" @@ -5470,7 +5471,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:139 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:55 msgid "Never" -msgstr "" +msgstr "לעולם לא" #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:24 #, c-format @@ -5515,7 +5516,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:54 msgid "Number" -msgstr "" +msgstr "מספר" #: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:55 msgid "Bind" @@ -5556,14 +5557,14 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:25 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:35 msgid "Filter:" -msgstr "" +msgstr "מסנן:" #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:30 #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:53 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:49 #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:44 msgid "Refresh" -msgstr "" +msgstr "רענן" #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:33 #: qcsrc/menu/xonotic/dialog_settings_user.qc:30 @@ -5581,7 +5582,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:48 #: qcsrc/menu/xonotic/util.qc:767 msgid "Background:" -msgstr "" +msgstr "רקע:" #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:50 #: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:62 @@ -5662,7 +5663,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_monstertools.qc:13 msgid "Monster:" -msgstr "" +msgstr "מפלצת:" #: qcsrc/menu/xonotic/dialog_monstertools.qc:22 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:20 @@ -5672,7 +5673,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_monstertools.qc:23 #: qcsrc/menu/xonotic/serverlist.qc:268 msgid "Remove" -msgstr "" +msgstr "הסר" #: qcsrc/menu/xonotic/dialog_monstertools.qc:25 msgid "Move target:" @@ -5696,7 +5697,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_monstertools.qc:31 msgid "Colors:" -msgstr "" +msgstr "צבעים:" #: qcsrc/menu/xonotic/dialog_monstertools.qc:33 #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:39 @@ -5709,7 +5710,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer.qc:14 msgid "Servers" -msgstr "" +msgstr "שרתים" #: qcsrc/menu/xonotic/dialog_multiplayer.qc:15 msgid "Find servers to play on" @@ -5743,12 +5744,12 @@ msgstr "" #: qcsrc/menu/xonotic/util.qc:785 qcsrc/menu/xonotic/util.qc:794 #: qcsrc/menu/xonotic/util.qc:802 qcsrc/menu/xonotic/util.qc:814 msgid "Default" -msgstr "" +msgstr "ברירת מחדל" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:48 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:64 msgid "Unlimited" -msgstr "" +msgstr "לא מוגבל" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:65 #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:66 @@ -5789,7 +5790,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:70 msgid "Lives:" -msgstr "" +msgstr "חיים:" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:71 msgid "Laps:" @@ -5805,11 +5806,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:97 msgid "Gametype" -msgstr "" +msgstr "סוג משחק" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:102 msgid "Time limit:" -msgstr "" +msgstr "הגבלת זמן:" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:104 msgid "Timelimit in minutes that when hit, will end the match" @@ -5827,7 +5828,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:107 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:159 msgid "1 minute" -msgstr "" +msgstr "דקה אחת" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:124 msgid "TIMLIM^Infinite" @@ -5835,19 +5836,19 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:132 msgid "Teams:" -msgstr "" +msgstr "צוותים:" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:135 msgid "2 teams" -msgstr "" +msgstr "2 צוותים" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:136 msgid "3 teams" -msgstr "" +msgstr "3 צוותים" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:137 msgid "4 teams" -msgstr "" +msgstr "4 צוותים" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:140 msgid "Player slots:" @@ -5881,15 +5882,15 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:153 msgid "Beginner" -msgstr "" +msgstr "מתחיל" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:154 msgid "You will win" -msgstr "" +msgstr "אתה תנצח" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:155 msgid "You can win" -msgstr "" +msgstr "אתה יכול לנצח" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:156 msgid "You might win" @@ -5897,27 +5898,27 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:157 msgid "Advanced" -msgstr "" +msgstr "מתקדם" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:158 msgid "Expert" -msgstr "" +msgstr "מומחה" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:159 msgid "Pro" -msgstr "" +msgstr "מקצוען" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:160 msgid "Assassin" -msgstr "" +msgstr "מתנקש" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:161 msgid "Unhuman" -msgstr "" +msgstr "לא אנושי" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:162 msgid "Godlike" -msgstr "" +msgstr "דמוי אל" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:178 msgid "Mutators..." @@ -5955,7 +5956,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:217 msgid "Add all" -msgstr "" +msgstr "הוסף הכל" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:218 msgid "Add every available map to your selection" @@ -5963,7 +5964,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:221 msgid "Remove all" -msgstr "" +msgstr "הסר הכל" #: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:222 msgid "Remove all the maps from your selection" @@ -5975,20 +5976,20 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:58 msgid "Title:" -msgstr "" +msgstr "כותרת:" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:64 msgid "Author:" -msgstr "" +msgstr "מחבר:" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:70 msgid "Game types:" -msgstr "" +msgstr "סוגי משחק:" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:93 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:296 msgid "Close" -msgstr "" +msgstr "סגור" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:96 msgid "MAP^Play" @@ -6044,7 +6045,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:75 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:282 msgid "No start weapons" -msgstr "" +msgstr "ללא נשקי התחלה" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:77 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:195 @@ -6073,7 +6074,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:89 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:229 msgid "Weapons stay" -msgstr "" +msgstr "נשקים נשארים" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:91 #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:184 @@ -6129,7 +6130,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:178 msgid "Damage done to your enemy gets added to your own health" -msgstr "" +msgstr "נזק שנעשה לאויב שלך מתווסף לחיים שלך" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:183 msgid "" @@ -6182,11 +6183,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:255 msgid "Most weapons" -msgstr "" +msgstr "רוב הנשקים" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:260 msgid "All weapons" -msgstr "" +msgstr "כל הנשקים" #: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:264 msgid "Special arenas:" @@ -6255,11 +6256,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:67 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:223 msgid "Address:" -msgstr "" +msgstr "כתובת:" #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:78 msgid "Info..." -msgstr "" +msgstr "מידע..." #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:79 msgid "Show more information about the currently highlighted server" @@ -6268,7 +6269,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:84 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:303 msgid "Join!" -msgstr "" +msgstr "הצטרף!" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:154 #: qcsrc/menu/xonotic/serverlist.qc:1061 @@ -6282,7 +6283,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:161 msgid "Official" -msgstr "" +msgstr "רשמי" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:169 msgid "N/A (auth library missing, can't connect)" @@ -6294,7 +6295,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:177 msgid "Not supported (can't connect)" -msgstr "" +msgstr "לא נתמך(לא יכול להתחבר)" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:179 msgid "Not supported (won't encrypt)" @@ -6330,11 +6331,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:231 msgid "Gametype:" -msgstr "" +msgstr "סוג משחק:" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:236 msgid "Map:" -msgstr "" +msgstr "מפה:" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:241 msgid "Mod:" @@ -6342,16 +6343,16 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:246 msgid "Version:" -msgstr "" +msgstr "גרסה:" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:251 msgid "Settings:" -msgstr "" +msgstr "הגדרות:" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:258 #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:290 msgid "Players:" -msgstr "" +msgstr "שחקנים:" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:263 msgid "Bots:" @@ -6375,7 +6376,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qh:7 msgid "Server Information" -msgstr "" +msgstr "מידע על השרת" #: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:25 msgid "Demos" @@ -6412,12 +6413,12 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:15 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:15 msgid "Do you really wish to disconnect now?" -msgstr "" +msgstr "אתה באמת רוצה להתנתק עכשיו?" #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qh:6 #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qh:6 msgid "Disconnect" -msgstr "" +msgstr "התנתק" #: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:13 msgid "Timing a demo will disconnect you from the current match." @@ -6445,7 +6446,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:55 msgid "Random order" -msgstr "" +msgstr "סדר אקראי" #: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:60 msgid "MUSICPL^Stop" @@ -6485,19 +6486,19 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:139 msgid "Reset" -msgstr "" +msgstr "אפס" #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:144 msgid "Previous" -msgstr "" +msgstr "קודם" #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:147 msgid "Next" -msgstr "" +msgstr "הבא" #: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:152 msgid "Slide show" -msgstr "" +msgstr "מצגת שקופיות" #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:34 #: qcsrc/menu/xonotic/dialog_settings_audio.qc:21 @@ -6510,7 +6511,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:48 msgid "Name" -msgstr "" +msgstr "שם" #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:77 msgid "Model" @@ -6538,38 +6539,38 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:145 msgid "Country" -msgstr "" +msgstr "מדינה" #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:159 msgid "Gender:" -msgstr "" +msgstr "מין:" #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:161 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:174 msgid "Undisclosed" -msgstr "" +msgstr "לא ידוע" #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:162 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:172 msgid "Female" -msgstr "" +msgstr "נקבה" #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:163 #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:173 msgid "Male" -msgstr "" +msgstr "זכר" #: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:166 msgid "Gender" -msgstr "" +msgstr "מין" #: qcsrc/menu/xonotic/dialog_quit.qc:11 msgid "Are you sure you want to quit?" -msgstr "" +msgstr "אתה בטוח שברצונך לצאת?" #: qcsrc/menu/xonotic/dialog_quit.qc:15 msgid "Back to work..." -msgstr "" +msgstr "בחזרה לעבודה..." #: qcsrc/menu/xonotic/dialog_quit.qc:17 msgid "I got some more fragging to do!" @@ -6577,7 +6578,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_quit.qh:7 msgid "Quit the game" -msgstr "" +msgstr "צא מהמשחק" #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:15 msgid "Model:" @@ -6585,15 +6586,15 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:21 msgid "Remove *" -msgstr "" +msgstr "הסר *" #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:23 msgid "Copy *" -msgstr "" +msgstr "העתק *" #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:24 msgid "Paste" -msgstr "" +msgstr "הדבק" #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:26 msgid "Bone:" @@ -6693,7 +6694,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:81 msgid "Show help" -msgstr "" +msgstr "הצג עזרה" #: qcsrc/menu/xonotic/dialog_sandboxtools.qc:82 msgid "* is the object you are facing" @@ -6709,23 +6710,23 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings.qc:19 msgid "Effects" -msgstr "" +msgstr "אפקטים" #: qcsrc/menu/xonotic/dialog_settings.qc:20 msgid "Audio" -msgstr "" +msgstr "שמע" #: qcsrc/menu/xonotic/dialog_settings.qc:22 msgid "Game" -msgstr "" +msgstr "משחק" #: qcsrc/menu/xonotic/dialog_settings.qc:23 msgid "Input" -msgstr "" +msgstr "קלט" #: qcsrc/menu/xonotic/dialog_settings.qc:24 msgid "User" -msgstr "" +msgstr "משתמש" #: qcsrc/menu/xonotic/dialog_settings.qc:25 #: qcsrc/menu/xonotic/keybinder.qc:105 @@ -6734,11 +6735,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings.qh:6 msgid "Settings" -msgstr "" +msgstr "הגדרות" #: qcsrc/menu/xonotic/dialog_settings.qh:7 msgid "Change the game settings" -msgstr "" +msgstr "שנה את הגדרות המשחק" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:29 msgid "Master:" @@ -6746,7 +6747,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:35 msgid "Music:" -msgstr "" +msgstr "מוזיקה:" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:43 msgid "VOL^Ambient:" @@ -6754,7 +6755,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:50 msgid "Info:" -msgstr "" +msgstr "מידע:" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:57 msgid "Items:" @@ -6766,7 +6767,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:71 msgid "Player:" -msgstr "" +msgstr "שחקן:" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:78 msgid "Shots:" @@ -6774,11 +6775,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:85 msgid "Voice:" -msgstr "" +msgstr "קול:" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:93 msgid "Weapons:" -msgstr "" +msgstr "נשקים:" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:99 msgid "New style sound attenuation" @@ -6842,7 +6843,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:123 msgid "Stereo" -msgstr "" +msgstr "סטראו" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:124 msgid "2.1" @@ -6900,7 +6901,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:149 msgid "Menu sounds" -msgstr "" +msgstr "צלילי תפריט" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:150 msgid "Play sounds when clicking menu items" @@ -6924,7 +6925,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:160 msgid "5 minutes" -msgstr "" +msgstr "5 דקות" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:161 msgid "WRN^Both" @@ -6940,17 +6941,17 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:168 msgid "Sometimes" -msgstr "" +msgstr "לפעמים" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:169 msgid "Often" -msgstr "" +msgstr "לעתים קרובות" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:170 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:141 #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:57 msgid "Always" -msgstr "" +msgstr "תמיד" #: qcsrc/menu/xonotic/dialog_settings_audio.qc:176 msgid "Debug info about sounds" @@ -7180,7 +7181,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:169 #: qcsrc/menu/xonotic/dialog_settings_effects.qc:253 msgid "Distance:" -msgstr "" +msgstr "מרחק" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:172 msgid "Decals further away than this will not be drawn (default: 300)" @@ -7188,7 +7189,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:176 msgid "Time:" -msgstr "" +msgstr "זמן:" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:179 msgid "Time in seconds before decals fade away (default: 2)" @@ -7264,7 +7265,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:212 msgid "Use normal maps" -msgstr "" +msgstr "השתמש במפות רגילות" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:213 msgid "Enable use of directional shading on textures (default: enabled)" @@ -7312,7 +7313,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:239 msgid "Particles" -msgstr "" +msgstr "חלקיקים" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:240 msgid "Spawnpoint effects" @@ -7324,7 +7325,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:246 msgid "Quality:" -msgstr "" +msgstr "איכות:" #: qcsrc/menu/xonotic/dialog_settings_effects.qc:249 msgid "" @@ -7355,11 +7356,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:81 #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:97 msgid "Size:" -msgstr "" +msgstr "גודל:" #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:64 msgid "By health" -msgstr "" +msgstr "לפי חיים" #: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:76 msgid "Use rings to indicate weapon status" @@ -7455,7 +7456,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:74 #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:124 msgid "Fontsize:" -msgstr "" +msgstr "גודל גופן:" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:80 msgid "Edge offset:" @@ -7467,7 +7468,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:94 msgid "Damage" -msgstr "" +msgstr "נזק" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:96 msgid "Overlay:" @@ -7487,11 +7488,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:114 msgid "Show names above players" -msgstr "" +msgstr "הצג שמות מעל שחקנים" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:130 msgid "Max distance:" -msgstr "" +msgstr "מרחק מקסימלי:" #: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:136 msgid "Decolorize:" @@ -7597,7 +7598,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:65 msgid "Gamemode Settings" -msgstr "" +msgstr "אפשרויות מצב משחק" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:67 msgid "Display capture times in Capture The Flag" @@ -7611,7 +7612,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_input.qc:91 #: qcsrc/menu/xonotic/dialog_settings_misc.qc:133 msgid "Other" -msgstr "" +msgstr "אחר" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:78 msgid "Display console messages in the top left corner" @@ -7655,7 +7656,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_messages.qh:7 msgid "Messages" -msgstr "" +msgstr "הודעות" #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:30 msgid "Items" @@ -7696,7 +7697,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:49 #: qcsrc/menu/xonotic/serverlist.qc:767 msgid "Players" -msgstr "" +msgstr "שחקנים" #: qcsrc/menu/xonotic/dialog_settings_game_model.qc:51 msgid "Force player models to mine" @@ -7768,7 +7769,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:51 msgid "3rd person perspective" -msgstr "" +msgstr "נקודת מבט מגוף שלישי" #: qcsrc/menu/xonotic/dialog_settings_game_view.qc:55 msgid "Back distance" @@ -7913,7 +7914,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_game_weapons.qh:7 #: qcsrc/menu/xonotic/keybinder.qc:43 msgid "Weapons" -msgstr "" +msgstr "נשקים" #: qcsrc/menu/xonotic/dialog_settings_input.qc:33 msgid "Key Bindings" @@ -7925,19 +7926,19 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_input.qc:41 msgid "Edit..." -msgstr "" +msgstr "ערוך..." #: qcsrc/menu/xonotic/dialog_settings_input.qc:47 msgid "Clear" -msgstr "" +msgstr "נקה" #: qcsrc/menu/xonotic/dialog_settings_input.qc:52 msgid "Reset all" -msgstr "" +msgstr "אפס הכל" #: qcsrc/menu/xonotic/dialog_settings_input.qc:57 msgid "Mouse" -msgstr "" +msgstr "עכבר" #: qcsrc/menu/xonotic/dialog_settings_input.qc:59 msgid "Sensitivity:" @@ -8013,7 +8014,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_input.qc:114 #: qcsrc/menu/xonotic/dialog_settings_input.qc:119 msgid "Use joystick input" -msgstr "" +msgstr "התשתמש בקלט מג'ויסטיק" #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:31 msgid "Command when pressed:" @@ -8025,7 +8026,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:40 msgid "Cancel" -msgstr "" +msgstr "בטל" #: qcsrc/menu/xonotic/dialog_settings_input_userbind.qh:7 msgid "User defined key bind" @@ -8048,7 +8049,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:27 msgid "Network" -msgstr "" +msgstr "רשת" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:29 msgid "Client UDP port:" @@ -8060,11 +8061,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:34 msgid "Bandwidth:" -msgstr "" +msgstr "רוחב פס:" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:36 msgid "Specify your network speed" -msgstr "" +msgstr "צין את מהירות הרשת שלך" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:37 msgid "56k" @@ -8100,7 +8101,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:52 msgid "Downloads:" -msgstr "" +msgstr "הורדות:" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:54 msgid "Maximum number of concurrent HTTP/FTP downloads" @@ -8108,7 +8109,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:56 msgid "Download speed:" -msgstr "" +msgstr "מהירות הורדה:" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:69 msgid "Local latency:" @@ -8148,7 +8149,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:102 msgid "Target:" -msgstr "" +msgstr "מטרה:" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:104 msgid "TRGT^Disabled" @@ -8168,7 +8169,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:129 msgid "Show frames per second" -msgstr "" +msgstr "הצג פריימים לשנייה" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:130 msgid "Show your rendered frames per second" @@ -8206,7 +8207,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:147 msgid "Enable developer mode" -msgstr "" +msgstr "אפשר מצב מפתח" #: qcsrc/menu/xonotic/dialog_settings_misc.qc:151 msgid "Advanced settings..." @@ -8235,23 +8236,23 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:49 msgid "Type:" -msgstr "" +msgstr "סוג:" #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:53 msgid "Value:" -msgstr "" +msgstr "ערך:" #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:70 msgid "Description:" -msgstr "" +msgstr "תיאור:" #: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qh:7 msgid "Advanced settings" -msgstr "" +msgstr "אפשרויות מתקדמות" #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:11 msgid "Are you sure you want to reset all settings?" -msgstr "" +msgstr "האם אתה בטוח שברצונך לאפס את כל ההגדרות?" #: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:13 msgid "This will create a backup config in your data directory" @@ -8263,11 +8264,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_user.qc:64 msgid "Text Language" -msgstr "" +msgstr "שפת טקסט" #: qcsrc/menu/xonotic/dialog_settings_user.qc:69 msgid "Set language" -msgstr "" +msgstr "קבע שפה" #: qcsrc/menu/xonotic/dialog_settings_user.qc:74 msgid "Disable gore effects and harsh language" @@ -8289,11 +8290,11 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:16 msgid "Disconnect now" -msgstr "" +msgstr "התנתק עכשיו" #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:17 msgid "Switch language" -msgstr "" +msgstr "החלף שפה" #: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qh:6 msgid "Warning" @@ -8361,7 +8362,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_settings_video.qc:59 msgid "Full screen" -msgstr "" +msgstr "מסך מלא" #: qcsrc/menu/xonotic/dialog_settings_video.qc:61 msgid "Vertical Synchronization" @@ -8611,7 +8612,7 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7 msgid "Winner" -msgstr "" +msgstr "מנצח" #: qcsrc/menu/xonotic/dialog_teamselect.qc:32 msgid "join 'best' team (auto-select)" @@ -8623,27 +8624,27 @@ msgstr "" #: qcsrc/menu/xonotic/dialog_teamselect.qc:37 msgid "red" -msgstr "" +msgstr "אדום" #: qcsrc/menu/xonotic/dialog_teamselect.qc:38 msgid "blue" -msgstr "" +msgstr "כחול" #: qcsrc/menu/xonotic/dialog_teamselect.qc:39 msgid "yellow" -msgstr "" +msgstr "צהוב" #: qcsrc/menu/xonotic/dialog_teamselect.qc:40 msgid "pink" -msgstr "" +msgstr "ורוד" #: qcsrc/menu/xonotic/dialog_teamselect.qc:43 msgid "spectate" -msgstr "" +msgstr "צפה" #: qcsrc/menu/xonotic/dialog_teamselect.qh:7 msgid "Team Selection" -msgstr "" +msgstr "בחירת צוות" #: qcsrc/menu/xonotic/dialog_uid2name.qc:10 msgid "Allow player statistics to use your nickname?" @@ -8667,7 +8668,7 @@ msgstr "" #: qcsrc/menu/xonotic/keybinder.qc:30 msgid "forward" -msgstr "" +msgstr "קדימה" #: qcsrc/menu/xonotic/keybinder.qc:31 msgid "backpedal" @@ -8739,7 +8740,7 @@ msgstr "" #: qcsrc/menu/xonotic/keybinder.qc:80 msgid "screen shot" -msgstr "" +msgstr "צילום מסך" #: qcsrc/menu/xonotic/keybinder.qc:81 msgid "maximize radar" @@ -8771,11 +8772,11 @@ msgstr "" #: qcsrc/menu/xonotic/keybinder.qc:89 msgid "vote YES" -msgstr "" +msgstr "הצבע כן" #: qcsrc/menu/xonotic/keybinder.qc:90 msgid "vote NO" -msgstr "" +msgstr "הצבע לא" #: qcsrc/menu/xonotic/keybinder.qc:93 msgid "Client" @@ -8787,11 +8788,11 @@ msgstr "" #: qcsrc/menu/xonotic/keybinder.qc:96 msgid "disconnect" -msgstr "" +msgstr "התנתק" #: qcsrc/menu/xonotic/keybinder.qc:97 msgid "quit" -msgstr "" +msgstr "צא" #: qcsrc/menu/xonotic/keybinder.qc:101 msgid "auto-join team" @@ -8865,7 +8866,7 @@ msgstr "" #: qcsrc/menu/xonotic/serverlist.qc:765 msgid "Map" -msgstr "" +msgstr "מפה" #: qcsrc/menu/xonotic/serverlist.qc:766 msgid "Type" @@ -9008,7 +9009,7 @@ msgstr "" #: qcsrc/menu/xonotic/slider_resolution.qc:115 msgid "Screen resolution" -msgstr "" +msgstr "רזולוציית מסך" #: qcsrc/menu/xonotic/slider_sbfadetime.qc:13 msgid "PART^Slow" @@ -9024,51 +9025,51 @@ msgstr "" #: qcsrc/menu/xonotic/statslist.qc:29 msgid "January" -msgstr "" +msgstr "ינואר" #: qcsrc/menu/xonotic/statslist.qc:30 msgid "February" -msgstr "" +msgstr "פברואר" #: qcsrc/menu/xonotic/statslist.qc:31 msgid "March" -msgstr "" +msgstr "מרץ" #: qcsrc/menu/xonotic/statslist.qc:32 msgid "April" -msgstr "" +msgstr "אפריל" #: qcsrc/menu/xonotic/statslist.qc:33 msgid "May" -msgstr "" +msgstr "מאי" #: qcsrc/menu/xonotic/statslist.qc:34 msgid "June" -msgstr "" +msgstr "יוני" #: qcsrc/menu/xonotic/statslist.qc:35 msgid "July" -msgstr "" +msgstr "יולי" #: qcsrc/menu/xonotic/statslist.qc:36 msgid "August" -msgstr "" +msgstr "אוגוסט" #: qcsrc/menu/xonotic/statslist.qc:37 msgid "September" -msgstr "" +msgstr "ספטמבר" #: qcsrc/menu/xonotic/statslist.qc:38 msgid "October" -msgstr "" +msgstr "אוקטובר" #: qcsrc/menu/xonotic/statslist.qc:39 msgid "November" -msgstr "" +msgstr "נובמבר" #: qcsrc/menu/xonotic/statslist.qc:40 msgid "December" -msgstr "" +msgstr "דצמבר" #: qcsrc/menu/xonotic/statslist.qc:96 msgid "Joined:" @@ -9145,7 +9146,7 @@ msgstr "" #: qcsrc/menu/xonotic/util.qc:780 msgid "Use default" -msgstr "" +msgstr "השתמש בברירת מחדל" #: qcsrc/menu/xonotic/util.qc:800 msgid "Team Color:" diff --git a/gfx/hud/default/as_defend.tga b/gfx/hud/default/as_defend.tga new file mode 100644 index 000000000..5aca85e59 Binary files /dev/null and b/gfx/hud/default/as_defend.tga differ diff --git a/gfx/hud/default/as_destroy.tga b/gfx/hud/default/as_destroy.tga new file mode 100644 index 000000000..7c779a1aa Binary files /dev/null and b/gfx/hud/default/as_destroy.tga differ diff --git a/gfx/hud/luma/as_defend.tga b/gfx/hud/luma/as_defend.tga new file mode 100644 index 000000000..5aca85e59 Binary files /dev/null and b/gfx/hud/luma/as_defend.tga differ diff --git a/gfx/hud/luma/as_destroy.tga b/gfx/hud/luma/as_destroy.tga new file mode 100644 index 000000000..7c779a1aa Binary files /dev/null and b/gfx/hud/luma/as_destroy.tga differ diff --git a/gfx/hud/luma/ok_weapon_rail.tga b/gfx/hud/luma/ok_weapon_rail.tga index e2e83ae75..b90d291fb 100644 Binary files a/gfx/hud/luma/ok_weapon_rail.tga and b/gfx/hud/luma/ok_weapon_rail.tga differ diff --git a/gfx/hud/luma/ok_weapon_shotgun.tga b/gfx/hud/luma/ok_weapon_shotgun.tga index f5fb92e13..b0e7bf932 100644 Binary files a/gfx/hud/luma/ok_weapon_shotgun.tga and b/gfx/hud/luma/ok_weapon_shotgun.tga differ diff --git a/gfx/hud/luma/ok_weapon_smg.tga b/gfx/hud/luma/ok_weapon_smg.tga index 5aee32ab5..cb26a1657 100644 Binary files a/gfx/hud/luma/ok_weapon_smg.tga and b/gfx/hud/luma/ok_weapon_smg.tga differ diff --git a/languages.txt b/languages.txt index 65ce90942..e16e0b878 100644 --- a/languages.txt +++ b/languages.txt @@ -1,25 +1,25 @@ -ko Korean "한국의" 33% -ast Asturian "Asturianu" 73% +ast "Asturian" "Asturianu" 73% +de "German" "Deutsch" 99% +de_CH "German (Switzerland)" "Deutsch (Schweiz)" 99% +en "English" "English" 100% +en_AU "English (Australia)" "English (Australia)" 86% +es "Spanish" "Español" 99% +fr "French" "Français" 99% +ga "Irish" "Irish" 35% +it "Italian" "Italiano" 99% +hu "Hungarian" "Magyar" 55% +nl "Dutch" "Nederlands" 70% +pl "Polish" "Polski" 81% +pt "Portuguese" "Português" 98% +pt_BR "Portuguese (Brazil)" "Português (Brasil)" 99% +ro "Romanian" "Romana" 83% +fi "Finnish" "Suomi" 33% +el "Greek" "Ελληνική" 33% +be "Belarusian" "Беларуская" 61% +bg "Bulgarian" "Български" 68% +ru "Russian" "Русский" 99% +sr "Serbian" "Српски" 71% +uk "Ukrainian" "Українська" 57% zh_CN "Chinese (China)" "中文" 62% -de German "Deutsch" -de_CH German "Deutsch (Schweiz)" -en English "English" -en_AU English "English (Australia)" 86% -es Spanish "Español" 99% -fr French "Français" -ga Irish "Irish" 35% -it Italian "Italiano" -hu Hungarian "Magyar" 55% -nl Dutch "Nederlands" 70% -pl Polish "Polski" 81% -pt Portuguese "Português" -pt_BR pt_BR "pt_BR" 99% -ro Romanian "Romana" 83% -fi Finnish "Suomi" 33% zh_TW "Chinese (Taiwan)" "國語" 68% -el Greek "Ελληνική" 33% -be Belarusian "Беларуская" 61% -bg Bulgarian "Български" 68% -ru Russian "Русский" -sr Serbian "Српски" 71% -uk Ukrainian "Українська" 57% +ko "Korean" "한국의" 33% diff --git a/qcsrc/client/commands/cl_cmd.qc b/qcsrc/client/commands/cl_cmd.qc index 1a6a9f884..c4b1ec041 100644 --- a/qcsrc/client/commands/cl_cmd.qc +++ b/qcsrc/client/commands/cl_cmd.qc @@ -43,7 +43,7 @@ void DrawDebugModel(entity this) void LocalCommand_blurtest(int request) { - TC(int, request); + TC(int, request); // Simple command to work with postprocessing temporarily... possibly completely pointless, the glsl shader is used for a real feature now... // Anyway, to enable it, just compile the client with -DBLURTEST and then you can use the command. @@ -79,7 +79,7 @@ void LocalCommand_blurtest(int request) void LocalCommand_boxparticles(int request, int argc) { - TC(int, request); TC(int, argc); + TC(int, request); TC(int, argc); switch (request) { case CMD_REQUEST_COMMAND: @@ -135,7 +135,7 @@ void LocalCommand_boxparticles(int request, int argc) void LocalCommand_create_scrshot_ent(int request) { - TC(int, request); + TC(int, request); switch (request) { case CMD_REQUEST_COMMAND: @@ -175,7 +175,7 @@ void LocalCommand_create_scrshot_ent(int request) void LocalCommand_debugmodel(int request, int argc) { - TC(int, request); TC(int, argc); + TC(int, request); TC(int, argc); switch (request) { case CMD_REQUEST_COMMAND: @@ -205,7 +205,7 @@ void LocalCommand_debugmodel(int request, int argc) void LocalCommand_handlevote(int request, int argc) { - TC(int, request); TC(int, argc); + TC(int, request); TC(int, argc); switch (request) { case CMD_REQUEST_COMMAND: @@ -255,7 +255,7 @@ void LocalCommand_handlevote(int request, int argc) void LocalCommand_hud(int request, int argc) { - TC(int, request); TC(int, argc); + TC(int, request); TC(int, argc); switch (request) { case CMD_REQUEST_COMMAND: @@ -351,7 +351,7 @@ void LocalCommand_hud(int request, int argc) void LocalCommand_localprint(int request, int argc) { - TC(int, request); TC(int, argc); + TC(int, request); TC(int, argc); switch (request) { case CMD_REQUEST_COMMAND: @@ -378,7 +378,7 @@ void LocalCommand_localprint(int request, int argc) void LocalCommand_mv_download(int request, int argc) { - TC(int, request); TC(int, argc); + TC(int, request); TC(int, argc); switch (request) { case CMD_REQUEST_COMMAND: @@ -405,7 +405,7 @@ void LocalCommand_mv_download(int request, int argc) void LocalCommand_sendcvar(int request, int argc) { - TC(int, request); TC(int, argc); + TC(int, request); TC(int, argc); switch (request) { case CMD_REQUEST_COMMAND: diff --git a/qcsrc/client/csqcmodel_hooks.qc b/qcsrc/client/csqcmodel_hooks.qc index d8f6d26a3..035ba2a16 100644 --- a/qcsrc/client/csqcmodel_hooks.qc +++ b/qcsrc/client/csqcmodel_hooks.qc @@ -362,7 +362,7 @@ void CSQCPlayer_AnimDecide_PostUpdate(entity this, bool isnew) } int CSQCPlayer_FallbackFrame(entity this, int f) { - TC(int, f); + TC(int, f); if(frameduration(this.modelindex, f) > 0) return f; // goooooood if(frameduration(this.modelindex, 1) <= 0) diff --git a/qcsrc/client/hud/hud.qc b/qcsrc/client/hud/hud.qc index 2b8eed95f..2becced8e 100644 --- a/qcsrc/client/hud/hud.qc +++ b/qcsrc/client/hud/hud.qc @@ -75,14 +75,14 @@ vector HUD_Get_Num_Color (float hp, float maxvalue) float HUD_GetRowCount(int item_count, vector size, float item_aspect) { - TC(int, item_count); + TC(int, item_count); float aspect = size_y / size_x; return bound(1, floor((sqrt(4 * item_aspect * aspect * item_count + aspect * aspect) + aspect + 0.5) / 2), item_count); } vector HUD_GetTableSize_BestItemAR(int item_count, vector psize, float item_aspect) { - TC(int, item_count); + TC(int, item_count); float columns, rows; float ratio, best_ratio = 0; float best_columns = 1, best_rows = 1; @@ -180,7 +180,7 @@ void HUD_Panel_LoadCvars() //basically the same code of draw_ButtonPicture and draw_VertButtonPicture for the menu void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, float length_ratio, bool vertical, float baralign, vector theColor, float theAlpha, int drawflag) { - TC(bool, vertical); TC(int, drawflag); + TC(bool, vertical); TC(int, drawflag); if(!length_ratio || !theAlpha) return; if(length_ratio > 1) @@ -287,7 +287,7 @@ void HUD_Panel_DrawProgressBar(vector theOrigin, vector theSize, string pic, flo void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theAlpha, int drawflag) { - TC(int, drawflag); + TC(int, drawflag); if(!theAlpha) return; @@ -308,7 +308,7 @@ void HUD_Panel_DrawHighlight(vector pos, vector mySize, vector color, float theA void DrawNumIcon_expanding(vector myPos, vector mySize, float theTime, string icon, bool vertical, int icon_right_align, vector color, float theAlpha, float fadelerp) { - TC(bool, vertical); TC(int, icon_right_align); + TC(bool, vertical); TC(int, icon_right_align); vector newPos = '0 0 0', newSize = '0 0 0'; vector picpos, numpos; @@ -388,7 +388,7 @@ void DrawNumIcon_expanding(vector myPos, vector mySize, float theTime, string ic void DrawNumIcon(vector myPos, vector mySize, float theTime, string icon, bool vertical, int icon_right_align, vector color, float theAlpha) { - TC(bool, vertical); TC(int, icon_right_align); + TC(bool, vertical); TC(int, icon_right_align); DrawNumIcon_expanding(myPos, mySize, theTime, icon, vertical, icon_right_align, color, theAlpha, 0); } diff --git a/qcsrc/client/hud/panel/ammo.qc b/qcsrc/client/hud/panel/ammo.qc index 01ce50cdb..ce700586c 100644 --- a/qcsrc/client/hud/panel/ammo.qc +++ b/qcsrc/client/hud/panel/ammo.qc @@ -22,7 +22,7 @@ void DrawNadeProgressBar(vector myPos, vector mySize, float progress, vector col void DrawAmmoItem(vector myPos, vector mySize, int ammoType, bool isCurrent, bool isInfinite) { - TC(bool, isCurrent); TC(bool, isInfinite); + TC(bool, isCurrent); TC(bool, isInfinite); if(ammoType == RESOURCE_NONE) return; diff --git a/qcsrc/client/hud/panel/centerprint.qc b/qcsrc/client/hud/panel/centerprint.qc index f8f70c818..90a496e0d 100644 --- a/qcsrc/client/hud/panel/centerprint.qc +++ b/qcsrc/client/hud/panel/centerprint.qc @@ -20,7 +20,7 @@ bool centerprint_showing; void centerprint_generic(int new_id, string strMessage, float duration, int countdown_num) { - TC(int, new_id); TC(int, countdown_num); + TC(int, new_id); TC(int, countdown_num); //printf("centerprint_generic(%d, '%s^7', %d, %d);\n", new_id, strMessage, duration, countdown_num); int i, j; @@ -94,7 +94,7 @@ void centerprint_generic(int new_id, string strMessage, float duration, int coun void centerprint_kill(int id) { - TC(int, id); + TC(int, id); centerprint_generic(id, "", 0, 0); } diff --git a/qcsrc/client/hud/panel/modicons.qc b/qcsrc/client/hud/panel/modicons.qc index 89b8a8c18..87e4a7fb2 100644 --- a/qcsrc/client/hud/panel/modicons.qc +++ b/qcsrc/client/hud/panel/modicons.qc @@ -13,7 +13,7 @@ bool mod_active; // is there any active mod icon? void DrawCAItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i) { - TC(int, layout); TC(int, i); + TC(int, layout); TC(int, i); int stat = -1; string pic = ""; vector color = '0 0 0'; @@ -626,7 +626,7 @@ void HUD_Mod_Race(vector pos, vector mySize) void DrawDomItem(vector myPos, vector mySize, float aspect_ratio, int layout, int i) { - TC(int, layout); TC(int, i); + TC(int, layout); TC(int, i); float stat = -1; string pic = ""; vector color = '0 0 0'; diff --git a/qcsrc/client/hud/panel/powerups.qc b/qcsrc/client/hud/panel/powerups.qc index dd574cf9b..947bfd53b 100644 --- a/qcsrc/client/hud/panel/powerups.qc +++ b/qcsrc/client/hud/panel/powerups.qc @@ -47,7 +47,7 @@ void addPowerupItem(string name, string icon, vector color, float currentTime, f int getPowerupItemAlign(int align, int column, int row, int columns, int rows, bool isVertical) { - TC(int, align); TC(int, column); TC(int, row); TC(int, columns); TC(int, rows); TC(bool, isVertical); + TC(int, align); TC(int, column); TC(int, row); TC(int, columns); TC(int, rows); TC(bool, isVertical); if(align < 2) return align; diff --git a/qcsrc/client/hud/panel/quickmenu.qc b/qcsrc/client/hud/panel/quickmenu.qc index 29f69b3d4..98b15ee95 100644 --- a/qcsrc/client/hud/panel/quickmenu.qc +++ b/qcsrc/client/hud/panel/quickmenu.qc @@ -43,7 +43,7 @@ float QuickMenu_TimeOut; // if s1 is not empty s will be displayed as command otherwise as submenu void QuickMenu_Page_LoadEntry(int i, string s, string s1) { - TC(int, i); + TC(int, i); //LOG_INFOF("^xc80 entry %d: %s, %s\n", i, s, s1); strcpy(QuickMenu_Page_Description[i], s); strcpy(QuickMenu_Page_Command[i], s1); @@ -51,7 +51,7 @@ void QuickMenu_Page_LoadEntry(int i, string s, string s1) void QuickMenu_Page_ClearEntry(int i) { - TC(int, i); + TC(int, i); strfree(QuickMenu_Page_Description[i]); strfree(QuickMenu_Page_Command[i]); QuickMenu_Page_Command_Type[i] = 0; @@ -225,7 +225,7 @@ bool QuickMenu_IsOpened() bool HUD_Quickmenu_PlayerListEntries_Create(string cmd, int teamplayers, bool without_me) { - TC(int, teamplayers); TC(bool, without_me); + TC(int, teamplayers); TC(bool, without_me); int i; for(i = 0; i < QUICKMENU_MAXLINES; ++i) QuickMenu_Page_ClearEntry(i); @@ -250,7 +250,7 @@ bool HUD_Quickmenu_PlayerListEntries_Create(string cmd, int teamplayers, bool wi int QuickMenu_Buffer_Index_Prev; bool QuickMenu_Page_Load(string target_submenu, bool new_page) { - TC(bool, new_page); + TC(bool, new_page); string s = string_null, cmd = string_null, z_submenu; if (new_page == 0) @@ -361,7 +361,7 @@ bool QuickMenu_Page_Load(string target_submenu, bool new_page) bool QuickMenu_ActionForNumber(int num) { - TC(int, num); + TC(int, num); if (!QuickMenu_IsLastPage) { if (num < 0 || num >= QUICKMENU_MAXLINES) @@ -389,7 +389,7 @@ bool QuickMenu_ActionForNumber(int num) void QuickMenu_Page_ActiveEntry(int entry_num) { - TC(int, entry_num); + TC(int, entry_num); QuickMenu_Page_ActivatedEntry = entry_num; QuickMenu_Page_ActivatedEntry_Time = time + 0.1; if(QuickMenu_Page_Command[QuickMenu_Page_ActivatedEntry]) @@ -407,7 +407,7 @@ void QuickMenu_Page_ActiveEntry(int entry_num) bool QuickMenu_InputEvent(int bInputType, float nPrimary, float nSecondary) { - TC(int, bInputType); + TC(int, bInputType); // we only care for keyboard events if(bInputType == 2) return false; @@ -748,7 +748,7 @@ void HUD_QuickMenu() void HUD_Quickmenu_PlayerListEntries(string cmd, int teamplayers, bool without_me) { - TC(int, teamplayers); TC(bool, without_me); + TC(int, teamplayers); TC(bool, without_me); entity pl; if(teamplayers && !team_count) return; diff --git a/qcsrc/client/hud/panel/radar.qc b/qcsrc/client/hud/panel/radar.qc index bd94520d4..65073d9fe 100644 --- a/qcsrc/client/hud/panel/radar.qc +++ b/qcsrc/client/hud/panel/radar.qc @@ -19,7 +19,7 @@ bool HUD_Radar_Clickable() void HUD_Radar_Show_Maximized(bool doshow, bool clickable) { - TC(bool, doshow); + TC(bool, doshow); hud_panel_radar_maximized = doshow; hud_panel_radar_temp_hidden = 0; @@ -56,7 +56,7 @@ void HUD_Radar_Hide_Maximized() float HUD_Radar_InputEvent(int bInputType, float nPrimary, float nSecondary) { - TC(int, bInputType); + TC(int, bInputType); if(!hud_panel_radar_maximized || !hud_panel_radar_mouse || autocvar__hud_configure || mv_active) return false; diff --git a/qcsrc/client/hud/panel/scoreboard.qc b/qcsrc/client/hud/panel/scoreboard.qc index 91d9f6f70..32ccccfca 100644 --- a/qcsrc/client/hud/panel/scoreboard.qc +++ b/qcsrc/client/hud/panel/scoreboard.qc @@ -175,7 +175,7 @@ void Scoreboard_UpdatePlayerTeams() int Scoreboard_CompareScore(int vl, int vr, int f) { - TC(int, vl); TC(int, vr); TC(int, f); + TC(int, vl); TC(int, vr); TC(int, f); if(f & SFL_ZERO_IS_WORST) { if(vl == 0 && vr != 0) @@ -381,7 +381,7 @@ void Cmd_Scoreboard_Help() void Cmd_Scoreboard_SetFields(int argc) { - TC(int, argc); + TC(int, argc); int i, slash; string str, pattern; bool have_name = false, have_primary = false, have_secondary = false, have_separator = false; @@ -716,7 +716,7 @@ float sbt_fixcolumnwidth_marginlen; string Scoreboard_FixColumnWidth(int i, string str) { - TC(int, i); + TC(int, i); float f; vector sz; @@ -840,7 +840,7 @@ vector Scoreboard_DrawHeader(vector pos, vector rgb, bool other_players) void Scoreboard_DrawItem(vector item_pos, vector rgb, entity pl, bool is_self, int pl_number) { - TC(bool, is_self); TC(int, pl_number); + TC(bool, is_self); TC(int, pl_number); string str; bool is_spec = (entcs_GetTeam(pl.sv_entnum) == NUM_SPECTATOR); diff --git a/qcsrc/client/hud/panel/weapons.qc b/qcsrc/client/hud/panel/weapons.qc index 5d75c7dd2..8bf11cf1a 100644 --- a/qcsrc/client/hud/panel/weapons.qc +++ b/qcsrc/client/hud/panel/weapons.qc @@ -11,7 +11,7 @@ entity weaponorder[Weapons_MAX]; void weaponorder_swap(int i, int j, entity pass) { - TC(int, i); TC(int, j); + TC(int, i); TC(int, j); entity h = weaponorder[i]; weaponorder[i] = weaponorder[j]; weaponorder[j] = h; @@ -20,7 +20,7 @@ void weaponorder_swap(int i, int j, entity pass) string weaponorder_cmp_str; int weaponorder_cmp(int i, int j, entity pass) { - TC(int, i); TC(int, j); + TC(int, i); TC(int, j); int ai = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[i].m_id), 0); int aj = strstrofs(weaponorder_cmp_str, sprintf(" %d ", weaponorder[j].m_id), 0); return aj - ai; // the string is in REVERSE order (higher prio at the right is what we want, but higher prio first is the string) diff --git a/qcsrc/client/main.qc b/qcsrc/client/main.qc index 218df18a4..863905a3d 100644 --- a/qcsrc/client/main.qc +++ b/qcsrc/client/main.qc @@ -230,7 +230,7 @@ void Shutdown() .float has_team; float SetTeam(entity o, int Team) { - TC(int, Team); + TC(int, Team); devassert_once(Team); entity tm; if(teamplay) diff --git a/qcsrc/client/mapvoting.qc b/qcsrc/client/mapvoting.qc index 8412bd757..03e94dc7f 100644 --- a/qcsrc/client/mapvoting.qc +++ b/qcsrc/client/mapvoting.qc @@ -43,7 +43,7 @@ int n_ssdirs; string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, vector fontsize) { - TC(int, id); + TC(int, id); string pre, post; pre = sprintf("%d. ", id+1); if(mv_detail) @@ -64,7 +64,7 @@ string MapVote_FormatMapItem(int id, string map, float _count, float maxwidth, v vector MapVote_RGB(int id) { - TC(int, id); + TC(int, id); if(!(mv_flags[id] & GTV_AVAILABLE)) return '1 1 1'; if(id == mv_ownvote) @@ -77,7 +77,7 @@ vector MapVote_RGB(int id) void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string gtype, string pic, float _count, int id) { - TC(int, id); + TC(int, id); // Find the correct alpha float alpha; if(!(mv_flags_start[id] & GTV_AVAILABLE)) @@ -189,7 +189,7 @@ void GameTypeVote_DrawGameTypeItem(vector pos, float maxh, float tsize, string g void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, string pic, float _count, int id) { - TC(int, id); + TC(int, id); vector img_size = '0 0 0'; string label; float text_size; @@ -264,7 +264,7 @@ void MapVote_DrawMapItem(vector pos, float isize, float tsize, string map, strin void MapVote_DrawAbstain(vector pos, float isize, float tsize, float _count, int id) { - TC(int, id); + TC(int, id); vector rgb; float text_size; string label; @@ -281,7 +281,7 @@ void MapVote_DrawAbstain(vector pos, float isize, float tsize, float _count, int vector MapVote_GridVec(vector gridspec, int i, int m) { - TC(int, i); TC(int, m); + TC(int, i); TC(int, m); int r = i % m; return '1 0 0' * (gridspec.x * r) @@ -491,7 +491,7 @@ void MapVote_Draw() void Cmd_MapVote_MapDownload(int argc) { - TC(int, argc); + TC(int, argc); entity pak; if(argc != 2 || !mv_pk3list) @@ -522,7 +522,7 @@ void Cmd_MapVote_MapDownload(int argc) void MapVote_CheckPK3(string pic, string pk3, int id) { - TC(int, id); + TC(int, id); entity pak; pak = spawn(); pak.netname = pk3; @@ -544,7 +544,7 @@ void MapVote_CheckPK3(string pic, string pk3, int id) void MapVote_CheckPic(string pic, string pk3, int id) { - TC(int, id); + TC(int, id); // never try to retrieve a pic for the "don't care" 'map' if(mv_abstain && id == mv_num_maps - 1) return; @@ -587,7 +587,7 @@ void MapVote_ReadMask() void MapVote_ReadOption(int i) { - TC(int, i); + TC(int, i); string map = strzone(ReadString()); string pk3 = strzone(ReadString()); int j = bound(0, ReadByte(), n_ssdirs - 1); @@ -604,7 +604,7 @@ void MapVote_ReadOption(int i) void GameTypeVote_ReadOption(int i) { - TC(int, i); + TC(int, i); string gt = strzone(ReadString()); mv_maps[i] = gt; @@ -711,13 +711,13 @@ void MapVote_Init() void MapVote_SendChoice(int index) { - TC(int, index); + TC(int, index); localcmd(strcat("\nimpulse ", ftos(index+1), "\n")); } int MapVote_MoveLeft(int pos) { - TC(int, pos); + TC(int, pos); int imp; if ( pos < 0 ) imp = mv_num_maps - 1; @@ -729,7 +729,7 @@ int MapVote_MoveLeft(int pos) } int MapVote_MoveRight(int pos) { - TC(int, pos); + TC(int, pos); int imp; if ( pos < 0 ) imp = 0; @@ -741,7 +741,7 @@ int MapVote_MoveRight(int pos) } int MapVote_MoveUp(int pos) { - TC(int, pos); + TC(int, pos); int imp; if ( pos < 0 ) imp = mv_num_maps - 1; @@ -761,7 +761,7 @@ int MapVote_MoveUp(int pos) } int MapVote_MoveDown(int pos) { - TC(int, pos); + TC(int, pos); int imp; if ( pos < 0 ) imp = 0; @@ -778,7 +778,7 @@ int MapVote_MoveDown(int pos) float MapVote_InputEvent(int bInputType, float nPrimary, float nSecondary) { - TC(int, bInputType); + TC(int, bInputType); float imp; if (!mv_active) diff --git a/qcsrc/client/miscfunctions.qc b/qcsrc/client/miscfunctions.qc index 01409280a..360305601 100644 --- a/qcsrc/client/miscfunctions.qc +++ b/qcsrc/client/miscfunctions.qc @@ -121,7 +121,7 @@ void RemoveTeam(entity Team) entity GetTeam(int Team, bool add) { - TC(int, Team); TC(bool, add); + TC(int, Team); TC(bool, add); int num = (Team == NUM_SPECTATOR) ? 16 : Team; if(teamslots[num]) return teamslots[num]; @@ -553,7 +553,7 @@ void DrawCircleClippedPic(vector centre, float radi, string pic, float f, vector /** engine callback */ void URI_Get_Callback(int id, int status, string data) { - TC(int, id); TC(int, status); + TC(int, id); TC(int, status); if(url_URI_Get_Callback(id, status, data)) { // handled diff --git a/qcsrc/client/player_skeleton.qc b/qcsrc/client/player_skeleton.qc index bb1b6f919..d9c9ab142 100644 --- a/qcsrc/client/player_skeleton.qc +++ b/qcsrc/client/player_skeleton.qc @@ -83,7 +83,7 @@ void skeleton_markbones(entity e) void skel_set_boneabs(float s, int bone, vector absorg) { - TC(int, bone); + TC(int, bone); vector absang = fixedvectoangles2(v_forward, v_up); vector parentorg = skel_get_boneabs(s, skel_get_boneparent(s, bone)); @@ -113,7 +113,7 @@ void free_skeleton_from_frames(entity e) void skeleton_from_frames(entity e, bool is_dead) { - TC(bool, is_dead); + TC(bool, is_dead); float m = e.modelindex; if(!e.skeletonindex) { diff --git a/qcsrc/client/teamradar.qc b/qcsrc/client/teamradar.qc index c5f1c2fb4..5d40dbe04 100644 --- a/qcsrc/client/teamradar.qc +++ b/qcsrc/client/teamradar.qc @@ -149,7 +149,7 @@ void draw_teamradar_icon(vector coord, entity icon, entity pingdata, vector rgb, void draw_teamradar_link(vector start, vector end, int colors) { - TC(int, colors); + TC(int, colors); vector c0, c1, norm; start = teamradar_texcoord_to_2dcoord(teamradar_3dcoord_to_texcoord(start)); diff --git a/qcsrc/client/view.qc b/qcsrc/client/view.qc index 253829947..a7fbe1368 100644 --- a/qcsrc/client/view.qc +++ b/qcsrc/client/view.qc @@ -1568,7 +1568,7 @@ int lasthud; float vh_notice_time; void CSQC_UpdateView(entity this, float w, float h) { - TC(int, w); TC(int, h); + TC(int, w); TC(int, h); entity e; float fov; float f; diff --git a/qcsrc/client/weapons/projectile.qc b/qcsrc/client/weapons/projectile.qc index 41b976944..f4871e7fc 100644 --- a/qcsrc/client/weapons/projectile.qc +++ b/qcsrc/client/weapons/projectile.qc @@ -171,7 +171,7 @@ void Projectile_Draw(entity this) void loopsound(entity e, int ch, Sound samp, float vol, float attn) { - TC(int, ch); + TC(int, ch); if (e.silent) return; diff --git a/qcsrc/common/command/command.qh b/qcsrc/common/command/command.qh index 349d492da..26308b89d 100644 --- a/qcsrc/common/command/command.qh +++ b/qcsrc/common/command/command.qh @@ -8,6 +8,6 @@ CLASS(Command, Object) ATTRIB(Command, m_description, string); METHOD(Command, m_invokecmd, void(Command this, int request, entity caller, int arguments, string command)) { - TC(Command, this); + TC(Command, this); } ENDCLASS(Command) diff --git a/qcsrc/common/effects/all.inc b/qcsrc/common/effects/all.inc index 6439a49bb..3b534ab78 100644 --- a/qcsrc/common/effects/all.inc +++ b/qcsrc/common/effects/all.inc @@ -258,6 +258,6 @@ entity EFFECT_ROCKETMINSTA_LASER(int teamid) case NUM_TEAM_4: e = EFFECT_ROCKETMINSTA_LASER_PINK; break; default: e = EFFECT_ROCKETMINSTA_LASER_NEUTRAL; break; } - if (particleeffectnum(e) < 0 || Team_TeamToNumber(teamid) == -1) { e = EFFECT_TR_NEXUIZPLASMA; } + if (particleeffectnum(e) < 0 || !Team_IsValidTeam(teamid)) { e = EFFECT_TR_NEXUIZPLASMA; } return e; } diff --git a/qcsrc/common/gamemodes/gamemode/assault/assault.qc b/qcsrc/common/gamemodes/gamemode/assault/assault.qc index 710f03095..bc048563e 100644 --- a/qcsrc/common/gamemodes/gamemode/assault/assault.qc +++ b/qcsrc/common/gamemodes/gamemode/assault/assault.qc @@ -606,10 +606,10 @@ MUTATOR_HOOKFUNCTION(as, PlayHitsound) return (frag_victim.classname == "func_assault_destructible"); } -MUTATOR_HOOKFUNCTION(as, CheckAllowedTeams) +MUTATOR_HOOKFUNCTION(as, TeamBalance_CheckAllowedTeams) { // assault always has 2 teams - c1 = c2 = 0; + M_ARGV(0, float) = BIT(0) | BIT(1); return true; } diff --git a/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qc b/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qc index f4aea4357..a81a23a51 100644 --- a/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qc +++ b/qcsrc/common/gamemodes/gamemode/clanarena/clanarena.qc @@ -7,53 +7,64 @@ bool autocvar_g_ca_spectate_enemies; void CA_count_alive_players() { - total_players = redalive = bluealive = yellowalive = pinkalive = 0; - FOREACH_CLIENT(IS_PLAYER(it), { - switch(it.team) + total_players = 0; + for (int i = 1; i <= NUM_TEAMS; ++i) + { + Team_SetNumberOfAlivePlayers(Team_GetTeamFromIndex(i), 0); + } + FOREACH_CLIENT(IS_PLAYER(it) && Entity_HasValidTeam(it), + { + ++total_players; + if (IS_DEAD(it)) { - case NUM_TEAM_1: ++total_players; if(!IS_DEAD(it)) ++redalive; break; - case NUM_TEAM_2: ++total_players; if(!IS_DEAD(it)) ++bluealive; break; - case NUM_TEAM_3: ++total_players; if(!IS_DEAD(it)) ++yellowalive; break; - case NUM_TEAM_4: ++total_players; if(!IS_DEAD(it)) ++pinkalive; break; + continue; } + entity team_ = Entity_GetTeam(it); + int num_alive = Team_GetNumberOfAlivePlayers(team_); + ++num_alive; + Team_SetNumberOfAlivePlayers(team_, num_alive); }); - FOREACH_CLIENT(IS_REAL_CLIENT(it), { - STAT(REDALIVE, it) = redalive; - STAT(BLUEALIVE, it) = bluealive; - STAT(YELLOWALIVE, it) = yellowalive; - STAT(PINKALIVE, it) = pinkalive; + FOREACH_CLIENT(IS_REAL_CLIENT(it), + { + STAT(REDALIVE, it) = Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex( + 1)); + STAT(BLUEALIVE, it) = Team_GetNumberOfAlivePlayers( + Team_GetTeamFromIndex(2)); + STAT(YELLOWALIVE, it) = Team_GetNumberOfAlivePlayers( + Team_GetTeamFromIndex(3)); + STAT(PINKALIVE, it) = Team_GetNumberOfAlivePlayers( + Team_GetTeamFromIndex(4)); }); } -float CA_GetWinnerTeam() +int CA_GetWinnerTeam() { - float winner_team = 0; - if(redalive >= 1) - winner_team = NUM_TEAM_1; - if(bluealive >= 1) + int winner_team = 0; + if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(1)) >= 1) { - if(winner_team) return 0; - winner_team = NUM_TEAM_2; + winner_team = NUM_TEAM_1; } - if(yellowalive >= 1) + for (int i = 2; i <= NUM_TEAMS; ++i) { - if(winner_team) return 0; - winner_team = NUM_TEAM_3; + if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) >= 1) + { + if (winner_team != 0) + { + return 0; + } + winner_team = Team_IndexToTeam(i); + } } - if(pinkalive >= 1) + if (winner_team) { - if(winner_team) return 0; - winner_team = NUM_TEAM_4; - } - if(winner_team) return winner_team; + } return -1; // no player left } void nades_Clear(entity player); -#define CA_ALIVE_TEAMS() ((redalive > 0) + (bluealive > 0) + (yellowalive > 0) + (pinkalive > 0)) -#define CA_ALIVE_TEAMS_OK() (CA_ALIVE_TEAMS() == NumTeams(ca_teams)) +#define CA_ALIVE_TEAMS_OK() (Team_GetNumberOfAliveTeams() == NumTeams(ca_teams)) float CA_CheckWinner() { if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0) @@ -69,8 +80,10 @@ float CA_CheckWinner() } CA_count_alive_players(); - if(CA_ALIVE_TEAMS() > 1) + if (Team_GetNumberOfAliveTeams() > 1) + { return 0; + } int winner_team = CA_GetWinnerTeam(); if(winner_team > 0) @@ -119,14 +132,14 @@ bool CA_CheckTeams() return false; } int missing_teams_mask = 0; - if(ca_teams & BIT(0)) - missing_teams_mask += (!redalive) * 1; - if(ca_teams & BIT(1)) - missing_teams_mask += (!bluealive) * 2; - if(ca_teams & BIT(2)) - missing_teams_mask += (!yellowalive) * 4; - if(ca_teams & BIT(3)) - missing_teams_mask += (!pinkalive) * 8; + for (int i = 1; i <= NUM_TEAMS; ++i) + { + if ((ca_teams & Team_IndexToBit(i)) && + (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) == 0)) + { + missing_teams_mask |= Team_IndexToBit(i); + } + } if(prev_missing_teams_mask != missing_teams_mask) { Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_MISSING_TEAMS, missing_teams_mask); @@ -232,9 +245,10 @@ MUTATOR_HOOKFUNCTION(ca, reset_map_global) return true; } -MUTATOR_HOOKFUNCTION(ca, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) +MUTATOR_HOOKFUNCTION(ca, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) { M_ARGV(0, float) = ca_teams; + return true; } entity ca_LastPlayerForTeam(entity this) diff --git a/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc b/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc index 855b04337..13d89c1be 100644 --- a/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc +++ b/qcsrc/common/gamemodes/gamemode/ctf/ctf.qc @@ -2503,11 +2503,9 @@ MUTATOR_HOOKFUNCTION(ctf, HavocBot_ChooseRole) return true; } -MUTATOR_HOOKFUNCTION(ctf, CheckAllowedTeams) +MUTATOR_HOOKFUNCTION(ctf, TeamBalance_CheckAllowedTeams) { - //M_ARGV(0, float) = ctf_teams; M_ARGV(1, string) = "ctf_team"; - return true; } MUTATOR_HOOKFUNCTION(ctf, SpectateCopy) @@ -2733,7 +2731,6 @@ spawnfunc(team_CTL_bluelolly) { spawnfunc_item_flag_team2(this); } // scoreboard setup void ctf_ScoreRules(int teams) { - CheckAllowedTeams(NULL); GameRules_scoring(teams, SFL_SORT_PRIO_PRIMARY, 0, { field_team(ST_CTF_CAPS, "caps", SFL_SORT_PRIO_PRIMARY); field(SP_CTF_CAPS, "caps", SFL_SORT_PRIO_SECONDARY); diff --git a/qcsrc/common/gamemodes/gamemode/domination/domination.qc b/qcsrc/common/gamemodes/gamemode/domination/domination.qc index e27a701c1..b8f08a5a1 100644 --- a/qcsrc/common/gamemodes/gamemode/domination/domination.qc +++ b/qcsrc/common/gamemodes/gamemode/domination/domination.qc @@ -297,47 +297,55 @@ void dom_controlpoint_setup(entity this) WaypointSprite_SpawnFixed(WP_DomNeut, this.origin + '0 0 32', this, sprite, RADARICON_DOMPOINT); } -float total_controlpoints; +int total_control_points; void Domination_count_controlpoints() { - total_controlpoints = redowned = blueowned = yellowowned = pinkowned = 0; + total_control_points = 0; + for (int i = 1; i <= NUM_TEAMS; ++i) + { + Team_SetNumberOfControlPoints(Team_GetTeamFromIndex(i), 0); + } IL_EACH(g_dompoints, true, { - ++total_controlpoints; - redowned += (it.goalentity.team == NUM_TEAM_1); - blueowned += (it.goalentity.team == NUM_TEAM_2); - yellowowned += (it.goalentity.team == NUM_TEAM_3); - pinkowned += (it.goalentity.team == NUM_TEAM_4); + ++total_control_points; + if (!Entity_HasValidTeam(it.goalentity)) + { + continue; + } + entity team_ = Entity_GetTeam(it.goalentity); + int num_control_points = Team_GetNumberOfControlPoints(team_); + ++num_control_points; + Team_SetNumberOfControlPoints(team_, num_control_points); }); } -float Domination_GetWinnerTeam() +int Domination_GetWinnerTeam() { - float winner_team = 0; - if(redowned == total_controlpoints) - winner_team = NUM_TEAM_1; - if(blueowned == total_controlpoints) + int winner_team = 0; + if (Team_GetNumberOfControlPoints(Team_GetTeamFromIndex(1)) == + total_control_points) { - if(winner_team) return 0; - winner_team = NUM_TEAM_2; + winner_team = NUM_TEAM_1; } - if(yellowowned == total_controlpoints) + for (int i = 2; i <= NUM_TEAMS; ++i) { - if(winner_team) return 0; - winner_team = NUM_TEAM_3; + if (Team_GetNumberOfControlPoints(Team_GetTeamFromIndex(i)) == + total_control_points) + { + if (winner_team != 0) + { + return 0; + } + winner_team = Team_IndexToTeam(i); + } } - if(pinkowned == total_controlpoints) + if (winner_team) { - if(winner_team) return 0; - winner_team = NUM_TEAM_4; - } - if(winner_team) return winner_team; + } return -1; // no control points left? } -#define DOM_OWNED_CONTROLPOINTS() ((redowned > 0) + (blueowned > 0) + (yellowowned > 0) + (pinkowned > 0)) -#define DOM_OWNED_CONTROLPOINTS_OK() (DOM_OWNED_CONTROLPOINTS() < total_controlpoints) float Domination_CheckWinner() { if(round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0) @@ -417,7 +425,7 @@ void havocbot_role_dom(entity this) } } -MUTATOR_HOOKFUNCTION(dom, CheckAllowedTeams) +MUTATOR_HOOKFUNCTION(dom, TeamBalance_CheckAllowedTeams) { // fallback? M_ARGV(0, float) = domination_teams; @@ -428,12 +436,9 @@ MUTATOR_HOOKFUNCTION(dom, CheckAllowedTeams) { if(head.netname != "") { - switch(head.team) + if (Team_IsValidTeam(head.team)) { - case NUM_TEAM_1: c1 = 0; break; - case NUM_TEAM_2: c2 = 0; break; - case NUM_TEAM_3: c3 = 0; break; - case NUM_TEAM_4: c4 = 0; break; + M_ARGV(0, float) |= Team_TeamToBit(head.team); } } @@ -584,10 +589,10 @@ void ScoreRules_dom(int teams) } // code from here on is just to support maps that don't have control point and team entities -void dom_spawnteam (string teamname, float teamcolor, string pointmodel, float pointskin, Sound capsound, string capnarration, string capmessage) +void dom_spawnteam(string teamname, float teamcolor, string pointmodel, float pointskin, Sound capsound, string capnarration, string capmessage) { - TC(Sound, capsound); - entity e = new_pure(dom_team); + TC(Sound, capsound); + entity e = new_pure(dom_team); e.netname = strzone(teamname); e.cnt = teamcolor; e.model = pointmodel; @@ -621,7 +626,7 @@ void dom_spawnpoint(vector org) // spawn some default teams if the map is not set up for domination void dom_spawnteams(int teams) { - TC(int, teams); + TC(int, teams); dom_spawnteam(Team_ColoredFullName(NUM_TEAM_1), NUM_TEAM_1-1, "models/domination/dom_red.md3", 0, SND_DOM_CLAIM, "", "Red team has captured a control point"); dom_spawnteam(Team_ColoredFullName(NUM_TEAM_2), NUM_TEAM_2-1, "models/domination/dom_blue.md3", 0, SND_DOM_CLAIM, "", "Blue team has captured a control point"); if(teams >= 3) @@ -644,14 +649,9 @@ void dom_DelayedInit(entity this) // Do this check with a delay so we can wait f dom_spawnteams(domination_teams); } - CheckAllowedTeams(NULL); - //domination_teams = ((c4>=0) ? 4 : (c3>=0) ? 3 : 2); - - int teams = 0; - if(c1 >= 0) teams |= BIT(0); - if(c2 >= 0) teams |= BIT(1); - if(c3 >= 0) teams |= BIT(2); - if(c4 >= 0) teams |= BIT(3); + entity balance = TeamBalance_CheckAllowedTeams(NULL); + int teams = TeamBalance_GetAllowedTeams(balance); + TeamBalance_Destroy(balance); domination_teams = teams; domination_roundbased = autocvar_g_domination_roundbased; diff --git a/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qc b/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qc index 4d9175574..6919518b8 100644 --- a/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qc +++ b/qcsrc/common/gamemodes/gamemode/freezetag/freezetag.qc @@ -2,6 +2,7 @@ // TODO: sv_freezetag #ifdef SVQC + #include float autocvar_g_freezetag_frozen_maxtime; @@ -13,27 +14,40 @@ float autocvar_g_freezetag_warmup; void freezetag_count_alive_players() { - total_players = redalive = bluealive = yellowalive = pinkalive = 0; - FOREACH_CLIENT(IS_PLAYER(it), { - switch(it.team) + total_players = 0; + for (int i = 1; i <= NUM_TEAMS; ++i) + { + Team_SetNumberOfAlivePlayers(Team_GetTeamFromIndex(i), 0); + } + FOREACH_CLIENT(IS_PLAYER(it) && Entity_HasValidTeam(it), + { + ++total_players; + if ((GetResourceAmount(it, RESOURCE_HEALTH) < 1) || + (STAT(FROZEN, it) == 1)) { - case NUM_TEAM_1: ++total_players; if(STAT(FROZEN, it) != 1 && GetResourceAmount(it, RESOURCE_HEALTH) >= 1) ++redalive; break; - case NUM_TEAM_2: ++total_players; if(STAT(FROZEN, it) != 1 && GetResourceAmount(it, RESOURCE_HEALTH) >= 1) ++bluealive; break; - case NUM_TEAM_3: ++total_players; if(STAT(FROZEN, it) != 1 && GetResourceAmount(it, RESOURCE_HEALTH) >= 1) ++yellowalive; break; - case NUM_TEAM_4: ++total_players; if(STAT(FROZEN, it) != 1 && GetResourceAmount(it, RESOURCE_HEALTH) >= 1) ++pinkalive; break; + continue; } + entity team_ = Entity_GetTeam(it); + int num_alive = Team_GetNumberOfAlivePlayers(team_); + ++num_alive; + Team_SetNumberOfAlivePlayers(team_, num_alive); }); - FOREACH_CLIENT(IS_REAL_CLIENT(it), { - STAT(REDALIVE, it) = redalive; - STAT(BLUEALIVE, it) = bluealive; - STAT(YELLOWALIVE, it) = yellowalive; - STAT(PINKALIVE, it) = pinkalive; + FOREACH_CLIENT(IS_REAL_CLIENT(it), + { + STAT(REDALIVE, it) = Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex( + 1)); + STAT(BLUEALIVE, it) = Team_GetNumberOfAlivePlayers( + Team_GetTeamFromIndex(2)); + STAT(YELLOWALIVE, it) = Team_GetNumberOfAlivePlayers( + Team_GetTeamFromIndex(3)); + STAT(PINKALIVE, it) = Team_GetNumberOfAlivePlayers( + Team_GetTeamFromIndex(4)); }); eliminatedPlayers.SendFlags |= 1; } -#define FREEZETAG_ALIVE_TEAMS() ((redalive > 0) + (bluealive > 0) + (yellowalive > 0) + (pinkalive > 0)) -#define FREEZETAG_ALIVE_TEAMS_OK() (FREEZETAG_ALIVE_TEAMS() == NumTeams(freezetag_teams)) + +#define FREEZETAG_ALIVE_TEAMS_OK() (Team_GetNumberOfAliveTeams() == NumTeams(freezetag_teams)) float freezetag_CheckTeams() { @@ -53,14 +67,14 @@ float freezetag_CheckTeams() return 0; } int missing_teams_mask = 0; - if(freezetag_teams & BIT(0)) - missing_teams_mask += (!redalive) * 1; - if(freezetag_teams & BIT(1)) - missing_teams_mask += (!bluealive) * 2; - if(freezetag_teams & BIT(2)) - missing_teams_mask += (!yellowalive) * 4; - if(freezetag_teams & BIT(3)) - missing_teams_mask += (!pinkalive) * 8; + for (int i = 1; i <= NUM_TEAMS; ++i) + { + if ((freezetag_teams & Team_IndexToBit(i)) && + (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) == 0)) + { + missing_teams_mask |= Team_IndexToBit(i); + } + } if(prev_missing_teams_mask != missing_teams_mask) { Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_MISSING_TEAMS, missing_teams_mask); @@ -69,28 +83,28 @@ float freezetag_CheckTeams() return 0; } -float freezetag_getWinnerTeam() +int freezetag_getWinnerTeam() { - float winner_team = 0; - if(redalive >= 1) - winner_team = NUM_TEAM_1; - if(bluealive >= 1) + int winner_team = 0; + if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(1)) >= 1) { - if(winner_team) return 0; - winner_team = NUM_TEAM_2; + winner_team = NUM_TEAM_1; } - if(yellowalive >= 1) + for (int i = 2; i <= NUM_TEAMS; ++i) { - if(winner_team) return 0; - winner_team = NUM_TEAM_3; + if (Team_GetNumberOfAlivePlayers(Team_GetTeamFromIndex(i)) >= 1) + { + if (winner_team != 0) + { + return 0; + } + winner_team = Team_IndexToTeam(i); + } } - if(pinkalive >= 1) + if (winner_team) { - if(winner_team) return 0; - winner_team = NUM_TEAM_4; - } - if(winner_team) return winner_team; + } return -1; // no player left } @@ -112,8 +126,10 @@ float freezetag_CheckWinner() return 1; } - if(FREEZETAG_ALIVE_TEAMS() > 1) + if (Team_GetNumberOfAliveTeams() > 1) + { return 0; + } int winner_team = freezetag_getWinnerTeam(); if(winner_team > 0) @@ -559,9 +575,10 @@ MUTATOR_HOOKFUNCTION(ft, HavocBot_ChooseRole) return true; } -MUTATOR_HOOKFUNCTION(ft, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) +MUTATOR_HOOKFUNCTION(ft, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) { M_ARGV(0, float) = freezetag_teams; + return true; } MUTATOR_HOOKFUNCTION(ft, SetWeaponArena) diff --git a/qcsrc/common/gamemodes/gamemode/invasion/invasion.qc b/qcsrc/common/gamemodes/gamemode/invasion/invasion.qc index 3dff70195..00e2241c6 100644 --- a/qcsrc/common/gamemodes/gamemode/invasion/invasion.qc +++ b/qcsrc/common/gamemodes/gamemode/invasion/invasion.qc @@ -548,9 +548,10 @@ MUTATOR_HOOKFUNCTION(inv, CheckRules_World) return true; } -MUTATOR_HOOKFUNCTION(inv, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) +MUTATOR_HOOKFUNCTION(inv, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) { M_ARGV(0, float) = invasion_teams; + return true; } MUTATOR_HOOKFUNCTION(inv, AllowMobButcher) @@ -561,7 +562,6 @@ MUTATOR_HOOKFUNCTION(inv, AllowMobButcher) void invasion_ScoreRules(int inv_teams) { - if(inv_teams) { CheckAllowedTeams(NULL); } GameRules_score_enabled(false); GameRules_scoring(inv_teams, 0, 0, { if (inv_teams) { diff --git a/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qc b/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qc index 00eb886d5..5af4c45b7 100644 --- a/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qc +++ b/qcsrc/common/gamemodes/gamemode/keyhunt/keyhunt.qc @@ -1264,9 +1264,10 @@ MUTATOR_HOOKFUNCTION(kh, MatchEnd) kh_finalize(); } -MUTATOR_HOOKFUNCTION(kh, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) +MUTATOR_HOOKFUNCTION(kh, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) { M_ARGV(0, float) = kh_teams; + return true; } MUTATOR_HOOKFUNCTION(kh, SpectateCopy) diff --git a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc index 487012aa5..89c53a82a 100644 --- a/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc +++ b/qcsrc/common/gamemodes/gamemode/nexball/nexball.qc @@ -635,7 +635,7 @@ void SpawnGoal(entity this) EXACTTRIGGER_INIT; - if(this.team != GOAL_OUT && Team_TeamToNumber(this.team) != -1) + if(this.team != GOAL_OUT && Team_IsValidTeam(this.team)) { entity wp = WaypointSprite_SpawnFixed(WP_NbGoal, (this.absmin + this.absmax) * 0.5, this, sprite, RADARICON_NONE); wp.colormod = ((this.team) ? Team_ColorRGB(this.team) : '1 0.5 0'); @@ -920,7 +920,7 @@ MUTATOR_HOOKFUNCTION(nb, ItemTouch) return MUT_ITEMTOUCH_CONTINUE; } -MUTATOR_HOOKFUNCTION(nb, CheckAllowedTeams) +MUTATOR_HOOKFUNCTION(nb, TeamBalance_CheckAllowedTeams) { M_ARGV(1, string) = "nexball_team"; return true; diff --git a/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc b/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc index 9b175f179..6d719eb97 100644 --- a/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc +++ b/qcsrc/common/gamemodes/gamemode/onslaught/sv_onslaught.qc @@ -1113,46 +1113,52 @@ int total_generators; void Onslaught_count_generators() { entity e; - total_generators = redowned = blueowned = yellowowned = pinkowned = 0; + total_generators = 0; + for (int i = 1; i <= NUM_TEAMS; ++i) + { + Team_SetNumberOfControlPoints(Team_GetTeamFromIndex(i), 0); + } for(e = ons_worldgeneratorlist; e; e = e.ons_worldgeneratornext) { ++total_generators; - redowned += (e.team == NUM_TEAM_1 && GetResourceAmount(e, RESOURCE_HEALTH) > 0); - blueowned += (e.team == NUM_TEAM_2 && GetResourceAmount(e, RESOURCE_HEALTH) > 0); - yellowowned += (e.team == NUM_TEAM_3 && GetResourceAmount(e, RESOURCE_HEALTH) > 0); - pinkowned += (e.team == NUM_TEAM_4 && GetResourceAmount(e, RESOURCE_HEALTH) > 0); + if (GetResourceAmount(e, RESOURCE_HEALTH) < 1) + { + continue; + } + entity team_ = Entity_GetTeam(e); + int num_control_points = Team_GetNumberOfControlPoints(team_); + ++num_control_points; + Team_SetNumberOfControlPoints(team_, num_control_points); } } int Onslaught_GetWinnerTeam() { int winner_team = 0; - if(redowned > 0) - winner_team = NUM_TEAM_1; - if(blueowned > 0) + if (Team_GetNumberOfControlPoints(Team_GetTeamFromIndex(1)) >= 1) { - if(winner_team) return 0; - winner_team = NUM_TEAM_2; + winner_team = NUM_TEAM_1; } - if(yellowowned > 0) + for (int i = 2; i <= NUM_TEAMS; ++i) { - if(winner_team) return 0; - winner_team = NUM_TEAM_3; + if (Team_GetNumberOfControlPoints(Team_GetTeamFromIndex(i)) >= 1) + { + if (winner_team != 0) + { + return 0; + } + winner_team = Team_IndexToTeam(i); + } } - if(pinkowned > 0) + if (winner_team) { - if(winner_team) return 0; - winner_team = NUM_TEAM_4; - } - if(winner_team) return winner_team; + } return -1; // no generators left? } void nades_Clear(entity e); -#define ONS_OWNED_GENERATORS() ((redowned > 0) + (blueowned > 0) + (yellowowned > 0) + (pinkowned > 0)) -#define ONS_OWNED_GENERATORS_OK() (ONS_OWNED_GENERATORS() > 1) bool Onslaught_CheckWinner() { if ((autocvar_timelimit && time > game_starttime + autocvar_timelimit * 60) || (round_handler_GetEndTime() > 0 && round_handler_GetEndTime() - time <= 0)) @@ -1198,8 +1204,10 @@ bool Onslaught_CheckWinner() Onslaught_count_generators(); - if(ONS_OWNED_GENERATORS_OK()) + if (Team_GetNumberOfTeamsWithControlPoints() > 1) + { return 0; + } int winner_team = Onslaught_GetWinnerTeam(); @@ -1897,17 +1905,14 @@ MUTATOR_HOOKFUNCTION(ons, HavocBot_ChooseRole) return true; } -MUTATOR_HOOKFUNCTION(ons, CheckAllowedTeams) +MUTATOR_HOOKFUNCTION(ons, TeamBalance_CheckAllowedTeams) { // onslaught is special for(entity tmp_entity = ons_worldgeneratorlist; tmp_entity; tmp_entity = tmp_entity.ons_worldgeneratornext) { - switch(tmp_entity.team) + if (Team_IsValidTeam(tmp_entity.team)) { - case NUM_TEAM_1: c1 = 0; break; - case NUM_TEAM_2: c2 = 0; break; - case NUM_TEAM_3: c3 = 0; break; - case NUM_TEAM_4: c4 = 0; break; + M_ARGV(0, float) |= Team_TeamToBit(tmp_entity.team); } } @@ -2137,12 +2142,9 @@ spawnfunc(onslaught_generator) // scoreboard setup void ons_ScoreRules() { - CheckAllowedTeams(NULL); - int teams = 0; - if(c1 >= 0) teams |= BIT(0); - if(c2 >= 0) teams |= BIT(1); - if(c3 >= 0) teams |= BIT(2); - if(c4 >= 0) teams |= BIT(3); + entity balance = TeamBalance_CheckAllowedTeams(NULL); + int teams = TeamBalance_GetAllowedTeams(balance); + TeamBalance_Destroy(balance); GameRules_scoring(teams, SFL_SORT_PRIO_PRIMARY, 0, { field_team(ST_ONS_CAPS, "destroyed", SFL_SORT_PRIO_PRIMARY); field(SP_ONS_CAPS, "caps", SFL_SORT_PRIO_SECONDARY); diff --git a/qcsrc/common/gamemodes/gamemode/race/race.qc b/qcsrc/common/gamemodes/gamemode/race/race.qc index c98e1b6a8..aaf83cb39 100644 --- a/qcsrc/common/gamemodes/gamemode/race/race.qc +++ b/qcsrc/common/gamemodes/gamemode/race/race.qc @@ -366,9 +366,10 @@ MUTATOR_HOOKFUNCTION(rc, ForbidPlayerScore_Clear) return true; // in qualifying, you don't lose score by observing } -MUTATOR_HOOKFUNCTION(rc, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) +MUTATOR_HOOKFUNCTION(rc, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) { M_ARGV(0, float) = race_teams; + return true; } MUTATOR_HOOKFUNCTION(rc, Scores_CountFragsRemaining) diff --git a/qcsrc/common/gamemodes/gamemode/tdm/tdm.qc b/qcsrc/common/gamemodes/gamemode/tdm/tdm.qc index 39e5fec1e..cf328902b 100644 --- a/qcsrc/common/gamemodes/gamemode/tdm/tdm.qc +++ b/qcsrc/common/gamemodes/gamemode/tdm/tdm.qc @@ -53,10 +53,9 @@ void tdm_DelayedInit(entity this) } } -MUTATOR_HOOKFUNCTION(tdm, CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) +MUTATOR_HOOKFUNCTION(tdm, TeamBalance_CheckAllowedTeams, CBC_ORDER_EXCLUSIVE) { M_ARGV(1, string) = "tdm_team"; - return true; } MUTATOR_HOOKFUNCTION(tdm, Scores_CountFragsRemaining) diff --git a/qcsrc/common/gamemodes/sv_rules.qh b/qcsrc/common/gamemodes/sv_rules.qh index 979477cba..ca1b6f8e7 100644 --- a/qcsrc/common/gamemodes/sv_rules.qh +++ b/qcsrc/common/gamemodes/sv_rules.qh @@ -2,7 +2,6 @@ // TODO: find a better location for these? float total_players; -float redalive, bluealive, yellowalive, pinkalive; // todo: accept the number of teams as a parameter void GameRules_teams(bool value); diff --git a/qcsrc/common/mutators/mutator/overkill/okrpc.qc b/qcsrc/common/mutators/mutator/overkill/okrpc.qc index 37d82e22e..3174fa7ff 100644 --- a/qcsrc/common/mutators/mutator/overkill/okrpc.qc +++ b/qcsrc/common/mutators/mutator/overkill/okrpc.qc @@ -2,12 +2,20 @@ #ifdef SVQC +.float m_chainsaw_damage; // accumulated damage of the missile as it passes trough enemies + void W_OverkillRocketPropelledChainsaw_Explode(entity this, entity directhitentity) { this.event_damage = func_null; this.takedamage = DAMAGE_NO; - RadiusDamage(this, this.realowner, WEP_CVAR_PRI(okrpc, damage), WEP_CVAR_PRI(okrpc, edgedamage), WEP_CVAR_PRI(okrpc, radius), NULL, NULL, WEP_CVAR_PRI(okrpc, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity); + float explosion_damage = RadiusDamage(this, this.realowner, WEP_CVAR_PRI(okrpc, damage), WEP_CVAR_PRI(okrpc, edgedamage), WEP_CVAR_PRI(okrpc, radius), NULL, NULL, WEP_CVAR_PRI(okrpc, force), this.projectiledeathtype, this.weaponentity_fld, directhitentity); + if (explosion_damage > 0 && this.m_chainsaw_damage > 0) + { + // if chainsaw hit something, it removed fired damage (so that direct hit is 100%) + // now that we also damaged something by explosion we'd go over 100% so let's add the fired damage back + accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype).m_id, WEP_CVAR(okrpc, damage), 0); + } delete(this); } @@ -53,8 +61,22 @@ void W_OverkillRocketPropelledChainsaw_Think(entity this) vector mydir = normalize(this.velocity); tracebox(this.origin, this.mins, this.maxs, this.origin + mydir * (2 * myspeed_accel), MOVE_NORMAL, this); - if(IS_PLAYER(trace_ent)) + if (IS_PLAYER(trace_ent)) + { + if (accuracy_isgooddamage(this.realowner, trace_ent)) + { + if (this.m_chainsaw_damage == 0) // first hit + { + // The fired damage of the explosion is already counted in the statistics (when launching the chainsaw). + // We remove it here so that a direct hit that passes through and doesn't damage anything by the explosion later is still 100%. + float fired_damage = WEP_CVAR_PRI(okrpc, damage2) - WEP_CVAR_PRI(okrpc, damage); + float hit_damage = WEP_CVAR_PRI(okrpc, damage2); + accuracy_add(this.realowner, DEATH_WEAPONOF(this.projectiledeathtype).m_id, fired_damage, hit_damage); + } + this.m_chainsaw_damage += WEP_CVAR_PRI(okrpc, damage2); + } Damage(trace_ent, this, this.realowner, WEP_CVAR_PRI(okrpc, damage2), this.projectiledeathtype, this.weaponentity_fld, this.origin, normalize(this.origin - trace_ent.origin) * WEP_CVAR_PRI(okrpc, force)); + } this.velocity = mydir * (myspeed + (WEP_CVAR_PRI(okrpc, speedaccel) * sys_frametime)); @@ -106,6 +128,7 @@ void W_OverkillRocketPropelledChainsaw_Attack (Weapon thiswep, entity actor, .en SUB_SetFade (flash, time, 0.1); flash.effects = EF_ADDITIVE | EF_FULLBRIGHT | EF_LOWPRECISION; W_AttachToShotorg(actor, weaponentity, flash, '5 0 0'); + missile.m_chainsaw_damage = 0; MUTATOR_CALLHOOK(EditProjectile, actor, missile); } diff --git a/qcsrc/common/sounds/sound.qh b/qcsrc/common/sounds/sound.qh index d46ac9eaf..49cfb4488 100644 --- a/qcsrc/common/sounds/sound.qh +++ b/qcsrc/common/sounds/sound.qh @@ -128,7 +128,7 @@ CLASS(Sound, Object) } METHOD(Sound, sound_precache, void(Sound this)) { - TC(Sound, this); + TC(Sound, this); string s = _Sound_fixpath(this.sound_str()); if (!s) return; profile(sprintf("precache_sound(\"%s\")", s)); diff --git a/qcsrc/common/t_items.qc b/qcsrc/common/t_items.qc index 140b619c5..28ea1add9 100644 --- a/qcsrc/common/t_items.qc +++ b/qcsrc/common/t_items.qc @@ -613,14 +613,18 @@ float adjust_respawntime(float normal_respawntime) { return normal_respawntime; } - CheckAllowedTeams(NULL); - GetTeamCounts(NULL); + entity balance = TeamBalance_CheckAllowedTeams(NULL); + TeamBalance_GetTeamCounts(balance, NULL); int players = 0; - if (c1 != -1) players += c1; - if (c2 != -1) players += c2; - if (c3 != -1) players += c3; - if (c4 != -1) players += c4; - + for (int i = 1; i <= NUM_TEAMS; ++i) + { + if (TeamBalance_IsTeamAllowed(balance, i)) + { + players += TeamBalance_GetNumberOfPlayers(balance, i); + } + } + TeamBalance_Destroy(balance); + if (players >= 2) { return normal_respawntime * (r / (players + o) + l); } else { diff --git a/qcsrc/common/teams.qh b/qcsrc/common/teams.qh index 57d644c04..1a2e1b176 100644 --- a/qcsrc/common/teams.qh +++ b/qcsrc/common/teams.qh @@ -1,5 +1,7 @@ #pragma once +const int NUM_TEAMS = 4; ///< Number of teams in the game. + #ifdef TEAMNUMBERS_THAT_ARENT_STUPID const int NUM_TEAM_1 = 1; // red const int NUM_TEAM_2 = 2; // blue @@ -125,12 +127,12 @@ float Team_ColorToTeam(string team_color) return -1; } -/// \brief Returns whether team is valid. -/// \param[in] team_ Team to check. +/// \brief Returns whether team value is valid. +/// \param[in] team_num Team to check. /// \return True if team is valid, false otherwise. -bool Team_IsValidTeam(int team_) +bool Team_IsValidTeam(int team_num) { - switch (team_) + switch (team_num) { case NUM_TEAM_1: case NUM_TEAM_2: @@ -143,12 +145,12 @@ bool Team_IsValidTeam(int team_) return false; } -/// \brief Returns whether team number is valid. -/// \param[in] number Team number to check. -/// \return True if team number is valid, false otherwise. -bool Team_IsValidNumber(int number) +/// \brief Returns whether the team index is valid. +/// \param[in] index Team index to check. +/// \return True if team index is valid, false otherwise. +bool Team_IsValidIndex(int index) { - switch (number) + switch (index) { case 1: case 2: @@ -161,36 +163,60 @@ bool Team_IsValidNumber(int number) return false; } -float Team_NumberToTeam(float number) +/// \brief Converts team index into team value. +/// \param[in] index Team index to convert. +/// \return Team value. +int Team_IndexToTeam(int index) { - switch(number) + switch (index) { case 1: return NUM_TEAM_1; case 2: return NUM_TEAM_2; case 3: return NUM_TEAM_3; case 4: return NUM_TEAM_4; } - return -1; } -float Team_TeamToNumber(float teamid) +/// \brief Converts team value into team index. +/// \param[in] team_num Team value to convert. +/// \return Team index. +int Team_TeamToIndex(int team_num) { - switch(teamid) + switch (team_num) { case NUM_TEAM_1: return 1; case NUM_TEAM_2: return 2; case NUM_TEAM_3: return 3; case NUM_TEAM_4: return 4; } - return -1; } +/// \brief Converts team value into bit value that is used in team bitmasks. +/// \param[in] team_num Team value to convert. +/// \return Team bit. +int Team_TeamToBit(int team_num) +{ + if (!Team_IsValidTeam(team_num)) + { + return 0; + } + return BIT(Team_TeamToIndex(team_num) - 1); +} + +/// \brief Converts team index into bit value that is used in team bitmasks. +/// \param[in] index Team index to convert. +/// \return Team bit. +int Team_IndexToBit(int index) +{ + return BIT(index - 1); +} + // legacy aliases for shitty code -#define TeamByColor(teamid) (Team_TeamToNumber(teamid) - 1) -#define ColorByTeam(number) Team_NumberToTeam(number + 1) +#define TeamByColor(teamid) (Team_TeamToIndex(teamid) - 1) +#define ColorByTeam(number) Team_IndexToTeam(number + 1) // useful aliases #define Team_ColorName_Lower(teamid) strtolower(Team_ColorName(teamid)) @@ -203,8 +229,8 @@ float Team_TeamToNumber(float teamid) #define Team_FullName(teamid) strcat(Team_ColorName(teamid), " ", NAME_TEAM, "^7") #define Team_ColoredFullName(teamid) strcat(Team_ColorCode(teamid), Team_ColorName(teamid), " ", NAME_TEAM, "^7") -#define Team_NumberToFullName(number) Team_FullName(Team_NumberToTeam(number)) -#define Team_NumberToColoredFullName(number) Team_ColoredFullName(Team_NumberToTeam(number)) +#define Team_IndexToFullName(index) Team_FullName(Team_IndexToTeam(index)) +#define Team_IndexToColoredFullName(index) Team_ColoredFullName(Team_IndexToTeam(index)) // replace these flags in a string with the strings provided #define TCR(input,type,team) strreplace("^TC", COL_TEAM_##team, strreplace("^TT", strtoupper(type##_TEAM_##team), input)) diff --git a/qcsrc/common/turrets/sv_turrets.qc b/qcsrc/common/turrets/sv_turrets.qc index b68aca16f..95ee41981 100644 --- a/qcsrc/common/turrets/sv_turrets.qc +++ b/qcsrc/common/turrets/sv_turrets.qc @@ -474,7 +474,7 @@ void turret_projectile_damage(entity this, entity inflictor, entity attacker, fl entity turret_projectile(entity actor, Sound _snd, float _size, float _health, float _death, float _proj_type, float _cull, float _cli_anim) { - TC(Sound, _snd); + TC(Sound, _snd); entity proj; sound (actor, CH_WEAPON_A, _snd, VOL_BASE, ATTEN_NORM); diff --git a/qcsrc/common/vehicles/cl_vehicles.qc b/qcsrc/common/vehicles/cl_vehicles.qc index 51ac4bee4..06c8484ff 100644 --- a/qcsrc/common/vehicles/cl_vehicles.qc +++ b/qcsrc/common/vehicles/cl_vehicles.qc @@ -21,7 +21,7 @@ float alarm2time; void vehicle_alarm(entity e, int ch, Sound s0und) { - TC(Sound, s0und); + TC(Sound, s0und); if(!autocvar_cl_vehicles_alarm) return; diff --git a/qcsrc/common/vehicles/sv_vehicles.qc b/qcsrc/common/vehicles/sv_vehicles.qc index 214109c97..716dfe8d0 100644 --- a/qcsrc/common/vehicles/sv_vehicles.qc +++ b/qcsrc/common/vehicles/sv_vehicles.qc @@ -251,7 +251,7 @@ entity vehicles_projectile(entity this, string _mzlfx, Sound _mzlsound, int _deahtype, float _projtype, float _health, bool _cull, bool _clianim, entity _owner) { - TC(Sound, _mzlsound); + TC(Sound, _mzlsound); entity proj; proj = spawn(); diff --git a/qcsrc/lib/i18n.qh b/qcsrc/lib/i18n.qh index 3dfac6224..841486f58 100644 --- a/qcsrc/lib/i18n.qh +++ b/qcsrc/lib/i18n.qh @@ -45,14 +45,14 @@ ERASEABLE string CTX(string s) { #if CTX_CACHE - string c = HM_gets(CTX_cache, s); - if (c != "") return c; + string c = HM_gets(CTX_cache, s); + if (c != "") return c; #endif int p = strstrofs(s, "^", 0); string ret = (p < 0) ? s : substring(s, p + 1, -1); #if CTX_CACHE - LOG_DEBUGF("CTX(\"%s\")", s); - HM_sets(CTX_cache, s, ret); + LOG_DEBUGF("CTX(\"%s\")", s); + HM_sets(CTX_cache, s, ret); #endif return ret; } diff --git a/qcsrc/lib/oo.qh b/qcsrc/lib/oo.qh index b22ff7915..e482d7d9a 100644 --- a/qcsrc/lib/oo.qh +++ b/qcsrc/lib/oo.qh @@ -326,7 +326,7 @@ CLASS(Object) #define remove(this) delete(this) METHOD(Object, describe, string(Object this)) { - TC(Object, this); + TC(Object, this); string s = _("No description"); if (cvar("developer")) { @@ -340,7 +340,7 @@ CLASS(Object) } METHOD(Object, display, void(Object this, void(string name, string icon) returns)) { - TC(Object, this); + TC(Object, this); returns(sprintf("entity %i", this), "nopreview_map"); } ENDCLASS(Object) diff --git a/qcsrc/server/bot/default/bot.qc b/qcsrc/server/bot/default/bot.qc index b3a143b9a..f03bdfc74 100644 --- a/qcsrc/server/bot/default/bot.qc +++ b/qcsrc/server/bot/default/bot.qc @@ -434,15 +434,15 @@ void bot_clientconnect(entity this) else if(this.bot_forced_team==4) this.team = NUM_TEAM_4; else - JoinBestTeam(this, true); + TeamBalance_JoinBestTeam(this, true); 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; @@ -461,12 +461,10 @@ void bot_removefromlargestteam() int thiscount = 0; - switch(it.team) + if (Team_IsValidTeam(it.team)) { - case NUM_TEAM_1: thiscount = c1; break; - case NUM_TEAM_2: thiscount = c2; break; - case NUM_TEAM_3: thiscount = c3; break; - case NUM_TEAM_4: thiscount = c4; break; + thiscount = TeamBalance_GetNumberOfPlayers(balance, + Team_TeamToIndex(it.team)); } if(thiscount > bestcount) @@ -481,6 +479,7 @@ void bot_removefromlargestteam() best = it; } }); + TeamBalance_Destroy(balance); if(!bcount) return; // no bots to remove currentbots = currentbots - 1; diff --git a/qcsrc/server/client.qc b/qcsrc/server/client.qc index 9214900f3..53a203eb9 100644 --- a/qcsrc/server/client.qc +++ b/qcsrc/server/client.qc @@ -287,10 +287,8 @@ void PutObserverInServer(entity this) if (mutator_returnvalue) { // mutator prevents resetting teams+score } else { - int oldteam = this.team; - this.team = -1; // move this as it is needed to log the player spectating in eventlog - MUTATOR_CALLHOOK(Player_ChangedTeam, this, oldteam, this.team); - this.frags = FRAGS_SPECTATOR; + Player_SetTeamIndex(this, -1); + this.frags = FRAGS_SPECTATOR; PlayerScore_Clear(this); // clear scores when needed } @@ -302,7 +300,7 @@ void PutObserverInServer(entity this) Send_Notification(NOTIF_ONE_ONLY, this, MSG_INFO, INFO_CHAT_NOSPECTATORS); if(!CS(this).just_joined) - LogTeamchange(this.playerid, -1, 4); + LogTeamchange(this.playerid, -1, TEAM_CHANGE_SPECTATOR); else CS(this).just_joined = false; } @@ -521,7 +519,7 @@ void PutPlayerInServer(entity this) accuracy_resend(this); if (this.team < 0) - JoinBestTeam(this, true); + TeamBalance_JoinBestTeam(this, true); entity spot = SelectSpawnPoint(this, false); if (!spot) { @@ -915,7 +913,7 @@ void ClientKill_Now_TeamChange(entity this) { if(this.killindicator_teamchange == -1) { - JoinBestTeam( this, true ); + TeamBalance_JoinBestTeam(this, true); } else if(this.killindicator_teamchange == -2) { @@ -1175,6 +1173,76 @@ void ClientPreConnect(entity this) } #endif +string GetClientVersionMessage(entity this) +{ + if (CS(this).version_mismatch) { + if(CS(this).version < autocvar_gameversion) { + return strcat("This is Xonotic ", autocvar_g_xonoticversion, + "\n^3Your client version is outdated.\n\n\n### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###\n\n\nPlease update!!!^8"); + } else { + return strcat("This is Xonotic ", autocvar_g_xonoticversion, + "\n^3This server is using an outdated Xonotic version.\n\n\n ### THIS SERVER IS INCOMPATIBLE AND THUS YOU CANNOT JOIN ###.^8"); + } + } else { + return strcat("Welcome to Xonotic ", autocvar_g_xonoticversion); + } +} + +string getwelcomemessage(entity this) +{ + MUTATOR_CALLHOOK(BuildMutatorsPrettyString, ""); + string modifications = M_ARGV(0, string); + + if(g_weaponarena) + { + if(g_weaponarena_random) + modifications = strcat(modifications, ", ", ftos(g_weaponarena_random), " of ", g_weaponarena_list, " Arena"); + else + modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena"); + } + else if(cvar("g_balance_blaster_weaponstartoverride") == 0) + modifications = strcat(modifications, ", No start weapons"); + if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity"))) + modifications = strcat(modifications, ", Low gravity"); + if(g_weapon_stay && !g_cts) + modifications = strcat(modifications, ", Weapons stay"); + if(g_jetpack) + modifications = strcat(modifications, ", Jet pack"); + if(autocvar_g_powerups == 0) + modifications = strcat(modifications, ", No powerups"); + if(autocvar_g_powerups > 0) + modifications = strcat(modifications, ", Powerups"); + modifications = substring(modifications, 2, strlen(modifications) - 2); + + string versionmessage = GetClientVersionMessage(this); + string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n"); + + if(modifications != "") + s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n"); + + if(cache_lastmutatormsg != autocvar_g_mutatormsg) + { + strcpy(cache_lastmutatormsg, autocvar_g_mutatormsg); + strcpy(cache_mutatormsg, cache_lastmutatormsg); + } + + if (cache_mutatormsg != "") { + s = strcat(s, "\n\n^8special gameplay tips: ^7", cache_mutatormsg); + } + + string mutator_msg = ""; + MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg); + mutator_msg = M_ARGV(0, string); + + s = strcat(s, mutator_msg); // trust that the mutator will do proper formatting + + string motd = autocvar_sv_motd; + if (motd != "") { + s = strcat(s, "\n\n^8MOTD: ^7", strreplace("\\n", "\n", motd)); + } + return s; +} + /** ============= ClientConnect @@ -1230,7 +1298,7 @@ void ClientConnect(entity this) int playerid_save = this.playerid; this.playerid = 0; // silent - JoinBestTeam(this, false); // if the team number is valid, keep it + TeamBalance_JoinBestTeam(this, false); // if the team number is valid, keep it this.playerid = playerid_save; TRANSMUTE(Observer, this); @@ -1246,7 +1314,7 @@ void ClientConnect(entity this) if (autocvar_sv_eventlog) GameLogEcho(strcat(":join:", ftos(this.playerid), ":", ftos(etof(this)), ":", ((IS_REAL_CLIENT(this)) ? this.netaddress : "bot"), ":", playername(this, false))); - LogTeamchange(this.playerid, this.team, 1); + LogTeamchange(this.playerid, this.team, TEAM_CHANGE_CONNECT); CS(this).just_joined = true; // stop spamming the eventlog with additional lines when the client connects @@ -1266,12 +1334,9 @@ void ClientConnect(entity this) // notify about available teams if (teamplay) { - CheckAllowedTeams(this); - int t = 0; - if (c1 >= 0) t |= BIT(0); - if (c2 >= 0) t |= BIT(1); - if (c3 >= 0) t |= BIT(2); - if (c4 >= 0) t |= BIT(3); + entity balance = TeamBalance_CheckAllowedTeams(this); + int t = TeamBalance_GetAllowedTeams(balance); + TeamBalance_Destroy(balance); stuffcmd(this, sprintf("set _teams_available %d\n", t)); } else @@ -1523,7 +1588,7 @@ void DebugPrintToChatTeam(int team_num, string text) void play_countdown(entity this, float finished, Sound samp) { - TC(Sound, samp); + TC(Sound, samp); if(IS_REAL_CLIENT(this)) if(floor(finished - time - frametime) != floor(finished - time)) if(finished - time < 6) @@ -1803,7 +1868,7 @@ spectate mode routines void SpectateCopy(entity this, entity spectatee) { - TC(Client, this); TC(Client, spectatee); + TC(Client, this); TC(Client, spectatee); MUTATOR_CALLHOOK(SpectateCopy, spectatee, this); PS(this) = PS(spectatee); @@ -2056,7 +2121,7 @@ void Join(entity this) if(!this.team_selected) if(autocvar_g_campaign || autocvar_g_balance_teams) - JoinBestTeam(this, true); + TeamBalance_JoinBestTeam(this, true); if(autocvar_g_campaign) campaign_bots_may_start = true; @@ -2067,7 +2132,9 @@ void Join(entity this) if(IS_PLAYER(this)) if(teamplay && this.team != -1) - Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname); + { + //Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(this.team, INFO_JOIN_PLAY_TEAM), this.netname); + } else Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_JOIN_PLAY, this.netname); this.team_selected = false; diff --git a/qcsrc/server/command/cmd.qc b/qcsrc/server/command/cmd.qc index 9b7a0f657..0e6781e37 100644 --- a/qcsrc/server/command/cmd.qc +++ b/qcsrc/server/command/cmd.qc @@ -394,13 +394,16 @@ void ClientCommand_selectteam(entity caller, float request, float argc) if ((selection != -1) && autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance) { - CheckAllowedTeams(caller); - GetTeamCounts(caller); - if ((BIT(Team_TeamToNumber(selection) - 1) & FindBestTeams(caller, false)) == 0) + entity balance = TeamBalance_CheckAllowedTeams(caller); + TeamBalance_GetTeamCounts(balance, caller); + if ((Team_IndexToBit(Team_TeamToIndex(selection)) & + TeamBalance_FindBestTeams(balance, caller, false)) == 0) { Send_Notification(NOTIF_ONE, caller, MSG_INFO, INFO_TEAMCHANGE_LARGERTEAM); + TeamBalance_Destroy(balance); return; } + TeamBalance_Destroy(balance); } ClientKill_TeamChange(caller, selection); if (!IS_PLAYER(caller)) diff --git a/qcsrc/server/command/sv_cmd.qc b/qcsrc/server/command/sv_cmd.qc index 1076225d8..9ba78c32a 100644 --- a/qcsrc/server/command/sv_cmd.qc +++ b/qcsrc/server/command/sv_cmd.qc @@ -1057,6 +1057,7 @@ void GameCommand_moveplayer(float request, float argc) // find the team to move the player to team_id = Team_ColorToTeam(destination); + entity balance; if (team_id == client.team) // already on the destination team { // keep the forcing undone @@ -1065,30 +1066,72 @@ void GameCommand_moveplayer(float request, float argc) } else if (team_id == 0) // auto team { - CheckAllowedTeams(client); - team_id = Team_NumberToTeam(FindSmallestTeam(client, false)); + balance = TeamBalance_CheckAllowedTeams(client); + team_id = Team_IndexToTeam(TeamBalance_FindBestTeam(balance, client, false)); } else { - CheckAllowedTeams(client); + balance = TeamBalance_CheckAllowedTeams(client); } client.team_forced = save; // Check to see if the destination team is even available switch (team_id) { - case NUM_TEAM_1: if (c1 == -1) { LOG_INFO("Sorry, can't move player to red team if it doesn't exist."); return; } break; - case NUM_TEAM_2: if (c2 == -1) { LOG_INFO("Sorry, can't move player to blue team if it doesn't exist."); return; } break; - case NUM_TEAM_3: if (c3 == -1) { LOG_INFO("Sorry, can't move player to yellow team if it doesn't exist."); return; } break; - case NUM_TEAM_4: if (c4 == -1) { LOG_INFO("Sorry, can't move player to pink team if it doesn't exist."); return; } break; - - default: LOG_INFO("Sorry, can't move player here if team ", destination, " doesn't exist."); + case NUM_TEAM_1: + { + if (!TeamBalance_IsTeamAllowed(balance, 1)) + { + LOG_INFO("Sorry, can't move player to red team if it doesn't exist."); + TeamBalance_Destroy(balance); + return; + } + TeamBalance_Destroy(balance); + break; + } + case NUM_TEAM_2: + { + if (!TeamBalance_IsTeamAllowed(balance, 2)) + { + LOG_INFO("Sorry, can't move player to blue team if it doesn't exist."); + TeamBalance_Destroy(balance); + return; + } + TeamBalance_Destroy(balance); + break; + } + case NUM_TEAM_3: + { + if (!TeamBalance_IsTeamAllowed(balance, 3)) + { + LOG_INFO("Sorry, can't move player to yellow team if it doesn't exist."); + TeamBalance_Destroy(balance); + return; + } + TeamBalance_Destroy(balance); + break; + } + case NUM_TEAM_4: + { + if (!TeamBalance_IsTeamAllowed(balance, 4)) + { + LOG_INFO("Sorry, can't move player to pink team if it doesn't exist."); + TeamBalance_Destroy(balance); + return; + } + TeamBalance_Destroy(balance); + break; + } + default: + { + LOG_INFO("Sorry, can't move player here if team ", destination, " doesn't exist."); return; + } } // If so, lets continue and finally move the player client.team_forced = 0; - if (MoveToTeam(client, team_id, 6)) + if (MoveToTeam(client, Team_TeamToIndex(team_id), 6)) { successful = strcat(successful, (successful ? ", " : ""), playername(client, false)); LOG_INFO("Player ", ftos(GetFilteredNumber(t)), " (", playername(client, false), ") has been moved to the ", Team_ColoredFullName(team_id), "^7."); @@ -1279,16 +1322,23 @@ void GameCommand_shuffleteams(float request) }); int number_of_teams = 0; - CheckAllowedTeams(NULL); - if (c1 >= 0) number_of_teams = max(1, number_of_teams); - if (c2 >= 0) number_of_teams = max(2, number_of_teams); - if (c3 >= 0) number_of_teams = max(3, number_of_teams); - if (c4 >= 0) number_of_teams = max(4, number_of_teams); + entity balance = TeamBalance_CheckAllowedTeams(NULL); + for (int i = 1; i <= NUM_TEAMS; ++i) + { + if (TeamBalance_IsTeamAllowed(balance, i)) + { + number_of_teams = max(i, number_of_teams); + } + } + TeamBalance_Destroy(balance); int team_index = 0; FOREACH_CLIENT_RANDOM(IS_PLAYER(it) || it.caplayer, { - int target_team_number = Team_NumberToTeam(team_index + 1); - if (it.team != target_team_number) MoveToTeam(it, target_team_number, 6); + int target_team_index = team_index + 1; + if (Entity_GetTeamIndex(it) != target_team_index) + { + MoveToTeam(it, target_team_index, 6); + } team_index = (team_index + 1) % number_of_teams; }); diff --git a/qcsrc/server/command/vote.qc b/qcsrc/server/command/vote.qc index 5f034f12f..b990888e6 100644 --- a/qcsrc/server/command/vote.qc +++ b/qcsrc/server/command/vote.qc @@ -10,6 +10,7 @@ #include "../g_damage.qh" #include "../g_world.qh" +#include "../teamplay.qh" #include "../race.qh" #include "../round_handler.qh" #include "../scores.qh" diff --git a/qcsrc/server/defs.qh b/qcsrc/server/defs.qh index 4c23aaeb3..d2a695aeb 100644 --- a/qcsrc/server/defs.qh +++ b/qcsrc/server/defs.qh @@ -27,8 +27,6 @@ float bots_would_leave; void UpdateFrags(entity player, int f); .float totalfrags; -float team1_score, team2_score, team3_score, team4_score; - // flag set on worldspawn so that the code knows if it is dedicated or not float server_is_dedicated; @@ -231,8 +229,6 @@ void Damage (entity targ, entity inflictor, entity attacker, float damage, int d // WEAPONTODO #define DMG_NOWEP (weaponentities[0]) -float lockteams; - float sv_maxidle; float sv_maxidle_spectatorsareidle; int sv_maxidle_slots; diff --git a/qcsrc/server/g_damage.qc b/qcsrc/server/g_damage.qc index 38284c30d..a25ae5bec 100644 --- a/qcsrc/server/g_damage.qc +++ b/qcsrc/server/g_damage.qc @@ -35,7 +35,7 @@ void UpdateFrags(entity player, int f) GameRules_scoring_add_team(player, SCORE, f); } -void GiveFrags (entity attacker, entity targ, float f, int deathtype, .entity weaponentity) +void GiveFrags(entity attacker, entity targ, float f, int deathtype, .entity weaponentity) { // TODO route through PlayerScores instead if(game_stopped) return; @@ -566,7 +566,7 @@ void Unfreeze(entity targ) MUTATOR_CALLHOOK(Unfreeze, targ); } -void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) +void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) { float complainteamdamage = 0; float mirrordamage = 0; @@ -1040,9 +1040,9 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in } if(targ == directhitentity || DEATH_ISSPECIAL(deathtype)) - Damage (targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force); + Damage(targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force); else - Damage (targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, weaponentity, nearest, force); + Damage(targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, weaponentity, nearest, force); } } } @@ -1058,9 +1058,9 @@ float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector in return total_damage_to_creatures; } -float RadiusDamage (entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity) +float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype, .entity weaponentity, entity directhitentity) { - return RadiusDamageForSource (inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, false, forceintensity, deathtype, weaponentity, directhitentity); + return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad, cantbe, mustbe, false, forceintensity, deathtype, weaponentity, directhitentity); } bool Heal(entity targ, entity inflictor, float amount, float limit) diff --git a/qcsrc/server/g_world.qc b/qcsrc/server/g_world.qc index 26a4cfb08..038936ee4 100644 --- a/qcsrc/server/g_world.qc +++ b/qcsrc/server/g_world.qc @@ -16,6 +16,7 @@ #include #include "race.qh" #include "scores.qh" +#include "scores_rules.qh" #include "teamplay.qh" #include "weapons/weaponstats.qh" #include "../common/constants.qh" @@ -578,6 +579,58 @@ STATIC_INIT_EARLY(maxclients) } } +void default_delayedinit(entity this) +{ + if(!scores_initialized) + ScoreRules_generic(); +} + +void InitGameplayMode() +{ + VoteReset(); + + // find out good world mins/maxs bounds, either the static bounds found by looking for solid, or the mapinfo specified bounds + get_mi_min_max(1); + // assign reflectively to avoid "assignment to world" warning + int done = 0; for (int i = 0, n = numentityfields(); i < n; ++i) { + string k = entityfieldname(i); vector v = (k == "mins") ? mi_min : (k == "maxs") ? mi_max : '0 0 0'; + if (v) { + putentityfieldstring(i, world, sprintf("%v", v)); + if (++done == 2) break; + } + } + // currently, NetRadiant's limit is 131072 qu for each side + // distance from one corner of a 131072qu cube to the opposite corner is approx. 227023 qu + // set the distance according to map size but don't go over the limit to avoid issues with float precision + // in case somebody makes extremely large maps + max_shot_distance = min(230000, vlen(world.maxs - world.mins)); + + MapInfo_LoadMapSettings(mapname); + GameRules_teams(false); + + if (!cvar_value_issafe(world.fog)) + { + LOG_INFO("The current map contains a potentially harmful fog setting, ignored"); + world.fog = string_null; + } + if(MapInfo_Map_fog != "") + if(MapInfo_Map_fog == "none") + world.fog = string_null; + else + world.fog = strzone(MapInfo_Map_fog); + clientstuff = strzone(MapInfo_Map_clientstuff); + + MapInfo_ClearTemps(); + + gamemode_name = MapInfo_Type_ToText(MapInfo_LoadedGametype); + + cache_mutatormsg = strzone(""); + cache_lastmutatormsg = strzone(""); + + InitializeEntity(NULL, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK); +} + +void Map_MarkAsRecent(string m); float world_already_spawned; spawnfunc(worldspawn) { @@ -1646,10 +1699,11 @@ float WinningCondition_Scores(float limit, float leadlimit) if(teamplay) { - team1_score = TeamScore_GetCompareValue(NUM_TEAM_1); - team2_score = TeamScore_GetCompareValue(NUM_TEAM_2); - team3_score = TeamScore_GetCompareValue(NUM_TEAM_3); - team4_score = TeamScore_GetCompareValue(NUM_TEAM_4); + for (int i = 1; i < 5; ++i) + { + Team_SetTeamScore(Team_GetTeamFromIndex(i), + TeamScore_GetCompareValue(Team_IndexToTeam(i))); + } } ClearWinners(); @@ -1719,30 +1773,32 @@ float WinningCondition_RanOutOfSpawns() if(!some_spawn_has_been_used) return WINNING_NO; - team1_score = team2_score = team3_score = team4_score = 0; - - FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it), { - switch(it.team) + for (int i = 1; i < 5; ++i) + { + Team_SetTeamScore(Team_GetTeamFromIndex(i), 0); + } + + FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it), + { + if (Team_IsValidTeam(it.team)) { - case NUM_TEAM_1: team1_score = 1; break; - case NUM_TEAM_2: team2_score = 1; break; - case NUM_TEAM_3: team3_score = 1; break; - case NUM_TEAM_4: team4_score = 1; break; + Team_SetTeamScore(Team_GetTeam(it.team), 1); } }); IL_EACH(g_spawnpoints, true, { - switch(it.team) + if (Team_IsValidTeam(it.team)) { - case NUM_TEAM_1: team1_score = 1; break; - case NUM_TEAM_2: team2_score = 1; break; - case NUM_TEAM_3: team3_score = 1; break; - case NUM_TEAM_4: team4_score = 1; break; + Team_SetTeamScore(Team_GetTeam(it.team), 1); } }); ClearWinners(); + float team1_score = Team_GetTeamScore(Team_GetTeamFromIndex(1)); + float team2_score = Team_GetTeamScore(Team_GetTeamFromIndex(2)); + float team3_score = Team_GetTeamScore(Team_GetTeamFromIndex(3)); + float team4_score = Team_GetTeamScore(Team_GetTeamFromIndex(4)); if(team1_score + team2_score + team3_score + team4_score == 0) { checkrules_equality = true; @@ -1752,20 +1808,28 @@ float WinningCondition_RanOutOfSpawns() { float t, i; if(team1_score) - t = NUM_TEAM_1; + t = 1; else if(team2_score) - t = NUM_TEAM_2; + t = 2; else if(team3_score) - t = NUM_TEAM_3; + t = 3; else // if(team4_score) - t = NUM_TEAM_4; - CheckAllowedTeams(NULL); + t = 4; + entity balance = TeamBalance_CheckAllowedTeams(NULL); for(i = 0; i < MAX_TEAMSCORE; ++i) { - if(t != NUM_TEAM_1) if(c1 >= 0) TeamScore_AddToTeam(NUM_TEAM_1, i, -1000); - if(t != NUM_TEAM_2) if(c2 >= 0) TeamScore_AddToTeam(NUM_TEAM_2, i, -1000); - if(t != NUM_TEAM_3) if(c3 >= 0) TeamScore_AddToTeam(NUM_TEAM_3, i, -1000); - if(t != NUM_TEAM_4) if(c4 >= 0) TeamScore_AddToTeam(NUM_TEAM_4, i, -1000); + for (int j = 1; j <= NUM_TEAMS; ++j) + { + if (t == j) + { + continue; + } + if (!TeamBalance_IsTeamAllowed(balance, j)) + { + continue; + } + TeamScore_AddToTeam(Team_IndexToTeam(j), i, -1000); + } } AddWinners(team, t); diff --git a/qcsrc/server/g_world.qh b/qcsrc/server/g_world.qh index c0c35589a..da950f185 100644 --- a/qcsrc/server/g_world.qh +++ b/qcsrc/server/g_world.qh @@ -5,6 +5,9 @@ float checkrules_suddendeathwarning; float checkrules_suddendeathend; float checkrules_overtimesadded; //how many overtimes have been already added +string cache_mutatormsg; +string cache_lastmutatormsg; + const int WINNING_NO = 0; // no winner, but time limits may terminate the game const int WINNING_YES = 1; // winner found const int WINNING_NEVER = 2; // no winner, enter overtime if time limit is reached diff --git a/qcsrc/server/mutators/events.qh b/qcsrc/server/mutators/events.qh index a4cf9df8e..58e9ca127 100644 --- a/qcsrc/server/mutators/events.qh +++ b/qcsrc/server/mutators/events.qh @@ -137,40 +137,51 @@ MUTATOR_HOOKABLE(GiveFragsForKill, EV_GiveFragsForKill); /** called when the match ends */ MUTATOR_HOOKABLE(MatchEnd, EV_NO_ARGS); -/** allows adjusting allowed teams */ -#define EV_CheckAllowedTeams(i, o) \ +/** Allows adjusting allowed teams. Return true to use the bitmask value and set + * non-empty string to use team entity name. Both behaviors can be active at the + * same time and will stack allowed teams. + */ +#define EV_TeamBalance_CheckAllowedTeams(i, o) \ /** mask of teams */ i(float, MUTATOR_ARGV_0_float) \ /**/ o(float, MUTATOR_ARGV_0_float) \ /** team entity name */ i(string, MUTATOR_ARGV_1_string) \ /**/ o(string, MUTATOR_ARGV_1_string) \ /** player checked */ i(entity, MUTATOR_ARGV_2_entity) \ /**/ -MUTATOR_HOOKABLE(CheckAllowedTeams, EV_CheckAllowedTeams); +MUTATOR_HOOKABLE(TeamBalance_CheckAllowedTeams, + EV_TeamBalance_CheckAllowedTeams); /** return true to manually override team counts */ -MUTATOR_HOOKABLE(GetTeamCounts, EV_NO_ARGS); +MUTATOR_HOOKABLE(TeamBalance_GetTeamCounts, EV_NO_ARGS); -/** allow overriding of team counts */ -#define EV_GetTeamCount(i, o) \ - /** team to count */ i(float, MUTATOR_ARGV_0_float) \ +/** allows overriding of team counts */ +#define EV_TeamBalance_GetTeamCount(i, o) \ + /** team index to count */ i(float, MUTATOR_ARGV_0_float) \ /** player to ignore */ i(entity, MUTATOR_ARGV_1_entity) \ - /** number of players in a team */ i(float, MUTATOR_ARGV_2_float) \ - /**/ o(float, MUTATOR_ARGV_2_float) \ - /** number of bots in a team */ i(float, MUTATOR_ARGV_3_float) \ - /**/ o(float, MUTATOR_ARGV_3_float) \ - /** lowest scoring human in a team */ i(entity, MUTATOR_ARGV_4_entity) \ - /**/ o(entity, MUTATOR_ARGV_4_entity) \ - /** lowest scoring bot in a team */ i(entity, MUTATOR_ARGV_5_entity) \ - /**/ o(entity, MUTATOR_ARGV_5_entity) \ - /**/ -MUTATOR_HOOKABLE(GetTeamCount, EV_GetTeamCount); - -/** allows overriding best teams */ -#define EV_FindBestTeams(i, o) \ + /** number of players in a team */ o(float, MUTATOR_ARGV_2_float) \ + /** number of bots in a team */ o(float, MUTATOR_ARGV_3_float) \ + /**/ +MUTATOR_HOOKABLE(TeamBalance_GetTeamCount, EV_TeamBalance_GetTeamCount); + +/** allows overriding the teams that will make the game most balanced if the + * player joins any of them. + */ +#define EV_TeamBalance_FindBestTeams(i, o) \ /** player checked */ i(entity, MUTATOR_ARGV_0_entity) \ /** bitmask of teams */ o(float, MUTATOR_ARGV_1_float) \ /**/ -MUTATOR_HOOKABLE(FindBestTeams, EV_FindBestTeams); +MUTATOR_HOOKABLE(TeamBalance_FindBestTeams, EV_TeamBalance_FindBestTeams); + +/** Called during autobalance. Return true to override the player that will be +switched. */ +#define EV_TeamBalance_GetPlayerForTeamSwitch(i, o) \ + /** source team index */ i(int, MUTATOR_ARGV_0_int) \ + /** destination team index */ i(int, MUTATOR_ARGV_1_int) \ + /** is looking for bot */ i(bool, MUTATOR_ARGV_2_bool) \ + /** player to switch */ o(entity, MUTATOR_ARGV_3_entity) \ + /**/ +MUTATOR_HOOKABLE(TeamBalance_GetPlayerForTeamSwitch, + EV_TeamBalance_GetPlayerForTeamSwitch); /** copies variables for spectating "spectatee" to "this" */ #define EV_SpectateCopy(i, o) \ @@ -1041,9 +1052,9 @@ MUTATOR_HOOKABLE(MonsterModel, EV_MonsterModel); * Called before player changes their team. Return true to block team change. */ #define EV_Player_ChangeTeam(i, o) \ - /** player */ i(entity, MUTATOR_ARGV_0_entity) \ - /** current team */ i(float, MUTATOR_ARGV_1_float) \ - /** new team */ i(float, MUTATOR_ARGV_2_float) \ + /** player */ i(entity, MUTATOR_ARGV_0_entity) \ + /** current team index */ i(float, MUTATOR_ARGV_1_float) \ + /** new team index */ i(float, MUTATOR_ARGV_2_float) \ /**/ MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam); @@ -1051,9 +1062,9 @@ MUTATOR_HOOKABLE(Player_ChangeTeam, EV_Player_ChangeTeam); * Called after player has changed their team. */ #define EV_Player_ChangedTeam(i, o) \ - /** player */ i(entity, MUTATOR_ARGV_0_entity) \ - /** old team */ i(float, MUTATOR_ARGV_1_float) \ - /** current team */ i(float, MUTATOR_ARGV_2_float) \ + /** player */ i(entity, MUTATOR_ARGV_0_entity) \ + /** old team index */ i(float, MUTATOR_ARGV_1_float) \ + /** current team index */ i(float, MUTATOR_ARGV_2_float) \ /**/ MUTATOR_HOOKABLE(Player_ChangedTeam, EV_Player_ChangedTeam); diff --git a/qcsrc/server/player.qc b/qcsrc/server/player.qc index 5bd4b5989..3755da963 100644 --- a/qcsrc/server/player.qc +++ b/qcsrc/server/player.qc @@ -675,21 +675,6 @@ bool PlayerHeal(entity targ, entity inflictor, float amount, float limit) return true; } -bool MoveToTeam(entity client, int team_colour, int type) -{ - int lockteams_backup = lockteams; // backup any team lock - lockteams = 0; // disable locked teams - TeamchangeFrags(client); // move the players frags - if (!SetPlayerTeamSimple(client, team_colour)) - { - return false; - } - Damage(client, client, client, 100000, DEATH_AUTOTEAMCHANGE.m_id, DMG_NOWEP, client.origin, '0 0 0'); // kill the player - lockteams = lockteams_backup; // restore the team lock - LogTeamchange(client.playerid, client.team, type); - return true; -} - /** * message "": do not say, just test flood control * return value: diff --git a/qcsrc/server/player.qh b/qcsrc/server/player.qh index 8c9bac9b6..1c38a9fbe 100644 --- a/qcsrc/server/player.qh +++ b/qcsrc/server/player.qh @@ -30,13 +30,6 @@ void calculate_player_respawn_time(entity this); void ClientKill_Now_TeamChange(entity this); -/// \brief Moves player to the specified team. -/// \param[in,out] client Client to move. -/// \param[in] team_colour Color of the team. -/// \param[in] type ??? -/// \return True on success, false otherwise. -bool MoveToTeam(entity client, float team_colour, float type); - void PlayerDamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force); bool PlayerHeal(entity targ, entity inflictor, float amount, float limit); diff --git a/qcsrc/server/scores_rules.qc b/qcsrc/server/scores_rules.qc index 160b5df5e..39dbd49a3 100644 --- a/qcsrc/server/scores_rules.qc +++ b/qcsrc/server/scores_rules.qc @@ -17,8 +17,6 @@ int NumTeams(int teams) int AvailableTeams() { return NumTeams(ScoreRules_teams); - // NOTE: this method is unreliable, as forced teams set the c* globals to weird values - //return boolean(c1 >= 0) + boolean(c2 >= 0) + boolean(c3 >= 0) + boolean(c4 >= 0); } // NOTE: ST_constants may not be >= MAX_TEAMSCORE @@ -64,12 +62,11 @@ void ScoreRules_basics_end() void ScoreRules_generic() { int teams = 0; - if (teamplay) { - CheckAllowedTeams(NULL); - if (c1 >= 0) teams |= BIT(0); - if (c2 >= 0) teams |= BIT(1); - if (c3 >= 0) teams |= BIT(2); - if (c4 >= 0) teams |= BIT(3); + if (teamplay) + { + entity balance = TeamBalance_CheckAllowedTeams(NULL); + teams = TeamBalance_GetAllowedTeams(balance); + TeamBalance_Destroy(balance); } GameRules_scoring(teams, SFL_SORT_PRIO_PRIMARY, SFL_SORT_PRIO_PRIMARY, {}); } diff --git a/qcsrc/server/teamplay.qc b/qcsrc/server/teamplay.qc index b0d9e0992..25acdd3e0 100644 --- a/qcsrc/server/teamplay.qc +++ b/qcsrc/server/teamplay.qc @@ -15,141 +15,110 @@ #include #include "../common/teams.qh" -void TeamchangeFrags(entity e) +/// \brief Describes a state of team balance entity. +enum { - PlayerScore_Clear(e); -} + TEAM_BALANCE_UNINITIALIZED, ///< The team balance has not been initialized. + /// \brief TeamBalance_CheckAllowedTeams has been called. + TEAM_BALANCE_TEAMS_CHECKED, + /// \brief TeamBalance_GetTeamCounts has been called. + TEAM_BALANCE_TEAM_COUNTS_FILLED +}; -void LogTeamchange(float player_id, float team_number, float type) -{ - if(!autocvar_sv_eventlog) - return; +/// \brief Indicates that the player is not allowed to join a team. +const int TEAM_NOT_ALLOWED = -1; - if(player_id < 1) - return; +.int m_team_balance_state; ///< Holds the state of the team balance entity. +.entity m_team_balance_team[NUM_TEAMS]; ///< ??? - GameLogEcho(strcat(":team:", ftos(player_id), ":", ftos(team_number), ":", ftos(type))); -} +.float m_team_score; ///< The score of the team. +.int m_num_players; ///< Number of players (both humans and bots) in a team. +.int m_num_bots; ///< Number of bots in a team. +.int m_num_players_alive; ///< Number of alive players in a team. +.int m_num_control_points; ///< Number of control points owned by a team. + +entity g_team_entities[NUM_TEAMS]; ///< Holds global team entities. -void default_delayedinit(entity this) +STATIC_INIT(g_team_entities) { - if(!scores_initialized) - ScoreRules_generic(); + for (int i = 0; i < NUM_TEAMS; ++i) + { + g_team_entities[i] = spawn(); + } } -void InitGameplayMode() +entity Team_GetTeamFromIndex(int index) { - VoteReset(); - - // find out good world mins/maxs bounds, either the static bounds found by looking for solid, or the mapinfo specified bounds - get_mi_min_max(1); - // assign reflectively to avoid "assignment to world" warning - int done = 0; for (int i = 0, n = numentityfields(); i < n; ++i) { - string k = entityfieldname(i); vector v = (k == "mins") ? mi_min : (k == "maxs") ? mi_max : '0 0 0'; - if (v) { - putentityfieldstring(i, world, sprintf("%v", v)); - if (++done == 2) break; - } - } - // currently, NetRadiant's limit is 131072 qu for each side - // distance from one corner of a 131072qu cube to the opposite corner is approx. 227023 qu - // set the distance according to map size but don't go over the limit to avoid issues with float precision - // in case somebody makes extremely large maps - max_shot_distance = min(230000, vlen(world.maxs - world.mins)); - - MapInfo_LoadMapSettings(mapname); - GameRules_teams(false); - - if (!cvar_value_issafe(world.fog)) - { - LOG_INFO("The current map contains a potentially harmful fog setting, ignored"); - world.fog = string_null; - } - if(MapInfo_Map_fog != "") - if(MapInfo_Map_fog == "none") - world.fog = string_null; - else - world.fog = strzone(MapInfo_Map_fog); - clientstuff = strzone(MapInfo_Map_clientstuff); - - MapInfo_ClearTemps(); - - gamemode_name = MapInfo_Type_ToText(MapInfo_LoadedGametype); - - cache_mutatormsg = strzone(""); - cache_lastmutatormsg = strzone(""); - - InitializeEntity(NULL, default_delayedinit, INITPRIO_GAMETYPE_FALLBACK); + if (!Team_IsValidIndex(index)) + { + LOG_FATALF("Team_GetTeamFromIndex: Index is invalid: %f", index); + } + return g_team_entities[index - 1]; } -string GetClientVersionMessage(entity this) +entity Team_GetTeam(int team_num) { - if (CS(this).version_mismatch) { - if(CS(this).version < autocvar_gameversion) { - return strcat("This is Xonotic ", autocvar_g_xonoticversion, - "\n^3Your client version is outdated.\n\n\n### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###\n\n\nPlease update!!!^8"); - } else { - return strcat("This is Xonotic ", autocvar_g_xonoticversion, - "\n^3This server is using an outdated Xonotic version.\n\n\n ### THIS SERVER IS INCOMPATIBLE AND THUS YOU CANNOT JOIN ###.^8"); - } - } else { - return strcat("Welcome to Xonotic ", autocvar_g_xonoticversion); + if (!Team_IsValidTeam(team_num)) + { + LOG_FATALF("Team_GetTeam: Value is invalid: %f", team_num); } + return g_team_entities[Team_TeamToIndex(team_num) - 1]; } -string getwelcomemessage(entity this) +float Team_GetTeamScore(entity team_ent) { - MUTATOR_CALLHOOK(BuildMutatorsPrettyString, ""); - string modifications = M_ARGV(0, string); + return team_ent.m_team_score; +} - if(g_weaponarena) - { - if(g_weaponarena_random) - modifications = strcat(modifications, ", ", ftos(g_weaponarena_random), " of ", g_weaponarena_list, " Arena"); // TODO: somehow get this into the mutator - else - modifications = strcat(modifications, ", ", g_weaponarena_list, " Arena"); - } - else if(cvar("g_balance_blaster_weaponstartoverride") == 0) - modifications = strcat(modifications, ", No start weapons"); - if(cvar("sv_gravity") < stof(cvar_defstring("sv_gravity"))) - modifications = strcat(modifications, ", Low gravity"); - if(g_weapon_stay && !g_cts) - modifications = strcat(modifications, ", Weapons stay"); - if(g_jetpack) - modifications = strcat(modifications, ", Jetpack"); - if(autocvar_g_powerups == 0) - modifications = strcat(modifications, ", No powerups"); - if(autocvar_g_powerups > 0) - modifications = strcat(modifications, ", Powerups"); - modifications = substring(modifications, 2, strlen(modifications) - 2); +void Team_SetTeamScore(entity team_ent, float score) +{ + team_ent.m_team_score = score; +} - string versionmessage = GetClientVersionMessage(this); - string s = strcat(versionmessage, "^8\n^8\nmatch type is ^1", gamemode_name, "^8\n"); +int Team_GetNumberOfAlivePlayers(entity team_ent) +{ + return team_ent.m_num_players_alive; +} - if(modifications != "") - s = strcat(s, "^8\nactive modifications: ^3", modifications, "^8\n"); +void Team_SetNumberOfAlivePlayers(entity team_ent, int number) +{ + team_ent.m_num_players_alive = number; +} - if(cache_lastmutatormsg != autocvar_g_mutatormsg) +int Team_GetNumberOfAliveTeams() +{ + int result = 0; + for (int i = 0; i < NUM_TEAMS; ++i) { - strcpy(cache_lastmutatormsg, autocvar_g_mutatormsg); - strcpy(cache_mutatormsg, cache_lastmutatormsg); - } - - if (cache_mutatormsg != "") { - s = strcat(s, "\n\n^8special gameplay tips: ^7", cache_mutatormsg); + if (g_team_entities[i].m_num_players_alive > 0) + { + ++result; + } } + return result; +} - string mutator_msg = ""; - MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg); - mutator_msg = M_ARGV(0, string); +int Team_GetNumberOfControlPoints(entity team_ent) +{ + return team_ent.m_num_control_points; +} - s = strcat(s, mutator_msg); // trust that the mutator will do proper formatting +void Team_SetNumberOfControlPoints(entity team_ent, int number) +{ + team_ent.m_num_control_points = number; +} - string motd = autocvar_sv_motd; - if (motd != "") { - s = strcat(s, "\n\n^8MOTD: ^7", strreplace("\\n", "\n", motd)); +int Team_GetNumberOfTeamsWithControlPoints() +{ + int result = 0; + for (int i = 0; i < NUM_TEAMS; ++i) + { + if (g_team_entities[i].m_num_control_points > 0) + { + ++result; + } } - return s; + return result; } void setcolor(entity this, int clr) @@ -162,6 +131,26 @@ void setcolor(entity this, int clr) #endif } +bool Entity_HasValidTeam(entity this) +{ + return Team_IsValidTeam(this.team); +} + +int Entity_GetTeamIndex(entity this) +{ + return Team_TeamToIndex(this.team); +} + +entity Entity_GetTeam(entity this) +{ + int index = Entity_GetTeamIndex(this); + if (!Team_IsValidIndex(index)) + { + return NULL; + } + return Team_GetTeamFromIndex(index); +} + void SetPlayerColors(entity player, float _color) { float pants = _color & 0x0F; @@ -176,748 +165,720 @@ void SetPlayerColors(entity player, float _color) } } -void KillPlayerForTeamChange(entity player) +bool Player_SetTeamIndex(entity player, int index) { - if (IS_DEAD(player)) + int new_team = Team_IndexToTeam(index); + if (player.team == new_team) { - return; + if (new_team != -1) + { + // This is important when players join the game and one of their + // color matches the team color while other doesn't. For example + // [BOT]Lion. + SetPlayerColors(player, new_team - 1); + } + return true; } - if (MUTATOR_CALLHOOK(Player_ChangeTeamKill, player) == true) + int old_index = Team_TeamToIndex(player.team); + if (MUTATOR_CALLHOOK(Player_ChangeTeam, player, old_index, index) == true) { - return; + // Mutator has blocked team change. + return false; } - Damage(player, player, player, 100000, DEATH_TEAMCHANGE.m_id, DMG_NOWEP, player.origin, - '0 0 0'); + if (new_team == -1) + { + player.team = -1; + } + else + { + SetPlayerColors(player, new_team - 1); + } + MUTATOR_CALLHOOK(Player_ChangedTeam, player, old_index, index); + return true; } -bool SetPlayerTeamSimple(entity player, int team_num) +bool SetPlayerTeam(entity player, int team_index, int type) { - if (player.team == team_num) + int old_team_index = Entity_GetTeamIndex(player); + if (!Player_SetTeamIndex(player, team_index)) { - // This is important when players join the game and one of their color - // matches the team color while other doesn't. For example [BOT]Lion. - SetPlayerColors(player, team_num - 1); - return true; + return false; } - if (MUTATOR_CALLHOOK(Player_ChangeTeam, player, Team_TeamToNumber( - player.team), Team_TeamToNumber(team_num)) == true) + LogTeamchange(player.playerid, player.team, type); + if (team_index != old_team_index) { - // Mutator has blocked team change. - return false; + Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(player.team, + INFO_JOIN_PLAY_TEAM), player.netname); + KillPlayerForTeamChange(player); } - int old_team = player.team; - SetPlayerColors(player, team_num - 1); - MUTATOR_CALLHOOK(Player_ChangedTeam, player, old_team, player.team); return true; } -bool SetPlayerTeam(entity player, int destination_team, int source_team, - bool no_print) +bool MoveToTeam(entity client, int team_index, int type) { - int team_num = Team_NumberToTeam(destination_team); - if (!SetPlayerTeamSimple(player, team_num)) + //PrintToChatAll(sprintf("MoveToTeam: %s, %f", client.netname, team_index)); + int lockteams_backup = lockteams; // backup any team lock + lockteams = 0; // disable locked teams + PlayerScore_Clear(client); + if (!SetPlayerTeam(client, team_index, type)) { + lockteams = lockteams_backup; // restore the team lock return false; } - LogTeamchange(player.playerid, player.team, 3); // log manual team join - if (no_print) + lockteams = lockteams_backup; // restore the team lock + return true; +} + +void KillPlayerForTeamChange(entity player) +{ + if (IS_DEAD(player)) { - return true; + return; } - bprint(playername(player, false), "^7 has changed from ", Team_NumberToColoredFullName(source_team), "^7 to ", Team_NumberToColoredFullName(destination_team), "\n"); - return true; + if (MUTATOR_CALLHOOK(Player_ChangeTeamKill, player) == true) + { + return; + } + 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; - c1 = c2 = c3 = c4 = -1; - num_bots_team1 = num_bots_team2 = num_bots_team3 = num_bots_team4 = 0; + if(player_id < 1) + return; - string teament_name = string_null; + GameLogEcho(strcat(":team:", ftos(player_id), ":", ftos(team_number), ":", ftos(type))); +} - bool mutator_returnvalue = MUTATOR_CALLHOOK(CheckAllowedTeams, teams_mask, teament_name, for_whom); +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(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; - } - // 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; - } + LOG_FATALF("TeamBalance_GetNumberOfPlayers: Team index is invalid: %f", + index); } - 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, bool force_best_team) +{ + //PrintToChatAll(sprintf("JoinBestTeam: %s, %f", this.netname, force_best_team)); + // don't join a team if we're not playing a team game + if (!teamplay) + { + return; + } + + // find out what teams are available + entity balance = TeamBalance_CheckAllowedTeams(this); + + // 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) { - case 1: + int selected_team_index = -1; + for (int i = 1; i <= NUM_TEAMS; ++i) { - 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; + if (TeamBalance_IsTeamAllowedInternal(balance, i) && + (Team_TeamToIndex(this.team) == i)) + { + selected_team_index = i; + break; + } } - case 4: + + if (Team_IsValidIndex(selected_team_index)) { - num_players_team_b = c4; - num_bots_team_b = num_bots_team4; - score_team_b = team4_score; - break; + SetPlayerTeam(this, selected_team_index, TEAM_CHANGE_AUTO_RELAXED); + TeamBalance_Destroy(balance); + return; } } - // invalid - if (num_players_team_a < 0 || num_players_team_b < 0) - return false; - - if (IS_REAL_CLIENT(player) && bots_would_leave) + // otherwise end up on the smallest team (handled below) + if (this.bot_forced_team) { - num_players_team_a -= num_bots_team_a; - num_players_team_b -= num_bots_team_b; + TeamBalance_Destroy(balance); + return; } - if (!use_score) + int best_team_index = TeamBalance_FindBestTeam(balance, this, true); + int old_team_index = Team_TeamToIndex(this.team); + TeamBalance_Destroy(balance); + PlayerScore_Clear(this); + if (!SetPlayerTeam(this, best_team_index, TEAM_CHANGE_AUTO)) { - 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)) + if (i != index) { - selected_team = this.team; - } - else if ((c4 >= 0) && (this.team == NUM_TEAM_4)) - { - selected_team = this.team; - } - else - { - 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; } - int best_team = FindSmallestTeam(this, true); - best_team = Team_NumberToTeam(best_team); - if (best_team == -1) + if (!TeamBalanceTeam_IsAllowed(team_a) || + !TeamBalanceTeam_IsAllowed(team_b)) { - error("JoinBestTeam: invalid team\n"); + return TEAMS_COMPARE_INVALID; } - 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)) + 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) { - AutoBalanceBots(old_team, Team_TeamToNumber(best_team)); + return TEAMS_COMPARE_GREATER; } - KillPlayerForTeamChange(this); + if (!use_score) + { + return TEAMS_COMPARE_EQUAL; + } + if (team_a.m_team_score < team_b.m_team_score) + { + return TEAMS_COMPARE_LESS; + } + if (team_a.m_team_score > team_b.m_team_score) + { + return TEAMS_COMPARE_GREATER; + } + return TEAMS_COMPARE_EQUAL; } +// Called when the player connects or when they change their color with "color" +// command. void SV_ChangeTeam(entity this, float _color) { - float source_color, destination_color, source_team, destination_team; + //PrintToChatAll(sprintf("SV_ChangeTeam: %s, %f", this.netname, _color)); // in normal deathmatch we can just apply the color and we're done if(!teamplay) @@ -933,28 +894,48 @@ void SV_ChangeTeam(entity this, float _color) if(!teamplay) return; + int source_color, destination_color; + int source_team_index, destination_team_index; + source_color = this.clientcolors & 0x0F; destination_color = _color & 0x0F; - source_team = Team_TeamToNumber(source_color + 1); - destination_team = Team_TeamToNumber(destination_color + 1); + source_team_index = Team_TeamToIndex(source_color + 1); + destination_team_index = Team_TeamToIndex(destination_color + 1); - if (destination_team == -1) + if (destination_team_index == -1) { return; } - CheckAllowedTeams(this); + entity balance = TeamBalance_CheckAllowedTeams(this); - if (destination_team == 1 && c1 < 0) destination_team = 4; - if (destination_team == 4 && c4 < 0) destination_team = 3; - if (destination_team == 3 && c3 < 0) destination_team = 2; - if (destination_team == 2 && c2 < 0) destination_team = 1; + if (destination_team_index == 1 && !TeamBalance_IsTeamAllowedInternal( + balance, 1)) + { + destination_team_index = 4; + } + if (destination_team_index == 4 && !TeamBalance_IsTeamAllowedInternal( + balance, 4)) + { + destination_team_index = 3; + } + if (destination_team_index == 3 && !TeamBalance_IsTeamAllowedInternal( + balance, 3)) + { + destination_team_index = 2; + } + if (destination_team_index == 2 && !TeamBalance_IsTeamAllowedInternal( + balance, 2)) + { + destination_team_index = 1; + } // not changing teams if (source_color == destination_color) { - SetPlayerTeam(this, destination_team, source_team, true); + SetPlayerTeam(this, destination_team_index, TEAM_CHANGE_MANUAL); + TeamBalance_Destroy(balance); return; } @@ -966,111 +947,24 @@ void SV_ChangeTeam(entity this, float _color) // autocvar_g_balance_teams_prevent_imbalance only makes sense if autocvar_g_balance_teams is on, as it makes the team selection dialog pointless if (autocvar_g_balance_teams && autocvar_g_balance_teams_prevent_imbalance) { - GetTeamCounts(this); - if ((BIT(destination_team - 1) & FindBestTeams(this, false)) == 0) + TeamBalance_GetTeamCounts(balance, this); + if ((Team_IndexToBit(destination_team_index) & + TeamBalance_FindBestTeams(balance, this, false)) == 0) { Send_Notification(NOTIF_ONE, this, MSG_INFO, INFO_TEAMCHANGE_LARGERTEAM); + TeamBalance_Destroy(balance); return; } } - if(IS_PLAYER(this) && source_team != destination_team) + TeamBalance_Destroy(balance); + if (IS_PLAYER(this) && source_team_index != destination_team_index) { // reduce frags during a team change - TeamchangeFrags(this); - } - if (!SetPlayerTeam(this, destination_team, source_team, !IS_CLIENT(this))) - { - return; - } - AutoBalanceBots(source_team, destination_team); - if (!IS_PLAYER(this) || (source_team == destination_team)) - { - return; - } - KillPlayerForTeamChange(this); -} - -void AutoBalanceBots(int source_team, int destination_team) -{ - if (!Team_IsValidNumber(source_team)) - { - 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; - } + PlayerScore_Clear(this); } - if ((num_players_destination_team <= num_players_source_team) || - (lowest_bot_destination_team == NULL)) + if (!SetPlayerTeam(this, destination_team_index, TEAM_CHANGE_MANUAL)) { return; } - SetPlayerTeamSimple(lowest_bot_destination_team, - Team_NumberToTeam(source_team)); - KillPlayerForTeamChange(lowest_bot_destination_team); + TeamBalance_AutoBalanceBots(destination_team_index, source_team_index); } diff --git a/qcsrc/server/teamplay.qh b/qcsrc/server/teamplay.qh index 7c4ebe77b..f0ad95ce1 100644 --- a/qcsrc/server/teamplay.qh +++ b/qcsrc/server/teamplay.qh @@ -1,120 +1,266 @@ #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_CONNECT = 1, + TEAM_CHANGE_AUTO = 2, + TEAM_CHANGE_MANUAL = 3, + TEAM_CHANGE_SPECTATOR = 4, + TEAM_CHANGE_AUTO_RELAXED = 99 +}; -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, bool force_best_team); -/// \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); diff --git a/qcsrc/server/weapons/selection.qc b/qcsrc/server/weapons/selection.qc index c2a9c32ac..4af13e102 100644 --- a/qcsrc/server/weapons/selection.qc +++ b/qcsrc/server/weapons/selection.qc @@ -240,7 +240,7 @@ float W_GetCycleWeapon(entity this, string weaponorder, float dir, float imp, fl void W_SwitchWeapon_Force(Player this, Weapon wep, .entity weaponentity) { - TC(Weapon, wep); + TC(Weapon, wep); this.(weaponentity).cnt = this.(weaponentity).m_switchweapon.m_id; this.(weaponentity).m_switchweapon = wep; this.(weaponentity).selectweapon = wep.m_id; diff --git a/qcsrc/server/weapons/tracing.qc b/qcsrc/server/weapons/tracing.qc index ddf1ff262..b023180a1 100644 --- a/qcsrc/server/weapons/tracing.qc +++ b/qcsrc/server/weapons/tracing.qc @@ -138,7 +138,7 @@ void W_SetupShot_Dir_ProjectileSize_Range(entity ent, .entity weaponentity, vect ent.punchangle_x = recoil * -1; if (snd != SND_Null) { - sound (ent, chan, snd, (W_DualWielding(ent) ? VOL_BASE * 0.7 : VOL_BASE), ATTN_NORM); + sound(ent, chan, snd, (W_DualWielding(ent) ? VOL_BASE * 0.7 : VOL_BASE), ATTN_NORM); W_PlayStrengthSound(ent); } diff --git a/qcsrc/server/weapons/weaponsystem.qc b/qcsrc/server/weapons/weaponsystem.qc index bf81f7044..2017e65a7 100644 --- a/qcsrc/server/weapons/weaponsystem.qc +++ b/qcsrc/server/weapons/weaponsystem.qc @@ -428,8 +428,8 @@ bool forbidWeaponUse(entity player) void W_WeaponFrame(Player actor, .entity weaponentity) { - TC(Player, actor); - TC(PlayerState, PS(actor)); + TC(Player, actor); + TC(PlayerState, PS(actor)); entity this = actor.(weaponentity); if (frametime) this.weapon_frametime = frametime; @@ -595,8 +595,8 @@ void W_WeaponFrame(Player actor, .entity weaponentity) if (!block_weapon) { - Weapon e = this.m_weapon; - TC(Weapon, e); + Weapon e = this.m_weapon; + TC(Weapon, e); if (w != WEP_Null) { e.wr_think(e, actor, weaponentity, button_atck | (button_atck2 << 1)); @@ -731,7 +731,7 @@ void W_ReloadedAndReady(Weapon thiswep, entity actor, .entity weaponentity, int void W_Reload(entity actor, .entity weaponentity, float sent_ammo_min, Sound sent_sound) { - TC(Sound, sent_sound); + TC(Sound, sent_sound); // set global values to work with entity this = actor.(weaponentity); Weapon e = this.m_weapon;