-Sun Jul 26 07:24:53 CEST 2020
+Tue Aug 4 07:23:45 CEST 2020
# Translators:
# 411370735b8ef90fa32c21e58a50941e_d905c03 <7784313cf022f885419b74f26eaf98f3_541595>, 2016-2017
# set_killer <mettall@abv.bg>, 2014
+# Nik Dim <lilo@abv.bg>, 2020
# ubone <van_ds_ff@mail.bg>, 2016
# set_killer <mettall@abv.bg>, 2014
# ubone <van_ds_ff@mail.bg>, 2016
"Project-Id-Version: Xonotic\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-07 07:23+0200\n"
-"PO-Revision-Date: 2020-06-07 05:23+0000\n"
-"Last-Translator: divVerent <divVerent@xonotic.org>\n"
+"PO-Revision-Date: 2020-07-29 08:59+0000\n"
+"Last-Translator: Nik Dim <lilo@abv.bg>\n"
"Language-Team: Bulgarian (http://www.transifex.com/team-xonotic/xonotic/"
"language/bg/)\n"
"Language: bg\n"
#: qcsrc/client/hud/panel/infomessages.qc:108
#: qcsrc/menu/xonotic/keybinder.qc:47
msgid "primary fire"
-msgstr ""
+msgstr "Основна стрелба"
#: qcsrc/client/hud/panel/infomessages.qc:110
#, c-format
#: qcsrc/client/hud/panel/infomessages.qc:116
#: qcsrc/menu/xonotic/keybinder.qc:48
msgid "secondary fire"
-msgstr ""
+msgstr "Второстепенна стрелба"
#: qcsrc/client/hud/panel/infomessages.qc:119
#, c-format
#: qcsrc/client/hud/panel/infomessages.qc:217
msgid "^1Spectating this player:"
-msgstr ""
+msgstr "^1Наблюдаващи този играч:"
#: qcsrc/client/hud/panel/infomessages.qc:217
msgid "^1Spectating you:"
-msgstr ""
+msgstr "^1Наблюдаващи теб:"
#: qcsrc/client/hud/panel/infomessages.qc:233
msgid "^7Press ^3ESC ^7to show HUD options."
#: qcsrc/client/hud/panel/quickmenu.qc:787
#: qcsrc/client/hud/panel/quickmenu.qc:794
msgid "Chat"
-msgstr ""
+msgstr "Чат"
#: qcsrc/client/hud/panel/quickmenu.qc:788
msgid "QMCMD^Send public message to"
#: qcsrc/client/hud/panel/quickmenu.qc:790
msgid "QMCMD^good game"
-msgstr ""
+msgstr "QMCMD^добра игра"
#: qcsrc/client/hud/panel/quickmenu.qc:791
msgid "QMCMD^hi / good luck"
#: qcsrc/client/hud/panel/quickmenu.qc:798
#: qcsrc/client/hud/panel/quickmenu.qc:814
msgid "QMCMD^Team chat"
-msgstr ""
+msgstr "QMCMD^Отборен чат"
#: qcsrc/client/hud/panel/quickmenu.qc:799
msgid "QMCMD^strength soon"
#: qcsrc/client/hud/panel/quickmenu.qc:802
msgid "QMCMD^negative"
-msgstr ""
+msgstr "QMCMD^отрицателен"
#: qcsrc/client/hud/panel/quickmenu.qc:803
msgid "QMCMD^positive"
-msgstr ""
+msgstr "QMCMD^положителен"
#: qcsrc/client/hud/panel/quickmenu.qc:804
msgid "QMCMD^need help (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
#: qcsrc/client/hud/panel/quickmenu.qc:817
msgid "QMCMD^Send private message to"
-msgstr ""
+msgstr "QMCMD^Изпрати лично съобщение до"
#: qcsrc/client/hud/panel/quickmenu.qc:819
#: qcsrc/client/hud/panel/quickmenu.qc:849
msgid "QMCMD^Settings"
-msgstr ""
+msgstr "QMCMD^Настройки"
#: qcsrc/client/hud/panel/quickmenu.qc:820
#: qcsrc/client/hud/panel/quickmenu.qc:827
#: qcsrc/client/hud/panel/quickmenu.qc:842
msgid "QMCMD^Increase speed"
-msgstr ""
+msgstr "QMCMD^Увеличи скоростта"
#: qcsrc/client/hud/panel/quickmenu.qc:843
msgid "QMCMD^Decrease speed"
-msgstr ""
+msgstr "QMCMD^Намали скоростта"
#: qcsrc/client/hud/panel/quickmenu.qc:844
msgid "QMCMD^Wall collision"
#: qcsrc/client/hud/panel/quickmenu.qc:848
msgid "QMCMD^Fullscreen"
-msgstr ""
+msgstr "QMCMD^Цял екран"
#: qcsrc/client/hud/panel/quickmenu.qc:851
#: qcsrc/client/hud/panel/quickmenu.qc:861
#: qcsrc/client/hud/panel/quickmenu.qc:852
msgid "QMCMD^Restart the map"
-msgstr ""
+msgstr "QMCMD^Рестартиране на картата"
#: qcsrc/client/hud/panel/quickmenu.qc:853
msgid "QMCMD^End match"
#: qcsrc/client/hud/panel/racetimer.qc:159 qcsrc/client/main.qc:1102
msgid "missing a checkpoint"
-msgstr ""
+msgstr "пропуснат чекпойнт"
#: qcsrc/client/hud/panel/radar.qc:386
msgid "Click to select teleport destination"
#: qcsrc/client/hud/panel/scoreboard.qc:109
msgid "Number of deaths"
-msgstr ""
+msgstr "Брой умирания"
#: qcsrc/client/hud/panel/scoreboard.qc:109
msgid "SCO^deaths"
#: qcsrc/client/hud/panel/scoreboard.qc:111
msgid "The total damage done"
-msgstr ""
+msgstr "Общa нанесена щета"
#: qcsrc/client/hud/panel/scoreboard.qc:112
msgid "SCO^dmgtaken"
#: qcsrc/client/hud/panel/scoreboard.qc:119
msgid "Number of kills minus suicides"
-msgstr ""
+msgstr "Брой убийства без самоубийствата"
#: qcsrc/client/hud/panel/scoreboard.qc:119
msgid "SCO^frags"
#: qcsrc/client/hud/panel/scoreboard.qc:125
msgid "Number of kills"
-msgstr ""
+msgstr "Брой убийства"
#: qcsrc/client/hud/panel/scoreboard.qc:125
msgid "SCO^kills"
#: qcsrc/client/hud/panel/scoreboard.qc:128
msgid "Number of times a key was lost"
-msgstr ""
+msgstr "Колко пъти ключа е бил изгубен"
#: qcsrc/client/hud/panel/scoreboard.qc:128
msgid "SCO^losses"
#: qcsrc/client/hud/panel/scoreboard.qc:129
#: qcsrc/client/hud/panel/scoreboard.qc:130
msgid "Player name"
-msgstr ""
+msgstr "Име на играч"
#: qcsrc/client/hud/panel/scoreboard.qc:129
msgid "SCO^name"
#: qcsrc/client/hud/panel/scoreboard.qc:131
msgid "Number of objectives destroyed"
-msgstr ""
+msgstr "Брой унищожени цели"
#: qcsrc/client/hud/panel/scoreboard.qc:131
msgid "SCO^objectives"
#: qcsrc/client/hud/panel/scoreboard.qc:134
msgid "Packet loss"
-msgstr ""
+msgstr "Загубени пакети"
#: qcsrc/client/hud/panel/scoreboard.qc:134
msgid "SCO^pl"
#: qcsrc/client/hud/panel/scoreboard.qc:138
msgid "Number of revivals"
-msgstr ""
+msgstr "Брой съживявания"
#: qcsrc/client/hud/panel/scoreboard.qc:138
msgid "SCO^revivals"
#: qcsrc/client/hud/panel/scoreboard.qc:139
msgid "Number of rounds won"
-msgstr ""
+msgstr "Брой спечелени рундове"
#: qcsrc/client/hud/panel/scoreboard.qc:139
msgid "SCO^rounds won"
-msgstr ""
+msgstr "SCO^спечелени рундове"
#: qcsrc/client/hud/panel/scoreboard.qc:140
msgid "SCO^score"
#: qcsrc/client/hud/panel/scoreboard.qc:140
msgid "Total score"
-msgstr ""
+msgstr "Общ резултат"
#: qcsrc/client/hud/panel/scoreboard.qc:141
msgid "Number of suicides"
#: qcsrc/client/hud/panel/scoreboard.qc:331
msgid "Usage:"
-msgstr ""
+msgstr "Употреба:"
#: qcsrc/client/hud/panel/scoreboard.qc:333
msgid "^2scoreboard_columns_set ^3field1 field2 ..."
#: qcsrc/client/hud/panel/timer.qc:72
msgid "WARMUP"
-msgstr ""
+msgstr "ЗАГРЯВКА"
#: qcsrc/client/hud/panel/vote.qc:33
msgid "^1You must answer before entering hud configure mode"
#: qcsrc/common/items/item/armor.qh:42
msgid "Small armor"
-msgstr ""
+msgstr "Малка броня"
#: qcsrc/common/items/item/armor.qh:80
msgid "Medium armor"
-msgstr ""
+msgstr "Средна броня"
#: qcsrc/common/items/item/armor.qh:118 qcsrc/common/items/item/armor.qh:121
msgid "Big armor"
-msgstr ""
+msgstr "Голяма броня"
#: qcsrc/common/items/item/armor.qh:158 qcsrc/common/items/item/armor.qh:161
msgid "Mega armor"
-msgstr ""
+msgstr "Мега броня"
#: qcsrc/common/items/item/health.qh:42
msgid "Small health"
-msgstr ""
+msgstr "Малка аптечка"
#: qcsrc/common/items/item/health.qh:80
msgid "Medium health"
-msgstr ""
+msgstr "Средна аптечка"
#: qcsrc/common/items/item/health.qh:118 qcsrc/common/items/item/health.qh:121
msgid "Big health"
-msgstr ""
+msgstr "Голяма аптечка"
#: qcsrc/common/items/item/health.qh:158 qcsrc/common/items/item/health.qh:161
msgid "Mega health"
-msgstr ""
+msgstr "Мега аптечка"
#: qcsrc/common/items/item/jetpack.qh:38 qcsrc/common/items/item/jetpack.qh:41
#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:91
#: qcsrc/common/mapinfo.qh:590
msgid "Duel"
-msgstr ""
+msgstr "Дуел"
#: qcsrc/common/mapinfo.qh:590
msgid "Fight in a one versus one arena battle to decide the winner"
#: qcsrc/common/minigames/minigame/pong.qc:589
#: qcsrc/common/minigames/minigame/ttt.qc:299
msgid "AI"
-msgstr ""
+msgstr "ИИ"
#: qcsrc/common/minigames/minigame/pong.qc:606
msgid "Press ^1Start Match^7 to start the match with the current players"
#: qcsrc/common/minigames/minigame/ttt.qc:672
msgid "Single Player"
-msgstr ""
+msgstr "Солова Игра"
#: qcsrc/common/monsters/monster/mage.qh:17
#: qcsrc/menu/xonotic/dialog_monstertools.qc:18
#: qcsrc/common/mutators/mutator/buffs/all.inc:87
msgid "Jump"
-msgstr ""
+msgstr "Скок"
#: qcsrc/common/mutators/mutator/buffs/all.inc:96
msgid "Invisible"
#: qcsrc/common/mutators/mutator/buffs/all.inc:129
msgid "Luck"
-msgstr ""
+msgstr "Късмет"
#: qcsrc/common/mutators/mutator/buffs/all.inc:137
msgid "Flight"
#: qcsrc/common/mutators/mutator/nades/nades.inc:18
msgid "Napalm grenade"
-msgstr ""
+msgstr "Напалмова граната"
#: qcsrc/common/mutators/mutator/nades/nades.inc:26
msgid "Ice grenade"
-msgstr ""
+msgstr "Ледена граната"
#: qcsrc/common/mutators/mutator/nades/nades.inc:34
msgid "Translocate grenade"
#: qcsrc/common/mutators/mutator/nades/nades.qh:33
msgid "Grenade"
-msgstr ""
+msgstr "Граната"
#: qcsrc/common/mutators/mutator/overkill/okhmg.qh:20
msgid "Overkill Heavy Machine Gun"
#: qcsrc/common/notifications/all.inc:561
msgid "^BGYou got the flag!"
-msgstr ""
+msgstr "^BGТи взе флага!"
#: qcsrc/common/notifications/all.inc:562
#, c-format
msgid "^BGYou got your %steam^BG's flag, return it!"
-msgstr ""
+msgstr "^BGТи взе твоя %s team^BG's флаг, върни го!"
#: qcsrc/common/notifications/all.inc:563
#, c-format
#: qcsrc/common/notifications/all.qh:419
msgid "point"
-msgstr ""
+msgstr "точка"
#: qcsrc/common/notifications/all.qh:419
msgid "points"
-msgstr ""
+msgstr "точки"
#: qcsrc/common/notifications/all.qh:428
msgid "drop flag"
#: qcsrc/common/util.qc:1451 qcsrc/common/util.qc:1508
#, c-format
msgid "UPARROW"
-msgstr ""
+msgstr "СТРЕЛКА НАГОРЕ"
#: qcsrc/common/util.qc:1452 qcsrc/common/util.qc:1503
#, c-format
msgid "DOWNARROW"
-msgstr ""
+msgstr "СТРЕЛКА НАДОЛУ"
#: qcsrc/common/util.qc:1453 qcsrc/common/util.qc:1505
#, c-format
msgid "LEFTARROW"
-msgstr ""
+msgstr "СТРЕЛКА НАЛЯВО"
#: qcsrc/common/util.qc:1454 qcsrc/common/util.qc:1506
#, c-format
msgid "RIGHTARROW"
-msgstr ""
+msgstr "СТРЕЛКА НАДЯСНО"
#: qcsrc/common/util.qc:1456
msgid "ALT"
#: qcsrc/common/util.qc:1477
msgid "APOSTROPHE"
-msgstr ""
+msgstr "АПОСТРОФ"
#: qcsrc/common/util.qc:1478
msgid "BACKSLASH"
#: qcsrc/common/util.qc:1510
#, c-format
msgid "PERIOD"
-msgstr ""
+msgstr "ТОЧКА"
#: qcsrc/common/util.qc:1512
#, c-format
#: qcsrc/common/util.qc:1515
#, c-format
msgid "MINUS"
-msgstr ""
+msgstr "МИНУС"
#: qcsrc/common/util.qc:1516
#, c-format
msgid "PLUS"
-msgstr ""
+msgstr "ПЛЮС"
#: qcsrc/common/util.qc:1518
#, c-format
msgid "EQUALS"
-msgstr ""
+msgstr "РАВНО"
#: qcsrc/common/util.qc:1523
msgid "PRINTSCREEN"
#: qcsrc/common/util.qc:1546
#, c-format
msgid "START"
-msgstr ""
+msgstr "СТАРТ"
#: qcsrc/common/util.qc:1547
#, c-format
#: qcsrc/common/util.qc:1571
#, c-format
msgid "UP"
-msgstr ""
+msgstr "НАГОРЕ"
#: qcsrc/common/util.qc:1572
#, c-format
#: qcsrc/menu/xonotic/credits.qc:158
msgid "Bulgarian"
-msgstr ""
+msgstr "Български"
#: qcsrc/menu/xonotic/credits.qc:165
msgid "Chinese (China)"
#: qcsrc/menu/xonotic/credits.qc:179
msgid "Czech"
-msgstr ""
+msgstr "Чешки"
#: qcsrc/menu/xonotic/credits.qc:184
msgid "Dutch"
#: qcsrc/menu/xonotic/credits.qc:201
msgid "French"
-msgstr ""
+msgstr "Френски"
#: qcsrc/menu/xonotic/credits.qc:209
msgid "German"
-msgstr ""
+msgstr "Немски"
#: qcsrc/menu/xonotic/credits.qc:220
msgid "Greek"
-msgstr ""
+msgstr "Гръцки"
#: qcsrc/menu/xonotic/credits.qc:226
msgid "Hungarian"
-msgstr ""
+msgstr "Унгарски"
#: qcsrc/menu/xonotic/credits.qc:230
msgid "Irish"
#: qcsrc/menu/xonotic/credits.qc:233
msgid "Italian"
-msgstr ""
+msgstr "Италиански"
#: qcsrc/menu/xonotic/credits.qc:239
msgid "Kazakh"
#: qcsrc/menu/xonotic/credits.qc:242
msgid "Korean"
-msgstr ""
+msgstr "Корейски"
#: qcsrc/menu/xonotic/credits.qc:246
msgid "Polish"
-msgstr ""
+msgstr "Полски"
#: qcsrc/menu/xonotic/credits.qc:254
msgid "Portuguese"
#: qcsrc/menu/xonotic/credits.qc:260
msgid "Romanian"
-msgstr ""
+msgstr "Румънски"
#: qcsrc/menu/xonotic/credits.qc:267
msgid "Russian"
-msgstr ""
+msgstr "Руски"
#: qcsrc/menu/xonotic/credits.qc:278
msgid "Scottish Gaelic"
#: qcsrc/menu/xonotic/credits.qc:281
msgid "Serbian"
-msgstr ""
+msgstr "Сръбски"
#: qcsrc/menu/xonotic/credits.qc:287
msgid "Spanish"
-msgstr ""
+msgstr "Испански"
#: qcsrc/menu/xonotic/credits.qc:298
msgid "Swedish"
#: qcsrc/menu/xonotic/credits.qc:302
msgid "Ukrainian"
-msgstr ""
+msgstr "Украински"
#: qcsrc/menu/xonotic/credits.qc:309
msgid "Past Contributors"
#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:40
#: qcsrc/menu/xonotic/dialog_settings_misc.qc:60
msgid "Unlimited"
-msgstr ""
+msgstr "Неограничен"
#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:74
msgid "Gametype"
#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:142
msgid "Previous"
-msgstr ""
+msgstr "Предходен"
#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:145
msgid "Next"
-msgstr ""
+msgstr "Следващ"
#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:150
msgid "Slide show"
#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:156
msgid "Select language..."
-msgstr ""
+msgstr "Избери език..."
#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:172
msgid "Gender:"
#: qcsrc/menu/xonotic/keybinder.qc:56
msgid "reload"
-msgstr ""
+msgstr "презареждане"
#: qcsrc/menu/xonotic/keybinder.qc:57
msgid "drop weapon / throw nade"
#: qcsrc/menu/xonotic/keybinder.qc:102
msgid "Client"
-msgstr ""
+msgstr "Клиент"
#: qcsrc/menu/xonotic/keybinder.qc:106 qcsrc/menu/xonotic/keybinder.qc:108
msgid "enter console"
#: 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:46
#, no-c-format
"Project-Id-Version: Xonotic\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-07 07:23+0200\n"
-"PO-Revision-Date: 2020-07-24 22:50+0000\n"
+"PO-Revision-Date: 2020-07-31 22:16+0000\n"
"Last-Translator: LegendGuard\n"
"Language-Team: Catalan (http://www.transifex.com/team-xonotic/xonotic/"
"language/ca/)\n"
"or in all but these game types. You can also specify 'all' as a\n"
"field to show all fields available for the current game mode."
msgstr ""
+"Després d'un camp pots posar un signe + o -, i després una llista de \n"
+"tipus de joc separats per comes, després una barra diagonal, per fer \n"
+"que el camp es mostri només en aquests o en tots menys en aquests \n"
+"tipus de jocs. També pots especificar 'all' com a camp per a mostrar \n"
+"tots els camps disponibles per a la manera de joc actual."
#: qcsrc/client/hud/panel/scoreboard.qc:350
msgid ""
"The special game type names 'teams' and 'noteams' can be used to\n"
"include/exclude ALL teams/noteams game modes."
msgstr ""
+"Els noms especials de tipus de joc 'teams' i 'noteams' poden ser \n"
+"utilitzats per a incloure/excloure TOTS els modes de joc teams/noteams."
#: qcsrc/client/hud/panel/scoreboard.qc:354
msgid "Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4"
-msgstr ""
+msgstr "Exemple: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4"
#: qcsrc/client/hud/panel/scoreboard.qc:355
msgid ""
"will display name, ping and pl aligned to the left, and the fields\n"
"right of the vertical bar aligned to the right."
msgstr ""
+"mostrarà el nom, ping i pl alineats a l'esquerra, i els camps a la \n"
+"dreta de la barra vertical alineada a la dreta."
#: qcsrc/client/hud/panel/scoreboard.qc:357
msgid ""
"'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
"other gamemodes except DM."
msgstr ""
+"'field3' només serà mostrat en CTF, i 'field4' serà mostrat en tots \n"
+"els altres modes de joc excepte DM."
#: qcsrc/client/hud/panel/scoreboard.qc:621
#: qcsrc/client/hud/panel/scoreboard.qc:628
#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:164
#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:169
msgid "N/A"
-msgstr ""
+msgstr "N/A"
#: qcsrc/client/hud/panel/scoreboard.qc:1206
#, c-format
msgid "Accuracy stats (average %d%%)"
-msgstr ""
+msgstr "Estadístiques de precisió (mitjana %d%%)"
#: qcsrc/client/hud/panel/scoreboard.qc:1354
msgid "Map stats:"
-msgstr ""
+msgstr "Estadístiques de mapa:"
#: qcsrc/client/hud/panel/scoreboard.qc:1384
msgid "Monsters killed:"
-msgstr ""
+msgstr "Monstres assassinats:"
#: qcsrc/client/hud/panel/scoreboard.qc:1391
msgid "Secrets found:"
-msgstr ""
+msgstr "Secrets trobats:"
#: qcsrc/client/hud/panel/scoreboard.qc:1413
msgid "Capture time rankings"
-msgstr ""
+msgstr "Classificacions de temps de captura"
#: qcsrc/client/hud/panel/scoreboard.qc:1413
msgid "Rankings"
-msgstr ""
+msgstr "Classificacions"
#: qcsrc/client/hud/panel/scoreboard.qc:1631
#, c-format
msgid "^3%1.0f minutes"
-msgstr ""
+msgstr "^3%1.0f minuts"
#: qcsrc/client/hud/panel/scoreboard.qc:1640
#: qcsrc/client/hud/panel/scoreboard.qc:1647
#, c-format
msgid "^5%s %s"
-msgstr ""
+msgstr "^5%s %s"
#: qcsrc/client/hud/panel/scoreboard.qc:1641
#: qcsrc/client/hud/panel/scoreboard.qc:1648
#: qcsrc/client/hud/panel/scoreboard.qc:1667
#: qcsrc/client/hud/panel/scoreboard.qc:1674
msgid "SCO^points"
-msgstr ""
+msgstr "punts"
#: qcsrc/client/hud/panel/scoreboard.qc:1666
#: qcsrc/client/hud/panel/scoreboard.qc:1673
#, c-format
msgid "^2+%s %s"
-msgstr ""
+msgstr "^2+%s %s"
#: qcsrc/client/hud/panel/scoreboard.qc:1684
#, c-format
msgid "^7Map: ^2%s"
-msgstr ""
+msgstr "^7Mapa: ^2%s"
#: qcsrc/client/hud/panel/scoreboard.qc:1823
#, c-format
msgid "Speed award: %d%s ^7(%s^7)"
-msgstr ""
+msgstr "Premi de velocitat: %d%s ^7(%s^7)"
#: qcsrc/client/hud/panel/scoreboard.qc:1827
#, c-format
msgid "All-time fastest: %d%s ^7(%s^7)"
-msgstr ""
+msgstr "El més ràpid de tots els temps: %d%s ^7(%s^7)"
#: qcsrc/client/hud/panel/scoreboard.qc:1843
#, c-format
msgid "Spectators"
-msgstr ""
+msgstr "Espectadors"
#: qcsrc/client/hud/panel/scoreboard.qc:1870
#, c-format
msgid "^1Respawning in ^3%s^1..."
-msgstr ""
+msgstr "^1Reapareixent en ^3%s^1..."
#: qcsrc/client/hud/panel/scoreboard.qc:1880
#, c-format
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+msgid ""
+msgstr ""
+"Project-Id-Version: Xonotic\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-06-07 07:23+0200\n"
+"PO-Revision-Date: 2013-09-12 16:53+0000\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: Danish (http://www.transifex.com/team-xonotic/xonotic/"
+"language/da/)\n"
+"Language: da\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: qcsrc/client/hud/hud_config.qc:81
+#, c-format
+msgid "^2Successfully exported to %s! (Note: It's saved in data/data/)"
+msgstr ""
+
+#: qcsrc/client/hud/hud_config.qc:85
+#, c-format
+msgid "^1Couldn't write to %s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/centerprint.qc:174
+#, c-format
+msgid "^3Countdown message at time %s, seconds left: ^COUNT"
+msgstr ""
+
+#: qcsrc/client/hud/panel/centerprint.qc:176
+#, c-format
+msgid ""
+"^1Multiline message at time %s that\n"
+"^1lasts longer than normal"
+msgstr ""
+
+#: qcsrc/client/hud/panel/centerprint.qc:178
+#, c-format
+msgid "Message at time %s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/centerprint.qc:183
+msgid "Generic message"
+msgstr ""
+
+#: qcsrc/client/hud/panel/chat.qc:89
+msgid "^3Player^7: This is the chat area."
+msgstr ""
+
+#: qcsrc/client/hud/panel/engineinfo.qc:76
+#, c-format
+msgid "FPS: %.*f"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:95
+msgid "^1Observing"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:97
+#, c-format
+msgid "^1Spectating: ^7%s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:108
+#, c-format
+msgid "^1Press ^3%s^1 to spectate"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:108
+#: qcsrc/menu/xonotic/keybinder.qc:47
+msgid "primary fire"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:110
+#, c-format
+msgid "^1Press ^3%s^1 or ^3%s^1 for next or previous player"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:110
+#: qcsrc/client/hud/panel/infomessages.qc:114
+msgid "next weapon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:110
+#: qcsrc/client/hud/panel/infomessages.qc:114
+msgid "previous weapon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:114
+#, c-format
+msgid "^1Use ^3%s^1 or ^3%s^1 to change the speed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:116
+#, c-format
+msgid "^1Press ^3%s^1 to observe, ^3%s^1 to change camera mode"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:116
+#: qcsrc/common/vehicles/cl_vehicles.qc:190
+msgid "drop weapon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:116
+#: qcsrc/menu/xonotic/keybinder.qc:48
+msgid "secondary fire"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:119
+#, c-format
+msgid "^1Press ^3%s^1 for gamemode info"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:119
+#: qcsrc/menu/xonotic/keybinder.qc:103
+msgid "server info"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:132
+msgid "^1Match has already begun"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:134
+msgid "^1You have no more lives left"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:136
+#: qcsrc/client/hud/panel/infomessages.qc:139
+#, c-format
+msgid "^1Press ^3%s^1 to join"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:136
+#: qcsrc/client/hud/panel/infomessages.qc:139
+#: qcsrc/common/notifications/all.qh:430
+msgid "jump"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:147
+#, c-format
+msgid "^1Game starts in ^3%d^1 seconds"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:153
+msgid "^2Currently in ^1warmup^2 stage!"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:168
+#, c-format
+msgid "%sPress ^3%s%s to end warmup"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:168
+#: qcsrc/client/hud/panel/infomessages.qc:170
+#: qcsrc/client/hud/panel/infomessages.qc:183
+#: qcsrc/menu/xonotic/keybinder.qc:99
+msgid "ready"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:170
+#, c-format
+msgid "%sPress ^3%s%s once you are ready"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:175
+msgid "^2Waiting for others to ready up to end warmup..."
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:177
+msgid "^2Waiting for others to ready up..."
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:183
+#, c-format
+msgid "^2Press ^3%s^2 to end warmup"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:204
+msgid "Teamnumbers are unbalanced!"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:207
+#, c-format
+msgid " Press ^3%s%s to adjust"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:207
+#: qcsrc/menu/xonotic/keybinder.qc:115
+msgid "team menu"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:217
+msgid "^1Spectating this player:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:217
+msgid "^1Spectating you:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:233
+msgid "^7Press ^3ESC ^7to show HUD options."
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:234
+msgid "^3Doubleclick ^7a panel for panel-specific options."
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:235
+msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:236
+msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."
+msgstr ""
+
+#: qcsrc/client/hud/panel/modicons.qc:183
+msgid "Personal best"
+msgstr ""
+
+#: qcsrc/client/hud/panel/modicons.qc:193
+msgid "Server best"
+msgstr ""
+
+#: qcsrc/client/hud/panel/notify.qc:127 qcsrc/client/hud/panel/notify.qc:128
+#: qcsrc/client/hud/panel/score.qc:69
+#, c-format
+msgid "Player %d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:597
+#: qcsrc/client/hud/panel/quickmenu.qc:599
+#, c-format
+msgid "Submenu%d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:604
+#, c-format
+msgid "Command%d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:630
+msgid "Continue..."
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:787
+#: qcsrc/client/hud/panel/quickmenu.qc:794
+msgid "Chat"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:788
+msgid "QMCMD^Send public message to"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:789
+msgid "QMCMD^:-) / nice one"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:789
+msgid "QMCMD^nice one"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:790
+msgid "QMCMD^good game"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:791
+msgid "QMCMD^hi / good luck"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:791
+msgid "QMCMD^hi / good luck and have fun"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:793
+msgid "QMCMD^Send in English"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:798
+#: qcsrc/client/hud/panel/quickmenu.qc:814
+msgid "QMCMD^Team chat"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:799
+msgid "QMCMD^strength soon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:800
+msgid "QMCMD^free item %x^7 (l:%y^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:800
+msgid "QMCMD^free item, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:801
+msgid "QMCMD^took item (l:%l^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:801
+msgid "QMCMD^took item, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:802
+msgid "QMCMD^negative"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:803
+msgid "QMCMD^positive"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:804
+msgid "QMCMD^need help (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:804
+msgid "QMCMD^need help, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:805
+msgid "QMCMD^enemy seen (l:%y^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:805
+msgid "QMCMD^enemy seen, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:806
+msgid "QMCMD^flag seen (l:%y^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:806
+msgid "QMCMD^flag seen, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:807
+msgid "QMCMD^defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:807
+msgid "QMCMD^defending, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:808
+msgid "QMCMD^roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:808
+msgid "QMCMD^roaming, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:809
+msgid "QMCMD^attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:809
+msgid "QMCMD^attacking, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:810
+msgid "QMCMD^killed flagcarrier (l:%y^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:810
+msgid "QMCMD^killed flagcarrier, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:811
+#, c-format
+msgid "QMCMD^dropped flag (l:%d^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:811
+msgid "QMCMD^dropped flag, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:812
+msgid "QMCMD^drop weapon, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:812
+msgid "QMCMD^dropped weapon %w^7 (l:%l^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:813
+msgid "QMCMD^drop flag/key, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:813
+msgid "QMCMD^dropped flag/key %w^7 (l:%l^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:817
+msgid "QMCMD^Send private message to"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:819
+#: qcsrc/client/hud/panel/quickmenu.qc:849
+msgid "QMCMD^Settings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:820
+#: qcsrc/client/hud/panel/quickmenu.qc:827
+msgid "QMCMD^View/HUD settings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:821
+msgid "QMCMD^3rd person view"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:822
+msgid "QMCMD^Player models like mine"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:823
+msgid "QMCMD^Names above players"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:824
+msgid "QMCMD^Crosshair per weapon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:825
+msgid "QMCMD^FPS"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:826
+msgid "QMCMD^Net graph"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:829
+#: qcsrc/client/hud/panel/quickmenu.qc:832
+msgid "QMCMD^Sound settings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:830
+msgid "QMCMD^Hit sound"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:831
+msgid "QMCMD^Chat sound"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:836
+msgid "QMCMD^Change spectator camera"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:841
+#: qcsrc/client/hud/panel/quickmenu.qc:845
+msgid "QMCMD^Observer camera"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:842
+msgid "QMCMD^Increase speed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:843
+msgid "QMCMD^Decrease speed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:844
+msgid "QMCMD^Wall collision"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:848
+msgid "QMCMD^Fullscreen"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:851
+#: qcsrc/client/hud/panel/quickmenu.qc:861
+msgid "QMCMD^Call a vote"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:852
+msgid "QMCMD^Restart the map"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:853
+msgid "QMCMD^End match"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:856
+msgid "QMCMD^Reduce match time"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:857
+msgid "QMCMD^Extend match time"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:860
+msgid "QMCMD^Shuffle teams"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:865
+msgid "QMCMD^Spectate a player"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:59
+#, c-format
+msgid " (-%dL)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:64
+#, c-format
+msgid " (+%dL)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:83
+msgid "Start line"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:85
+#: qcsrc/client/hud/panel/racetimer.qc:89
+msgid "Finish line"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:87
+#: qcsrc/client/hud/panel/racetimer.qc:156
+#, c-format
+msgid "Intermediate %d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:159
+#: qcsrc/client/hud/panel/racetimer.qc:206
+#: qcsrc/client/hud/panel/racetimer.qc:267
+#, c-format
+msgid "PENALTY: %.1f (%s)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:159 qcsrc/client/main.qc:1102
+msgid "missing a checkpoint"
+msgstr ""
+
+#: qcsrc/client/hud/panel/radar.qc:386
+msgid "Click to select teleport destination"
+msgstr ""
+
+#: qcsrc/client/hud/panel/radar.qc:390
+msgid "Click to select spawn location"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:105
+msgid "Number of ball carrier kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:105
+msgid "SCO^bckills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:106
+msgid "SCO^bctime"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:106
+msgid "Total amount of time holding the ball in Keepaway"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:107
+msgid "How often a flag (CTF) or a key (KeyHunt) was captured"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:107
+msgid "SCO^caps"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:108
+msgid "SCO^captime"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:108
+msgid "Time of fastest capture (CTF)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:109
+msgid "Number of deaths"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:109
+msgid "SCO^deaths"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:110
+msgid "Number of keys destroyed by pushing them into void"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:110
+msgid "SCO^destroyed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:111
+msgid "SCO^damage"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:111
+msgid "The total damage done"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:112
+msgid "SCO^dmgtaken"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:112
+msgid "The total damage taken"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:113
+msgid "Number of flag drops"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:113
+msgid "SCO^drops"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:114
+msgid "Player ELO"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:114
+msgid "SCO^elo"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:115
+msgid "SCO^fastest"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:115
+msgid "Time of fastest lap (Race/CTS)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:116
+msgid "Number of faults committed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:116
+msgid "SCO^faults"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:117
+msgid "Number of flag carrier kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:117
+msgid "SCO^fckills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:118
+msgid "FPS"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:118
+msgid "SCO^fps"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:119
+msgid "Number of kills minus suicides"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:119
+msgid "SCO^frags"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:120
+msgid "Number of goals scored"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:120
+msgid "SCO^goals"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:121
+msgid "Number of keys carrier kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:121
+msgid "SCO^kckills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:122
+msgid "SCO^k/d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:122
+#: qcsrc/client/hud/panel/scoreboard.qc:123
+#: qcsrc/client/hud/panel/scoreboard.qc:124
+msgid "The kill-death ratio"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:123
+msgid "SCO^kdr"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:124
+msgid "SCO^kdratio"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:125
+msgid "Number of kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:125
+msgid "SCO^kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:126
+msgid "Number of laps finished (Race/CTS)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:126
+msgid "SCO^laps"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:127
+msgid "Number of lives (LMS)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:127
+msgid "SCO^lives"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:128
+msgid "Number of times a key was lost"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:128
+msgid "SCO^losses"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:129
+#: qcsrc/client/hud/panel/scoreboard.qc:130
+msgid "Player name"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:129
+msgid "SCO^name"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:130
+msgid "SCO^nick"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:131
+msgid "Number of objectives destroyed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:131
+msgid "SCO^objectives"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:132
+msgid ""
+"How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:132
+msgid "SCO^pickups"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:133
+msgid "Ping time"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:133
+msgid "SCO^ping"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:134
+msgid "Packet loss"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:134
+msgid "SCO^pl"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:135
+msgid "Number of players pushed into void"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:135
+msgid "SCO^pushes"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:136
+msgid "Player rank"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:136
+msgid "SCO^rank"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:137
+msgid "Number of flag returns"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:137
+msgid "SCO^returns"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:138
+msgid "Number of revivals"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:138
+msgid "SCO^revivals"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:139
+msgid "Number of rounds won"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:139
+msgid "SCO^rounds won"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:140
+msgid "SCO^score"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:140
+msgid "Total score"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:141
+msgid "Number of suicides"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:141
+msgid "SCO^suicides"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:142
+msgid "Number of kills minus deaths"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:142
+msgid "SCO^sum"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:143
+msgid "Number of domination points taken (Domination)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:143
+msgid "SCO^takes"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:144
+msgid "Number of teamkills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:144
+msgid "SCO^teamkills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:145
+msgid "Number of ticks (Domination)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:145
+msgid "SCO^ticks"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:146
+msgid "SCO^time"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:146
+msgid "Total time raced (Race/CTS)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:330
+msgid ""
+"You can modify the scoreboard using the ^2scoreboard_columns_set command."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:331
+msgid "Usage:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:333
+msgid "^2scoreboard_columns_set ^3field1 field2 ..."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:334
+msgid ""
+"^2scoreboard_columns_set ^7without arguments reads the arguments from the "
+"cvar scoreboard_columns"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:335
+msgid ""
+" ^5Note: ^7scoreboard_columns_set without arguments is executed on every "
+"map start"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:336
+msgid ""
+"^2scoreboard_columns_set ^3expand_default ^7loads default layout and expands "
+"it into the cvar scoreboard_columns so you can edit it"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:337
+msgid "You can use a ^3|^7 to start the right-aligned fields."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:338
+msgid "The following field names are recognized (case insensitive):"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:344
+msgid ""
+"Before a field you can put a + or - sign, then a comma separated list\n"
+"of game types, then a slash, to make the field show up only in these\n"
+"or in all but these game types. You can also specify 'all' as a\n"
+"field to show all fields available for the current game mode."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:350
+msgid ""
+"The special game type names 'teams' and 'noteams' can be used to\n"
+"include/exclude ALL teams/noteams game modes."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:354
+msgid "Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:355
+msgid ""
+"will display name, ping and pl aligned to the left, and the fields\n"
+"right of the vertical bar aligned to the right."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:357
+msgid ""
+"'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
+"other gamemodes except DM."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:621
+#: qcsrc/client/hud/panel/scoreboard.qc:628
+#: qcsrc/client/hud/panel/scoreboard.qc:680
+#: qcsrc/client/hud/panel/scoreboard.qc:691
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:46
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:47
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:121
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:164
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:169
+msgid "N/A"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1206
+#, c-format
+msgid "Accuracy stats (average %d%%)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1354
+msgid "Map stats:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1384
+msgid "Monsters killed:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1391
+msgid "Secrets found:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1413
+msgid "Capture time rankings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1413
+msgid "Rankings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1631
+#, c-format
+msgid "^3%1.0f minutes"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1640
+#: qcsrc/client/hud/panel/scoreboard.qc:1647
+#, c-format
+msgid "^5%s %s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1641
+#: qcsrc/client/hud/panel/scoreboard.qc:1648
+#: qcsrc/client/hud/panel/scoreboard.qc:1667
+#: qcsrc/client/hud/panel/scoreboard.qc:1674
+msgid "SCO^points"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1666
+#: qcsrc/client/hud/panel/scoreboard.qc:1673
+#, c-format
+msgid "^2+%s %s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1684
+#, c-format
+msgid "^7Map: ^2%s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1823
+#, c-format
+msgid "Speed award: %d%s ^7(%s^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1827
+#, c-format
+msgid "All-time fastest: %d%s ^7(%s^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1843
+#, c-format
+msgid "Spectators"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1870
+#, c-format
+msgid "^1Respawning in ^3%s^1..."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1880
+#, c-format
+msgid "You are dead, wait ^3%s^7 before respawning"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1889
+#, c-format
+msgid "You are dead, press ^2%s^7 to respawn"
+msgstr ""
+
+#: qcsrc/client/hud/panel/timer.qc:72
+msgid "WARMUP"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:33
+msgid "^1You must answer before entering hud configure mode"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:36
+msgid "^2Name ^7instead of \"^1Anonymous player^7\" in stats"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:122
+msgid "A vote has been called for:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:124
+msgid "Allow servers to store and display your name?"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:128
+msgid "^1Configure the HUD"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:132
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:19
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:82
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:18
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:18
+#: qcsrc/menu/xonotic/dialog_quit.qc:14
+#: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qc:14
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:26
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:16
+#: qcsrc/menu/xonotic/dialog_uid2name.qc:15
+msgid "Yes"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:134
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:22
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:83
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:21
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:21
+#: qcsrc/menu/xonotic/dialog_quit.qc:16
+#: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qc:17
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:29
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:17
+#: qcsrc/menu/xonotic/dialog_uid2name.qc:17
+msgid "No"
+msgstr ""
+
+#: qcsrc/client/hud/panel/weapons.qc:584
+msgid "Out of ammo"
+msgstr ""
+
+#: qcsrc/client/hud/panel/weapons.qc:588
+msgid "Don't have"
+msgstr ""
+
+#: qcsrc/client/hud/panel/weapons.qc:592
+msgid "Unavailable"
+msgstr ""
+
+#: qcsrc/client/main.qc:1000
+msgid " qu/s"
+msgstr ""
+
+#: qcsrc/client/main.qc:1002
+msgid " m/s"
+msgstr ""
+
+#: qcsrc/client/main.qc:1004
+msgid " km/h"
+msgstr ""
+
+#: qcsrc/client/main.qc:1006
+msgid " mph"
+msgstr ""
+
+#: qcsrc/client/main.qc:1008
+msgid " knots"
+msgstr ""
+
+#: qcsrc/client/main.qc:1255
+#, c-format
+msgid "%s (not bound)"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:59
+msgid " (1 vote)"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:61
+#, c-format
+msgid " (%d votes)"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:281
+msgid "Don't care"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:382
+msgid "Decide the gametype"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:382
+msgid "Vote for a map"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:399
+#, c-format
+msgid "%d seconds left"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:512
+msgid "mv_mapdownload: ^3You're not supposed to use this command on your own!"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:522
+msgid "^1Error:^7 Couldn't find pak index."
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:531
+msgid "Requesting preview..."
+msgstr ""
+
+#: qcsrc/client/miscfunctions.qc:111
+msgid "Trying to remove a team which is not in the teamlist!"
+msgstr ""
+
+#: qcsrc/client/view.qc:939
+msgid "Nade timer"
+msgstr ""
+
+#: qcsrc/client/view.qc:944
+msgid "Capture progress"
+msgstr ""
+
+#: qcsrc/client/view.qc:949
+msgid "Revival progress"
+msgstr ""
+
+#: qcsrc/common/command/generic.qc:156
+msgid "error creating curl handle"
+msgstr ""
+
+#: qcsrc/common/command/generic.qc:412
+msgid "Notification restart command only works with cl_cmd and sv_cmd."
+msgstr ""
+
+#: qcsrc/common/gamemodes/gamemode/nexball/weapon.qh:7
+msgid "Ball Stealer"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:66
+msgid "bullets"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:96
+msgid "cells"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:126
+msgid "plasma"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:156
+msgid "rockets"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:190
+msgid "shells"
+msgstr ""
+
+#: qcsrc/common/items/item/armor.qh:42
+msgid "Small armor"
+msgstr ""
+
+#: qcsrc/common/items/item/armor.qh:80
+msgid "Medium armor"
+msgstr ""
+
+#: qcsrc/common/items/item/armor.qh:118 qcsrc/common/items/item/armor.qh:121
+msgid "Big armor"
+msgstr ""
+
+#: qcsrc/common/items/item/armor.qh:158 qcsrc/common/items/item/armor.qh:161
+msgid "Mega armor"
+msgstr ""
+
+#: qcsrc/common/items/item/health.qh:42
+msgid "Small health"
+msgstr ""
+
+#: qcsrc/common/items/item/health.qh:80
+msgid "Medium health"
+msgstr ""
+
+#: qcsrc/common/items/item/health.qh:118 qcsrc/common/items/item/health.qh:121
+msgid "Big health"
+msgstr ""
+
+#: qcsrc/common/items/item/health.qh:158 qcsrc/common/items/item/health.qh:161
+msgid "Mega health"
+msgstr ""
+
+#: qcsrc/common/items/item/jetpack.qh:38 qcsrc/common/items/item/jetpack.qh:41
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:91
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:215
+msgid "Jetpack"
+msgstr ""
+
+#: qcsrc/common/items/item/jetpack.qh:71
+msgid "fuel"
+msgstr ""
+
+#: qcsrc/common/items/item/jetpack.qh:96
+msgid "Fuel regenerator"
+msgstr ""
+
+#: qcsrc/common/items/item/jetpack.qh:99
+msgid "Fuel regen"
+msgstr ""
+
+#: qcsrc/common/items/item/powerup.qh:43 qcsrc/common/items/item/powerup.qh:46
+msgid "Strength"
+msgstr ""
+
+#: qcsrc/common/items/item/powerup.qh:79 qcsrc/common/items/item/powerup.qh:82
+msgid "Shield"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qc:626
+#, no-c-format
+msgid "@!#%'n Tuba Throwing"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:72 qcsrc/common/mapinfo.qh:334
+#: qcsrc/common/mapinfo.qh:529
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:105
+msgid "Frag limit:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:72 qcsrc/common/mapinfo.qh:334
+#: qcsrc/common/mapinfo.qh:529
+msgid "The amount of frags needed before the match will end"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:115
+msgid "Deathmatch"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:115
+msgid "Score as many frags as you can"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:128
+msgid "Last Man Standing"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:128
+msgid "Survive and kill until the enemies have no lives left"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:137
+msgid "Lives:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:149
+msgid "Race"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:149
+msgid "Race against other players to the finish line"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:176
+msgid "Laps:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:189
+msgid "Race CTS"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:189
+msgid "Race for fastest time."
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:206 qcsrc/common/mapinfo.qh:257
+#: qcsrc/common/mapinfo.qh:373 qcsrc/common/mapinfo.qh:416
+#: qcsrc/common/mapinfo.qh:442 qcsrc/common/mapinfo.qh:462
+#: qcsrc/common/mapinfo.qh:582
+msgid "Point limit:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:219
+msgid "Help your team score the most frags against the enemy team"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:219
+msgid "Team Deathmatch"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:257 qcsrc/common/mapinfo.qh:373
+#: qcsrc/common/mapinfo.qh:416
+msgid "The amount of points needed before the match will end"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:271
+msgid "Capture the Flag"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:271
+msgid ""
+"Find and bring the enemy flag to your base to capture it, defend your base "
+"from the other team"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:289
+msgid "Capture limit:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:289
+msgid "The amount of captures needed before the match will end"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:306
+msgid "Clan Arena"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:306
+msgid "Kill all enemy teammates to win the round"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:350
+msgid "Capture and defend all the control points to win"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:350
+msgid "Domination"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:388
+msgid "Gather all the keys to win the round"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:388
+msgid "Key Hunt"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:428
+msgid "Assault"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:428
+msgid ""
+"Destroy obstacles to find and destroy the enemy power core before time runs "
+"out"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:452
+msgid "Capture control points to reach and destroy the enemy generator"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:452
+msgid "Onslaught"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:474
+msgid "Nexball"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:474
+msgid "Shoot and kick the ball into the enemies goal, keep your goal clean"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:488
+msgid "Goals:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:488
+msgid "The amount of goals needed before the match will end"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:501
+msgid "Freeze Tag"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:501
+msgid ""
+"Kill enemies to freeze them, stand next to frozen teammates to revive them; "
+"freeze all enemies to win"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:545
+msgid "Hold the ball to get points for kills"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:545
+msgid "Keepaway"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:560
+msgid "Invasion"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:560
+msgid "Survive against waves of monsters"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:590
+msgid "Duel"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:590
+msgid "Fight in a one versus one arena battle to decide the winner"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames.qc:383
+msgid "It's your turn"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:366
+#: qcsrc/menu/xonotic/dialog_quit.qh:6
+msgid "Quit"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:371
+msgid "Invite"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:410
+msgid "Current Game"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:435
+msgid "Exit Menu"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:447
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:16
+msgid "Create"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:450
+msgid "Join"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:526
+msgid "Minigames"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:587
+msgid "Minigame message"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:2
+msgid "Bulldozer"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1092
+#: qcsrc/common/minigames/minigame/ps.qc:421
+#: qcsrc/common/minigames/minigame/ps.qc:427
+msgid "Game over!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1095
+msgid "Well done! Click 'Next Level' to continue"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1162
+msgid "Better luck next time!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1167
+msgid "Tubular! Press \"Next Level\" to continue!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1169
+msgid "Wicked! Press \"Next Level\" to continue!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1173
+msgid "Press the space bar to change your currently selected tile"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1176
+msgid "Push the boulders onto the targets"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1403
+msgid "Next Level"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1404
+msgid "Restart"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1405
+msgid "Editor"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1406
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:37
+msgid "Save"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:2
+msgid "Connect Four"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:311
+#: qcsrc/common/minigames/minigame/c4.qc:317
+#: qcsrc/common/minigames/minigame/nmm.qc:491
+#: qcsrc/common/minigames/minigame/nmm.qc:497
+#: qcsrc/common/minigames/minigame/pp.qc:362
+#: qcsrc/common/minigames/minigame/pp.qc:368
+#, c-format
+msgid "%s^7 won the game!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:373
+#: qcsrc/common/minigames/minigame/pp.qc:438
+#: qcsrc/common/minigames/minigame/ttt.qc:319
+msgid "Draw"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:378
+#: qcsrc/common/minigames/minigame/nmm.qc:606
+#: qcsrc/common/minigames/minigame/pp.qc:444
+#: qcsrc/common/minigames/minigame/ttt.qc:326
+msgid "You lost the game!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:379
+#: qcsrc/common/minigames/minigame/nmm.qc:607
+#: qcsrc/common/minigames/minigame/pp.qc:445
+#: qcsrc/common/minigames/minigame/ttt.qc:327
+msgid "You win!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:383
+#: qcsrc/common/minigames/minigame/nmm.qc:611
+#: qcsrc/common/minigames/minigame/pp.qc:456
+#: qcsrc/common/minigames/minigame/ttt.qc:338
+msgid "Wait for your opponent to make their move"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:386
+#: qcsrc/common/minigames/minigame/nmm.qc:613
+#: qcsrc/common/minigames/minigame/pp.qc:459
+#: qcsrc/common/minigames/minigame/ttt.qc:341
+msgid "Click on the game board to place your piece"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/nmm.qc:7
+msgid "Nine Men's Morris"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/nmm.qc:615
+msgid ""
+"You can select one of your pieces to move it in one of the surrounding places"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/nmm.qc:617
+msgid "You can select one of your pieces to move it anywhere on the board"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/nmm.qc:619
+msgid "You can take one of the opponent's pieces"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:2
+msgid "Pong"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:589
+#: qcsrc/common/minigames/minigame/ttt.qc:299
+msgid "AI"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:606
+msgid "Press ^1Start Match^7 to start the match with the current players"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:679
+msgid "Start Match"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:680
+msgid "Add AI player"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:681
+msgid "Remove AI player"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:2
+msgid "Push-Pull"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:444
+#: qcsrc/common/minigames/minigame/ttt.qc:326
+msgid "Select \"^1Next Match^7\" on the menu for a rematch!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:445
+#: qcsrc/common/minigames/minigame/pp.qc:451
+#: qcsrc/common/minigames/minigame/ttt.qc:327
+#: qcsrc/common/minigames/minigame/ttt.qc:333
+msgid "Select \"^1Next Match^7\" on the menu to start a new match!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:452
+#: qcsrc/common/minigames/minigame/ttt.qc:334
+msgid "Wait for your opponent to confirm the rematch"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:587
+#: qcsrc/common/minigames/minigame/ttt.qc:671
+msgid "Next Match"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:2
+msgid "Peg Solitaire"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:414
+msgid "All pieces cleared!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:416
+msgid "Remaining pieces:"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:481
+#, c-format
+msgid "Pieces left: %s"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:491
+msgid "No more valid moves"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:494
+msgid "Well done, you win!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:497
+msgid "Jump a piece over another to capture it"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ttt.qc:2
+msgid "Tic Tac Toe"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ttt.qc:672
+msgid "Single Player"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/mage.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:18
+msgid "Mage"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/mage.qh:29
+msgid "Mage spike"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/shambler.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:17
+msgid "Shambler"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/spider.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:16
+msgid "Spider"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/spider.qh:28
+msgid "Spider attack"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/wyvern.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:19
+msgid "Wyvern"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/wyvern.qh:28
+msgid "Wyvern attack"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/zombie.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:15
+msgid "Zombie"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:16
+msgid "Ammo"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:25
+msgid "Resistance"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:34
+#: qcsrc/common/mutators/mutator/instagib/items.qh:126
+#: qcsrc/common/mutators/mutator/instagib/items.qh:129
+msgid "Speed"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:44
+msgid "Medic"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:54
+msgid "Bash"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:63
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:83
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:184
+msgid "Vampire"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:71
+msgid "Disability"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:79
+msgid "Vengeance"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:87
+msgid "Jump"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:96
+msgid "Invisible"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:105
+msgid "Inferno"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:113
+msgid "Swapper"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:121
+msgid "Magnet"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:129
+msgid "Luck"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:137
+msgid "Flight"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/buffs.qh:11
+msgid "Buff"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:8
+msgid "Damage text"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:18
+msgid "Draw damage numbers"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:20
+msgid "Font size minimum:"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:25
+msgid "Font size maximum:"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:30
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:55
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:102
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:60
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:109
+#: qcsrc/menu/xonotic/util.qc:775
+msgid "Color:"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:36
+msgid "Draw damage numbers for friendly fire"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/instagib/items.qh:33
+msgid "Vaporizer ammo"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/instagib/items.qh:59
+#: qcsrc/common/mutators/mutator/instagib/items.qh:62
+msgid "Extra life"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/instagib/items.qh:91
+#: qcsrc/common/mutators/mutator/instagib/items.qh:94
+msgid "Invisibility"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:18
+msgid "Napalm grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:26
+msgid "Ice grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:34
+msgid "Translocate grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:42
+msgid "Spawn grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:50
+msgid "Heal grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:58
+msgid "Monster grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:66
+msgid "Entrap grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:74
+msgid "Veil grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.qh:33
+msgid "Grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/okhmg.qh:20
+msgid "Overkill Heavy Machine Gun"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/okmachinegun.qh:18
+msgid "Overkill MachineGun"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/oknex.qh:19
+msgid "Overkill Nex"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/okrpc.qh:20
+msgid "Overkill Rocket Propelled Chainsaw"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/okshotgun.qh:18
+msgid "Overkill Shotgun"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:3
+msgid "Waypoint"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:4
+msgid "Help me!"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:5
+msgid "Here"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:6
+msgid "DANGER"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:8
+msgid "Frozen!"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:10
+msgid "Item"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:12
+msgid "Checkpoint"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:13
+#: qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc:240
+msgid "Finish"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:14
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:15
+#: qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc:240
+msgid "Start"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:17
+msgid "Defend"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:18
+msgid "Destroy"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:19
+msgid "Push"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:21
+msgid "Flag carrier"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:22
+msgid "Enemy carrier"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:23
+msgid "Dropped flag"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:24
+msgid "White base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:25
+msgid "Red base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:26
+msgid "Blue base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:27
+msgid "Yellow base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:28
+msgid "Pink base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:29
+msgid "Return flag here"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:31
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:32
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:33
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:34
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:35
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:51
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:52
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:53
+msgid "Control point"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:37
+msgid "Dropped key"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:38
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:40
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:41
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:42
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:43
+msgid "Key carrier"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:39
+msgid "Run here"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:45
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:48
+msgid "Ball"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:46
+msgid "Ball carrier"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:49
+msgid "Goal"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:54
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:55
+msgid "Generator"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:57
+msgid "Weapon"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:59
+msgid "Monster"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:61
+msgid "Vehicle"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:62
+msgid "Intruder!"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:64
+msgid "Tagged"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc:697
+#, c-format
+msgid "%s needing help!"
+msgstr ""
+
+#: qcsrc/common/net_notice.qc:90
+msgid "^1Server notices:"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:230
+msgid "^F4NOTE: ^BGSpectator chat is not sent to players during the match"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:232
+#, c-format
+msgid "^BG%s^BG captured the ^TC^TT^BG flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:233
+#, c-format
+msgid ""
+"^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds, breaking ^BG"
+"%s^BG's previous record of ^F2%s^BG seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:234
+#, c-format
+msgid "^BG%s^BG captured the flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:235
+#, c-format
+msgid "^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:236
+#, c-format
+msgid ""
+"^BG%s^BG captured the ^TC^TT^BG flag in ^F2%s^BG seconds, failing to break "
+"^BG%s^BG's previous record of ^F1%s^BG seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:237
+msgid "^BGThe ^TC^TT^BG flag was returned to base by its owner"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:238
+msgid "^BGThe flag was returned by its owner"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:239
+msgid "^BGThe ^TC^TT^BG flag was destroyed and returned to base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:240
+msgid "^BGThe flag was destroyed and returned to base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:241
+msgid "^BGThe ^TC^TT^BG flag was dropped in the base and returned itself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:242
+msgid "^BGThe flag was dropped in the base and returned itself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:243
+msgid ""
+"^BGThe ^TC^TT^BG flag fell somewhere it couldn't be reached and returned to "
+"base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:244
+msgid "^BGThe flag fell somewhere it couldn't be reached and returned to base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:245
+#, c-format
+msgid ""
+"^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned "
+"itself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:246
+#, c-format
+msgid ""
+"^BGThe flag became impatient after ^F1%.2f^BG seconds and returned itself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:247
+msgid "^BGThe ^TC^TT^BG flag has returned to the base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:248
+msgid "^BGThe flag has returned to the base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:249
+#, c-format
+msgid "^BG%s^BG lost the ^TC^TT^BG flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:250
+#, c-format
+msgid "^BG%s^BG lost the flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:251
+#, c-format
+msgid "^BG%s^BG got the ^TC^TT^BG flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:252
+#, c-format
+msgid "^BG%s^BG got the flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:253
+#: qcsrc/common/notifications/all.inc:254
+#, c-format
+msgid "^BG%s^BG returned the ^TC^TT^BG flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:256
+#: qcsrc/common/notifications/all.inc:544
+#, c-format
+msgid "^F2Throwing coin... Result: %s^F2!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:258
+msgid "^BGYou don't have any fuel for the ^F1Jetpack"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:260
+msgid "^F2You lack a UID, superspec options will not be saved/restored"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:262
+msgid "^F1Round already started, you will join the game in the next round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:263
+msgid "^F2You will spectate in the next round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:265
+#, c-format
+msgid "^BG%s%s^K1 was killed by ^BG%s^K1's ^BG%s^K1 buff ^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:265
+#, c-format
+msgid "^BG%s%s^K1 was scored against by ^BG%s^K1's ^BG%s^K1 buff ^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:266
+#, c-format
+msgid "^BG%s%s^K1 was unfairly eliminated by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:267
+#, c-format
+msgid "^BG%s%s^K1 was drowned by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:268
+#, c-format
+msgid "^BG%s%s^K1 was grounded by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:269
+#, c-format
+msgid "^BG%s%s^K1 felt a little hot from ^BG%s^K1's fire^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:269
+#, c-format
+msgid "^BG%s%s^K1 was burnt up into a crisp by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:270
+#, c-format
+msgid "^BG%s%s^K1 was cooked by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:271
+#, c-format
+msgid "^BG%s%s^K1 was pushed in front of a monster by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:272
+#, c-format
+msgid "^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:273
+#, c-format
+msgid "^BG%s%s^K1 got too close to a napalm explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:273
+#, c-format
+msgid "^BG%s%s^K1 was burned to death by ^BG%s^K1's Napalm Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:274
+#, c-format
+msgid "^BG%s%s^K1 was blown up by ^BG%s^K1's Ice Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:275
+#, c-format
+msgid "^BG%s%s^K1 was frozen to death by ^BG%s^K1's Ice Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:276
+#, c-format
+msgid "^BG%s%s^K1 has not been healed by ^BG%s^K1's Healing Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:277
+#, c-format
+msgid "^BG%s%s^K1 was shot into space by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:278
+#, c-format
+msgid "^BG%s%s^K1 was slimed by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:279
+#, c-format
+msgid "^BG%s%s^K1 was preserved by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:280
+#, c-format
+msgid "^BG%s%s^K1 tried to occupy ^BG%s^K1's teleport destination space%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:280
+#, c-format
+msgid "^BG%s%s^K1 was telefragged by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:281
+#, c-format
+msgid "^BG%s%s^K1 died in an accident with ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:282
+#, c-format
+msgid ""
+"^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Bumblebee exploded%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:283
+#, c-format
+msgid "^BG%s%s^K1 saw the pretty lights of ^BG%s^K1's Bumblebee gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:284
+#, c-format
+msgid "^BG%s%s^K1 was crushed by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:285
+#, c-format
+msgid "^BG%s%s^K1 was cluster bombed by ^BG%s^K1's Raptor%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:286
+#, c-format
+msgid "^BG%s%s^K1 couldn't resist ^BG%s^K1's purple blobs%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:287
+#, c-format
+msgid "^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Raptor exploded%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:288
+#, c-format
+msgid ""
+"^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Spiderbot exploded%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:289
+#, c-format
+msgid "^BG%s%s^K1 got shredded by ^BG%s^K1's Spiderbot%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:290
+#, c-format
+msgid "^BG%s%s^K1 was blasted to bits by ^BG%s^K1's Spiderbot%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:291
+#, c-format
+msgid "^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Racer exploded%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:292
+#, c-format
+msgid "^BG%s%s^K1 was bolted down by ^BG%s^K1's Racer%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:293
+#, c-format
+msgid "^BG%s%s^K1 couldn't find shelter from ^BG%s^K1's Racer%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:294
+#, c-format
+msgid "^BG%s%s^K1 was thrown into a world of hurt by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:296
+#, c-format
+msgid "^BG%s^K1 was moved into the %s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:297
+#, c-format
+msgid "^BG%s^K1 became enemies with the Lord of Teamplay%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:298
+#, c-format
+msgid "^BG%s^K1 thought they found a nice camping ground%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:299
+#, c-format
+msgid "^BG%s^K1 unfairly eliminated themself%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:301
+#, c-format
+msgid "^BG%s^K1 couldn't catch their breath%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:301
+#, c-format
+msgid "^BG%s^K1 was in the water for too long%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:302
+#, c-format
+msgid "^BG%s^K1 hit the ground with a bit too much force%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:302
+#, c-format
+msgid "^BG%s^K1 hit the ground with a crunch%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:303
+#, c-format
+msgid "^BG%s^K1 became a bit too crispy%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:303
+#, c-format
+msgid "^BG%s^K1 felt a little hot%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:304
+#, c-format
+msgid "^BG%s^K1 died%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:305
+#, c-format
+msgid "^BG%s^K1 found a hot place%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:305
+#, c-format
+msgid "^BG%s^K1 turned into hot slag%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:306
+#, c-format
+msgid "^BG%s^K1 was exploded by a Mage%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:307
+#, c-format
+msgid "^BG%s^K1's innards became outwards by a Shambler%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:308
+#, c-format
+msgid "^BG%s^K1 was smashed by a Shambler%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:309
+#, c-format
+msgid "^BG%s^K1 was zapped to death by a Shambler%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:310
+#, c-format
+msgid "^BG%s^K1 was bitten by a Spider%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:311
+#, c-format
+msgid "^BG%s^K1 was fireballed by a Wyvern%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:312
+#, c-format
+msgid "^BG%s^K1 joins the Zombies%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:313
+#, c-format
+msgid "^BG%s^K1 was given kung fu lessons by a Zombie%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:314
+#: qcsrc/common/notifications/all.inc:316
+#, c-format
+msgid "^BG%s^K1 mastered the art of self-nading%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:315
+#, c-format
+msgid ""
+"^BG%s^K1 decided to take a look at the results of their napalm explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:315
+#, c-format
+msgid "^BG%s^K1 was burned to death by their own Napalm Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:317
+#, c-format
+msgid "^BG%s^K1 felt a little chilly%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:317
+#, c-format
+msgid "^BG%s^K1 was frozen to death by their own Ice Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:318
+#, c-format
+msgid "^BG%s^K1's Healing Nade didn't quite heal them%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:319
+#, c-format
+msgid "^BG%s^K1 died%s%s. What's the point of living without ammo?"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:319
+#, c-format
+msgid "^BG%s^K1 ran out of ammo%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:320
+#, c-format
+msgid "^BG%s^K1 rotted away%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:321
+#, c-format
+msgid "^BG%s^K1 became a shooting star%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:322
+#, c-format
+msgid "^BG%s^K1 was slimed%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:323
+#, c-format
+msgid "^BG%s^K1 couldn't take it anymore%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:324
+#, c-format
+msgid "^BG%s^K1 is now preserved for centuries to come%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:325
+#, c-format
+msgid "^BG%s^K1 switched to the %s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:326
+#, c-format
+msgid "^BG%s^K1 died in an accident%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:327
+#, c-format
+msgid "^BG%s^K1 ran into a turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:328
+#, c-format
+msgid "^BG%s^K1 was blasted away by an eWheel turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:329
+#, c-format
+msgid "^BG%s^K1 got caught up in the FLAC turret fire%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:330
+#, c-format
+msgid "^BG%s^K1 was blasted away by a Hellion turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:331
+#, c-format
+msgid "^BG%s^K1 could not hide from the Hunter turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:332
+#, c-format
+msgid "^BG%s^K1 was riddled full of holes by a Machinegun turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:333
+#, c-format
+msgid "^BG%s^K1 got turned into smoldering gibs by an MLRS turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:334
+#, c-format
+msgid "^BG%s^K1 was phased out by a turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:335
+#, c-format
+msgid "^BG%s^K1 got served some superheated plasma from a turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:336
+#, c-format
+msgid "^BG%s^K1 was electrocuted by a Tesla turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:337
+#, c-format
+msgid "^BG%s^K1 got served a lead enrichment by a Walker turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:338
+#, c-format
+msgid "^BG%s^K1 was impaled by a Walker turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:339
+#, c-format
+msgid "^BG%s^K1 was blasted away by a Walker turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:340
+#, c-format
+msgid "^BG%s^K1 got caught in the blast of a Bumblebee explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:341
+#, c-format
+msgid "^BG%s^K1 was crushed by a vehicle%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:342
+#, c-format
+msgid "^BG%s^K1 was caught in a Raptor cluster bomb%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:343
+#, c-format
+msgid "^BG%s^K1 got caught in the blast of a Raptor explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:344
+#, c-format
+msgid "^BG%s^K1 got caught in the blast of a Spiderbot explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:345
+#, c-format
+msgid "^BG%s^K1 was blasted to bits by a Spiderbot rocket%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:346
+#, c-format
+msgid "^BG%s^K1 got caught in the blast of a Racer explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:347
+#, c-format
+msgid "^BG%s^K1 couldn't find shelter from a Racer rocket%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:350
+#, c-format
+msgid "^BG%s^K1 was betrayed by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:352
+#, c-format
+msgid "^BG%s^BG%s^BG (%s %s every %s seconds)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:354
+#, c-format
+msgid "^BG%s^K1 was frozen by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:355
+#, c-format
+msgid "^BG%s^K3 was revived by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:356
+#, c-format
+msgid "^BG%s^K3 was revived by falling"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:357
+#, c-format
+msgid "^BG%s^K3 was revived by their Nade explosion"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:358
+#, c-format
+msgid "^BG%s^K3 was automatically revived after %s seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:359
+#, c-format
+msgid "^BG%s^K1 froze themself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:361
+#: qcsrc/common/notifications/all.inc:675
+msgid "^TC^TT^BG team wins the round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:362
+#: qcsrc/common/notifications/all.inc:676
+#, c-format
+msgid "^BG%s^BG wins the round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:363
+#: qcsrc/common/notifications/all.inc:539
+msgid "^BGRound tied"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:364
+#: qcsrc/common/notifications/all.inc:540
+msgid "^BGRound over, there's no winner"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:366
+#, c-format
+msgid "^BGGodmode saved you %s units of damage, cheater!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:368
+#, c-format
+msgid "^BG%s^BG got the %s^BG buff!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:369
+#, c-format
+msgid "^BG%s^BG lost the %s^BG buff!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:370
+#: qcsrc/common/notifications/all.inc:683
+#, c-format
+msgid "^BGYou dropped the %s^BG buff!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:371
+#: qcsrc/common/notifications/all.inc:684
+#, c-format
+msgid "^BGYou got the %s^BG buff!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:373
+#: qcsrc/common/notifications/all.inc:687
+#, c-format
+msgid "^BGYou do not have the ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:374
+#: qcsrc/common/notifications/all.inc:688
+#, c-format
+msgid "^BGYou dropped the ^F1%s^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:375
+#: qcsrc/common/notifications/all.inc:689
+#, c-format
+msgid "^BGYou got the ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:376
+#: qcsrc/common/notifications/all.inc:690
+#, c-format
+msgid "^BGYou don't have enough ammo for the ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:377
+#: qcsrc/common/notifications/all.inc:691
+#, c-format
+msgid "^F1%s %s^BG is unable to fire, but its ^F1%s^BG can"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:378
+#: qcsrc/common/notifications/all.inc:692
+#, c-format
+msgid "^F1%s^BG is ^F4not available^BG on this map"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:380
+#, c-format
+msgid "^BG%s^BG is connecting..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:381
+#, c-format
+msgid "^BG%s^F3 connected"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:382
+#, c-format
+msgid "^BG%s^F3 is now playing"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:383
+#, c-format
+msgid "^BG%s^F3 is now playing on the ^TC^TT team"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:385
+#: qcsrc/common/notifications/all.inc:697
+#, c-format
+msgid "^BG%s^BG has dropped the ball!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:386
+#: qcsrc/common/notifications/all.inc:698
+#, c-format
+msgid "^BG%s^BG has picked up the ball!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:388
+#, c-format
+msgid "^BG%s^BG captured the keys for the ^TC^TT team"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:389
+#, c-format
+msgid "^BG%s^BG dropped the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:390
+#, c-format
+msgid "^BG%s^BG lost the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:391
+#, c-format
+msgid "^BG%s^BG pushed %s^BG causing the ^TC^TT Key ^BGdestruction"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:392
+#, c-format
+msgid "^BG%s^BG destroyed the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:393
+#, c-format
+msgid "^BG%s^BG picked up the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:395
+#, c-format
+msgid "^BG%s^F3 forfeited"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:396
+#, c-format
+msgid "^BG%s^F3 has no more lives left"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:398
+msgid "^BGMonsters are currently disabled"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:400
+msgid "^BGThe ^TC^TT^BG team held the ball for too long"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:402
+#, c-format
+msgid "^BG%s^BG captured %s^BG control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:403
+#, c-format
+msgid "^BG%s^BG captured a control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:404
+#, c-format
+msgid "^TC^TT^BG team %s^BG control point has been destroyed by %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:405
+#, c-format
+msgid "^TC^TT^BG team control point has been destroyed by %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:406
+msgid "^TC^TT^BG generator has been destroyed"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:407
+msgid "^TC^TT^BG generator spontaneously combusted due to overtime!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:409
+#, c-format
+msgid "^BG%s^K1 picked up Invisibility"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:410
+#, c-format
+msgid "^BG%s^K1 picked up Shield"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:411
+#, c-format
+msgid "^BG%s^K1 picked up Speed"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:412
+#, c-format
+msgid "^BG%s^K1 picked up Strength"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:414
+#, c-format
+msgid "^BG%s^F3 disconnected"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:415
+#, c-format
+msgid "^BG%s^F3 was kicked for idling"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:416
+msgid ""
+"^F2You were kicked from the server because you are a spectator and "
+"spectators aren't allowed at the moment."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:417
+#, c-format
+msgid "^BG%s^F3 was kicked for excessive teamkilling"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:418
+#, c-format
+msgid "^BG%s^F3 is now spectating"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:420
+#, c-format
+msgid "^BG%s^BG has abandoned the race"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:421
+#, c-format
+msgid "^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:422
+#, c-format
+msgid "^BG%s^BG couldn't break the %s%s^BG place record of %s%s %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:423
+#, c-format
+msgid "^BG%s^BG has finished the race"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:424
+#, c-format
+msgid "^BG%s^BG broke %s^BG's %s%s^BG place record with %s%s %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:425
+#, c-format
+msgid "^BG%s^BG improved their %s%s^BG place record with %s%s %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:426
+#, c-format
+msgid ""
+"^BG%s^BG scored a new record with ^F2%s^BG, but unfortunately lacks a UID "
+"and will be lost."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:427
+#, c-format
+msgid ""
+"^BG%s^BG scored a new record with ^F2%s^BG, but is anonymous and will be "
+"lost."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:428
+#, c-format
+msgid "^BG%s^BG set the %s%s^BG place record with %s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:430
+#, c-format
+msgid ""
+"^F4You have been invited by ^BG%s^F4 to join their game of ^F2%s^F4 "
+"(^F1%s^F4)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:432
+msgid "^TC^TT ^BGteam scores!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:434
+#, c-format
+msgid ""
+"^F2You have to become a player within the next %s, otherwise you will be "
+"kicked, because spectating isn't allowed at this time!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:436
+#, c-format
+msgid "^BG%s^K1 picked up a Superweapon"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:438
+msgid "^BGYou cannot change to a larger team"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:439
+msgid "^BGYou are not allowed to change teams"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:441
+#, c-format
+msgid ""
+"^F4NOTE: ^BGThe server is running ^F1Xonotic %s (beta)^BG, you have "
+"^F2Xonotic %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:442
+#, c-format
+msgid ""
+"^F4NOTE: ^BGThe server is running ^F1Xonotic %s^BG, you have ^F2Xonotic %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:443
+#, c-format
+msgid ""
+"^F4NOTE: ^F1Xonotic %s^BG is out, and you still have ^F2Xonotic %s^BG - get "
+"the update from ^F3http://www.xonotic.org/^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:445
+#, c-format
+msgid "^F3SVQC Build information: ^F4%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:447
+#, c-format
+msgid ""
+"^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Accordeon%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:448
+#, c-format
+msgid "^BG%s^K1 hurt their own ears with the @!#%%'n Accordeon%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:449
+#, c-format
+msgid "^BG%s%s^K1 was electrocuted by ^BG%s^K1's Arc%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:450
+#, c-format
+msgid "^BG%s%s^K1 was blasted by ^BG%s^K1's Arc bolts%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:451
+#, c-format
+msgid "^BG%s%s^K1 was shot to death by ^BG%s^K1's Blaster%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:452
+#, c-format
+msgid "^BG%s^K1 shot themself to hell with their Blaster%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:453
+#, c-format
+msgid "^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:454
+#, c-format
+msgid "^BG%s^K1 felt the strong pull of their Crylink%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:455
+#, c-format
+msgid "^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:456
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's rocket%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:457
+#, c-format
+msgid "^BG%s^K1 blew themself up with their Devastator%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:458
+#, c-format
+msgid "^BG%s%s^K1 was blasted by ^BG%s^K1's Electro bolt%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:459
+#, c-format
+msgid "^BG%s%s^K1 felt the electrifying air of ^BG%s^K1's Electro combo%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:460
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's Electro orb%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:461
+#, c-format
+msgid "^BG%s^K1 played with Electro bolts%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:462
+#, c-format
+msgid "^BG%s^K1 could not remember where they put their Electro orb%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:463
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's fireball%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:464
+#, c-format
+msgid "^BG%s%s^K1 got burnt by ^BG%s^K1's firemine%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:465
+#, c-format
+msgid "^BG%s^K1 should have used a smaller gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:466
+#, c-format
+msgid "^BG%s^K1 forgot about their firemine%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:467
+#, c-format
+msgid "^BG%s%s^K1 was pummeled by a burst of ^BG%s^K1's Hagar rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:468
+#, c-format
+msgid "^BG%s%s^K1 was pummeled by ^BG%s^K1's Hagar rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:469
+#, c-format
+msgid "^BG%s^K1 played with tiny Hagar rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:470
+#, c-format
+msgid "^BG%s%s^K1 was cut down with ^BG%s^K1's HLAC%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:471
+#, c-format
+msgid "^BG%s^K1 got a little jumpy with their HLAC%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:472
+#, c-format
+msgid "^BG%s%s^K1 was caught in ^BG%s^K1's Hook gravity bomb%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:473
+#, c-format
+msgid ""
+"^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Klein Bottle%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:474
+#, c-format
+msgid "^BG%s^K1 hurt their own ears with the @!#%%'n Klein Bottle%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:475
+#, c-format
+msgid "^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:476
+#, c-format
+msgid "^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:477
+#: qcsrc/common/notifications/all.inc:782
+#, c-format
+msgid "^BGYou cannot place more than ^F2%s^BG mines at a time"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:478
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's mine%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:479
+#, c-format
+msgid "^BG%s^K1 forgot about their mine%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:480
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's Mortar grenade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:481
+#, c-format
+msgid "^BG%s%s^K1 ate ^BG%s^K1's Mortar grenade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:482
+#, c-format
+msgid "^BG%s^K1 didn't see their own Mortar grenade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:483
+#, c-format
+msgid "^BG%s^K1 blew themself up with their own Mortar%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:484
+#, c-format
+msgid "^BG%s%s^K1 was sniped by ^BG%s^K1's Overkill Heavy Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:485
+#, c-format
+msgid ""
+"^BG%s%s^K1 was torn to bits by ^BG%s^K1's Overkill Heavy Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:486
+#, c-format
+msgid ""
+"^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Overkill Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:487
+#, c-format
+msgid "^BG%s%s^K1 has been vaporized by ^BG%s^K1's Overkill Nex%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:488
+#, c-format
+msgid ""
+"^BG%s%s^K1 was sawn in half by ^BG%s^K1's Overkill Rocket Propelled Chainsaw"
+"%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:489
+#, c-format
+msgid ""
+"^BG%s%s^K1 almost dodged ^BG%s^K1's Overkill Rocket Propelled Chainsaw%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:490
+#, c-format
+msgid ""
+"^BG%s^K1 was sawn in half by their own Overkill Rocket Propelled Chainsaw%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:491
+#, c-format
+msgid ""
+"^BG%s^K1 blew themself up with their Overkill Rocket Propelled Chainsaw%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:493
+#, c-format
+msgid "^BG%s%s^K1 was gunned down by ^BG%s^K1's Overkill Shotgun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:494
+#, c-format
+msgid "^BG%s%s^K1 was sniped with a Rifle by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:495
+#, c-format
+msgid "^BG%s%s^K1 died in ^BG%s^K1's Rifle bullet hail%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:496
+#, c-format
+msgid "^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle bullet hail%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:497
+#, c-format
+msgid "^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:498
+#, c-format
+msgid "^BG%s%s^K1 was pummeled by ^BG%s^K1's Seeker rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:499
+#, c-format
+msgid "^BG%s%s^K1 was tagged by ^BG%s^K1's Seeker%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:500
+#, c-format
+msgid "^BG%s^K1 played with tiny Seeker rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:501
+#, c-format
+msgid "^BG%s%s^K1 was gunned down by ^BG%s^K1's Shockwave%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:502
+#, c-format
+msgid "^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shockwave%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:503
+#, c-format
+msgid "^BG%s%s^K1 was gunned down by ^BG%s^K1's Shotgun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:504
+#, c-format
+msgid "^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shotgun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:505
+#, c-format
+msgid "^BG%s^K1 is now thinking with portals%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:506
+#, c-format
+msgid "^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Tuba%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:507
+#, c-format
+msgid "^BG%s^K1 hurt their own ears with the @!#%%'n Tuba%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:508
+#, c-format
+msgid "^BG%s%s^K1 has been sublimated by ^BG%s^K1's Vaporizer%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:509
+#, c-format
+msgid "^BG%s%s^K1 has been vaporized by ^BG%s^K1's Vortex%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:528
+msgid "^F4You are now alone!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:530
+msgid "^BGYou are attacking!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:531
+msgid "^BGYou are defending!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:532
+#, c-format
+msgid "^BGObjective destroyed in ^F4%s^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:534
+msgid "^F4Begin!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:535
+msgid "^F4Game starts in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:536
+msgid "^F4Round starts in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:537
+msgid "^F4Round cannot start"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:542
+msgid "^F2Don't camp!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:546
+msgid ""
+"^BGYou are now free.\n"
+"^BGFeel free to ^F2try to capture^BG the flag again\n"
+"^BGif you think you will succeed."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:547
+msgid "^BGThis flag is currently inactive"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:548
+msgid ""
+"^BGYou are now ^F1shielded^BG from the flag(s)\n"
+"^BGfor ^F2too many unsuccessful attempts^BG to capture.\n"
+"^BGMake some defensive scores before trying again."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:549
+msgid "^BGYou captured the ^TC^TT^BG flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:550
+msgid "^BGYou captured the flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:551
+#, c-format
+msgid "^BGToo many flag throws! Throwing disabled for %s."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:552
+#, c-format
+msgid "^BG%s^BG passed the ^TC^TT^BG flag to %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:553
+#, c-format
+msgid "^BG%s^BG passed the flag to %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:554
+#, c-format
+msgid "^BGYou received the ^TC^TT^BG flag from %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:555
+#, c-format
+msgid "^BGYou received the flag from %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:556
+#, c-format
+msgid "^BGPress ^F2%s^BG to receive the flag from %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:557
+#, c-format
+msgid "^BGRequesting %s^BG to pass you the flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:558
+#, c-format
+msgid "^BGYou passed the ^TC^TT^BG flag to %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:559
+#, c-format
+msgid "^BGYou passed the flag to %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:560
+msgid "^BGYou got the ^TC^TT^BG flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:561
+msgid "^BGYou got the flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:562
+#, c-format
+msgid "^BGYou got your %steam^BG's flag, return it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:563
+#, c-format
+msgid "^BGYou got the %senemy^BG's flag, return it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:564
+#, c-format
+msgid "^BGThe %senemy^BG got your flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:565
+#, c-format
+msgid "^BGThe %senemy (^BG%s%s)^BG got your flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:566
+#, c-format
+msgid "^BGThe %senemy^BG got the flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:567
+#, c-format
+msgid "^BGThe %senemy (^BG%s%s)^BG got the flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:568
+#, c-format
+msgid "^BGThe %senemy^BG got their flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:569
+#, c-format
+msgid "^BGThe %senemy (^BG%s%s)^BG got their flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:570
+#, c-format
+msgid "^BGYour %steam mate^BG got the ^TC^TT^BG flag! Protect them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:571
+#, c-format
+msgid "^BGYour %steam mate (^BG%s%s)^BG got the ^TC^TT^BG flag! Protect them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:572
+#, c-format
+msgid "^BGYour %steam mate^BG got the flag! Protect them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:573
+#, c-format
+msgid "^BGYour %steam mate (^BG%s%s)^BG got the flag! Protect them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:574
+msgid "^BGEnemies can now see you on radar!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:575
+msgid "^BGYou returned the ^TC^TT^BG flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:576
+msgid "^BGStalemate! Enemies can now see you on radar!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:577
+msgid "^BGStalemate! Flag carriers can now be seen by enemies on radar!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:581
+#, c-format
+msgid "^K3%sYou fragged ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:582
+#: qcsrc/common/notifications/all.inc:591
+#: qcsrc/common/notifications/all.inc:600
+#, c-format
+msgid "^K3%sYou scored against ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:583
+#, c-format
+msgid "^K1%sYou were fragged by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:584
+#: qcsrc/common/notifications/all.inc:593
+#: qcsrc/common/notifications/all.inc:602
+#, c-format
+msgid "^K1%sYou were scored against by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:590
+#, c-format
+msgid "^K3%sYou burned ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:592
+#, c-format
+msgid "^K1%sYou were burned by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:599
+#, c-format
+msgid "^K3%sYou froze ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:601
+#, c-format
+msgid "^K1%sYou were frozen by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:608
+#, c-format
+msgid "^K1%sYou typefragged ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:609
+#, c-format
+msgid "^K1%sYou scored against ^BG%s^K1 while they were typing"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:610
+#, c-format
+msgid "^K1%sYou were typefragged by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:611
+#, c-format
+msgid "^K1%sYou were scored against by ^BG%s^K1 while typing"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:617
+#, c-format
+msgid "^BGPress ^F2%s^BG again to toss the nade!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:618
+msgid "^F2You got a ^K1BONUS GRENADE^F2!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:620
+#, c-format
+msgid ""
+"^BGYou have been moved into a different team\n"
+"You are now on: %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:621
+msgid "^K1Don't go against your team mates!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:621
+msgid "^K1Don't shoot your team mates!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:622
+msgid "^K1Die camper!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:622
+msgid "^K1Reconsider your tactics, camper!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:623
+msgid "^K1You unfairly eliminated yourself!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:624
+#, c-format
+msgid "^K1You were %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:625
+msgid "^K1You couldn't catch your breath!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:626
+msgid "^K1You hit the ground with a crunch!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:627
+msgid "^K1You felt a little too hot!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:627
+msgid "^K1You got a little bit too crispy!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:628
+msgid "^K1You killed your own dumb self!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:628
+msgid "^K1You need to be more careful!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:629
+msgid "^K1You couldn't stand the heat!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:630
+msgid "^K1You need to watch out for monsters!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:630
+msgid "^K1You were killed by a monster!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:631
+msgid "^K1Tastes like chicken!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:631
+msgid "^K1You forgot to put the pin back in!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:632
+msgid "^K1Hanging around a napalm explosion is bad!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:633
+msgid "^K1You felt a little chilly!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:633
+msgid "^K1You got a little bit too cold!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:634
+msgid "^K1Your Healing Nade is a bit defective"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:635
+msgid "^K1You are respawning for running out of ammo..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:635
+msgid "^K1You were killed for running out of ammo..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:636
+msgid "^K1You grew too old without taking your medicine"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:636
+msgid "^K1You need to preserve your health"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:637
+msgid "^K1You became a shooting star!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:638
+msgid "^K1You melted away in slime!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:639
+msgid "^K1You committed suicide!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:639
+msgid "^K1You ended it all!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:640
+msgid "^K1You got stuck in a swamp!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:641
+#, c-format
+msgid "^BGYou are now on: %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:642
+msgid "^K1You died in an accident!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:643
+msgid "^K1You had an unfortunate run in with a turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:643
+msgid "^K1You were fragged by a turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:644
+msgid "^K1You had an unfortunate run in with an eWheel turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:644
+msgid "^K1You were fragged by an eWheel turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:645
+msgid "^K1You had an unfortunate run in with a Walker turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:645
+msgid "^K1You were fragged by a Walker turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:646
+msgid "^K1You got caught in the blast of a Bumblebee explosion!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:647
+msgid "^K1You were crushed by a vehicle!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:648
+msgid "^K1You were caught in a Raptor cluster bomb!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:649
+msgid "^K1You got caught in the blast of a Raptor explosion!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:650
+msgid "^K1You got caught in the blast of a Spiderbot explosion!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:651
+msgid "^K1You were blasted to bits by a Spiderbot rocket!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:652
+msgid "^K1You got caught in the blast of a Racer explosion!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:653
+msgid "^K1You couldn't find shelter from a Racer rocket!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:654
+msgid "^K1Watch your step!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:656
+#, c-format
+msgid "^K1Moron! You fragged ^BG%s^K1, a team mate!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:656
+#, c-format
+msgid "^K1Moron! You went against ^BG%s^K1, a team mate!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:657
+#, c-format
+msgid "^K1You were fragged by ^BG%s^K1, a team mate"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:657
+#, c-format
+msgid "^K1You were scored against by ^BG%s^K1, a team mate"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:659
+msgid ""
+"^K1Stop idling!\n"
+"^BGDisconnecting in ^COUNT..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:661
+#, c-format
+msgid "^BGYou need %s^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:662
+#, c-format
+msgid "^BGYou also need %s^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:663
+msgid "^BGDoor unlocked!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:665
+#, c-format
+msgid "^F2Extra lives taken: ^K1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:667
+#, c-format
+msgid "^K3You revived ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:668
+msgid "^K3You revived yourself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:669
+#, c-format
+msgid "^K3You were revived by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:670
+#, c-format
+msgid "^K3You were automatically revived after %s seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:672
+msgid "^BGThe generator is under attack!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:674
+msgid "^TC^TT^BG team loses the round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:678
+msgid "^K1You froze yourself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:679
+msgid "^K1Round already started, you spawn as frozen"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:681
+#, c-format
+msgid "^K1A %s has arrived!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:685
+msgid "^BGYou got the ^F1Fuel regenerator"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:686
+msgid "^BGYou got the ^F1Jetpack"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:694
+msgid ""
+"^K1No spawnpoints available!\n"
+"Hope your team can fix it..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:695
+msgid ""
+"^K1You may not join the game at this time.\n"
+"The player limit reached maximum capacity."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:699
+msgid "^BGYou picked up the ball"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:700
+msgid "^BGKilling people while you don't have the ball gives no points!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:702
+msgid ""
+"^BGAll keys are in your team's hands!\n"
+"Help the key carriers to meet!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:703
+msgid ""
+"^BGAll keys are in ^TC^TT team^BG's hands!\n"
+"Interfere ^F4NOW^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:704
+msgid ""
+"^BGAll keys are in your team's hands!\n"
+"Meet the other key carriers ^F4NOW^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:705
+msgid "^F4Round will start in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:706
+msgid "^BGScanning frequency range..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:707
+msgid "^BGYou are starting with the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:709
+msgid "^BGYou have no lives left, you must wait until the next match"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:711
+#, c-format
+msgid ""
+"^BGWaiting for players to join...\n"
+"Need active players for: %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:712
+#, c-format
+msgid "^BGWaiting for %s player(s) to join..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:714
+msgid "^BGYour weapon has been downgraded until you find some ammo!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:715
+msgid "^F4^COUNT^BG left to find some ammo!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:716
+msgid "^BGGet some ammo or you'll be dead in ^F4^COUNT^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:716
+msgid "^BGGet some ammo! ^F4^COUNT^BG left!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:717
+#, c-format
+msgid "^F2Extra lives remaining: ^K1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:719 qcsrc/menu/xonotic/campaign.qc:244
+#, c-format
+msgid "Level %s: "
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:719
+#, c-format
+msgid "^BGPress ^F2%s^BG to enter the game"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:722
+#, c-format
+msgid ""
+"^F2^COUNT^BG until weapon change...\n"
+"Next weapon: ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:723
+#, c-format
+msgid "^F2Active weapon: ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:725
+#, c-format
+msgid "^BGYou captured %s^BG control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:726
+msgid "^BGYou captured a control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:727
+#, c-format
+msgid "^TC^TT^BG team captured %s^BG control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:728
+msgid "^TC^TT^BG team captured a control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:729
+msgid "^BGThis control point currently cannot be captured"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:730
+msgid ""
+"^BGThe enemy generator cannot be destroyed yet\n"
+"^F2Capture some control points to unshield it"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:731
+msgid "^BGThe ^TCenemy^BG generator is no longer shielded!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:732
+msgid ""
+"^K1Your generator is NOT shielded!\n"
+"^BGRe-capture control points to shield it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:733
+#, c-format
+msgid "^BGPress ^F2%s^BG to teleport"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:734
+#, c-format
+msgid "^BGTeleporting disabled for %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:736
+msgid ""
+"^F2Now playing ^F4OVERTIME^F2!\n"
+"Keep fragging until we have a winner!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:736
+msgid ""
+"^F2Now playing ^F4OVERTIME^F2!\n"
+"Keep scoring until we have a winner!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:737
+msgid ""
+"^F2Now playing ^F4OVERTIME^F2!\n"
+"\n"
+"Generators are now decaying.\n"
+"The more control points your team holds,\n"
+"the faster the enemy generator decays"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:738
+#, c-format
+msgid ""
+"^F2Now playing ^F4OVERTIME^F2!\n"
+"^BGAdded ^F4%s^BG to the game!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:740
+msgid "^K1In^BG-portal created"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:741
+msgid "^F3Out^BG-portal created"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:742
+msgid "^F1Portal creation failed"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:744
+msgid "^F2Strength infuses your weapons with devastating power"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:745
+msgid "^F2Strength has worn off"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:747
+msgid "^F2Shield surrounds you"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:748
+msgid "^F2Shield has worn off"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:750
+msgid "^F2You are on speed"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:751
+msgid "^F2Speed has worn off"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:753
+msgid "^F2You are invisible"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:754
+msgid "^F2Invisibility has worn off"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:756
+msgid "^F2The race is over, finish your lap!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:758
+msgid "^BGSequence completed!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:759
+msgid "^BGThere are more to go..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:760
+#, c-format
+msgid "^BGOnly %s^BG more to go..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:762
+msgid "^F2Superweapons have broken down"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:763
+msgid "^F2Superweapons have been lost"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:764
+msgid "^F2You now have a superweapon"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:766
+msgid "^K1Changing to ^TC^TT^K1 in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:767
+msgid "^K1Changing team in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:768
+msgid "^K1Spectating in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:769
+msgid "^K1Suicide in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:771
+msgid "^F4Timeout begins in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:772
+msgid "^F4Timeout ends in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:774
+msgid "^K1Cannot join given minigame session!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:776
+#, c-format
+msgid "^BGPress ^F2%s^BG to enter/exit the vehicle"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:777
+#, c-format
+msgid "^BGPress ^F2%s^BG to enter the vehicle gunner"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:778
+#, c-format
+msgid "^BGPress ^F2%s^BG to steal this vehicle"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:779
+msgid ""
+"^F2The enemy is stealing one of your vehicles!\n"
+"^F4Stop them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:780
+msgid "^F2Intruder detected, disabling shields!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:198
+msgid "Notification dump command only works with cl_cmd and sv_cmd."
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:408 qcsrc/common/notifications/all.qh:409
+#, c-format
+msgid " (near %s)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:416 qcsrc/common/notifications/all.qh:417
+msgid "primary"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:416 qcsrc/common/notifications/all.qh:417
+msgid "secondary"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:419
+msgid "point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:419
+msgid "points"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:428
+msgid "drop flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:429
+msgid "throw nade"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:455
+#, c-format
+msgid "%s^K1 made a TRIPLE FRAG! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:455
+#, c-format
+msgid "%s^K1 made a TRIPLE SCORE! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:455
+msgid "TRIPLE FRAG! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:456
+#, c-format
+msgid "%s^K1 made FIVE SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:456
+#, c-format
+msgid "%s^K1 unlocked RAGE! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:456
+msgid "RAGE! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:457
+#, c-format
+msgid "%s^K1 made TEN SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:457
+#, c-format
+msgid "%s^K1 started a MASSACRE! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:457
+msgid "MASSACRE! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:458
+#, c-format
+msgid "%s^K1 executed MAYHEM! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:458
+#, c-format
+msgid "%s^K1 made FIFTEEN SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:458
+msgid "MAYHEM! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:459
+#, c-format
+msgid "%s^K1 is a BERSERKER! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:459
+#, c-format
+msgid "%s^K1 made TWENTY SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:459
+msgid "BERSERKER! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:460
+#, c-format
+msgid "%s^K1 inflicts CARNAGE! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:460
+#, c-format
+msgid "%s^K1 made TWENTY FIVE SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:460
+msgid "CARNAGE! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:461
+#, c-format
+msgid "%s^K1 made THIRTY SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:461
+#, c-format
+msgid "%s^K1 unleashes ARMAGEDDON! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:461
+msgid "ARMAGEDDON! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:468
+#, c-format
+msgid "%s(^F1Bot^BG)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:470
+#, c-format
+msgid "%s(Ping ^F1%d^BG)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:477
+#, c-format
+msgid ""
+"\n"
+"(Health ^1%d^BG / Armor ^2%d^BG)%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:479
+#, c-format
+msgid ""
+"\n"
+"(^F4Dead^BG)%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:500 qcsrc/common/notifications/all.qh:513
+#, c-format
+msgid "%d score spree! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:512
+#, c-format
+msgid "%d frag spree! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:525
+msgid "First blood! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:525
+msgid "First score! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:529
+msgid "First casualty! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:529
+msgid "First victim! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:570
+#, c-format
+msgid "%s^K1 has %d frags in a row! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:571
+#, c-format
+msgid "%s^K1 made %d scores in a row! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:589
+#, c-format
+msgid "%s^K1 drew first blood! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:590
+#, c-format
+msgid "%s^K1 got the first score! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:606
+#, c-format
+msgid ", ending their %d frag spree"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:607
+#, c-format
+msgid ", ending their %d score spree"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:621
+#, c-format
+msgid ", losing their %d frag spree"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:622
+#, c-format
+msgid ", losing their %d score spree"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:647
+#, c-format
+msgid " with %d %s"
+msgstr ""
+
+#: qcsrc/common/teams.qh:31
+msgid "TEAM^Red"
+msgstr ""
+
+#: qcsrc/common/teams.qh:32
+msgid "TEAM^Blue"
+msgstr ""
+
+#: qcsrc/common/teams.qh:33
+msgid "TEAM^Yellow"
+msgstr ""
+
+#: qcsrc/common/teams.qh:34
+msgid "TEAM^Pink"
+msgstr ""
+
+#: qcsrc/common/teams.qh:35
+msgid "Team"
+msgstr ""
+
+#: qcsrc/common/teams.qh:36
+msgid "Neutral"
+msgstr ""
+
+#: qcsrc/common/teams.qh:39
+msgid "KEY^Red"
+msgstr ""
+
+#: qcsrc/common/teams.qh:40
+msgid "KEY^Blue"
+msgstr ""
+
+#: qcsrc/common/teams.qh:41
+msgid "KEY^Yellow"
+msgstr ""
+
+#: qcsrc/common/teams.qh:42
+msgid "KEY^Pink"
+msgstr ""
+
+#: qcsrc/common/teams.qh:43
+msgid "FLAG^Red"
+msgstr ""
+
+#: qcsrc/common/teams.qh:44
+msgid "FLAG^Blue"
+msgstr ""
+
+#: qcsrc/common/teams.qh:45
+msgid "FLAG^Yellow"
+msgstr ""
+
+#: qcsrc/common/teams.qh:46
+msgid "FLAG^Pink"
+msgstr ""
+
+#: qcsrc/common/teams.qh:47
+msgid "GENERATOR^Red"
+msgstr ""
+
+#: qcsrc/common/teams.qh:48
+msgid "GENERATOR^Blue"
+msgstr ""
+
+#: qcsrc/common/teams.qh:49
+msgid "GENERATOR^Yellow"
+msgstr ""
+
+#: qcsrc/common/teams.qh:50
+msgid "GENERATOR^Pink"
+msgstr ""
+
+#: qcsrc/common/turrets/all.qh:95
+msgid "Turrets dump command only works with sv_cmd."
+msgstr ""
+
+#: qcsrc/common/turrets/cl_turrets.qc:125
+#, c-format
+msgid "%s under attack!"
+msgstr ""
+
+#: qcsrc/common/turrets/turret.qh:11
+msgid "Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/ewheel.qh:15
+msgid "eWheel Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/ewheel_weapon.qh:7
+msgid "eWheel"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/flac.qh:13
+msgid "FLAC Cannon"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/flac_weapon.qh:7
+msgid "FLAC"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/fusionreactor.qh:11
+msgid "Fusion Reactor"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/hellion.qh:13
+msgid "Hellion Missile Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/hellion_weapon.qh:7
+msgid "Hellion"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/hk.qh:15
+msgid "Hunter-Killer Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/hk_weapon.qh:7
+msgid "Hunter-Killer"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/machinegun.qh:13
+msgid "Machinegun Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/machinegun_weapon.qh:7
+msgid "Machinegun"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/mlrs.qh:13
+msgid "MLRS Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/mlrs_weapon.qh:7
+msgid "MLRS"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/phaser.qh:13
+msgid "Phaser Cannon"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/phaser_weapon.qh:7
+msgid "Phaser"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/plasma.qh:13
+msgid "Plasma Cannon"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/plasma_dual.qh:8
+msgid "Dual plasma"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/plasma_dual.qh:20
+msgid "Dual Plasma Cannon"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/plasma_weapon.qh:7
+msgid "Plasma"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/tesla.qh:13
+#: qcsrc/common/turrets/turret/tesla_weapon.qh:7
+msgid "Tesla Coil"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/walker.qh:15
+msgid "Walker Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/walker_weapon.qh:7
+msgid "Walker"
+msgstr ""
+
+#: qcsrc/common/util.qc:1390
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:176
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:186
+msgid "Male"
+msgstr ""
+
+#: qcsrc/common/util.qc:1391
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:175
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:185
+msgid "Female"
+msgstr ""
+
+#: qcsrc/common/util.qc:1392
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:174
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:187
+msgid "Undisclosed"
+msgstr ""
+
+#: qcsrc/common/util.qc:1439
+msgid "<KEY NOT FOUND>"
+msgstr ""
+
+#: qcsrc/common/util.qc:1440
+msgid "<UNKNOWN KEYNUM>"
+msgstr ""
+
+#: qcsrc/common/util.qc:1445
+msgid "TAB"
+msgstr ""
+
+#: qcsrc/common/util.qc:1446 qcsrc/common/util.qc:1517
+#, c-format
+msgid "ENTER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1447
+msgid "ESCAPE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1448
+msgid "SPACE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1450
+msgid "BACKSPACE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1451 qcsrc/common/util.qc:1508
+#, c-format
+msgid "UPARROW"
+msgstr ""
+
+#: qcsrc/common/util.qc:1452 qcsrc/common/util.qc:1503
+#, c-format
+msgid "DOWNARROW"
+msgstr ""
+
+#: qcsrc/common/util.qc:1453 qcsrc/common/util.qc:1505
+#, c-format
+msgid "LEFTARROW"
+msgstr ""
+
+#: qcsrc/common/util.qc:1454 qcsrc/common/util.qc:1506
+#, c-format
+msgid "RIGHTARROW"
+msgstr ""
+
+#: qcsrc/common/util.qc:1456
+msgid "ALT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1457
+msgid "CTRL"
+msgstr ""
+
+#: qcsrc/common/util.qc:1458
+msgid "SHIFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1460 qcsrc/common/util.qc:1501
+#, c-format
+msgid "INS"
+msgstr ""
+
+#: qcsrc/common/util.qc:1461 qcsrc/common/util.qc:1511
+#, c-format
+msgid "DEL"
+msgstr ""
+
+#: qcsrc/common/util.qc:1462 qcsrc/common/util.qc:1504
+#, c-format
+msgid "PGDN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1463 qcsrc/common/util.qc:1509
+#, c-format
+msgid "PGUP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1464 qcsrc/common/util.qc:1507
+#, c-format
+msgid "HOME"
+msgstr ""
+
+#: qcsrc/common/util.qc:1465 qcsrc/common/util.qc:1502
+#, c-format
+msgid "END"
+msgstr ""
+
+#: qcsrc/common/util.qc:1467
+msgid "PAUSE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1469
+msgid "NUMLOCK"
+msgstr ""
+
+#: qcsrc/common/util.qc:1470
+msgid "CAPSLOCK"
+msgstr ""
+
+#: qcsrc/common/util.qc:1471
+msgid "SCROLLOCK"
+msgstr ""
+
+#: qcsrc/common/util.qc:1473
+msgid "SEMICOLON"
+msgstr ""
+
+#: qcsrc/common/util.qc:1474
+msgid "TILDE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1475
+msgid "BACKQUOTE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1476
+msgid "QUOTE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1477
+msgid "APOSTROPHE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1478
+msgid "BACKSLASH"
+msgstr ""
+
+#: qcsrc/common/util.qc:1486
+#, c-format
+msgid "F%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1496
+#, c-format
+msgid "KP_%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1501 qcsrc/common/util.qc:1502
+#: qcsrc/common/util.qc:1503 qcsrc/common/util.qc:1504
+#: qcsrc/common/util.qc:1505 qcsrc/common/util.qc:1506
+#: qcsrc/common/util.qc:1507 qcsrc/common/util.qc:1508
+#: qcsrc/common/util.qc:1509 qcsrc/common/util.qc:1510
+#: qcsrc/common/util.qc:1511 qcsrc/common/util.qc:1512
+#: qcsrc/common/util.qc:1513 qcsrc/common/util.qc:1514
+#: qcsrc/common/util.qc:1515 qcsrc/common/util.qc:1516
+#: qcsrc/common/util.qc:1517 qcsrc/common/util.qc:1518
+#, c-format
+msgid "KP_%s"
+msgstr ""
+
+#: qcsrc/common/util.qc:1510
+#, c-format
+msgid "PERIOD"
+msgstr ""
+
+#: qcsrc/common/util.qc:1512
+#, c-format
+msgid "DIVIDE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1513
+#, c-format
+msgid "SLASH"
+msgstr ""
+
+#: qcsrc/common/util.qc:1514
+#, c-format
+msgid "MULTIPLY"
+msgstr ""
+
+#: qcsrc/common/util.qc:1515
+#, c-format
+msgid "MINUS"
+msgstr ""
+
+#: qcsrc/common/util.qc:1516
+#, c-format
+msgid "PLUS"
+msgstr ""
+
+#: qcsrc/common/util.qc:1518
+#, c-format
+msgid "EQUALS"
+msgstr ""
+
+#: qcsrc/common/util.qc:1523
+msgid "PRINTSCREEN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1526
+#, c-format
+msgid "MOUSE%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1528
+msgid "MWHEELUP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1529
+msgid "MWHEELDOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1532
+#, c-format
+msgid "JOY%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1535
+#, c-format
+msgid "AUX%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1542
+#, c-format
+msgid "DPAD_UP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1542 qcsrc/common/util.qc:1543
+#: qcsrc/common/util.qc:1544 qcsrc/common/util.qc:1545
+#: qcsrc/common/util.qc:1546 qcsrc/common/util.qc:1547
+#: qcsrc/common/util.qc:1548 qcsrc/common/util.qc:1549
+#: qcsrc/common/util.qc:1550 qcsrc/common/util.qc:1551
+#: qcsrc/common/util.qc:1552 qcsrc/common/util.qc:1553
+#: qcsrc/common/util.qc:1554 qcsrc/common/util.qc:1555
+#: qcsrc/common/util.qc:1556 qcsrc/common/util.qc:1557
+#: qcsrc/common/util.qc:1558 qcsrc/common/util.qc:1559
+#: qcsrc/common/util.qc:1560 qcsrc/common/util.qc:1561
+#, c-format
+msgid "X360_%s"
+msgstr ""
+
+#: qcsrc/common/util.qc:1543
+#, c-format
+msgid "DPAD_DOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1544
+#, c-format
+msgid "DPAD_LEFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1545
+#, c-format
+msgid "DPAD_RIGHT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1546
+#, c-format
+msgid "START"
+msgstr ""
+
+#: qcsrc/common/util.qc:1547
+#, c-format
+msgid "BACK"
+msgstr ""
+
+#: qcsrc/common/util.qc:1548
+#, c-format
+msgid "LEFT_THUMB"
+msgstr ""
+
+#: qcsrc/common/util.qc:1549
+#, c-format
+msgid "RIGHT_THUMB"
+msgstr ""
+
+#: qcsrc/common/util.qc:1550
+#, c-format
+msgid "LEFT_SHOULDER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1551
+#, c-format
+msgid "RIGHT_SHOULDER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1552
+#, c-format
+msgid "LEFT_TRIGGER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1553
+#, c-format
+msgid "RIGHT_TRIGGER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1554
+#, c-format
+msgid "LEFT_THUMB_UP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1555
+#, c-format
+msgid "LEFT_THUMB_DOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1556
+#, c-format
+msgid "LEFT_THUMB_LEFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1557
+#, c-format
+msgid "LEFT_THUMB_RIGHT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1558
+#, c-format
+msgid "RIGHT_THUMB_UP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1559
+#, c-format
+msgid "RIGHT_THUMB_DOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1560
+#, c-format
+msgid "RIGHT_THUMB_LEFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1561
+#, c-format
+msgid "RIGHT_THUMB_RIGHT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1571 qcsrc/common/util.qc:1572
+#: qcsrc/common/util.qc:1573 qcsrc/common/util.qc:1574
+#, c-format
+msgid "JOY_%s"
+msgstr ""
+
+#: qcsrc/common/util.qc:1571
+#, c-format
+msgid "UP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1572
+#, c-format
+msgid "DOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1573
+#, c-format
+msgid "LEFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1574
+#, c-format
+msgid "RIGHT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1580
+#, c-format
+msgid "MIDINOTE%d"
+msgstr ""
+
+#: qcsrc/common/vehicles/cl_vehicles.qc:190
+#, c-format
+msgid "Press %s"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/bumblebee.qc:954
+msgid "No right gunner!"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/bumblebee.qc:960
+msgid "No left gunner!"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/bumblebee.qh:19
+msgid "Bumblebee"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/racer.qh:19
+msgid "Racer"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/racer_weapon.qh:9
+msgid "Racer cannon"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/raptor.qh:19
+msgid "Raptor"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/raptor_weapons.qh:9
+msgid "Raptor cannon"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/raptor_weapons.qh:17
+msgid "Raptor bomb"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/raptor_weapons.qh:25
+msgid "Raptor flare"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/spiderbot.qh:19
+msgid "Spiderbot"
+msgstr ""
+
+#: qcsrc/common/weapons/all.qh:76
+msgid "Weapons dump command only works with sv_cmd."
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/arc.qh:18
+msgid "Arc"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/blaster.qh:18
+msgid "Blaster"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/crylink.qh:18
+msgid "Crylink"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/devastator.qh:18
+msgid "Devastator"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/electro.qh:18
+msgid "Electro"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/fireball.qh:18
+msgid "Fireball"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/hagar.qh:18
+msgid "Hagar"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/hlac.qh:18
+msgid "Heavy Laser Assault Cannon"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/hook.qh:18
+msgid "Grappling Hook"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/machinegun.qh:18
+msgid "MachineGun"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/minelayer.qh:18
+msgid "Mine Layer"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/mortar.qh:18
+msgid "Mortar"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/porto.qh:18
+msgid "Port-O-Launch"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/rifle.qh:19
+msgid "Rifle"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/seeker.qh:18
+msgid "T.A.G. Seeker"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/shockwave.qh:18
+msgid "Shockwave"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/shotgun.qh:18
+msgid "Shotgun"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/tuba.qh:18
+#, no-c-format
+msgid "@!#%'n Tuba"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/vaporizer.qh:19
+msgid "Vaporizer"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/vortex.qh:19
+msgid "Vortex"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:9
+#, c-format
+msgid "CI_DEC^%s years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:12
+#, c-format
+msgid "CI_ZER^%d years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:13
+#, c-format
+msgid "CI_FIR^%d year"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:14
+#, c-format
+msgid "CI_SEC^%d years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:15
+#, c-format
+msgid "CI_THI^%d years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:16
+#, c-format
+msgid "CI_MUL^%d years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:18
+#, c-format
+msgid "CI_DEC^%s weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:21
+#, c-format
+msgid "CI_ZER^%d weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:22
+#, c-format
+msgid "CI_FIR^%d week"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:23
+#, c-format
+msgid "CI_SEC^%d weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:24
+#, c-format
+msgid "CI_THI^%d weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:25
+#, c-format
+msgid "CI_MUL^%d weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:27
+#, c-format
+msgid "CI_DEC^%s days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:30
+#, c-format
+msgid "CI_ZER^%d days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:31
+#, c-format
+msgid "CI_FIR^%d day"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:32
+#, c-format
+msgid "CI_SEC^%d days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:33
+#, c-format
+msgid "CI_THI^%d days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:34
+#, c-format
+msgid "CI_MUL^%d days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:36
+#, c-format
+msgid "CI_DEC^%s hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:39
+#, c-format
+msgid "CI_ZER^%d hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:40
+#, c-format
+msgid "CI_FIR^%d hour"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:41
+#, c-format
+msgid "CI_SEC^%d hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:42
+#, c-format
+msgid "CI_THI^%d hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:43
+#, c-format
+msgid "CI_MUL^%d hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:46
+#, c-format
+msgid "CI_DEC^%s minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:49
+#, c-format
+msgid "CI_ZER^%d minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:50
+#, c-format
+msgid "CI_FIR^%d minute"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:51
+#, c-format
+msgid "CI_SEC^%d minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:52
+#, c-format
+msgid "CI_THI^%d minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:53
+#, c-format
+msgid "CI_MUL^%d minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:55
+#, c-format
+msgid "CI_DEC^%s seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:58
+#, c-format
+msgid "CI_ZER^%d seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:59
+#, c-format
+msgid "CI_FIR^%d second"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:60
+#, c-format
+msgid "CI_SEC^%d seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:61
+#, c-format
+msgid "CI_THI^%d seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:62
+#, c-format
+msgid "CI_MUL^%d seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:79
+#, c-format
+msgid "%dst"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:80
+#, c-format
+msgid "%dnd"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:81
+#, c-format
+msgid "%drd"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:85
+#, c-format
+msgid "%dth"
+msgstr ""
+
+#: qcsrc/lib/oo.qh:324
+msgid "No description"
+msgstr ""
+
+#: qcsrc/lib/spawnfunc.qh:248
+#, c-format
+msgid ""
+"Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, "
+"please file an issue."
+msgstr ""
+
+#: qcsrc/lib/string.qh:81
+#, c-format
+msgid "%d days, %02d:%02d:%02d"
+msgstr ""
+
+#: qcsrc/lib/string.qh:82
+#, c-format
+msgid "%02d:%02d:%02d"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:48
+msgid "Usage: menu_cmd command..., where possible commands are:"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:49
+msgid " sync - reloads all cvars on the current menu page"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:50
+msgid " directmenu ITEM - select a menu item as main item"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:51
+msgid " dumptree - dump the state of the menu as a tree to the console"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:81
+msgid "Available options:"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:130
+msgid "Invalid command. For a list of supported commands, try menu_cmd help."
+msgstr ""
+
+#: qcsrc/menu/item/listbox.qc:413
+#, c-format
+msgid "Item %d"
+msgstr ""
+
+#: qcsrc/menu/item/textslider.qc:11 qcsrc/menu/item/textslider.qc:12
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:37
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:68
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:115
+msgid "Custom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:4
+msgid "Core Team"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:15
+msgid "Extended Team"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:46
+msgid "Website"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:51
+msgid "Stats"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:55
+msgid "Art"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:63
+msgid "Animation"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:67
+msgid "Level Design"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:90
+msgid "Music / Sound FX"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:106
+msgid "Game Code"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:114
+msgid "Marketing / PR"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:120
+msgid "Legal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:125
+msgid "Game Engine"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:129
+msgid "Engine Additions"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:135
+msgid "Compiler"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:141
+msgid "Other Active Contributors"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:148
+msgid "Translators"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:150
+msgid "Asturian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:155
+msgid "Belarusian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:158
+msgid "Bulgarian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:165
+msgid "Chinese (China)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:171
+msgid "Chinese (Taiwan)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:176
+msgid "Cornish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:179
+msgid "Czech"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:184
+msgid "Dutch"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:191
+msgid "English (Australia)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:196
+msgid "Finnish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:201
+msgid "French"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:209
+msgid "German"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:220
+msgid "Greek"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:226
+msgid "Hungarian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:230
+msgid "Irish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:233
+msgid "Italian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:239
+msgid "Kazakh"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:242
+msgid "Korean"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:246
+msgid "Polish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:254
+msgid "Portuguese"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:260
+msgid "Romanian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:267
+msgid "Russian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:278
+msgid "Scottish Gaelic"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:281
+msgid "Serbian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:287
+msgid "Spanish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:298
+msgid "Swedish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:302
+msgid "Ukrainian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:309
+msgid "Past Contributors"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:73
+msgid "forced to be saved to config.cfg"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:79 qcsrc/menu/xonotic/cvarlist.qc:89
+msgid "will not be saved"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:84
+msgid "will be saved to config.cfg"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:93
+msgid "private"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:95
+msgid "engine setting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:97
+msgid "read only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_credits.qc:13
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:38
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:303
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:85
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:75
+#: qcsrc/menu/xonotic/dialog_singleplayer_winner.qc:14
+msgid "OK"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_credits.qh:7
+msgid "Credits"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_credits.qh:8
+msgid "The Xonotic credits"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:16
+msgid "Are you sure to disconnect from server?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:19
+msgid "I would disconnect from server..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:22
+msgid "I would play more!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qh:6
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qh:6
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qh:6
+msgid "Disconnect"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qh:7
+msgid "Disconnect from the server you are connected to"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:39
+msgid ""
+"Welcome to Xonotic, please select your language preference and enter your "
+"player name to get started. You can change these options later through the "
+"menu system."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:45
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:28
+msgid "Name:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:53
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:62
+msgid "Name under which you will appear in the game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:69
+msgid "Text language:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:78
+msgid "Allow player statistics to use your nickname at stats.xonotic.org?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:84
+msgid "Undecided"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:88
+msgid "Save settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qh:6
+msgid "Welcome"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:18
+msgid "Ammunition display:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:21
+msgid "Show only current ammo type"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:24
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:46
+msgid "Noncurrent alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:28
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:50
+msgid "Noncurrent scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:32
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:24
+msgid "Align icon:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:33
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:32
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:25
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:37
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:25
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:23
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:35
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:21
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:57
+msgid "Left"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:34
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:34
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:27
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:38
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:26
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:25
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:36
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:23
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:59
+msgid "Right"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qh:6
+msgid "Ammo Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:19
+msgid "Message duration:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:23
+msgid "Fade time:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:27
+msgid "Flip messages order"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:29
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:18
+msgid "Text alignment:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:33
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:22
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:70
+msgid "Center"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:37
+msgid "Font scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qh:6
+msgid "Centerprint Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:17
+msgid "Chat entries:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:20
+msgid "Chat size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:24
+msgid "Chat lifetime:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:28
+msgid "Chat beep sound"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qh:6
+msgid "Chat Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.qc:16
+msgid "Engine info:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.qc:19
+msgid "Use an averaging algorithm for fps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.qh:6
+msgid "Engine Info Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:17
+msgid "Combine health and armor"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:19
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:28
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:17
+msgid "Enable status bar"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:21
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:19
+msgid "Status bar alignment:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:29
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:39
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:27
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:37
+msgid "Inward"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:31
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:40
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:29
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:38
+msgid "Outward"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:34
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:32
+msgid "Icon alignment:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:42
+msgid "Flip health and armor positions"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qh:6
+msgid "Health/Armor Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.qc:16
+msgid "Info messages:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.qc:19
+msgid "Flip align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.qh:6
+msgid "Info Messages Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:16
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:15
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:14
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:15
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:50
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:62
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:77
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:116
+#: qcsrc/menu/xonotic/util.qc:770 qcsrc/menu/xonotic/util.qc:786
+#: qcsrc/menu/xonotic/util.qc:803
+msgid "Disable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:17
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:15
+msgid "Enable spectating"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:18
+msgid "Enable even playing in warmup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:29
+msgid "Reduced"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:32
+msgid "Text/icon ratio:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:35
+msgid "Hide spawned items"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:37
+msgid "Hide big armor and health"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:39
+msgid "Dynamic size"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qh:6
+msgid "Items Time Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.qh:6
+msgid "Mod Icons Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:17
+msgid "Notifications:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:20
+msgid "Also print notifications to the console"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:23
+msgid "Flip notify order"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:26
+msgid "Entry lifetime:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:30
+msgid "Entry fadetime:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qh:6
+msgid "Notification Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:16
+#: qcsrc/menu/xonotic/util.qc:758
+msgid "Enable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:17
+msgid "Enable even observing"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:18
+msgid "Enable only in Race/CTS"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:24
+msgid "Status bar"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:26
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:67
+msgid "Left align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:27
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:73
+msgid "Right align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:28
+msgid "Inward align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:29
+msgid "Outward align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:33
+msgid "Flip speed/acceleration positions"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:37
+msgid "Speed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:38
+msgid "Include vertical speed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:49
+msgid "Speed unit:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:51
+msgid "qu/s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:52
+msgid "m/s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:53
+msgid "km/h"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:54
+msgid "mph"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:55
+msgid "knots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:57
+msgid "Show"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:60
+msgid "Top speed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:66
+msgid "Acceleration:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:67
+msgid "Include vertical acceleration"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qh:6
+msgid "Physics Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qh:6
+msgid "Powerups Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:16
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:17
+msgid "Always enable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:23
+msgid "Forced aspect:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qh:6
+msgid "Pressed Keys Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qh:6
+msgid "Quick Menu Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.qh:6
+msgid "Race Timer Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:16
+msgid "Enable in team games"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:23
+msgid "Radar:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:26
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:68
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:107
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:54
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:87
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:103
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:45
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:70
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:124
+#: qcsrc/menu/xonotic/util.qc:792
+msgid "Alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:30
+msgid "Rotation:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:32
+msgid "Forward"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:33
+msgid "West"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:34
+msgid "South"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:35
+msgid "East"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:36
+msgid "North"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:40
+msgid "Scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:44
+msgid "Zoom mode:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:46
+msgid "Zoomed in"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:47
+msgid "Zoomed out"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:48
+msgid "Always zoomed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:49
+msgid "Never zoomed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qh:6
+msgid "Radar Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:17
+msgid "Score:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:20
+msgid "Rankings:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:21
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:58
+msgid "Off"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:22
+msgid "And me"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:23
+msgid "Pure"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qh:6
+msgid "Score Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_timer.qc:16
+msgid "Timer:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_timer.qc:19
+msgid "Show elapsed time"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_timer.qh:6
+msgid "Timer Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_vote.qc:17
+msgid "Alpha after voting:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_vote.qh:6
+msgid "Vote Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:22
+msgid "Fade out after:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:24
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:167
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:145
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:55
+msgid "Never"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:26
+#, c-format
+msgid "%ds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:30
+msgid "Fade effect:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:33
+msgid "EF^None"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:34
+msgid "Alpha"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:35
+msgid "Slide"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:36
+msgid "EF^Both"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:40
+msgid "Weapon icons:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:43
+msgid "Show only owned weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:54
+msgid "Show weapon ID as:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:55
+msgid "SHOWAS^None"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:56
+msgid "Number"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:57
+msgid "Bind"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:60
+msgid "Weapon ID scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:66
+msgid "Show Accuracy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:67
+msgid "Show Ammo"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:70
+msgid "Ammo bar alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:76
+msgid "Ammo bar color:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qh:6
+msgid "Weapons Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:19
+msgid "HUD skins"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:22
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:173
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:32
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:42
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:25
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:33
+msgid "Filter:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:30
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:54
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:49
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:43
+msgid "Refresh"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:33
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:28
+msgid "Set skin"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:37
+msgid "Save current skin"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:46
+msgid "Panel background defaults:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:48
+#: qcsrc/menu/xonotic/util.qc:767
+msgid "Background:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:60
+#: qcsrc/menu/xonotic/util.qc:783
+msgid "Border size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:75
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:114
+msgid "Team color:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:83
+#: qcsrc/menu/xonotic/util.qc:809
+msgid "Test team color in configure mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:86
+#: qcsrc/menu/xonotic/util.qc:812
+msgid "Padding:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:93
+msgid "HUD Dock:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:95
+msgid "DOCK^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:96
+msgid "DOCK^Small"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:97
+msgid "DOCK^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:98
+msgid "DOCK^Large"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:121
+msgid "Grid settings:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:124
+msgid "Snap panels to grid"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:127
+msgid "Grid size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:129
+msgid "X:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:136
+msgid "Y:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:145
+msgid "Exit setup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qh:6
+msgid "Panel HUD Setup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:13
+msgid "Monster:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:22
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:20
+msgid "Spawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:23
+msgid "Remove"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:25
+msgid "Move target:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:26
+msgid "Follow"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:27
+msgid "Wander"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:28
+msgid "Spawnpoint"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:29
+msgid "No moving"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:31
+msgid "Colors:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:33
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:39
+msgid "Set skin:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qh:6
+msgid "Monster Tools"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:14
+msgid "Servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:15
+msgid "Find servers to play on"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:17
+msgid "Host your own game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:18
+msgid "Media"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:19
+msgid "Profile"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qh:6
+msgid "Multiplayer"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qh:7
+msgid ""
+"Play online, against your friends in LAN, view demos or change player "
+"settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:38
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:111
+#: qcsrc/menu/xonotic/skinlist.qc:88 qcsrc/menu/xonotic/util.qc:769
+#: 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 ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:40
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:60
+msgid "Unlimited"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:74
+msgid "Gametype"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:79
+msgid "Time limit:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:81
+msgid "Timelimit in minutes that when hit, will end the match"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:82
+#, c-format
+msgid "%d minutes"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:83
+msgid "TIMLIM^Default"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:84
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:159
+msgid "1 minute"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:101
+msgid "TIMLIM^Infinite"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:109
+msgid "Teams:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:112
+msgid "2 teams"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:113
+msgid "3 teams"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:114
+msgid "4 teams"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:117
+msgid "Player slots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:119
+msgid ""
+"The maximum amount of players or bots that can be connected to your server "
+"at once"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:121
+msgid "Number of bots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:123
+msgid "Amount of bots on your server"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:125
+msgid "Bot skill:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:128
+msgid "Specify how experienced the bots will be"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:129
+msgid "Botlike"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:130
+msgid "Beginner"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:131
+msgid "You will win"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:132
+msgid "You can win"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:133
+msgid "You might win"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:134
+msgid "Advanced"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:135
+msgid "Expert"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:136
+msgid "Pro"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:137
+msgid "Assassin"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:138
+msgid "Unhuman"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:139
+msgid "Godlike"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:155
+msgid "Mutators..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:156
+msgid "Mutators and weapon arenas"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:165
+msgid "Maplist"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:175
+msgid ""
+"Click here or Ctrl-F to provide a keyword to narrow down the map list. Ctrl-"
+"Delete to clear; Enter when done."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:184
+msgid "Add shown"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:185
+msgid "Add the maps shown in the list to your selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:188
+msgid "Remove shown"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:189
+msgid "Remove the maps shown in the list from your selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:194
+msgid "Add all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:195
+msgid "Add every available map to your selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:198
+msgid "Remove all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:199
+msgid "Remove all the maps from your selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:206
+msgid "Start Multiplayer!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:50
+msgid "Title:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:56
+msgid "Author:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:62
+msgid "Game types:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:85
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:257
+msgid "Close"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:88
+msgid "MAP^Play"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qh:7
+msgid "Map Information"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:28
+msgid "All Weapons Arena"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:30
+msgid "Most Weapons Arena"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:46
+#, c-format
+msgid "%s Arena"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:57
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:163
+msgid "Dodging"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:59
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:283
+msgid "InstaGib"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:61
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:224
+msgid "New Toys"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:63
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:288
+msgid "NIX"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:65
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:229
+msgid "Rocket Flying"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:67
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:219
+msgid "Invincible Projectiles"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:71
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:298
+msgid "No start weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:73
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:202
+msgid "Low gravity"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:75
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:171
+msgid "Cloaked"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:77
+msgid "Hook"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:79
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:180
+msgid "Midair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:81
+msgid "Melee only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:85
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:234
+msgid "Piñata"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:87
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:239
+msgid "Weapons stay"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:89
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:191
+msgid "Blood loss"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:93
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:175
+msgid "Buffs"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:95
+msgid "Overkill"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:97
+msgid "No powerups"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:99
+msgid "Powerups"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:101
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:167
+msgid "Touch explode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:103
+msgid "Wall jumping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:105
+msgid "MUT^None"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:160
+msgid "Gameplay mutators:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:164
+msgid ""
+"Enable dodging (quick acceleration in a given direction). Double-tap a "
+"directional key to dodge"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:168
+msgid "An explosion occurs when two players collide"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:172
+msgid "All players are almost invisible"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:176
+msgid ""
+"Enable buff pickups (random bonuses like Medic, Invisible, etc.) on the maps "
+"that support it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:181
+msgid "Only possible to inflict damage on your enemy while they're airborne"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:185
+msgid "Damage done to your enemy gets added to your own health"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:190
+msgid ""
+"Amount of health below which players start bleeding out (health rots and "
+"they can't jump)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:199
+msgid "Make things fall to the ground slower (percentage of normal gravity)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:208
+msgid "Weapon & item mutators:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:211
+msgid "Grappling hook"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:212
+msgid "Players spawn with the grappling hook. Press the 'hook' key to use it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:216
+msgid ""
+"Players spawn with the jetpack. Double-tap 'jump' or press the 'jetpack' key "
+"to use it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:220
+msgid ""
+"Projectiles can't be destroyed. However, you can still explode Electro orbs "
+"with the Electro primary fire"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:225
+msgid ""
+"Some weapon spawns will be randomly replaced with new weapons: Heavy Laser "
+"Assault Cannon, Mine Layer, Rifle, T.A.G. Seeker"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:230
+msgid ""
+"Devastator rockets can be detonated instantly (otherwise, there's a short "
+"delay). This allows players to fire and detonate a Devastator rocket while "
+"in the air for a strong mid-air boost even while moving fast"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:235
+msgid "Players will drop all weapons they possessed when they are killed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:240
+msgid "Weapons stay after they are picked up"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:245
+msgid "Regular (no arena)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:246
+msgid ""
+"Players will be given a set of weapons at spawn as well as unlimited ammo, "
+"without weapon pickups"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:248
+msgid "Weapon arenas:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:251
+msgid "Custom weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:273
+msgid "Most weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:277
+msgid "All weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:280
+msgid "Special arenas:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:284
+msgid ""
+"Players will be given only one weapon, which can instantly kill the opponent "
+"with a single shot. If the player runs out of ammo, he will have 10 seconds "
+"to find some or if he fails to do so, face death. The secondary fire mode "
+"does not inflict any damage but is good for doing trickjumps."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:289
+msgid ""
+"No items Xonotic - instead of pickup items, everyone plays with the same "
+"weapon. After some time, a countdown will start, after which everyone will "
+"switch to another weapon."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:293
+msgid "with blaster"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:294
+msgid "Always carry the blaster as an additional weapon in Nix"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qh:9
+msgid "Mutators"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:39
+msgid "SRVS^Categories"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:42
+msgid "SRVS^Empty"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:43
+msgid "Show empty servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:47
+msgid "SRVS^Full"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:48
+msgid "Show full servers that have no slots available"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:52
+msgid "Pause"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:53
+msgid ""
+"Pause updating the server list to prevent servers from \"jumping around\""
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:54
+msgid "Reload the server list"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:68
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:184
+msgid "Address:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:79
+msgid "Info..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:80
+msgid "Show more information about the currently highlighted server"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:92
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:264
+msgid "Join!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:114
+#: qcsrc/menu/xonotic/serverlist.qc:1020
+msgid "MOD^Default"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:121
+#, c-format
+msgid "%d modified"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:121
+msgid "Official"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:129
+msgid "N/A (auth library missing, can't connect)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:131
+msgid "N/A (auth library missing)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:137
+msgid "Not supported (can't connect)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:139
+msgid "Not supported (won't encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:143
+msgid "Supported (will encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:145
+msgid "Supported (won't encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:149
+msgid "Requested (will encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:151
+msgid "Requested (won't encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:155
+msgid "Required (can't connect)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:157
+msgid "Required (will encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:161
+msgid "Use the `crypto_aeslevel` cvar to change your preferences"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:178
+msgid "Hostname:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:192
+msgid "Gametype:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:197
+msgid "Map:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:202
+msgid "Mod:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:207
+msgid "Version:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:212
+msgid "Settings:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:219
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:251
+msgid "Players:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:224
+msgid "Bots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:229
+msgid "Free slots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:235
+msgid "Encryption:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:240
+msgid "ID:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:245
+msgid "Key:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qh:7
+msgid "Server Information"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:25
+msgid "Demos"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:26
+msgid "Screenshots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:27
+msgid "Music Player"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:48
+msgid "Auto record demos"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:57
+msgid "Timedemo"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:58
+msgid "Benchmark how fast your computer can run the highlighted demo"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:62
+msgid "DEMO^Play"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:13
+msgid "Playing a demo will disconnect you from the current match."
+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 ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:13
+msgid "Timing a demo will disconnect you from the current match."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:37
+msgid "MUSICPL^Add"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:40
+msgid "MUSICPL^Add all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:44
+msgid "Set as menu track"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:48
+msgid "Reset default menu track"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:54
+msgid "Playlist:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:55
+msgid "Random order"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:60
+msgid "MUSICPL^Stop"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:63
+msgid "MUSICPL^Play"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:66
+msgid "MUSICPL^Pause"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:69
+msgid "MUSICPL^Prev"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:72
+msgid "MUSICPL^Next"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:76
+msgid "MUSICPL^Remove"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:79
+msgid "MUSICPL^Remove all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:41
+msgid "Auto screenshot scoreboard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:62
+msgid "Open in the viewer"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:137
+msgid "Reset"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:142
+msgid "Previous"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:145
+msgid "Next"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:150
+msgid "Slide show"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:38
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:21
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:37
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:26
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:21
+msgid "Apply immediately"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:50
+msgid "Name"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:79
+msgid "Model"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:98
+msgid "Glowing color"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:108
+msgid "Detail color"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:123
+msgid "Statistics"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:127
+msgid "Allow player statistics to track your client"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:131
+msgid "Allow player statistics to use your nickname"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:136
+msgid "Allow player statistics to rank you in leaderboards"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:152
+msgid "Country"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:156
+msgid "Select language..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:172
+msgid "Gender:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:179
+msgid "Gender"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_quit.qc:11
+msgid "Are you sure you want to quit?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_quit.qc:15
+msgid "Back to work..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_quit.qc:17
+msgid "I got some more fragging to do!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_quit.qh:7
+msgid "Quit the game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:15
+msgid "Model:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:21
+msgid "Remove *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:23
+msgid "Copy *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:24
+msgid "Paste"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:26
+msgid "Bone:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:31
+msgid "Set * as child"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:32
+msgid "Attach to *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:34
+msgid "Detach from *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:37
+msgid "Visual object properties for *:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:41
+msgid "Set alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:44
+msgid "Set color main:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:46
+msgid "Set color glow:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:50
+msgid "Set frame:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:54
+msgid "Physical object properties for *:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:56
+msgid "Set material:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:62
+msgid "Set solidity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:63
+msgid "Non-solid"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:64
+msgid "Solid"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:65
+msgid "Set physics:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:66
+msgid "Static"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:67
+msgid "Movable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:68
+msgid "Physical"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:70
+msgid "Set scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:72
+msgid "Set force:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:76
+msgid "Claim *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:78
+msgid "* object info"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:79
+msgid "* mesh info"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:80
+msgid "* attachment info"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:81
+msgid "Show help"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:82
+msgid "* is the object you are facing"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qh:6
+msgid "Sandbox Tools"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:18
+msgid "Video"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:19
+msgid "Effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:20
+msgid "Audio"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:22
+msgid "Game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:23
+msgid "Input"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:24
+msgid "User"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:25
+#: qcsrc/menu/xonotic/keybinder.qc:119
+msgid "Misc"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qh:6
+msgid "Settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qh:7
+msgid "Change the game settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:29
+msgid "Master:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:35
+msgid "Music:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:43
+msgid "VOL^Ambient:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:50
+msgid "Info:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:57
+msgid "Items:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:64
+msgid "Pain:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:71
+msgid "Player:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:78
+msgid "Shots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:85
+msgid "Voice:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:93
+msgid "Weapons:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:99
+msgid "New style sound attenuation"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:102
+msgid "Mute sounds when not active"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:105
+msgid "Frequency:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:107
+msgid "Sound output frequency"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:108
+msgid "8 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:109
+msgid "11.025 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:110
+msgid "16 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:111
+msgid "22.05 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:112
+msgid "24 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:113
+msgid "32 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:114
+msgid "44.1 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:115
+msgid "48 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:119
+msgid "Channels:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:121
+msgid "Number of channels for the sound output"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:122
+msgid "Mono"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:123
+msgid "Stereo"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:124
+msgid "2.1"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:125
+msgid "4"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:126
+msgid "5"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:127
+msgid "5.1"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:128
+msgid "6.1"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:129
+msgid "7.1"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:134
+msgid "Swap stereo output channels"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:135
+msgid "Swap left/right channels"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:138
+msgid "Headphone friendly mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:139
+msgid ""
+"Enable spatialization (blend the right and left channel slightly to decrease "
+"stereo separation a bit for headphones)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:143
+msgid "Hit indication sound"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:144
+msgid "Play a hit indicator sound when your shot hits an enemy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:147
+msgid "Chat message sound"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:149
+msgid "Menu sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:150
+msgid "Play sounds when clicking menu items"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:151
+msgid "Focus sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:152
+msgid "Play sounds when hovering over menu items too"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:156
+msgid "Time announcer:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:158
+msgid "WRN^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:160
+msgid "5 minutes"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:161
+msgid "WRN^Both"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:164
+msgid "Automatic taunts:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:166
+msgid "Automatically taunt enemies after fragging them"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:168
+msgid "Sometimes"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:169
+msgid "Often"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:170
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:147
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:57
+msgid "Always"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:176
+msgid "Debug info about sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qc:11
+msgid "Are you sure you want to reset all key bindings?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qh:6
+msgid "Reset key bindings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:41
+msgid "Quality preset:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:45
+msgid "PRE^OMG!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:48
+msgid "PRE^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:50
+msgid "PRE^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:52
+msgid "PRE^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:54
+msgid "PRE^High"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:56
+msgid "PRE^Ultra"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:60
+msgid "PRE^Ultimate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:65
+msgid "Geometry detail:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:67
+msgid "Change the smoothness of the curves on the map"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:68
+msgid "DET^Lowest"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:69
+msgid "DET^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:70
+msgid "DET^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:71
+msgid "DET^Good"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:72
+msgid "DET^Best"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:73
+msgid "DET^Insane"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:77
+msgid "Player detail:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:79
+msgid "PDET^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:80
+msgid "PDET^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:81
+msgid "PDET^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:82
+msgid "PDET^Good"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:83
+msgid "PDET^Best"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:87
+msgid "Texture resolution:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:91
+msgid "RES^Leet"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:92
+msgid "RES^Lowest"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:93
+msgid "RES^Very low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:94
+msgid "RES^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:95
+msgid "RES^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:96
+msgid "RES^Good"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:97
+msgid "RES^Best"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:110
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:115
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:120
+msgid "Avoid lossy texture compression"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:129
+msgid "Disable sky for performance and visibility"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:129
+msgid "Show sky"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:132
+msgid "Show surfaces"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:133
+msgid ""
+"Disable textures completely for very slow hardware. This gives a huge "
+"performance boost, but looks very ugly."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:136
+msgid "Use lightmaps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:137
+msgid ""
+"Use high resolution lightmaps, which will look pretty but use up some extra "
+"video memory"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:139
+msgid "Deluxe mapping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:140
+msgid "Use per-pixel lighting effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:142
+msgid "Gloss"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:143
+msgid "Enable the use of glossmaps on textures supporting it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:146
+msgid "Offset mapping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:147
+msgid ""
+"Offset mapping effect that will make textures with bumpmaps appear like they "
+"\"pop out\" of the flat 2D surface"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:149
+msgid "Relief mapping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:150
+msgid ""
+"Higher quality offset mapping, which also has a huge impact on performance"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:153
+msgid "Reflections:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:154
+msgid ""
+"Reflection and refraction quality, has a huge impact on performance on maps "
+"with reflecting surfaces"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:157
+msgid "Resolution of reflections/refractions"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:158
+msgid "Blurred"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:159
+msgid "REFL^Good"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:160
+msgid "Sharp"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:164
+msgid "Decals"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:165
+msgid "Enable decals (bullet holes and blood)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:166
+msgid "Decals on models"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:170
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:254
+msgid "Distance:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:173
+msgid "Decals further away than this will not be drawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:177
+msgid "Time:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:180
+msgid "Time in seconds before decals fade away"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:184
+msgid "Damage effects:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:186
+msgid "DMGFX^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:187
+msgid "Skeletal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:188
+msgid "DMGFX^All"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:192
+msgid "No dynamic lighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:193
+msgid "Enable corona flares around certain lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:195
+msgid "Fake corona lighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:196
+msgid ""
+"Enable faster but uglier dynamic lights by rendering bright coronas instead "
+"of real dynamic lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:199
+msgid "Realtime dynamic lighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:200
+msgid "Enable rendering of dynamic lights such as explosions and rocket lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:202
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:208
+msgid "Shadows"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:203
+msgid "Enable rendering of shadows from dynamic lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:206
+msgid "Realtime world lighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:207
+msgid ""
+"Enable rendering of full realtime world lighting on maps that support it. "
+"Note that this might have a big impact on performance."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:209
+msgid "Enable rendering of shadows from realtime world lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:213
+msgid "Use normal maps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:214
+msgid "Enable use of directional shading on textures"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:216
+msgid "Soft shadows"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:220
+msgid "Fade corona according to visibility"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:221
+msgid "Fade coronas according to visibility"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:225
+msgid "Bloom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:226
+msgid ""
+"Enable bloom effect, which brightens the neighboring pixels of very bright "
+"pixels. Has a big impact on performance."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:227
+msgid "Extra postprocessing effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:228
+msgid ""
+"Enables special postprocessing effects for when damaged or under water or "
+"using a powerup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:233
+msgid "Motion blur strength - 0.4 recommended"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:234
+msgid "Motion blur:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:240
+msgid "Particles"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:241
+msgid "Spawnpoint effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:242
+msgid "Particles effects at all spawn points and whenever a player spawns"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:247
+msgid "Quality:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:250
+#: qcsrc/menu/xonotic/slider_particles.qc:13
+msgid ""
+"Multiplier for amount of particles. Less means less particles, which in turn "
+"gives for better performance"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:257
+msgid "Particles further away than this will not be drawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:31
+msgid "No crosshair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:33
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:62
+msgid "Per weapon"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:34
+msgid ""
+"Set a different crosshair for each weapon, good if you play without weapon "
+"models"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:48
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:81
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:97
+msgid "Size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:64
+msgid "By health"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:76
+msgid "Use rings to indicate weapon status"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:93
+msgid "Enable center crosshair dot"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:111
+msgid "Use normal crosshair color"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:122
+msgid "Smooth effects of crosshairs"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:125
+msgid "Hit testing:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:128
+msgid ""
+"None: do not do hit tests for the crosshair; TrueAim: blur the crosshair "
+"when there's an obstacle between your gun and the target; Enemies: also "
+"enlarge the crosshair when you would hit an enemy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:129
+msgid "HTTST^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:130
+msgid "HTTST^TrueAim"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:131
+msgid "HTTST^Enemies"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:136
+msgid "Blur crosshair if the shot is obstructed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:140
+msgid "Enlarge crosshair if targeting an enemy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:143
+msgid "Animate crosshair when hitting an enemy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:146
+msgid "Animate crosshair when picking up an item"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qh:7
+msgid "Crosshair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:43
+msgid "Scoreboard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:48
+msgid "Fading speed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:51
+msgid "Enable rows / columns highlighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:53
+msgid "Show accuracy underneath scoreboard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:55
+msgid "Show team sizes:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:56
+msgid ""
+"Team size position: Off=do not show; Left=on the left side of the scoreboard "
+"and move team scores to the right; Right=on the right of the scoreboard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:64
+msgid "Waypoints"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:66
+msgid "Display waypoint markers for objectives on the map"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:67
+msgid "Show various gametype specific waypoints"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:73
+msgid "Control transparency of the waypoints"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:77
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:130
+msgid "Fontsize:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:83
+msgid "Edge offset:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:91
+msgid "Fade when near the crosshair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:95
+msgid "Display names instead of icons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:100
+msgid "Damage"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:102
+msgid "Overlay:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:105
+msgid "Factor:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:110
+msgid "Fade rate:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:118
+msgid "Player Names"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:120
+msgid "Show names above players"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:136
+msgid "Max distance:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:142
+msgid "Decolorize:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:146
+#: qcsrc/menu/xonotic/keybinder.qc:113
+msgid "Teamplay"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:154
+msgid "Only when near crosshair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:158
+msgid "Display health and armor"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:163
+msgid "Damage overlay:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:166
+msgid "Dynamic HUD"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:167
+msgid "HUD moves around following player's movement"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:169
+msgid "Shake the HUD when hurt"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:173
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qh:6
+msgid "Enter HUD editor"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qh:7
+msgid "HUD"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:21
+msgid "In order for the HUD editor to show, you must first be in game."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:23
+msgid "Do you wish to start a local game to set up the HUD?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:24
+msgid "Frag Information"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:26
+msgid "Display information about killing sprees"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:29
+msgid "Only display sprees if they are achievements"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:34
+msgid "Show spree information in centerprints"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:38
+msgid "Show spree information in death messages"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:43
+msgid "Sprees in info messages:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:46
+msgid "SPREES^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:47
+msgid "Target"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:48
+msgid "Attacker"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:49
+msgid "SPREES^Both"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:55
+msgid "Print on a seperate line"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:58
+msgid "Add extra frag information to centerprint when available"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:62
+msgid "Add frag location to death messages when available"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:65
+msgid "Gamemode Settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:67
+msgid "Display capture times in Capture The Flag"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:71
+msgid "Display name of flag stealer in Capture The Flag"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:76
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:92
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:126
+msgid "Other"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:78
+msgid "Display console messages in the top left corner"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:80
+msgid "Display all info messages in the chatbox"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:82
+msgid "Display player statuses in the chatbox"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:86
+msgid "Powerup notifications"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:89
+msgid "Weapon centerprint notifications"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:92
+msgid "Weapon info message notifications"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:96
+msgid "Announcers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:98
+msgid "Respawn countdown sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:101
+msgid "Killstreak sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:104
+msgid "Achievement sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qh:7
+msgid "Messages"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:30
+msgid "Items"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:32
+msgid "Use simple 2D images instead of item models"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:34
+msgid "Unavailable alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:37
+msgid "Unavailable color:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:39
+msgid "GHOITEMS^Black"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:40
+msgid "GHOITEMS^Dark"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:41
+msgid "GHOITEMS^Tinted"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:42
+msgid "GHOITEMS^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:43
+msgid "GHOITEMS^Blue"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:49
+#: qcsrc/menu/xonotic/serverlist.qc:737
+msgid "Players"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:51
+msgid "Force player models to mine"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:53
+msgid "Force player colors to mine"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:56
+msgid "In non teamplay modes only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:60
+msgid "Body fading:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:63
+msgid "Gibs:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:65
+msgid "GIBS^None"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:66
+msgid "GIBS^Few"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:67
+msgid "GIBS^Many"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:68
+msgid "GIBS^Lots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qh:7
+msgid "Models"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qh:8
+msgid "Customize how players and items are displayed in game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:26
+msgid "1st person perspective"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:29
+msgid "Slide to third person upon death"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:33
+msgid "Smooth the view when landing from a jump"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:37
+msgid "Smooth the view while crouching"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:41
+msgid "View waving while idle"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:45
+msgid "View bobbing while walking around"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:50
+msgid "3rd person perspective"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:53
+msgid "Back distance"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:59
+msgid "Up distance"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:65
+msgid "Allow passing through walls while spectating"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:69
+msgid "Field of view:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:71
+msgid "Field of vision in degrees"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:75
+msgid "ZOOM^Zoom factor:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:77
+msgid "How big the zoom factor is when the zoom button is pressed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:80
+msgid "ZOOM^Zoom speed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:82
+msgid "How fast the view will be zoomed, disable to zoom instantly"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:91
+msgid "ZOOM^Instant"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:95
+msgid "ZOOM^Zoom sensitivity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:97
+msgid ""
+"How zoom changes sensitivity, from 0 (lower sensitivity) to 1 (no "
+"sensitivity change)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:100
+msgid "Velocity zoom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:101
+msgid "Forward movement only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:105
+msgid "VZOOM^Factor"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:112
+msgid "Display reticle 2D overlay while zooming"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:115
+msgid "Release zoom when you die or respawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:119
+msgid "Release zoom when you switch weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qh:7
+#: qcsrc/menu/xonotic/keybinder.qc:83
+msgid "View"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:33
+msgid "Weapon Priority List (* = mutator weapon)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:39
+msgid "Up"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:43
+msgid "Down"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:49
+msgid "Use priority list for weapon cycling"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:50
+msgid ""
+"Make use of the list above when cycling through weapons with the mouse wheel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:52
+msgid "Cycle through only usable weapon selections"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:56
+msgid "Auto switch weapons on pickup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:57
+msgid ""
+"Automatically switch to newly picked up weapons if they are better than what "
+"you are carrying"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:60
+msgid "Release attack buttons when you switch weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:63
+msgid "Draw 1st person weapon model"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:64
+msgid "Draw the weapon model"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:68
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:71
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:74
+msgid "Position of the weapon model; requires reconnect"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:77
+msgid "Weapon model opacity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:91
+msgid "Gun model swaying"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:96
+msgid "Gun model bobbing"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qh:7
+#: qcsrc/menu/xonotic/keybinder.qc:51
+msgid "Weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:34
+msgid "Key Bindings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:38
+msgid "Change key..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:42
+msgid "Edit..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:48
+msgid "Clear"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:53
+msgid "Reset all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:58
+msgid "Mouse"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:60
+msgid "Sensitivity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:62
+msgid "Mouse speed multiplier"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:64
+msgid "Smooth aiming"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:65
+msgid "Smoothes the mouse movement, but makes aiming slightly less responsive"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:67
+msgid "Invert aiming"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:68
+msgid "Invert mouse movement on the Y-axis"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:70
+msgid "Use system mouse positioning"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:75
+msgid "Enable built in mouse acceleration"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:79
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:83
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:86
+msgid "Disable system mouse acceleration"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:80
+msgid "Make use of DGA mouse input"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:94
+msgid "Pressing \"enter console\" key also closes it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:95
+msgid "Allow the console toggling bind to also close the console"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:97
+msgid "Automatically repeat jumping if holding jump"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:100
+msgid "Jetpack on jump:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:102
+msgid "JPJUMP^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:103
+msgid "Air only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:104
+msgid "JPJUMP^All"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:110
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:115
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:120
+msgid "Use joystick input"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:31
+msgid "Command when pressed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:34
+msgid "Command when released:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:40
+msgid "Cancel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qh:7
+msgid "User defined key bind"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:11
+#, c-format
+msgid "%d fps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:12
+#, c-format
+msgid "%d KB/s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:13
+#, c-format
+msgid "%d MB/s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:27
+msgid "Network"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:29
+msgid "Client UDP port:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:31
+msgid "Force client to use chosen port unless it is set to 0"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:34
+msgid "Bandwidth:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:36
+msgid "Specify your network speed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:37
+msgid "56k"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:38
+msgid "ISDN"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:39
+msgid "Slow ADSL"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:40
+msgid "Fast ADSL"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:41
+msgid "Broadband"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:44
+msgid "Server queries/s:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:48
+msgid "Downloads:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:50
+msgid "Maximum number of concurrent HTTP/FTP downloads"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:52
+msgid "Download speed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:65
+msgid "Local latency:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:69
+msgid "Show netgraph"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:70
+msgid "Show a graph of packet sizes and other information"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:72
+msgid "Client-side movement prediction"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:74
+msgid "Movement error compensation"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:78
+msgid "Use encryption (AES) when available"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:81
+msgid "Framerate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:83
+msgid "Maximum:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:93
+msgid "MAXFPS^Unlimited"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:96
+msgid "Target:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:98
+msgid "TRGT^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:109
+msgid "Idle limit:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:115
+msgid "IDLFPS^Unlimited"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:119
+msgid "Save processing time for other apps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:122
+msgid "Show frames per second"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:123
+msgid "Show your rendered frames per second"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:128
+msgid "Menu tooltips:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:130
+msgid ""
+"Menu tooltips: disabled, standard or advanced (also shows cvar or console "
+"command bound to the menu item)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:131
+msgid "TLTIP^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:132
+msgid "TLTIP^Standard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:133
+msgid "TLTIP^Advanced"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:136
+msgid "Show current date and time"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:137
+msgid "Show current date and time of day, useful on screenshots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:140
+msgid "Enable developer mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:144
+msgid "Advanced settings..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:145
+msgid "Advanced settings where you can tweak every single variable of the game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:150
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qh:6
+msgid "Factory reset"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:31
+msgid "Cvar filter:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:38
+msgid "Modified cvars only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:45
+msgid "Setting:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:49
+msgid "Type:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:53
+msgid "Value:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:70
+msgid "Description:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qh:7
+msgid "Advanced settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:11
+msgid "Are you sure you want to reset all settings?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:13
+msgid "This will create a backup config in your data directory"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:23
+msgid "Menu Skins"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:62
+msgid "Text Language"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:67
+msgid "Set language"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:72
+msgid "Disable gore effects and harsh language"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:73
+msgid "Replace blood and gibs with content that does not have any gore effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:10
+msgid "While connected language changes will be applied only to the menu,"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:12
+msgid "full language changes will take effect starting from the next game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:16
+msgid "Disconnect now"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:17
+msgid "Switch language"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qh:6
+msgid "Warning"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:33
+msgid "Resolution:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:37
+msgid "Font/UI size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:39
+msgid "SZ^Unreadable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:40
+msgid "SZ^Tiny"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:41
+msgid "SZ^Little"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:42
+msgid "SZ^Small"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:43
+msgid "SZ^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:44
+msgid "SZ^Large"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:45
+msgid "SZ^Huge"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:46
+msgid "SZ^Gigantic"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:47
+msgid "SZ^Colossal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:51
+msgid "Color depth:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:53
+msgid "How many bits per pixel (BPP) to render at, 32 is recommended"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:54
+msgid "16bit"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:55
+msgid "32bit"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:59
+msgid "Full screen"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:61
+msgid "Vertical Synchronization"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:62
+msgid ""
+"Enable vertical synchronization to prevent tearing, will cap your fps to the "
+"screen refresh rate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:67
+msgid "Flip view horizontally"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:68
+msgid "Poor man's left handed mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:71
+msgid "Anisotropy:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:73
+msgid "Anisotropic filtering quality"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:74
+msgid "ANISO^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:75
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:86
+msgid "2x"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:76
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:87
+msgid "4x"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:77
+msgid "8x"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:78
+msgid "16x"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:81
+msgid "Antialiasing:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:84
+msgid ""
+"Enable antialiasing, which smooths the edges of 3D geometry. Note that it "
+"might decrease performance by quite a lot"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:85
+msgid "AA^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:92
+msgid "High-quality frame buffer"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:97
+msgid "Depth first:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:99
+msgid ""
+"Eliminate overdraw by rendering a depth-only version of the scene before the "
+"normal rendering starts"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:100
+msgid "DF^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:101
+msgid "DF^World"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:102
+msgid "DF^All"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:105
+msgid "Vertex Buffer Objects (VBOs)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:108
+msgid "VBO^Off"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:109
+msgid "Vertices, some Tris (compatible)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:110
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:114
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:116
+msgid ""
+"Make use of Vertex Buffer Objects to store static geometry in video memory "
+"for faster rendering"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:113
+msgid "Vertices"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:115
+msgid "Vertices and Triangles"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:119
+msgid "Brightness:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:121
+msgid "Brightness of black"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:123
+msgid "Contrast:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:125
+msgid "Brightness of white"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:127
+msgid "Gamma:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:130
+msgid ""
+"Inverse gamma correction value, a brightness effect that does not affect "
+"white or black"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:133
+msgid "Contrast boost:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:136
+msgid "By how much to multiply the contrast in dark areas"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:139
+msgid "Saturation:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:142
+msgid ""
+"Saturation adjustment (0 = grayscale, 1 = normal, 2 = oversaturated), "
+"requires GLSL color control"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:146
+msgid "LIT^Ambient:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:148
+msgid ""
+"Ambient lighting, if set too high it tends to make light on maps look dull "
+"and flat"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:150
+msgid "Intensity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:152
+msgid "Global rendering brightness"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:155
+msgid "Wait for GPU to finish each frame"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:156
+msgid ""
+"Make the CPU wait for the GPU to finish each frame, can help with some "
+"strange input or video lag on some machines"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:158
+msgid "Use OpenGL 2.0 shaders (GLSL)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:163
+msgid "Psycho coloring (easter egg)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:166
+msgid "Trippy vertices (easter egg)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:109
+msgid "Instant action! (random map with bots)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:116
+msgid "???"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:129
+msgid "Campaign Difficulty:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:130
+msgid "CSKL^Easy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:131
+msgid "CSKL^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:132
+msgid "CSKL^Hard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:134
+msgid "Start Singleplayer!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qh:6
+msgid "Singleplayer"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qh:7
+msgid "Play the singleplayer campaign or instant action matches against bots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7
+msgid "Winner"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:32
+msgid "join 'best' team (auto-select)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:33
+msgid "Autoselect team (recommended)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:37
+msgid "red"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:38
+msgid "blue"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:39
+msgid "yellow"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:40
+msgid "pink"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:43
+#: qcsrc/menu/xonotic/keybinder.qc:116
+msgid "spectate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qh:7
+msgid "Team Selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_uid2name.qc:10
+msgid "Allow player statistics to use your nickname?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_uid2name.qc:12
+msgid "Answering \"No\" you will appear as \"Anonymous player\""
+msgstr ""
+
+#: qcsrc/menu/xonotic/gametypelist.qc:87
+msgid "teamplay"
+msgstr ""
+
+#: qcsrc/menu/xonotic/gametypelist.qc:89
+msgid "free for all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:35
+msgid "Moving"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:36
+msgid "forward"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:37
+msgid "backpedal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:38
+msgid "strafe left"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:39
+msgid "strafe right"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:40
+msgid "jump / swim"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:41
+msgid "crouch / sink"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:42
+msgid "off-hand hook"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:43
+msgid "jetpack"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:46
+msgid "Attacking"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:52
+msgid "WEAPON^previous"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:53
+msgid "WEAPON^next"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:54
+msgid "WEAPON^previously used"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:55
+msgid "WEAPON^best"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:56
+msgid "reload"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:57
+msgid "drop weapon / throw nade"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:84
+msgid "hold zoom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:85
+msgid "toggle zoom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:86
+msgid "show scores"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:87
+msgid "screen shot"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:88
+msgid "maximize radar"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:89
+msgid "3rd person view"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:90
+msgid "enter spectator mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:93
+msgid "Communication"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:94
+msgid "public chat"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:95
+msgid "team chat"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:96
+msgid "show chat history"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:97
+msgid "vote YES"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:98
+msgid "vote NO"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:102
+msgid "Client"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:106 qcsrc/menu/xonotic/keybinder.qc:108
+msgid "enter console"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:109
+msgid "disconnect"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:110
+msgid "quit"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:114
+msgid "auto-join team"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:120
+msgid "drop key/flag, exit vehicle"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:121
+msgid "suicide / respawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:122
+msgid "quick menu"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:125
+msgid "User defined"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:132
+msgid "Development"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:133
+msgid "sandbox menu"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:134
+msgid "drag object (sandbox)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:135
+msgid "waypoint editor menu"
+msgstr ""
+
+#: qcsrc/menu/xonotic/mainwindow.qc:96 qcsrc/menu/xonotic/mainwindow.qc:99
+msgid "Do not press this button again!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/maplist.qc:288
+msgid ""
+"Huh? Can't play this (m is NULL). Refiltering so this won't happen again."
+msgstr ""
+
+#: qcsrc/menu/xonotic/maplist.qc:296
+#, c-format
+msgid "%s's Xonotic Server"
+msgstr ""
+
+#: qcsrc/menu/xonotic/maplist.qc:301
+msgid ""
+"Huh? Can't play this (invalid game type). Refiltering so this won't happen "
+"again."
+msgstr ""
+
+#: qcsrc/menu/xonotic/playerlist.qc:102 qcsrc/menu/xonotic/playerlist.qc:112
+msgid "spectator"
+msgstr ""
+
+#: qcsrc/menu/xonotic/playermodel.qc:161
+msgid "<no model found>"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:256
+msgid "SERVER^Remove favorite"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:257
+msgid "Remove the currently highlighted server from bookmarks"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:261
+msgid "SERVER^Favorite"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:262
+msgid ""
+"Bookmark the currently highlighted server so that it's faster to find in the "
+"future"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:733
+msgid "Ping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:734
+msgid "Hostname"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:735
+msgid "Map"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:736
+msgid "Type"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1019
+#, c-format
+msgid "AES level %d"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1019
+msgid "ENC^none"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1019
+msgid "encryption:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1020
+#, c-format
+msgid "mod: %s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1022
+#, c-format
+msgid "modified settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1022
+#, c-format
+msgid "official settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1024
+msgid "stats disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1024
+msgid "stats enabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:152
+msgid "SLCAT^Favorites"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:153
+msgid "SLCAT^Recommended"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:154
+msgid "SLCAT^Normal Servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:155
+msgid "SLCAT^Servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:156
+msgid "SLCAT^Competitive Mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:157
+msgid "SLCAT^Modified Servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:158
+msgid "SLCAT^Overkill"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:159
+msgid "SLCAT^InstaGib"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:160
+msgid "SLCAT^Defrag Mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/skinlist.qc:70
+msgid "<TITLE>"
+msgstr ""
+
+#: qcsrc/menu/xonotic/skinlist.qc:71
+msgid "<AUTHOR>"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_decibels.qc:72
+msgid "VOL^MAX"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_decibels.qc:74
+msgid "VOL^OFF"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_decibels.qc:82
+#, c-format
+msgid "%s dB"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:14
+msgid "PART^OMG"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:15
+msgid "PART^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:16
+msgid "PART^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:17
+#: qcsrc/menu/xonotic/slider_sbfadetime.qc:14
+msgid "PART^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:18
+msgid "PART^High"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:19
+msgid "PART^Ultra"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:20
+msgid "PART^Ultimate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_picmip.qc:13
+msgid ""
+"Change the sharpness of the textures. Lowering it will effectively reduce "
+"texture memory usage, but make the textures appear very blurry."
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_resolution.qc:115
+msgid "Screen resolution"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_sbfadetime.qc:13
+msgid "PART^Slow"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_sbfadetime.qc:15
+msgid "PART^Fast"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_sbfadetime.qc:16
+msgid "PART^Instant"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:29
+msgid "January"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:30
+msgid "February"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:31
+msgid "March"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:32
+msgid "April"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:33
+msgid "May"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:34
+msgid "June"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:35
+msgid "July"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:36
+msgid "August"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:37
+msgid "September"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:38
+msgid "October"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:39
+msgid "November"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:40
+msgid "December"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:46
+#, no-c-format
+msgid "DATE^%m %d, %Y"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:97
+msgid "Joined:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:104
+msgid "Last match:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:111
+msgid "Time played:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:118 qcsrc/menu/xonotic/statslist.qc:231
+msgid "Favorite map:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:150 qcsrc/menu/xonotic/statslist.qc:202
+#: qcsrc/menu/xonotic/statslist.qc:245
+#, c-format
+msgid "Matches:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:155
+#, c-format
+msgid "Wins/Losses:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:156
+#, c-format
+msgid "Win percentage:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:167
+#, c-format
+msgid "Kills/Deaths:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:173
+#, c-format
+msgid "Kill ratio:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:208
+msgid "ELO:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:215
+msgid "Rank:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:222
+msgid "Percentile:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:247
+#, c-format
+msgid "%d (unranked)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:420
+msgid "Update can be downloaded at:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:528
+msgid "Autogenerating mapinfo for newly added maps..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:566
+#, c-format
+msgid "Update to %s now!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:650
+msgid ""
+"^1ERROR: Texture compression is required but not supported.\n"
+"^1Expect visual problems."
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:780
+msgid "Use default"
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:800
+msgid "Team Color:"
+msgstr ""
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Translators:
+# LegendGuard, 2020
+# LegendGuard, 2020
+msgid ""
+msgstr ""
+"Project-Id-Version: Xonotic\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2020-06-07 07:23+0200\n"
+"PO-Revision-Date: 2020-07-30 22:37+0000\n"
+"Last-Translator: LegendGuard\n"
+"Language-Team: Galician (http://www.transifex.com/team-xonotic/xonotic/"
+"language/gl/)\n"
+"Language: gl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: qcsrc/client/hud/hud_config.qc:81
+#, c-format
+msgid "^2Successfully exported to %s! (Note: It's saved in data/data/)"
+msgstr ""
+
+#: qcsrc/client/hud/hud_config.qc:85
+#, c-format
+msgid "^1Couldn't write to %s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/centerprint.qc:174
+#, c-format
+msgid "^3Countdown message at time %s, seconds left: ^COUNT"
+msgstr ""
+
+#: qcsrc/client/hud/panel/centerprint.qc:176
+#, c-format
+msgid ""
+"^1Multiline message at time %s that\n"
+"^1lasts longer than normal"
+msgstr ""
+
+#: qcsrc/client/hud/panel/centerprint.qc:178
+#, c-format
+msgid "Message at time %s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/centerprint.qc:183
+msgid "Generic message"
+msgstr "Mensaxe xenérica"
+
+#: qcsrc/client/hud/panel/chat.qc:89
+msgid "^3Player^7: This is the chat area."
+msgstr "^3Xogador^7: Esta é a área de chat."
+
+#: qcsrc/client/hud/panel/engineinfo.qc:76
+#, c-format
+msgid "FPS: %.*f"
+msgstr "FPS: %.*f"
+
+#: qcsrc/client/hud/panel/infomessages.qc:95
+msgid "^1Observing"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:97
+#, c-format
+msgid "^1Spectating: ^7%s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:108
+#, c-format
+msgid "^1Press ^3%s^1 to spectate"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:108
+#: qcsrc/menu/xonotic/keybinder.qc:47
+msgid "primary fire"
+msgstr "tiro principal"
+
+#: qcsrc/client/hud/panel/infomessages.qc:110
+#, c-format
+msgid "^1Press ^3%s^1 or ^3%s^1 for next or previous player"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:110
+#: qcsrc/client/hud/panel/infomessages.qc:114
+msgid "next weapon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:110
+#: qcsrc/client/hud/panel/infomessages.qc:114
+msgid "previous weapon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:114
+#, c-format
+msgid "^1Use ^3%s^1 or ^3%s^1 to change the speed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:116
+#, c-format
+msgid "^1Press ^3%s^1 to observe, ^3%s^1 to change camera mode"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:116
+#: qcsrc/common/vehicles/cl_vehicles.qc:190
+msgid "drop weapon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:116
+#: qcsrc/menu/xonotic/keybinder.qc:48
+msgid "secondary fire"
+msgstr "tiro secundario"
+
+#: qcsrc/client/hud/panel/infomessages.qc:119
+#, c-format
+msgid "^1Press ^3%s^1 for gamemode info"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:119
+#: qcsrc/menu/xonotic/keybinder.qc:103
+msgid "server info"
+msgstr "información do servidor"
+
+#: qcsrc/client/hud/panel/infomessages.qc:132
+msgid "^1Match has already begun"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:134
+msgid "^1You have no more lives left"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:136
+#: qcsrc/client/hud/panel/infomessages.qc:139
+#, c-format
+msgid "^1Press ^3%s^1 to join"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:136
+#: qcsrc/client/hud/panel/infomessages.qc:139
+#: qcsrc/common/notifications/all.qh:430
+msgid "jump"
+msgstr "saltar"
+
+#: qcsrc/client/hud/panel/infomessages.qc:147
+#, c-format
+msgid "^1Game starts in ^3%d^1 seconds"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:153
+msgid "^2Currently in ^1warmup^2 stage!"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:168
+#, c-format
+msgid "%sPress ^3%s%s to end warmup"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:168
+#: qcsrc/client/hud/panel/infomessages.qc:170
+#: qcsrc/client/hud/panel/infomessages.qc:183
+#: qcsrc/menu/xonotic/keybinder.qc:99
+msgid "ready"
+msgstr "listo"
+
+#: qcsrc/client/hud/panel/infomessages.qc:170
+#, c-format
+msgid "%sPress ^3%s%s once you are ready"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:175
+msgid "^2Waiting for others to ready up to end warmup..."
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:177
+msgid "^2Waiting for others to ready up..."
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:183
+#, c-format
+msgid "^2Press ^3%s^2 to end warmup"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:204
+msgid "Teamnumbers are unbalanced!"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:207
+#, c-format
+msgid " Press ^3%s%s to adjust"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:207
+#: qcsrc/menu/xonotic/keybinder.qc:115
+msgid "team menu"
+msgstr "menú do equipo"
+
+#: qcsrc/client/hud/panel/infomessages.qc:217
+msgid "^1Spectating this player:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:217
+msgid "^1Spectating you:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:233
+msgid "^7Press ^3ESC ^7to show HUD options."
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:234
+msgid "^3Doubleclick ^7a panel for panel-specific options."
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:235
+msgid "^3CTRL ^7to disable collision testing, ^3SHIFT ^7and"
+msgstr ""
+
+#: qcsrc/client/hud/panel/infomessages.qc:236
+msgid "^3ALT ^7+ ^3ARROW KEYS ^7for fine adjustments."
+msgstr ""
+
+#: qcsrc/client/hud/panel/modicons.qc:183
+msgid "Personal best"
+msgstr ""
+
+#: qcsrc/client/hud/panel/modicons.qc:193
+msgid "Server best"
+msgstr ""
+
+#: qcsrc/client/hud/panel/notify.qc:127 qcsrc/client/hud/panel/notify.qc:128
+#: qcsrc/client/hud/panel/score.qc:69
+#, c-format
+msgid "Player %d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:597
+#: qcsrc/client/hud/panel/quickmenu.qc:599
+#, c-format
+msgid "Submenu%d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:604
+#, c-format
+msgid "Command%d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:630
+msgid "Continue..."
+msgstr "Continúa..."
+
+#: qcsrc/client/hud/panel/quickmenu.qc:787
+#: qcsrc/client/hud/panel/quickmenu.qc:794
+msgid "Chat"
+msgstr "Chat"
+
+#: qcsrc/client/hud/panel/quickmenu.qc:788
+msgid "QMCMD^Send public message to"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:789
+msgid "QMCMD^:-) / nice one"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:789
+msgid "QMCMD^nice one"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:790
+msgid "QMCMD^good game"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:791
+msgid "QMCMD^hi / good luck"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:791
+msgid "QMCMD^hi / good luck and have fun"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:793
+msgid "QMCMD^Send in English"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:798
+#: qcsrc/client/hud/panel/quickmenu.qc:814
+msgid "QMCMD^Team chat"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:799
+msgid "QMCMD^strength soon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:800
+msgid "QMCMD^free item %x^7 (l:%y^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:800
+msgid "QMCMD^free item, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:801
+msgid "QMCMD^took item (l:%l^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:801
+msgid "QMCMD^took item, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:802
+msgid "QMCMD^negative"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:803
+msgid "QMCMD^positive"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:804
+msgid "QMCMD^need help (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:804
+msgid "QMCMD^need help, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:805
+msgid "QMCMD^enemy seen (l:%y^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:805
+msgid "QMCMD^enemy seen, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:806
+msgid "QMCMD^flag seen (l:%y^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:806
+msgid "QMCMD^flag seen, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:807
+msgid "QMCMD^defending (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:807
+msgid "QMCMD^defending, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:808
+msgid "QMCMD^roaming (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:808
+msgid "QMCMD^roaming, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:809
+msgid "QMCMD^attacking (l:%l^7) (h:%h^7 a:%a^7 w:%w^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:809
+msgid "QMCMD^attacking, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:810
+msgid "QMCMD^killed flagcarrier (l:%y^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:810
+msgid "QMCMD^killed flagcarrier, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:811
+#, c-format
+msgid "QMCMD^dropped flag (l:%d^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:811
+msgid "QMCMD^dropped flag, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:812
+msgid "QMCMD^drop weapon, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:812
+msgid "QMCMD^dropped weapon %w^7 (l:%l^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:813
+msgid "QMCMD^drop flag/key, icon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:813
+msgid "QMCMD^dropped flag/key %w^7 (l:%l^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:817
+msgid "QMCMD^Send private message to"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:819
+#: qcsrc/client/hud/panel/quickmenu.qc:849
+msgid "QMCMD^Settings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:820
+#: qcsrc/client/hud/panel/quickmenu.qc:827
+msgid "QMCMD^View/HUD settings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:821
+msgid "QMCMD^3rd person view"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:822
+msgid "QMCMD^Player models like mine"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:823
+msgid "QMCMD^Names above players"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:824
+msgid "QMCMD^Crosshair per weapon"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:825
+msgid "QMCMD^FPS"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:826
+msgid "QMCMD^Net graph"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:829
+#: qcsrc/client/hud/panel/quickmenu.qc:832
+msgid "QMCMD^Sound settings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:830
+msgid "QMCMD^Hit sound"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:831
+msgid "QMCMD^Chat sound"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:836
+msgid "QMCMD^Change spectator camera"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:841
+#: qcsrc/client/hud/panel/quickmenu.qc:845
+msgid "QMCMD^Observer camera"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:842
+msgid "QMCMD^Increase speed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:843
+msgid "QMCMD^Decrease speed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:844
+msgid "QMCMD^Wall collision"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:848
+msgid "QMCMD^Fullscreen"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:851
+#: qcsrc/client/hud/panel/quickmenu.qc:861
+msgid "QMCMD^Call a vote"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:852
+msgid "QMCMD^Restart the map"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:853
+msgid "QMCMD^End match"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:856
+msgid "QMCMD^Reduce match time"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:857
+msgid "QMCMD^Extend match time"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:860
+msgid "QMCMD^Shuffle teams"
+msgstr ""
+
+#: qcsrc/client/hud/panel/quickmenu.qc:865
+msgid "QMCMD^Spectate a player"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:59
+#, c-format
+msgid " (-%dL)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:64
+#, c-format
+msgid " (+%dL)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:83
+msgid "Start line"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:85
+#: qcsrc/client/hud/panel/racetimer.qc:89
+msgid "Finish line"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:87
+#: qcsrc/client/hud/panel/racetimer.qc:156
+#, c-format
+msgid "Intermediate %d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:159
+#: qcsrc/client/hud/panel/racetimer.qc:206
+#: qcsrc/client/hud/panel/racetimer.qc:267
+#, c-format
+msgid "PENALTY: %.1f (%s)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/racetimer.qc:159 qcsrc/client/main.qc:1102
+msgid "missing a checkpoint"
+msgstr ""
+
+#: qcsrc/client/hud/panel/radar.qc:386
+msgid "Click to select teleport destination"
+msgstr ""
+
+#: qcsrc/client/hud/panel/radar.qc:390
+msgid "Click to select spawn location"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:105
+msgid "Number of ball carrier kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:105
+msgid "SCO^bckills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:106
+msgid "SCO^bctime"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:106
+msgid "Total amount of time holding the ball in Keepaway"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:107
+msgid "How often a flag (CTF) or a key (KeyHunt) was captured"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:107
+msgid "SCO^caps"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:108
+msgid "SCO^captime"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:108
+msgid "Time of fastest capture (CTF)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:109
+msgid "Number of deaths"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:109
+msgid "SCO^deaths"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:110
+msgid "Number of keys destroyed by pushing them into void"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:110
+msgid "SCO^destroyed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:111
+msgid "SCO^damage"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:111
+msgid "The total damage done"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:112
+msgid "SCO^dmgtaken"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:112
+msgid "The total damage taken"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:113
+msgid "Number of flag drops"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:113
+msgid "SCO^drops"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:114
+msgid "Player ELO"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:114
+msgid "SCO^elo"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:115
+msgid "SCO^fastest"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:115
+msgid "Time of fastest lap (Race/CTS)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:116
+msgid "Number of faults committed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:116
+msgid "SCO^faults"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:117
+msgid "Number of flag carrier kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:117
+msgid "SCO^fckills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:118
+msgid "FPS"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:118
+msgid "SCO^fps"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:119
+msgid "Number of kills minus suicides"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:119
+msgid "SCO^frags"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:120
+msgid "Number of goals scored"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:120
+msgid "SCO^goals"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:121
+msgid "Number of keys carrier kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:121
+msgid "SCO^kckills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:122
+msgid "SCO^k/d"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:122
+#: qcsrc/client/hud/panel/scoreboard.qc:123
+#: qcsrc/client/hud/panel/scoreboard.qc:124
+msgid "The kill-death ratio"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:123
+msgid "SCO^kdr"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:124
+msgid "SCO^kdratio"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:125
+msgid "Number of kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:125
+msgid "SCO^kills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:126
+msgid "Number of laps finished (Race/CTS)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:126
+msgid "SCO^laps"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:127
+msgid "Number of lives (LMS)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:127
+msgid "SCO^lives"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:128
+msgid "Number of times a key was lost"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:128
+msgid "SCO^losses"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:129
+#: qcsrc/client/hud/panel/scoreboard.qc:130
+msgid "Player name"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:129
+msgid "SCO^name"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:130
+msgid "SCO^nick"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:131
+msgid "Number of objectives destroyed"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:131
+msgid "SCO^objectives"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:132
+msgid ""
+"How often a flag (CTF) or a key (KeyHunt) or a ball (Keepaway) was picked up"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:132
+msgid "SCO^pickups"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:133
+msgid "Ping time"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:133
+msgid "SCO^ping"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:134
+msgid "Packet loss"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:134
+msgid "SCO^pl"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:135
+msgid "Number of players pushed into void"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:135
+msgid "SCO^pushes"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:136
+msgid "Player rank"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:136
+msgid "SCO^rank"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:137
+msgid "Number of flag returns"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:137
+msgid "SCO^returns"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:138
+msgid "Number of revivals"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:138
+msgid "SCO^revivals"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:139
+msgid "Number of rounds won"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:139
+msgid "SCO^rounds won"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:140
+msgid "SCO^score"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:140
+msgid "Total score"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:141
+msgid "Number of suicides"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:141
+msgid "SCO^suicides"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:142
+msgid "Number of kills minus deaths"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:142
+msgid "SCO^sum"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:143
+msgid "Number of domination points taken (Domination)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:143
+msgid "SCO^takes"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:144
+msgid "Number of teamkills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:144
+msgid "SCO^teamkills"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:145
+msgid "Number of ticks (Domination)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:145
+msgid "SCO^ticks"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:146
+msgid "SCO^time"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:146
+msgid "Total time raced (Race/CTS)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:330
+msgid ""
+"You can modify the scoreboard using the ^2scoreboard_columns_set command."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:331
+msgid "Usage:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:333
+msgid "^2scoreboard_columns_set ^3field1 field2 ..."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:334
+msgid ""
+"^2scoreboard_columns_set ^7without arguments reads the arguments from the "
+"cvar scoreboard_columns"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:335
+msgid ""
+" ^5Note: ^7scoreboard_columns_set without arguments is executed on every "
+"map start"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:336
+msgid ""
+"^2scoreboard_columns_set ^3expand_default ^7loads default layout and expands "
+"it into the cvar scoreboard_columns so you can edit it"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:337
+msgid "You can use a ^3|^7 to start the right-aligned fields."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:338
+msgid "The following field names are recognized (case insensitive):"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:344
+msgid ""
+"Before a field you can put a + or - sign, then a comma separated list\n"
+"of game types, then a slash, to make the field show up only in these\n"
+"or in all but these game types. You can also specify 'all' as a\n"
+"field to show all fields available for the current game mode."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:350
+msgid ""
+"The special game type names 'teams' and 'noteams' can be used to\n"
+"include/exclude ALL teams/noteams game modes."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:354
+msgid "Example: scoreboard_columns_set name ping pl | +ctf/field3 -dm/field4"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:355
+msgid ""
+"will display name, ping and pl aligned to the left, and the fields\n"
+"right of the vertical bar aligned to the right."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:357
+msgid ""
+"'field3' will only be shown in CTF, and 'field4' will be shown in all\n"
+"other gamemodes except DM."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:621
+#: qcsrc/client/hud/panel/scoreboard.qc:628
+#: qcsrc/client/hud/panel/scoreboard.qc:680
+#: qcsrc/client/hud/panel/scoreboard.qc:691
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:46
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:47
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:121
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:164
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:169
+msgid "N/A"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1206
+#, c-format
+msgid "Accuracy stats (average %d%%)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1354
+msgid "Map stats:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1384
+msgid "Monsters killed:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1391
+msgid "Secrets found:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1413
+msgid "Capture time rankings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1413
+msgid "Rankings"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1631
+#, c-format
+msgid "^3%1.0f minutes"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1640
+#: qcsrc/client/hud/panel/scoreboard.qc:1647
+#, c-format
+msgid "^5%s %s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1641
+#: qcsrc/client/hud/panel/scoreboard.qc:1648
+#: qcsrc/client/hud/panel/scoreboard.qc:1667
+#: qcsrc/client/hud/panel/scoreboard.qc:1674
+msgid "SCO^points"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1666
+#: qcsrc/client/hud/panel/scoreboard.qc:1673
+#, c-format
+msgid "^2+%s %s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1684
+#, c-format
+msgid "^7Map: ^2%s"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1823
+#, c-format
+msgid "Speed award: %d%s ^7(%s^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1827
+#, c-format
+msgid "All-time fastest: %d%s ^7(%s^7)"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1843
+#, c-format
+msgid "Spectators"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1870
+#, c-format
+msgid "^1Respawning in ^3%s^1..."
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1880
+#, c-format
+msgid "You are dead, wait ^3%s^7 before respawning"
+msgstr ""
+
+#: qcsrc/client/hud/panel/scoreboard.qc:1889
+#, c-format
+msgid "You are dead, press ^2%s^7 to respawn"
+msgstr ""
+
+#: qcsrc/client/hud/panel/timer.qc:72
+msgid "WARMUP"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:33
+msgid "^1You must answer before entering hud configure mode"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:36
+msgid "^2Name ^7instead of \"^1Anonymous player^7\" in stats"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:122
+msgid "A vote has been called for:"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:124
+msgid "Allow servers to store and display your name?"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:128
+msgid "^1Configure the HUD"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:132
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:19
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:82
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:18
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:18
+#: qcsrc/menu/xonotic/dialog_quit.qc:14
+#: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qc:14
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:26
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:16
+#: qcsrc/menu/xonotic/dialog_uid2name.qc:15
+msgid "Yes"
+msgstr ""
+
+#: qcsrc/client/hud/panel/vote.qc:134
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:22
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:83
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:21
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:21
+#: qcsrc/menu/xonotic/dialog_quit.qc:16
+#: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qc:17
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:29
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:17
+#: qcsrc/menu/xonotic/dialog_uid2name.qc:17
+msgid "No"
+msgstr ""
+
+#: qcsrc/client/hud/panel/weapons.qc:584
+msgid "Out of ammo"
+msgstr ""
+
+#: qcsrc/client/hud/panel/weapons.qc:588
+msgid "Don't have"
+msgstr ""
+
+#: qcsrc/client/hud/panel/weapons.qc:592
+msgid "Unavailable"
+msgstr ""
+
+#: qcsrc/client/main.qc:1000
+msgid " qu/s"
+msgstr ""
+
+#: qcsrc/client/main.qc:1002
+msgid " m/s"
+msgstr ""
+
+#: qcsrc/client/main.qc:1004
+msgid " km/h"
+msgstr ""
+
+#: qcsrc/client/main.qc:1006
+msgid " mph"
+msgstr ""
+
+#: qcsrc/client/main.qc:1008
+msgid " knots"
+msgstr ""
+
+#: qcsrc/client/main.qc:1255
+#, c-format
+msgid "%s (not bound)"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:59
+msgid " (1 vote)"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:61
+#, c-format
+msgid " (%d votes)"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:281
+msgid "Don't care"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:382
+msgid "Decide the gametype"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:382
+msgid "Vote for a map"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:399
+#, c-format
+msgid "%d seconds left"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:512
+msgid "mv_mapdownload: ^3You're not supposed to use this command on your own!"
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:522
+msgid "^1Error:^7 Couldn't find pak index."
+msgstr ""
+
+#: qcsrc/client/mapvoting.qc:531
+msgid "Requesting preview..."
+msgstr ""
+
+#: qcsrc/client/miscfunctions.qc:111
+msgid "Trying to remove a team which is not in the teamlist!"
+msgstr ""
+
+#: qcsrc/client/view.qc:939
+msgid "Nade timer"
+msgstr ""
+
+#: qcsrc/client/view.qc:944
+msgid "Capture progress"
+msgstr ""
+
+#: qcsrc/client/view.qc:949
+msgid "Revival progress"
+msgstr ""
+
+#: qcsrc/common/command/generic.qc:156
+msgid "error creating curl handle"
+msgstr ""
+
+#: qcsrc/common/command/generic.qc:412
+msgid "Notification restart command only works with cl_cmd and sv_cmd."
+msgstr ""
+
+#: qcsrc/common/gamemodes/gamemode/nexball/weapon.qh:7
+msgid "Ball Stealer"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:66
+msgid "bullets"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:96
+msgid "cells"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:126
+msgid "plasma"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:156
+msgid "rockets"
+msgstr ""
+
+#: qcsrc/common/items/item/ammo.qh:190
+msgid "shells"
+msgstr ""
+
+#: qcsrc/common/items/item/armor.qh:42
+msgid "Small armor"
+msgstr ""
+
+#: qcsrc/common/items/item/armor.qh:80
+msgid "Medium armor"
+msgstr ""
+
+#: qcsrc/common/items/item/armor.qh:118 qcsrc/common/items/item/armor.qh:121
+msgid "Big armor"
+msgstr ""
+
+#: qcsrc/common/items/item/armor.qh:158 qcsrc/common/items/item/armor.qh:161
+msgid "Mega armor"
+msgstr ""
+
+#: qcsrc/common/items/item/health.qh:42
+msgid "Small health"
+msgstr ""
+
+#: qcsrc/common/items/item/health.qh:80
+msgid "Medium health"
+msgstr ""
+
+#: qcsrc/common/items/item/health.qh:118 qcsrc/common/items/item/health.qh:121
+msgid "Big health"
+msgstr ""
+
+#: qcsrc/common/items/item/health.qh:158 qcsrc/common/items/item/health.qh:161
+msgid "Mega health"
+msgstr ""
+
+#: qcsrc/common/items/item/jetpack.qh:38 qcsrc/common/items/item/jetpack.qh:41
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:91
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:215
+msgid "Jetpack"
+msgstr ""
+
+#: qcsrc/common/items/item/jetpack.qh:71
+msgid "fuel"
+msgstr ""
+
+#: qcsrc/common/items/item/jetpack.qh:96
+msgid "Fuel regenerator"
+msgstr ""
+
+#: qcsrc/common/items/item/jetpack.qh:99
+msgid "Fuel regen"
+msgstr ""
+
+#: qcsrc/common/items/item/powerup.qh:43 qcsrc/common/items/item/powerup.qh:46
+msgid "Strength"
+msgstr ""
+
+#: qcsrc/common/items/item/powerup.qh:79 qcsrc/common/items/item/powerup.qh:82
+msgid "Shield"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qc:626
+#, no-c-format
+msgid "@!#%'n Tuba Throwing"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:72 qcsrc/common/mapinfo.qh:334
+#: qcsrc/common/mapinfo.qh:529
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:105
+msgid "Frag limit:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:72 qcsrc/common/mapinfo.qh:334
+#: qcsrc/common/mapinfo.qh:529
+msgid "The amount of frags needed before the match will end"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:115
+msgid "Deathmatch"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:115
+msgid "Score as many frags as you can"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:128
+msgid "Last Man Standing"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:128
+msgid "Survive and kill until the enemies have no lives left"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:137
+msgid "Lives:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:149
+msgid "Race"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:149
+msgid "Race against other players to the finish line"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:176
+msgid "Laps:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:189
+msgid "Race CTS"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:189
+msgid "Race for fastest time."
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:206 qcsrc/common/mapinfo.qh:257
+#: qcsrc/common/mapinfo.qh:373 qcsrc/common/mapinfo.qh:416
+#: qcsrc/common/mapinfo.qh:442 qcsrc/common/mapinfo.qh:462
+#: qcsrc/common/mapinfo.qh:582
+msgid "Point limit:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:219
+msgid "Help your team score the most frags against the enemy team"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:219
+msgid "Team Deathmatch"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:257 qcsrc/common/mapinfo.qh:373
+#: qcsrc/common/mapinfo.qh:416
+msgid "The amount of points needed before the match will end"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:271
+msgid "Capture the Flag"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:271
+msgid ""
+"Find and bring the enemy flag to your base to capture it, defend your base "
+"from the other team"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:289
+msgid "Capture limit:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:289
+msgid "The amount of captures needed before the match will end"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:306
+msgid "Clan Arena"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:306
+msgid "Kill all enemy teammates to win the round"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:350
+msgid "Capture and defend all the control points to win"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:350
+msgid "Domination"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:388
+msgid "Gather all the keys to win the round"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:388
+msgid "Key Hunt"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:428
+msgid "Assault"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:428
+msgid ""
+"Destroy obstacles to find and destroy the enemy power core before time runs "
+"out"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:452
+msgid "Capture control points to reach and destroy the enemy generator"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:452
+msgid "Onslaught"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:474
+msgid "Nexball"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:474
+msgid "Shoot and kick the ball into the enemies goal, keep your goal clean"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:488
+msgid "Goals:"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:488
+msgid "The amount of goals needed before the match will end"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:501
+msgid "Freeze Tag"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:501
+msgid ""
+"Kill enemies to freeze them, stand next to frozen teammates to revive them; "
+"freeze all enemies to win"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:545
+msgid "Hold the ball to get points for kills"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:545
+msgid "Keepaway"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:560
+msgid "Invasion"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:560
+msgid "Survive against waves of monsters"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:590
+msgid "Duel"
+msgstr ""
+
+#: qcsrc/common/mapinfo.qh:590
+msgid "Fight in a one versus one arena battle to decide the winner"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames.qc:383
+msgid "It's your turn"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:366
+#: qcsrc/menu/xonotic/dialog_quit.qh:6
+msgid "Quit"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:371
+msgid "Invite"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:410
+msgid "Current Game"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:435
+msgid "Exit Menu"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:447
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:16
+msgid "Create"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:450
+msgid "Join"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:526
+msgid "Minigames"
+msgstr ""
+
+#: qcsrc/common/minigames/cl_minigames_hud.qc:587
+msgid "Minigame message"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:2
+msgid "Bulldozer"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1092
+#: qcsrc/common/minigames/minigame/ps.qc:421
+#: qcsrc/common/minigames/minigame/ps.qc:427
+msgid "Game over!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1095
+msgid "Well done! Click 'Next Level' to continue"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1162
+msgid "Better luck next time!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1167
+msgid "Tubular! Press \"Next Level\" to continue!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1169
+msgid "Wicked! Press \"Next Level\" to continue!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1173
+msgid "Press the space bar to change your currently selected tile"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1176
+msgid "Push the boulders onto the targets"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1403
+msgid "Next Level"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1404
+msgid "Restart"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1405
+msgid "Editor"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/bd.qc:1406
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:37
+msgid "Save"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:2
+msgid "Connect Four"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:311
+#: qcsrc/common/minigames/minigame/c4.qc:317
+#: qcsrc/common/minigames/minigame/nmm.qc:491
+#: qcsrc/common/minigames/minigame/nmm.qc:497
+#: qcsrc/common/minigames/minigame/pp.qc:362
+#: qcsrc/common/minigames/minigame/pp.qc:368
+#, c-format
+msgid "%s^7 won the game!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:373
+#: qcsrc/common/minigames/minigame/pp.qc:438
+#: qcsrc/common/minigames/minigame/ttt.qc:319
+msgid "Draw"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:378
+#: qcsrc/common/minigames/minigame/nmm.qc:606
+#: qcsrc/common/minigames/minigame/pp.qc:444
+#: qcsrc/common/minigames/minigame/ttt.qc:326
+msgid "You lost the game!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:379
+#: qcsrc/common/minigames/minigame/nmm.qc:607
+#: qcsrc/common/minigames/minigame/pp.qc:445
+#: qcsrc/common/minigames/minigame/ttt.qc:327
+msgid "You win!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:383
+#: qcsrc/common/minigames/minigame/nmm.qc:611
+#: qcsrc/common/minigames/minigame/pp.qc:456
+#: qcsrc/common/minigames/minigame/ttt.qc:338
+msgid "Wait for your opponent to make their move"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/c4.qc:386
+#: qcsrc/common/minigames/minigame/nmm.qc:613
+#: qcsrc/common/minigames/minigame/pp.qc:459
+#: qcsrc/common/minigames/minigame/ttt.qc:341
+msgid "Click on the game board to place your piece"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/nmm.qc:7
+msgid "Nine Men's Morris"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/nmm.qc:615
+msgid ""
+"You can select one of your pieces to move it in one of the surrounding places"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/nmm.qc:617
+msgid "You can select one of your pieces to move it anywhere on the board"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/nmm.qc:619
+msgid "You can take one of the opponent's pieces"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:2
+msgid "Pong"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:589
+#: qcsrc/common/minigames/minigame/ttt.qc:299
+msgid "AI"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:606
+msgid "Press ^1Start Match^7 to start the match with the current players"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:679
+msgid "Start Match"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:680
+msgid "Add AI player"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pong.qc:681
+msgid "Remove AI player"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:2
+msgid "Push-Pull"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:444
+#: qcsrc/common/minigames/minigame/ttt.qc:326
+msgid "Select \"^1Next Match^7\" on the menu for a rematch!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:445
+#: qcsrc/common/minigames/minigame/pp.qc:451
+#: qcsrc/common/minigames/minigame/ttt.qc:327
+#: qcsrc/common/minigames/minigame/ttt.qc:333
+msgid "Select \"^1Next Match^7\" on the menu to start a new match!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:452
+#: qcsrc/common/minigames/minigame/ttt.qc:334
+msgid "Wait for your opponent to confirm the rematch"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/pp.qc:587
+#: qcsrc/common/minigames/minigame/ttt.qc:671
+msgid "Next Match"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:2
+msgid "Peg Solitaire"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:414
+msgid "All pieces cleared!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:416
+msgid "Remaining pieces:"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:481
+#, c-format
+msgid "Pieces left: %s"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:491
+msgid "No more valid moves"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:494
+msgid "Well done, you win!"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ps.qc:497
+msgid "Jump a piece over another to capture it"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ttt.qc:2
+msgid "Tic Tac Toe"
+msgstr ""
+
+#: qcsrc/common/minigames/minigame/ttt.qc:672
+msgid "Single Player"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/mage.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:18
+msgid "Mage"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/mage.qh:29
+msgid "Mage spike"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/shambler.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:17
+msgid "Shambler"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/spider.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:16
+msgid "Spider"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/spider.qh:28
+msgid "Spider attack"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/wyvern.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:19
+msgid "Wyvern"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/wyvern.qh:28
+msgid "Wyvern attack"
+msgstr ""
+
+#: qcsrc/common/monsters/monster/zombie.qh:17
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:15
+msgid "Zombie"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:16
+msgid "Ammo"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:25
+msgid "Resistance"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:34
+#: qcsrc/common/mutators/mutator/instagib/items.qh:126
+#: qcsrc/common/mutators/mutator/instagib/items.qh:129
+msgid "Speed"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:44
+msgid "Medic"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:54
+msgid "Bash"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:63
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:83
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:184
+msgid "Vampire"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:71
+msgid "Disability"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:79
+msgid "Vengeance"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:87
+msgid "Jump"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:96
+msgid "Invisible"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:105
+msgid "Inferno"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:113
+msgid "Swapper"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:121
+msgid "Magnet"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:129
+msgid "Luck"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/all.inc:137
+msgid "Flight"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/buffs/buffs.qh:11
+msgid "Buff"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:8
+msgid "Damage text"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:18
+msgid "Draw damage numbers"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:20
+msgid "Font size minimum:"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:25
+msgid "Font size maximum:"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:30
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:55
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:102
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:60
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:109
+#: qcsrc/menu/xonotic/util.qc:775
+msgid "Color:"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/damagetext/ui_damagetext.qc:36
+msgid "Draw damage numbers for friendly fire"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/instagib/items.qh:33
+msgid "Vaporizer ammo"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/instagib/items.qh:59
+#: qcsrc/common/mutators/mutator/instagib/items.qh:62
+msgid "Extra life"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/instagib/items.qh:91
+#: qcsrc/common/mutators/mutator/instagib/items.qh:94
+msgid "Invisibility"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:18
+msgid "Napalm grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:26
+msgid "Ice grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:34
+msgid "Translocate grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:42
+msgid "Spawn grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:50
+msgid "Heal grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:58
+msgid "Monster grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:66
+msgid "Entrap grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.inc:74
+msgid "Veil grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/nades/nades.qh:33
+msgid "Grenade"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/okhmg.qh:20
+msgid "Overkill Heavy Machine Gun"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/okmachinegun.qh:18
+msgid "Overkill MachineGun"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/oknex.qh:19
+msgid "Overkill Nex"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/okrpc.qh:20
+msgid "Overkill Rocket Propelled Chainsaw"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/overkill/okshotgun.qh:18
+msgid "Overkill Shotgun"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:3
+msgid "Waypoint"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:4
+msgid "Help me!"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:5
+msgid "Here"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:6
+msgid "DANGER"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:8
+msgid "Frozen!"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:10
+msgid "Item"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:12
+msgid "Checkpoint"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:13
+#: qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc:240
+msgid "Finish"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:14
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:15
+#: qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc:240
+msgid "Start"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:17
+msgid "Defend"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:18
+msgid "Destroy"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:19
+msgid "Push"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:21
+msgid "Flag carrier"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:22
+msgid "Enemy carrier"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:23
+msgid "Dropped flag"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:24
+msgid "White base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:25
+msgid "Red base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:26
+msgid "Blue base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:27
+msgid "Yellow base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:28
+msgid "Pink base"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:29
+msgid "Return flag here"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:31
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:32
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:33
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:34
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:35
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:51
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:52
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:53
+msgid "Control point"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:37
+msgid "Dropped key"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:38
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:40
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:41
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:42
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:43
+msgid "Key carrier"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:39
+msgid "Run here"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:45
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:48
+msgid "Ball"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:46
+msgid "Ball carrier"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:49
+msgid "Goal"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:54
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:55
+msgid "Generator"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:57
+msgid "Weapon"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:59
+msgid "Monster"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:61
+msgid "Vehicle"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:62
+msgid "Intruder!"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/all.inc:64
+msgid "Tagged"
+msgstr ""
+
+#: qcsrc/common/mutators/mutator/waypoints/waypointsprites.qc:697
+#, c-format
+msgid "%s needing help!"
+msgstr ""
+
+#: qcsrc/common/net_notice.qc:90
+msgid "^1Server notices:"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:230
+msgid "^F4NOTE: ^BGSpectator chat is not sent to players during the match"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:232
+#, c-format
+msgid "^BG%s^BG captured the ^TC^TT^BG flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:233
+#, c-format
+msgid ""
+"^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds, breaking ^BG"
+"%s^BG's previous record of ^F2%s^BG seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:234
+#, c-format
+msgid "^BG%s^BG captured the flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:235
+#, c-format
+msgid "^BG%s^BG captured the ^TC^TT^BG flag in ^F1%s^BG seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:236
+#, c-format
+msgid ""
+"^BG%s^BG captured the ^TC^TT^BG flag in ^F2%s^BG seconds, failing to break "
+"^BG%s^BG's previous record of ^F1%s^BG seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:237
+msgid "^BGThe ^TC^TT^BG flag was returned to base by its owner"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:238
+msgid "^BGThe flag was returned by its owner"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:239
+msgid "^BGThe ^TC^TT^BG flag was destroyed and returned to base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:240
+msgid "^BGThe flag was destroyed and returned to base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:241
+msgid "^BGThe ^TC^TT^BG flag was dropped in the base and returned itself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:242
+msgid "^BGThe flag was dropped in the base and returned itself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:243
+msgid ""
+"^BGThe ^TC^TT^BG flag fell somewhere it couldn't be reached and returned to "
+"base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:244
+msgid "^BGThe flag fell somewhere it couldn't be reached and returned to base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:245
+#, c-format
+msgid ""
+"^BGThe ^TC^TT^BG flag became impatient after ^F1%.2f^BG seconds and returned "
+"itself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:246
+#, c-format
+msgid ""
+"^BGThe flag became impatient after ^F1%.2f^BG seconds and returned itself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:247
+msgid "^BGThe ^TC^TT^BG flag has returned to the base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:248
+msgid "^BGThe flag has returned to the base"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:249
+#, c-format
+msgid "^BG%s^BG lost the ^TC^TT^BG flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:250
+#, c-format
+msgid "^BG%s^BG lost the flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:251
+#, c-format
+msgid "^BG%s^BG got the ^TC^TT^BG flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:252
+#, c-format
+msgid "^BG%s^BG got the flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:253
+#: qcsrc/common/notifications/all.inc:254
+#, c-format
+msgid "^BG%s^BG returned the ^TC^TT^BG flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:256
+#: qcsrc/common/notifications/all.inc:544
+#, c-format
+msgid "^F2Throwing coin... Result: %s^F2!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:258
+msgid "^BGYou don't have any fuel for the ^F1Jetpack"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:260
+msgid "^F2You lack a UID, superspec options will not be saved/restored"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:262
+msgid "^F1Round already started, you will join the game in the next round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:263
+msgid "^F2You will spectate in the next round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:265
+#, c-format
+msgid "^BG%s%s^K1 was killed by ^BG%s^K1's ^BG%s^K1 buff ^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:265
+#, c-format
+msgid "^BG%s%s^K1 was scored against by ^BG%s^K1's ^BG%s^K1 buff ^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:266
+#, c-format
+msgid "^BG%s%s^K1 was unfairly eliminated by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:267
+#, c-format
+msgid "^BG%s%s^K1 was drowned by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:268
+#, c-format
+msgid "^BG%s%s^K1 was grounded by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:269
+#, c-format
+msgid "^BG%s%s^K1 felt a little hot from ^BG%s^K1's fire^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:269
+#, c-format
+msgid "^BG%s%s^K1 was burnt up into a crisp by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:270
+#, c-format
+msgid "^BG%s%s^K1 was cooked by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:271
+#, c-format
+msgid "^BG%s%s^K1 was pushed in front of a monster by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:272
+#, c-format
+msgid "^BG%s%s^K1 was blown up by ^BG%s^K1's Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:273
+#, c-format
+msgid "^BG%s%s^K1 got too close to a napalm explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:273
+#, c-format
+msgid "^BG%s%s^K1 was burned to death by ^BG%s^K1's Napalm Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:274
+#, c-format
+msgid "^BG%s%s^K1 was blown up by ^BG%s^K1's Ice Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:275
+#, c-format
+msgid "^BG%s%s^K1 was frozen to death by ^BG%s^K1's Ice Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:276
+#, c-format
+msgid "^BG%s%s^K1 has not been healed by ^BG%s^K1's Healing Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:277
+#, c-format
+msgid "^BG%s%s^K1 was shot into space by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:278
+#, c-format
+msgid "^BG%s%s^K1 was slimed by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:279
+#, c-format
+msgid "^BG%s%s^K1 was preserved by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:280
+#, c-format
+msgid "^BG%s%s^K1 tried to occupy ^BG%s^K1's teleport destination space%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:280
+#, c-format
+msgid "^BG%s%s^K1 was telefragged by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:281
+#, c-format
+msgid "^BG%s%s^K1 died in an accident with ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:282
+#, c-format
+msgid ""
+"^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Bumblebee exploded%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:283
+#, c-format
+msgid "^BG%s%s^K1 saw the pretty lights of ^BG%s^K1's Bumblebee gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:284
+#, c-format
+msgid "^BG%s%s^K1 was crushed by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:285
+#, c-format
+msgid "^BG%s%s^K1 was cluster bombed by ^BG%s^K1's Raptor%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:286
+#, c-format
+msgid "^BG%s%s^K1 couldn't resist ^BG%s^K1's purple blobs%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:287
+#, c-format
+msgid "^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Raptor exploded%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:288
+#, c-format
+msgid ""
+"^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Spiderbot exploded%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:289
+#, c-format
+msgid "^BG%s%s^K1 got shredded by ^BG%s^K1's Spiderbot%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:290
+#, c-format
+msgid "^BG%s%s^K1 was blasted to bits by ^BG%s^K1's Spiderbot%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:291
+#, c-format
+msgid "^BG%s%s^K1 got caught in the blast when ^BG%s^K1's Racer exploded%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:292
+#, c-format
+msgid "^BG%s%s^K1 was bolted down by ^BG%s^K1's Racer%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:293
+#, c-format
+msgid "^BG%s%s^K1 couldn't find shelter from ^BG%s^K1's Racer%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:294
+#, c-format
+msgid "^BG%s%s^K1 was thrown into a world of hurt by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:296
+#, c-format
+msgid "^BG%s^K1 was moved into the %s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:297
+#, c-format
+msgid "^BG%s^K1 became enemies with the Lord of Teamplay%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:298
+#, c-format
+msgid "^BG%s^K1 thought they found a nice camping ground%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:299
+#, c-format
+msgid "^BG%s^K1 unfairly eliminated themself%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:301
+#, c-format
+msgid "^BG%s^K1 couldn't catch their breath%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:301
+#, c-format
+msgid "^BG%s^K1 was in the water for too long%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:302
+#, c-format
+msgid "^BG%s^K1 hit the ground with a bit too much force%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:302
+#, c-format
+msgid "^BG%s^K1 hit the ground with a crunch%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:303
+#, c-format
+msgid "^BG%s^K1 became a bit too crispy%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:303
+#, c-format
+msgid "^BG%s^K1 felt a little hot%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:304
+#, c-format
+msgid "^BG%s^K1 died%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:305
+#, c-format
+msgid "^BG%s^K1 found a hot place%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:305
+#, c-format
+msgid "^BG%s^K1 turned into hot slag%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:306
+#, c-format
+msgid "^BG%s^K1 was exploded by a Mage%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:307
+#, c-format
+msgid "^BG%s^K1's innards became outwards by a Shambler%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:308
+#, c-format
+msgid "^BG%s^K1 was smashed by a Shambler%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:309
+#, c-format
+msgid "^BG%s^K1 was zapped to death by a Shambler%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:310
+#, c-format
+msgid "^BG%s^K1 was bitten by a Spider%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:311
+#, c-format
+msgid "^BG%s^K1 was fireballed by a Wyvern%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:312
+#, c-format
+msgid "^BG%s^K1 joins the Zombies%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:313
+#, c-format
+msgid "^BG%s^K1 was given kung fu lessons by a Zombie%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:314
+#: qcsrc/common/notifications/all.inc:316
+#, c-format
+msgid "^BG%s^K1 mastered the art of self-nading%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:315
+#, c-format
+msgid ""
+"^BG%s^K1 decided to take a look at the results of their napalm explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:315
+#, c-format
+msgid "^BG%s^K1 was burned to death by their own Napalm Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:317
+#, c-format
+msgid "^BG%s^K1 felt a little chilly%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:317
+#, c-format
+msgid "^BG%s^K1 was frozen to death by their own Ice Nade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:318
+#, c-format
+msgid "^BG%s^K1's Healing Nade didn't quite heal them%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:319
+#, c-format
+msgid "^BG%s^K1 died%s%s. What's the point of living without ammo?"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:319
+#, c-format
+msgid "^BG%s^K1 ran out of ammo%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:320
+#, c-format
+msgid "^BG%s^K1 rotted away%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:321
+#, c-format
+msgid "^BG%s^K1 became a shooting star%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:322
+#, c-format
+msgid "^BG%s^K1 was slimed%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:323
+#, c-format
+msgid "^BG%s^K1 couldn't take it anymore%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:324
+#, c-format
+msgid "^BG%s^K1 is now preserved for centuries to come%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:325
+#, c-format
+msgid "^BG%s^K1 switched to the %s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:326
+#, c-format
+msgid "^BG%s^K1 died in an accident%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:327
+#, c-format
+msgid "^BG%s^K1 ran into a turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:328
+#, c-format
+msgid "^BG%s^K1 was blasted away by an eWheel turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:329
+#, c-format
+msgid "^BG%s^K1 got caught up in the FLAC turret fire%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:330
+#, c-format
+msgid "^BG%s^K1 was blasted away by a Hellion turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:331
+#, c-format
+msgid "^BG%s^K1 could not hide from the Hunter turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:332
+#, c-format
+msgid "^BG%s^K1 was riddled full of holes by a Machinegun turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:333
+#, c-format
+msgid "^BG%s^K1 got turned into smoldering gibs by an MLRS turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:334
+#, c-format
+msgid "^BG%s^K1 was phased out by a turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:335
+#, c-format
+msgid "^BG%s^K1 got served some superheated plasma from a turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:336
+#, c-format
+msgid "^BG%s^K1 was electrocuted by a Tesla turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:337
+#, c-format
+msgid "^BG%s^K1 got served a lead enrichment by a Walker turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:338
+#, c-format
+msgid "^BG%s^K1 was impaled by a Walker turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:339
+#, c-format
+msgid "^BG%s^K1 was blasted away by a Walker turret%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:340
+#, c-format
+msgid "^BG%s^K1 got caught in the blast of a Bumblebee explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:341
+#, c-format
+msgid "^BG%s^K1 was crushed by a vehicle%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:342
+#, c-format
+msgid "^BG%s^K1 was caught in a Raptor cluster bomb%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:343
+#, c-format
+msgid "^BG%s^K1 got caught in the blast of a Raptor explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:344
+#, c-format
+msgid "^BG%s^K1 got caught in the blast of a Spiderbot explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:345
+#, c-format
+msgid "^BG%s^K1 was blasted to bits by a Spiderbot rocket%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:346
+#, c-format
+msgid "^BG%s^K1 got caught in the blast of a Racer explosion%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:347
+#, c-format
+msgid "^BG%s^K1 couldn't find shelter from a Racer rocket%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:350
+#, c-format
+msgid "^BG%s^K1 was betrayed by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:352
+#, c-format
+msgid "^BG%s^BG%s^BG (%s %s every %s seconds)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:354
+#, c-format
+msgid "^BG%s^K1 was frozen by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:355
+#, c-format
+msgid "^BG%s^K3 was revived by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:356
+#, c-format
+msgid "^BG%s^K3 was revived by falling"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:357
+#, c-format
+msgid "^BG%s^K3 was revived by their Nade explosion"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:358
+#, c-format
+msgid "^BG%s^K3 was automatically revived after %s seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:359
+#, c-format
+msgid "^BG%s^K1 froze themself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:361
+#: qcsrc/common/notifications/all.inc:675
+msgid "^TC^TT^BG team wins the round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:362
+#: qcsrc/common/notifications/all.inc:676
+#, c-format
+msgid "^BG%s^BG wins the round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:363
+#: qcsrc/common/notifications/all.inc:539
+msgid "^BGRound tied"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:364
+#: qcsrc/common/notifications/all.inc:540
+msgid "^BGRound over, there's no winner"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:366
+#, c-format
+msgid "^BGGodmode saved you %s units of damage, cheater!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:368
+#, c-format
+msgid "^BG%s^BG got the %s^BG buff!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:369
+#, c-format
+msgid "^BG%s^BG lost the %s^BG buff!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:370
+#: qcsrc/common/notifications/all.inc:683
+#, c-format
+msgid "^BGYou dropped the %s^BG buff!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:371
+#: qcsrc/common/notifications/all.inc:684
+#, c-format
+msgid "^BGYou got the %s^BG buff!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:373
+#: qcsrc/common/notifications/all.inc:687
+#, c-format
+msgid "^BGYou do not have the ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:374
+#: qcsrc/common/notifications/all.inc:688
+#, c-format
+msgid "^BGYou dropped the ^F1%s^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:375
+#: qcsrc/common/notifications/all.inc:689
+#, c-format
+msgid "^BGYou got the ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:376
+#: qcsrc/common/notifications/all.inc:690
+#, c-format
+msgid "^BGYou don't have enough ammo for the ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:377
+#: qcsrc/common/notifications/all.inc:691
+#, c-format
+msgid "^F1%s %s^BG is unable to fire, but its ^F1%s^BG can"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:378
+#: qcsrc/common/notifications/all.inc:692
+#, c-format
+msgid "^F1%s^BG is ^F4not available^BG on this map"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:380
+#, c-format
+msgid "^BG%s^BG is connecting..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:381
+#, c-format
+msgid "^BG%s^F3 connected"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:382
+#, c-format
+msgid "^BG%s^F3 is now playing"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:383
+#, c-format
+msgid "^BG%s^F3 is now playing on the ^TC^TT team"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:385
+#: qcsrc/common/notifications/all.inc:697
+#, c-format
+msgid "^BG%s^BG has dropped the ball!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:386
+#: qcsrc/common/notifications/all.inc:698
+#, c-format
+msgid "^BG%s^BG has picked up the ball!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:388
+#, c-format
+msgid "^BG%s^BG captured the keys for the ^TC^TT team"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:389
+#, c-format
+msgid "^BG%s^BG dropped the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:390
+#, c-format
+msgid "^BG%s^BG lost the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:391
+#, c-format
+msgid "^BG%s^BG pushed %s^BG causing the ^TC^TT Key ^BGdestruction"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:392
+#, c-format
+msgid "^BG%s^BG destroyed the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:393
+#, c-format
+msgid "^BG%s^BG picked up the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:395
+#, c-format
+msgid "^BG%s^F3 forfeited"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:396
+#, c-format
+msgid "^BG%s^F3 has no more lives left"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:398
+msgid "^BGMonsters are currently disabled"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:400
+msgid "^BGThe ^TC^TT^BG team held the ball for too long"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:402
+#, c-format
+msgid "^BG%s^BG captured %s^BG control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:403
+#, c-format
+msgid "^BG%s^BG captured a control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:404
+#, c-format
+msgid "^TC^TT^BG team %s^BG control point has been destroyed by %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:405
+#, c-format
+msgid "^TC^TT^BG team control point has been destroyed by %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:406
+msgid "^TC^TT^BG generator has been destroyed"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:407
+msgid "^TC^TT^BG generator spontaneously combusted due to overtime!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:409
+#, c-format
+msgid "^BG%s^K1 picked up Invisibility"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:410
+#, c-format
+msgid "^BG%s^K1 picked up Shield"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:411
+#, c-format
+msgid "^BG%s^K1 picked up Speed"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:412
+#, c-format
+msgid "^BG%s^K1 picked up Strength"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:414
+#, c-format
+msgid "^BG%s^F3 disconnected"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:415
+#, c-format
+msgid "^BG%s^F3 was kicked for idling"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:416
+msgid ""
+"^F2You were kicked from the server because you are a spectator and "
+"spectators aren't allowed at the moment."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:417
+#, c-format
+msgid "^BG%s^F3 was kicked for excessive teamkilling"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:418
+#, c-format
+msgid "^BG%s^F3 is now spectating"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:420
+#, c-format
+msgid "^BG%s^BG has abandoned the race"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:421
+#, c-format
+msgid "^BG%s^BG couldn't break their %s%s^BG place record of %s%s %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:422
+#, c-format
+msgid "^BG%s^BG couldn't break the %s%s^BG place record of %s%s %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:423
+#, c-format
+msgid "^BG%s^BG has finished the race"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:424
+#, c-format
+msgid "^BG%s^BG broke %s^BG's %s%s^BG place record with %s%s %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:425
+#, c-format
+msgid "^BG%s^BG improved their %s%s^BG place record with %s%s %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:426
+#, c-format
+msgid ""
+"^BG%s^BG scored a new record with ^F2%s^BG, but unfortunately lacks a UID "
+"and will be lost."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:427
+#, c-format
+msgid ""
+"^BG%s^BG scored a new record with ^F2%s^BG, but is anonymous and will be "
+"lost."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:428
+#, c-format
+msgid "^BG%s^BG set the %s%s^BG place record with %s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:430
+#, c-format
+msgid ""
+"^F4You have been invited by ^BG%s^F4 to join their game of ^F2%s^F4 "
+"(^F1%s^F4)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:432
+msgid "^TC^TT ^BGteam scores!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:434
+#, c-format
+msgid ""
+"^F2You have to become a player within the next %s, otherwise you will be "
+"kicked, because spectating isn't allowed at this time!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:436
+#, c-format
+msgid "^BG%s^K1 picked up a Superweapon"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:438
+msgid "^BGYou cannot change to a larger team"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:439
+msgid "^BGYou are not allowed to change teams"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:441
+#, c-format
+msgid ""
+"^F4NOTE: ^BGThe server is running ^F1Xonotic %s (beta)^BG, you have "
+"^F2Xonotic %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:442
+#, c-format
+msgid ""
+"^F4NOTE: ^BGThe server is running ^F1Xonotic %s^BG, you have ^F2Xonotic %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:443
+#, c-format
+msgid ""
+"^F4NOTE: ^F1Xonotic %s^BG is out, and you still have ^F2Xonotic %s^BG - get "
+"the update from ^F3http://www.xonotic.org/^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:445
+#, c-format
+msgid "^F3SVQC Build information: ^F4%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:447
+#, c-format
+msgid ""
+"^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Accordeon%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:448
+#, c-format
+msgid "^BG%s^K1 hurt their own ears with the @!#%%'n Accordeon%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:449
+#, c-format
+msgid "^BG%s%s^K1 was electrocuted by ^BG%s^K1's Arc%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:450
+#, c-format
+msgid "^BG%s%s^K1 was blasted by ^BG%s^K1's Arc bolts%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:451
+#, c-format
+msgid "^BG%s%s^K1 was shot to death by ^BG%s^K1's Blaster%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:452
+#, c-format
+msgid "^BG%s^K1 shot themself to hell with their Blaster%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:453
+#, c-format
+msgid "^BG%s%s^K1 felt the strong pull of ^BG%s^K1's Crylink%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:454
+#, c-format
+msgid "^BG%s^K1 felt the strong pull of their Crylink%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:455
+#, c-format
+msgid "^BG%s%s^K1 ate ^BG%s^K1's rocket%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:456
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's rocket%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:457
+#, c-format
+msgid "^BG%s^K1 blew themself up with their Devastator%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:458
+#, c-format
+msgid "^BG%s%s^K1 was blasted by ^BG%s^K1's Electro bolt%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:459
+#, c-format
+msgid "^BG%s%s^K1 felt the electrifying air of ^BG%s^K1's Electro combo%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:460
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's Electro orb%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:461
+#, c-format
+msgid "^BG%s^K1 played with Electro bolts%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:462
+#, c-format
+msgid "^BG%s^K1 could not remember where they put their Electro orb%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:463
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's fireball%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:464
+#, c-format
+msgid "^BG%s%s^K1 got burnt by ^BG%s^K1's firemine%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:465
+#, c-format
+msgid "^BG%s^K1 should have used a smaller gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:466
+#, c-format
+msgid "^BG%s^K1 forgot about their firemine%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:467
+#, c-format
+msgid "^BG%s%s^K1 was pummeled by a burst of ^BG%s^K1's Hagar rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:468
+#, c-format
+msgid "^BG%s%s^K1 was pummeled by ^BG%s^K1's Hagar rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:469
+#, c-format
+msgid "^BG%s^K1 played with tiny Hagar rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:470
+#, c-format
+msgid "^BG%s%s^K1 was cut down with ^BG%s^K1's HLAC%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:471
+#, c-format
+msgid "^BG%s^K1 got a little jumpy with their HLAC%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:472
+#, c-format
+msgid "^BG%s%s^K1 was caught in ^BG%s^K1's Hook gravity bomb%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:473
+#, c-format
+msgid ""
+"^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Klein Bottle%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:474
+#, c-format
+msgid "^BG%s^K1 hurt their own ears with the @!#%%'n Klein Bottle%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:475
+#, c-format
+msgid "^BG%s%s^K1 was sniped by ^BG%s^K1's Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:476
+#, c-format
+msgid "^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:477
+#: qcsrc/common/notifications/all.inc:782
+#, c-format
+msgid "^BGYou cannot place more than ^F2%s^BG mines at a time"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:478
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's mine%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:479
+#, c-format
+msgid "^BG%s^K1 forgot about their mine%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:480
+#, c-format
+msgid "^BG%s%s^K1 got too close to ^BG%s^K1's Mortar grenade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:481
+#, c-format
+msgid "^BG%s%s^K1 ate ^BG%s^K1's Mortar grenade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:482
+#, c-format
+msgid "^BG%s^K1 didn't see their own Mortar grenade%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:483
+#, c-format
+msgid "^BG%s^K1 blew themself up with their own Mortar%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:484
+#, c-format
+msgid "^BG%s%s^K1 was sniped by ^BG%s^K1's Overkill Heavy Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:485
+#, c-format
+msgid ""
+"^BG%s%s^K1 was torn to bits by ^BG%s^K1's Overkill Heavy Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:486
+#, c-format
+msgid ""
+"^BG%s%s^K1 was riddled full of holes by ^BG%s^K1's Overkill Machine Gun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:487
+#, c-format
+msgid "^BG%s%s^K1 has been vaporized by ^BG%s^K1's Overkill Nex%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:488
+#, c-format
+msgid ""
+"^BG%s%s^K1 was sawn in half by ^BG%s^K1's Overkill Rocket Propelled Chainsaw"
+"%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:489
+#, c-format
+msgid ""
+"^BG%s%s^K1 almost dodged ^BG%s^K1's Overkill Rocket Propelled Chainsaw%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:490
+#, c-format
+msgid ""
+"^BG%s^K1 was sawn in half by their own Overkill Rocket Propelled Chainsaw%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:491
+#, c-format
+msgid ""
+"^BG%s^K1 blew themself up with their Overkill Rocket Propelled Chainsaw%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:493
+#, c-format
+msgid "^BG%s%s^K1 was gunned down by ^BG%s^K1's Overkill Shotgun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:494
+#, c-format
+msgid "^BG%s%s^K1 was sniped with a Rifle by ^BG%s^K1%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:495
+#, c-format
+msgid "^BG%s%s^K1 died in ^BG%s^K1's Rifle bullet hail%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:496
+#, c-format
+msgid "^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle bullet hail%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:497
+#, c-format
+msgid "^BG%s%s^K1 failed to hide from ^BG%s^K1's Rifle%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:498
+#, c-format
+msgid "^BG%s%s^K1 was pummeled by ^BG%s^K1's Seeker rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:499
+#, c-format
+msgid "^BG%s%s^K1 was tagged by ^BG%s^K1's Seeker%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:500
+#, c-format
+msgid "^BG%s^K1 played with tiny Seeker rockets%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:501
+#, c-format
+msgid "^BG%s%s^K1 was gunned down by ^BG%s^K1's Shockwave%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:502
+#, c-format
+msgid "^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shockwave%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:503
+#, c-format
+msgid "^BG%s%s^K1 was gunned down by ^BG%s^K1's Shotgun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:504
+#, c-format
+msgid "^BG%s%s^K1 slapped ^BG%s^K1 around a bit with a large Shotgun%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:505
+#, c-format
+msgid "^BG%s^K1 is now thinking with portals%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:506
+#, c-format
+msgid "^BG%s%s^K1 died of ^BG%s^K1's great playing on the @!#%%'n Tuba%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:507
+#, c-format
+msgid "^BG%s^K1 hurt their own ears with the @!#%%'n Tuba%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:508
+#, c-format
+msgid "^BG%s%s^K1 has been sublimated by ^BG%s^K1's Vaporizer%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:509
+#, c-format
+msgid "^BG%s%s^K1 has been vaporized by ^BG%s^K1's Vortex%s%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:528
+msgid "^F4You are now alone!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:530
+msgid "^BGYou are attacking!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:531
+msgid "^BGYou are defending!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:532
+#, c-format
+msgid "^BGObjective destroyed in ^F4%s^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:534
+msgid "^F4Begin!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:535
+msgid "^F4Game starts in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:536
+msgid "^F4Round starts in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:537
+msgid "^F4Round cannot start"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:542
+msgid "^F2Don't camp!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:546
+msgid ""
+"^BGYou are now free.\n"
+"^BGFeel free to ^F2try to capture^BG the flag again\n"
+"^BGif you think you will succeed."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:547
+msgid "^BGThis flag is currently inactive"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:548
+msgid ""
+"^BGYou are now ^F1shielded^BG from the flag(s)\n"
+"^BGfor ^F2too many unsuccessful attempts^BG to capture.\n"
+"^BGMake some defensive scores before trying again."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:549
+msgid "^BGYou captured the ^TC^TT^BG flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:550
+msgid "^BGYou captured the flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:551
+#, c-format
+msgid "^BGToo many flag throws! Throwing disabled for %s."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:552
+#, c-format
+msgid "^BG%s^BG passed the ^TC^TT^BG flag to %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:553
+#, c-format
+msgid "^BG%s^BG passed the flag to %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:554
+#, c-format
+msgid "^BGYou received the ^TC^TT^BG flag from %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:555
+#, c-format
+msgid "^BGYou received the flag from %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:556
+#, c-format
+msgid "^BGPress ^F2%s^BG to receive the flag from %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:557
+#, c-format
+msgid "^BGRequesting %s^BG to pass you the flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:558
+#, c-format
+msgid "^BGYou passed the ^TC^TT^BG flag to %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:559
+#, c-format
+msgid "^BGYou passed the flag to %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:560
+msgid "^BGYou got the ^TC^TT^BG flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:561
+msgid "^BGYou got the flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:562
+#, c-format
+msgid "^BGYou got your %steam^BG's flag, return it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:563
+#, c-format
+msgid "^BGYou got the %senemy^BG's flag, return it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:564
+#, c-format
+msgid "^BGThe %senemy^BG got your flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:565
+#, c-format
+msgid "^BGThe %senemy (^BG%s%s)^BG got your flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:566
+#, c-format
+msgid "^BGThe %senemy^BG got the flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:567
+#, c-format
+msgid "^BGThe %senemy (^BG%s%s)^BG got the flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:568
+#, c-format
+msgid "^BGThe %senemy^BG got their flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:569
+#, c-format
+msgid "^BGThe %senemy (^BG%s%s)^BG got their flag! Retrieve it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:570
+#, c-format
+msgid "^BGYour %steam mate^BG got the ^TC^TT^BG flag! Protect them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:571
+#, c-format
+msgid "^BGYour %steam mate (^BG%s%s)^BG got the ^TC^TT^BG flag! Protect them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:572
+#, c-format
+msgid "^BGYour %steam mate^BG got the flag! Protect them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:573
+#, c-format
+msgid "^BGYour %steam mate (^BG%s%s)^BG got the flag! Protect them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:574
+msgid "^BGEnemies can now see you on radar!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:575
+msgid "^BGYou returned the ^TC^TT^BG flag!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:576
+msgid "^BGStalemate! Enemies can now see you on radar!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:577
+msgid "^BGStalemate! Flag carriers can now be seen by enemies on radar!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:581
+#, c-format
+msgid "^K3%sYou fragged ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:582
+#: qcsrc/common/notifications/all.inc:591
+#: qcsrc/common/notifications/all.inc:600
+#, c-format
+msgid "^K3%sYou scored against ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:583
+#, c-format
+msgid "^K1%sYou were fragged by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:584
+#: qcsrc/common/notifications/all.inc:593
+#: qcsrc/common/notifications/all.inc:602
+#, c-format
+msgid "^K1%sYou were scored against by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:590
+#, c-format
+msgid "^K3%sYou burned ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:592
+#, c-format
+msgid "^K1%sYou were burned by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:599
+#, c-format
+msgid "^K3%sYou froze ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:601
+#, c-format
+msgid "^K1%sYou were frozen by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:608
+#, c-format
+msgid "^K1%sYou typefragged ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:609
+#, c-format
+msgid "^K1%sYou scored against ^BG%s^K1 while they were typing"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:610
+#, c-format
+msgid "^K1%sYou were typefragged by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:611
+#, c-format
+msgid "^K1%sYou were scored against by ^BG%s^K1 while typing"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:617
+#, c-format
+msgid "^BGPress ^F2%s^BG again to toss the nade!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:618
+msgid "^F2You got a ^K1BONUS GRENADE^F2!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:620
+#, c-format
+msgid ""
+"^BGYou have been moved into a different team\n"
+"You are now on: %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:621
+msgid "^K1Don't go against your team mates!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:621
+msgid "^K1Don't shoot your team mates!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:622
+msgid "^K1Die camper!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:622
+msgid "^K1Reconsider your tactics, camper!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:623
+msgid "^K1You unfairly eliminated yourself!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:624
+#, c-format
+msgid "^K1You were %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:625
+msgid "^K1You couldn't catch your breath!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:626
+msgid "^K1You hit the ground with a crunch!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:627
+msgid "^K1You felt a little too hot!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:627
+msgid "^K1You got a little bit too crispy!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:628
+msgid "^K1You killed your own dumb self!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:628
+msgid "^K1You need to be more careful!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:629
+msgid "^K1You couldn't stand the heat!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:630
+msgid "^K1You need to watch out for monsters!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:630
+msgid "^K1You were killed by a monster!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:631
+msgid "^K1Tastes like chicken!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:631
+msgid "^K1You forgot to put the pin back in!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:632
+msgid "^K1Hanging around a napalm explosion is bad!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:633
+msgid "^K1You felt a little chilly!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:633
+msgid "^K1You got a little bit too cold!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:634
+msgid "^K1Your Healing Nade is a bit defective"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:635
+msgid "^K1You are respawning for running out of ammo..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:635
+msgid "^K1You were killed for running out of ammo..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:636
+msgid "^K1You grew too old without taking your medicine"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:636
+msgid "^K1You need to preserve your health"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:637
+msgid "^K1You became a shooting star!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:638
+msgid "^K1You melted away in slime!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:639
+msgid "^K1You committed suicide!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:639
+msgid "^K1You ended it all!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:640
+msgid "^K1You got stuck in a swamp!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:641
+#, c-format
+msgid "^BGYou are now on: %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:642
+msgid "^K1You died in an accident!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:643
+msgid "^K1You had an unfortunate run in with a turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:643
+msgid "^K1You were fragged by a turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:644
+msgid "^K1You had an unfortunate run in with an eWheel turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:644
+msgid "^K1You were fragged by an eWheel turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:645
+msgid "^K1You had an unfortunate run in with a Walker turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:645
+msgid "^K1You were fragged by a Walker turret!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:646
+msgid "^K1You got caught in the blast of a Bumblebee explosion!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:647
+msgid "^K1You were crushed by a vehicle!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:648
+msgid "^K1You were caught in a Raptor cluster bomb!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:649
+msgid "^K1You got caught in the blast of a Raptor explosion!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:650
+msgid "^K1You got caught in the blast of a Spiderbot explosion!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:651
+msgid "^K1You were blasted to bits by a Spiderbot rocket!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:652
+msgid "^K1You got caught in the blast of a Racer explosion!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:653
+msgid "^K1You couldn't find shelter from a Racer rocket!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:654
+msgid "^K1Watch your step!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:656
+#, c-format
+msgid "^K1Moron! You fragged ^BG%s^K1, a team mate!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:656
+#, c-format
+msgid "^K1Moron! You went against ^BG%s^K1, a team mate!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:657
+#, c-format
+msgid "^K1You were fragged by ^BG%s^K1, a team mate"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:657
+#, c-format
+msgid "^K1You were scored against by ^BG%s^K1, a team mate"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:659
+msgid ""
+"^K1Stop idling!\n"
+"^BGDisconnecting in ^COUNT..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:661
+#, c-format
+msgid "^BGYou need %s^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:662
+#, c-format
+msgid "^BGYou also need %s^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:663
+msgid "^BGDoor unlocked!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:665
+#, c-format
+msgid "^F2Extra lives taken: ^K1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:667
+#, c-format
+msgid "^K3You revived ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:668
+msgid "^K3You revived yourself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:669
+#, c-format
+msgid "^K3You were revived by ^BG%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:670
+#, c-format
+msgid "^K3You were automatically revived after %s seconds"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:672
+msgid "^BGThe generator is under attack!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:674
+msgid "^TC^TT^BG team loses the round"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:678
+msgid "^K1You froze yourself"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:679
+msgid "^K1Round already started, you spawn as frozen"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:681
+#, c-format
+msgid "^K1A %s has arrived!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:685
+msgid "^BGYou got the ^F1Fuel regenerator"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:686
+msgid "^BGYou got the ^F1Jetpack"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:694
+msgid ""
+"^K1No spawnpoints available!\n"
+"Hope your team can fix it..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:695
+msgid ""
+"^K1You may not join the game at this time.\n"
+"The player limit reached maximum capacity."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:699
+msgid "^BGYou picked up the ball"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:700
+msgid "^BGKilling people while you don't have the ball gives no points!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:702
+msgid ""
+"^BGAll keys are in your team's hands!\n"
+"Help the key carriers to meet!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:703
+msgid ""
+"^BGAll keys are in ^TC^TT team^BG's hands!\n"
+"Interfere ^F4NOW^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:704
+msgid ""
+"^BGAll keys are in your team's hands!\n"
+"Meet the other key carriers ^F4NOW^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:705
+msgid "^F4Round will start in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:706
+msgid "^BGScanning frequency range..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:707
+msgid "^BGYou are starting with the ^TC^TT Key"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:709
+msgid "^BGYou have no lives left, you must wait until the next match"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:711
+#, c-format
+msgid ""
+"^BGWaiting for players to join...\n"
+"Need active players for: %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:712
+#, c-format
+msgid "^BGWaiting for %s player(s) to join..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:714
+msgid "^BGYour weapon has been downgraded until you find some ammo!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:715
+msgid "^F4^COUNT^BG left to find some ammo!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:716
+msgid "^BGGet some ammo or you'll be dead in ^F4^COUNT^BG!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:716
+msgid "^BGGet some ammo! ^F4^COUNT^BG left!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:717
+#, c-format
+msgid "^F2Extra lives remaining: ^K1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:719 qcsrc/menu/xonotic/campaign.qc:244
+#, c-format
+msgid "Level %s: "
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:719
+#, c-format
+msgid "^BGPress ^F2%s^BG to enter the game"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:722
+#, c-format
+msgid ""
+"^F2^COUNT^BG until weapon change...\n"
+"Next weapon: ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:723
+#, c-format
+msgid "^F2Active weapon: ^F1%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:725
+#, c-format
+msgid "^BGYou captured %s^BG control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:726
+msgid "^BGYou captured a control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:727
+#, c-format
+msgid "^TC^TT^BG team captured %s^BG control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:728
+msgid "^TC^TT^BG team captured a control point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:729
+msgid "^BGThis control point currently cannot be captured"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:730
+msgid ""
+"^BGThe enemy generator cannot be destroyed yet\n"
+"^F2Capture some control points to unshield it"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:731
+msgid "^BGThe ^TCenemy^BG generator is no longer shielded!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:732
+msgid ""
+"^K1Your generator is NOT shielded!\n"
+"^BGRe-capture control points to shield it!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:733
+#, c-format
+msgid "^BGPress ^F2%s^BG to teleport"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:734
+#, c-format
+msgid "^BGTeleporting disabled for %s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:736
+msgid ""
+"^F2Now playing ^F4OVERTIME^F2!\n"
+"Keep fragging until we have a winner!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:736
+msgid ""
+"^F2Now playing ^F4OVERTIME^F2!\n"
+"Keep scoring until we have a winner!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:737
+msgid ""
+"^F2Now playing ^F4OVERTIME^F2!\n"
+"\n"
+"Generators are now decaying.\n"
+"The more control points your team holds,\n"
+"the faster the enemy generator decays"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:738
+#, c-format
+msgid ""
+"^F2Now playing ^F4OVERTIME^F2!\n"
+"^BGAdded ^F4%s^BG to the game!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:740
+msgid "^K1In^BG-portal created"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:741
+msgid "^F3Out^BG-portal created"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:742
+msgid "^F1Portal creation failed"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:744
+msgid "^F2Strength infuses your weapons with devastating power"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:745
+msgid "^F2Strength has worn off"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:747
+msgid "^F2Shield surrounds you"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:748
+msgid "^F2Shield has worn off"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:750
+msgid "^F2You are on speed"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:751
+msgid "^F2Speed has worn off"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:753
+msgid "^F2You are invisible"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:754
+msgid "^F2Invisibility has worn off"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:756
+msgid "^F2The race is over, finish your lap!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:758
+msgid "^BGSequence completed!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:759
+msgid "^BGThere are more to go..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:760
+#, c-format
+msgid "^BGOnly %s^BG more to go..."
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:762
+msgid "^F2Superweapons have broken down"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:763
+msgid "^F2Superweapons have been lost"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:764
+msgid "^F2You now have a superweapon"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:766
+msgid "^K1Changing to ^TC^TT^K1 in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:767
+msgid "^K1Changing team in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:768
+msgid "^K1Spectating in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:769
+msgid "^K1Suicide in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:771
+msgid "^F4Timeout begins in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:772
+msgid "^F4Timeout ends in ^COUNT"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:774
+msgid "^K1Cannot join given minigame session!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:776
+#, c-format
+msgid "^BGPress ^F2%s^BG to enter/exit the vehicle"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:777
+#, c-format
+msgid "^BGPress ^F2%s^BG to enter the vehicle gunner"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:778
+#, c-format
+msgid "^BGPress ^F2%s^BG to steal this vehicle"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:779
+msgid ""
+"^F2The enemy is stealing one of your vehicles!\n"
+"^F4Stop them!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.inc:780
+msgid "^F2Intruder detected, disabling shields!"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:198
+msgid "Notification dump command only works with cl_cmd and sv_cmd."
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:408 qcsrc/common/notifications/all.qh:409
+#, c-format
+msgid " (near %s)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:416 qcsrc/common/notifications/all.qh:417
+msgid "primary"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:416 qcsrc/common/notifications/all.qh:417
+msgid "secondary"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:419
+msgid "point"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:419
+msgid "points"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:428
+msgid "drop flag"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:429
+msgid "throw nade"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:455
+#, c-format
+msgid "%s^K1 made a TRIPLE FRAG! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:455
+#, c-format
+msgid "%s^K1 made a TRIPLE SCORE! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:455
+msgid "TRIPLE FRAG! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:456
+#, c-format
+msgid "%s^K1 made FIVE SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:456
+#, c-format
+msgid "%s^K1 unlocked RAGE! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:456
+msgid "RAGE! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:457
+#, c-format
+msgid "%s^K1 made TEN SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:457
+#, c-format
+msgid "%s^K1 started a MASSACRE! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:457
+msgid "MASSACRE! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:458
+#, c-format
+msgid "%s^K1 executed MAYHEM! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:458
+#, c-format
+msgid "%s^K1 made FIFTEEN SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:458
+msgid "MAYHEM! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:459
+#, c-format
+msgid "%s^K1 is a BERSERKER! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:459
+#, c-format
+msgid "%s^K1 made TWENTY SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:459
+msgid "BERSERKER! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:460
+#, c-format
+msgid "%s^K1 inflicts CARNAGE! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:460
+#, c-format
+msgid "%s^K1 made TWENTY FIVE SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:460
+msgid "CARNAGE! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:461
+#, c-format
+msgid "%s^K1 made THIRTY SCORES IN A ROW! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:461
+#, c-format
+msgid "%s^K1 unleashes ARMAGEDDON! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:461
+msgid "ARMAGEDDON! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:468
+#, c-format
+msgid "%s(^F1Bot^BG)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:470
+#, c-format
+msgid "%s(Ping ^F1%d^BG)"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:477
+#, c-format
+msgid ""
+"\n"
+"(Health ^1%d^BG / Armor ^2%d^BG)%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:479
+#, c-format
+msgid ""
+"\n"
+"(^F4Dead^BG)%s"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:500 qcsrc/common/notifications/all.qh:513
+#, c-format
+msgid "%d score spree! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:512
+#, c-format
+msgid "%d frag spree! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:525
+msgid "First blood! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:525
+msgid "First score! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:529
+msgid "First casualty! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:529
+msgid "First victim! "
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:570
+#, c-format
+msgid "%s^K1 has %d frags in a row! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:571
+#, c-format
+msgid "%s^K1 made %d scores in a row! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:589
+#, c-format
+msgid "%s^K1 drew first blood! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:590
+#, c-format
+msgid "%s^K1 got the first score! %s^BG"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:606
+#, c-format
+msgid ", ending their %d frag spree"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:607
+#, c-format
+msgid ", ending their %d score spree"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:621
+#, c-format
+msgid ", losing their %d frag spree"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:622
+#, c-format
+msgid ", losing their %d score spree"
+msgstr ""
+
+#: qcsrc/common/notifications/all.qh:647
+#, c-format
+msgid " with %d %s"
+msgstr ""
+
+#: qcsrc/common/teams.qh:31
+msgid "TEAM^Red"
+msgstr ""
+
+#: qcsrc/common/teams.qh:32
+msgid "TEAM^Blue"
+msgstr ""
+
+#: qcsrc/common/teams.qh:33
+msgid "TEAM^Yellow"
+msgstr ""
+
+#: qcsrc/common/teams.qh:34
+msgid "TEAM^Pink"
+msgstr ""
+
+#: qcsrc/common/teams.qh:35
+msgid "Team"
+msgstr ""
+
+#: qcsrc/common/teams.qh:36
+msgid "Neutral"
+msgstr ""
+
+#: qcsrc/common/teams.qh:39
+msgid "KEY^Red"
+msgstr ""
+
+#: qcsrc/common/teams.qh:40
+msgid "KEY^Blue"
+msgstr ""
+
+#: qcsrc/common/teams.qh:41
+msgid "KEY^Yellow"
+msgstr ""
+
+#: qcsrc/common/teams.qh:42
+msgid "KEY^Pink"
+msgstr ""
+
+#: qcsrc/common/teams.qh:43
+msgid "FLAG^Red"
+msgstr ""
+
+#: qcsrc/common/teams.qh:44
+msgid "FLAG^Blue"
+msgstr ""
+
+#: qcsrc/common/teams.qh:45
+msgid "FLAG^Yellow"
+msgstr ""
+
+#: qcsrc/common/teams.qh:46
+msgid "FLAG^Pink"
+msgstr ""
+
+#: qcsrc/common/teams.qh:47
+msgid "GENERATOR^Red"
+msgstr ""
+
+#: qcsrc/common/teams.qh:48
+msgid "GENERATOR^Blue"
+msgstr ""
+
+#: qcsrc/common/teams.qh:49
+msgid "GENERATOR^Yellow"
+msgstr ""
+
+#: qcsrc/common/teams.qh:50
+msgid "GENERATOR^Pink"
+msgstr ""
+
+#: qcsrc/common/turrets/all.qh:95
+msgid "Turrets dump command only works with sv_cmd."
+msgstr ""
+
+#: qcsrc/common/turrets/cl_turrets.qc:125
+#, c-format
+msgid "%s under attack!"
+msgstr ""
+
+#: qcsrc/common/turrets/turret.qh:11
+msgid "Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/ewheel.qh:15
+msgid "eWheel Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/ewheel_weapon.qh:7
+msgid "eWheel"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/flac.qh:13
+msgid "FLAC Cannon"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/flac_weapon.qh:7
+msgid "FLAC"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/fusionreactor.qh:11
+msgid "Fusion Reactor"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/hellion.qh:13
+msgid "Hellion Missile Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/hellion_weapon.qh:7
+msgid "Hellion"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/hk.qh:15
+msgid "Hunter-Killer Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/hk_weapon.qh:7
+msgid "Hunter-Killer"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/machinegun.qh:13
+msgid "Machinegun Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/machinegun_weapon.qh:7
+msgid "Machinegun"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/mlrs.qh:13
+msgid "MLRS Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/mlrs_weapon.qh:7
+msgid "MLRS"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/phaser.qh:13
+msgid "Phaser Cannon"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/phaser_weapon.qh:7
+msgid "Phaser"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/plasma.qh:13
+msgid "Plasma Cannon"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/plasma_dual.qh:8
+msgid "Dual plasma"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/plasma_dual.qh:20
+msgid "Dual Plasma Cannon"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/plasma_weapon.qh:7
+msgid "Plasma"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/tesla.qh:13
+#: qcsrc/common/turrets/turret/tesla_weapon.qh:7
+msgid "Tesla Coil"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/walker.qh:15
+msgid "Walker Turret"
+msgstr ""
+
+#: qcsrc/common/turrets/turret/walker_weapon.qh:7
+msgid "Walker"
+msgstr ""
+
+#: qcsrc/common/util.qc:1390
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:176
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:186
+msgid "Male"
+msgstr ""
+
+#: qcsrc/common/util.qc:1391
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:175
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:185
+msgid "Female"
+msgstr ""
+
+#: qcsrc/common/util.qc:1392
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:174
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:187
+msgid "Undisclosed"
+msgstr ""
+
+#: qcsrc/common/util.qc:1439
+msgid "<KEY NOT FOUND>"
+msgstr ""
+
+#: qcsrc/common/util.qc:1440
+msgid "<UNKNOWN KEYNUM>"
+msgstr ""
+
+#: qcsrc/common/util.qc:1445
+msgid "TAB"
+msgstr ""
+
+#: qcsrc/common/util.qc:1446 qcsrc/common/util.qc:1517
+#, c-format
+msgid "ENTER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1447
+msgid "ESCAPE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1448
+msgid "SPACE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1450
+msgid "BACKSPACE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1451 qcsrc/common/util.qc:1508
+#, c-format
+msgid "UPARROW"
+msgstr ""
+
+#: qcsrc/common/util.qc:1452 qcsrc/common/util.qc:1503
+#, c-format
+msgid "DOWNARROW"
+msgstr ""
+
+#: qcsrc/common/util.qc:1453 qcsrc/common/util.qc:1505
+#, c-format
+msgid "LEFTARROW"
+msgstr ""
+
+#: qcsrc/common/util.qc:1454 qcsrc/common/util.qc:1506
+#, c-format
+msgid "RIGHTARROW"
+msgstr ""
+
+#: qcsrc/common/util.qc:1456
+msgid "ALT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1457
+msgid "CTRL"
+msgstr ""
+
+#: qcsrc/common/util.qc:1458
+msgid "SHIFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1460 qcsrc/common/util.qc:1501
+#, c-format
+msgid "INS"
+msgstr ""
+
+#: qcsrc/common/util.qc:1461 qcsrc/common/util.qc:1511
+#, c-format
+msgid "DEL"
+msgstr ""
+
+#: qcsrc/common/util.qc:1462 qcsrc/common/util.qc:1504
+#, c-format
+msgid "PGDN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1463 qcsrc/common/util.qc:1509
+#, c-format
+msgid "PGUP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1464 qcsrc/common/util.qc:1507
+#, c-format
+msgid "HOME"
+msgstr ""
+
+#: qcsrc/common/util.qc:1465 qcsrc/common/util.qc:1502
+#, c-format
+msgid "END"
+msgstr ""
+
+#: qcsrc/common/util.qc:1467
+msgid "PAUSE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1469
+msgid "NUMLOCK"
+msgstr ""
+
+#: qcsrc/common/util.qc:1470
+msgid "CAPSLOCK"
+msgstr ""
+
+#: qcsrc/common/util.qc:1471
+msgid "SCROLLOCK"
+msgstr ""
+
+#: qcsrc/common/util.qc:1473
+msgid "SEMICOLON"
+msgstr ""
+
+#: qcsrc/common/util.qc:1474
+msgid "TILDE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1475
+msgid "BACKQUOTE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1476
+msgid "QUOTE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1477
+msgid "APOSTROPHE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1478
+msgid "BACKSLASH"
+msgstr ""
+
+#: qcsrc/common/util.qc:1486
+#, c-format
+msgid "F%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1496
+#, c-format
+msgid "KP_%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1501 qcsrc/common/util.qc:1502
+#: qcsrc/common/util.qc:1503 qcsrc/common/util.qc:1504
+#: qcsrc/common/util.qc:1505 qcsrc/common/util.qc:1506
+#: qcsrc/common/util.qc:1507 qcsrc/common/util.qc:1508
+#: qcsrc/common/util.qc:1509 qcsrc/common/util.qc:1510
+#: qcsrc/common/util.qc:1511 qcsrc/common/util.qc:1512
+#: qcsrc/common/util.qc:1513 qcsrc/common/util.qc:1514
+#: qcsrc/common/util.qc:1515 qcsrc/common/util.qc:1516
+#: qcsrc/common/util.qc:1517 qcsrc/common/util.qc:1518
+#, c-format
+msgid "KP_%s"
+msgstr ""
+
+#: qcsrc/common/util.qc:1510
+#, c-format
+msgid "PERIOD"
+msgstr ""
+
+#: qcsrc/common/util.qc:1512
+#, c-format
+msgid "DIVIDE"
+msgstr ""
+
+#: qcsrc/common/util.qc:1513
+#, c-format
+msgid "SLASH"
+msgstr ""
+
+#: qcsrc/common/util.qc:1514
+#, c-format
+msgid "MULTIPLY"
+msgstr ""
+
+#: qcsrc/common/util.qc:1515
+#, c-format
+msgid "MINUS"
+msgstr ""
+
+#: qcsrc/common/util.qc:1516
+#, c-format
+msgid "PLUS"
+msgstr ""
+
+#: qcsrc/common/util.qc:1518
+#, c-format
+msgid "EQUALS"
+msgstr ""
+
+#: qcsrc/common/util.qc:1523
+msgid "PRINTSCREEN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1526
+#, c-format
+msgid "MOUSE%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1528
+msgid "MWHEELUP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1529
+msgid "MWHEELDOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1532
+#, c-format
+msgid "JOY%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1535
+#, c-format
+msgid "AUX%d"
+msgstr ""
+
+#: qcsrc/common/util.qc:1542
+#, c-format
+msgid "DPAD_UP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1542 qcsrc/common/util.qc:1543
+#: qcsrc/common/util.qc:1544 qcsrc/common/util.qc:1545
+#: qcsrc/common/util.qc:1546 qcsrc/common/util.qc:1547
+#: qcsrc/common/util.qc:1548 qcsrc/common/util.qc:1549
+#: qcsrc/common/util.qc:1550 qcsrc/common/util.qc:1551
+#: qcsrc/common/util.qc:1552 qcsrc/common/util.qc:1553
+#: qcsrc/common/util.qc:1554 qcsrc/common/util.qc:1555
+#: qcsrc/common/util.qc:1556 qcsrc/common/util.qc:1557
+#: qcsrc/common/util.qc:1558 qcsrc/common/util.qc:1559
+#: qcsrc/common/util.qc:1560 qcsrc/common/util.qc:1561
+#, c-format
+msgid "X360_%s"
+msgstr ""
+
+#: qcsrc/common/util.qc:1543
+#, c-format
+msgid "DPAD_DOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1544
+#, c-format
+msgid "DPAD_LEFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1545
+#, c-format
+msgid "DPAD_RIGHT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1546
+#, c-format
+msgid "START"
+msgstr ""
+
+#: qcsrc/common/util.qc:1547
+#, c-format
+msgid "BACK"
+msgstr ""
+
+#: qcsrc/common/util.qc:1548
+#, c-format
+msgid "LEFT_THUMB"
+msgstr ""
+
+#: qcsrc/common/util.qc:1549
+#, c-format
+msgid "RIGHT_THUMB"
+msgstr ""
+
+#: qcsrc/common/util.qc:1550
+#, c-format
+msgid "LEFT_SHOULDER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1551
+#, c-format
+msgid "RIGHT_SHOULDER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1552
+#, c-format
+msgid "LEFT_TRIGGER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1553
+#, c-format
+msgid "RIGHT_TRIGGER"
+msgstr ""
+
+#: qcsrc/common/util.qc:1554
+#, c-format
+msgid "LEFT_THUMB_UP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1555
+#, c-format
+msgid "LEFT_THUMB_DOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1556
+#, c-format
+msgid "LEFT_THUMB_LEFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1557
+#, c-format
+msgid "LEFT_THUMB_RIGHT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1558
+#, c-format
+msgid "RIGHT_THUMB_UP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1559
+#, c-format
+msgid "RIGHT_THUMB_DOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1560
+#, c-format
+msgid "RIGHT_THUMB_LEFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1561
+#, c-format
+msgid "RIGHT_THUMB_RIGHT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1571 qcsrc/common/util.qc:1572
+#: qcsrc/common/util.qc:1573 qcsrc/common/util.qc:1574
+#, c-format
+msgid "JOY_%s"
+msgstr ""
+
+#: qcsrc/common/util.qc:1571
+#, c-format
+msgid "UP"
+msgstr ""
+
+#: qcsrc/common/util.qc:1572
+#, c-format
+msgid "DOWN"
+msgstr ""
+
+#: qcsrc/common/util.qc:1573
+#, c-format
+msgid "LEFT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1574
+#, c-format
+msgid "RIGHT"
+msgstr ""
+
+#: qcsrc/common/util.qc:1580
+#, c-format
+msgid "MIDINOTE%d"
+msgstr ""
+
+#: qcsrc/common/vehicles/cl_vehicles.qc:190
+#, c-format
+msgid "Press %s"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/bumblebee.qc:954
+msgid "No right gunner!"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/bumblebee.qc:960
+msgid "No left gunner!"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/bumblebee.qh:19
+msgid "Bumblebee"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/racer.qh:19
+msgid "Racer"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/racer_weapon.qh:9
+msgid "Racer cannon"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/raptor.qh:19
+msgid "Raptor"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/raptor_weapons.qh:9
+msgid "Raptor cannon"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/raptor_weapons.qh:17
+msgid "Raptor bomb"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/raptor_weapons.qh:25
+msgid "Raptor flare"
+msgstr ""
+
+#: qcsrc/common/vehicles/vehicle/spiderbot.qh:19
+msgid "Spiderbot"
+msgstr ""
+
+#: qcsrc/common/weapons/all.qh:76
+msgid "Weapons dump command only works with sv_cmd."
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/arc.qh:18
+msgid "Arc"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/blaster.qh:18
+msgid "Blaster"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/crylink.qh:18
+msgid "Crylink"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/devastator.qh:18
+msgid "Devastator"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/electro.qh:18
+msgid "Electro"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/fireball.qh:18
+msgid "Fireball"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/hagar.qh:18
+msgid "Hagar"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/hlac.qh:18
+msgid "Heavy Laser Assault Cannon"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/hook.qh:18
+msgid "Grappling Hook"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/machinegun.qh:18
+msgid "MachineGun"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/minelayer.qh:18
+msgid "Mine Layer"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/mortar.qh:18
+msgid "Mortar"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/porto.qh:18
+msgid "Port-O-Launch"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/rifle.qh:19
+msgid "Rifle"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/seeker.qh:18
+msgid "T.A.G. Seeker"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/shockwave.qh:18
+msgid "Shockwave"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/shotgun.qh:18
+msgid "Shotgun"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/tuba.qh:18
+#, no-c-format
+msgid "@!#%'n Tuba"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/vaporizer.qh:19
+msgid "Vaporizer"
+msgstr ""
+
+#: qcsrc/common/weapons/weapon/vortex.qh:19
+msgid "Vortex"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:9
+#, c-format
+msgid "CI_DEC^%s years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:12
+#, c-format
+msgid "CI_ZER^%d years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:13
+#, c-format
+msgid "CI_FIR^%d year"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:14
+#, c-format
+msgid "CI_SEC^%d years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:15
+#, c-format
+msgid "CI_THI^%d years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:16
+#, c-format
+msgid "CI_MUL^%d years"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:18
+#, c-format
+msgid "CI_DEC^%s weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:21
+#, c-format
+msgid "CI_ZER^%d weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:22
+#, c-format
+msgid "CI_FIR^%d week"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:23
+#, c-format
+msgid "CI_SEC^%d weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:24
+#, c-format
+msgid "CI_THI^%d weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:25
+#, c-format
+msgid "CI_MUL^%d weeks"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:27
+#, c-format
+msgid "CI_DEC^%s days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:30
+#, c-format
+msgid "CI_ZER^%d days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:31
+#, c-format
+msgid "CI_FIR^%d day"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:32
+#, c-format
+msgid "CI_SEC^%d days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:33
+#, c-format
+msgid "CI_THI^%d days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:34
+#, c-format
+msgid "CI_MUL^%d days"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:36
+#, c-format
+msgid "CI_DEC^%s hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:39
+#, c-format
+msgid "CI_ZER^%d hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:40
+#, c-format
+msgid "CI_FIR^%d hour"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:41
+#, c-format
+msgid "CI_SEC^%d hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:42
+#, c-format
+msgid "CI_THI^%d hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:43
+#, c-format
+msgid "CI_MUL^%d hours"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:46
+#, c-format
+msgid "CI_DEC^%s minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:49
+#, c-format
+msgid "CI_ZER^%d minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:50
+#, c-format
+msgid "CI_FIR^%d minute"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:51
+#, c-format
+msgid "CI_SEC^%d minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:52
+#, c-format
+msgid "CI_THI^%d minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:53
+#, c-format
+msgid "CI_MUL^%d minutes"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:55
+#, c-format
+msgid "CI_DEC^%s seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:58
+#, c-format
+msgid "CI_ZER^%d seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:59
+#, c-format
+msgid "CI_FIR^%d second"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:60
+#, c-format
+msgid "CI_SEC^%d seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:61
+#, c-format
+msgid "CI_THI^%d seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:62
+#, c-format
+msgid "CI_MUL^%d seconds"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:79
+#, c-format
+msgid "%dst"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:80
+#, c-format
+msgid "%dnd"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:81
+#, c-format
+msgid "%drd"
+msgstr ""
+
+#: qcsrc/lib/counting.qh:85
+#, c-format
+msgid "%dth"
+msgstr ""
+
+#: qcsrc/lib/oo.qh:324
+msgid "No description"
+msgstr ""
+
+#: qcsrc/lib/spawnfunc.qh:248
+#, c-format
+msgid ""
+"Entity field %s.%s (%s) is not whitelisted. If you believe this is an error, "
+"please file an issue."
+msgstr ""
+
+#: qcsrc/lib/string.qh:81
+#, c-format
+msgid "%d days, %02d:%02d:%02d"
+msgstr ""
+
+#: qcsrc/lib/string.qh:82
+#, c-format
+msgid "%02d:%02d:%02d"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:48
+msgid "Usage: menu_cmd command..., where possible commands are:"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:49
+msgid " sync - reloads all cvars on the current menu page"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:50
+msgid " directmenu ITEM - select a menu item as main item"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:51
+msgid " dumptree - dump the state of the menu as a tree to the console"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:81
+msgid "Available options:"
+msgstr ""
+
+#: qcsrc/menu/command/menu_cmd.qc:130
+msgid "Invalid command. For a list of supported commands, try menu_cmd help."
+msgstr ""
+
+#: qcsrc/menu/item/listbox.qc:413
+#, c-format
+msgid "Item %d"
+msgstr ""
+
+#: qcsrc/menu/item/textslider.qc:11 qcsrc/menu/item/textslider.qc:12
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:37
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:68
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:115
+msgid "Custom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:4
+msgid "Core Team"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:15
+msgid "Extended Team"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:46
+msgid "Website"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:51
+msgid "Stats"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:55
+msgid "Art"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:63
+msgid "Animation"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:67
+msgid "Level Design"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:90
+msgid "Music / Sound FX"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:106
+msgid "Game Code"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:114
+msgid "Marketing / PR"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:120
+msgid "Legal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:125
+msgid "Game Engine"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:129
+msgid "Engine Additions"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:135
+msgid "Compiler"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:141
+msgid "Other Active Contributors"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:148
+msgid "Translators"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:150
+msgid "Asturian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:155
+msgid "Belarusian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:158
+msgid "Bulgarian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:165
+msgid "Chinese (China)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:171
+msgid "Chinese (Taiwan)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:176
+msgid "Cornish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:179
+msgid "Czech"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:184
+msgid "Dutch"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:191
+msgid "English (Australia)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:196
+msgid "Finnish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:201
+msgid "French"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:209
+msgid "German"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:220
+msgid "Greek"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:226
+msgid "Hungarian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:230
+msgid "Irish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:233
+msgid "Italian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:239
+msgid "Kazakh"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:242
+msgid "Korean"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:246
+msgid "Polish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:254
+msgid "Portuguese"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:260
+msgid "Romanian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:267
+msgid "Russian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:278
+msgid "Scottish Gaelic"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:281
+msgid "Serbian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:287
+msgid "Spanish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:298
+msgid "Swedish"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:302
+msgid "Ukrainian"
+msgstr ""
+
+#: qcsrc/menu/xonotic/credits.qc:309
+msgid "Past Contributors"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:73
+msgid "forced to be saved to config.cfg"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:79 qcsrc/menu/xonotic/cvarlist.qc:89
+msgid "will not be saved"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:84
+msgid "will be saved to config.cfg"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:93
+msgid "private"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:95
+msgid "engine setting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/cvarlist.qc:97
+msgid "read only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_credits.qc:13
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:38
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:303
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:85
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:75
+#: qcsrc/menu/xonotic/dialog_singleplayer_winner.qc:14
+msgid "OK"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_credits.qh:7
+msgid "Credits"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_credits.qh:8
+msgid "The Xonotic credits"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:16
+msgid "Are you sure to disconnect from server?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:19
+msgid "I would disconnect from server..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qc:22
+msgid "I would play more!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qh:6
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qh:6
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qh:6
+msgid "Disconnect"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_disconnect.qh:7
+msgid "Disconnect from the server you are connected to"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:39
+msgid ""
+"Welcome to Xonotic, please select your language preference and enter your "
+"player name to get started. You can change these options later through the "
+"menu system."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:45
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:28
+msgid "Name:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:53
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:62
+msgid "Name under which you will appear in the game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:69
+msgid "Text language:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:78
+msgid "Allow player statistics to use your nickname at stats.xonotic.org?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:84
+msgid "Undecided"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qc:88
+msgid "Save settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_firstrun.qh:6
+msgid "Welcome"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:18
+msgid "Ammunition display:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:21
+msgid "Show only current ammo type"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:24
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:46
+msgid "Noncurrent alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:28
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:50
+msgid "Noncurrent scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:32
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:24
+msgid "Align icon:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:33
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:32
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:25
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:37
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:25
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:23
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:35
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:21
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:57
+msgid "Left"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qc:34
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:34
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:27
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:38
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:26
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:25
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:36
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:23
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:59
+msgid "Right"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_ammo.qh:6
+msgid "Ammo Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:19
+msgid "Message duration:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:23
+msgid "Fade time:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:27
+msgid "Flip messages order"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:29
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:18
+msgid "Text alignment:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:33
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qc:22
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:70
+msgid "Center"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qc:37
+msgid "Font scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_centerprint.qh:6
+msgid "Centerprint Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:17
+msgid "Chat entries:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:20
+msgid "Chat size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:24
+msgid "Chat lifetime:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qc:28
+msgid "Chat beep sound"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_chat.qh:6
+msgid "Chat Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.qc:16
+msgid "Engine info:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.qc:19
+msgid "Use an averaging algorithm for fps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_engineinfo.qh:6
+msgid "Engine Info Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:17
+msgid "Combine health and armor"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:19
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:28
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:17
+msgid "Enable status bar"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:21
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:19
+msgid "Status bar alignment:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:29
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:39
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:27
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:37
+msgid "Inward"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:31
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:40
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:29
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:38
+msgid "Outward"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:34
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qc:32
+msgid "Icon alignment:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qc:42
+msgid "Flip health and armor positions"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_healtharmor.qh:6
+msgid "Health/Armor Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.qc:16
+msgid "Info messages:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.qc:19
+msgid "Flip align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_infomessages.qh:6
+msgid "Info Messages Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:16
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:15
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:14
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:15
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:50
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:62
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:77
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:116
+#: qcsrc/menu/xonotic/util.qc:770 qcsrc/menu/xonotic/util.qc:786
+#: qcsrc/menu/xonotic/util.qc:803
+msgid "Disable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:17
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:15
+msgid "Enable spectating"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:18
+msgid "Enable even playing in warmup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:29
+msgid "Reduced"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:32
+msgid "Text/icon ratio:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:35
+msgid "Hide spawned items"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:37
+msgid "Hide big armor and health"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qc:39
+msgid "Dynamic size"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_itemstime.qh:6
+msgid "Items Time Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_modicons.qh:6
+msgid "Mod Icons Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:17
+msgid "Notifications:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:20
+msgid "Also print notifications to the console"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:23
+msgid "Flip notify order"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:26
+msgid "Entry lifetime:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qc:30
+msgid "Entry fadetime:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_notification.qh:6
+msgid "Notification Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:16
+#: qcsrc/menu/xonotic/util.qc:758
+msgid "Enable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:17
+msgid "Enable even observing"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:18
+msgid "Enable only in Race/CTS"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:24
+msgid "Status bar"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:26
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:67
+msgid "Left align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:27
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:73
+msgid "Right align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:28
+msgid "Inward align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:29
+msgid "Outward align"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:33
+msgid "Flip speed/acceleration positions"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:37
+msgid "Speed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:38
+msgid "Include vertical speed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:49
+msgid "Speed unit:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:51
+msgid "qu/s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:52
+msgid "m/s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:53
+msgid "km/h"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:54
+msgid "mph"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:55
+msgid "knots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:57
+msgid "Show"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:60
+msgid "Top speed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:66
+msgid "Acceleration:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qc:67
+msgid "Include vertical acceleration"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_physics.qh:6
+msgid "Physics Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_powerups.qh:6
+msgid "Powerups Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:16
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:17
+msgid "Always enable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qc:23
+msgid "Forced aspect:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_pressedkeys.qh:6
+msgid "Pressed Keys Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_quickmenu.qh:6
+msgid "Quick Menu Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_racetimer.qh:6
+msgid "Race Timer Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:16
+msgid "Enable in team games"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:23
+msgid "Radar:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:26
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:68
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:107
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:54
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:87
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:103
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:45
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:70
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:124
+#: qcsrc/menu/xonotic/util.qc:792
+msgid "Alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:30
+msgid "Rotation:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:32
+msgid "Forward"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:33
+msgid "West"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:34
+msgid "South"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:35
+msgid "East"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:36
+msgid "North"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:40
+msgid "Scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:44
+msgid "Zoom mode:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:46
+msgid "Zoomed in"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:47
+msgid "Zoomed out"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:48
+msgid "Always zoomed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qc:49
+msgid "Never zoomed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_radar.qh:6
+msgid "Radar Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:17
+msgid "Score:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:20
+msgid "Rankings:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:21
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:58
+msgid "Off"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:22
+msgid "And me"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qc:23
+msgid "Pure"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_score.qh:6
+msgid "Score Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_timer.qc:16
+msgid "Timer:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_timer.qc:19
+msgid "Show elapsed time"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_timer.qh:6
+msgid "Timer Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_vote.qc:17
+msgid "Alpha after voting:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_vote.qh:6
+msgid "Vote Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:22
+msgid "Fade out after:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:24
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:167
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:145
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:55
+msgid "Never"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:26
+#, c-format
+msgid "%ds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:30
+msgid "Fade effect:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:33
+msgid "EF^None"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:34
+msgid "Alpha"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:35
+msgid "Slide"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:36
+msgid "EF^Both"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:40
+msgid "Weapon icons:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:43
+msgid "Show only owned weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:54
+msgid "Show weapon ID as:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:55
+msgid "SHOWAS^None"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:56
+msgid "Number"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:57
+msgid "Bind"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:60
+msgid "Weapon ID scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:66
+msgid "Show Accuracy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:67
+msgid "Show Ammo"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:70
+msgid "Ammo bar alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qc:76
+msgid "Ammo bar color:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudpanel_weapons.qh:6
+msgid "Weapons Panel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:19
+msgid "HUD skins"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:22
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:173
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:32
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:42
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:25
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:33
+msgid "Filter:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:30
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:54
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:49
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:43
+msgid "Refresh"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:33
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:28
+msgid "Set skin"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:37
+msgid "Save current skin"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:46
+msgid "Panel background defaults:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:48
+#: qcsrc/menu/xonotic/util.qc:767
+msgid "Background:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:60
+#: qcsrc/menu/xonotic/util.qc:783
+msgid "Border size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:75
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:114
+msgid "Team color:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:83
+#: qcsrc/menu/xonotic/util.qc:809
+msgid "Test team color in configure mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:86
+#: qcsrc/menu/xonotic/util.qc:812
+msgid "Padding:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:93
+msgid "HUD Dock:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:95
+msgid "DOCK^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:96
+msgid "DOCK^Small"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:97
+msgid "DOCK^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:98
+msgid "DOCK^Large"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:121
+msgid "Grid settings:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:124
+msgid "Snap panels to grid"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:127
+msgid "Grid size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:129
+msgid "X:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:136
+msgid "Y:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qc:145
+msgid "Exit setup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_hudsetup_exit.qh:6
+msgid "Panel HUD Setup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:13
+msgid "Monster:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:22
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:20
+msgid "Spawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:23
+msgid "Remove"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:25
+msgid "Move target:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:26
+msgid "Follow"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:27
+msgid "Wander"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:28
+msgid "Spawnpoint"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:29
+msgid "No moving"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:31
+msgid "Colors:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qc:33
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:39
+msgid "Set skin:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_monstertools.qh:6
+msgid "Monster Tools"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:14
+msgid "Servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:15
+msgid "Find servers to play on"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:17
+msgid "Host your own game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:18
+msgid "Media"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qc:19
+msgid "Profile"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qh:6
+msgid "Multiplayer"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer.qh:7
+msgid ""
+"Play online, against your friends in LAN, view demos or change player "
+"settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:38
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:111
+#: qcsrc/menu/xonotic/skinlist.qc:88 qcsrc/menu/xonotic/util.qc:769
+#: 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 ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:40
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:60
+msgid "Unlimited"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:74
+msgid "Gametype"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:79
+msgid "Time limit:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:81
+msgid "Timelimit in minutes that when hit, will end the match"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:82
+#, c-format
+msgid "%d minutes"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:83
+msgid "TIMLIM^Default"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:84
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:159
+msgid "1 minute"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:101
+msgid "TIMLIM^Infinite"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:109
+msgid "Teams:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:112
+msgid "2 teams"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:113
+msgid "3 teams"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:114
+msgid "4 teams"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:117
+msgid "Player slots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:119
+msgid ""
+"The maximum amount of players or bots that can be connected to your server "
+"at once"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:121
+msgid "Number of bots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:123
+msgid "Amount of bots on your server"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:125
+msgid "Bot skill:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:128
+msgid "Specify how experienced the bots will be"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:129
+msgid "Botlike"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:130
+msgid "Beginner"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:131
+msgid "You will win"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:132
+msgid "You can win"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:133
+msgid "You might win"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:134
+msgid "Advanced"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:135
+msgid "Expert"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:136
+msgid "Pro"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:137
+msgid "Assassin"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:138
+msgid "Unhuman"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:139
+msgid "Godlike"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:155
+msgid "Mutators..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:156
+msgid "Mutators and weapon arenas"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:165
+msgid "Maplist"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:175
+msgid ""
+"Click here or Ctrl-F to provide a keyword to narrow down the map list. Ctrl-"
+"Delete to clear; Enter when done."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:184
+msgid "Add shown"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:185
+msgid "Add the maps shown in the list to your selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:188
+msgid "Remove shown"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:189
+msgid "Remove the maps shown in the list from your selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:194
+msgid "Add all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:195
+msgid "Add every available map to your selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:198
+msgid "Remove all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:199
+msgid "Remove all the maps from your selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create.qc:206
+msgid "Start Multiplayer!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:50
+msgid "Title:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:56
+msgid "Author:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:62
+msgid "Game types:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:85
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:257
+msgid "Close"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qc:88
+msgid "MAP^Play"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mapinfo.qh:7
+msgid "Map Information"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:28
+msgid "All Weapons Arena"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:30
+msgid "Most Weapons Arena"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:46
+#, c-format
+msgid "%s Arena"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:57
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:163
+msgid "Dodging"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:59
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:283
+msgid "InstaGib"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:61
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:224
+msgid "New Toys"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:63
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:288
+msgid "NIX"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:65
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:229
+msgid "Rocket Flying"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:67
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:219
+msgid "Invincible Projectiles"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:71
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:298
+msgid "No start weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:73
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:202
+msgid "Low gravity"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:75
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:171
+msgid "Cloaked"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:77
+msgid "Hook"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:79
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:180
+msgid "Midair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:81
+msgid "Melee only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:85
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:234
+msgid "Piñata"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:87
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:239
+msgid "Weapons stay"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:89
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:191
+msgid "Blood loss"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:93
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:175
+msgid "Buffs"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:95
+msgid "Overkill"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:97
+msgid "No powerups"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:99
+msgid "Powerups"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:101
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:167
+msgid "Touch explode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:103
+msgid "Wall jumping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:105
+msgid "MUT^None"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:160
+msgid "Gameplay mutators:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:164
+msgid ""
+"Enable dodging (quick acceleration in a given direction). Double-tap a "
+"directional key to dodge"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:168
+msgid "An explosion occurs when two players collide"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:172
+msgid "All players are almost invisible"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:176
+msgid ""
+"Enable buff pickups (random bonuses like Medic, Invisible, etc.) on the maps "
+"that support it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:181
+msgid "Only possible to inflict damage on your enemy while they're airborne"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:185
+msgid "Damage done to your enemy gets added to your own health"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:190
+msgid ""
+"Amount of health below which players start bleeding out (health rots and "
+"they can't jump)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:199
+msgid "Make things fall to the ground slower (percentage of normal gravity)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:208
+msgid "Weapon & item mutators:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:211
+msgid "Grappling hook"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:212
+msgid "Players spawn with the grappling hook. Press the 'hook' key to use it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:216
+msgid ""
+"Players spawn with the jetpack. Double-tap 'jump' or press the 'jetpack' key "
+"to use it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:220
+msgid ""
+"Projectiles can't be destroyed. However, you can still explode Electro orbs "
+"with the Electro primary fire"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:225
+msgid ""
+"Some weapon spawns will be randomly replaced with new weapons: Heavy Laser "
+"Assault Cannon, Mine Layer, Rifle, T.A.G. Seeker"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:230
+msgid ""
+"Devastator rockets can be detonated instantly (otherwise, there's a short "
+"delay). This allows players to fire and detonate a Devastator rocket while "
+"in the air for a strong mid-air boost even while moving fast"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:235
+msgid "Players will drop all weapons they possessed when they are killed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:240
+msgid "Weapons stay after they are picked up"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:245
+msgid "Regular (no arena)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:246
+msgid ""
+"Players will be given a set of weapons at spawn as well as unlimited ammo, "
+"without weapon pickups"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:248
+msgid "Weapon arenas:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:251
+msgid "Custom weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:273
+msgid "Most weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:277
+msgid "All weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:280
+msgid "Special arenas:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:284
+msgid ""
+"Players will be given only one weapon, which can instantly kill the opponent "
+"with a single shot. If the player runs out of ammo, he will have 10 seconds "
+"to find some or if he fails to do so, face death. The secondary fire mode "
+"does not inflict any damage but is good for doing trickjumps."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:289
+msgid ""
+"No items Xonotic - instead of pickup items, everyone plays with the same "
+"weapon. After some time, a countdown will start, after which everyone will "
+"switch to another weapon."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:293
+msgid "with blaster"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qc:294
+msgid "Always carry the blaster as an additional weapon in Nix"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_create_mutators.qh:9
+msgid "Mutators"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:39
+msgid "SRVS^Categories"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:42
+msgid "SRVS^Empty"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:43
+msgid "Show empty servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:47
+msgid "SRVS^Full"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:48
+msgid "Show full servers that have no slots available"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:52
+msgid "Pause"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:53
+msgid ""
+"Pause updating the server list to prevent servers from \"jumping around\""
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:54
+msgid "Reload the server list"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:68
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:184
+msgid "Address:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:79
+msgid "Info..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:80
+msgid "Show more information about the currently highlighted server"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join.qc:92
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:264
+msgid "Join!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:114
+#: qcsrc/menu/xonotic/serverlist.qc:1020
+msgid "MOD^Default"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:121
+#, c-format
+msgid "%d modified"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:121
+msgid "Official"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:129
+msgid "N/A (auth library missing, can't connect)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:131
+msgid "N/A (auth library missing)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:137
+msgid "Not supported (can't connect)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:139
+msgid "Not supported (won't encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:143
+msgid "Supported (will encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:145
+msgid "Supported (won't encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:149
+msgid "Requested (will encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:151
+msgid "Requested (won't encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:155
+msgid "Required (can't connect)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:157
+msgid "Required (will encrypt)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:161
+msgid "Use the `crypto_aeslevel` cvar to change your preferences"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:178
+msgid "Hostname:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:192
+msgid "Gametype:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:197
+msgid "Map:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:202
+msgid "Mod:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:207
+msgid "Version:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:212
+msgid "Settings:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:219
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:251
+msgid "Players:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:224
+msgid "Bots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:229
+msgid "Free slots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:235
+msgid "Encryption:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:240
+msgid "ID:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qc:245
+msgid "Key:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_join_serverinfo.qh:7
+msgid "Server Information"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:25
+msgid "Demos"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:26
+msgid "Screenshots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media.qc:27
+msgid "Music Player"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:48
+msgid "Auto record demos"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:57
+msgid "Timedemo"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:58
+msgid "Benchmark how fast your computer can run the highlighted demo"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo.qc:62
+msgid "DEMO^Play"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_startconfirm.qc:13
+msgid "Playing a demo will disconnect you from the current match."
+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 ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_demo_timeconfirm.qc:13
+msgid "Timing a demo will disconnect you from the current match."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:37
+msgid "MUSICPL^Add"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:40
+msgid "MUSICPL^Add all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:44
+msgid "Set as menu track"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:48
+msgid "Reset default menu track"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:54
+msgid "Playlist:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:55
+msgid "Random order"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:60
+msgid "MUSICPL^Stop"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:63
+msgid "MUSICPL^Play"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:66
+msgid "MUSICPL^Pause"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:69
+msgid "MUSICPL^Prev"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:72
+msgid "MUSICPL^Next"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:76
+msgid "MUSICPL^Remove"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_musicplayer.qc:79
+msgid "MUSICPL^Remove all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:41
+msgid "Auto screenshot scoreboard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot.qc:62
+msgid "Open in the viewer"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:137
+msgid "Reset"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:142
+msgid "Previous"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:145
+msgid "Next"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_media_screenshot_viewer.qc:150
+msgid "Slide show"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:38
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:21
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:37
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:26
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:21
+msgid "Apply immediately"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:50
+msgid "Name"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:79
+msgid "Model"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:98
+msgid "Glowing color"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:108
+msgid "Detail color"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:123
+msgid "Statistics"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:127
+msgid "Allow player statistics to track your client"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:131
+msgid "Allow player statistics to use your nickname"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:136
+msgid "Allow player statistics to rank you in leaderboards"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:152
+msgid "Country"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:156
+msgid "Select language..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:172
+msgid "Gender:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_multiplayer_profile.qc:179
+msgid "Gender"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_quit.qc:11
+msgid "Are you sure you want to quit?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_quit.qc:15
+msgid "Back to work..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_quit.qc:17
+msgid "I got some more fragging to do!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_quit.qh:7
+msgid "Quit the game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:15
+msgid "Model:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:21
+msgid "Remove *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:23
+msgid "Copy *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:24
+msgid "Paste"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:26
+msgid "Bone:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:31
+msgid "Set * as child"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:32
+msgid "Attach to *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:34
+msgid "Detach from *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:37
+msgid "Visual object properties for *:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:41
+msgid "Set alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:44
+msgid "Set color main:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:46
+msgid "Set color glow:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:50
+msgid "Set frame:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:54
+msgid "Physical object properties for *:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:56
+msgid "Set material:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:62
+msgid "Set solidity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:63
+msgid "Non-solid"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:64
+msgid "Solid"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:65
+msgid "Set physics:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:66
+msgid "Static"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:67
+msgid "Movable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:68
+msgid "Physical"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:70
+msgid "Set scale:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:72
+msgid "Set force:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:76
+msgid "Claim *"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:78
+msgid "* object info"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:79
+msgid "* mesh info"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:80
+msgid "* attachment info"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:81
+msgid "Show help"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qc:82
+msgid "* is the object you are facing"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_sandboxtools.qh:6
+msgid "Sandbox Tools"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:18
+msgid "Video"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:19
+msgid "Effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:20
+msgid "Audio"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:22
+msgid "Game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:23
+msgid "Input"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:24
+msgid "User"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qc:25
+#: qcsrc/menu/xonotic/keybinder.qc:119
+msgid "Misc"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qh:6
+msgid "Settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings.qh:7
+msgid "Change the game settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:29
+msgid "Master:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:35
+msgid "Music:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:43
+msgid "VOL^Ambient:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:50
+msgid "Info:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:57
+msgid "Items:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:64
+msgid "Pain:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:71
+msgid "Player:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:78
+msgid "Shots:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:85
+msgid "Voice:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:93
+msgid "Weapons:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:99
+msgid "New style sound attenuation"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:102
+msgid "Mute sounds when not active"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:105
+msgid "Frequency:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:107
+msgid "Sound output frequency"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:108
+msgid "8 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:109
+msgid "11.025 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:110
+msgid "16 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:111
+msgid "22.05 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:112
+msgid "24 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:113
+msgid "32 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:114
+msgid "44.1 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:115
+msgid "48 kHz"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:119
+msgid "Channels:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:121
+msgid "Number of channels for the sound output"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:122
+msgid "Mono"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:123
+msgid "Stereo"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:124
+msgid "2.1"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:125
+msgid "4"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:126
+msgid "5"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:127
+msgid "5.1"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:128
+msgid "6.1"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:129
+msgid "7.1"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:134
+msgid "Swap stereo output channels"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:135
+msgid "Swap left/right channels"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:138
+msgid "Headphone friendly mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:139
+msgid ""
+"Enable spatialization (blend the right and left channel slightly to decrease "
+"stereo separation a bit for headphones)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:143
+msgid "Hit indication sound"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:144
+msgid "Play a hit indicator sound when your shot hits an enemy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:147
+msgid "Chat message sound"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:149
+msgid "Menu sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:150
+msgid "Play sounds when clicking menu items"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:151
+msgid "Focus sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:152
+msgid "Play sounds when hovering over menu items too"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:156
+msgid "Time announcer:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:158
+msgid "WRN^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:160
+msgid "5 minutes"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:161
+msgid "WRN^Both"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:164
+msgid "Automatic taunts:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:166
+msgid "Automatically taunt enemies after fragging them"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:168
+msgid "Sometimes"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:169
+msgid "Often"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:170
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:147
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:57
+msgid "Always"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_audio.qc:176
+msgid "Debug info about sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qc:11
+msgid "Are you sure you want to reset all key bindings?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_bindings_reset.qh:6
+msgid "Reset key bindings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:41
+msgid "Quality preset:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:45
+msgid "PRE^OMG!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:48
+msgid "PRE^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:50
+msgid "PRE^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:52
+msgid "PRE^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:54
+msgid "PRE^High"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:56
+msgid "PRE^Ultra"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:60
+msgid "PRE^Ultimate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:65
+msgid "Geometry detail:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:67
+msgid "Change the smoothness of the curves on the map"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:68
+msgid "DET^Lowest"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:69
+msgid "DET^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:70
+msgid "DET^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:71
+msgid "DET^Good"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:72
+msgid "DET^Best"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:73
+msgid "DET^Insane"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:77
+msgid "Player detail:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:79
+msgid "PDET^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:80
+msgid "PDET^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:81
+msgid "PDET^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:82
+msgid "PDET^Good"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:83
+msgid "PDET^Best"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:87
+msgid "Texture resolution:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:91
+msgid "RES^Leet"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:92
+msgid "RES^Lowest"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:93
+msgid "RES^Very low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:94
+msgid "RES^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:95
+msgid "RES^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:96
+msgid "RES^Good"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:97
+msgid "RES^Best"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:110
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:115
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:120
+msgid "Avoid lossy texture compression"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:129
+msgid "Disable sky for performance and visibility"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:129
+msgid "Show sky"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:132
+msgid "Show surfaces"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:133
+msgid ""
+"Disable textures completely for very slow hardware. This gives a huge "
+"performance boost, but looks very ugly."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:136
+msgid "Use lightmaps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:137
+msgid ""
+"Use high resolution lightmaps, which will look pretty but use up some extra "
+"video memory"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:139
+msgid "Deluxe mapping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:140
+msgid "Use per-pixel lighting effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:142
+msgid "Gloss"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:143
+msgid "Enable the use of glossmaps on textures supporting it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:146
+msgid "Offset mapping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:147
+msgid ""
+"Offset mapping effect that will make textures with bumpmaps appear like they "
+"\"pop out\" of the flat 2D surface"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:149
+msgid "Relief mapping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:150
+msgid ""
+"Higher quality offset mapping, which also has a huge impact on performance"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:153
+msgid "Reflections:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:154
+msgid ""
+"Reflection and refraction quality, has a huge impact on performance on maps "
+"with reflecting surfaces"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:157
+msgid "Resolution of reflections/refractions"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:158
+msgid "Blurred"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:159
+msgid "REFL^Good"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:160
+msgid "Sharp"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:164
+msgid "Decals"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:165
+msgid "Enable decals (bullet holes and blood)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:166
+msgid "Decals on models"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:170
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:254
+msgid "Distance:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:173
+msgid "Decals further away than this will not be drawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:177
+msgid "Time:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:180
+msgid "Time in seconds before decals fade away"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:184
+msgid "Damage effects:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:186
+msgid "DMGFX^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:187
+msgid "Skeletal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:188
+msgid "DMGFX^All"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:192
+msgid "No dynamic lighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:193
+msgid "Enable corona flares around certain lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:195
+msgid "Fake corona lighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:196
+msgid ""
+"Enable faster but uglier dynamic lights by rendering bright coronas instead "
+"of real dynamic lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:199
+msgid "Realtime dynamic lighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:200
+msgid "Enable rendering of dynamic lights such as explosions and rocket lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:202
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:208
+msgid "Shadows"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:203
+msgid "Enable rendering of shadows from dynamic lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:206
+msgid "Realtime world lighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:207
+msgid ""
+"Enable rendering of full realtime world lighting on maps that support it. "
+"Note that this might have a big impact on performance."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:209
+msgid "Enable rendering of shadows from realtime world lights"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:213
+msgid "Use normal maps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:214
+msgid "Enable use of directional shading on textures"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:216
+msgid "Soft shadows"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:220
+msgid "Fade corona according to visibility"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:221
+msgid "Fade coronas according to visibility"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:225
+msgid "Bloom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:226
+msgid ""
+"Enable bloom effect, which brightens the neighboring pixels of very bright "
+"pixels. Has a big impact on performance."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:227
+msgid "Extra postprocessing effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:228
+msgid ""
+"Enables special postprocessing effects for when damaged or under water or "
+"using a powerup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:233
+msgid "Motion blur strength - 0.4 recommended"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:234
+msgid "Motion blur:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:240
+msgid "Particles"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:241
+msgid "Spawnpoint effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:242
+msgid "Particles effects at all spawn points and whenever a player spawns"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:247
+msgid "Quality:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:250
+#: qcsrc/menu/xonotic/slider_particles.qc:13
+msgid ""
+"Multiplier for amount of particles. Less means less particles, which in turn "
+"gives for better performance"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_effects.qc:257
+msgid "Particles further away than this will not be drawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:31
+msgid "No crosshair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:33
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:62
+msgid "Per weapon"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:34
+msgid ""
+"Set a different crosshair for each weapon, good if you play without weapon "
+"models"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:48
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:81
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:97
+msgid "Size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:64
+msgid "By health"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:76
+msgid "Use rings to indicate weapon status"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:93
+msgid "Enable center crosshair dot"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:111
+msgid "Use normal crosshair color"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:122
+msgid "Smooth effects of crosshairs"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:125
+msgid "Hit testing:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:128
+msgid ""
+"None: do not do hit tests for the crosshair; TrueAim: blur the crosshair "
+"when there's an obstacle between your gun and the target; Enemies: also "
+"enlarge the crosshair when you would hit an enemy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:129
+msgid "HTTST^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:130
+msgid "HTTST^TrueAim"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:131
+msgid "HTTST^Enemies"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:136
+msgid "Blur crosshair if the shot is obstructed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:140
+msgid "Enlarge crosshair if targeting an enemy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:143
+msgid "Animate crosshair when hitting an enemy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qc:146
+msgid "Animate crosshair when picking up an item"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_crosshair.qh:7
+msgid "Crosshair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:43
+msgid "Scoreboard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:48
+msgid "Fading speed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:51
+msgid "Enable rows / columns highlighting"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:53
+msgid "Show accuracy underneath scoreboard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:55
+msgid "Show team sizes:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:56
+msgid ""
+"Team size position: Off=do not show; Left=on the left side of the scoreboard "
+"and move team scores to the right; Right=on the right of the scoreboard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:64
+msgid "Waypoints"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:66
+msgid "Display waypoint markers for objectives on the map"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:67
+msgid "Show various gametype specific waypoints"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:73
+msgid "Control transparency of the waypoints"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:77
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:130
+msgid "Fontsize:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:83
+msgid "Edge offset:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:91
+msgid "Fade when near the crosshair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:95
+msgid "Display names instead of icons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:100
+msgid "Damage"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:102
+msgid "Overlay:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:105
+msgid "Factor:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:110
+msgid "Fade rate:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:118
+msgid "Player Names"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:120
+msgid "Show names above players"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:136
+msgid "Max distance:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:142
+msgid "Decolorize:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:146
+#: qcsrc/menu/xonotic/keybinder.qc:113
+msgid "Teamplay"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:154
+msgid "Only when near crosshair"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:158
+msgid "Display health and armor"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:163
+msgid "Damage overlay:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:166
+msgid "Dynamic HUD"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:167
+msgid "HUD moves around following player's movement"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:169
+msgid "Shake the HUD when hurt"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qc:173
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qh:6
+msgid "Enter HUD editor"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hud.qh:7
+msgid "HUD"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:21
+msgid "In order for the HUD editor to show, you must first be in game."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_hudconfirm.qc:23
+msgid "Do you wish to start a local game to set up the HUD?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:24
+msgid "Frag Information"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:26
+msgid "Display information about killing sprees"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:29
+msgid "Only display sprees if they are achievements"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:34
+msgid "Show spree information in centerprints"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:38
+msgid "Show spree information in death messages"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:43
+msgid "Sprees in info messages:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:46
+msgid "SPREES^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:47
+msgid "Target"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:48
+msgid "Attacker"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:49
+msgid "SPREES^Both"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:55
+msgid "Print on a seperate line"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:58
+msgid "Add extra frag information to centerprint when available"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:62
+msgid "Add frag location to death messages when available"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:65
+msgid "Gamemode Settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:67
+msgid "Display capture times in Capture The Flag"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:71
+msgid "Display name of flag stealer in Capture The Flag"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:76
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:92
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:126
+msgid "Other"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:78
+msgid "Display console messages in the top left corner"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:80
+msgid "Display all info messages in the chatbox"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:82
+msgid "Display player statuses in the chatbox"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:86
+msgid "Powerup notifications"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:89
+msgid "Weapon centerprint notifications"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:92
+msgid "Weapon info message notifications"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:96
+msgid "Announcers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:98
+msgid "Respawn countdown sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:101
+msgid "Killstreak sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qc:104
+msgid "Achievement sounds"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_messages.qh:7
+msgid "Messages"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:30
+msgid "Items"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:32
+msgid "Use simple 2D images instead of item models"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:34
+msgid "Unavailable alpha:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:37
+msgid "Unavailable color:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:39
+msgid "GHOITEMS^Black"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:40
+msgid "GHOITEMS^Dark"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:41
+msgid "GHOITEMS^Tinted"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:42
+msgid "GHOITEMS^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:43
+msgid "GHOITEMS^Blue"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:49
+#: qcsrc/menu/xonotic/serverlist.qc:737
+msgid "Players"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:51
+msgid "Force player models to mine"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:53
+msgid "Force player colors to mine"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:56
+msgid "In non teamplay modes only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:60
+msgid "Body fading:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:63
+msgid "Gibs:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:65
+msgid "GIBS^None"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:66
+msgid "GIBS^Few"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:67
+msgid "GIBS^Many"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qc:68
+msgid "GIBS^Lots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qh:7
+msgid "Models"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_model.qh:8
+msgid "Customize how players and items are displayed in game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:26
+msgid "1st person perspective"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:29
+msgid "Slide to third person upon death"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:33
+msgid "Smooth the view when landing from a jump"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:37
+msgid "Smooth the view while crouching"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:41
+msgid "View waving while idle"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:45
+msgid "View bobbing while walking around"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:50
+msgid "3rd person perspective"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:53
+msgid "Back distance"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:59
+msgid "Up distance"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:65
+msgid "Allow passing through walls while spectating"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:69
+msgid "Field of view:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:71
+msgid "Field of vision in degrees"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:75
+msgid "ZOOM^Zoom factor:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:77
+msgid "How big the zoom factor is when the zoom button is pressed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:80
+msgid "ZOOM^Zoom speed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:82
+msgid "How fast the view will be zoomed, disable to zoom instantly"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:91
+msgid "ZOOM^Instant"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:95
+msgid "ZOOM^Zoom sensitivity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:97
+msgid ""
+"How zoom changes sensitivity, from 0 (lower sensitivity) to 1 (no "
+"sensitivity change)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:100
+msgid "Velocity zoom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:101
+msgid "Forward movement only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:105
+msgid "VZOOM^Factor"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:112
+msgid "Display reticle 2D overlay while zooming"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:115
+msgid "Release zoom when you die or respawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qc:119
+msgid "Release zoom when you switch weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_view.qh:7
+#: qcsrc/menu/xonotic/keybinder.qc:83
+msgid "View"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:33
+msgid "Weapon Priority List (* = mutator weapon)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:39
+msgid "Up"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:43
+msgid "Down"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:49
+msgid "Use priority list for weapon cycling"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:50
+msgid ""
+"Make use of the list above when cycling through weapons with the mouse wheel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:52
+msgid "Cycle through only usable weapon selections"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:56
+msgid "Auto switch weapons on pickup"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:57
+msgid ""
+"Automatically switch to newly picked up weapons if they are better than what "
+"you are carrying"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:60
+msgid "Release attack buttons when you switch weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:63
+msgid "Draw 1st person weapon model"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:64
+msgid "Draw the weapon model"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:68
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:71
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:74
+msgid "Position of the weapon model; requires reconnect"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:77
+msgid "Weapon model opacity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:91
+msgid "Gun model swaying"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qc:96
+msgid "Gun model bobbing"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_game_weapons.qh:7
+#: qcsrc/menu/xonotic/keybinder.qc:51
+msgid "Weapons"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:34
+msgid "Key Bindings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:38
+msgid "Change key..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:42
+msgid "Edit..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:48
+msgid "Clear"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:53
+msgid "Reset all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:58
+msgid "Mouse"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:60
+msgid "Sensitivity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:62
+msgid "Mouse speed multiplier"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:64
+msgid "Smooth aiming"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:65
+msgid "Smoothes the mouse movement, but makes aiming slightly less responsive"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:67
+msgid "Invert aiming"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:68
+msgid "Invert mouse movement on the Y-axis"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:70
+msgid "Use system mouse positioning"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:75
+msgid "Enable built in mouse acceleration"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:79
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:83
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:86
+msgid "Disable system mouse acceleration"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:80
+msgid "Make use of DGA mouse input"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:94
+msgid "Pressing \"enter console\" key also closes it"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:95
+msgid "Allow the console toggling bind to also close the console"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:97
+msgid "Automatically repeat jumping if holding jump"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:100
+msgid "Jetpack on jump:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:102
+msgid "JPJUMP^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:103
+msgid "Air only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:104
+msgid "JPJUMP^All"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:110
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:115
+#: qcsrc/menu/xonotic/dialog_settings_input.qc:120
+msgid "Use joystick input"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:31
+msgid "Command when pressed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:34
+msgid "Command when released:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qc:40
+msgid "Cancel"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_input_userbind.qh:7
+msgid "User defined key bind"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:11
+#, c-format
+msgid "%d fps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:12
+#, c-format
+msgid "%d KB/s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:13
+#, c-format
+msgid "%d MB/s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:27
+msgid "Network"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:29
+msgid "Client UDP port:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:31
+msgid "Force client to use chosen port unless it is set to 0"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:34
+msgid "Bandwidth:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:36
+msgid "Specify your network speed"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:37
+msgid "56k"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:38
+msgid "ISDN"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:39
+msgid "Slow ADSL"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:40
+msgid "Fast ADSL"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:41
+msgid "Broadband"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:44
+msgid "Server queries/s:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:48
+msgid "Downloads:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:50
+msgid "Maximum number of concurrent HTTP/FTP downloads"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:52
+msgid "Download speed:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:65
+msgid "Local latency:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:69
+msgid "Show netgraph"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:70
+msgid "Show a graph of packet sizes and other information"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:72
+msgid "Client-side movement prediction"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:74
+msgid "Movement error compensation"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:78
+msgid "Use encryption (AES) when available"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:81
+msgid "Framerate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:83
+msgid "Maximum:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:93
+msgid "MAXFPS^Unlimited"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:96
+msgid "Target:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:98
+msgid "TRGT^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:109
+msgid "Idle limit:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:115
+msgid "IDLFPS^Unlimited"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:119
+msgid "Save processing time for other apps"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:122
+msgid "Show frames per second"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:123
+msgid "Show your rendered frames per second"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:128
+msgid "Menu tooltips:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:130
+msgid ""
+"Menu tooltips: disabled, standard or advanced (also shows cvar or console "
+"command bound to the menu item)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:131
+msgid "TLTIP^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:132
+msgid "TLTIP^Standard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:133
+msgid "TLTIP^Advanced"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:136
+msgid "Show current date and time"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:137
+msgid "Show current date and time of day, useful on screenshots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:140
+msgid "Enable developer mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:144
+msgid "Advanced settings..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:145
+msgid "Advanced settings where you can tweak every single variable of the game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc.qc:150
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qh:6
+msgid "Factory reset"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:31
+msgid "Cvar filter:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:38
+msgid "Modified cvars only"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:45
+msgid "Setting:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:49
+msgid "Type:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:53
+msgid "Value:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qc:70
+msgid "Description:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_cvars.qh:7
+msgid "Advanced settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:11
+msgid "Are you sure you want to reset all settings?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_misc_reset.qc:13
+msgid "This will create a backup config in your data directory"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:23
+msgid "Menu Skins"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:62
+msgid "Text Language"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:67
+msgid "Set language"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:72
+msgid "Disable gore effects and harsh language"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user.qc:73
+msgid "Replace blood and gibs with content that does not have any gore effects"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:10
+msgid "While connected language changes will be applied only to the menu,"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:12
+msgid "full language changes will take effect starting from the next game"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:16
+msgid "Disconnect now"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qc:17
+msgid "Switch language"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_user_languagewarning.qh:6
+msgid "Warning"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:33
+msgid "Resolution:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:37
+msgid "Font/UI size:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:39
+msgid "SZ^Unreadable"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:40
+msgid "SZ^Tiny"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:41
+msgid "SZ^Little"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:42
+msgid "SZ^Small"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:43
+msgid "SZ^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:44
+msgid "SZ^Large"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:45
+msgid "SZ^Huge"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:46
+msgid "SZ^Gigantic"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:47
+msgid "SZ^Colossal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:51
+msgid "Color depth:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:53
+msgid "How many bits per pixel (BPP) to render at, 32 is recommended"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:54
+msgid "16bit"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:55
+msgid "32bit"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:59
+msgid "Full screen"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:61
+msgid "Vertical Synchronization"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:62
+msgid ""
+"Enable vertical synchronization to prevent tearing, will cap your fps to the "
+"screen refresh rate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:67
+msgid "Flip view horizontally"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:68
+msgid "Poor man's left handed mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:71
+msgid "Anisotropy:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:73
+msgid "Anisotropic filtering quality"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:74
+msgid "ANISO^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:75
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:86
+msgid "2x"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:76
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:87
+msgid "4x"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:77
+msgid "8x"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:78
+msgid "16x"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:81
+msgid "Antialiasing:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:84
+msgid ""
+"Enable antialiasing, which smooths the edges of 3D geometry. Note that it "
+"might decrease performance by quite a lot"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:85
+msgid "AA^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:92
+msgid "High-quality frame buffer"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:97
+msgid "Depth first:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:99
+msgid ""
+"Eliminate overdraw by rendering a depth-only version of the scene before the "
+"normal rendering starts"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:100
+msgid "DF^Disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:101
+msgid "DF^World"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:102
+msgid "DF^All"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:105
+msgid "Vertex Buffer Objects (VBOs)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:108
+msgid "VBO^Off"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:109
+msgid "Vertices, some Tris (compatible)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:110
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:114
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:116
+msgid ""
+"Make use of Vertex Buffer Objects to store static geometry in video memory "
+"for faster rendering"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:113
+msgid "Vertices"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:115
+msgid "Vertices and Triangles"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:119
+msgid "Brightness:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:121
+msgid "Brightness of black"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:123
+msgid "Contrast:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:125
+msgid "Brightness of white"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:127
+msgid "Gamma:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:130
+msgid ""
+"Inverse gamma correction value, a brightness effect that does not affect "
+"white or black"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:133
+msgid "Contrast boost:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:136
+msgid "By how much to multiply the contrast in dark areas"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:139
+msgid "Saturation:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:142
+msgid ""
+"Saturation adjustment (0 = grayscale, 1 = normal, 2 = oversaturated), "
+"requires GLSL color control"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:146
+msgid "LIT^Ambient:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:148
+msgid ""
+"Ambient lighting, if set too high it tends to make light on maps look dull "
+"and flat"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:150
+msgid "Intensity:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:152
+msgid "Global rendering brightness"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:155
+msgid "Wait for GPU to finish each frame"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:156
+msgid ""
+"Make the CPU wait for the GPU to finish each frame, can help with some "
+"strange input or video lag on some machines"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:158
+msgid "Use OpenGL 2.0 shaders (GLSL)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:163
+msgid "Psycho coloring (easter egg)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_settings_video.qc:166
+msgid "Trippy vertices (easter egg)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:109
+msgid "Instant action! (random map with bots)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:116
+msgid "???"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:129
+msgid "Campaign Difficulty:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:130
+msgid "CSKL^Easy"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:131
+msgid "CSKL^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:132
+msgid "CSKL^Hard"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qc:134
+msgid "Start Singleplayer!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qh:6
+msgid "Singleplayer"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer.qh:7
+msgid "Play the singleplayer campaign or instant action matches against bots"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_singleplayer_winner.qh:7
+msgid "Winner"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:32
+msgid "join 'best' team (auto-select)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:33
+msgid "Autoselect team (recommended)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:37
+msgid "red"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:38
+msgid "blue"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:39
+msgid "yellow"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:40
+msgid "pink"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qc:43
+#: qcsrc/menu/xonotic/keybinder.qc:116
+msgid "spectate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_teamselect.qh:7
+msgid "Team Selection"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_uid2name.qc:10
+msgid "Allow player statistics to use your nickname?"
+msgstr ""
+
+#: qcsrc/menu/xonotic/dialog_uid2name.qc:12
+msgid "Answering \"No\" you will appear as \"Anonymous player\""
+msgstr ""
+
+#: qcsrc/menu/xonotic/gametypelist.qc:87
+msgid "teamplay"
+msgstr ""
+
+#: qcsrc/menu/xonotic/gametypelist.qc:89
+msgid "free for all"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:35
+msgid "Moving"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:36
+msgid "forward"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:37
+msgid "backpedal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:38
+msgid "strafe left"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:39
+msgid "strafe right"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:40
+msgid "jump / swim"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:41
+msgid "crouch / sink"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:42
+msgid "off-hand hook"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:43
+msgid "jetpack"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:46
+msgid "Attacking"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:52
+msgid "WEAPON^previous"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:53
+msgid "WEAPON^next"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:54
+msgid "WEAPON^previously used"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:55
+msgid "WEAPON^best"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:56
+msgid "reload"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:57
+msgid "drop weapon / throw nade"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:84
+msgid "hold zoom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:85
+msgid "toggle zoom"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:86
+msgid "show scores"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:87
+msgid "screen shot"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:88
+msgid "maximize radar"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:89
+msgid "3rd person view"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:90
+msgid "enter spectator mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:93
+msgid "Communication"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:94
+msgid "public chat"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:95
+msgid "team chat"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:96
+msgid "show chat history"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:97
+msgid "vote YES"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:98
+msgid "vote NO"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:102
+msgid "Client"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:106 qcsrc/menu/xonotic/keybinder.qc:108
+msgid "enter console"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:109
+msgid "disconnect"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:110
+msgid "quit"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:114
+msgid "auto-join team"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:120
+msgid "drop key/flag, exit vehicle"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:121
+msgid "suicide / respawn"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:122
+msgid "quick menu"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:125
+msgid "User defined"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:132
+msgid "Development"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:133
+msgid "sandbox menu"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:134
+msgid "drag object (sandbox)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/keybinder.qc:135
+msgid "waypoint editor menu"
+msgstr ""
+
+#: qcsrc/menu/xonotic/mainwindow.qc:96 qcsrc/menu/xonotic/mainwindow.qc:99
+msgid "Do not press this button again!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/maplist.qc:288
+msgid ""
+"Huh? Can't play this (m is NULL). Refiltering so this won't happen again."
+msgstr ""
+
+#: qcsrc/menu/xonotic/maplist.qc:296
+#, c-format
+msgid "%s's Xonotic Server"
+msgstr ""
+
+#: qcsrc/menu/xonotic/maplist.qc:301
+msgid ""
+"Huh? Can't play this (invalid game type). Refiltering so this won't happen "
+"again."
+msgstr ""
+
+#: qcsrc/menu/xonotic/playerlist.qc:102 qcsrc/menu/xonotic/playerlist.qc:112
+msgid "spectator"
+msgstr ""
+
+#: qcsrc/menu/xonotic/playermodel.qc:161
+msgid "<no model found>"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:256
+msgid "SERVER^Remove favorite"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:257
+msgid "Remove the currently highlighted server from bookmarks"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:261
+msgid "SERVER^Favorite"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:262
+msgid ""
+"Bookmark the currently highlighted server so that it's faster to find in the "
+"future"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:733
+msgid "Ping"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:734
+msgid "Hostname"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:735
+msgid "Map"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:736
+msgid "Type"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1019
+#, c-format
+msgid "AES level %d"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1019
+msgid "ENC^none"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1019
+msgid "encryption:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1020
+#, c-format
+msgid "mod: %s"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1022
+#, c-format
+msgid "modified settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1022
+#, c-format
+msgid "official settings"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1024
+msgid "stats disabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qc:1024
+msgid "stats enabled"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:152
+msgid "SLCAT^Favorites"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:153
+msgid "SLCAT^Recommended"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:154
+msgid "SLCAT^Normal Servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:155
+msgid "SLCAT^Servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:156
+msgid "SLCAT^Competitive Mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:157
+msgid "SLCAT^Modified Servers"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:158
+msgid "SLCAT^Overkill"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:159
+msgid "SLCAT^InstaGib"
+msgstr ""
+
+#: qcsrc/menu/xonotic/serverlist.qh:160
+msgid "SLCAT^Defrag Mode"
+msgstr ""
+
+#: qcsrc/menu/xonotic/skinlist.qc:70
+msgid "<TITLE>"
+msgstr ""
+
+#: qcsrc/menu/xonotic/skinlist.qc:71
+msgid "<AUTHOR>"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_decibels.qc:72
+msgid "VOL^MAX"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_decibels.qc:74
+msgid "VOL^OFF"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_decibels.qc:82
+#, c-format
+msgid "%s dB"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:14
+msgid "PART^OMG"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:15
+msgid "PART^Low"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:16
+msgid "PART^Medium"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:17
+#: qcsrc/menu/xonotic/slider_sbfadetime.qc:14
+msgid "PART^Normal"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:18
+msgid "PART^High"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:19
+msgid "PART^Ultra"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_particles.qc:20
+msgid "PART^Ultimate"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_picmip.qc:13
+msgid ""
+"Change the sharpness of the textures. Lowering it will effectively reduce "
+"texture memory usage, but make the textures appear very blurry."
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_resolution.qc:115
+msgid "Screen resolution"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_sbfadetime.qc:13
+msgid "PART^Slow"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_sbfadetime.qc:15
+msgid "PART^Fast"
+msgstr ""
+
+#: qcsrc/menu/xonotic/slider_sbfadetime.qc:16
+msgid "PART^Instant"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:29
+msgid "January"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:30
+msgid "February"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:31
+msgid "March"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:32
+msgid "April"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:33
+msgid "May"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:34
+msgid "June"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:35
+msgid "July"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:36
+msgid "August"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:37
+msgid "September"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:38
+msgid "October"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:39
+msgid "November"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:40
+msgid "December"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:46
+#, no-c-format
+msgid "DATE^%m %d, %Y"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:97
+msgid "Joined:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:104
+msgid "Last match:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:111
+msgid "Time played:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:118 qcsrc/menu/xonotic/statslist.qc:231
+msgid "Favorite map:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:150 qcsrc/menu/xonotic/statslist.qc:202
+#: qcsrc/menu/xonotic/statslist.qc:245
+#, c-format
+msgid "Matches:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:155
+#, c-format
+msgid "Wins/Losses:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:156
+#, c-format
+msgid "Win percentage:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:167
+#, c-format
+msgid "Kills/Deaths:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:173
+#, c-format
+msgid "Kill ratio:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:208
+msgid "ELO:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:215
+msgid "Rank:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:222
+msgid "Percentile:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/statslist.qc:247
+#, c-format
+msgid "%d (unranked)"
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:420
+msgid "Update can be downloaded at:"
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:528
+msgid "Autogenerating mapinfo for newly added maps..."
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:566
+#, c-format
+msgid "Update to %s now!"
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:650
+msgid ""
+"^1ERROR: Texture compression is required but not supported.\n"
+"^1Expect visual problems."
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:780
+msgid "Use default"
+msgstr ""
+
+#: qcsrc/menu/xonotic/util.qc:800
+msgid "Team Color:"
+msgstr ""
# Antoni Das <Antonidas159@gmail.com>, 2015
# Antoni Das <Antonidas159@gmail.com>, 2015,2017
# sapphireliu <balancedliu@gmail.com>, 2014
+# CodingJellyfish <dumaosen_main01@outlook.com>, 2018
# kalawore <kalawore@outlook.com>, 2015
# Liang Liu <dxkliu@126.com>, 2019
# Losier Blackheath <losier.cc@gmail.com>, 2018
# sapphireliu <balancedliu@gmail.com>, 2014
-# 杜茂森 <dumaosen_main01@outlook.com>, 2018-2020
-# 杜茂森 <dumaosen_main01@outlook.com>, 2018
+# CodingJellyfish <dumaosen_main01@outlook.com>, 2018-2020
+# CodingJellyfish <dumaosen_main01@outlook.com>, 2018
# 韬 刘 <jiegushijia@gmail.com>, 2019
msgid ""
msgstr ""
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2020-06-07 07:23+0200\n"
"PO-Revision-Date: 2020-07-25 11:27+0000\n"
-"Last-Translator: 杜茂森 <dumaosen_main01@outlook.com>\n"
+"Last-Translator: CodingJellyfish <dumaosen_main01@outlook.com>\n"
"Language-Team: Chinese (China) (http://www.transifex.com/team-xonotic/"
"xonotic/language/zh_CN/)\n"
"Language: zh_CN\n"
seta hud_panel_centerprint_align "0.5"
seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
-seta hud_panel_centerprint_fontscale_bold "1.8"
+seta hud_panel_centerprint_fontscale_bold "1.4"
seta hud_panel_centerprint_time "3"
seta hud_panel_centerprint_fade_in "0.2"
seta hud_panel_centerprint_fade_out "0.5"
seta hud_panel_centerprint_align "0.5"
seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
-seta hud_panel_centerprint_fontscale_bold "1.8"
+seta hud_panel_centerprint_fontscale_bold "1.4"
seta hud_panel_centerprint_time "3"
seta hud_panel_centerprint_fade_in "0.2"
seta hud_panel_centerprint_fade_out "0.5"
seta hud_panel_centerprint_align "0.5"
seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
-seta hud_panel_centerprint_fontscale_bold "1.8"
+seta hud_panel_centerprint_fontscale_bold "1.4"
seta hud_panel_centerprint_time "3"
seta hud_panel_centerprint_fade_in "0.2"
seta hud_panel_centerprint_fade_out "0.5"
seta hud_panel_centerprint_align "0.5"
seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
-seta hud_panel_centerprint_fontscale_bold "1.8"
+seta hud_panel_centerprint_fontscale_bold "1.4"
seta hud_panel_centerprint_time "3"
seta hud_panel_centerprint_fade_in "0.2"
seta hud_panel_centerprint_fade_out "0.5"
seta hud_panel_centerprint_align "0.5"
seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
-seta hud_panel_centerprint_fontscale_bold "1.8"
+seta hud_panel_centerprint_fontscale_bold "1.4"
seta hud_panel_centerprint_time "3"
seta hud_panel_centerprint_fade_in "0.2"
seta hud_panel_centerprint_fade_out "0.5"
seta hud_panel_centerprint_align "0.5"
seta hud_panel_centerprint_flip "0"
seta hud_panel_centerprint_fontscale "1"
-seta hud_panel_centerprint_fontscale_bold "1.8"
+seta hud_panel_centerprint_fontscale_bold "1.4"
seta hud_panel_centerprint_time "3"
seta hud_panel_centerprint_fade_in "0.2"
seta hud_panel_centerprint_fade_out "0.5"
fi "Finnish" "Suomi" 100%
el "Greek" "Ελληνική" 47%
be "Belarusian" "Беларуская" 54%
-bg "Bulgarian" "Български" 59%
+bg "Bulgarian" "Български" 63%
ru "Russian" "Русский" 100%
sr "Serbian" "Српски" 64%
uk "Ukrainian" "Українська" 50%
#include <client/teamradar.qc>
#include <client/view.qc>
-#include <client/commands/_mod.inc>
+#include <client/command/_mod.inc>
#include <client/hud/_mod.inc>
+#include <client/items/_mod.inc>
#include <client/mutators/_mod.inc>
#include <client/weapons/_mod.inc>
#include <client/teamradar.qh>
#include <client/view.qh>
-#include <client/commands/_mod.qh>
+#include <client/command/_mod.qh>
#include <client/hud/_mod.qh>
+#include <client/items/_mod.qh>
#include <client/mutators/_mod.qh>
#include <client/weapons/_mod.qh>
float autocvar_hud_panel_centerprint_fade_minfontsize = 0;
bool autocvar_hud_panel_centerprint_flip;
float autocvar_hud_panel_centerprint_fontscale;
-float autocvar_hud_panel_centerprint_fontscale_bold = 1.8;
+float autocvar_hud_panel_centerprint_fontscale_bold = 1.4;
float autocvar_hud_panel_centerprint_time;
bool autocvar_hud_panel_chat;
bool autocvar_hud_panel_engineinfo;
#include <common/util.qh>
#include <client/autocvars.qh>
-#include <client/defs.qh>
#include <client/main.qh>
#define CONSTANT_SPEED_DECAY
#pragma once
-entityclass(BGMScript);
-classfield(BGMScript) .string bgmscript;
-classfield(BGMScript) .float bgmscriptattack;
-classfield(BGMScript) .float bgmscriptdecay;
-classfield(BGMScript) .float bgmscriptsustain;
-classfield(BGMScript) .float bgmscriptrelease;
+#include <common/mapobjects/bgmscript.qh>
classfield(BGMScript) .float just_toggled;
-#ifdef CSQC
+float bgmtime;
+
void BGMScript_InitEntity(entity e);
float doBGMScript(entity e);
-#endif
--- /dev/null
+// generated file; do not modify
+#ifdef CSQC
+ #include <client/command/cl_cmd.qc>
+#endif
--- /dev/null
+// generated file; do not modify
+#ifdef CSQC
+ #include <client/command/cl_cmd.qh>
+#endif
--- /dev/null
+#include "cl_cmd.qh"
+// ==============================================
+// CSQC client commands code, written by Samual
+// Last updated: December 28th, 2011
+// ==============================================
+
+#include <common/command/_mod.qh>
+#include "cl_cmd.qh"
+
+#include "../autocvars.qh"
+#include <client/hud/_mod.qh>
+#include <client/hud/panel/quickmenu.qh>
+#include <client/hud/panel/radar.qh>
+#include <client/hud/panel/scoreboard.qh>
+#include <client/hud/panel/vote.qh>
+#include "../main.qh"
+#include "../mapvoting.qh"
+#include "../miscfunctions.qh"
+#include <client/view.qh>
+
+#include <client/mutators/_mod.qh>
+
+#include <common/minigames/cl_minigames_hud.qh>
+
+#include <common/mapinfo.qh>
+
+void DrawDebugModel(entity this)
+{
+ if (time - floor(time) > 0.5)
+ {
+ PolyDrawModel(this);
+ this.drawmask = 0;
+ }
+ else
+ {
+ this.renderflags = 0;
+ this.drawmask = MASK_NORMAL;
+ }
+}
+
+
+// =======================
+// Command Sub-Functions
+// =======================
+
+void LocalCommand_blurtest(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.
+
+ #ifdef BLURTEST
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ blurtest_time0 = time;
+ blurtest_time1 = time + stof(argv(1));
+ blurtest_radius = stof(argv(2));
+ blurtest_power = stof(argv(3));
+ LOG_INFO("Enabled blurtest");
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd blurtest");
+ LOG_HELP(" No arguments required.");
+ return;
+ }
+ }
+ #else
+ if (request)
+ {
+ LOG_INFO("Blurtest is not enabled on this client.");
+ return;
+ }
+ #endif
+}
+
+void LocalCommand_boxparticles(int request, int argc)
+{
+ TC(int, request); TC(int, argc);
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if (argc == 9)
+ {
+ int effect = _particleeffectnum(argv(1));
+ if (effect >= 0)
+ {
+ int index = stoi(argv(2));
+ entity own;
+ if (index <= 0)
+ own = entitybyindex(-index);
+ else
+ own = findfloat(NULL, entnum, index);
+ vector org_from = stov(argv(3));
+ vector org_to = stov(argv(4));
+ vector dir_from = stov(argv(5));
+ vector dir_to = stov(argv(6));
+ int countmultiplier = stoi(argv(7));
+ int flags = stoi(argv(8));
+ boxparticles(effect, own, org_from, org_to, dir_from, dir_to, countmultiplier, flags);
+ return;
+ }
+ }
+ }
+
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP(
+ "Usage:^3 cl_cmd boxparticles effectname own org_from org_to, dir_from, dir_to, countmultiplier, flags\n"
+ " 'effectname' is the name of a particle effect in effectinfo.txt\n"
+ " 'own' is the entity number of the owner (negative for csqc ent, positive for svqc ent)\n"
+ " 'org_from' is the starting origin of the box\n"
+ " 'org_to' is the ending origin of the box\n"
+ " 'dir_from' is the minimum velocity\n"
+ " 'dir_to' is the maximum velocity\n"
+ " 'countmultiplier' defines a multiplier for the particle count (affects count only, not countabsolute or trailspacing)\n"
+ " 'flags' can contain:\n"
+ " 1 to respect globals particles_alphamin, particles_alphamax (set right before via prvm_globalset client)\n"
+ " 2 to respect globals particles_colormin, particles_colormax (set right before via prvm_globalset client)\n"
+ " 4 to respect globals particles_fade (set right before via prvm_globalset client)\n"
+ " 128 to draw a trail, not a box"
+ );
+ return;
+ }
+ }
+}
+
+void LocalCommand_create_scrshot_ent(int request)
+{
+ TC(int, request);
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ string path = ((argv(1) == "") ? "" : strcat(argv(1), "/"));
+ string filename = strcat(path, MapInfo_Map_bspname, "_scrshot_ent.txt");
+ int fh = fopen(filename, FILE_APPEND);
+
+ if (fh >= 0)
+ {
+ fputs(fh, "{\n");
+ fputs(fh, strcat("\"classname\" \"info_autoscreenshot\"\n"));
+ fputs(fh, strcat("\"origin\" \"", strcat(ftos(view_origin.x), " ", ftos(view_origin.y), " ", ftos(view_origin.z)), "\"\n"));
+ fputs(fh, strcat("\"angles\" \"", strcat(ftos(view_angles.x), " ", ftos(view_angles.y), " ", ftos(view_angles.z)), "\"\n"));
+ fputs(fh, "}\n");
+
+ LOG_INFO("Completed screenshot entity dump in ^2data/data/", path, MapInfo_Map_bspname, "_scrshot_ent.txt^7.");
+
+ fclose(fh);
+ }
+ else
+ {
+ LOG_INFO("^1Error: ^7Could not dump to file!");
+ }
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd create_scrshot_ent [path]");
+ LOG_HELP(" Where 'path' can be the subdirectory of data/data in which the file is saved.");
+ return;
+ }
+ }
+}
+
+void LocalCommand_debugmodel(int request, int argc)
+{
+ TC(int, request); TC(int, argc);
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ string modelname = argv(1);
+
+ entity debugmodel_entity = new(debugmodel);
+ precache_model(modelname);
+ _setmodel(debugmodel_entity, modelname);
+ setorigin(debugmodel_entity, view_origin);
+ debugmodel_entity.angles = view_angles;
+ debugmodel_entity.draw = DrawDebugModel;
+ IL_PUSH(g_drawables, debugmodel_entity);
+
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd debugmodel model");
+ LOG_HELP(" Where 'model' is a string of the model name to use for the debug model.");
+ return;
+ }
+ }
+}
+
+void LocalCommand_handlevote(int request, int argc)
+{
+ TC(int, request); TC(int, argc);
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ int vote_selection;
+ string vote_string;
+
+ if (InterpretBoolean(argv(1)))
+ {
+ vote_selection = 2;
+ vote_string = "yes";
+ }
+ else
+ {
+ vote_selection = 1;
+ vote_string = "no";
+ }
+
+ if (vote_selection)
+ {
+ if (uid2name_dialog) // handled by "uid2name" option
+ {
+ vote_active = 0;
+ vote_prev = 0;
+ vote_change = -9999;
+ localcmd(strcat("setreport cl_allow_uid2name ", ftos(vote_selection - 1), "\n"));
+ uid2name_dialog = 0;
+ }
+ else { localcmd(strcat("cmd vote ", vote_string, "\n")); }
+
+ return;
+ }
+ }
+
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd handlevote vote");
+ LOG_HELP(" Where 'vote' is the selection for either the current poll or uid2name.");
+ return;
+ }
+ }
+}
+
+void LocalCommand_hud(int request, int argc)
+{
+ TC(int, request); TC(int, argc);
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if(MUTATOR_CALLHOOK(HUD_Command, argc))
+ return;
+
+ switch (argv(1))
+ {
+ case "configure":
+ {
+ cvar_set("_hud_configure", ftos(!autocvar__hud_configure));
+ return;
+ }
+
+ case "quickmenu":
+ {
+ if (argv(2) == "help")
+ {
+ LOG_HELP(" quickmenu [[default | file | \"\"] submenu file]");
+ LOG_HELP("Called without options (or with \"\") loads either the default quickmenu or a quickmenu file if hud_panel_quickmenu_file is set to a valid filename.");
+ LOG_HELP("A submenu name can be given to open the quickmenu directly in a submenu; it requires to specify 'default', 'file' or '\"\"' option.");
+ LOG_HELP("A file name can also be given to open a different quickmenu");
+ return;
+ }
+ string file = ((argv(4) == "") ? autocvar_hud_panel_quickmenu_file : argv(4));
+ if (QuickMenu_IsOpened())
+ QuickMenu_Close();
+ else
+ QuickMenu_Open(argv(2), argv(3), file); // mode, submenu
+ return;
+ }
+
+ case "save":
+ {
+ if (argv(2))
+ {
+ HUD_Panel_ExportCfg(argv(2));
+ return;
+ }
+ else
+ {
+ break; // go to usage, we're missing the paramater needed here.
+ }
+ }
+
+ case "scoreboard_columns_set":
+ {
+ Cmd_Scoreboard_SetFields(argc);
+ return;
+ }
+
+ case "scoreboard_columns_help":
+ {
+ Cmd_Scoreboard_Help();
+ return;
+ }
+
+ case "radar":
+ {
+ if (argv(2))
+ HUD_Radar_Show_Maximized(InterpretBoolean(argv(2)), 0);
+ else
+ HUD_Radar_Show_Maximized(!hud_panel_radar_maximized, 0);
+ return;
+ }
+
+ case "clickradar":
+ {
+ if(!isdemo())
+ HUD_Radar_Show_Maximized(!hud_panel_radar_mouse, 1);
+ return;
+ }
+ }
+ }
+
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd hud action [configname | radartoggle | layout]");
+ LOG_HELP(" Where 'action' is the command to complete,");
+ LOG_HELP(" 'configname' is the name to save to for \"save\" action,");
+ LOG_HELP(" 'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,");
+ LOG_HELP(" and 'layout' is how to organize the scoreboard columns for the set action.");
+ LOG_HELP(" Full list of commands here: \"configure, quickmenu, minigame, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"");
+ return;
+ }
+ }
+}
+
+void LocalCommand_localprint(int request, int argc)
+{
+ TC(int, request); TC(int, argc);
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if (argv(1))
+ {
+ centerprint_AddStandard(argv(1));
+ return;
+ }
+ }
+
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd localprint \"message\"");
+ LOG_HELP(" 'message' is the centerprint message to send to yourself.");
+ return;
+ }
+ }
+}
+
+void LocalCommand_mv_download(int request, int argc)
+{
+ TC(int, request); TC(int, argc);
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if (argv(1))
+ {
+ Cmd_MapVote_MapDownload(argc);
+ return;
+ }
+ }
+
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd mv_download mapid");
+ LOG_HELP(" Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.");
+ return;
+ }
+ }
+}
+
+void LocalCommand_sendcvar(int request, int argc)
+{
+ TC(int, request); TC(int, argc);
+ switch (request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+ if (argv(1))
+ {
+ // W_FixWeaponOrder will trash argv, so save what we need.
+ string thiscvar = string_null; strcpy(thiscvar, argv(1));
+ string s = cvar_string(thiscvar);
+
+ if (thiscvar == "cl_weaponpriority")
+ s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1);
+ else if (substring(thiscvar, 0, 17) == "cl_weaponpriority" && strlen(thiscvar) == 18)
+ s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0);
+
+ localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n");
+ strfree(thiscvar);
+ return;
+ }
+ }
+
+ default:
+ LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd sendcvar <cvar>");
+ LOG_HELP(" Where 'cvar' is the cvar to send to the server.");
+ return;
+ }
+ }
+}
+
+/* use this when creating a new command, making sure to place it in alphabetical order... also,
+** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
+void LocalCommand_(int request)
+{
+ switch(request)
+ {
+ case CMD_REQUEST_COMMAND:
+ {
+
+ return;
+ }
+
+ default:
+ case CMD_REQUEST_USAGE:
+ {
+ LOG_HELP("Usage:^3 cl_cmd ");
+ LOG_HELP(" No arguments required.");
+ return;
+ }
+ }
+}
+*/
+
+
+// ==================================
+// Macro system for client commands
+// ==================================
+
+// Normally do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
+CLIENT_COMMAND(blurtest, "Feature for testing blur postprocessing") { LocalCommand_blurtest(request); }
+CLIENT_COMMAND(boxparticles, "Spawn particles manually") { LocalCommand_boxparticles(request, arguments); }
+CLIENT_COMMAND(create_scrshot_ent, "Create an entity at this location for automatic screenshots") { LocalCommand_create_scrshot_ent(request); }
+CLIENT_COMMAND(debugmodel, "Spawn a debug model manually") { LocalCommand_debugmodel(request, arguments); }
+CLIENT_COMMAND(handlevote, "System to handle selecting a vote or option") { LocalCommand_handlevote(request, arguments); }
+CLIENT_COMMAND(hud, "Commands regarding/controlling the HUD system") { LocalCommand_hud(request, arguments); }
+CLIENT_COMMAND(localprint, "Create your own centerprint sent to yourself") { LocalCommand_localprint(request, arguments); }
+CLIENT_COMMAND(mv_download, "Retrieve mapshot picture from the server") { LocalCommand_mv_download(request, arguments); }
+CLIENT_COMMAND(sendcvar, "Send a cvar to the server (like cl_weaponpriority)") { LocalCommand_sendcvar(request, arguments); }
+
+void LocalCommand_macro_help()
+{
+ FOREACH(CLIENT_COMMANDS, true, LOG_HELPF(" ^2%s^7: %s", it.m_name, it.m_description));
+}
+
+bool LocalCommand_macro_command(int argc, string command)
+{
+ string c = strtolower(argv(0));
+ FOREACH(CLIENT_COMMANDS, it.m_name == c, {
+ it.m_invokecmd(it, CMD_REQUEST_COMMAND, NULL, argc, command);
+ return true;
+ });
+ return false;
+}
+
+bool LocalCommand_macro_usage(int argc)
+{
+ string c = strtolower(argv(1));
+ FOREACH(CLIENT_COMMANDS, it.m_name == c, {
+ it.m_invokecmd(it, CMD_REQUEST_USAGE, NULL, argc, "");
+ return true;
+ });
+ return false;
+}
+
+void LocalCommand_macro_write_aliases(int fh)
+{
+ FOREACH(CLIENT_COMMANDS, true, CMD_Write_Alias("qc_cmd_cl", it.m_name, it.m_description));
+}
+
+
+// =========================================
+// Main Function Called By Engine (cl_cmd)
+// =========================================
+// If this function exists, client code handles gamecommand instead of the engine code.
+
+void GameCommand(string command)
+{
+ int argc = tokenize_console(command);
+
+ // Guide for working with argc arguments by example:
+ // argc: 1 - 2 - 3 - 4
+ // argv: 0 - 1 - 2 - 3
+ // cmd vote - master - login - password
+ string s = strtolower(argv(0));
+ if (s == "help")
+ {
+ if (argc == 1)
+ {
+ LOG_HELP("Client console commands:");
+ LocalCommand_macro_help();
+
+ LOG_HELP("\nGeneric commands shared by all programs:");
+ GenericCommand_macro_help();
+
+ LOG_HELP("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are listed above.");
+ LOG_HELP("For help about a specific command, type cl_cmd help COMMAND");
+
+ return;
+ }
+ else if (GenericCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
+ {
+ return;
+ }
+ else if (LocalCommand_macro_usage(argc)) // now try for normal commands too
+ {
+ return;
+ }
+ }
+ // continue as usual and scan for normal commands
+ if (GenericCommand(command) // handled by common/command/generic.qc
+ || LocalCommand_macro_command(argc, command) // handled by one of the above LocalCommand_* functions
+ || MUTATOR_CALLHOOK(CSQC_ConsoleCommand, s, argc, command) // handled by a mutator
+ ) return;
+
+ // nothing above caught the command, must be invalid
+ LOG_INFO(((command != "") ? strcat("Unknown client command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try cl_cmd help.");
+}
+
+
+// ===================================
+// Macro system for console commands
+// ===================================
+
+// These functions are here specifically to add special + - commands to the game, and are not really normal commands.
+// Please add client commands to the function above this, as this is only for special reasons.
+// NOTE: showaccuracy is kept as legacy command
+#define CONSOLE_COMMANDS_NORMAL() \
+ CONSOLE_COMMAND("+showscores", { scoreboard_showscores = true; }) \
+ CONSOLE_COMMAND("-showscores", { scoreboard_showscores = false; }) \
+ CONSOLE_COMMAND("+showaccuracy", { }) \
+ CONSOLE_COMMAND("-showaccuracy", { }) \
+ /* nothing */
+
+#define CONSOLE_COMMANDS_MOVEMENT() \
+ CONSOLE_COMMAND("+forward", { ++camera_direction.x; }) \
+ CONSOLE_COMMAND("-forward", { --camera_direction.x; }) \
+ CONSOLE_COMMAND("+back", { --camera_direction.x; }) \
+ CONSOLE_COMMAND("-back", { ++camera_direction.x; }) \
+ CONSOLE_COMMAND("+moveup", { ++camera_direction.z; }) \
+ CONSOLE_COMMAND("-moveup", { --camera_direction.z; }) \
+ CONSOLE_COMMAND("+movedown", { --camera_direction.z; }) \
+ CONSOLE_COMMAND("-movedown", { ++camera_direction.z; }) \
+ CONSOLE_COMMAND("+moveright", { --camera_direction.y; }) \
+ CONSOLE_COMMAND("-moveright", { ++camera_direction.y; }) \
+ CONSOLE_COMMAND("+moveleft", { ++camera_direction.y; }) \
+ CONSOLE_COMMAND("-moveleft", { --camera_direction.y; }) \
+ CONSOLE_COMMAND("+roll_right", { ++camera_roll; }) \
+ CONSOLE_COMMAND("-roll_right", { --camera_roll; }) \
+ CONSOLE_COMMAND("+roll_left", { --camera_roll; }) \
+ CONSOLE_COMMAND("-roll_left", { ++camera_roll; }) \
+ /* nothing */
+
+void ConsoleCommand_macro_init()
+{
+ // first init normal commands
+ #define CONSOLE_COMMAND(name, execution) \
+ { registercommand(name); }
+
+ CONSOLE_COMMANDS_NORMAL();
+ #undef CONSOLE_COMMAND
+
+ // then init movement commands
+ #ifndef CAMERATEST
+ if (isdemo())
+ {
+ #endif
+ #define CONSOLE_COMMAND(name, execution) \
+ registercommand(name);
+
+ CONSOLE_COMMANDS_MOVEMENT();
+ #undef CONSOLE_COMMAND
+ #ifndef CAMERATEST
+}
+ #endif
+}
+
+bool ConsoleCommand_macro_normal(string s, int argc)
+{
+ #define CONSOLE_COMMAND(name, execution) \
+ { if (name == s) { { execution } return true; } }
+
+ CONSOLE_COMMANDS_NORMAL();
+ #undef CONSOLE_COMMAND
+
+ return false;
+}
+
+bool ConsoleCommand_macro_movement(string s, int argc)
+{
+ if (camera_active)
+ {
+ #define CONSOLE_COMMAND(name, execution) \
+ { if (name == s) { { execution } return true; } }
+
+ CONSOLE_COMMANDS_MOVEMENT();
+ #undef CONSOLE_COMMAND
+ }
+
+ return false;
+}
+
+
+// ======================================================
+// Main Function Called By Engine (registered commands)
+// ======================================================
+// Used to parse commands in the console that have been registered with the "registercommand" function
+
+bool CSQC_ConsoleCommand(string command)
+{
+ int argc = tokenize_console(command);
+ string s = strtolower(argv(0));
+ // Return value should be true if CSQC handled the command, otherwise return false to have the engine handle it.
+ return ConsoleCommand_macro_normal(s, argc)
+ || ConsoleCommand_macro_movement(s, argc)
+ ;
+}
--- /dev/null
+#pragma once
+
+void Cmd_Scoreboard_SetFields(int);
+void Cmd_Scoreboard_Help();
+void ConsoleCommand_macro_init();
+
+// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
+void LocalCommand_macro_write_aliases(int fh);
+
+REGISTRY(CLIENT_COMMANDS, BITS(7))
+REGISTER_REGISTRY(CLIENT_COMMANDS)
+REGISTRY_SORT(CLIENT_COMMANDS)
+
+REGISTRY_DEFINE_GET(CLIENT_COMMANDS, NULL)
+
+#define CLIENT_COMMAND(id, description) \
+ CLASS(clientcommand_##id, Command) \
+ ATTRIB(clientcommand_##id, m_name, string, #id); \
+ ATTRIB(clientcommand_##id, m_description, string, description); \
+ ENDCLASS(clientcommand_##id) \
+ REGISTER(CLIENT_COMMANDS, CMD_CL, id, m_id, NEW(clientcommand_##id)); \
+ METHOD(clientcommand_##id, m_invokecmd, void(clientcommand_##id this, int request, entity caller, int arguments, string command))
+
+STATIC_INIT(CLIENT_COMMANDS_aliases) {
+ FOREACH(CLIENT_COMMANDS, true, localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, "qc_cmd_cl")));
+}
+++ /dev/null
-// generated file; do not modify
-#ifdef CSQC
- #include <client/commands/cl_cmd.qc>
-#endif
+++ /dev/null
-// generated file; do not modify
-#ifdef CSQC
- #include <client/commands/cl_cmd.qh>
-#endif
+++ /dev/null
-#include "cl_cmd.qh"
-// ==============================================
-// CSQC client commands code, written by Samual
-// Last updated: December 28th, 2011
-// ==============================================
-
-#include <common/command/_mod.qh>
-#include "cl_cmd.qh"
-
-#include "../autocvars.qh"
-#include "../defs.qh"
-#include <client/hud/_mod.qh>
-#include <client/hud/panel/quickmenu.qh>
-#include <client/hud/panel/radar.qh>
-#include "../main.qh"
-#include "../mapvoting.qh"
-#include "../miscfunctions.qh"
-
-#include <client/mutators/_mod.qh>
-
-#include <common/minigames/cl_minigames_hud.qh>
-
-#include <common/mapinfo.qh>
-
-void DrawDebugModel(entity this)
-{
- if (time - floor(time) > 0.5)
- {
- PolyDrawModel(this);
- this.drawmask = 0;
- }
- else
- {
- this.renderflags = 0;
- this.drawmask = MASK_NORMAL;
- }
-}
-
-
-// =======================
-// Command Sub-Functions
-// =======================
-
-void LocalCommand_blurtest(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.
-
- #ifdef BLURTEST
- switch (request)
- {
- case CMD_REQUEST_COMMAND:
- {
- blurtest_time0 = time;
- blurtest_time1 = time + stof(argv(1));
- blurtest_radius = stof(argv(2));
- blurtest_power = stof(argv(3));
- LOG_INFO("Enabled blurtest");
- return;
- }
-
- default:
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd blurtest");
- LOG_HELP(" No arguments required.");
- return;
- }
- }
- #else
- if (request)
- {
- LOG_INFO("Blurtest is not enabled on this client.");
- return;
- }
- #endif
-}
-
-void LocalCommand_boxparticles(int request, int argc)
-{
- TC(int, request); TC(int, argc);
- switch (request)
- {
- case CMD_REQUEST_COMMAND:
- {
- if (argc == 9)
- {
- int effect = _particleeffectnum(argv(1));
- if (effect >= 0)
- {
- int index = stoi(argv(2));
- entity own;
- if (index <= 0)
- own = entitybyindex(-index);
- else
- own = findfloat(NULL, entnum, index);
- vector org_from = stov(argv(3));
- vector org_to = stov(argv(4));
- vector dir_from = stov(argv(5));
- vector dir_to = stov(argv(6));
- int countmultiplier = stoi(argv(7));
- int flags = stoi(argv(8));
- boxparticles(effect, own, org_from, org_to, dir_from, dir_to, countmultiplier, flags);
- return;
- }
- }
- }
-
- default:
- LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP(
- "Usage:^3 cl_cmd boxparticles effectname own org_from org_to, dir_from, dir_to, countmultiplier, flags\n"
- " 'effectname' is the name of a particle effect in effectinfo.txt\n"
- " 'own' is the entity number of the owner (negative for csqc ent, positive for svqc ent)\n"
- " 'org_from' is the starting origin of the box\n"
- " 'org_to' is the ending origin of the box\n"
- " 'dir_from' is the minimum velocity\n"
- " 'dir_to' is the maximum velocity\n"
- " 'countmultiplier' defines a multiplier for the particle count (affects count only, not countabsolute or trailspacing)\n"
- " 'flags' can contain:\n"
- " 1 to respect globals particles_alphamin, particles_alphamax (set right before via prvm_globalset client)\n"
- " 2 to respect globals particles_colormin, particles_colormax (set right before via prvm_globalset client)\n"
- " 4 to respect globals particles_fade (set right before via prvm_globalset client)\n"
- " 128 to draw a trail, not a box"
- );
- return;
- }
- }
-}
-
-void LocalCommand_create_scrshot_ent(int request)
-{
- TC(int, request);
- switch (request)
- {
- case CMD_REQUEST_COMMAND:
- {
- string path = ((argv(1) == "") ? "" : strcat(argv(1), "/"));
- string filename = strcat(path, MapInfo_Map_bspname, "_scrshot_ent.txt");
- int fh = fopen(filename, FILE_APPEND);
-
- if (fh >= 0)
- {
- fputs(fh, "{\n");
- fputs(fh, strcat("\"classname\" \"info_autoscreenshot\"\n"));
- fputs(fh, strcat("\"origin\" \"", strcat(ftos(view_origin.x), " ", ftos(view_origin.y), " ", ftos(view_origin.z)), "\"\n"));
- fputs(fh, strcat("\"angles\" \"", strcat(ftos(view_angles.x), " ", ftos(view_angles.y), " ", ftos(view_angles.z)), "\"\n"));
- fputs(fh, "}\n");
-
- LOG_INFO("Completed screenshot entity dump in ^2data/data/", path, MapInfo_Map_bspname, "_scrshot_ent.txt^7.");
-
- fclose(fh);
- }
- else
- {
- LOG_INFO("^1Error: ^7Could not dump to file!");
- }
- return;
- }
-
- default:
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd create_scrshot_ent [path]");
- LOG_HELP(" Where 'path' can be the subdirectory of data/data in which the file is saved.");
- return;
- }
- }
-}
-
-void LocalCommand_debugmodel(int request, int argc)
-{
- TC(int, request); TC(int, argc);
- switch (request)
- {
- case CMD_REQUEST_COMMAND:
- {
- string modelname = argv(1);
-
- entity debugmodel_entity = new(debugmodel);
- precache_model(modelname);
- _setmodel(debugmodel_entity, modelname);
- setorigin(debugmodel_entity, view_origin);
- debugmodel_entity.angles = view_angles;
- debugmodel_entity.draw = DrawDebugModel;
- IL_PUSH(g_drawables, debugmodel_entity);
-
- return;
- }
-
- default:
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd debugmodel model");
- LOG_HELP(" Where 'model' is a string of the model name to use for the debug model.");
- return;
- }
- }
-}
-
-void LocalCommand_handlevote(int request, int argc)
-{
- TC(int, request); TC(int, argc);
- switch (request)
- {
- case CMD_REQUEST_COMMAND:
- {
- int vote_selection;
- string vote_string;
-
- if (InterpretBoolean(argv(1)))
- {
- vote_selection = 2;
- vote_string = "yes";
- }
- else
- {
- vote_selection = 1;
- vote_string = "no";
- }
-
- if (vote_selection)
- {
- if (uid2name_dialog) // handled by "uid2name" option
- {
- vote_active = 0;
- vote_prev = 0;
- vote_change = -9999;
- localcmd(strcat("setreport cl_allow_uid2name ", ftos(vote_selection - 1), "\n"));
- uid2name_dialog = 0;
- }
- else { localcmd(strcat("cmd vote ", vote_string, "\n")); }
-
- return;
- }
- }
-
- default:
- LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd handlevote vote");
- LOG_HELP(" Where 'vote' is the selection for either the current poll or uid2name.");
- return;
- }
- }
-}
-
-void LocalCommand_hud(int request, int argc)
-{
- TC(int, request); TC(int, argc);
- switch (request)
- {
- case CMD_REQUEST_COMMAND:
- {
- if(MUTATOR_CALLHOOK(HUD_Command, argc))
- return;
-
- switch (argv(1))
- {
- case "configure":
- {
- cvar_set("_hud_configure", ftos(!autocvar__hud_configure));
- return;
- }
-
- case "quickmenu":
- {
- if (argv(2) == "help")
- {
- LOG_HELP(" quickmenu [[default | file | \"\"] submenu file]");
- LOG_HELP("Called without options (or with \"\") loads either the default quickmenu or a quickmenu file if hud_panel_quickmenu_file is set to a valid filename.");
- LOG_HELP("A submenu name can be given to open the quickmenu directly in a submenu; it requires to specify 'default', 'file' or '\"\"' option.");
- LOG_HELP("A file name can also be given to open a different quickmenu");
- return;
- }
- string file = ((argv(4) == "") ? autocvar_hud_panel_quickmenu_file : argv(4));
- if (QuickMenu_IsOpened())
- QuickMenu_Close();
- else
- QuickMenu_Open(argv(2), argv(3), file); // mode, submenu
- return;
- }
-
- case "save":
- {
- if (argv(2))
- {
- HUD_Panel_ExportCfg(argv(2));
- return;
- }
- else
- {
- break; // go to usage, we're missing the paramater needed here.
- }
- }
-
- case "scoreboard_columns_set":
- {
- Cmd_Scoreboard_SetFields(argc);
- return;
- }
-
- case "scoreboard_columns_help":
- {
- Cmd_Scoreboard_Help();
- return;
- }
-
- case "radar":
- {
- if (argv(2))
- HUD_Radar_Show_Maximized(InterpretBoolean(argv(2)), 0);
- else
- HUD_Radar_Show_Maximized(!hud_panel_radar_maximized, 0);
- return;
- }
-
- case "clickradar":
- {
- if(!isdemo())
- HUD_Radar_Show_Maximized(!hud_panel_radar_mouse, 1);
- return;
- }
- }
- }
-
- default:
- LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd hud action [configname | radartoggle | layout]");
- LOG_HELP(" Where 'action' is the command to complete,");
- LOG_HELP(" 'configname' is the name to save to for \"save\" action,");
- LOG_HELP(" 'radartoggle' is to control hud_panel_radar_maximized for \"radar\" action,");
- LOG_HELP(" and 'layout' is how to organize the scoreboard columns for the set action.");
- LOG_HELP(" Full list of commands here: \"configure, quickmenu, minigame, save, scoreboard_columns_help, scoreboard_columns_set, radar.\"");
- return;
- }
- }
-}
-
-void LocalCommand_localprint(int request, int argc)
-{
- TC(int, request); TC(int, argc);
- switch (request)
- {
- case CMD_REQUEST_COMMAND:
- {
- if (argv(1))
- {
- centerprint_AddStandard(argv(1));
- return;
- }
- }
-
- default:
- LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd localprint \"message\"");
- LOG_HELP(" 'message' is the centerprint message to send to yourself.");
- return;
- }
- }
-}
-
-void LocalCommand_mv_download(int request, int argc)
-{
- TC(int, request); TC(int, argc);
- switch (request)
- {
- case CMD_REQUEST_COMMAND:
- {
- if (argv(1))
- {
- Cmd_MapVote_MapDownload(argc);
- return;
- }
- }
-
- default:
- LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd mv_download mapid");
- LOG_HELP(" Where 'mapid' is the id number of the map to request an image of on the map vote selection menu.");
- return;
- }
- }
-}
-
-void LocalCommand_sendcvar(int request, int argc)
-{
- TC(int, request); TC(int, argc);
- switch (request)
- {
- case CMD_REQUEST_COMMAND:
- {
- if (argv(1))
- {
- // W_FixWeaponOrder will trash argv, so save what we need.
- string thiscvar = string_null; strcpy(thiscvar, argv(1));
- string s = cvar_string(thiscvar);
-
- if (thiscvar == "cl_weaponpriority")
- s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 1);
- else if (substring(thiscvar, 0, 17) == "cl_weaponpriority" && strlen(thiscvar) == 18)
- s = W_FixWeaponOrder(W_NumberWeaponOrder(s), 0);
-
- localcmd("cmd sentcvar ", thiscvar, " \"", s, "\"\n");
- strfree(thiscvar);
- return;
- }
- }
-
- default:
- LOG_INFOF("Incorrect parameters for ^2%s^7", argv(0));
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd sendcvar <cvar>");
- LOG_HELP(" Where 'cvar' is the cvar to send to the server.");
- return;
- }
- }
-}
-
-/* use this when creating a new command, making sure to place it in alphabetical order... also,
-** ADD ALL NEW COMMANDS TO commands.cfg WITH PROPER ALIASES IN THE SAME FASHION!
-void LocalCommand_(int request)
-{
- switch(request)
- {
- case CMD_REQUEST_COMMAND:
- {
-
- return;
- }
-
- default:
- case CMD_REQUEST_USAGE:
- {
- LOG_HELP("Usage:^3 cl_cmd ");
- LOG_HELP(" No arguments required.");
- return;
- }
- }
-}
-*/
-
-
-// ==================================
-// Macro system for client commands
-// ==================================
-
-// Normally do not hard code aliases for these, instead create them in commands.cfg... also: keep in alphabetical order, please ;)
-CLIENT_COMMAND(blurtest, "Feature for testing blur postprocessing") { LocalCommand_blurtest(request); }
-CLIENT_COMMAND(boxparticles, "Spawn particles manually") { LocalCommand_boxparticles(request, arguments); }
-CLIENT_COMMAND(create_scrshot_ent, "Create an entity at this location for automatic screenshots") { LocalCommand_create_scrshot_ent(request); }
-CLIENT_COMMAND(debugmodel, "Spawn a debug model manually") { LocalCommand_debugmodel(request, arguments); }
-CLIENT_COMMAND(handlevote, "System to handle selecting a vote or option") { LocalCommand_handlevote(request, arguments); }
-CLIENT_COMMAND(hud, "Commands regarding/controlling the HUD system") { LocalCommand_hud(request, arguments); }
-CLIENT_COMMAND(localprint, "Create your own centerprint sent to yourself") { LocalCommand_localprint(request, arguments); }
-CLIENT_COMMAND(mv_download, "Retrieve mapshot picture from the server") { LocalCommand_mv_download(request, arguments); }
-CLIENT_COMMAND(sendcvar, "Send a cvar to the server (like cl_weaponpriority)") { LocalCommand_sendcvar(request, arguments); }
-
-void LocalCommand_macro_help()
-{
- FOREACH(CLIENT_COMMANDS, true, LOG_HELPF(" ^2%s^7: %s", it.m_name, it.m_description));
-}
-
-bool LocalCommand_macro_command(int argc, string command)
-{
- string c = strtolower(argv(0));
- FOREACH(CLIENT_COMMANDS, it.m_name == c, {
- it.m_invokecmd(it, CMD_REQUEST_COMMAND, NULL, argc, command);
- return true;
- });
- return false;
-}
-
-bool LocalCommand_macro_usage(int argc)
-{
- string c = strtolower(argv(1));
- FOREACH(CLIENT_COMMANDS, it.m_name == c, {
- it.m_invokecmd(it, CMD_REQUEST_USAGE, NULL, argc, "");
- return true;
- });
- return false;
-}
-
-void LocalCommand_macro_write_aliases(int fh)
-{
- FOREACH(CLIENT_COMMANDS, true, CMD_Write_Alias("qc_cmd_cl", it.m_name, it.m_description));
-}
-
-
-// =========================================
-// Main Function Called By Engine (cl_cmd)
-// =========================================
-// If this function exists, client code handles gamecommand instead of the engine code.
-
-void GameCommand(string command)
-{
- int argc = tokenize_console(command);
-
- // Guide for working with argc arguments by example:
- // argc: 1 - 2 - 3 - 4
- // argv: 0 - 1 - 2 - 3
- // cmd vote - master - login - password
- string s = strtolower(argv(0));
- if (s == "help")
- {
- if (argc == 1)
- {
- LOG_HELP("Client console commands:");
- LocalCommand_macro_help();
-
- LOG_HELP("\nGeneric commands shared by all programs:");
- GenericCommand_macro_help();
-
- LOG_HELP("\nUsage:^3 cl_cmd COMMAND...^7, where possible commands are listed above.");
- LOG_HELP("For help about a specific command, type cl_cmd help COMMAND");
-
- return;
- }
- else if (GenericCommand_macro_usage(argc)) // Instead of trying to call a command, we're going to see detailed information about it
- {
- return;
- }
- else if (LocalCommand_macro_usage(argc)) // now try for normal commands too
- {
- return;
- }
- }
- // continue as usual and scan for normal commands
- if (GenericCommand(command) // handled by common/command/generic.qc
- || LocalCommand_macro_command(argc, command) // handled by one of the above LocalCommand_* functions
- || MUTATOR_CALLHOOK(CSQC_ConsoleCommand, s, argc, command) // handled by a mutator
- ) return;
-
- // nothing above caught the command, must be invalid
- LOG_INFO(((command != "") ? strcat("Unknown client command \"", command, "\"") : "No command provided"), ". For a list of supported commands, try cl_cmd help.");
-}
-
-
-// ===================================
-// Macro system for console commands
-// ===================================
-
-// These functions are here specifically to add special + - commands to the game, and are not really normal commands.
-// Please add client commands to the function above this, as this is only for special reasons.
-// NOTE: showaccuracy is kept as legacy command
-#define CONSOLE_COMMANDS_NORMAL() \
- CONSOLE_COMMAND("+showscores", { scoreboard_showscores = true; }) \
- CONSOLE_COMMAND("-showscores", { scoreboard_showscores = false; }) \
- CONSOLE_COMMAND("+showaccuracy", { }) \
- CONSOLE_COMMAND("-showaccuracy", { }) \
- /* nothing */
-
-#define CONSOLE_COMMANDS_MOVEMENT() \
- CONSOLE_COMMAND("+forward", { ++camera_direction.x; }) \
- CONSOLE_COMMAND("-forward", { --camera_direction.x; }) \
- CONSOLE_COMMAND("+back", { --camera_direction.x; }) \
- CONSOLE_COMMAND("-back", { ++camera_direction.x; }) \
- CONSOLE_COMMAND("+moveup", { ++camera_direction.z; }) \
- CONSOLE_COMMAND("-moveup", { --camera_direction.z; }) \
- CONSOLE_COMMAND("+movedown", { --camera_direction.z; }) \
- CONSOLE_COMMAND("-movedown", { ++camera_direction.z; }) \
- CONSOLE_COMMAND("+moveright", { --camera_direction.y; }) \
- CONSOLE_COMMAND("-moveright", { ++camera_direction.y; }) \
- CONSOLE_COMMAND("+moveleft", { ++camera_direction.y; }) \
- CONSOLE_COMMAND("-moveleft", { --camera_direction.y; }) \
- CONSOLE_COMMAND("+roll_right", { ++camera_roll; }) \
- CONSOLE_COMMAND("-roll_right", { --camera_roll; }) \
- CONSOLE_COMMAND("+roll_left", { --camera_roll; }) \
- CONSOLE_COMMAND("-roll_left", { ++camera_roll; }) \
- /* nothing */
-
-void ConsoleCommand_macro_init()
-{
- // first init normal commands
- #define CONSOLE_COMMAND(name, execution) \
- { registercommand(name); }
-
- CONSOLE_COMMANDS_NORMAL();
- #undef CONSOLE_COMMAND
-
- // then init movement commands
- #ifndef CAMERATEST
- if (isdemo())
- {
- #endif
- #define CONSOLE_COMMAND(name, execution) \
- registercommand(name);
-
- CONSOLE_COMMANDS_MOVEMENT();
- #undef CONSOLE_COMMAND
- #ifndef CAMERATEST
-}
- #endif
-}
-
-bool ConsoleCommand_macro_normal(string s, int argc)
-{
- #define CONSOLE_COMMAND(name, execution) \
- { if (name == s) { { execution } return true; } }
-
- CONSOLE_COMMANDS_NORMAL();
- #undef CONSOLE_COMMAND
-
- return false;
-}
-
-bool ConsoleCommand_macro_movement(string s, int argc)
-{
- if (camera_active)
- {
- #define CONSOLE_COMMAND(name, execution) \
- { if (name == s) { { execution } return true; } }
-
- CONSOLE_COMMANDS_MOVEMENT();
- #undef CONSOLE_COMMAND
- }
-
- return false;
-}
-
-
-// ======================================================
-// Main Function Called By Engine (registered commands)
-// ======================================================
-// Used to parse commands in the console that have been registered with the "registercommand" function
-
-bool CSQC_ConsoleCommand(string command)
-{
- int argc = tokenize_console(command);
- string s = strtolower(argv(0));
- // Return value should be true if CSQC handled the command, otherwise return false to have the engine handle it.
- return ConsoleCommand_macro_normal(s, argc)
- || ConsoleCommand_macro_movement(s, argc)
- ;
-}
+++ /dev/null
-#pragma once
-
-void Cmd_Scoreboard_SetFields(int);
-void Cmd_Scoreboard_Help();
-void ConsoleCommand_macro_init();
-
-// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
-void LocalCommand_macro_write_aliases(int fh);
-
-REGISTRY(CLIENT_COMMANDS, BITS(7))
-REGISTER_REGISTRY(CLIENT_COMMANDS)
-REGISTRY_SORT(CLIENT_COMMANDS)
-
-REGISTRY_DEFINE_GET(CLIENT_COMMANDS, NULL)
-
-#define CLIENT_COMMAND(id, description) \
- CLASS(clientcommand_##id, Command) \
- ATTRIB(clientcommand_##id, m_name, string, #id); \
- ATTRIB(clientcommand_##id, m_description, string, description); \
- ENDCLASS(clientcommand_##id) \
- REGISTER(CLIENT_COMMANDS, CMD_CL, id, m_id, NEW(clientcommand_##id)); \
- METHOD(clientcommand_##id, m_invokecmd, void(clientcommand_##id this, int request, entity caller, int arguments, string command))
-
-STATIC_INIT(CLIENT_COMMANDS_aliases) {
- FOREACH(CLIENT_COMMANDS, true, localcmd(sprintf("alias %1$s \"%2$s %1$s ${* ?}\"\n", it.m_name, "qc_cmd_cl")));
-}
#include "csqcmodel_hooks.qh"
#include "autocvars.qh"
+#include "main.qh"
#include "miscfunctions.qh"
#include <client/mutators/_mod.qh>
+#include <client/main.qh>
#include "player_skeleton.qh"
#include "weapons/projectile.qh"
#include <common/animdecide.qh>
#include <common/ent_cs.qh>
+#include <common/gamemodes/_mod.qh>
+#include <common/mapinfo.qh>
#include <common/physics/movetypes/movetypes.qh>
+#include <common/physics/player.qh>
#include <common/viewloc.qh>
#include <common/effects/all.qh>
#include <common/effects/all.inc>
if(autocvar_cl_forcemyplayercolors)
forcecolor_friend = 1024 + autocvar_cl_forcemyplayercolors;
- if(autocvar_cl_forceplayercolors == 2 && team_count == 2)
+ if((autocvar_cl_forceplayercolors == 2 && team_count == 2)
+ || (autocvar_cl_forceplayercolors == 3 && IS_GAMETYPE(DUEL)))
forcecolor_enemy = 1024 + autocvar__cl_color;
if(forcecolor_enemy && !forcecolor_friend)
if(eff & EF_FULLBRIGHT)
this.renderflags |= RF_FULLBRIGHT;
if(eff & EF_FLAME)
- pointparticles(EFFECT_EF_FLAME, this.origin, '0 0 0', bound(0, frametime, 0.1));
+ {
+ boxparticles(particleeffectnum(EFFECT_EF_FLAME), this, this.absmin, this.absmax, this.velocity, this.velocity, bound(0, frametime, 0.1), 0);
+ //pointparticles(EFFECT_EF_FLAME, this.origin, '0 0 0', bound(0, frametime, 0.1));
+ }
if(eff & EF_STARDUST)
- pointparticles(EFFECT_EF_STARDUST, this.origin, '0 0 0', bound(0, frametime, 0.1));
+ {
+ boxparticles(particleeffectnum(EFFECT_EF_STARDUST), this, this.absmin, this.absmax, this.velocity, this.velocity, bound(0, frametime, 0.1), 0);
+ //pointparticles(EFFECT_EF_STARDUST, this.origin, '0 0 0', bound(0, frametime, 0.1));
+ }
if(eff & EF_NOSHADOW)
this.renderflags |= RF_NOSHADOW;
if(eff & EF_NODEPTHTEST)
.int csqcmodel_modelflags;
.int csqcmodel_traileffect;
+.bool csqcmodel_isdead; // used by shownames and miscfunctions (entcs_IsDead) to know when a player is dead
+
.int isplayermodel;
void CSQCModel_Effects_Apply(entity this);
+++ /dev/null
-#pragma once
-
-// Additional OPTIONAL Fields and Globals
-//float intermission;
-float scoreboard_showscores;
-.string message;
-.float renderflags;
-// float coop;
-// float deathmatch;
-
-float dmg_take;
-// float dmg_save;
-// vector dmg_origin;
-
-// Darkplaces Render Modifications
-#if 0
-.float alpha;
-.vector colormod;
-.float scale;
-#endif
-
-// Basic variables
-.int enttype; // entity type sent from server
-.int sv_entnum; // entity number sent from server
-.int team;
-.int team_size;
-
-float vid_conheight;
-int binddb;
-
-// QUALIFYING
-float race_checkpoint;
-float race_time;
-float race_laptime;
-float race_checkpointtime;
-float race_previousbesttime;
-float race_mypreviousbesttime;
-string race_previousbestname;
-float race_nextcheckpoint;
-float race_nextbesttime;
-float race_mybesttime;
-string race_nextbestname;
-float race_penaltyaccumulator; // qualifying: total penalty time in tenths
-float race_penaltyeventtime; // time when the player got the penalty
-float race_penaltytime; // duration of penalty time, in tenths
-string race_penaltyreason; // reason for penalty
-float race_server_record; // server record
-float race_speedaward;
-string race_speedaward_holder;
-string race_speedaward_unit;
-float race_speedaward_alltimebest;
-string race_speedaward_alltimebest_holder;
-string race_speedaward_alltimebest_unit;
-
-// RACE
-float race_mycheckpoint;
-float race_mycheckpointtime;
-float race_mycheckpointdelta;
-float race_mycheckpointlapsdelta;
-string race_mycheckpointenemy;
-float race_othercheckpoint;
-float race_othercheckpointtime;
-float race_othercheckpointdelta;
-float race_othercheckpointlapsdelta;
-string race_othercheckpointenemy;
-float scoreboard_showscores_force;
-float race_status;
-string race_status_name;
-float race_myrank;
-
-// Nexball
-float nb_pb_period;
-
-// Spectating
-// -1 - observing
-// 0 - playing
-// >0 - id of spectated player
-float spectatee_status;
-float spectatee_status_changed_time;
-
-// short mapname
-string shortmapname;
-
-// database for misc stuff
-int tempdb;
-int ClientProgsDB;
-vector hook_shotorigin[4];
-vector lightning_shotorigin[4];
-
-
-#ifdef BLURTEST
-float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power;
-#endif
-
-float serverprevtime, serverdeltatime;
-
-float ticrate;
-
-.float damageforcescale;
-const float MIN_DAMAGEEXTRARADIUS = 2;
-const float MAX_DAMAGEEXTRARADIUS = 16;
-.float damageextraradius;
-.void(entity this, float thisdmg, int hittype, vector org, vector thisforce) event_damage;
-
-// weapons
-.bool silent;
-
-int w_deathtype;
-float w_issilent, w_random;
-vector w_org, w_backoff;
-
-float autoswitch;
-bool cvar_cl_allow_uid2name;
-bool cvar_cl_allow_uidranking;
-float cvar_cl_autoscreenshot;
-float cvar_cl_autotaunt;
-float cvar_cl_clippedspectating;
-int cvar_cl_gunalign;
-float cvar_cl_handicap;
-float cvar_cl_jetpack_jump;
-float cvar_cl_movement_track_canjump;
-float cvar_cl_noantilag;
-string cvar_cl_physics;
-float cvar_cl_voice_directional;
-float cvar_cl_voice_directional_taunt_attenuation;
-float cvar_cl_weaponimpulsemode;
-string cvar_g_xonoticversion;
-float cvar_cl_cts_noautoswitch;
-bool cvar_cl_weapon_switch_reload;
-bool cvar_cl_weapon_switch_fallback_to_impulse;
-
-REPLICATE(autoswitch, bool, "cl_autoswitch");
-REPLICATE(cvar_cl_allow_uid2name, bool, "cl_allow_uid2name");
-REPLICATE(cvar_cl_allow_uidranking, bool, "cl_allow_uidranking");
-REPLICATE(cvar_cl_autoscreenshot, int, "cl_autoscreenshot");
-REPLICATE(cvar_cl_autotaunt, float, "cl_autotaunt");
-REPLICATE(cvar_cl_clippedspectating, bool, "cl_clippedspectating");
-REPLICATE(cvar_cl_gunalign, int, "cl_gunalign");
-REPLICATE(cvar_cl_handicap, float, "cl_handicap");
-REPLICATE(cvar_cl_jetpack_jump, bool, "cl_jetpack_jump");
-REPLICATE(cvar_cl_movement_track_canjump, bool, "cl_movement_track_canjump");
-REPLICATE(cvar_cl_noantilag, bool, "cl_noantilag");
-REPLICATE(cvar_cl_physics, string, "cl_physics");
-REPLICATE(cvar_cl_voice_directional, int, "cl_voice_directional");
-REPLICATE(cvar_cl_voice_directional_taunt_attenuation, float, "cl_voice_directional_taunt_attenuation");
-REPLICATE(cvar_cl_weaponimpulsemode, int, "cl_weaponimpulsemode");
-REPLICATE(cvar_g_xonoticversion, string, "g_xonoticversion");
-REPLICATE(cvar_cl_cts_noautoswitch, bool, "cl_cts_noautoswitch");
-REPLICATE(cvar_cl_weapon_switch_reload, bool, "cl_weapon_switch_reload");
-REPLICATE(cvar_cl_weapon_switch_fallback_to_impulse, bool, "cl_weapon_switch_fallback_to_impulse");
-/*
-// cvar cl_newusekeysupported doesn't exist
-float cvar_cl_newusekeysupported;
-REPLICATE(cvar_cl_newusekeysupported, bool, "cl_newusekeysupported");
-*/
-string cvar_cl_allow_uidtracking;
-REPLICATE(cvar_cl_allow_uidtracking, string, "cl_allow_uidtracking");
-
-string cvar_cl_weaponpriority;
-REPLICATE(cvar_cl_weaponpriority, string, "cl_weaponpriority");
-
-string cvar_cl_weaponpriorities[10];
-REPLICATE(cvar_cl_weaponpriorities[0], string, "cl_weaponpriority0");
-REPLICATE(cvar_cl_weaponpriorities[1], string, "cl_weaponpriority1");
-REPLICATE(cvar_cl_weaponpriorities[2], string, "cl_weaponpriority2");
-REPLICATE(cvar_cl_weaponpriorities[3], string, "cl_weaponpriority3");
-REPLICATE(cvar_cl_weaponpriorities[4], string, "cl_weaponpriority4");
-REPLICATE(cvar_cl_weaponpriorities[5], string, "cl_weaponpriority5");
-REPLICATE(cvar_cl_weaponpriorities[6], string, "cl_weaponpriority6");
-REPLICATE(cvar_cl_weaponpriorities[7], string, "cl_weaponpriority7");
-REPLICATE(cvar_cl_weaponpriorities[8], string, "cl_weaponpriority8");
-REPLICATE(cvar_cl_weaponpriorities[9], string, "cl_weaponpriority9");
-
-float bgmtime;
-
-float vortex_charge_movingavg;
-
-int serverflags;
-
-float uid2name_dialog;
-
-float intermission_time;
-
-.bool csqcmodel_isdead; // used by shownames and miscfunctions (entcs_IsDead) to know when a player is dead
-
-#define player_currententnum (spectatee_status > 0 ? spectatee_status : player_localnum + 1)
#pragma once
+float vortex_charge_movingavg; // WEAPONTODO
+
vector crosshair_getcolor(entity this, float health_stat);
void TrueAim_Init();
void HUD_Crosshair(entity this);
#include "hud.qh"
-#include <client/defs.qh>
+#include <client/items/items.qh>
#include <client/miscfunctions.qh>
#include <client/view.qh>
#include "panel/scoreboard.qh"
#include "../mapvoting.qh"
#include "../teamradar.qh"
#include <common/minigames/cl_minigames.qh>
-#include <common/t_items.qh>
#include <common/deathtypes/all.qh>
#include <common/ent_cs.qh>
#include <common/items/_mod.qh>
#include "hud.qh"
#include "panel/scoreboard.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
#include <client/miscfunctions.qh>
#include <client/view.qh>
#include "ammo.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
+#include <client/items/items.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
#include <client/view.qh>
-#include <common/t_items.qh>
#include <common/wepent.qh>
#include <common/mutators/mutator/nades/nades.qh>
#include "scoreboard.qh"
#include <common/notifications/all.qh>
-#include <client/defs.qh>
#include <client/miscfunctions.qh>
// CenterPrint (#16)
#include "chat.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
#include <client/miscfunctions.qh>
// Chat (#12)
#include "healtharmor.qh"
-#include <client/defs.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
#include <common/deathtypes/all.qh>
#include "infomessages.qh"
#include <client/autocvars.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
#include <common/ent_cs.qh>
#include "physics.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
#include <client/miscfunctions.qh>
#include <client/main.qh>
#include <lib/csqcmodel/cl_player.qh>
#include "powerups.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
#include <common/items/_mod.qh>
+#include <common/util.qh>
// Powerups (#2)
#include "pressedkeys.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
// Pressed keys (#11)
#include "quickmenu.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
#include <common/ent_cs.qh>
#include <common/minigames/cl_minigames.qh>
#include "racetimer.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
// Race timer (#8)
#pragma once
#include "../panel.qh"
+
+// QUALIFYING
+float race_checkpoint;
+float race_time;
+float race_laptime;
+float race_checkpointtime;
+float race_previousbesttime;
+float race_mypreviousbesttime;
+string race_previousbestname;
+float race_nextcheckpoint;
+float race_nextbesttime;
+float race_mybesttime;
+string race_nextbestname;
+float race_penaltyaccumulator; // qualifying: total penalty time in tenths
+float race_penaltyeventtime; // time when the player got the penalty
+float race_penaltytime; // duration of penalty time, in tenths
+string race_penaltyreason; // reason for penalty
+float race_server_record; // server record
+float race_speedaward;
+string race_speedaward_holder;
+string race_speedaward_unit;
+float race_speedaward_alltimebest;
+string race_speedaward_alltimebest_holder;
+string race_speedaward_alltimebest_unit;
+
+// RACE
+float race_mycheckpoint;
+float race_mycheckpointtime;
+float race_mycheckpointdelta;
+float race_mycheckpointlapsdelta;
+string race_mycheckpointenemy;
+float race_othercheckpoint;
+float race_othercheckpointtime;
+float race_othercheckpointdelta;
+float race_othercheckpointlapsdelta;
+string race_othercheckpointenemy;
+float scoreboard_showscores_force;
+float race_status;
+string race_status_name;
+float race_myrank;
#include "radar.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
#include <common/ent_cs.qh>
#include <client/mapvoting.qh>
#include "score.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
#include "scoreboard.qh"
#include <common/ent_cs.qh>
#include "scoreboard.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
#include <client/main.qh>
#include <client/miscfunctions.qh>
+#include <client/hud/panel/racetimer.qh>
#include "quickmenu.qh"
#include <common/ent_cs.qh>
#include <common/constants.qh>
#pragma once
#include "../panel.qh"
+bool scoreboard_showscores;
+
bool scoreboard_active;
float scoreboard_fade_alpha;
float scoreboard_acc_fade_alpha;
#include "timer.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
#include <client/miscfunctions.qh>
+#include <client/view.qh>
// Timer (#5)
#include "vote.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
// Vote (#9)
#pragma once
#include "../panel.qh"
+
+float uid2name_dialog;
#include "weapons.qh"
#include <client/autocvars.qh>
-#include <client/defs.qh>
+#include <client/main.qh>
#include <client/miscfunctions.qh>
#include <client/view.qh>
#include <common/wepent.qh>
--- /dev/null
+// generated file; do not modify
+#include <client/items/items.qc>
--- /dev/null
+// generated file; do not modify
+#include <client/items/items.qh>
--- /dev/null
+#include "items.qh"
+
+#include <common/items/_mod.qh>
+
+#include <client/main.qh>
+#include <common/physics/movetypes/movetypes.qh>
+#include <common/weapons/_all.qh>
+#include <lib/csqcmodel/cl_model.qh>
+#include <lib/csqcmodel/common.qh>
+#include <lib/warpzone/common.qh>
+
+bool autocvar_cl_ghost_items_vehicle = true;
+.vector item_glowmod;
+.bool item_simple; // probably not really needed, but better safe than sorry
+.float alpha;
+.bool pushable;
+void Item_SetAlpha(entity this)
+{
+ bool veh_hud = (hud && autocvar_cl_ghost_items_vehicle);
+
+ if(!veh_hud && (this.ItemStatus & ITS_AVAILABLE))
+ {
+ this.alpha = 1;
+ this.colormod = '1 1 1';
+ this.glowmod = this.item_glowmod;
+ }
+ else
+ {
+ this.alpha = autocvar_cl_ghost_items;
+ this.colormod = this.glowmod = autocvar_cl_ghost_items_color;
+ }
+
+ if((!veh_hud) && (this.ItemStatus & ITS_STAYWEP))
+ {
+ this.colormod = this.glowmod = autocvar_cl_weapon_stay_color;
+ this.alpha = autocvar_cl_weapon_stay_alpha;
+ }
+
+ this.drawmask = ((this.alpha <= 0) ? 0 : MASK_NORMAL);
+}
+
+void ItemDraw(entity this)
+{
+ if(this.gravity)
+ {
+ Movetype_Physics_MatchServer(this, false);
+ if(IS_ONGROUND(this))
+ { // For some reason avelocity gets set to '0 0 0' here ...
+ this.oldorigin = this.origin;
+ this.gravity = 0;
+
+ if(autocvar_cl_animate_items)
+ { // ... so reset it if animations are requested.
+ if(this.ItemStatus & ITS_ANIMATE1)
+ this.avelocity = '0 180 0';
+
+ if(this.ItemStatus & ITS_ANIMATE2)
+ this.avelocity = '0 -90 0';
+ }
+
+ // delay is for blocking item's position for a while;
+ // it's a workaround for dropped weapons that receive the position
+ // another time right after they spawn overriding animation position
+ this.onground_time = time + 0.5;
+ }
+ }
+ else if (autocvar_cl_animate_items && !this.item_simple) // no bobbing applied to simple items, for consistency's sake (no visual difference between ammo and weapons)
+ {
+ if(this.ItemStatus & ITS_ANIMATE1)
+ {
+ this.angles += this.avelocity * frametime;
+ float fade_in = bound(0, time - this.onground_time, 1);
+ setorigin(this, this.oldorigin + fade_in * ('0 0 10' + '0 0 8' * sin((time - this.onground_time) * 2)));
+ }
+
+ if(this.ItemStatus & ITS_ANIMATE2)
+ {
+ this.angles += this.avelocity * frametime;
+ float fade_in = bound(0, time - this.onground_time, 1);
+ setorigin(this, this.oldorigin + fade_in * ('0 0 8' + '0 0 4' * sin((time - this.onground_time) * 3)));
+ }
+ }
+
+ Item_SetAlpha(this);
+}
+
+void Item_PreDraw(entity this)
+{
+ if(warpzone_warpzones_exist)
+ {
+ setpredraw(this, func_null); // no need to keep running this
+ return;
+ }
+ float alph;
+ vector org = getpropertyvec(VF_ORIGIN);
+ //if(!checkpvs(org, this)) // this makes sense as long as we don't support recursive warpzones
+ //alph = 0; // this shouldn't be needed, since items behind walls are culled anyway
+ if(this.fade_start)
+ {
+ if(vdist(org - this.origin, >, this.fade_end))
+ alph = 0; // save on some processing
+ else if(vdist(org - this.origin, <, this.fade_start))
+ alph = 1; // more processing saved
+ else
+ alph = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1);
+ }
+ else
+ alph = 1;
+ //printf("%v <-> %v\n", view_origin, this.origin + 0.5 * (this.mins + this.maxs));
+ if(!hud && (this.ItemStatus & ITS_AVAILABLE))
+ this.alpha = alph;
+ if(alph <= 0)
+ this.drawmask = 0;
+ //else
+ //this.drawmask = MASK_NORMAL; // reset by the setalpha function
+}
+
+void ItemRemove(entity this)
+{
+ strfree(this.mdl);
+}
+
+HashMap ENT_CLIENT_ITEM_simple;
+STATIC_INIT(ENT_CLIENT_ITEM_simple)
+{
+ HM_NEW(ENT_CLIENT_ITEM_simple);
+}
+SHUTDOWN(ENT_CLIENT_ITEM_simple)
+{
+ HM_DELETE(ENT_CLIENT_ITEM_simple);
+}
+
+NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
+{
+ int sf = ReadByte();
+
+ if(sf & ISF_LOCATION)
+ {
+ this.origin = ReadVector();
+ setorigin(this, this.origin);
+ this.oldorigin = this.origin;
+ }
+
+ if(sf & ISF_ANGLES)
+ {
+ this.angles = ReadAngleVector();
+ }
+
+ if(sf & ISF_SIZE)
+ {
+ setsize(this, '-16 -16 0', '16 16 48');
+ }
+
+ if(sf & ISF_STATUS) // need to read/write status first so model can handle simple, fb etc.
+ {
+ this.ItemStatus = ReadByte();
+
+ Item_SetAlpha(this);
+
+ if(this.ItemStatus & ITS_ALLOWFB)
+ this.effects |= EF_FULLBRIGHT;
+ else
+ this.effects &= ~EF_FULLBRIGHT;
+
+ if(this.ItemStatus & ITS_GLOW)
+ {
+ if(this.ItemStatus & ITS_AVAILABLE)
+ this.effects |= (EF_ADDITIVE | EF_FULLBRIGHT);
+ else
+ this.effects &= ~(EF_ADDITIVE | EF_FULLBRIGHT);
+ }
+ }
+
+ if(sf & ISF_MODEL)
+ {
+ this.drawmask = MASK_NORMAL;
+ set_movetype(this, MOVETYPE_TOSS);
+ if (isnew) IL_PUSH(g_drawables, this);
+ this.draw = ItemDraw;
+ this.solid = SOLID_TRIGGER;
+ //this.flags |= FL_ITEM;
+
+ this.fade_end = ReadShort();
+ this.fade_start = ReadShort();
+ if(!warpzone_warpzones_exist && this.fade_start && !autocvar_cl_items_nofade)
+ setpredraw(this, Item_PreDraw);
+
+ strfree(this.mdl);
+
+ string _fn = ReadString();
+ this.item_simple = false; // reset it!
+
+ if(autocvar_cl_simple_items && (this.ItemStatus & ITS_ALLOWSI))
+ {
+ string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
+ this.item_simple = true;
+
+ #define extensions(x) \
+ x(md3) \
+ x(dpm) \
+ x(iqm) \
+ x(mdl) \
+ /**/
+ #define tryext(ext) { \
+ string s = strcat(_fn2, autocvar_cl_simpleitems_postfix, "." #ext); \
+ string cached = HM_gets(ENT_CLIENT_ITEM_simple, s); \
+ if (cached == "") { \
+ HM_sets(ENT_CLIENT_ITEM_simple, s, cached = fexists(s) ? "1" : "0"); \
+ } \
+ if (cached != "0") { \
+ strcpy(this.mdl, s); \
+ break; \
+ } \
+ }
+ do {
+ extensions(tryext);
+ this.item_simple = false;
+ LOG_TRACEF("Simple item requested for %s but no model exists for it", _fn);
+ } while (0);
+ #undef tryext
+ #undef extensions
+ }
+
+ if(!this.item_simple)
+ strcpy(this.mdl, _fn);
+
+ if(this.mdl == "")
+ LOG_WARNF("this.mdl is unset for item %s", this.classname);
+
+ precache_model(this.mdl);
+ _setmodel(this, this.mdl);
+
+ setsize(this, '-16 -16 0', '16 16 48');
+ }
+
+ if(sf & ISF_COLORMAP)
+ {
+ this.colormap = ReadShort();
+ this.item_glowmod_x = ReadByte() / 255.0;
+ this.item_glowmod_y = ReadByte() / 255.0;
+ this.item_glowmod_z = ReadByte() / 255.0;
+ }
+
+ if(sf & ISF_DROP)
+ {
+ this.gravity = 1;
+ this.pushable = true;
+ //this.angles = '0 0 0';
+ set_movetype(this, MOVETYPE_TOSS);
+ this.velocity = ReadVector();
+ setorigin(this, this.oldorigin);
+
+ if(!this.move_time)
+ {
+ this.move_time = time;
+ this.spawntime = time;
+ }
+ else
+ this.move_time = max(this.move_time, time);
+ }
+
+ if(autocvar_cl_animate_items)
+ {
+ if(this.ItemStatus & ITS_ANIMATE1)
+ this.avelocity = '0 180 0';
+
+ if(this.ItemStatus & ITS_ANIMATE2)
+ this.avelocity = '0 -90 0';
+ }
+
+ this.entremove = ItemRemove;
+
+ return true;
+}
--- /dev/null
+#pragma once
+
+const int AMMO_COUNT = 4; // amount of ammo types to show in the ammo panel
+
+.float onground_time;
+
+bool autocvar_cl_items_nofade;
+float autocvar_cl_animate_items = 1;
+float autocvar_cl_ghost_items = 0.45;
+vector autocvar_cl_ghost_items_color = '-1 -1 -1';
+vector autocvar_cl_weapon_stay_color = '2 0.5 0.5';
+float autocvar_cl_weapon_stay_alpha = 0.75;
+float autocvar_cl_simple_items = 0;
+string autocvar_cl_simpleitems_postfix = "_simple";
+.float spawntime;
+.float gravity;
+.vector colormod;
+
+void ItemDraw(entity this);
#include "main.qh"
-#include "defs.qh"
+#include <client/items/items.qh>
#include <common/ent_cs.qh>
#include "miscfunctions.qh"
#include <common/effects/effect.qh>
#include <common/effects/all.qh>
#include <common/effects/all.inc>
#include "hud/_mod.qh"
-#include "commands/cl_cmd.qh"
+#include "command/cl_cmd.qh"
#include "mapvoting.qh"
#include <client/mutators/_mod.qh>
#include "hud/panel/centerprint.qh"
#include "hud/panel/quickmenu.qh"
#include "shownames.qh"
#include "view.qh"
-#include <common/t_items.qh>
#include "weapons/projectile.qh"
#include <common/deathtypes/all.qh>
#include <common/items/_mod.qh>
+#include <common/gamemodes/gamemode/nexball/cl_nexball.qh>
#include <common/mapinfo.qh>
#include <common/minigames/cl_minigames.qh>
#include <common/minigames/cl_minigames_hud.qh>
for(i = 0; i < MAX_SPECTATORS; ++i)
spectatorlist[i] = 0; // reset list first
- for(i = 0; i < num_spectators; ++i)
+ int limit = min(num_spectators, MAX_SPECTATORS);
+ for(i = 0; i < limit; ++i)
{
slot = ReadByte();
spectatorlist[i] = slot - 1;
}
}
+ else
+ {
+ for(int j = 0; j < MAX_SPECTATORS; ++j)
+ spectatorlist[j] = 0; // reset list if showspectators has been turned off
+ num_spectators = 0;
+ }
return = true;
float drawframetime;
vector view_origin, view_forward, view_right, view_up;
+.float renderflags; // engine field
bool button_zoom;
bool spectatorbutton_zoom;
float GetSpeedUnitFactor(int speed_unit);
string GetSpeedUnit(int speed_unit);
+
+.int enttype; // entity type sent from server
+.int sv_entnum; // entity number sent from server
+
+.int team;
+.int team_size;
+
+int binddb;
+
+// Spectating
+// -1 - observing
+// 0 - playing
+// >0 - id of spectated player
+float spectatee_status;
+float spectatee_status_changed_time;
+
+#define player_currententnum (spectatee_status > 0 ? spectatee_status : player_localnum + 1)
+
+// short mapname
+string shortmapname;
+
+// database for misc stuff
+int tempdb;
+int ClientProgsDB;
+vector hook_shotorigin[4]; // WEAPONTODO
+vector lightning_shotorigin[4]; // TODO: unused
+
+float serverprevtime, serverdeltatime;
+
+float ticrate;
+
+int serverflags;
#include "mapvoting.qh"
#include "autocvars.qh"
+#include "main.qh"
#include "miscfunctions.qh"
-#include "defs.qh"
#include "hud/_mod.qh"
#include "hud/panel/scoreboard.qh"
#include <common/mapinfo.qh>
+#include <common/util.qh>
// MapVote (#21)
#include "miscfunctions.qh"
#include "autocvars.qh"
-#include "defs.qh"
#include "hud/_mod.qh"
+#include "main.qh"
#include <common/command/_mod.qh>
#include "shownames.qh"
#include "autocvars.qh"
+#include "main.qh"
#include "miscfunctions.qh"
#include "resources.qh"
#include "hud/_mod.qh"
#include "autocvars.qh"
#include "hud/_mod.qh"
+#include <client/main.qh>
#include <common/mutators/mutator/waypoints/all.qh>
#include "miscfunctions.qh"
#include "announcer.qh"
#include "hud/_mod.qh"
+#include "main.qh"
#include "mapvoting.qh"
#include "shownames.qh"
#include "hud/panel/scoreboard.qh"
#include <lib/warpzone/client.qh>
#include <lib/warpzone/common.qh>
-#define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT)
-
float autocvar_cl_viewmodel_scale;
float autocvar_cl_viewmodel_alpha = 1;
float drawtime;
float unaccounted_damage = 0;
float zoomscript_caught;
+
+float dmg_take;
+// float dmg_save;
+// vector dmg_origin;
+
+#ifdef BLURTEST
+float blurtest_time0, blurtest_time1, blurtest_radius, blurtest_power;
+#endif
+
+float intermission_time;
#include "projectile.qh"
#include "../autocvars.qh"
-#include "../defs.qh"
#include "../main.qh"
#include <client/mutators/_mod.qh>
void loopsound(entity e, int ch, Sound samp, float vol, float attn);
void Ent_RemoveProjectile(entity this);
-
-const int FL_PROJECTILE = BIT(15);
#include "effects/all.qc"
#include "impulses/all.qc"
#include "notifications/all.qc"
-#include "t_items.qc"
#endif
#include "items/_mod.inc"
#include <common/mapinfo.qc>
#include <common/net_notice.qc>
#include <common/playerstats.qc>
+#include <common/replicate.qc>
#include <common/state.qc>
-#include <common/t_items.qc>
#include <common/util.qc>
#include <common/viewloc.qc>
#include <common/wepent.qc>
#include <common/mapinfo.qh>
#include <common/net_notice.qh>
#include <common/playerstats.qh>
+#include <common/replicate.qh>
#include <common/state.qh>
-#include <common/t_items.qh>
#include <common/util.qh>
#include <common/viewloc.qh>
#include <common/wepent.qh>
#if defined(SVQC)
#include "util.qh"
- #include "../server/defs.qh"
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
#endif
bool monsters_animoverride(entity this)
#endif
#ifdef CSQC
- #include <client/commands/cl_cmd.qh>
+ #include <client/command/cl_cmd.qh>
#endif
#ifdef SVQC
#pragma once
+const int FRAGS_PLAYER = 0;
+const int FRAGS_SPECTATOR = -666;
+const int FRAGS_PLAYER_OUT_OF_GAME = -616;
+
+///////////////////////////
+// cvar constants
+
+const int CVAR_SAVE = 1;
+const int CVAR_NOTIFY = 2;
+const int CVAR_READONLY = 4;
+
+// server flags
+const int SERVERFLAG_ALLOW_FULLBRIGHT = 1;
+const int SERVERFLAG_TEAMPLAY = 2;
+const int SERVERFLAG_PLAYERSTATS = 4;
+
+const int SPECIES_HUMAN = 0;
+const int SPECIES_ROBOT_SOLID = 1;
+const int SPECIES_ALIEN = 2;
+const int SPECIES_ANIMAL = 3;
+const int SPECIES_ROBOT_RUSTY = 4;
+const int SPECIES_ROBOT_SHINY = 5;
+const int SPECIES_RESERVED = 15;
+
+#ifdef GAMEQC
const int RANKINGS_CNT = 99;
///////////////////////////
const int KEY_ATCK = BIT(6);
const int KEY_ATCK2 = BIT(7);
-///////////////////////////
-// cvar constants
-
-const int CVAR_SAVE = 1;
-const int CVAR_NOTIFY = 2;
-const int CVAR_READONLY = 4;
-
///////////////////////////
// csqc communication stuff
// # of maps, I'll use arrays for them :P
const int MAPVOTE_COUNT = 30;
-const int SPECIES_HUMAN = 0;
-const int SPECIES_ROBOT_SOLID = 1;
-const int SPECIES_ALIEN = 2;
-const int SPECIES_ANIMAL = 3;
-const int SPECIES_ROBOT_RUSTY = 4;
-const int SPECIES_ROBOT_SHINY = 5;
-const int SPECIES_RESERVED = 15;
-
-const int FRAGS_PLAYER = 0;
-const int FRAGS_SPECTATOR = -666;
-const int FRAGS_PLAYER_OUT_OF_GAME = -616;
-
-// server flags
-const int SERVERFLAG_ALLOW_FULLBRIGHT = 1;
-const int SERVERFLAG_TEAMPLAY = 2;
-const int SERVERFLAG_PLAYERSTATS = 4;
-
// a bit more constant
const vector PL_MAX_CONST = '16 16 45';
const vector PL_MIN_CONST = '-16 -16 -24';
const int GTV_FORBIDDEN = 0; // Cannot be voted
const int GTV_AVAILABLE = 1; // Can be voted
const int GTV_CUSTOM = 2; // Custom entry
+
+// generic entity flags
+// engine flags can't be redefined as they are used by the engine (unfortunately), they are listed here for posterity
+#ifdef CSQC
+const int FL_FLY = 1; /* BIT(0) */
+const int FL_SWIM = 2; /* BIT(1) */
+const int FL_CLIENT = 8; /* BIT(2) */ // set for all client edicts
+const int FL_INWATER = 16; /* BIT(3) */ // for enter / leave water splash
+const int FL_MONSTER = 32; /* BIT(4) */
+const int FL_GODMODE = 64; /* BIT(5) */ // player cheat
+const int FL_NOTARGET = 128; /* BIT(6) */ // player cheat
+const int FL_ITEM = 256; /* BIT(7) */ // extra wide size for bonus items
+const int FL_ONGROUND = 512; /* BIT(8) */ // standing on something
+const int FL_PARTIALGROUND = 1024; /* BIT(9) */ // not all corners are valid
+const int FL_WATERJUMP = 2048; /* BIT(10) */ // player jumping out of water
+const int FL_JUMPRELEASED = 4096; /* BIT(11) */ // for jump debouncing
+#endif
+const int FL_WEAPON = BIT(12);
+const int FL_POWERUP = BIT(13);
+const int FL_PROJECTILE = BIT(14);
+const int FL_TOSSED = BIT(15);
+const int FL_SPAWNING = BIT(16);
+const int FL_PICKUPITEMS = BIT(17);
+const int FL_DUCKED = BIT(18);
+const int FL_ONSLICK = BIT(19);
+#endif
+
+#if defined(SVQC)
+ #define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT)
+#elif defined(CSQC)
+ #define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOSHADOW | EF_SELECTABLE | EF_TELEPORT_BIT)
+#endif
# define ALPHA m_alpha
.float m_alpha;
+
+# define GROUNDENTITY_NAME ground_networkentity
+# define GROUNDENTITY_TYPE float
+.float ground_networkentity;
#else
# define TAG_ENTITY_NAME tag_entity
# define TAG_ENTITY_TYPE entity
# define TAG_VIEWLOC_TYPE entity
# define ALPHA alpha
+
+# define GROUNDENTITY_NAME groundentity
+# define GROUNDENTITY_TYPE entity
#endif
// add properties you want networked to CSQC here
CSQCMODEL_PROPERTY(BIT(14), TAG_VIEWLOC_TYPE, ReadShort, WriteEntity, TAG_VIEWLOC_NAME) \
CSQCMODEL_PROPERTY(BIT(16), int, ReadByte, WriteByte, multijump_count) \
CSQCMODEL_PROPERTY(BIT(16), int, ReadByte, WriteByte, move_movetype) \
+ CSQCMODEL_IF(isplayer) \
+ CSQCMODEL_PROPERTY(BIT(17), GROUNDENTITY_TYPE, ReadShort, WriteEntity, GROUNDENTITY_NAME) \
+ CSQCMODEL_ENDIF \
CSQCMODEL_PROPERTY(BIT(17), int, ReadByte, WriteByte, clipgroup)
// TODO get rid of colormod/glowmod here; also get rid of some useless properties on non-players that only exist for CopyBody
#include "casings.qh"
+#include <common/replicate.qh>
#include <common/util.qh>
#ifdef CSQC
.float cnt;
.int state;
+.bool silent;
+
void DamageEffect_Think(entity this)
{
// if particle distribution is enabled, slow ticrate by total number of damages
#include <client/mutators/_mod.qh>
#include <common/vehicles/all.qh>
#include <common/weapons/_all.qh>
+
+int w_deathtype;
+float w_issilent, w_random;
+vector w_org, w_backoff;
+
+.float damageforcescale;
+const float MIN_DAMAGEEXTRARADIUS = 2;
+const float MAX_DAMAGEEXTRARADIUS = 16;
+.float damageextraradius;
+.void(entity this, float thisdmg, int hittype, vector org, vector thisforce) event_damage;
#endif
#ifdef SVQC
#include <server/player.qh>
#endif
+ #ifdef CSQC
+ #include <client/main.qh>
+ #endif
REGISTER_NET_TEMP(globalsound)
REGISTER_NET_TEMP(playersound)
}
if(f & 2)
{
- WriteCoord(MSG_ENTITY, this.angles.x);
- WriteCoord(MSG_ENTITY, this.angles.y);
- WriteCoord(MSG_ENTITY, this.angles.z);
+ WriteAngleVector(MSG_ENTITY, this.angles);
}
if(f & 4)
{
- WriteCoord(MSG_ENTITY, this.avelocity.x);
- WriteCoord(MSG_ENTITY, this.avelocity.y);
- WriteCoord(MSG_ENTITY, this.avelocity.z);
+ WriteAngleVector(MSG_ENTITY, this.avelocity);
}
WriteShort(MSG_ENTITY, this.scale * 256.0);
WriteShort(MSG_ENTITY, this.scale2 * 256.0);
}
if(f & 2)
{
- e.angles_x = ReadAngle();
- e.angles_y = ReadAngle();
- e.angles_z = ReadAngle();
+ e.angles = ReadAngleVector();
}
if(f & 4)
{
- e.avelocity_x = ReadAngle();
- e.avelocity_y = ReadAngle();
- e.avelocity_z = ReadAngle();
+ e.avelocity = ReadAngleVector();
}
e.scale1 = ReadShort() / 256.0;
e.scale2 = ReadShort() / 256.0;
do {
if (IS_PLAYER(player))
{
- if (radar_showennemies) break;
+ if (radar_showenemies) break;
if (SAME_TEAM(to, player)) break;
if (!(IS_PLAYER(to) || to.caplayer) && time > game_starttime) break;
}
#pragma once
#ifdef CSQC
-#include <client/defs.qh>
+#include <client/csqcmodel_hooks.qh>
#endif
REGISTER_NET_LINKED(ENT_CLIENT_ENTCS)
void entcs_force_origin(entity player);
+ bool radar_showenemies;
+
#endif
#ifdef CSQC
#include "sv_assault.qh"
+#include <server/command/vote.qh>
#include <common/mapobjects/func/breakable.qh>
+#include <common/mapobjects/triggers.qh>
+#include <common/turrets/sv_turrets.qh>
+#include <server/damage.qh>
+#include <server/world.qh>
+#include <server/spawnpoints.qh>
.entity sprite;
#define AS_ROUND_DELAY 5
#include "sv_ctf.qh"
#include <common/effects/all.qh>
+#include <common/mapobjects/teleporters.qh>
+#include <common/mapobjects/triggers.qh>
#include <common/vehicles/all.qh>
+#include <server/command/vote.qh>
+#include <server/client.qh>
#include <server/gamelog.qh>
+#include <server/damage.qh>
+#include <server/world.qh>
+#include <server/items/items.qh>
+#include <server/race.qh>
#include <server/teamplay.qh>
#include <lib/warpzone/common.qh>
ctf_CaptureShield_Update(player, 0); // shield player from picking up flag
}
+#if 0
void shockwave_spawn(string m, vector org, float sz, float t1, float t2)
{
return modeleffect_spawn(m, 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, sz, 1, t1, t2);
}
+#endif
// ==============
// Event Handlers
// effects
Send_Effect_(flag.capeffect, flag.origin, '0 0 0', 1);
- //shockwave_spawn("models/ctf/shockwavetransring.md3", flag.origin - '0 0 15', -0.8, 0, 1);
+#if 0
+ shockwave_spawn("models/ctf/shockwavetransring.md3", flag.origin - '0 0 15', -0.8, 0, 1);
+#endif
// other
if(capturetype == CAPTURE_NORMAL)
WaypointSprite_UpdateHealth(player.wps_flagcarrier, healtharmor_maxdamage(GetResource(player, RES_HEALTH), GetResource(player, RES_ARMOR), autocvar_g_balance_armor_blockpercent, DEATH_WEAPON.m_id).x);
}
-MUTATOR_HOOKFUNCTION(ctf, Damage_Calculate) // for changing damage and force values that are applied to players in g_damage.qc
+MUTATOR_HOOKFUNCTION(ctf, Damage_Calculate) // for changing damage and force values that are applied to players in damage.qc
{
entity frag_attacker = M_ARGV(1, entity);
entity frag_target = M_ARGV(2, entity);
if(head != player && SAME_TEAM(head, player))
if(!head.speedrunning && !head.vehicle)
{
- // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc)
+ // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in damage.qc)
vector head_center = WarpZone_UnTransformOrigin(head, CENTER_OR_VIEWOFS(head));
vector passer_center = CENTER_OR_VIEWOFS(player);
.float score_return;
.float score_team_capture; // shouldn't be too high
+// property set on objects to point to the flag they're carrying (if any)
+.entity flagcarried;
+
// effects
.string toucheffect;
.string passeffect;
#include "sv_cts.qh"
+#include <server/client.qh>
#include <server/race.qh>
+#include <server/world.qh>
#include <server/gamelog.qh>
-#include <server/items.qh>
+#include <server/items/spawning.qh>
+#include <server/weapons/common.qh>
+#include <common/mapobjects/triggers.qh>
float autocvar_g_cts_finish_kill_delay;
bool autocvar_g_cts_selfdamage;
#include "sv_domination.qh"
+#include <server/client.qh>
+#include <server/command/vote.qh>
+#include <server/damage.qh>
#include <server/gamelog.qh>
+#include <server/items/items.qh>
#include <server/teamplay.qh>
+#include <common/mapobjects/platforms.qh>
+#include <common/mapobjects/triggers.qh>
bool g_domination;
#include "sv_invasion.qh"
+#include <common/mapobjects/triggers.qh>
#include <common/monsters/sv_spawn.qh>
#include <common/monsters/sv_spawner.qh>
#include <common/monsters/sv_monsters.qh>
+#include <server/bot/api.qh>
+#include <server/world.qh>
#include <server/teamplay.qh>
IntrusiveList g_invasion_roundends;
#include "sv_keepaway.qh"
#include <common/effects/all.qh>
+#include <server/client.qh>
#include <server/gamelog.qh>
+#include <server/damage.qh>
+#include <server/items/items.qh>
.entity ballcarried;
}
}
-MUTATOR_HOOKFUNCTION(ka, Damage_Calculate) // for changing damage and force values that are applied to players in g_damage.qc
+MUTATOR_HOOKFUNCTION(ka, Damage_Calculate) // for changing damage and force values that are applied to players in damage.qc
{
entity frag_attacker = M_ARGV(1, entity);
entity frag_target = M_ARGV(2, entity);
#include "sv_keyhunt.qh"
+#include <server/command/vote.qh>
#include <server/gamelog.qh>
+#include <server/damage.qh>
+#include <server/items/items.qh>
+#include <common/mapobjects/triggers.qh>
float autocvar_g_balance_keyhunt_damageforcescale;
float autocvar_g_balance_keyhunt_delay_collect;
#include <common/mutators/mutator/instagib/items.qh>
#include <server/campaign.qh>
#include <server/command/_mod.qh>
+#include <server/world.qh>
+#include <server/items/items.qh>
int autocvar_g_lms_extra_lives;
bool autocvar_g_lms_join_anytime;
#pragma once
void HUD_Mod_NexBall(vector pos, vector mySize);
+
+float nb_pb_period;
#include "sv_nexball.qh"
+#include <server/client.qh>
+#include <server/command/vote.qh>
#include <server/gamelog.qh>
+#include <common/ent_cs.qh>
+#include <common/mapobjects/triggers.qh>
.entity ballcarried;
CVTOV(g_nexball_delay_idle); //10
CVTOV(g_nexball_football_physics); //0
*/
- radar_showennemies = autocvar_g_nexball_radar_showallplayers;
+ radar_showenemies = autocvar_g_nexball_radar_showallplayers;
InitializeEntity(NULL, nb_delayedinit, INITPRIO_GAMETYPE);
WEP_NEXBALL.spawnflags &= ~WEP_FLAG_MUTATORBLOCKED;
.float nb_droptime;
.float teamtime;
+
+float g_nexball_meter_period;
this.origin = ReadVector();
setorigin(this, this.origin);
- this.angles_x = ReadAngle();
- this.angles_y = ReadAngle();
- this.angles_z = ReadAngle();
+ this.angles = ReadAngleVector();
this.drawmask = MASK_NORMAL;
setmodel(this, MDL_Null); // give it a size for clientcamera
#include "sv_controlpoint.qh"
#include "sv_generator.qh"
+#include <server/bot/api.qh>
+#include <server/command/vote.qh>
+#include <server/damage.qh>
+#include <server/items/items.qh>
+#include <common/mapobjects/defs.qh>
+#include <common/mapobjects/triggers.qh>
+
bool g_onslaught;
float autocvar_g_onslaught_teleport_wait;
WriteVector(MSG_ENTITY, this.origin);
- WriteAngle(MSG_ENTITY, this.angles_x);
- WriteAngle(MSG_ENTITY, this.angles_y);
- WriteAngle(MSG_ENTITY, this.angles_z);
+ WriteAngleVector(MSG_ENTITY, this.angles);
return true;
}
this.team = this.enemy.team;
}
-void ons_CaptureShield_Spawn(entity generator, bool is_generator)
+void ons_CaptureShield_Spawn(entity this, Model shield_model)
{
entity shield = new(ons_captureshield);
IL_PUSH(g_onsshields, shield);
- shield.enemy = generator;
- shield.team = generator.team;
- shield.colormap = generator.colormap;
+ shield.enemy = this;
+ shield.team = this.team;
+ shield.colormap = this.colormap;
shield.reset = ons_CaptureShield_Reset;
settouch(shield, ons_CaptureShield_Touch);
setcefc(shield, ons_CaptureShield_Customize);
set_movetype(shield, MOVETYPE_NOCLIP);
shield.solid = SOLID_TRIGGER;
shield.avelocity = '7 0 11';
- shield.scale = 1;
- shield.model = ((is_generator) ? "models/onslaught/generator_shield.md3" : "models/onslaught/controlpoint_shield.md3");
+ shield.scale = this.scale;
- precache_model(shield.model);
- setorigin(shield, generator.origin);
- _setmodel(shield, shield.model);
- setsize(shield, shield.scale * shield.mins, shield.scale * shield.maxs);
+ float shield_extra_size = 1.20; // hitbox is 20% larger than the object itself
+ setorigin(shield, this.origin);
+ setmodel(shield, shield_model);
+ setsize(shield, shield_extra_size * this.mins, shield_extra_size * this.maxs);
}
onslaught_updatelinks();
// captureshield setup
- ons_CaptureShield_Spawn(this, false);
+ ons_CaptureShield_Spawn(this, MDL_ONS_CP_SHIELD);
CSQCMODEL_AUTOINIT(this);
}
FOREACH_CLIENT(true, it.clientcamera = cam;);
+ // NOTE: engine networked
WriteByte(MSG_ALL, SVC_SETVIEWANGLES);
WriteAngle(MSG_ALL, cam.angles_x);
WriteAngle(MSG_ALL, cam.angles_y);
this.bot_basewaypoint = this.nearestwaypoint;
// captureshield setup
- ons_CaptureShield_Spawn(this, true);
+ ons_CaptureShield_Spawn(this, MDL_ONS_GEN_SHIELD);
onslaught_updatelinks();
#include "sv_race.qh"
+#include <server/client.qh>
+#include <server/world.qh>
#include <server/gamelog.qh>
#include <server/race.qh>
+#include <common/ent_cs.qh>
+#include <common/mapobjects/triggers.qh>
#define autocvar_g_race_laps_limit cvar("g_race_laps_limit")
float autocvar_g_race_qualifying_timelimit;
race_ScoreRules();
if(g_race_qualifying == 2)
warmup_stage = 0;
+ radar_showenemies = true;
}
void rc_SetLimits()
#include "sv_rules.qh"
+#include <server/spawnpoints.qh>
#include <server/teamplay.qh>
void GameRules_teams(bool value)
#endif
#ifdef SVQC
-#include <server/items.qh>
+#include <server/items/spawning.qh>
#endif
+#ifdef GAMEQC
const int IT_UNLIMITED_AMMO = BIT(0); // when this bit is set, using a weapon does not reduce ammo. Checkpoints can give this powerup.
const int IT_UNLIMITED_SUPERWEAPONS = BIT(1); // when this bit is set, superweapons don't expire. Checkpoints can give this powerup.
const int IT_KEY1 = BIT(6);
const int IT_KEY2 = BIT(7);
-const int IT_CTF_SHIELDED = BIT(8); // set for the flag shield
-
// special colorblend meaning in engine
const int IT_INVISIBILITY = BIT(9);
const int IT_INVINCIBLE = BIT(10);
// item masks
const int IT_PICKUPMASK = IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS | IT_JETPACK | IT_FUEL_REGEN; // strength and invincible are handled separately
+// item networking
+const int ISF_LOCATION = BIT(1);
+const int ISF_MODEL = BIT(2);
+const int ISF_STATUS = BIT(3);
+const int ISF_COLORMAP = BIT(4);
+const int ISF_DROP = BIT(5);
+const int ISF_ANGLES = BIT(6);
+const int ISF_SIZE = BIT(7);
+
+REGISTER_NET_LINKED(ENT_CLIENT_ITEM)
+
+// item status
+.int ItemStatus;
+const int ITS_STAYWEP = BIT(0);
+const int ITS_ANIMATE1 = BIT(1);
+const int ITS_ANIMATE2 = BIT(2);
+const int ITS_AVAILABLE = BIT(3);
+const int ITS_ALLOWFB = BIT(4);
+const int ITS_ALLOWSI = BIT(5);
+const int ITS_GLOW = BIT(6);
+
+.float fade_start;
+.float fade_end;
+
+.string mdl;
+#endif
+
#ifdef SVQC
.float strength_finished; // NOTE: this field is used only by map entities, it does not directly apply the strength stat
.float invincible_finished; // ditto
#include "pickup.qh"
#include <common/items/all.qh>
#ifdef SVQC
- #include <common/t_items.qh>
+ #include <server/items/items.qh>
#include <server/resources.qh>
#endif
ENDCLASS(Armor)
#ifdef SVQC
- #include <common/t_items.qh>
+ #include <server/items/items.qh>
#endif
#ifdef GAMEQC
ENDCLASS(Health)
#ifdef SVQC
- #include <common/t_items.qh>
+ #include <server/items/items.qh>
#endif
#ifdef GAMEQC
#pragma once
#ifdef SVQC
- #include <common/t_items.qh>
+ #include <server/items/items.qh>
#endif
#include "ammo.qh"
#ifdef SVQC
// For FL_POWERUP
- #include <server/constants.qh>
+ #include <common/constants.qh>
#endif
#include "pickup.qh"
this.m_color = '0 0 1';
this.m_waypoint = _("Strength");
this.m_waypointblink = 2;
+#ifdef GAMEQC
this.m_itemid = IT_STRENGTH;
+#endif
#ifdef SVQC
this.m_iteminit = powerup_strength_init;
#endif
this.m_color = '1 0 1';
this.m_waypoint = _("Shield");
this.m_waypointblink = 2;
+#ifdef GAMEQC
this.m_itemid = IT_INVINCIBLE;
+#endif
#ifdef SVQC
this.m_iteminit = powerup_shield_init;
#endif
#include "mapinfo.qh"
#if defined(CSQC)
- #include "../client/defs.qh"
#include "util.qh"
#include <common/weapons/_all.qh>
#elif defined(MENUQC)
// generated file; do not modify
+#include <common/mapobjects/bgmscript.qc>
#include <common/mapobjects/models.qc>
#include <common/mapobjects/platforms.qc>
#include <common/mapobjects/subs.qc>
// generated file; do not modify
+#include <common/mapobjects/bgmscript.qh>
#include <common/mapobjects/models.qh>
#include <common/mapobjects/platforms.qh>
#include <common/mapobjects/subs.qh>
--- /dev/null
+#include "bgmscript.qh"
--- /dev/null
+#pragma once
+
+entityclass(BGMScript);
+classfield(BGMScript) .string bgmscript;
+classfield(BGMScript) .float bgmscriptattack;
+classfield(BGMScript) .float bgmscriptdecay;
+classfield(BGMScript) .float bgmscriptsustain;
+classfield(BGMScript) .float bgmscriptrelease;
//----------------
// STATES & ACTIVE
//----------------
-#ifdef CSQC
-// this stuff is defined in the server side engine VM, so we must define it separately here
const int STATE_TOP = 0;
const int STATE_BOTTOM = 1;
const int STATE_UP = 2;
const int STATE_DOWN = 3;
+.int active;
+.void (entity this, int act_state) setactive;
const int ACTIVE_NOT = 0;
const int ACTIVE_ACTIVE = 1;
const int ACTIVE_IDLE = 2;
const int ACTIVE_BUSY = 2;
const int ACTIVE_TOGGLE = 3;
-#endif
#include "breakable.qh"
#ifdef SVQC
-#include <server/g_damage.qh>
+#include <server/damage.qh>
#include <server/bot/api.qh>
#include <common/csqcmodel_settings.qh>
#include <lib/csqcmodel/sv_model.qh>
IntrusiveList g_ladderents;
STATIC_INIT(g_ladderents) { g_ladderents = IL_NEW(); }
+#ifdef SVQC
+IntrusiveList g_ladders;
+STATIC_INIT(g_ladders) { g_ladders = IL_NEW(); }
+#endif
+
.entity ladder_entity;
WriteVector(MSG_ENTITY, this.size);
- WriteAngle(MSG_ENTITY, this.mangle_x);
- WriteAngle(MSG_ENTITY, this.mangle_y);
- WriteAngle(MSG_ENTITY, this.mangle_z);
+ WriteAngleVector(MSG_ENTITY, this.mangle);
WriteShort(MSG_ENTITY, this.speed);
WriteShort(MSG_ENTITY, this.height);
this.size = ReadVector();
- this.mangle_x = ReadAngle();
- this.mangle_y = ReadAngle();
- this.mangle_z = ReadAngle();
+ this.mangle = ReadAngleVector();
this.speed = ReadShort();
this.height = ReadShort();
Brush model that spins in place on one axis (default Z).
speed : speed to rotate (in degrees per second)
noise : path/name of looping .wav file to play.
-dmg : Do this mutch dmg every .dmgtime intervall when blocked
+dmg : Do this much damage every .dmgtime interval when blocked
dmgtime : See above.
*/
#include "stardust.qh"
#ifdef SVQC
+void func_stardust_think(entity this)
+{
+ this.nextthink = time + 0.25;
+ CSQCMODEL_AUTOUPDATE(this);
+}
spawnfunc(func_stardust)
{
+ if(this.model != "") { precache_model(this.model); _setmodel(this, this.model); }
+
this.effects = EF_STARDUST;
CSQCMODEL_AUTOINIT(this);
+
+ setthink(this, func_stardust_think);
+ this.nextthink = time + 0.25;
}
#endif
WriteVector(MSG_ENTITY, this.view_ofs);
- WriteAngle(MSG_ENTITY, this.mangle_x);
- WriteAngle(MSG_ENTITY, this.mangle_y);
- WriteAngle(MSG_ENTITY, this.mangle_z);
+ WriteAngleVector(MSG_ENTITY, this.mangle);
WriteShort(MSG_ENTITY, this.speed);
WriteShort(MSG_ENTITY, this.height);
this.view_ofs = ReadVector();
- this.mangle_x = ReadAngle();
- this.mangle_y = ReadAngle();
- this.mangle_z = ReadAngle();
+ this.mangle = ReadAngleVector();
this.speed = ReadShort();
this.height = ReadShort();
const int TRAIN_CURVE = BIT(0);
const int TRAIN_TURN = BIT(1);
const int TRAIN_NEEDACTIVATION = BIT(2);
-
-#ifdef CSQC
-.float dmgtime;
-#endif
vector func_vectormamamam_origin(entity o, float timestep)
{
- vector v, p;
- float flags;
+ vector p;
entity e;
-
- flags = o.spawnflags;
- v = '0 0 0';
+ int myflags = o.spawnflags;
+ vector v = '0 0 0';
e = o.wp00;
if(e)
{
p = e.origin + timestep * e.velocity;
- if(flags & PROJECT_ON_TARGETNORMAL)
+ if(myflags & PROJECT_ON_TARGETNORMAL)
v = v + (p * o.targetnormal) * o.targetnormal * o.targetfactor;
else
v = v + (p - (p * o.targetnormal) * o.targetnormal) * o.targetfactor;
if(e)
{
p = e.origin + timestep * e.velocity;
- if(flags & PROJECT_ON_TARGET2NORMAL)
+ if(myflags & PROJECT_ON_TARGET2NORMAL)
v = v + (p * o.target2normal) * o.target2normal * o.target2factor;
else
v = v + (p - (p * o.target2normal) * o.target2normal) * o.target2factor;
if(e)
{
p = e.origin + timestep * e.velocity;
- if(flags & PROJECT_ON_TARGET3NORMAL)
+ if(myflags & PROJECT_ON_TARGET3NORMAL)
v = v + (p * o.target3normal) * o.target3normal * o.target3factor;
else
v = v + (p - (p * o.target3normal) * o.target3normal) * o.target3factor;
if(e)
{
p = e.origin + timestep * e.velocity;
- if(flags & PROJECT_ON_TARGET4NORMAL)
+ if(myflags & PROJECT_ON_TARGET4NORMAL)
v = v + (p * o.target4normal) * o.target4normal * o.target4factor;
else
v = v + (p - (p * o.target4normal) * o.target4normal) * o.target4factor;
void func_vectormamamam_controller_think(entity this)
{
- this.nextthink = time + vectormamamam_timestep;
+ this.nextthink = time + VECTORMAMAMAM_TIMESTEP;
if(this.owner.active != ACTIVE_ACTIVE)
{
}
if(this.owner.classname == "func_vectormamamam") // don't brake stuff if the func_vectormamamam was killtarget'ed
- this.owner.velocity = (this.owner.destvec + func_vectormamamam_origin(this.owner, vectormamamam_timestep) - this.owner.origin) * 10;
+ this.owner.velocity = (this.owner.destvec + func_vectormamamam_origin(this.owner, VECTORMAMAMAM_TIMESTEP) - this.owner.origin) * 10;
}
void func_vectormamamam_findtarget(entity this)
{
- if(this.target != "")
+ if(this.target && this.target != "")
this.wp00 = find(NULL, targetname, this.target);
- if(this.target2 != "")
+ if(this.target2 && this.target2 != "")
this.wp01 = find(NULL, targetname, this.target2);
- if(this.target3 != "")
+ if(this.target3 && this.target3 != "")
this.wp02 = find(NULL, targetname, this.target3);
- if(this.target4 != "")
+ if(this.target4 && this.target4 != "")
this.wp03 = find(NULL, targetname, this.target4);
if(!this.wp00 && !this.wp01 && !this.wp02 && !this.wp03)
this.destvec = this.origin - func_vectormamamam_origin(this, 0);
- entity controller;
- controller = new(func_vectormamamam_controller);
+ entity controller = new(func_vectormamamam_controller);
controller.owner = this;
controller.nextthink = time + 1;
setthink(controller, func_vectormamamam_controller_think);
this.target4normal = normalize(this.target4normal);
setblocked(this, generic_plat_blocked);
- if(this.dmg && (this.message == ""))
+ if(this.dmg && (!this.message || this.message == ""))
this.message = " was squished";
- if(this.dmg && (this.message == ""))
+ if(this.dmg && (!this.message2 || this.message2 == ""))
this.message2 = "was squished by";
if(this.dmg && (!this.dmgtime))
this.dmgtime = 0.25;
#pragma once
-
const int PROJECT_ON_TARGETNORMAL = BIT(0);
const int PROJECT_ON_TARGET2NORMAL = BIT(1);
const int PROJECT_ON_TARGET3NORMAL = BIT(2);
const int PROJECT_ON_TARGET4NORMAL = BIT(3);
-const float vectormamamam_timestep = 0.1;
+const float VECTORMAMAMAM_TIMESTEP = 0.1;
#include "dynlight.qh"
#ifdef SVQC
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
const float LOOP = 1;
REGISTER_NET_LINKED(ENT_CLIENT_LASER)
#ifdef SVQC
-.float modelscale;
void misc_laser_aim(entity this)
{
vector a;
}
else
{
- WriteAngle(MSG_ENTITY, this.mangle_x);
- WriteAngle(MSG_ENTITY, this.mangle_y);
+ WriteAngleVector2D(MSG_ENTITY, this.mangle);
}
}
if(sendflags & SF_LASER_UPDATE_ACTIVE)
}
#elif defined(CSQC)
-// a laser goes from origin in direction angles
-// it has color 'beam_color'
-// and stops when something is in the way
-entityclass(Laser);
-classfield(Laser) .int cnt; // end effect
-classfield(Laser) .vector colormod;
-classfield(Laser) .int state; // on-off
-classfield(Laser) .int count; // flags for the laser
-classfield(Laser) .vector velocity; // laser endpoint if it is FINITE
-classfield(Laser) .float alpha;
-classfield(Laser) .float scale; // scaling factor of the thickness
-classfield(Laser) .float modelscale; // scaling factor of the dlight
-
void Draw_Laser(entity this)
{
if(this.active == ACTIVE_NOT)
}
else
{
- this.angles_x = ReadAngle();
- this.angles_y = ReadAngle();
+ this.angles = ReadAngleVector2D();
}
}
if(sendflags & SF_LASER_UPDATE_ACTIVE)
#pragma once
+// a laser goes from origin in direction angles
+// it has color 'beam_color'
+// and stops when something is in the way
+entityclass(Laser);
+classfield(Laser) .int cnt; // end effect
+classfield(Laser) .vector colormod;
+classfield(Laser) .int state; // on-off
+classfield(Laser) .int count; // flags for the laser
+classfield(Laser) .vector velocity; // laser endpoint if it is FINITE
+classfield(Laser) .float alpha;
+classfield(Laser) .float scale; // scaling factor of the thickness
+classfield(Laser) .float modelscale; // scaling factor of the dlight
const int LASER_FINITE = BIT(1);
const int LASER_NOTRACE = BIT(2);
WriteCoord(MSG_ENTITY, this.speed);
WriteString(MSG_ENTITY, this.targetname);
WriteVector(MSG_ENTITY, this.origin);
-
- WriteAngle(MSG_ENTITY, this.mangle_x);
- WriteAngle(MSG_ENTITY, this.mangle_y);
- WriteAngle(MSG_ENTITY, this.mangle_z);
+ WriteAngleVector(MSG_ENTITY, this.mangle);
}
return true;
this.speed = ReadCoord();
this.targetname = strzone(ReadString());
this.origin = ReadVector();
-
- this.mangle_x = ReadAngle();
- this.mangle_y = ReadAngle();
- this.mangle_z = ReadAngle();
+ this.mangle = ReadAngleVector();
setorigin(this, this.origin);
#include "models.qh"
#ifdef SVQC
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include <common/net_linked.qh>
#include "subs.qh"
#include "triggers.qh"
-
-entityclass(BGMScript);
-classfield(BGMScript) .string bgmscript;
-classfield(BGMScript) .float bgmscriptattack;
-classfield(BGMScript) .float bgmscriptdecay;
-classfield(BGMScript) .float bgmscriptsustain;
-classfield(BGMScript) .float bgmscriptrelease;
+#include "bgmscript.qh"
#include <common/constants.qh>
-#include "../../lib/csqcmodel/sv_model.qh"
-
-.float modelscale;
+#include <lib/csqcmodel/sv_model.qh>
void g_model_setcolormaptoactivator(entity this, entity actor, entity trigger)
{
if(sf & BIT(2))
{
if(sf & 0x10)
- {
- WriteAngle(MSG_ENTITY, this.angles.x);
- WriteAngle(MSG_ENTITY, this.angles.y);
- WriteAngle(MSG_ENTITY, this.angles.z);
- }
+ WriteAngleVector(MSG_ENTITY, this.angles);
}
if(sf & BIT(3))
if(f & 4)
{
if(f & 0x10)
- {
- this.angles_x = ReadAngle();
- this.angles_y = ReadAngle();
- this.angles_z = ReadAngle();
- }
+ this.angles = ReadAngleVector();
else
this.angles = '0 0 0';
}
#pragma once
+.float modelscale;
+
#ifdef CSQC
entityclass(Wall);
classfield(Wall) .float lip;
classfield(Wall) .float loddistance1, loddistance2;
classfield(Wall) .vector saved;
+void Ent_Wall_Draw(entity this);
+
+void Ent_Wall_Remove(entity this);
+#endif
+
// Needed for interactive clientwalls
.bool inactive; // Clientwall disappears when inactive
.float alpha_max, alpha_min;
// fade_vertical_offset is a vertival offset for player position
.float fade_start, fade_end, fade_vertical_offset;
.float default_solid;
-
-void Ent_Wall_Draw(entity this);
-
-void Ent_Wall_Remove(entity this);
-#endif
const int PLAT_LOW_TRIGGER = BIT(0);
+.float dmg;
+.float dmgtime;
.float dmgtime2;
+.float phase;
+
void plat_center_touch(entity this, entity toucher);
void plat_outside_touch(entity this, entity toucher);
void plat_trigger_use(entity this, entity actor, entity trigger);
void plat_go_up(entity this);
void plat_go_down(entity this);
void plat_crush(entity this, entity blocker);
-
-.float dmg;
#include "kill.qh"
-#include "location.qh"
-#ifdef SVQC
+#ifdef SVQC
void target_kill_use(entity this, entity actor, entity trigger)
{
+ if(this.active != ACTIVE_ACTIVE)
+ return;
+
if(actor.takedamage == DAMAGE_NO)
return;
Damage(actor, this, trigger, 1000, DEATH_HURTTRIGGER.m_id, DMG_NOWEP, actor.origin, '0 0 0');
}
-spawnfunc(target_kill)
+void target_kill_reset(entity this)
{
- this.classname = "target_kill";
+ this.active = ACTIVE_ACTIVE;
+}
+spawnfunc(target_kill)
+{
if (this.message == "")
this.message = "was in the wrong place";
+ if (this.message2 == "")
+ this.message2 = "was thrown into a world of hurt by";
+
this.use = target_kill_use;
+ this.reset = target_kill_reset;
+ this.active = ACTIVE_ACTIVE;
}
-
#endif
#pragma once
+
+#ifdef SVQC
+IntrusiveList g_locations;
+STATIC_INIT(g_locations) { g_locations = IL_NEW(); }
+#endif
#elif defined(SVQC)
#include <common/constants.qh>
#include <common/net_linked.qh>
- #include <server/constants.qh>
- #include <server/defs.qh>
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
#endif
REGISTER_NET_TEMP(TE_CSQC_TARGET_MUSIC)
#elif defined(MENUQC)
#elif defined(SVQC)
#include <common/util.qh>
- #include <server/defs.qh>
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
+ #include <server/world.qh>
#endif
#ifdef SVQC
#include "../util.qh"
#include <server/weapons/csqcprojectile.qh>
#include <server/autocvars.qh>
- #include <server/constants.qh>
- #include <server/defs.qh>
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
#include "../deathtypes/all.qh"
+ #include <server/main.qh>
#include "../turrets/sv_turrets.qh"
#include "../vehicles/all.qh"
#include <common/gamemodes/_mod.qh>
#define TELEPORT_FLAGS_PORTAL (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH | TELEPORT_FLAG_FORCE_TDEATH)
#define TELEPORT_FLAGS_TELEPORTER (TELEPORT_FLAG_SOUND | TELEPORT_FLAG_PARTICLES | TELEPORT_FLAG_TDEATH)
+.float teleportable;
// types for .teleportable entity setting
const int TELEPORT_NORMAL = 1; // play sounds/effects etc
const int TELEPORT_SIMPLE = 2; // only do teleport, nothing special
#include "counter.qh"
-#ifdef SVQC
-void counter_reset(entity this);
+#ifdef SVQC
void counter_use(entity this, entity actor, entity trigger)
{
+ if(this.active != ACTIVE_ACTIVE)
+ return;
+
entity store = this;
if(this.spawnflags & COUNTER_PER_PLAYER)
{
setthink(this, func_null);
this.nextthink = 0;
this.counter_cnt = 0;
+ this.active = ACTIVE_ACTIVE;
}
/*QUAKED spawnfunc_trigger_counter (.5 .5 .5) ? nomessage COUNTER_FIRE_AT_COUNT
this.counter_cnt = 0;
this.use = counter_use;
this.reset = counter_reset;
+ this.active = ACTIVE_ACTIVE;
}
#endif
#pragma once
#ifdef SVQC
-spawnfunc(trigger_counter);
+void counter_reset(entity this);
.float counter_cnt;
#include "delay.qh"
+
#ifdef SVQC
void delay_delayeduse(entity this)
{
void delay_use(entity this, entity actor, entity trigger)
{
+ if(this.active != ACTIVE_ACTIVE)
+ return;
+
this.enemy = actor;
this.goalentity = trigger;
setthink(this, delay_delayeduse);
this.enemy = this.goalentity = NULL;
setthink(this, func_null);
this.nextthink = 0;
+ this.active = ACTIVE_ACTIVE;
}
spawnfunc(trigger_delay)
this.use = delay_use;
this.reset = delay_reset;
+ this.active = ACTIVE_ACTIVE;
}
#endif
#include "flipflop.qh"
+
#ifdef SVQC
/*QUAKED spawnfunc_trigger_flipflop (.5 .5 .5) (-8 -8 -8) (8 8 8) START_ENABLED
"Flip-flop" trigger gate... lets only every second trigger event through
*/
void flipflop_use(entity this, entity actor, entity trigger)
{
+ if(this.active != ACTIVE_ACTIVE)
+ return;
+
this.state = !this.state;
if(this.state)
SUB_UseTargets(this, actor, trigger);
spawnfunc(trigger_flipflop)
{
- if(this.spawnflags & START_ENABLED)
- {
- this.state = true;
- }
+ this.active = ACTIVE_ACTIVE;
+ this.state = (this.spawnflags & START_ENABLED);
this.use = flipflop_use;
this.reset = spawnfunc_trigger_flipflop; // perfect resetter
}
-
#endif
#include "gamestart.qh"
+
#ifdef SVQC
void gamestart_use(entity this, entity actor, entity trigger)
{
SUB_UseTargets(this, this, trigger);
- delete(this);
-}
-
-void gamestart_use_this(entity this)
-{
- gamestart_use(this, NULL, NULL);
+ delete(this); // TODO: deleting this means it can't be used upon map reset!
}
spawnfunc(trigger_gamestart)
this.nextthink = game_starttime + this.wait;
}
else
- InitializeEntity(this, gamestart_use_this, INITPRIO_FINDTARGET);
+ InitializeEntity(this, adaptor_think2use, INITPRIO_FINDTARGET);
}
-
#endif
#pragma once
+#ifdef SVQC
const int HURT_SLOW = BIT(4);
+
+bool tracebox_hits_trigger_hurt(vector start, vector e_min, vector e_max, vector end);
+#endif
// TODO: split target_push and put it in the target folder
#ifdef SVQC
#include <common/physics/movetypes/movetypes.qh>
+#include <server/main.qh>
void trigger_push_use(entity this, entity actor, entity trigger)
{
WriteString(MSG_ENTITY, this.targetname);
WriteVector(MSG_ENTITY, this.origin);
- WriteAngle(MSG_ENTITY, this.angles_x);
- WriteAngle(MSG_ENTITY, this.angles_y);
- WriteAngle(MSG_ENTITY, this.angles_z);
+ WriteAngleVector(MSG_ENTITY, this.angles);
return true;
}
this.targetname = strzone(ReadString());
this.origin = ReadVector();
- this.angles_x = ReadAngle();
- this.angles_y = ReadAngle();
- this.angles_z = ReadAngle();
+ this.angles = ReadAngleVector();
return = true;
trigger_keylock_link(this);
}
#elif defined(CSQC)
-void keylock_remove(entity this)
-{
- strfree(this.target);
- strfree(this.target2);
- strfree(this.target3);
- strfree(this.target4);
- strfree(this.killtarget);
- strfree(this.targetname);
-}
-
NET_HANDLE(ENT_CLIENT_KEYLOCK, bool isnew)
{
this.itemkeys = ReadInt24_t();
return = true;
this.classname = "trigger_keylock";
- this.entremove = keylock_remove;
+ this.entremove = trigger_remove_generic;
}
#endif
return; // only players
}
- // TODO: restructure this so that trigger_secret is more independent
- if (this.classname == "trigger_secret")
- {
- if (!IS_PLAYER(this.enemy))
- return;
- found_secrets = found_secrets + 1;
- WriteByte (MSG_ALL, SVC_FOUNDSECRET);
- }
-
- if (this.noise)
+ if (this.noise && this.noise != "")
{
_sound (this.enemy, CH_TRIGGER, this.noise, VOL_BASE, ATTEN_NORM);
}
else if (this.sounds == 3)
this.noise = "misc/trigger1.wav";
- if(this.noise)
+ if(this.noise && this.noise != "")
precache_sound(this.noise);
if (!this.wait)
#include "relay_activators.qh"
+
#ifdef SVQC
void relay_activators_use(entity this, entity actor, entity trigger)
{
+ if(this.active != ACTIVE_ACTIVE)
+ return;
+
for(entity trg = NULL; (trg = find(trg, targetname, this.target)); )
{
if (trg.setactive)
}
}
+void relay_activators_init(entity this)
+{
+ this.reset = relay_activators_init; // doubles as a reset function
+ this.active = ACTIVE_ACTIVE;
+ this.use = relay_activators_use;
+}
+
spawnfunc(relay_activate)
{
this.cnt = ACTIVE_ACTIVE;
- this.use = relay_activators_use;
+ relay_activators_init(this);
}
spawnfunc(relay_deactivate)
{
this.cnt = ACTIVE_NOT;
- this.use = relay_activators_use;
+ relay_activators_init(this);
}
spawnfunc(relay_activatetoggle)
{
this.cnt = ACTIVE_TOGGLE;
- this.use = relay_activators_use;
+ relay_activators_init(this);
}
#endif
#include "relay_if.qh"
+
#ifdef SVQC
void trigger_relay_if_use(entity this, entity actor, entity trigger)
{
#include "relay_teamcheck.qh"
+
#ifdef SVQC
void trigger_relay_teamcheck_use(entity this, entity actor, entity trigger)
{
#elif defined(MENUQC)
#elif defined(SVQC)
#include <common/util.qh>
- #include <server/defs.qh>
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
#endif
#ifdef SVQC
-void secrets_setstatus(entity this)
-{
- // TODO: use global stats!
- STAT(SECRETS_TOTAL, this) = secrets_total;
- STAT(SECRETS_FOUND, this) = secrets_found;
-}
-
/**
* A secret has been found (maybe :P)
*/
if (!IS_PLAYER(toucher))
return;
+ EXACTTRIGGER_TOUCH(this, toucher);
+
// update secrets found counter
secrets_found += 1;
- //print("Secret found: ", ftos(secret_counter.cnt), "/");
- //print(ftos(secret_counter.count), "\n");
- // centerprint message (multi_touch() doesn't always call centerprint())
- centerprint(toucher, this.message);
- this.message = "";
+ // message and noise handled by SUB_UseTargets
+ SUB_UseTargets(this, toucher, toucher);
- // handle normal trigger features
- multi_touch(this, toucher);
// we can't just delete(this) here, because this is a touch function
// called while C code is looping through area links...
- //delete(this);
+ settouch(this, func_null);
+}
+
+#if 0
+void trigger_secret_reset(entity this)
+{
+ secrets_found = 0;
+ settouch(this, trigger_secret_touch);
}
+#endif
/*QUAKED trigger_secret (.5 .5 .5) ?
Variable sized secret trigger. Can be targeted at one or more entities.
secrets_total += 1;
// add default message
- if (this.message == "")
+ if (!this.message || this.message == "")
this.message = "You found a secret!";
// set default sound
- if (this.noise == "")
- if (!this.sounds)
+ if ((!this.noise || this.noise == "") && !this.sounds)
this.sounds = 1; // misc/secret.wav
- // this entity can't be a target itself!!!!
- this.targetname = "";
+ switch(this.sounds)
+ {
+ case 1: this.noise = "misc/secret.wav"; break;
+ case 2: this.noise = strzone(SND(TALK)); break;
+ case 3: this.noise = "misc/trigger1.wav"; break;
+ }
- // you can't just shoot a room to find it, can you?
- SetResourceExplicit(this, RES_HEALTH, 0);
+ if(this.noise && this.noise != "")
+ precache_sound(this.noise);
- // a secret can not be delayed
+ // a secret cannot be delayed
this.delay = 0;
- // convert this trigger to trigger_once
- //this.classname = "trigger_once";
- spawnfunc_trigger_once(this);
+ EXACTTRIGGER_INIT;
- // take over the touch() function, so we can mark secret as found
settouch(this, trigger_secret_touch);
- // ignore triggering;
- this.use = func_null;
+// NOTE: old maps don't expect secrets to reset, so enabling resetting can cause issues!
+#if 0
+ this.reset = trigger_secret_reset;
+#endif
}
#endif
#pragma once
-#ifdef SVQC
-
-/**
- * Total number of secrets on the map.
- */
-float secrets_total;
-
-/**
- * Total numbe of secrets found on the map.
- */
-float secrets_found;
+#ifdef SVQC
+// Total number of secrets on the map.
+int secrets_total;
-/**
- * update secrets status.
- */
-void secrets_setstatus(entity this);
+// Total numbe of secrets found on the map.
+int secrets_found;
#endif
#elif defined(SVQC)
#include <lib/warpzone/util_server.qh>
#include <common/weapons/_all.qh>
- #include <server/defs.qh>
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
#include <common/deathtypes/all.qh>
#endif
#elif defined(MENUQC)
#elif defined(SVQC)
#include <lib/warpzone/util_server.qh>
- #include <server/defs.qh>
+ #include <common/mapobjects/triggers.qh>
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
#endif
REGISTER_NET_LINKED(ENT_CLIENT_VIEWLOC)
WriteVector(MSG_ENTITY, this.origin);
- WriteAngle(MSG_ENTITY, this.angles_x);
- WriteAngle(MSG_ENTITY, this.angles_y);
- WriteAngle(MSG_ENTITY, this.angles_z);
+ WriteAngleVector(MSG_ENTITY, this.angles);
return true;
}
this.origin = ReadVector();
setorigin(this, this.origin);
- this.movedir_x = ReadAngle();
- this.movedir_y = ReadAngle();
- this.movedir_z = ReadAngle();
+ this.movedir = ReadAngleVector();
return = true;
.float lip;
+// handy fields used by a lot of the codebase, but more importantly used by map objects
+.float cnt;
+.float count;
+
// used elsewhere (will fix)
#ifdef SVQC
+.string message2;
+
void trigger_common_write(entity this, bool withtarget);
string trigger_magicear_processmessage_forallears(entity source, float teamsay, entity privatesay, string msgin);
void trigger_common_read(entity this, bool withtarget);
void trigger_remove_generic(entity this);
-.float active;
.string target;
.string targetname;
#endif
#ifdef SVQC
#include "sv_monsters.qh"
-#include <server/g_damage.qh>
+#include <server/damage.qh>
#include <server/bot/api.qh>
#include <server/weapons/common.qh>
#include <server/weapons/tracing.qh>
#include "../physics/movelib.qh"
#include "../weapons/_mod.qh"
#include <server/autocvars.qh>
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/damage.qh>
#include "../deathtypes/all.qh"
+#include <server/items/items.qh>
#include <server/mutators/_mod.qh>
#include <server/steerlib.qh>
+#include <server/main.qh>
#include "../turrets/sv_turrets.qh"
#include "../turrets/util.qh"
#include "../vehicles/all.qh"
#include <server/campaign.qh>
+#include <server/cheats.qh>
#include <server/command/_mod.qh>
+#include <common/items/_mod.qh>
+#include <common/mapobjects/teleporters.qh>
#include "../mapobjects/triggers.qh"
#include <lib/csqcmodel/sv_model.qh>
#include <server/round_handler.qh>
{
if(Monster_ValidTarget(this, it))
{
- // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc)
+ // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in damage.qc)
vector targ_center = CENTER_OR_VIEWOFS(it);
if(closest_target)
return true;
}
-void Monster_Respawn(entity this) { Monster_Spawn(this, true, this); }
+void Monster_Respawn(entity this) { Monster_Spawn(this, true, this.monsterdef); }
.vector pos1, pos2;
int animbits = deadbits;
if(STAT(FROZEN, this))
animbits |= ANIMSTATE_FROZEN;
- if(this.crouch)
+ if(IS_DUCKED(this))
animbits |= ANIMSTATE_DUCK; // not that monsters can crouch currently...
animdecide_setstate(this, animbits, false);
animdecide_setimplicitstate(this, (IS_ONGROUND(this)));
#pragma once
+#include "all.qh"
+
// stats networking
int monsters_total;
int monsters_killed;
#undef _MSOUND
float GetMonsterSoundSampleField_notFound;
+
+IntrusiveList g_monsters;
+STATIC_INIT(g_monsters) { g_monsters = IL_NEW(); }
+
+IntrusiveList g_monster_targets;
+STATIC_INIT(g_monster_targets) { g_monster_targets = IL_NEW(); }
#include "all.qh"
#include "sv_monsters.qh"
#include <server/autocvars.qh>
- #include <server/defs.qh>
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
+ #include <server/weapons/common.qh>
#endif
entity spawnmonster (entity e, string monster, Monster monster_id, entity spawnedby, entity own, vector orig, bool respwn, bool removeifinvalid, int moveflag)
{
+#include "sv_monsters.qh"
#include "sv_spawner.qh"
#include "sv_spawn.qh"
#include "sv_breakablehook.qh"
#include <common/deathtypes/all.qh>
-#include <server/g_hook.qh>
+#include <server/hook.qh>
REGISTER_MUTATOR(breakablehook, cvar("g_breakablehook"));
#include <common/mapobjects/target/music.qh>
#include <common/gamemodes/_mod.qh>
+#include <server/items/items.qh>
+#include <server/main.qh>
void buffs_DelayedInit(entity this);
this.m_color = '1 0 0';
this.m_waypoint = _("Extra life");
this.m_waypointblink = 2;
+#ifdef SVQC
this.m_itemid = IT_RESOURCE;
+#endif
}
SPAWNFUNC_ITEM(item_extralife, ITEM_ExtraLife)
this.m_color = '0 0 1';
this.m_waypoint = _("Invisibility");
this.m_waypointblink = 2;
+#ifdef GAMEQC
this.m_itemid = IT_STRENGTH;
+#endif
#ifdef SVQC
this.m_iteminit = powerup_invisibility_init;
#endif
this.m_color = '1 0 1';
this.m_waypoint = _("Speed");
this.m_waypointblink = 2;
+#ifdef GAMEQC
this.m_itemid = IT_INVINCIBLE;
+#endif
#ifdef SVQC
this.m_iteminit = powerup_speed_init;
#endif
#include "sv_new_toys.qh"
#include "../random_items/sv_random_items.qh"
+#include <server/weapons/spawning.qh>
/*
#include "sv_nix.qh"
+#include <server/weapons/selection.qh>
+
//string autocvar_g_nix;
int autocvar_g_balance_nix_ammo_cells;
int autocvar_g_balance_nix_ammo_plasma;
#include "sv_spawn_near_teammate.qh"
+#include <common/mapobjects/trigger/hurt.qh>
+
#include <lib/float.qh>
string autocvar_g_spawn_near_teammate;
#include <common/net_linked.qh>
#include <common/teams.qh>
#include <server/autocvars.qh>
- #include <server/constants.qh>
- #include <server/defs.qh>
+ #include <server/world.qh>
#include <server/mutators/_mod.qh>
#endif
return this.dphitcontentsmask;
else if(this.solid == SOLID_SLIDEBOX)
{
- if(this.flags & 32) // TODO: FL_MONSTER
+ if(this.flags & FL_MONSTER)
return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_MONSTERCLIP;
else
return DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP;
void Movetype_Physics_NoMatchTicrate(entity this, float movedt, bool isclient) // to be run every move frame
{
+ bool didmove = (this.move_time != 0);
this.move_time = time;
if(isclient)
_Movetype_Physics_ClientFrame(this, movedt);
else
+ {
+ // this doesn't apply to clients, and only applies to unmatched entities
+ // don't run think/move on newly spawned projectiles as it messes up
+ // movement interpolation and rocket trails, and is inconsistent with
+ // respect to entities spawned in the same frame
+ // (if an ent spawns a higher numbered ent, it moves in the same frame,
+ // but if it spawns a lower numbered ent, it doesn't - this never moves
+ // ents in the first frame regardless)
+ if(!didmove && GAMEPLAYFIX_DELAYPROJECTILES(this) > 0)
+ return;
_Movetype_Physics_Frame(this, movedt);
+ }
if(wasfreed(this))
return;
#define GAMEPLAYFIX_NOAIRBORNCORPSE(s) STAT(GAMEPLAYFIX_NOAIRBORNCORPSE)
#define NOAIRBORNCORPSE_ALLOWSUSPENDED(s) STAT(NOAIRBORNCORPSE_ALLOWSUSPENDED)
#define UPWARD_VELOCITY_CLEARS_ONGROUND(s) STAT(GAMEPLAYFIX_UPVELOCITYCLEARSONGROUND)
+#define GAMEPLAYFIX_DELAYPROJECTILES(s) STAT(GAMEPLAYFIX_DELAYPROJECTILES)
#define PHYS_STEPHEIGHT(s) STAT(MOVEVARS_STEPHEIGHT)
const int MOVETYPE_PHYSICS = 32;
const int MOVETYPE_FLY_WORLDONLY = 33;
-const int FL_ITEM = 256;
-const int FL_ONGROUND = 512;
#elif defined(SVQC)
const int MOVETYPE_ANGLENOCLIP = 1;
const int MOVETYPE_ANGLECLIP = 2;
const int MOVETYPE_QCPLAYER = 150; // QC-driven player physics, no think functions!
const int MOVETYPE_QCENTITY = 151; // QC-driven entity physics, some think functions!
-const int FL_ONSLICK = BIT(20);
-
const int MOVETYPE_FAKEPUSH = 13;
const int MOVEFLAG_VALID = BIT(23);
#ifdef SVQC
+#include <server/client.qh>
#include <server/miscfunctions.qh>
+#include <common/mapobjects/defs.qh>
#include "../mapobjects/trigger/viewloc.qh"
+#include <server/main.qh>
// client side physics
bool Physics_Valid(string thecvar)
STAT(MOVEVARS_HIGHSPEED, this) = autocvar_g_movement_highspeed;
MUTATOR_CALLHOOK(PlayerPhysics_UpdateStats, this);
- float maxspd_mod = PHYS_HIGHSPEED(this) * ((this.swampslug.active) ? this.swampslug.swamp_slowdown : 1);
+ float maxspd_mod = PHYS_HIGHSPEED(this) * ((this.swampslug.active == ACTIVE_ACTIVE) ? this.swampslug.swamp_slowdown : 1);
STAT(MOVEVARS_MAXSPEED, this) = Physics_ClientOption(this, "maxspeed", autocvar_sv_maxspeed) * maxspd_mod; // also slow walking
if (autocvar_g_movement_highspeed_q3_compat) {
STAT(MOVEVARS_AIRACCEL_QW, this) = Physics_ClientOption(this, "airaccel_qw", autocvar_sv_airaccel_qw);
#define WAS_ONGROUND(s) boolean((s).lastflags & FL_ONGROUND)
#define WAS_ONSLICK(s) boolean((s).lastflags & FL_ONSLICK)
+#define IS_DUCKED(s) (boolean((s).flags & FL_DUCKED))
+#define SET_DUCKED(s) ((s).flags |= FL_DUCKED)
+#define UNSET_DUCKED(s) ((s).flags &= ~FL_DUCKED)
+
#define ITEMS_STAT(s) ((s).items)
.float teleport_time;
string autocvar_cl_jumpspeedcap_min;
string autocvar_cl_jumpspeedcap_max;
- const int FL_WATERJUMP = 2048; // player jumping out of water
- const int FL_JUMPRELEASED = 4096; // for jump debouncing
-
.float watertype;
.float waterlevel;
.int items;
#define PHYS_INPUT_BUTTON_BUTTON15(s) boolean(input_buttons & BIT(17))
#define PHYS_INPUT_BUTTON_BUTTON16(s) boolean(input_buttons & BIT(18))
- #define IS_DUCKED(s) (boolean((s).flags & FL_DUCKED))
- #define SET_DUCKED(s) ((s).flags |= FL_DUCKED)
- #define UNSET_DUCKED(s) ((s).flags &= ~FL_DUCKED)
-
#define PHYS_INVEHICLE(s) (boolean(hud != HUD_NORMAL))
#define PHYS_JUMPSPEEDCAP_MIN autocvar_cl_jumpspeedcap_min
.string jumpspeedcap_min;
.string jumpspeedcap_max;
+ // footstep interval
+ .float nextstep;
+
#define PHYS_INPUT_ANGLES(s) ((s).v_angle)
#define PHYS_WORLD_ANGLES(s) ((s).angles)
#define PHYS_INPUT_BUTTON_BUTTON15(s) (CS(s).button15)
#define PHYS_INPUT_BUTTON_BUTTON16(s) (CS(s).button16)
- #define IS_DUCKED(s) ((s).crouch)
- #define SET_DUCKED(s) ((s).crouch = true)
- #define UNSET_DUCKED(s) ((s).crouch = false)
-
#define PHYS_INVEHICLE(s) (boolean((s).vehicle != NULL))
#define PHYS_JUMPSPEEDCAP_MIN autocvar_sv_jumpspeedcap_min
#include "constants.qh"
#include "util.qh"
#include <common/weapons/_all.qh>
+ #include <server/client.qh>
#include "../server/anticheat.qh"
- #include "../server/defs.qh"
+ #include <common/stats.qh>
#include "../server/scores.qh"
+ #include <server/world.qh>
#include "../server/weapons/accuracy.qh"
#endif
* G: game type
* O: mod name (icon request) as in server browser
* M: map name
- * I: match ID (see "matchid" in g_world.qc)
+ * I: match ID (see "matchid" in world.qc)
* S: "hostname" of the server
* C: number of "unpure" cvar changes
* U: UDP port number of the server
--- /dev/null
+#include "replicate.qh"
--- /dev/null
+#pragma once
+
+// TODO: sort/merge these!
+#if defined(CSQC)
+ float autoswitch;
+ bool cvar_cl_allow_uid2name;
+ float cvar_cl_allow_uidtracking;
+ bool cvar_cl_allow_uidranking;
+ float cvar_cl_autoscreenshot;
+ float cvar_cl_autotaunt;
+ float cvar_cl_clippedspectating;
+ int cvar_cl_gunalign;
+ float cvar_cl_handicap;
+ float cvar_cl_jetpack_jump;
+ float cvar_cl_movement_track_canjump;
+ float cvar_cl_noantilag;
+ string cvar_cl_physics;
+ float cvar_cl_voice_directional;
+ float cvar_cl_voice_directional_taunt_attenuation;
+ float cvar_cl_weaponimpulsemode;
+
+ string cvar_g_xonoticversion;
+ string cvar_cl_weaponpriority;
+ string cvar_cl_weaponpriorities[10];
+ float cvar_cl_cts_noautoswitch;
+ bool cvar_cl_weapon_switch_reload;
+ bool cvar_cl_weapon_switch_fallback_to_impulse;
+#elif defined(SVQC)
+ .float cvar_cl_handicap;
+ .int cvar_cl_gunalign;
+ .float cvar_cl_clippedspectating;
+ .float cvar_cl_autoscreenshot;
+ .float cvar_cl_jetpack_jump;
+ .float cvar_cl_movement_track_canjump;
+ //.float cvar_cl_newusekeysupported;
+ .float cvar_cl_cts_noautoswitch;
+ .bool cvar_cl_weapon_switch_reload;
+ .bool cvar_cl_weapon_switch_fallback_to_impulse;
+
+ .string cvar_g_xonoticversion;
+ .string cvar_cl_weaponpriority;
+ .string cvar_cl_weaponpriorities[10];
+ .float cvar_cl_noantilag;
+
+ // WEAPONTODO
+ .float autoswitch;
+ .float cvar_cl_weaponimpulsemode;
+
+ .float cvar_cl_allow_uid2name;
+ .float cvar_cl_allow_uidtracking;
+ .bool cvar_cl_allow_uidranking;
+
+ .string cvar_cl_physics;
+
+ // autotaunt system
+ .float cvar_cl_autotaunt;
+ .float cvar_cl_voice_directional;
+ .float cvar_cl_voice_directional_taunt_attenuation;
+#endif
+
+#ifdef GAMEQC
+REPLICATE(autoswitch, bool, "cl_autoswitch");
+REPLICATE(cvar_cl_allow_uid2name, bool, "cl_allow_uid2name");
+REPLICATE(cvar_cl_allow_uidranking, bool, "cl_allow_uidranking");
+REPLICATE(cvar_cl_autoscreenshot, int, "cl_autoscreenshot");
+REPLICATE(cvar_cl_autotaunt, float, "cl_autotaunt");
+REPLICATE(cvar_cl_clippedspectating, bool, "cl_clippedspectating");
+REPLICATE(cvar_cl_gunalign, int, "cl_gunalign");
+REPLICATE(cvar_cl_handicap, float, "cl_handicap");
+REPLICATE(cvar_cl_jetpack_jump, bool, "cl_jetpack_jump");
+REPLICATE(cvar_cl_movement_track_canjump, bool, "cl_movement_track_canjump");
+REPLICATE(cvar_cl_noantilag, bool, "cl_noantilag");
+REPLICATE(cvar_cl_physics, string, "cl_physics");
+REPLICATE(cvar_cl_voice_directional, int, "cl_voice_directional");
+REPLICATE(cvar_cl_voice_directional_taunt_attenuation, float, "cl_voice_directional_taunt_attenuation");
+REPLICATE(cvar_cl_weaponimpulsemode, int, "cl_weaponimpulsemode");
+REPLICATE(cvar_g_xonoticversion, string, "g_xonoticversion");
+REPLICATE(cvar_cl_cts_noautoswitch, bool, "cl_cts_noautoswitch");
+REPLICATE(cvar_cl_weapon_switch_reload, bool, "cl_weapon_switch_reload");
+REPLICATE(cvar_cl_weapon_switch_fallback_to_impulse, bool, "cl_weapon_switch_fallback_to_impulse");
+/*
+// cvar cl_newusekeysupported doesn't exist
+float cvar_cl_newusekeysupported;
+REPLICATE(cvar_cl_newusekeysupported, bool, "cl_newusekeysupported");
+*/
+#ifdef CSQC
+// handled specially on the server
+REPLICATE(cvar_cl_allow_uidtracking, float, "cl_allow_uidtracking");
+#endif
+
+REPLICATE(cvar_cl_weaponpriority, string, "cl_weaponpriority");
+
+REPLICATE(cvar_cl_weaponpriorities[0], string, "cl_weaponpriority0");
+REPLICATE(cvar_cl_weaponpriorities[1], string, "cl_weaponpriority1");
+REPLICATE(cvar_cl_weaponpriorities[2], string, "cl_weaponpriority2");
+REPLICATE(cvar_cl_weaponpriorities[3], string, "cl_weaponpriority3");
+REPLICATE(cvar_cl_weaponpriorities[4], string, "cl_weaponpriority4");
+REPLICATE(cvar_cl_weaponpriorities[5], string, "cl_weaponpriority5");
+REPLICATE(cvar_cl_weaponpriorities[6], string, "cl_weaponpriority6");
+REPLICATE(cvar_cl_weaponpriorities[7], string, "cl_weaponpriority7");
+REPLICATE(cvar_cl_weaponpriorities[8], string, "cl_weaponpriority8");
+REPLICATE(cvar_cl_weaponpriorities[9], string, "cl_weaponpriority9");
+#endif
#ifdef SVQC
#include <server/autocvars.qh>
#include <server/client.qh>
+#include <common/mapobjects/trigger/secret.qh>
#endif
// Full list of all stat constants, included in a single location for easy reference
#ifdef SVQC
float W_WeaponRateFactor(entity this);
float game_stopped;
-float game_starttime;
-float round_starttime;
+float game_starttime; //point in time when the countdown to game start is over
+float round_starttime; //point in time when the countdown to round start is over
bool autocvar_g_allow_oldvortexbeam;
int autocvar_leadlimit;
#endif
REGISTER_STAT(VEHICLESTAT_RELOAD2, int)
REGISTER_STAT(VEHICLESTAT_W2MODE, int)
REGISTER_STAT(NADE_TIMER, float)
-REGISTER_STAT(SECRETS_TOTAL, float)
-REGISTER_STAT(SECRETS_FOUND, float)
+REGISTER_STAT(SECRETS_TOTAL, int, secrets_total)
+REGISTER_STAT(SECRETS_FOUND, int, secrets_found)
REGISTER_STAT(RESPAWN_TIME, float)
REGISTER_STAT(ROUNDSTARTTIME, float, round_starttime)
REGISTER_STAT(MONSTERS_TOTAL, int)
int autocvar_sv_gameplayfix_grenadebouncedownslopes = 1;
int autocvar_sv_gameplayfix_noairborncorpse = 1;
int autocvar_sv_gameplayfix_noairborncorpse_allowsuspendeditems = 1;
+int autocvar_sv_gameplayfix_delayprojectiles = 0;
#endif
REGISTER_STAT(GAMEPLAYFIX_DOWNTRACEONGROUND, int, autocvar_sv_gameplayfix_downtracesupportsongroundflag)
REGISTER_STAT(GAMEPLAYFIX_EASIERWATERJUMP, int, autocvar_sv_gameplayfix_easierwaterjump)
REGISTER_STAT(GAMEPLAYFIX_GRENADEBOUNCESLOPES, int, autocvar_sv_gameplayfix_grenadebouncedownslopes)
REGISTER_STAT(GAMEPLAYFIX_NOAIRBORNCORPSE, int, autocvar_sv_gameplayfix_noairborncorpse)
REGISTER_STAT(NOAIRBORNCORPSE_ALLOWSUSPENDED, int, autocvar_sv_gameplayfix_noairborncorpse_allowsuspendeditems)
+REGISTER_STAT(GAMEPLAYFIX_DELAYPROJECTILES, int, autocvar_sv_gameplayfix_delayprojectiles)
REGISTER_STAT(MOVEVARS_JUMPSTEP, int, cvar("sv_jumpstep"))
REGISTER_STAT(NOSTEP, int, cvar("sv_nostep"))
+++ /dev/null
-#include "t_items.qh"
-
-#include "items/_mod.qh"
-
-#if defined(SVQC)
-
- #include "../server/bot/api.qh"
-
- #include <server/mutators/_mod.qh>
-
- #include "../server/weapons/common.qh"
- #include "../server/weapons/selection.qh"
- #include "../server/weapons/weaponsystem.qh"
-
- #include "constants.qh"
- #include <common/deathtypes/all.qh>
- #include <common/notifications/all.qh>
- #include "mapobjects/subs.qh"
- #include "util.qh"
-
- #include <common/monsters/_mod.qh>
-
- #include <common/weapons/_all.qh>
-
- #include <common/mutators/mutator/buffs/buffs.qh>
- #include <common/mutators/mutator/buffs/sv_buffs.qh>
-
- #include "../lib/warpzone/util_server.qh"
-#elif defined(CSQC)
- #include "physics/movetypes/movetypes.qh"
- #include <common/weapons/_all.qh>
- #include "../lib/csqcmodel/cl_model.qh"
- #include "../lib/csqcmodel/common.qh"
-#endif
-
-REGISTER_NET_LINKED(ENT_CLIENT_ITEM)
-
-#ifdef CSQC
-bool autocvar_cl_ghost_items_vehicle = true;
-.vector item_glowmod;
-.bool item_simple; // probably not really needed, but better safe than sorry
-void Item_SetAlpha(entity this)
-{
- bool veh_hud = (hud && autocvar_cl_ghost_items_vehicle);
-
- if(!veh_hud && (this.ItemStatus & ITS_AVAILABLE))
- {
- this.alpha = 1;
- this.colormod = '1 1 1';
- this.glowmod = this.item_glowmod;
- }
- else
- {
- this.alpha = autocvar_cl_ghost_items;
- this.colormod = this.glowmod = autocvar_cl_ghost_items_color;
- }
-
- if((!veh_hud) && (this.ItemStatus & ITS_STAYWEP))
- {
- this.colormod = this.glowmod = autocvar_cl_weapon_stay_color;
- this.alpha = autocvar_cl_weapon_stay_alpha;
- }
-
- this.drawmask = ((this.alpha <= 0) ? 0 : MASK_NORMAL);
-}
-
-void ItemDraw(entity this)
-{
- if(this.gravity)
- {
- Movetype_Physics_MatchServer(this, false);
- if(IS_ONGROUND(this))
- { // For some reason avelocity gets set to '0 0 0' here ...
- this.oldorigin = this.origin;
- this.gravity = 0;
-
- if(autocvar_cl_animate_items)
- { // ... so reset it if animations are requested.
- if(this.ItemStatus & ITS_ANIMATE1)
- this.avelocity = '0 180 0';
-
- if(this.ItemStatus & ITS_ANIMATE2)
- this.avelocity = '0 -90 0';
- }
-
- // delay is for blocking item's position for a while;
- // it's a workaround for dropped weapons that receive the position
- // another time right after they spawn overriding animation position
- this.onground_time = time + 0.5;
- }
- }
- else if (autocvar_cl_animate_items && !this.item_simple) // no bobbing applied to simple items, for consistency's sake (no visual difference between ammo and weapons)
- {
- if(this.ItemStatus & ITS_ANIMATE1)
- {
- this.angles += this.avelocity * frametime;
- float fade_in = bound(0, time - this.onground_time, 1);
- setorigin(this, this.oldorigin + fade_in * ('0 0 10' + '0 0 8' * sin((time - this.onground_time) * 2)));
- }
-
- if(this.ItemStatus & ITS_ANIMATE2)
- {
- this.angles += this.avelocity * frametime;
- float fade_in = bound(0, time - this.onground_time, 1);
- setorigin(this, this.oldorigin + fade_in * ('0 0 8' + '0 0 4' * sin((time - this.onground_time) * 3)));
- }
- }
-
- Item_SetAlpha(this);
-}
-
-void Item_PreDraw(entity this)
-{
- if(warpzone_warpzones_exist)
- {
- setpredraw(this, func_null); // no need to keep running this
- return;
- }
- float alph;
- vector org = getpropertyvec(VF_ORIGIN);
- //if(!checkpvs(org, this)) // this makes sense as long as we don't support recursive warpzones
- //alph = 0; // this shouldn't be needed, since items behind walls are culled anyway
- if(this.fade_start)
- {
- if(vdist(org - this.origin, >, this.fade_end))
- alph = 0; // save on some processing
- else if(vdist(org - this.origin, <, this.fade_start))
- alph = 1; // more processing saved
- else
- alph = bound(0, (this.fade_end - vlen(org - this.origin - 0.5 * (this.mins + this.maxs))) / (this.fade_end - this.fade_start), 1);
- }
- else
- alph = 1;
- //printf("%v <-> %v\n", view_origin, this.origin + 0.5 * (this.mins + this.maxs));
- if(!hud && (this.ItemStatus & ITS_AVAILABLE))
- this.alpha = alph;
- if(alph <= 0)
- this.drawmask = 0;
- //else
- //this.drawmask = MASK_NORMAL; // reset by the setalpha function
-}
-
-void ItemRemove(entity this)
-{
- strfree(this.mdl);
-}
-
-HashMap ENT_CLIENT_ITEM_simple;
-STATIC_INIT(ENT_CLIENT_ITEM_simple)
-{
- HM_NEW(ENT_CLIENT_ITEM_simple);
-}
-SHUTDOWN(ENT_CLIENT_ITEM_simple)
-{
- HM_DELETE(ENT_CLIENT_ITEM_simple);
-}
-
-NET_HANDLE(ENT_CLIENT_ITEM, bool isnew)
-{
- int sf = ReadByte();
-
- if(sf & ISF_LOCATION)
- {
- this.origin = ReadVector();
- setorigin(this, this.origin);
- this.oldorigin = this.origin;
- }
-
- if(sf & ISF_ANGLES)
- {
- this.angles_x = ReadAngle();
- this.angles_y = ReadAngle();
- this.angles_z = ReadAngle();
- }
-
- if(sf & ISF_SIZE)
- {
- setsize(this, '-16 -16 0', '16 16 48');
- }
-
- if(sf & ISF_STATUS) // need to read/write status first so model can handle simple, fb etc.
- {
- this.ItemStatus = ReadByte();
-
- Item_SetAlpha(this);
-
- if(this.ItemStatus & ITS_ALLOWFB)
- this.effects |= EF_FULLBRIGHT;
- else
- this.effects &= ~EF_FULLBRIGHT;
-
- if(this.ItemStatus & ITS_GLOW)
- {
- if(this.ItemStatus & ITS_AVAILABLE)
- this.effects |= (EF_ADDITIVE | EF_FULLBRIGHT);
- else
- this.effects &= ~(EF_ADDITIVE | EF_FULLBRIGHT);
- }
- }
-
- if(sf & ISF_MODEL)
- {
- this.drawmask = MASK_NORMAL;
- set_movetype(this, MOVETYPE_TOSS);
- if (isnew) IL_PUSH(g_drawables, this);
- this.draw = ItemDraw;
- this.solid = SOLID_TRIGGER;
- //this.flags |= FL_ITEM;
-
- this.fade_end = ReadShort();
- this.fade_start = ReadShort();
- if(!warpzone_warpzones_exist && this.fade_start && !autocvar_cl_items_nofade)
- setpredraw(this, Item_PreDraw);
-
- strfree(this.mdl);
-
- string _fn = ReadString();
- this.item_simple = false; // reset it!
-
- if(autocvar_cl_simple_items && (this.ItemStatus & ITS_ALLOWSI))
- {
- string _fn2 = substring(_fn, 0 , strlen(_fn) -4);
- this.item_simple = true;
-
- #define extensions(x) \
- x(md3) \
- x(dpm) \
- x(iqm) \
- x(mdl) \
- /**/
- #define tryext(ext) { \
- string s = strcat(_fn2, autocvar_cl_simpleitems_postfix, "." #ext); \
- string cached = HM_gets(ENT_CLIENT_ITEM_simple, s); \
- if (cached == "") { \
- HM_sets(ENT_CLIENT_ITEM_simple, s, cached = fexists(s) ? "1" : "0"); \
- } \
- if (cached != "0") { \
- strcpy(this.mdl, s); \
- break; \
- } \
- }
- do {
- extensions(tryext);
- this.item_simple = false;
- LOG_TRACEF("Simple item requested for %s but no model exists for it", _fn);
- } while (0);
- #undef tryext
- #undef extensions
- }
-
- if(!this.item_simple)
- strcpy(this.mdl, _fn);
-
- if(this.mdl == "")
- LOG_WARNF("this.mdl is unset for item %s", this.classname);
-
- precache_model(this.mdl);
- _setmodel(this, this.mdl);
-
- setsize(this, '-16 -16 0', '16 16 48');
- }
-
- if(sf & ISF_COLORMAP)
- {
- this.colormap = ReadShort();
- this.item_glowmod_x = ReadByte() / 255.0;
- this.item_glowmod_y = ReadByte() / 255.0;
- this.item_glowmod_z = ReadByte() / 255.0;
- }
-
- if(sf & ISF_DROP)
- {
- this.gravity = 1;
- this.pushable = true;
- //this.angles = '0 0 0';
- set_movetype(this, MOVETYPE_TOSS);
- this.velocity = ReadVector();
- setorigin(this, this.oldorigin);
-
- if(!this.move_time)
- {
- this.move_time = time;
- this.spawntime = time;
- }
- else
- this.move_time = max(this.move_time, time);
- }
-
- if(autocvar_cl_animate_items)
- {
- if(this.ItemStatus & ITS_ANIMATE1)
- this.avelocity = '0 180 0';
-
- if(this.ItemStatus & ITS_ANIMATE2)
- this.avelocity = '0 -90 0';
- }
-
- this.entremove = ItemRemove;
-
- return true;
-}
-
-#endif
-
-#ifdef SVQC
-bool ItemSend(entity this, entity to, int sf)
-{
- if(this.gravity)
- sf |= ISF_DROP;
- else
- sf &= ~ISF_DROP;
-
- WriteHeader(MSG_ENTITY, ENT_CLIENT_ITEM);
- WriteByte(MSG_ENTITY, sf);
-
- //WriteByte(MSG_ENTITY, this.cnt);
- if(sf & ISF_LOCATION)
- {
- WriteVector(MSG_ENTITY, this.origin);
- }
-
- if(sf & ISF_ANGLES)
- {
- WriteAngle(MSG_ENTITY, this.angles_x);
- WriteAngle(MSG_ENTITY, this.angles_y);
- WriteAngle(MSG_ENTITY, this.angles_z);
- }
-
- // sets size on the client, unused on server
- //if(sf & ISF_SIZE)
-
- if(sf & ISF_STATUS)
- WriteByte(MSG_ENTITY, this.ItemStatus);
-
- if(sf & ISF_MODEL)
- {
- WriteShort(MSG_ENTITY, this.fade_end);
- WriteShort(MSG_ENTITY, this.fade_start);
-
- if(this.mdl == "")
- LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "expect a crash just about now");
-
- WriteString(MSG_ENTITY, this.mdl);
- }
-
-
- if(sf & ISF_COLORMAP)
- {
- WriteShort(MSG_ENTITY, this.colormap);
- WriteByte(MSG_ENTITY, this.glowmod.x * 255.0);
- WriteByte(MSG_ENTITY, this.glowmod.y * 255.0);
- WriteByte(MSG_ENTITY, this.glowmod.z * 255.0);
- }
-
- if(sf & ISF_DROP)
- {
- WriteVector(MSG_ENTITY, this.velocity);
- }
-
- return true;
-}
-
-void ItemUpdate(entity this)
-{
- this.oldorigin = this.origin;
- this.SendFlags |= ISF_LOCATION;
-}
-
-void UpdateItemAfterTeleport(entity this)
-{
- if(getSendEntity(this) == ItemSend)
- ItemUpdate(this);
-}
-
-bool have_pickup_item(entity this)
-{
- if(this.itemdef.instanceOfPowerup)
- {
- if(autocvar_g_powerups > 0)
- return true;
- if(autocvar_g_powerups == 0)
- return false;
- }
- else
- {
- if(autocvar_g_pickup_items > 0)
- return true;
- if(autocvar_g_pickup_items == 0)
- return false;
- if(g_weaponarena)
- if(STAT(WEAPONS, this) || this.itemdef.instanceOfAmmo) // no item or ammo pickups in weaponarena
- return false;
- }
- return true;
-}
-
-void Item_Show(entity e, int mode)
-{
- e.effects &= ~(EF_ADDITIVE | EF_STARDUST | EF_FULLBRIGHT | EF_NODEPTHTEST);
- e.ItemStatus &= ~ITS_STAYWEP;
- entity def = e.itemdef;
- if (mode > 0)
- {
- // make the item look normal, and be touchable
- e.model = e.mdl;
- e.solid = SOLID_TRIGGER;
- e.spawnshieldtime = 1;
- e.ItemStatus |= ITS_AVAILABLE;
- }
- else if (mode < 0)
- {
- // hide the item completely
- e.model = string_null;
- e.solid = SOLID_NOT;
- e.spawnshieldtime = 1;
- e.ItemStatus &= ~ITS_AVAILABLE;
- }
- else
- {
- bool nostay = def.instanceOfWeaponPickup ? !!(def.m_weapon.m_wepset & WEPSET_SUPERWEAPONS) : false // no weapon-stay on superweapons
- || e.team // weapon stay isn't supported for teamed weapons
- ;
- if(def.instanceOfWeaponPickup && !nostay && g_weapon_stay)
- {
- // make the item translucent and not touchable
- e.model = e.mdl;
- e.solid = SOLID_TRIGGER; // can STILL be picked up!
- e.effects |= EF_STARDUST;
- e.spawnshieldtime = 0; // field indicates whether picking it up may give you anything other than the weapon
- e.ItemStatus |= (ITS_AVAILABLE | ITS_STAYWEP);
- }
- else
- {
- //setmodel(e, "null");
- e.solid = SOLID_NOT;
- e.colormod = '0 0 0';
- //e.glowmod = e.colormod;
- e.spawnshieldtime = 1;
- e.ItemStatus &= ~ITS_AVAILABLE;
- }
- }
-
- if (def.m_glow)
- e.ItemStatus |= ITS_GLOW;
-
- if (autocvar_g_nodepthtestitems)
- e.effects |= EF_NODEPTHTEST;
-
- if (autocvar_g_fullbrightitems)
- e.ItemStatus |= ITS_ALLOWFB;
- else
- e.ItemStatus &= ~ITS_ALLOWFB;
-
- if (autocvar_sv_simple_items)
- e.ItemStatus |= ITS_ALLOWSI;
-
- // relink entity (because solid may have changed)
- setorigin(e, e.origin);
- e.SendFlags |= ISF_STATUS;
-}
-
-void Item_Think(entity this)
-{
- this.nextthink = time;
- if(this.origin != this.oldorigin)
- ItemUpdate(this);
-}
-
-bool Item_ItemsTime_SpectatorOnly(GameItem it);
-bool Item_ItemsTime_Allow(GameItem it);
-float Item_ItemsTime_UpdateTime(entity e, float t);
-void Item_ItemsTime_SetTime(entity e, float t);
-void Item_ItemsTime_SetTimesForAllPlayers();
-
-void Item_Respawn(entity this)
-{
- Item_Show(this, 1);
- sound(this, CH_TRIGGER, this.itemdef.m_respawnsound, VOL_BASE, ATTEN_NORM); // play respawn sound
- setorigin(this, this.origin);
-
- if (Item_ItemsTime_Allow(this.itemdef) || (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS))
- {
- float t = Item_ItemsTime_UpdateTime(this, 0);
- Item_ItemsTime_SetTime(this, t);
- Item_ItemsTime_SetTimesForAllPlayers();
- }
-
- setthink(this, Item_Think);
- this.nextthink = time;
-
- //Send_Effect(EFFECT_ITEM_RESPAWN, this.origin + this.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1);
- Send_Effect(EFFECT_ITEM_RESPAWN, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
-}
-
-void Item_RespawnCountdown(entity this)
-{
- if(this.item_respawncounter >= ITEM_RESPAWN_TICKS)
- {
- if(this.waypointsprite_attached)
- WaypointSprite_Kill(this.waypointsprite_attached);
- Item_Respawn(this);
- }
- else
- {
- this.nextthink = time + 1;
- this.item_respawncounter += 1;
- if(this.item_respawncounter == 1)
- {
- do {
- {
- entity wi = REGISTRY_GET(Weapons, this.weapon);
- if (wi != WEP_Null) {
- entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, this, '0 0 64', NULL, 0, this, waypointsprite_attached, true, RADARICON_Weapon);
- wp.wp_extra = wi.m_id;
- break;
- }
- }
- {
- entity ii = this.itemdef;
- if (ii != NULL) {
- entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, this, '0 0 64', NULL, 0, this, waypointsprite_attached, true, RADARICON_Item);
- wp.wp_extra = ii.m_id;
- break;
- }
- }
- } while (0);
- bool mutator_returnvalue = MUTATOR_CALLHOOK(Item_RespawnCountdown, this);
- if(this.waypointsprite_attached)
- {
- GameItem def = this.itemdef;
- if (Item_ItemsTime_SpectatorOnly(def) && !mutator_returnvalue)
- WaypointSprite_UpdateRule(this.waypointsprite_attached, 0, SPRITERULE_SPECTATOR);
- WaypointSprite_UpdateBuildFinished(this.waypointsprite_attached, time + ITEM_RESPAWN_TICKS);
- }
- }
-
- if(this.waypointsprite_attached)
- {
- FOREACH_CLIENT(IS_REAL_CLIENT(it), {
- if(this.waypointsprite_attached.waypointsprite_visible_for_player(this.waypointsprite_attached, it, it))
- {
- msg_entity = it;
- soundto(MSG_ONE, this, CH_TRIGGER, SND(ITEMRESPAWNCOUNTDOWN), VOL_BASE, ATTEN_NORM, 0); // play respawn sound
- }
- });
-
- WaypointSprite_Ping(this.waypointsprite_attached);
- //WaypointSprite_UpdateHealth(this.waypointsprite_attached, this.item_respawncounter);
- }
- }
-}
-
-void Item_RespawnThink(entity this)
-{
- this.nextthink = time;
- if(this.origin != this.oldorigin)
- ItemUpdate(this);
-
- if(time >= this.wait)
- Item_Respawn(this);
-}
-
-void Item_ScheduleRespawnIn(entity e, float t)
-{
- // if the respawn time is longer than 10 seconds, show a waypoint, otherwise, just respawn normally
- if ((Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS) || MUTATOR_CALLHOOK(Item_ScheduleRespawn, e, t)) && (t - ITEM_RESPAWN_TICKS) > 0)
- {
- setthink(e, Item_RespawnCountdown);
- e.nextthink = time + max(0, t - ITEM_RESPAWN_TICKS);
- e.scheduledrespawntime = e.nextthink + ITEM_RESPAWN_TICKS;
- e.item_respawncounter = 0;
- if(Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
- {
- t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime);
- Item_ItemsTime_SetTime(e, t);
- Item_ItemsTime_SetTimesForAllPlayers();
- }
- }
- else
- {
- setthink(e, Item_RespawnThink);
- e.nextthink = time;
- e.scheduledrespawntime = time + t;
- e.wait = time + t;
-
- if(Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
- {
- t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime);
- Item_ItemsTime_SetTime(e, t);
- Item_ItemsTime_SetTimesForAllPlayers();
- }
- }
-}
-
-AUTOCVAR(g_pickup_respawntime_scaling_reciprocal, float, 0.0, "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `reciprocal` (with `offset` and `linear` set to 0) can be used to achieve a constant number of items spawned *per player*");
-AUTOCVAR(g_pickup_respawntime_scaling_offset, float, 0.0, "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `offset` offsets the curve left or right - the results are not intuitive and I recommend plotting the respawn time and the number of items per player to see what's happening");
-AUTOCVAR(g_pickup_respawntime_scaling_linear, float, 1.0, "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `linear` can be used to simply scale the respawn time linearly");
-
-/// Adjust respawn time according to the number of players.
-float adjust_respawntime(float normal_respawntime) {
- float r = autocvar_g_pickup_respawntime_scaling_reciprocal;
- float o = autocvar_g_pickup_respawntime_scaling_offset;
- float l = autocvar_g_pickup_respawntime_scaling_linear;
-
- if (r == 0 && l == 1) {
- return normal_respawntime;
- }
-
- entity balance = TeamBalance_CheckAllowedTeams(NULL);
- TeamBalance_GetTeamCounts(balance, NULL);
- int players = 0;
- 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 {
- return normal_respawntime;
- }
-}
-
-void Item_ScheduleRespawn(entity e)
-{
- if(e.respawntime > 0)
- {
- Item_Show(e, 0);
-
- float adjusted_respawntime = adjust_respawntime(e.respawntime);
- //LOG_INFOF("item %s will respawn in %f", e.classname, adjusted_respawntime);
-
- // range: adjusted_respawntime - respawntimejitter .. adjusted_respawntime + respawntimejitter
- float respawn_in = adjusted_respawntime + crandom() * e.respawntimejitter;
- Item_ScheduleRespawnIn(e, respawn_in);
- }
- else // if respawntime is -1, this item does not respawn
- Item_Show(e, -1);
-}
-
-AUTOCVAR(g_pickup_respawntime_initial_random, int, 1,
- "For items that don't start spawned: 0: spawn after their normal respawntime; 1: spawn after `random * respawntime` with the *same* random; 2: same as 1 but each item has separate random");
-
-void Item_ScheduleInitialRespawn(entity e)
-{
- Item_Show(e, 0);
-
- float spawn_in;
- if (autocvar_g_pickup_respawntime_initial_random == 0)
- {
- // range: respawntime .. respawntime + respawntimejitter
- spawn_in = e.respawntime + random() * e.respawntimejitter;
- }
- else
- {
- float rnd;
- if (autocvar_g_pickup_respawntime_initial_random == 1)
- {
- static float shared_random = 0;
- // NOTE this code works only if items are scheduled at the same time (normal case)
- // NOTE2 random() can't return exactly 1 so this check always work as intended
- if (!shared_random || floor(time) > shared_random)
- shared_random = floor(time) + random();
- rnd = shared_random - floor(time);
- }
- else
- rnd = random();
-
- // range:
- // if respawntime >= ITEM_RESPAWN_TICKS: ITEM_RESPAWN_TICKS .. respawntime + respawntimejitter
- // else: 0 .. ITEM_RESPAWN_TICKS
- // this is to prevent powerups spawning unexpectedly without waypoints
- spawn_in = ITEM_RESPAWN_TICKS + rnd * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
- }
-
- Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : spawn_in));
-}
-
-void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names,
- entity ammo_entity)
-{
- if (num_weapons == 0)
- {
- return;
- }
- int num_potential_weapons = tokenize_console(weapon_names);
- for (int give_attempt = 0; give_attempt < num_weapons; ++give_attempt)
- {
- RandomSelection_Init();
- for (int weapon_index = 0; weapon_index < num_potential_weapons;
- ++weapon_index)
- {
- string weapon = argv(weapon_index);
- FOREACH(Weapons, it != WEP_Null,
- {
- // Finding a weapon which player doesn't have.
- if (!(STAT(WEAPONS, receiver) & it.m_wepset) && (it.netname == weapon))
- {
- RandomSelection_AddEnt(it, 1, 1);
- break;
- }
- });
- }
- if (RandomSelection_chosen_ent == NULL)
- {
- return;
- }
- STAT(WEAPONS, receiver) |= RandomSelection_chosen_ent.m_wepset;
- if (RandomSelection_chosen_ent.ammo_type == RES_NONE)
- {
- continue;
- }
- if (GetResource(receiver,
- RandomSelection_chosen_ent.ammo_type) != 0)
- {
- continue;
- }
- GiveResource(receiver, RandomSelection_chosen_ent.ammo_type,
- GetResource(ammo_entity,
- RandomSelection_chosen_ent.ammo_type));
- }
-}
-
-bool Item_GiveAmmoTo(entity item, entity player, int res_type, float ammomax)
-{
- float amount = GetResource(item, res_type);
- if (amount == 0)
- {
- return false;
- }
- float player_amount = GetResource(player, res_type);
- if (item.spawnshieldtime)
- {
- if ((player_amount >= ammomax) && (item.pickup_anyway <= 0))
- return false;
- }
- else if (g_weapon_stay == 2)
- {
- ammomax = min(amount, ammomax);
- if(player_amount >= ammomax)
- return false;
- }
- else
- return false;
- if (amount < 0)
- TakeResourceWithLimit(player, res_type, -amount, ammomax);
- else
- GiveResourceWithLimit(player, res_type, amount, ammomax);
- return true;
-}
-
-bool Item_GiveTo(entity item, entity player)
-{
- // if nothing happens to player, just return without taking the item
- int _switchweapon = 0;
- // in case the player has autoswitch enabled do the following:
- // if the player is using their best weapon before items are given, they
- // probably want to switch to an even better weapon after items are given
-
- if(CS(player).autoswitch)
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
- {
- if(player.(weaponentity).m_switchweapon == w_getbestweapon(player, weaponentity))
- _switchweapon |= BIT(slot);
-
- if(!(STAT(WEAPONS, player) & WepSet_FromWeapon(player.(weaponentity).m_switchweapon)))
- _switchweapon |= BIT(slot);
- }
- }
- }
- bool pickedup = false;
- pickedup |= Item_GiveAmmoTo(item, player, RES_HEALTH, item.max_health);
- pickedup |= Item_GiveAmmoTo(item, player, RES_ARMOR, item.max_armorvalue);
- pickedup |= Item_GiveAmmoTo(item, player, RES_SHELLS, g_pickup_shells_max);
- pickedup |= Item_GiveAmmoTo(item, player, RES_BULLETS, g_pickup_nails_max);
- pickedup |= Item_GiveAmmoTo(item, player, RES_ROCKETS, g_pickup_rockets_max);
- pickedup |= Item_GiveAmmoTo(item, player, RES_CELLS, g_pickup_cells_max);
- pickedup |= Item_GiveAmmoTo(item, player, RES_PLASMA, g_pickup_plasma_max);
- pickedup |= Item_GiveAmmoTo(item, player, RES_FUEL, g_pickup_fuel_max);
- if (item.itemdef.instanceOfWeaponPickup)
- {
- WepSet w;
- w = STAT(WEAPONS, item);
- w &= ~STAT(WEAPONS, player);
-
- if (w || (item.spawnshieldtime && item.pickup_anyway > 0))
- {
- pickedup = true;
- FOREACH(Weapons, it != WEP_Null, {
- if(w & (it.m_wepset))
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
- W_DropEvent(wr_pickup, player, it.m_id, item, weaponentity);
- }
- W_GiveWeapon(player, it.m_id);
- }
- });
- }
- }
-
- if (item.itemdef.instanceOfPowerup)
- {
- if ((item.itemdef == ITEM_JetpackRegen) && !(player.items & IT_FUEL_REGEN))
- Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_ITEM_FUELREGEN_GOT);
- else if ((item.itemdef == ITEM_Jetpack) && !(player.items & IT_JETPACK))
- Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_ITEM_JETPACK_GOT);
- }
-
- int its;
- if((its = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
- {
- pickedup = true;
- player.items |= its;
- // TODO: we probably want to show a message in the console, but not this one!
- //Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_ITEM_WEAPON_GOT, item.netname);
- }
-
- if (item.strength_finished)
- {
- pickedup = true;
- STAT(STRENGTH_FINISHED, player) = max(STAT(STRENGTH_FINISHED, player), time) + item.strength_finished;
- }
- if (item.invincible_finished)
- {
- pickedup = true;
- STAT(INVINCIBLE_FINISHED, player) = max(STAT(INVINCIBLE_FINISHED, player), time) + item.invincible_finished;
- }
- if (item.superweapons_finished)
- {
- pickedup = true;
- STAT(SUPERWEAPONS_FINISHED, player) = max(STAT(SUPERWEAPONS_FINISHED, player), time) + item.superweapons_finished;
- }
-
- // always eat teamed entities
- if(item.team)
- pickedup = true;
-
- if (!pickedup)
- return false;
-
- // crude hack to enforce switching weapons
- if(g_cts && item.itemdef.instanceOfWeaponPickup && !CS(player).cvar_cl_cts_noautoswitch)
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
- W_SwitchWeapon_Force(player, REGISTRY_GET(Weapons, item.weapon), weaponentity);
- }
- return true;
- }
-
- if(_switchweapon)
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(_switchweapon & BIT(slot))
- if(player.(weaponentity).m_switchweapon != w_getbestweapon(player, weaponentity))
- W_SwitchWeapon_Force(player, w_getbestweapon(player, weaponentity), weaponentity);
- }
- }
-
- return true;
-}
-
-void Item_Touch(entity this, entity toucher)
-{
- // remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
- if (Item_IsLoot(this))
- {
- if (ITEM_TOUCH_NEEDKILL())
- {
- delete(this);
- return;
- }
- }
-
- if(!(toucher.flags & FL_PICKUPITEMS)
- || STAT(FROZEN, toucher)
- || IS_DEAD(toucher)
- || (this.solid != SOLID_TRIGGER)
- || (this.owner == toucher)
- || (time < this.item_spawnshieldtime)
- ) { return; }
-
- switch (MUTATOR_CALLHOOK(ItemTouch, this, toucher))
- {
- case MUT_ITEMTOUCH_RETURN: { return; }
- case MUT_ITEMTOUCH_PICKUP: { toucher = M_ARGV(1, entity); goto pickup; }
- }
-
- toucher = M_ARGV(1, entity);
-
- if (Item_IsExpiring(this))
- {
- this.strength_finished = max(0, this.strength_finished - time);
- this.invincible_finished = max(0, this.invincible_finished - time);
- this.superweapons_finished = max(0, this.superweapons_finished - time);
- }
- bool gave = ITEM_HANDLE(Pickup, this.itemdef, this, toucher);
- if (!gave)
- {
- if (Item_IsExpiring(this))
- {
- // undo what we did above
- this.strength_finished += time;
- this.invincible_finished += time;
- this.superweapons_finished += time;
- }
- return;
- }
-
-LABEL(pickup)
-
- if(this.target && this.target != "" && this.target != "###item###") // defrag support
- SUB_UseTargets(this, toucher, NULL);
-
- STAT(LAST_PICKUP, toucher) = time;
-
- Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
- _sound (toucher, (this.itemdef.instanceOfPowerup ? CH_TRIGGER_SINGLE : CH_TRIGGER), (this.item_pickupsound ? this.item_pickupsound : Sound_fixpath(this.item_pickupsound_ent)), VOL_BASE, ATTEN_NORM);
-
- MUTATOR_CALLHOOK(ItemTouched, this, toucher);
- if (wasfreed(this))
- {
- return;
- }
-
- if (Item_IsLoot(this))
- {
- delete(this);
- return;
- }
- if (!this.spawnshieldtime)
- {
- return;
- }
- entity e;
- if (this.team)
- {
- RandomSelection_Init();
- IL_EACH(g_items, it.team == this.team,
- {
- if (it.itemdef) // is a registered item
- {
- Item_Show(it, -1);
- it.scheduledrespawntime = 0;
- RandomSelection_AddEnt(it, it.cnt, 0);
- }
- });
- e = RandomSelection_chosen_ent;
- Item_Show(e, 1); // reset its state so it is visible (extra sendflags doesn't matter, this happens anyway)
- }
- else
- e = this;
- Item_ScheduleRespawn(e);
-}
-
-void Item_Reset(entity this)
-{
- Item_Show(this, !this.state);
- setorigin(this, this.origin);
-
- if (Item_IsLoot(this))
- {
- return;
- }
- setthink(this, Item_Think);
- this.nextthink = time;
- if (this.waypointsprite_attached)
- {
- WaypointSprite_Kill(this.waypointsprite_attached);
- }
- if (this.itemdef.instanceOfPowerup || (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS)) // do not spawn powerups initially!
- {
- Item_ScheduleInitialRespawn(this);
- }
-}
-
-void Item_FindTeam(entity this)
-{
- entity e;
-
- if(this.effects & EF_NODRAW)
- {
- // marker for item team search
- LOG_TRACE("Initializing item team ", ftos(this.team));
- RandomSelection_Init();
- IL_EACH(g_items, it.team == this.team,
- {
- if(it.itemdef) // is a registered item
- RandomSelection_AddEnt(it, it.cnt, 0);
- });
-
- e = RandomSelection_chosen_ent;
- if (!e)
- return;
-
- IL_EACH(g_items, it.team == this.team,
- {
- if(it.itemdef) // is a registered item
- {
- if(it != e)
- {
- // make it non-spawned
- Item_Show(it, -1);
- it.state = 1; // state 1 = initially hidden item, apparently
- }
- else
- Item_Reset(it);
- it.effects &= ~EF_NODRAW;
- }
- });
- }
-}
-
-// Savage: used for item garbage-collection
-void RemoveItem(entity this)
-{
- if(wasfreed(this) || !this) { return; }
- Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
- delete(this);
-}
-
-// pickup evaluation functions
-// these functions decide how desirable an item is to the bots
-
-float generic_pickupevalfunc(entity player, entity item) {return item.bot_pickupbasevalue;}
-
-float weapon_pickupevalfunc(entity player, entity item)
-{
- // See if I have it already
- if(STAT(WEAPONS, player) & STAT(WEAPONS, item))
- {
- // If I can pick it up
- if(!item.spawnshieldtime)
- return 0;
- return ammo_pickupevalfunc(player, item);
- }
-
- // reduce weapon value if bot already got a good arsenal
- float c = 1;
- int weapons_value = 0;
- FOREACH(Weapons, it != WEP_Null && (STAT(WEAPONS, player) & it.m_wepset), {
- weapons_value += it.bot_pickupbasevalue;
- });
- c -= bound(0, weapons_value / 20000, 1) * 0.5;
-
- return item.bot_pickupbasevalue * c;
-}
-
-float ammo_pickupevalfunc(entity player, entity item)
-{
- bool need_shells = false, need_nails = false, need_rockets = false, need_cells = false, need_plasma = false, need_fuel = false;
- entity wpn = NULL;
- float c = 0;
- float rating = 0;
-
- // Detect needed ammo
- if(item.itemdef.instanceOfWeaponPickup)
- {
- entity ammo = NULL;
- if(GetResource(item, RES_SHELLS)) { need_shells = true; ammo = ITEM_Shells; }
- else if(GetResource(item, RES_BULLETS)) { need_nails = true; ammo = ITEM_Bullets; }
- else if(GetResource(item, RES_ROCKETS)) { need_rockets = true; ammo = ITEM_Rockets; }
- else if(GetResource(item, RES_CELLS)) { need_cells = true; ammo = ITEM_Cells; }
- else if(GetResource(item, RES_PLASMA)) { need_plasma = true; ammo = ITEM_Plasma; }
- else if(GetResource(item, RES_FUEL)) { need_fuel = true; ammo = ITEM_JetpackFuel; }
-
- if(!ammo)
- return 0;
- wpn = item;
- rating = ammo.m_botvalue;
- }
- else
- {
- FOREACH(Weapons, it != WEP_Null, {
- if(!(STAT(WEAPONS, player) & (it.m_wepset)))
- continue;
-
- switch(it.ammo_type)
- {
- case RES_SHELLS: need_shells = true; break;
- case RES_BULLETS: need_nails = true; break;
- case RES_ROCKETS: need_rockets = true; break;
- case RES_CELLS: need_cells = true; break;
- case RES_PLASMA: need_plasma = true; break;
- case RES_FUEL: need_fuel = true; break;
- }
- });
- rating = item.bot_pickupbasevalue;
- }
-
- float noammorating = 0.5;
-
- if ((need_shells) && GetResource(item, RES_SHELLS) && (GetResource(player, RES_SHELLS) < g_pickup_shells_max))
- c = GetResource(item, RES_SHELLS) / max(noammorating, GetResource(player, RES_SHELLS));
-
- if ((need_nails) && GetResource(item, RES_BULLETS) && (GetResource(player, RES_BULLETS) < g_pickup_nails_max))
- c = GetResource(item, RES_BULLETS) / max(noammorating, GetResource(player, RES_BULLETS));
-
- if ((need_rockets) && GetResource(item, RES_ROCKETS) && (GetResource(player, RES_ROCKETS) < g_pickup_rockets_max))
- c = GetResource(item, RES_ROCKETS) / max(noammorating, GetResource(player, RES_ROCKETS));
-
- if ((need_cells) && GetResource(item, RES_CELLS) && (GetResource(player, RES_CELLS) < g_pickup_cells_max))
- c = GetResource(item, RES_CELLS) / max(noammorating, GetResource(player, RES_CELLS));
-
- if ((need_plasma) && GetResource(item, RES_PLASMA) && (GetResource(player, RES_PLASMA) < g_pickup_plasma_max))
- c = GetResource(item, RES_PLASMA) / max(noammorating, GetResource(player, RES_PLASMA));
-
- if ((need_fuel) && GetResource(item, RES_FUEL) && (GetResource(player, RES_FUEL) < g_pickup_fuel_max))
- c = GetResource(item, RES_FUEL) / max(noammorating, GetResource(player, RES_FUEL));
-
- rating *= min(c, 2);
- if(wpn)
- rating += wpn.bot_pickupbasevalue * 0.1;
- return rating;
-}
-
-float healtharmor_pickupevalfunc(entity player, entity item)
-{
- float c = 0;
- float rating = item.bot_pickupbasevalue;
-
- float itemarmor = GetResource(item, RES_ARMOR);
- float itemhealth = GetResource(item, RES_HEALTH);
-
- if(item.item_group)
- {
- itemarmor *= min(4, item.item_group_count);
- itemhealth *= min(4, item.item_group_count);
- }
-
- if (itemarmor && (GetResource(player, RES_ARMOR) < item.max_armorvalue))
- c = itemarmor / max(1, GetResource(player, RES_ARMOR) * 2/3 + GetResource(player, RES_HEALTH) * 1/3);
-
- if (itemhealth && (GetResource(player, RES_HEALTH) < item.max_health))
- c = itemhealth / max(1, GetResource(player, RES_HEALTH));
-
- rating *= min(2, c);
- return rating;
-}
-
-void Item_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
-{
- if(ITEM_DAMAGE_NEEDKILL(deathtype))
- RemoveItem(this);
-}
-
-void item_use(entity this, entity actor, entity trigger)
-{
- // use the touch function to handle collection
- gettouch(this)(this, actor);
-}
-
-void _StartItem(entity this, entity def, float defaultrespawntime, float defaultrespawntimejitter)
-{
- string itemname = def.m_name;
- Model itemmodel = def.m_model;
- Sound pickupsound = def.m_sound;
- float(entity player, entity item) pickupevalfunc = def.m_pickupevalfunc;
- float pickupbasevalue = def.m_botvalue;
- int itemflags = def.m_itemflags;
-
- startitem_failed = false;
-
- this.item_model_ent = itemmodel;
- this.item_pickupsound_ent = pickupsound;
-
- if(def.m_iteminit)
- def.m_iteminit(def, this);
-
- if(!this.respawntime) // both need to be set
- {
- this.respawntime = defaultrespawntime;
- this.respawntimejitter = defaultrespawntimejitter;
- }
-
- if(!this.pickup_anyway && def.m_pickupanyway)
- this.pickup_anyway = def.m_pickupanyway();
-
- int itemid = def.m_itemid;
- this.items = itemid;
- int weaponid = def.instanceOfWeaponPickup ? def.m_weapon.m_id : 0;
- this.weapon = weaponid;
-
- if(!this.fade_end)
- {
- this.fade_start = autocvar_g_items_mindist;
- this.fade_end = autocvar_g_items_maxdist;
- }
-
- if(weaponid)
- STAT(WEAPONS, this) = WepSet_FromWeapon(REGISTRY_GET(Weapons, weaponid));
-
- this.flags = FL_ITEM | itemflags;
- IL_PUSH(g_items, this);
-
- if(MUTATOR_CALLHOOK(FilterItem, this)) // error means we do not want the item
- {
- startitem_failed = true;
- delete(this);
- return;
- }
-
- precache_model(this.model);
- precache_sound(this.item_pickupsound);
-
- if (Item_IsLoot(this))
- {
- this.reset = SUB_Remove;
- set_movetype(this, MOVETYPE_TOSS);
-
- // Savage: remove thrown items after a certain period of time ("garbage collection")
- setthink(this, RemoveItem);
- this.nextthink = time + 20;
-
- this.takedamage = DAMAGE_YES;
- this.event_damage = Item_Damage;
-
- if (Item_IsExpiring(this))
- {
- // if item is worthless after a timer, have it expire then
- this.nextthink = max(this.strength_finished, this.invincible_finished, this.superweapons_finished);
- }
-
- // don't drop if in a NODROP zone (such as lava)
- traceline(this.origin, this.origin, MOVE_NORMAL, this);
- if (trace_dpstartcontents & DPCONTENTS_NODROP)
- {
- startitem_failed = true;
- delete(this);
- return;
- }
- }
- else
- {
- if(!have_pickup_item(this))
- {
- startitem_failed = true;
- delete(this);
- return;
- }
-
- if(this.angles != '0 0 0')
- this.SendFlags |= ISF_ANGLES;
-
- this.reset = Item_Reset;
- // it's a level item
- if(this.spawnflags & 1)
- this.noalign = 1;
- if (this.noalign > 0)
- set_movetype(this, MOVETYPE_NONE);
- else
- set_movetype(this, MOVETYPE_TOSS);
- // do item filtering according to game mode and other things
- if (this.noalign <= 0)
- {
- // first nudge it off the floor a little bit to avoid math errors
- setorigin(this, this.origin + '0 0 1');
- // set item size before we spawn a spawnfunc_waypoint
- setsize(this, def.m_mins, def.m_maxs);
- this.SendFlags |= ISF_SIZE;
- // note droptofloor returns false if stuck/or would fall too far
- if (!this.noalign)
- droptofloor(this);
- waypoint_spawnforitem(this);
- }
-
- /*
- * can't do it that way, as it would break maps
- * TODO make a target_give like entity another way, that perhaps has
- * the weapon name in a key
- if(this.targetname)
- {
- // target_give not yet supported; maybe later
- print("removed targeted ", this.classname, "\n");
- startitem_failed = true;
- delete(this);
- return;
- }
- */
-
- if(this.targetname != "" && (this.spawnflags & 16))
- this.use = item_use;
-
- if(autocvar_spawn_debug >= 2)
- {
- // why not flags & fl_item?
- FOREACH_ENTITY_RADIUS(this.origin, 3, it.is_item, {
- LOG_TRACE("XXX Found duplicated item: ", itemname, vtos(this.origin));
- LOG_TRACE(" vs ", it.netname, vtos(it.origin));
- error("Mapper sucks.");
- });
- this.is_item = true;
- }
-
- weaponsInMap |= WepSet_FromWeapon(REGISTRY_GET(Weapons, weaponid));
-
- if ( def.instanceOfPowerup
- || def.instanceOfWeaponPickup
- || (def.instanceOfHealth && def != ITEM_HealthSmall)
- || (def.instanceOfArmor && def != ITEM_ArmorSmall)
- || (itemid & (IT_KEY1 | IT_KEY2))
- )
- {
- if(!this.target || this.target == "")
- this.target = "###item###"; // for finding the nearest item using findnearest
- }
-
- Item_ItemsTime_SetTime(this, 0);
- }
-
- this.bot_pickup = true;
- this.bot_pickupevalfunc = pickupevalfunc;
- this.bot_pickupbasevalue = pickupbasevalue;
- this.mdl = this.model ? this.model : strzone(this.item_model_ent.model_str());
- this.netname = itemname;
- settouch(this, Item_Touch);
- setmodel(this, MDL_Null); // precision set below
- //this.effects |= EF_LOWPRECISION;
-
- setsize (this, this.pos1 = def.m_mins, this.pos2 = def.m_maxs);
-
- this.SendFlags |= ISF_SIZE;
-
- if (!(this.spawnflags & 1024)) {
- if(def.instanceOfPowerup)
- this.ItemStatus |= ITS_ANIMATE1;
-
- if(GetResource(this, RES_ARMOR) || GetResource(this, RES_HEALTH))
- this.ItemStatus |= ITS_ANIMATE2;
- }
-
- if(Item_IsLoot(this))
- this.gravity = 1;
-
- if(def.instanceOfWeaponPickup)
- {
- if (!Item_IsLoot(this)) // if dropped, colormap is already set up nicely
- this.colormap = 1024; // color shirt=0 pants=0 grey
- if (!(this.spawnflags & 1024))
- this.ItemStatus |= ITS_ANIMATE1;
- this.SendFlags |= ISF_COLORMAP;
- }
-
- this.state = 0;
- if(this.team)
- {
- if(!this.cnt)
- this.cnt = 1; // item probability weight
-
- this.effects |= EF_NODRAW; // marker for item team search
- InitializeEntity(this, Item_FindTeam, INITPRIO_FINDTARGET);
- }
- else
- Item_Reset(this);
-
- Net_LinkEntity(this, !(def.instanceOfPowerup || def.instanceOfHealth || def.instanceOfArmor), 0, ItemSend);
-
- // call this hook after everything else has been done
- if (MUTATOR_CALLHOOK(Item_Spawn, this))
- {
- startitem_failed = true;
- delete(this);
- return;
- }
-
- setItemGroup(this);
-}
-
-void StartItem(entity this, GameItem def)
-{
- def = def.m_spawnfunc_hookreplace(def, this);
- if (def.spawnflags & ITEM_FLAG_MUTATORBLOCKED)
- {
- delete(this);
- return;
- }
- this.classname = def.m_canonical_spawnfunc;
- _StartItem(
- this,
- this.itemdef = def,
- def.m_respawntime(), // defaultrespawntime
- def.m_respawntimejitter() // defaultrespawntimejitter
- );
-}
-
-#define IS_SMALL(def) ((def.instanceOfHealth && def == ITEM_HealthSmall) || (def.instanceOfArmor && def == ITEM_ArmorSmall))
-int group_count = 1;
-
-void setItemGroup(entity this)
-{
- if(!IS_SMALL(this.itemdef) || Item_IsLoot(this))
- return;
-
- FOREACH_ENTITY_RADIUS(this.origin, 120, (it != this) && IS_SMALL(it.itemdef),
- {
- if(!this.item_group)
- {
- if(!it.item_group)
- {
- it.item_group = group_count;
- group_count++;
- }
- this.item_group = it.item_group;
- }
- else // spawning item is already part of a item_group X
- {
- if(!it.item_group)
- it.item_group = this.item_group;
- else if(it.item_group != this.item_group) // found an item near the spawning item that is part of a different item_group Y
- {
- int grY = it.item_group;
- // move all items of item_group Y to item_group X
- IL_EACH(g_items, IS_SMALL(it.itemdef),
- {
- if(it.item_group == grY)
- it.item_group = this.item_group;
- });
- }
- }
- });
-}
-
-void setItemGroupCount()
-{
- for (int k = 1; k <= group_count; k++)
- {
- int count = 0;
- IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { count++; });
- if (count)
- IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { it.item_group_count = count; });
- }
-}
-
-void target_items_use(entity this, entity actor, entity trigger)
-{
- if(Item_IsLoot(actor))
- {
- EXACTTRIGGER_TOUCH(this, trigger);
- delete(actor);
- return;
- }
-
- if (!IS_PLAYER(actor) || IS_DEAD(actor))
- return;
-
- if(trigger.solid == SOLID_TRIGGER)
- {
- EXACTTRIGGER_TOUCH(this, trigger);
- }
-
- IL_EACH(g_items, it.enemy == actor && Item_IsLoot(it),
- {
- delete(it);
- });
-
- if(GiveItems(actor, 0, tokenize_console(this.netname)))
- centerprint(actor, this.message);
-}
-
-spawnfunc(target_items)
-{
- this.use = target_items_use;
- if(!this.strength_finished)
- this.strength_finished = autocvar_g_balance_powerup_strength_time;
- if(!this.invincible_finished)
- this.invincible_finished = autocvar_g_balance_powerup_invincible_time;
- if(!this.superweapons_finished)
- this.superweapons_finished = autocvar_g_balance_superweapons_time;
-
- string str;
- int n = tokenize_console(this.netname);
- if(argv(0) == "give")
- {
- str = substring(this.netname, argv_start_index(1), argv_end_index(-1) - argv_start_index(1));
- }
- else
- {
- for(int j = 0; j < n; ++j)
- {
- // this is from a time when unlimited superweapons were handled together with ammo in some parts of the code
- if (argv(j) == "unlimited_ammo") this.items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS;
- else if(argv(j) == "unlimited_weapon_ammo") this.items |= IT_UNLIMITED_AMMO;
- else if(argv(j) == "unlimited_superweapons") this.items |= IT_UNLIMITED_SUPERWEAPONS;
- else if(argv(j) == "strength") this.items |= ITEM_Strength.m_itemid;
- else if(argv(j) == "invincible") this.items |= ITEM_Shield.m_itemid;
- else if(argv(j) == "superweapons") this.items |= IT_SUPERWEAPON;
- else if(argv(j) == "jetpack") this.items |= ITEM_Jetpack.m_itemid;
- else if(argv(j) == "fuel_regen") this.items |= ITEM_JetpackRegen.m_itemid;
- else
- {
- FOREACH(Buffs, it != BUFF_Null,
- {
- string s = Buff_UndeprecateName(argv(j));
- if(s == it.netname)
- {
- STAT(BUFFS, this) |= (it.m_itemid);
- if(!STAT(BUFF_TIME, this))
- STAT(BUFF_TIME, this) = it.m_time(it);
- break;
- }
- });
- FOREACH(Weapons, it != WEP_Null, {
- string s = W_UndeprecateName(argv(j));
- if(s == it.netname)
- {
- STAT(WEAPONS, this) |= (it.m_wepset);
- if(this.spawnflags == 0 || this.spawnflags == 2)
- it.wr_init(it);
- break;
- }
- });
- }
- }
-
- string itemprefix, valueprefix;
- if(this.spawnflags == 0)
- {
- itemprefix = "";
- valueprefix = "";
- }
- else if(this.spawnflags == 1)
- {
- itemprefix = "max ";
- valueprefix = "max ";
- }
- else if(this.spawnflags == 2)
- {
- itemprefix = "min ";
- valueprefix = "min ";
- }
- else if(this.spawnflags == 4)
- {
- itemprefix = "minus ";
- valueprefix = "max ";
- }
- else
- {
- error("invalid spawnflags");
- itemprefix = valueprefix = string_null;
- }
-
- str = "";
- str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & IT_UNLIMITED_AMMO), "unlimited_weapon_ammo");
- str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
- str = sprintf("%s %s%d %s", str, valueprefix, this.strength_finished * boolean(this.items & ITEM_Strength.m_itemid), "strength");
- str = sprintf("%s %s%d %s", str, valueprefix, this.invincible_finished * boolean(this.items & ITEM_Shield.m_itemid), "invincible");
- str = sprintf("%s %s%d %s", str, valueprefix, this.superweapons_finished * boolean(this.items & IT_SUPERWEAPON), "superweapons");
- str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & ITEM_Jetpack.m_itemid), "jetpack");
- str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & ITEM_JetpackRegen.m_itemid), "fuel_regen");
- float res;
- res = GetResource(this, RES_SHELLS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "shells");
- res = GetResource(this, RES_BULLETS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "nails");
- res = GetResource(this, RES_ROCKETS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "rockets");
- res = GetResource(this, RES_CELLS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "cells");
- res = GetResource(this, RES_PLASMA); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "plasma");
- res = GetResource(this, RES_FUEL); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "fuel");
- res = GetResource(this, RES_HEALTH); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "health");
- res = GetResource(this, RES_ARMOR); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "armor");
- // HACK: buffs share a single timer, so we need to include enabled buffs AFTER disabled ones to avoid loss
- FOREACH(Buffs, it != BUFF_Null && !(STAT(BUFFS, this) & it.m_itemid), str = sprintf("%s %s%d %s", str, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
- FOREACH(Buffs, it != BUFF_Null && (STAT(BUFFS, this) & it.m_itemid), str = sprintf("%s %s%d %s", str, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
- FOREACH(Weapons, it != WEP_Null, str = sprintf("%s %s%d %s", str, itemprefix, !!(STAT(WEAPONS, this) & (it.m_wepset)), it.netname));
- }
- this.netname = strzone(str);
-
- n = tokenize_console(this.netname);
- for(int j = 0; j < n; ++j)
- {
- FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(argv(j)) == it.netname, {
- it.wr_init(it);
- break;
- });
- }
-}
-
-float GiveWeapon(entity e, float wpn, float op, float val)
-{
- WepSet v0, v1;
- WepSet s = WepSet_FromWeapon(REGISTRY_GET(Weapons, wpn));
- v0 = (STAT(WEAPONS, e) & s);
- switch(op)
- {
- case OP_SET:
- if(val > 0)
- STAT(WEAPONS, e) |= s;
- else
- STAT(WEAPONS, e) &= ~s;
- break;
- case OP_MIN:
- case OP_PLUS:
- if(val > 0)
- STAT(WEAPONS, e) |= s;
- break;
- case OP_MAX:
- if(val <= 0)
- STAT(WEAPONS, e) &= ~s;
- break;
- case OP_MINUS:
- if(val > 0)
- STAT(WEAPONS, e) &= ~s;
- break;
- }
- v1 = (STAT(WEAPONS, e) & s);
- return (v0 != v1);
-}
-
-bool GiveBuff(entity e, Buff thebuff, int op, int val)
-{
- bool had_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
- float new_buff_time = ((had_buff) ? STAT(BUFF_TIME, e) : 0);
- switch (op)
- {
- case OP_SET:
- new_buff_time = val;
- break;
- case OP_MIN:
- new_buff_time = max(new_buff_time, val);
- break;
- case OP_MAX:
- new_buff_time = min(new_buff_time, val);
- break;
- case OP_PLUS:
- new_buff_time += val;
- break;
- case OP_MINUS:
- new_buff_time -= val;
- break;
- }
- if(new_buff_time <= 0)
- {
- if(had_buff)
- STAT(BUFF_TIME, e) = new_buff_time;
- STAT(BUFFS, e) &= ~thebuff.m_itemid;
- }
- else
- {
- STAT(BUFF_TIME, e) = new_buff_time;
- STAT(BUFFS, e) = thebuff.m_itemid; // NOTE: replaces any existing buffs on the player!
- }
- bool have_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
- return (had_buff != have_buff);
-}
-
-void GiveSound(entity e, float v0, float v1, float t, Sound snd_incr, Sound snd_decr)
-{
- if(v1 == v0)
- return;
- if(v1 <= v0 - t)
- {
- if(snd_decr != NULL)
- sound (e, CH_TRIGGER, snd_decr, VOL_BASE, ATTEN_NORM);
- }
- else if(v0 >= v0 + t)
- {
- if(snd_incr != NULL)
- sound (e, CH_TRIGGER, snd_incr, VOL_BASE, ATTEN_NORM);
- }
-}
-
-void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .float regenfield, float regentime)
-{
- if(v0 < v1)
- e.(rotfield) = max(e.(rotfield), time + rottime);
- else if(v0 > v1)
- e.(regenfield) = max(e.(regenfield), time + regentime);
-}
-bool GiveResourceValue(entity e, int res_type, int op, int val)
-{
- int v0 = GetResource(e, res_type);
- float new_val = 0;
- switch (op)
- {
- // min 100 cells = at least 100 cells
- case OP_SET: new_val = val; break;
- case OP_MIN: new_val = max(v0, val); break;
- case OP_MAX: new_val = min(v0, val); break;
- case OP_PLUS: new_val = v0 + val; break;
- case OP_MINUS: new_val = v0 - val; break;
- default: return false;
- }
-
- return SetResourceExplicit(e, res_type, new_val);
-}
-
-float GiveItems(entity e, float beginarg, float endarg)
-{
- float got, i, val, op;
- string cmd;
-
- val = 999;
- op = OP_SET;
-
- got = 0;
-
- int _switchweapon = 0;
-
- if(CS(e).autoswitch)
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
- if(e.(weaponentity).m_switchweapon == w_getbestweapon(e, weaponentity))
- _switchweapon |= BIT(slot);
- }
- }
-
- STAT(STRENGTH_FINISHED, e) = max(0, STAT(STRENGTH_FINISHED, e) - time);
- STAT(INVINCIBLE_FINISHED, e) = max(0, STAT(INVINCIBLE_FINISHED, e) - time);
- STAT(SUPERWEAPONS_FINISHED, e) = max(0, STAT(SUPERWEAPONS_FINISHED, e) - time);
- STAT(BUFF_TIME, e) = max(0, STAT(BUFF_TIME, e) - time);
-
- PREGIVE(e, items);
- PREGIVE_WEAPONS(e);
- PREGIVE(e, stat_STRENGTH_FINISHED);
- PREGIVE(e, stat_INVINCIBLE_FINISHED);
- PREGIVE(e, stat_SUPERWEAPONS_FINISHED);
- PREGIVE_RESOURCE(e, RES_BULLETS);
- PREGIVE_RESOURCE(e, RES_CELLS);
- PREGIVE_RESOURCE(e, RES_PLASMA);
- PREGIVE_RESOURCE(e, RES_SHELLS);
- PREGIVE_RESOURCE(e, RES_ROCKETS);
- PREGIVE_RESOURCE(e, RES_FUEL);
- PREGIVE_RESOURCE(e, RES_ARMOR);
- PREGIVE_RESOURCE(e, RES_HEALTH);
-
- for(i = beginarg; i < endarg; ++i)
- {
- cmd = argv(i);
-
- if(cmd == "0" || stof(cmd))
- {
- val = stof(cmd);
- continue;
- }
- switch(cmd)
- {
- case "no":
- op = OP_MAX;
- val = 0;
- continue;
- case "max":
- op = OP_MAX;
- continue;
- case "min":
- op = OP_MIN;
- continue;
- case "plus":
- op = OP_PLUS;
- continue;
- case "minus":
- op = OP_MINUS;
- continue;
- case "ALL":
- got += GiveBit(e, items, ITEM_JetpackRegen.m_itemid, op, val);
- got += GiveValue(e, stat_STRENGTH_FINISHED, op, val);
- got += GiveValue(e, stat_INVINCIBLE_FINISHED, op, val);
- got += GiveValue(e, stat_SUPERWEAPONS_FINISHED, op, val);
- got += GiveBit(e, items, IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS, op, val);
- case "all":
- got += GiveBit(e, items, ITEM_Jetpack.m_itemid, op, val);
- got += GiveResourceValue(e, RES_HEALTH, op, val);
- got += GiveResourceValue(e, RES_ARMOR, op, val);
- case "allweapons":
- FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)), got += GiveWeapon(e, it.m_id, op, val));
- //case "allbuffs": // all buffs makes a player god, do not want!
- //FOREACH(Buffs, it != BUFF_Null, got += GiveBuff(e, it.m_itemid, op, val));
- case "allammo":
- got += GiveResourceValue(e, RES_CELLS, op, val);
- got += GiveResourceValue(e, RES_PLASMA, op, val);
- got += GiveResourceValue(e, RES_SHELLS, op, val);
- got += GiveResourceValue(e, RES_BULLETS, op, val);
- got += GiveResourceValue(e, RES_ROCKETS, op, val);
- got += GiveResourceValue(e, RES_FUEL, op, val);
- break;
- case "unlimited_ammo":
- // this is from a time when unlimited superweapons were handled together with ammo in some parts of the code
- got += GiveBit(e, items, IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS, op, val);
- break;
- case "unlimited_weapon_ammo":
- got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
- break;
- case "unlimited_superweapons":
- got += GiveBit(e, items, IT_UNLIMITED_SUPERWEAPONS, op, val);
- break;
- case "jetpack":
- got += GiveBit(e, items, ITEM_Jetpack.m_itemid, op, val);
- break;
- case "fuel_regen":
- got += GiveBit(e, items, ITEM_JetpackRegen.m_itemid, op, val);
- break;
- case "strength":
- got += GiveValue(e, stat_STRENGTH_FINISHED, op, val);
- break;
- case "invincible":
- got += GiveValue(e, stat_INVINCIBLE_FINISHED, op, val);
- break;
- case "superweapons":
- got += GiveValue(e, stat_SUPERWEAPONS_FINISHED, op, val);
- break;
- case "cells":
- got += GiveResourceValue(e, RES_CELLS, op, val);
- break;
- case "plasma":
- got += GiveResourceValue(e, RES_PLASMA, op, val);
- break;
- case "shells":
- got += GiveResourceValue(e, RES_SHELLS, op, val);
- break;
- case "nails":
- case "bullets":
- got += GiveResourceValue(e, RES_BULLETS, op, val);
- break;
- case "rockets":
- got += GiveResourceValue(e, RES_ROCKETS, op, val);
- break;
- case "health":
- got += GiveResourceValue(e, RES_HEALTH, op, val);
- break;
- case "armor":
- got += GiveResourceValue(e, RES_ARMOR, op, val);
- break;
- case "fuel":
- got += GiveResourceValue(e, RES_FUEL, op, val);
- break;
- default:
- FOREACH(Buffs, it != BUFF_Null && buff_Available(it) && Buff_UndeprecateName(cmd) == it.netname,
- {
- got += GiveBuff(e, it, op, val);
- break;
- });
- FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(cmd) == it.netname, {
- got += GiveWeapon(e, it.m_id, op, val);
- break;
- });
- break;
- }
- val = 999;
- op = OP_SET;
- }
-
- POSTGIVE_BIT(e, items, ITEM_JetpackRegen.m_itemid, SND_ITEMPICKUP, SND_Null);
- POSTGIVE_BIT(e, items, IT_UNLIMITED_SUPERWEAPONS, SND_POWERUP, SND_POWEROFF);
- POSTGIVE_BIT(e, items, IT_UNLIMITED_AMMO, SND_POWERUP, SND_POWEROFF);
- POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, SND_ITEMPICKUP, SND_Null);
- FOREACH(Weapons, it != WEP_Null, {
- POSTGIVE_WEAPON(e, it, SND_WEAPONPICKUP, SND_Null);
- if(!(save_weapons & (it.m_wepset)))
- if(STAT(WEAPONS, e) & (it.m_wepset))
- it.wr_init(it);
- });
- POSTGIVE_VALUE(e, stat_STRENGTH_FINISHED, 1, SND_POWERUP, SND_POWEROFF);
- POSTGIVE_VALUE(e, stat_INVINCIBLE_FINISHED, 1, SND_Shield, SND_POWEROFF);
- //POSTGIVE_VALUE(e, stat_SUPERWEAPONS_FINISHED, 1, SND_Null, SND_Null);
- POSTGIVE_RESOURCE(e, RES_BULLETS, 0, SND_ITEMPICKUP, SND_Null);
- POSTGIVE_RESOURCE(e, RES_CELLS, 0, SND_ITEMPICKUP, SND_Null);
- POSTGIVE_RESOURCE(e, RES_PLASMA, 0, SND_ITEMPICKUP, SND_Null);
- POSTGIVE_RESOURCE(e, RES_SHELLS, 0, SND_ITEMPICKUP, SND_Null);
- POSTGIVE_RESOURCE(e, RES_ROCKETS, 0, SND_ITEMPICKUP, SND_Null);
- POSTGIVE_RES_ROT(e, RES_FUEL, 1, pauserotfuel_finished, autocvar_g_balance_pause_fuel_rot, pauseregen_finished, autocvar_g_balance_pause_fuel_regen, SND_ITEMPICKUP, SND_Null);
- POSTGIVE_RES_ROT(e, RES_ARMOR, 1, pauserotarmor_finished, autocvar_g_balance_pause_armor_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND_ARMOR25, SND_Null);
- POSTGIVE_RES_ROT(e, RES_HEALTH, 1, pauserothealth_finished, autocvar_g_balance_pause_health_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND_MEGAHEALTH, SND_Null);
-
- if(STAT(SUPERWEAPONS_FINISHED, e) <= 0)
- if(!g_weaponarena && (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
- STAT(SUPERWEAPONS_FINISHED, e) = autocvar_g_balance_superweapons_time;
-
- if(STAT(STRENGTH_FINISHED, e) <= 0)
- STAT(STRENGTH_FINISHED, e) = 0;
- else
- STAT(STRENGTH_FINISHED, e) += time;
- if(STAT(INVINCIBLE_FINISHED, e) <= 0)
- STAT(INVINCIBLE_FINISHED, e) = 0;
- else
- STAT(INVINCIBLE_FINISHED, e) += time;
- if(STAT(SUPERWEAPONS_FINISHED, e) <= 0)
- STAT(SUPERWEAPONS_FINISHED, e) = 0;
- else
- STAT(SUPERWEAPONS_FINISHED, e) += time;
- if(STAT(BUFF_TIME, e) <= 0)
- STAT(BUFF_TIME, e) = 0;
- else
- STAT(BUFF_TIME, e) += time;
-
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
- if(!(STAT(WEAPONS, e) & WepSet_FromWeapon(e.(weaponentity).m_switchweapon)))
- _switchweapon |= BIT(slot);
- }
-
- if(_switchweapon)
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(_switchweapon & BIT(slot))
- {
- Weapon wep = w_getbestweapon(e, weaponentity);
- if(wep != e.(weaponentity).m_switchweapon)
- W_SwitchWeapon_Force(e, wep, weaponentity);
- }
- }
- }
-
- return got;
-}
-#endif
+++ /dev/null
-#pragma once
-
-const int AMMO_COUNT = 4; // amount of ammo types to show in the ammo panel
-
-// item networking
-const int ISF_LOCATION = BIT(1);
-const int ISF_MODEL = BIT(2);
-const int ISF_STATUS = BIT(3);
- const int ITS_STAYWEP = BIT(0);
- const int ITS_ANIMATE1 = BIT(1);
- const int ITS_ANIMATE2 = BIT(2);
- const int ITS_AVAILABLE = BIT(3);
- const int ITS_ALLOWFB = BIT(4);
- const int ITS_ALLOWSI = BIT(5);
- const int ITS_GLOW = BIT(6);
-const int ISF_COLORMAP = BIT(4);
-const int ISF_DROP = BIT(5);
-const int ISF_ANGLES = BIT(6);
-const int ISF_SIZE = BIT(7);
-
-.int ItemStatus;
-
-.float onground_time;
-.float fade_start;
-.float fade_end;
-
-#ifdef SVQC
-void StartItem(entity this, entity a);
-.int item_group;
-.int item_group_count;
-#endif
-
-#ifdef CSQC
-
-bool autocvar_cl_items_nofade;
-float autocvar_cl_animate_items = 1;
-float autocvar_cl_ghost_items = 0.45;
-vector autocvar_cl_ghost_items_color = '-1 -1 -1';
-vector autocvar_cl_weapon_stay_color = '2 0.5 0.5';
-float autocvar_cl_weapon_stay_alpha = 0.75;
-float autocvar_cl_simple_items = 0;
-string autocvar_cl_simpleitems_postfix = "_simple";
-.float spawntime;
-.float gravity;
-.vector colormod;
-
-void ItemDraw(entity this);
-
-#endif
-#ifdef SVQC
-
-float autocvar_sv_simple_items;
-bool ItemSend(entity this, entity to, int sf);
-
-bool have_pickup_item(entity this);
-
-const float ITEM_RESPAWN_TICKS = 10;
-
-.float max_armorvalue;
-.float pickup_anyway;
-
-.float item_respawncounter;
-
-void Item_Show (entity e, int mode);
-
-void Item_Respawn (entity this);
-
-void Item_RespawnCountdown(entity this);
-void Item_ScheduleRespawnIn(entity e, float t);
-
-void Item_ScheduleRespawn(entity e);
-
-void Item_ScheduleInitialRespawn(entity e);
-
-/// \brief Give several random weapons and ammo to the entity.
-/// \param[in,out] receiver Entity to give weapons to.
-/// \param[in] num_weapons Number of weapons to give.
-/// \param[in] weapon_names Names of weapons to give separated by spaces.
-/// \param[in] ammo Entity containing the ammo amount for each possible weapon.
-/// \return No return.
-void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names, entity ammo_entity);
-
-bool Item_GiveAmmoTo(entity item, entity player, int res_type, float ammomax);
-
-bool Item_GiveTo(entity item, entity player);
-
-void Item_Touch(entity this, entity toucher);
-
-void Item_Reset(entity this);
-
-void Item_FindTeam(entity this);
-// Savage: used for item garbage-collection
-
-bool ItemSend(entity this, entity to, int sf);
-void ItemUpdate(entity this);
-
-void UpdateItemAfterTeleport(entity this);
-
-// pickup evaluation functions
-// these functions decide how desirable an item is to the bots
-
-float generic_pickupevalfunc(entity player, entity item);// {return item.bot_pickupbasevalue;} // WEAPONTODO
-
-float weapon_pickupevalfunc(entity player, entity item);
-float ammo_pickupevalfunc(entity player, entity item);
-float healtharmor_pickupevalfunc(entity player, entity item);
-
-.bool is_item;
-.entity itemdef;
-void _StartItem(entity this, entity def, float defaultrespawntime, float defaultrespawntimejitter);
-
-void setItemGroup(entity this);
-void setItemGroupCount();
-
-float GiveWeapon(entity e, float wpn, float op, float val);
-
-float GiveBit(entity e, .float fld, float bit, float op, float val);
-
-float GiveValue(entity e, .float fld, float op, float val);
-
-void GiveSound(entity e, float v0, float v1, float t, Sound snd_incr, Sound snd_decr);
-
-void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .float regenfield, float regentime);
-
-spawnfunc(target_items);
-
-#define PREGIVE_WEAPONS(e) WepSet save_weapons; save_weapons = STAT(WEAPONS, e)
-#define PREGIVE(e,f) float save_##f; save_##f = (e).f
-#define PREGIVE_RESOURCE(e,f) float save_##f = GetResource((e), (f))
-#define POSTGIVE_WEAPON(e,b,snd_incr,snd_decr) GiveSound((e), !!(save_weapons & WepSet_FromWeapon(b)), !!(STAT(WEAPONS, e) & WepSet_FromWeapon(b)), 0, snd_incr, snd_decr)
-#define POSTGIVE_BIT(e,f,b,snd_incr,snd_decr) GiveSound((e), save_##f & (b), (e).f & (b), 0, snd_incr, snd_decr)
-#define POSTGIVE_RESOURCE(e,f,t,snd_incr,snd_decr) GiveSound((e), save_##f, GetResource((e), (f)), t, snd_incr, snd_decr)
-#define POSTGIVE_RES_ROT(e,f,t,rotfield,rottime,regenfield,regentime,snd_incr,snd_decr) GiveRot((e),save_##f,GetResource((e),(f)),rotfield,rottime,regenfield,regentime);GiveSound((e),save_##f,GetResource((e),(f)),t,snd_incr,snd_decr)
-#define POSTGIVE_VALUE(e,f,t,snd_incr,snd_decr) GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr)
-#define POSTGIVE_VALUE_ROT(e,f,t,rotfield,rottime,regenfield,regentime,snd_incr,snd_decr) GiveRot((e), save_##f, (e).f, rotfield, rottime, regenfield, regentime); GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr)
-
-float GiveItems(entity e, float beginarg, float endarg);
-#endif
this.origin = ReadVector();
setorigin(this, this.origin);
- this.angles_x = ReadAngle();
- this.angles_y = ReadAngle();
+ this.angles = ReadAngleVector2D();
turret_construct(this, isnew);
this.colormap = 1024;
#include "sv_turrets.qh"
#ifdef SVQC
#include <server/autocvars.qh>
+#include <server/bot/api.qh>
+#include <server/damage.qh>
+#include <server/weapons/common.qh>
+#include <server/weapons/weaponsystem.qh>
+#include <common/mapobjects/defs.qh>
// Generic aiming
vector turret_aim_generic(entity this)
bool turret_send(entity this, entity to, float sf)
{
-
WriteHeader(MSG_ENTITY, ENT_CLIENT_TURRET);
WriteByte(MSG_ENTITY, sf);
if(sf & TNSF_SETUP)
WriteVector(MSG_ENTITY, this.origin);
- WriteAngle(MSG_ENTITY, this.angles_x);
- WriteAngle(MSG_ENTITY, this.angles_y);
+ WriteAngleVector2D(MSG_ENTITY, this.angles);
}
if(sf & TNSF_ANG)
this.event_damage = func_null;
#ifdef TURRET_DEBUG
float d;
- d = RadiusDamage (this, this.owner, this.owner.shot_dmg, 0, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, DMG_NOWEP, NULL);
+ d = RadiusDamage (this, this.owner, this.owner.shot_dmg, 0, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.projectiledeathtype, DMG_NOWEP, NULL);
this.owner.tur_debug_dmg_t_h = this.owner.tur_debug_dmg_t_h + d;
this.owner.tur_debug_dmg_t_f = this.owner.tur_debug_dmg_t_f + this.owner.shot_dmg;
#else
- RadiusDamage (this, this.realowner, this.owner.shot_dmg, 0, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, DMG_NOWEP, NULL);
+ RadiusDamage (this, this.realowner, this.owner.shot_dmg, 0, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.projectiledeathtype, DMG_NOWEP, NULL);
#endif
delete(this);
}
IL_PUSH(g_projectiles, proj);
IL_PUSH(g_bot_dodge, proj);
proj.enemy = actor.enemy;
- proj.totalfrags = _death;
+ proj.projectiledeathtype = _death;
PROJECTILE_MAKETRIGGER(proj);
if(_health)
{
vector tvt_tadv; // turret angle diff vector, updated by a successful call to turret_validate_target
float tvt_thadf; // turret head angle diff float, updated by a successful call to turret_validate_target
float tvt_dist; // turret distance, updated by a successful call to turret_validate_target
+
+IntrusiveList g_turrets;
+STATIC_INIT(g_turrets) { g_turrets = IL_NEW(); }
setorigin(this, this.enemy.origin + randomvec() * this.owner.shot_radius);
#ifdef TURRET_DEBUG
- float d = RadiusDamage (this, this.owner, this.owner.shot_dmg, this.owner.shot_dmg, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, DMG_NOWEP, NULL);
+ float d = RadiusDamage (this, this.owner, this.owner.shot_dmg, this.owner.shot_dmg, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.projectiledeathtype, DMG_NOWEP, NULL);
this.owner.tur_debug_dmg_t_h = this.owner.tur_debug_dmg_t_h + d;
this.owner.tur_debug_dmg_t_f = this.owner.tur_debug_dmg_t_f + this.owner.shot_dmg;
#else
- RadiusDamage (this, this.realowner, this.owner.shot_dmg, this.owner.shot_dmg, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.totalfrags, DMG_NOWEP, NULL);
+ RadiusDamage (this, this.realowner, this.owner.shot_dmg, this.owner.shot_dmg, this.owner.shot_radius, this, NULL, this.owner.shot_force, this.projectiledeathtype, DMG_NOWEP, NULL);
#endif
delete(this);
}
#include "sv_vehicles.qh"
+#include <server/bot/api.qh>
+#include <server/damage.qh>
+#include <server/world.qh>
+#include <server/items/items.qh>
+#include <common/items/_mod.qh>
+#include <common/mapobjects/defs.qh>
+#include <common/mapobjects/teleporters.qh>
+#include <common/mapobjects/triggers.qh>
+#include <server/main.qh>
+#include <server/weapons/common.qh>
+
bool SendAuxiliaryXhair(entity this, entity to, int sf)
{
WriteHeader(MSG_ENTITY, ENT_CLIENT_AUXILIARYXHAIR);
PROJECTILE_TOUCH(this, toucher);
this.event_damage = func_null;
- RadiusDamage (this, this.realowner, this.shot_dmg, 0, this.shot_radius, this, NULL, this.shot_force, this.totalfrags, DMG_NOWEP, toucher);
+ RadiusDamage (this, this.realowner, this.shot_dmg, 0, this.shot_radius, this, NULL, this.shot_force, this.projectiledeathtype, DMG_NOWEP, toucher);
delete(this);
}
proj.shot_dmg = _dmg;
proj.shot_radius = _radi;
proj.shot_force = _force;
- proj.totalfrags = _deahtype;
+ proj.projectiledeathtype = _deahtype;
proj.solid = SOLID_BBOX;
set_movetype(proj, MOVETYPE_FLYMISSILE);
proj.flags = FL_PROJECTILE;
WriteByte (MSG_ONE, SVC_SETVIEWPORT);
WriteEntity( MSG_ONE, player);
+ // NOTE: engine networked
WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
WriteAngle(MSG_ONE, 0);
WriteAngle(MSG_ONE, vehic.angles_y);
veh.vehicle_hudmodel.viewmodelforclient = pl;
- pl.crouch = false;
+ UNSET_DUCKED(pl);
pl.view_ofs = STAT(PL_VIEW_OFS, pl);
setsize(pl, STAT(PL_MIN, pl), STAT(PL_MAX, pl));
WriteByte (MSG_ONE, SVC_SETVIEWPORT);
WriteEntity(MSG_ONE, veh.vehicle_viewport);
+ // NOTE: engine networked
WriteByte (MSG_ONE, SVC_SETVIEWANGLES);
if(veh.tur_head)
{
return false;
if(!this.tur_head)
- {
info.vr_precache(info);
- IL_PUSH(g_vehicles, this);
- }
if(this.targetname && this.targetname != "")
{
.float dmg_time;
+.float pain_frame;
+
.float play_time;
.int volly_counter;
WriteByte(MSG_ONE, SVC_SETVIEWPORT);
WriteEntity(MSG_ONE, player);
+ // NOTE: engine networked
WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
WriteAngle(MSG_ONE, 0);
WriteAngle(MSG_ONE, vehic.angles.y);
WriteByte(MSG_ONE, SVC_SETVIEWPORT);
WriteEntity(MSG_ONE, gunner.vehicle_viewport);
+ // NOTE: engine networked
WriteByte(MSG_ONE, SVC_SETVIEWANGLES);
WriteAngle(MSG_ONE, gunner.angles_x + vehic.angles_x); // tilt
WriteAngle(MSG_ONE, gunner.angles_y + vehic.angles_y); // yaw
#include "racer.qh"
+#if defined(SVQC)
+ #include <common/gamemodes/gamemode/ctf/sv_ctf.qh>
+#endif
+
#ifdef GAMEQC
#ifdef SVQC
vector autocvar_g_vehicle_racer_bouncepain = '200 0.15 150';
.float racer_watertime;
+.float racer_air_finished; // TODO: use a standard air meter for entities
var .vector(entity this, string tag_name, float spring_length, float max_power) racer_force_from_tag;
{
uforce = autocvar_g_vehicle_racer_water_upforcedamper;
- if(PHYS_INPUT_BUTTON_CROUCH(player) && time < this.air_finished)
+ if(PHYS_INPUT_BUTTON_CROUCH(player) && time < this.racer_air_finished)
this.velocity_z += 30;
else
this.velocity_z += 200;
int cont = Mod_Q1BSP_SuperContentsFromNativeContents(pointcontents(vehic.origin));
if(!(cont & DPCONTENTS_WATER))
- vehic.air_finished = 0;
- else if (!vehic.air_finished)
- vehic.air_finished = time + autocvar_g_vehicle_racer_water_time;
+ vehic.racer_air_finished = 0;
+ else if (!vehic.racer_air_finished)
+ vehic.racer_air_finished = time + autocvar_g_vehicle_racer_water_time;
if(IS_DEAD(vehic))
{
#include "raptor.qh"
+#if defined(SVQC)
+ #include <common/gamemodes/gamemode/ctf/sv_ctf.qh>
+#endif
+
#ifdef GAMEQC
#ifdef SVQC
bool incoming = false;
IL_EACH(g_projectiles, it.enemy == vehic,
{
- if(MISSILE_IS_TRACKING(it))
+ if(it.missile_flags & MIF_GUIDED_TRACKING)
if(vdist(vehic.origin - it.origin, <, 2 * autocvar_g_vehicle_raptor_flare_range))
{
incoming = true;
#include "spiderbot.qh"
+#if defined(SVQC)
+ #include <common/gamemodes/gamemode/ctf/sv_ctf.qh>
+#endif
+
#ifdef GAMEQC
const int SBRM_FIRST = 1;
#include "util.qh"
#if defined(CSQC)
- #include "../client/defs.qh"
+ #include <client/main.qh>
#include "constants.qh"
#elif defined(MENUQC)
#elif defined(SVQC)
- #include "../server/defs.qh"
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
#endif
// client movement
#define WEAPONS_ALL_C
#if defined(CSQC)
- #include <client/defs.qh>
#include "../constants.qh"
#include "../stats.qh"
#include <lib/warpzone/anglestransform.qh>
#include <common/util.qh>
#include "../monsters/_mod.qh"
#include "config.qh"
+ #include <server/weapons/common.qh>
#include <server/weapons/csqcprojectile.qh>
#include <server/weapons/tracing.qh>
- #include "../t_items.qh"
+ #include <server/items/spawning.qh>
#include <server/autocvars.qh>
- #include <server/constants.qh>
- #include <server/defs.qh>
#include "../notifications/all.qh"
#include "../deathtypes/all.qh"
#include <server/mutators/_mod.qh>
#include <server/command/_mod.qh>
#include <lib/csqcmodel/sv_model.qh>
#include <server/portals.qh>
- #include <server/g_hook.qh>
+ #include <server/hook.qh>
#endif
#ifdef GAMEQC
#include "calculations.qc"
vector md = wepent.movedir_aligned;
vector vecs = ((md.x > 0) ? md : '0 0 0');
- vector dv = right * -vecs.y + up * vecs.z;
+ vector dv = forward * vecs.x + right * -vecs.y + up * vecs.z;
vector org = rlplayer.origin + rlplayer.view_ofs + dv;
- tracebox(org, '0 0 0', '0 0 0', org + forward * (vecs.x + 1), MOVE_NORMAL, rlplayer);
- org = trace_endpos - forward * 1;
pointparticles(thiswep.m_muzzleeffect, org, forward * 1000, 1);
}
if(sf & ARC_SF_BEAMDIR) // beam direction
{
- WriteAngle(MSG_ENTITY, this.beam_dir.x);
- WriteAngle(MSG_ENTITY, this.beam_dir.y);
- WriteAngle(MSG_ENTITY, this.beam_dir.z);
+ WriteAngleVector(MSG_ENTITY, this.beam_dir);
}
if(sf & ARC_SF_BEAMTYPE) // beam type
{
if(sf & ARC_SF_BEAMDIR) // beam direction
{
- this.angles_x = ReadAngle();
- this.angles_y = ReadAngle();
- this.angles_z = ReadAngle();
+ this.angles = ReadAngleVector();
}
if(sf & ARC_SF_BEAMTYPE) // beam type
spread = WEP_CVAR_PRI(hlac, spread_min) + (WEP_CVAR_PRI(hlac, spread_add) * actor.(weaponentity).misc_bulletcounter);
spread = min(spread,WEP_CVAR_PRI(hlac, spread_max));
- if(actor.crouch)
+ if(IS_DUCKED(actor))
spread = spread * WEP_CVAR_PRI(hlac, spread_crouchmod);
W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_PRI(hlac, damage), thiswep.m_id);
spread = WEP_CVAR_SEC(hlac, spread);
- if(actor.crouch)
+ if(IS_DUCKED(actor))
spread = spread * WEP_CVAR_SEC(hlac, spread_crouchmod);
W_SetupShot(actor, weaponentity, false, 3, SND_LASERGUN_FIRE, CH_WEAPON_A, WEP_CVAR_SEC(hlac, damage), thiswep.m_id | HITTYPE_SECONDARY);
.float minelayer_detonate, mine_explodeanyway;
.float mine_time;
.vector mine_orientation;
+
+IntrusiveList g_mines;
+STATIC_INIT(g_mines) { g_mines = IL_NEW(); }
#endif
.float porto_forbidden;
void W_Porto_Fail(entity this, float failhard);
+void W_Porto_Remove (entity p);
#endif
// BLAST CONE CALCULATION
// ========================
- // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in g_damage.qc)
+ // if it's a player, use the view origin as reference (stolen from RadiusDamage functions in damage.qc)
center = CENTER_OR_VIEWOFS(head);
// find the closest point on the enemy to the center of the attack
SPAWNFUNC_WEAPON(weapon_nex, WEP_VORTEX)
#ifdef SVQC
+.float vortex_charge_rottime;
+
.float vortex_lasthit;
void W_Vortex_Charge(entity actor, .entity weaponentity, float dt);
\
PROP(false, porto_v_angle_held, WEPENT_SET_NORMAL, \
{ WriteByte(chan, this.porto_v_angle_held); if(this.porto_v_angle_held) { \
- WriteAngle(chan, this.owner.porto_v_angle.x); WriteAngle(chan, this.owner.porto_v_angle.y); \
+ WriteAngleVector2D(chan, this.owner.porto_v_angle); \
} }, \
{ (viewmodels[this.m_wepent_slot]).angles_held_status = ReadByte(); if((viewmodels[this.m_wepent_slot]).angles_held_status) { \
- (viewmodels[this.m_wepent_slot]).angles_held = vec2(ReadAngle(), ReadAngle()); } \
+ (viewmodels[this.m_wepent_slot]).angles_held = ReadAngleVector2D(); } \
else { (viewmodels[this.m_wepent_slot]).angles_held = '0 0 0'; } }) \
\
PROP(false, tuba_instrument, WEPENT_SET_NORMAL, \
float smoothtime = bound(0, time - smooth_prevtime, 0.1);
smooth_prevtime = max(smooth_prevtime, drawtime); // drawtime is the previous frame's time at this point
- if(this.csqcmodel_teleported || !(this.pmove_flags & PMF_ONGROUND) || autocvar_cl_stairsmoothspeed <= 0)
+ if(this.csqcmodel_teleported || !(this.pmove_flags & PMF_ONGROUND) || autocvar_cl_stairsmoothspeed <= 0 || this.ground_networkentity)
stairsmoothz = v.z;
else
{
//const int PMF_DUCKED = 4;
//const int PMF_ONGROUND = 8;
-const int FL_DUCKED = BIT(19);
-
void CSQCPlayer_SetCamera();
float CSQCPlayer_PreUpdate(entity this);
float CSQCPlayer_PostUpdate(entity this);
#include "i18n.qh"
#include "vector.qh"
- float vid_conwidth;
+ noref float vid_conwidth;
+ noref float vid_conheight;
void Draw_CylindricLine(vector from, vector to, float thickness, string texture, float aspect, float shift, vector rgb, float theAlpha, float drawflag, vector vieworg)
{
#define ReadFloat() ReadCoord()
#define ReadVector() vec3(ReadFloat(), ReadFloat(), ReadFloat())
#define ReadVector2D() vec2(ReadFloat(), ReadFloat())
+ #define ReadAngleVector() vec3(ReadAngle(), ReadAngle(), ReadAngle())
+ #define ReadAngleVector2D() vec2(ReadAngle(), ReadAngle())
int Readbits(int num)
{
#define WriteFloat(to, f) WriteCoord(to, f)
#define WriteVector(to, v) MACRO_BEGIN WriteFloat(to, v.x); WriteFloat(to, v.y); WriteFloat(to, v.z); MACRO_END
#define WriteVector2D(to, v) MACRO_BEGIN WriteFloat(to, v.x); WriteFloat(to, v.y); MACRO_END
+ #define WriteAngleVector(to, v) MACRO_BEGIN WriteAngle(to, v.x); WriteAngle(to, v.y); WriteAngle(to, v.z); MACRO_END
+ #define WriteAngleVector2D(to, v) MACRO_BEGIN WriteAngle(to, v.x); WriteAngle(to, v.y); MACRO_END
void Writebits(float dst, float val, int num)
{
#include "common.qh"
#if defined(CSQC)
- #include <common/t_items.qh>
+ #include <client/items/items.qh>
#elif defined(MENUQC)
#elif defined(SVQC)
#include <common/weapons/_all.qh>
#include <common/constants.qh>
#include <common/net_linked.qh>
#include <common/mapobjects/subs.qh>
+ #include <common/mapobjects/teleporters.qh>
#include <common/util.qh>
- #include <server/constants.qh>
- #include <server/defs.qh>
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
#include <server/utils.qh>
#endif
e.addValue(e, _("Never"), "0");
e.addValue(e, _("In non teamplay modes only"), "1");
e.addValue(e, _("Always"), "2");
+ e.addValue(e, _("Only in Duel"), "3");
e.configureXonoticTextSliderValues(e);
me.TR(me);
me.TD(me, 1, 1, e = makeXonoticTextLabel(0, _("Body fading:")));
#include <server/cheats.qc>
#include <server/client.qc>
#include <server/clientkill.qc>
-#include <server/g_damage.qc>
-#include <server/g_hook.qc>
-#include <server/g_world.qc>
+#include <server/damage.qc>
+#include <server/hook.qc>
+#include <server/world.qc>
#include <server/gamelog.qc>
#include <server/handicap.qc>
#include <server/impulse.qc>
#include <server/ipban.qc>
-#include <server/items.qc>
+#include <server/main.qc>
#include <server/mapvoting.qc>
#include <server/matrix.qc>
#include <server/miscfunctions.qc>
#include <server/scores_rules.qc>
#include <server/spawnpoints.qc>
#include <server/steerlib.qc>
-#ifdef SVQC
- #include <server/sv_main.qc>
-#endif
#include <server/teamplay.qc>
#include <server/tests.qc>
#include <server/bot/_mod.inc>
#include <server/command/_mod.inc>
#include <server/compat/_mod.inc>
+#include <server/items/_mod.inc>
#include <server/mutators/_mod.inc>
#include <server/pathlib/_mod.inc>
#include <server/weapons/_mod.inc>
#include <server/cheats.qh>
#include <server/client.qh>
#include <server/clientkill.qh>
-#include <server/g_damage.qh>
-#include <server/g_hook.qh>
-#include <server/g_world.qh>
+#include <server/damage.qh>
+#include <server/hook.qh>
+#include <server/world.qh>
#include <server/gamelog.qh>
#include <server/handicap.qh>
#include <server/impulse.qh>
#include <server/ipban.qh>
-#include <server/items.qh>
+#include <server/main.qh>
#include <server/mapvoting.qh>
#include <server/matrix.qh>
#include <server/miscfunctions.qh>
#include <server/scores_rules.qh>
#include <server/spawnpoints.qh>
#include <server/steerlib.qh>
-#ifdef SVQC
- #include <server/sv_main.qh>
-#endif
#include <server/teamplay.qh>
#include <server/tests.qh>
#include <server/bot/_mod.qh>
#include <server/command/_mod.qh>
#include <server/compat/_mod.qh>
+#include <server/items/_mod.qh>
#include <server/mutators/_mod.qh>
#include <server/pathlib/_mod.qh>
#include <server/weapons/_mod.qh>
#include "antilag.qh"
#include "autocvars.qh"
-#include "defs.qh"
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/client.qh>
#include <server/gamelog.qh>
+#include <server/main.qh>
#include "miscfunctions.qh"
#include "command/common.qh"
#if defined(CSQC)
#elif defined(MENUQC)
#elif defined(SVQC)
- #include <server/defs.qh>
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
+ #include <server/weapons/common.qh>
#include <common/state.qh>
+ #include <common/monsters/sv_monsters.qh>
#include <common/vehicles/all.qh>
#include <lib/warpzone/common.qh>
#include "antilag.qh"
#pragma once
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <common/weapons/_all.qh>
#include <common/physics/player.qh>
+bool bot_waypoints_for_items;
+
const int WAYPOINTFLAG_GENERATED = BIT(23);
const int WAYPOINTFLAG_ITEM = BIT(22);
const int WAYPOINTFLAG_TELEPORT = BIT(21); // teleports, warpzones and jumppads
.float ignoregoaltime;
.entity ignoregoal;
+bool bots_would_leave;
+
+int player_count;
+int currentbots;
+
.entity bot_basewaypoint;
.bool navigation_dynamicgoal;
void navigation_dynamicgoal_init(entity this, bool initially_static);
void waypoint_getSymmetricalOrigin_cmd(entity caller, bool save, int arg_idx);
void waypoint_getSymmetricalAxis_cmd(entity caller, bool save, int arg_idx);
+
+IntrusiveList g_waypoints;
+IntrusiveList g_bot_targets;
+IntrusiveList g_bot_dodge;
+STATIC_INIT(botapi)
+{
+ g_waypoints = IL_NEW();
+ g_bot_targets = IL_NEW();
+ g_bot_dodge = IL_NEW();
+}
#include "aim.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include "cvars.qh"
#include "../../autocvars.qh"
#include "../../campaign.qh"
#include "../../client.qh"
-#include "../../constants.qh"
-#include "../../defs.qh"
+#include <common/stats.qh>
+#include <server/world.qh>
+#include <server/damage.qh>
#include "../../race.qh"
-#include <common/t_items.qh>
+#include <server/items/items.qh>
#include <server/mutators/_mod.qh>
#include "roles.qh"
-#include <server/defs.qh>
+#include <server/bot/api.qh>
+#include <server/client.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/damage.qh>
+#include <server/items/items.qh>
#include <server/miscfunctions.qh>
+#include <server/weapons/selection.qh>
+#include <server/weapons/weaponsystem.qh>
#include "../cvars.qh"
#include "../aim.qh"
#include <common/mapobjects/func/ladder.qh>
#include <common/mapobjects/teleporters.qh>
+#include <common/mapobjects/trigger/hurt.qh>
#include <common/mapobjects/trigger/jumppads.qh>
#include <lib/warpzone/common.qh>
#include "roles.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
-#include <server/items.qh>
+#include <server/items/items.qh>
+#include <server/items/spawning.qh>
#include <server/resources.qh>
#include "havocbot.qh"
#include "navigation.qh"
-#include <server/defs.qh>
+#include <server/bot/api.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include "cvars.qh"
#include "bot.qh"
#include "waypoints.qh"
-#include <common/t_items.qh>
+#include <server/items/items.qh>
#include <common/items/_mod.qh>
#include <common/constants.qh>
#include <common/net_linked.qh>
#include <common/mapobjects/func/ladder.qh>
+#include <common/mapobjects/trigger/hurt.qh>
#include <common/mapobjects/trigger/jumppads.qh>
.float speed;
#include "scripting.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
+#include <server/weapons/selection.qh>
+#include <server/weapons/weaponsystem.qh>
#include "cvars.qh"
#include <common/state.qh>
+#include <common/gamemodes/gamemode/ctf/sv_ctf.qh>
#include <common/physics/player.qh>
#include <common/wepent.qh>
#include "waypoints.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/items/items.qh>
#include <server/miscfunctions.qh>
+#include <server/spawnpoints.qh>
#include "cvars.qh"
#include "bot.qh"
#include "campaign.qh"
-#include "defs.qh"
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include "cheats.qh"
#include "miscfunctions.qh"
-#include "g_world.qh"
+#include "world.qh"
#include "../common/campaign_common.qh"
#include "cheats.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include <common/effects/all.qh>
#include <server/resources.qh>
+#include <server/main.qh>
-#include "g_damage.qh"
+#include "damage.qh"
#include "clientkill.qh"
#include "player.qh"
#include "race.qh"
#include "../common/monsters/_mod.qh"
+#include <common/items/_mod.qh>
+
#include <common/weapons/_all.qh>
#include "../common/mapobjects/subs.qh"
const float CHRAME_DRAG = 8;
+// speedrun: when 1, player auto teleports back when capture timeout happens
+.bool speedrunning;
+
+.entity personal;
+
+.int grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
+
bool drag_undraggable(entity draggee, entity dragger);
.bool(entity this, entity dragger) draggable;
#include "client.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include <common/effects/all.qh>
#include "anticheat.qh"
#include "teamplay.qh"
#include "spawnpoints.qh"
#include "resources.qh"
-#include "g_damage.qh"
+#include "damage.qh"
#include "handicap.qh"
-#include "g_hook.qh"
+#include "hook.qh"
#include "command/common.qh"
#include "command/vote.qh"
#include "clientkill.qh"
#include "cheats.qh"
-#include "g_world.qh"
+#include "world.qh"
#include <server/gamelog.qh>
#include "race.qh"
+#include <server/main.qh>
#include "antilag.qh"
#include "campaign.qh"
#include "command/common.qh"
#include "../common/vehicles/all.qh"
#include "weapons/hitplot.qh"
+#include "weapons/selection.qh"
#include "weapons/weaponsystem.qh"
#include "../common/net_notice.qh"
#include "../common/items/_mod.qh"
+#include <common/gamemodes/gamemode/nexball/sv_nexball.qh>
+
#include "../common/mutators/mutator/waypoints/all.qh"
#include "../common/mutators/mutator/instagib/sv_instagib.qh"
#include <common/gamemodes/_mod.qh>
#include <common/mutators/mutator/overkill/oknex.qh>
+#include <common/weapons/weapon/vortex.qh>
+
STATIC_METHOD(Client, Add, void(Client this, int _team))
{
ClientConnect(this);
{
if(!player) { return; } // not sure how, but best to be safe
+ int spec_count = 0;
FOREACH_CLIENT(IS_REAL_CLIENT(it) && IS_SPEC(it) && it != to && it.enemy == player,
{
+ if(spec_count >= MAX_SPECTATORS)
+ break;
WriteByte(MSG_ENTITY, num_for_edict(it));
+ ++spec_count;
});
}
this.alpha = 0;
this.scale = 0;
this.fade_time = 0;
- this.pain_frame = 0;
this.pain_finished = 0;
STAT(STRENGTH_FINISHED, this) = 0;
STAT(INVINCIBLE_FINISHED, this) = 0;
STAT(SUPERWEAPONS_FINISHED, this) = 0;
- this.air_finished = 0;
+ STAT(AIR_FINISHED, this) = 0;
//this.dphitcontentsmask = 0;
this.dphitcontentsmask = DPCONTENTS_SOLID;
if (autocvar_g_playerclip_collisions)
setthink(this, func_null);
this.nextthink = 0;
this.deadflag = DEAD_NO;
- this.crouch = false;
+ UNSET_DUCKED(this);
STAT(REVIVE_PROGRESS, this) = 0;
this.revival_time = 0;
this.draggable = drag_undraggable;
bool q3dfcompat = autocvar_sv_q3defragcompat && autocvar_sv_q3defragcompat_changehitbox;
this.scale = ((q3dfcompat) ? 0.9 : autocvar_sv_player_scale);
this.fade_time = 0;
- this.pain_frame = 0;
this.pain_finished = 0;
this.pushltime = 0;
setthink(this, func_null); // players have no think function
STAT(BUFFS, this) = 0;
STAT(BUFF_TIME, this) = 0;
- this.air_finished = 0;
+ STAT(AIR_FINISHED, this) = 0;
this.waterlevel = WATERLEVEL_NONE;
this.watertype = CONTENT_EMPTY;
this.spawnpoint_targ = NULL;
- this.crouch = false;
+ UNSET_DUCKED(this);
this.view_ofs = STAT(PL_VIEW_OFS, this);
setsize(this, STAT(PL_MIN, this), STAT(PL_MAX, this));
this.spawnorigin = spot.origin;
}
}
+void calculate_player_respawn_time(entity this)
+{
+ if(MUTATOR_CALLHOOK(CalculateRespawnTime, this))
+ return;
+
+ float gametype_setting_tmp;
+ float sdelay_max = GAMETYPE_DEFAULTED_SETTING(respawn_delay_max);
+ float sdelay_small = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small);
+ float sdelay_large = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large);
+ float sdelay_small_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small_count);
+ float sdelay_large_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large_count);
+ float waves = GAMETYPE_DEFAULTED_SETTING(respawn_waves);
+
+ float pcount = 1; // Include myself whether or not team is already set right and I'm a "player".
+ if (teamplay)
+ {
+ FOREACH_CLIENT(IS_PLAYER(it) && it != this, {
+ if(it.team == this.team)
+ ++pcount;
+ });
+ if (sdelay_small_count == 0)
+ sdelay_small_count = 1;
+ if (sdelay_large_count == 0)
+ sdelay_large_count = 1;
+ }
+ else
+ {
+ FOREACH_CLIENT(IS_PLAYER(it) && it != this, {
+ ++pcount;
+ });
+ if (sdelay_small_count == 0)
+ {
+ if (IS_INDEPENDENT_PLAYER(this))
+ {
+ // Players play independently. No point in requiring enemies.
+ sdelay_small_count = 1;
+ }
+ else
+ {
+ // Players play AGAINST each other. Enemies required.
+ sdelay_small_count = 2;
+ }
+ }
+ if (sdelay_large_count == 0)
+ {
+ if (IS_INDEPENDENT_PLAYER(this))
+ {
+ // Players play independently. No point in requiring enemies.
+ sdelay_large_count = 1;
+ }
+ else
+ {
+ // Players play AGAINST each other. Enemies required.
+ sdelay_large_count = 2;
+ }
+ }
+ }
+
+ float sdelay;
+
+ if (pcount <= sdelay_small_count)
+ sdelay = sdelay_small;
+ else if (pcount >= sdelay_large_count)
+ sdelay = sdelay_large;
+ else // NOTE: this case implies sdelay_large_count > sdelay_small_count.
+ sdelay = sdelay_small + (sdelay_large - sdelay_small) * (pcount - sdelay_small_count) / (sdelay_large_count - sdelay_small_count);
+
+ if(waves)
+ this.respawn_time = ceil((time + sdelay) / waves) * waves;
+ else
+ this.respawn_time = time + sdelay;
+
+ if(sdelay < sdelay_max)
+ this.respawn_time_max = time + sdelay_max;
+ else
+ this.respawn_time_max = this.respawn_time;
+
+ if((sdelay + waves >= 5.0) && (this.respawn_time - time > 1.75))
+ this.respawn_countdown = 10; // first number to count down from is 10
+ else
+ this.respawn_countdown = -1; // do not count down
+
+ if(autocvar_g_forced_respawn)
+ this.respawn_flags = this.respawn_flags | RESPAWN_FORCE;
+}
// LordHavoc: this hack will be removed when proper _pants/_shirt layers are
// added to the model skins
STAT(STRENGTH_FINISHED, this) = STAT(STRENGTH_FINISHED, spectatee);
STAT(INVINCIBLE_FINISHED, this) = STAT(INVINCIBLE_FINISHED, spectatee);
STAT(SUPERWEAPONS_FINISHED, this) = STAT(SUPERWEAPONS_FINISHED, spectatee);
- this.air_finished = spectatee.air_finished;
+ STAT(AIR_FINISHED, this) = STAT(AIR_FINISHED, spectatee);
STAT(PRESSED_KEYS, this) = STAT(PRESSED_KEYS, spectatee);
STAT(WEAPONS, this) = STAT(WEAPONS, spectatee);
this.punchangle = spectatee.punchangle;
this.dmg_team = max(0, this.dmg_team - autocvar_g_teamdamage_resetspeed * frametime);
}
- secrets_setstatus(this);
monsters_setstatus(this);
return true;
if(IS_DEAD(this) || game_stopped || time < game_starttime || this.vehicle
|| STAT(FROZEN, this) || this.watertype != CONTENT_WATER)
{
- this.air_finished = 0;
+ STAT(AIR_FINISHED, this) = 0;
return;
}
if (this.waterlevel != WATERLEVEL_SUBMERGED)
{
- if(this.air_finished && this.air_finished < time)
+ if(STAT(AIR_FINISHED, this) && STAT(AIR_FINISHED, this) < time)
PlayerSound(this, playersound_gasp, CH_PLAYER, VOL_BASE, VOICETYPE_PLAYERSOUND);
- this.air_finished = 0;
+ STAT(AIR_FINISHED, this) = 0;
}
else
{
- if (!this.air_finished)
- this.air_finished = time + autocvar_g_balance_contents_drowndelay;
- if (this.air_finished < time)
+ if (!STAT(AIR_FINISHED, this))
+ STAT(AIR_FINISHED, this) = time + autocvar_g_balance_contents_drowndelay;
+ if (STAT(AIR_FINISHED, this) < time)
{ // drown!
if (this.pain_finished < time)
{
#pragma once
#include "utils.qh"
+#include <common/replicate.qh>
#include <common/sounds/all.qh>
+// WEAPONTODO
+.string weaponorder_byimpulse;
+
+.entity clientdata;
+
+.float jointime; // time of connecting
+.float startplaytime; // time of switching from spectator to player
+.float alivetime; // time of being alive
+.float motd_actived_time; // used for both motd and campaign_message
+
+.bool wasplayer;
+
+.int spectatee_status;
+.bool zoomstate;
+
+.bool just_joined;
+
+.int pressedkeys;
+
+.int playerid;
+
+.string playermodel;
+.string playerskin;
+
void ClientState_attach(entity this);
IntrusiveList g_players;
return false;
}
+int autocvar__independent_players;
+bool independent_players;
+#define INDEPENDENT_PLAYERS (autocvar__independent_players ? (autocvar__independent_players > 0) : independent_players)
+#define IS_INDEPENDENT_PLAYER(e) ((e).solid == SOLID_TRIGGER)
+#define MAKE_INDEPENDENT_PLAYER(e) (((e).solid = SOLID_TRIGGER), ((e).frags = FRAGS_PLAYER_OUT_OF_GAME))
+
+.int killcount;
+
+//flood fields
+.float nickspamtime; // time of last nick change
+.float nickspamcount;
+.float floodcontrol_chat;
+.float floodcontrol_chatteam;
+.float floodcontrol_chattell;
+.float floodcontrol_voice;
+.float floodcontrol_voiceteam;
+
+// respawning
+.int respawn_flags;
+.float respawn_time;
+.float respawn_time_max;
+
+.float respawn_countdown; // next number to count
+
+const int RESPAWN_FORCE = BIT(0);
+const int RESPAWN_SILENT = BIT(1);
+const int RESPAWN_DENY = BIT(2);
+
+float blockSpectators; // if set, new or existing spectators or observers will be removed unless they become a player within g_maxplayers_spectator_blocktime seconds
+.float spectatortime; // point in time since the client is spectating or observing
+
+.bool player_blocked;
+
+const int SVC_SETVIEW = 5; // TODO: move to dpdefs where this belongs!
+
+// TODO: standardise resource regeneration
+.float pauseregen_finished;
+.float pauserothealth_finished;
+.float pauserotarmor_finished;
+.float pauserotfuel_finished;
+
+// idle kicking
+float sv_maxidle;
+float sv_maxidle_spectatorsareidle;
+int sv_maxidle_slots;
+bool sv_maxidle_slots_countbots;
+
+// g_<gametype>_str:
+// If 0, default is used.
+// If <0, 0 is used.
+// Otherwise, g_str (default value) is used.
+// For consistency, negative values there are mapped to zero too.
+#define GAMETYPE_DEFAULTED_SETTING(str) \
+ ((gametype_setting_tmp = cvar(strcat("g_", GetGametype(), "_" #str))), \
+ (gametype_setting_tmp < 0) ? 0 \
+ : (gametype_setting_tmp == 0 || autocvar_g_respawn_delay_forced) ? max(0, autocvar_g_##str) \
+ : gametype_setting_tmp)
+
+void calculate_player_respawn_time(entity this);
+
bool PlayerInList(entity player, string list);
+void ClientData_Touch(entity e);
+
+int nJoinAllowed(entity this, entity ignore);
+
+void FixIntermissionClient(entity e);
+
+void checkSpectatorBlock(entity this);
+
+void PlayerUseKey(entity this);
+
+void FixClientCvars(entity e);
+
+// called when a client connects, useful for updating sounds and such of static objects
+.void(entity this, entity player) init_for_player;
+
+IntrusiveList g_initforplayer;
+STATIC_INIT(g_initforplayer) { g_initforplayer = IL_NEW(); }
+
/// \brief Print the string to the client's chat.
/// \param[in] client Client to print to.
/// \param[in] text Text to print.
#define SPECTATE_COPYFIELD(fld) SPECTATE_COPY() { this.(fld) = spectatee.(fld); }
int Say(entity source, int teamsay, entity privatesay, string msgin, bool floodcontrol);
+
+const int MAX_SPECTATORS = 7;
#include "clientkill.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/client.qh>
+#include <server/player.qh>
-#include "g_damage.qh"
+#include "damage.qh"
#include "teamplay.qh"
#include <common/vehicles/sv_vehicles.qh>
+#include <common/mapobjects/triggers.qh>
#include <common/notifications/all.qh>
#include <common/stats.qh>
#include "banning.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include <common/state.qh>
#include <common/command/_mod.qh>
#include "cmd.qh"
-#include <server/defs.qh>
+#include <server/world.qh>
#include <server/miscfunctions.qh>
#include <common/command/_mod.qh>
#include "common.qh"
-#include <server/defs.qh>
+#include <server/client.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/world.qh>
#include <server/miscfunctions.qh>
#include <common/command/_mod.qh>
.float allowed_timeouts; // contains the number of allowed timeouts for each player
.vector lastV_angle; // used when pausing the game in order to force the player to keep his old view angle fixed
-// allow functions to be used in other code like g_world.qc and teamplay.qc
+// allow functions to be used in other code like world.qc and teamplay.qc
void timeout_handler_think(entity this);
// used by common/command/generic.qc:GenericCommand_dumpcommands to list all commands into a .txt file
#include "getreplies.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/world.qh>
#include <server/miscfunctions.qh>
#include <common/command/_mod.qh>
// Last updated: December 30th, 2011
// =========================================================
-// These strings are set usually during init in g_world.qc,
+// These strings are set usually during init in world.qc,
// or also by some game modes or other functions manually,
// and their purpose is to output information to clients
// without using any extra processing time.
string top_uids[LADDER_SIZE];
float top_scores[LADDER_SIZE];
-// allow functions to be used in other code like g_world.qc and race.qc
+// allow functions to be used in other code like world.qc and race.qc
string getrecords(float page);
string getrankings();
string getladder();
#ifdef RADARMAP
#include <common/command/_mod.qh>
+#include <common/mapobjects/triggers.qh>
-#include "../g_world.qh"
+#include "../world.qh"
#include <common/util.qh>
#include "../campaign.qh"
#include "../client.qh"
#include "../player.qh"
-#include "../g_world.qh"
+#include "../world.qh"
#include "../ipban.qh"
#include "../teamplay.qh"
#include "vote.qh"
-#include <server/defs.qh>
+#include <server/client.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/gamelog.qh>
#include <server/miscfunctions.qh>
#include "common.qh"
-#include "../g_damage.qh"
-#include "../g_world.qh"
+#include "../damage.qh"
+#include "../world.qh"
#include "../teamplay.qh"
#include "../race.qh"
#include "../round_handler.qh"
string vote_parsed_command; // command which is fixed after being parsed
string vote_parsed_display; // visual string which is fixed after being parsed
-// allow functions to be used in other code like g_world.qc and teamplay.qc
+// allow functions to be used in other code like world.qc and teamplay.qc
void VoteThink();
void VoteReset();
void VoteCommand(int request, entity caller, int argc, string vote_command);
float readyrestart_happened; // keeps track of whether a restart has already happened
float restart_mapalreadyrestarted; // bool, indicates whether reset_map() was already executed
.float ready; // flag for if a player is ready
+.int team_saved; // team number to restore upon map reset
+.void(entity this) reset; // if set, an entity is reset using this
+.void(entity this) reset2; // if set, an entity is reset using this (after calling ALL the reset functions for other entities)
void reset_map(float dorespawn);
void ReadyCount();
void ReadyRestart_force();
void VoteCount(float first_count);
void Nagger_Init();
+
+IntrusiveList g_saved_team;
+STATIC_INIT(g_saved_team) { g_saved_team = IL_NEW(); }
#include "quake.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include <common/weapons/_all.qh>
#include "quake3.qh"
-#include <server/defs.qh>
+#include <server/client.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
-#include <server/items.qh>
+#include <server/items/items.qh>
+#include <server/items/spawning.qh>
#include <server/resources.qh>
#include <common/gamemodes/_mod.qh>
-#include <common/t_items.qh>
#include <common/gamemodes/gamemode/ctf/sv_ctf.qh>
#include <common/mapobjects/triggers.qh>
#include <common/mapobjects/trigger/counter.qh>
//spawnfunc(item_doubler) /* handled by buffs mutator */
//spawnfunc(item_haste) /* handled by buffs mutator */
//spawnfunc(item_health) /* handled in t_quake.qc */
-//spawnfunc(item_health_large) /* handled in t_items.qc */
-//spawnfunc(item_health_small) /* handled in t_items.qc */
-//spawnfunc(item_health_mega) /* handled in t_items.qc */
+//spawnfunc(item_health_large) /* handled in items.qc */
+//spawnfunc(item_health_small) /* handled in items.qc */
+//spawnfunc(item_health_mega) /* handled in items.qc */
//spawnfunc(item_invis) /* handled by buffs mutator */
//spawnfunc(item_regen) /* handled by buffs mutator */
#include "wop.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
-#include <server/items.qh>
+#include <server/items/spawning.qh>
#include <common/weapons/_all.qh>
spawnfunc(item_haste);
+++ /dev/null
-#pragma once
-
-const int FL_WEAPON = BIT(13);
-const int FL_POWERUP = BIT(14);
-const int FL_PROJECTILE = BIT(15);
-const int FL_TOSSED = BIT(16);
-const int FL_NO_WEAPON_STAY = BIT(17);
-const int FL_SPAWNING = BIT(18);
-const int FL_PICKUPITEMS = BIT(19);
-
-const int SVC_SETVIEW = 5;
-
-const int RESPAWN_FORCE = BIT(0);
-const int RESPAWN_SILENT = BIT(1);
-const int RESPAWN_DENY = BIT(2);
-
-#define EFMASK_CHEAP (EF_ADDITIVE | EF_DOUBLESIDED | EF_FULLBRIGHT | EF_NODEPTHTEST | EF_NODRAW | EF_NOGUNBOB | EF_NOSHADOW | EF_LOWPRECISION | EF_SELECTABLE | EF_TELEPORT_BIT)
-
-const int NUM_PLAYERSKINS_TEAMPLAY = 3;
--- /dev/null
+#include "damage.qh"
+
+#include <common/effects/all.qh>
+#include "bot/api.qh"
+#include "hook.qh"
+#include <server/client.qh>
+#include <server/gamelog.qh>
+#include <server/items/items.qh>
+#include <server/mutators/_mod.qh>
+#include <server/main.qh>
+#include "teamplay.qh"
+#include "scores.qh"
+#include "spawnpoints.qh"
+#include "../common/state.qh"
+#include "../common/physics/player.qh"
+#include "resources.qh"
+#include "../common/vehicles/all.qh"
+#include "../common/items/_mod.qh"
+#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
+#include "../common/mutators/mutator/instagib/sv_instagib.qh"
+#include "../common/mutators/mutator/buffs/buffs.qh"
+#include "weapons/accuracy.qh"
+#include "weapons/csqcprojectile.qh"
+#include "weapons/selection.qh"
+#include "../common/constants.qh"
+#include "../common/deathtypes/all.qh"
+#include <common/mapobjects/defs.qh>
+#include <common/mapobjects/triggers.qh>
+#include "../common/notifications/all.qh"
+#include "../common/physics/movetypes/movetypes.qh"
+#include "../common/playerstats.qh"
+#include "../common/teams.qh"
+#include "../common/util.qh"
+#include <common/gamemodes/_mod.qh>
+#include <common/gamemodes/rules.qh>
+#include <common/weapons/_all.qh>
+#include "../lib/csqcmodel/sv_model.qh"
+#include "../lib/warpzone/common.qh"
+
+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)
+{
+ // TODO route through PlayerScores instead
+ if(game_stopped) return;
+
+ if(f < 0)
+ {
+ if(targ == attacker)
+ {
+ // suicide
+ GameRules_scoring_add(attacker, SUICIDES, 1);
+ }
+ else
+ {
+ // teamkill
+ GameRules_scoring_add(attacker, TEAMKILLS, 1);
+ }
+ }
+ else
+ {
+ // regular frag
+ GameRules_scoring_add(attacker, KILLS, 1);
+ if(!warmup_stage && targ.playerid)
+ PlayerStats_GameReport_Event_Player(attacker, sprintf("kills-%d", targ.playerid), 1);
+ }
+
+ GameRules_scoring_add(targ, DEATHS, 1);
+
+ // FIXME fix the mess this is (we have REAL points now!)
+ if(MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f, deathtype, attacker.(weaponentity)))
+ f = M_ARGV(2, float);
+
+ attacker.totalfrags += f;
+
+ if(f)
+ UpdateFrags(attacker, f);
+}
+
+string AppendItemcodes(string s, entity player)
+{
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ int w = player.(weaponentity).m_weapon.m_id;
+ if(w == 0)
+ w = player.(weaponentity).cnt; // previous weapon
+ if(w != 0 || slot == 0)
+ s = strcat(s, ftos(w));
+ }
+ if(time < STAT(STRENGTH_FINISHED, player))
+ s = strcat(s, "S");
+ if(time < STAT(INVINCIBLE_FINISHED, player))
+ s = strcat(s, "I");
+ if(PHYS_INPUT_BUTTON_CHAT(player))
+ s = strcat(s, "T");
+ // TODO: include these codes as a flag on the item itself
+ MUTATOR_CALLHOOK(LogDeath_AppendItemCodes, player, s);
+ s = M_ARGV(1, string);
+ return s;
+}
+
+void LogDeath(string mode, int deathtype, entity killer, entity killed)
+{
+ string s;
+ if(!autocvar_sv_eventlog)
+ return;
+ s = strcat(":kill:", mode);
+ s = strcat(s, ":", ftos(killer.playerid));
+ s = strcat(s, ":", ftos(killed.playerid));
+ s = strcat(s, ":type=", Deathtype_Name(deathtype));
+ s = strcat(s, ":items=");
+ s = AppendItemcodes(s, killer);
+ if(killed != killer)
+ {
+ s = strcat(s, ":victimitems=");
+ s = AppendItemcodes(s, killed);
+ }
+ GameLogEcho(s);
+}
+
+void Obituary_SpecialDeath(
+ entity notif_target,
+ float murder,
+ int deathtype,
+ string s1, string s2, string s3,
+ float f1, float f2, float f3)
+{
+ if(!DEATH_ISSPECIAL(deathtype))
+ {
+ backtrace("Obituary_SpecialDeath called without a special deathtype?\n");
+ return;
+ }
+
+ entity deathent = REGISTRY_GET(Deathtypes, deathtype - DT_FIRST);
+ if (!deathent)
+ {
+ backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n");
+ return;
+ }
+
+ if(g_cts && deathtype == DEATH_KILL.m_id)
+ return; // TODO: somehow put this in CTS gamemode file!
+
+ Notification death_message = (murder) ? deathent.death_msgmurder : deathent.death_msgself;
+ if(death_message)
+ {
+ Send_Notification_WOCOVA(
+ NOTIF_ONE,
+ notif_target,
+ MSG_MULTI,
+ death_message,
+ s1, s2, s3, "",
+ f1, f2, f3, 0
+ );
+ Send_Notification_WOCOVA(
+ NOTIF_ALL_EXCEPT,
+ notif_target,
+ MSG_INFO,
+ death_message.nent_msginfo,
+ s1, s2, s3, "",
+ f1, f2, f3, 0
+ );
+ }
+}
+
+float Obituary_WeaponDeath(
+ entity notif_target,
+ float murder,
+ int deathtype,
+ string s1, string s2, string s3,
+ float f1, float f2)
+{
+ Weapon death_weapon = DEATH_WEAPONOF(deathtype);
+ if (death_weapon == WEP_Null)
+ return false;
+
+ w_deathtype = deathtype;
+ Notification death_message = ((murder) ? death_weapon.wr_killmessage(death_weapon) : death_weapon.wr_suicidemessage(death_weapon));
+ w_deathtype = false;
+
+ if (death_message)
+ {
+ Send_Notification_WOCOVA(
+ NOTIF_ONE,
+ notif_target,
+ MSG_MULTI,
+ death_message,
+ s1, s2, s3, "",
+ f1, f2, 0, 0
+ );
+ // send the info part to everyone
+ Send_Notification_WOCOVA(
+ NOTIF_ALL_EXCEPT,
+ notif_target,
+ MSG_INFO,
+ death_message.nent_msginfo,
+ s1, s2, s3, "",
+ f1, f2, 0, 0
+ );
+ }
+ else
+ {
+ LOG_TRACEF(
+ "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %s!\n",
+ deathtype,
+ death_weapon.netname
+ );
+ }
+
+ return true;
+}
+
+bool frag_centermessage_override(entity attacker, entity targ, int deathtype, int kill_count_to_attacker, int kill_count_to_target, string attacker_name)
+{
+ if(deathtype == DEATH_FIRE.m_id)
+ {
+ Send_Notification(NOTIF_ONE, attacker, MSG_CHOICE, CHOICE_FRAG_FIRE, targ.netname, kill_count_to_attacker, (IS_BOT_CLIENT(targ) ? -1 : CS(targ).ping));
+ Send_Notification(NOTIF_ONE, targ, MSG_CHOICE, CHOICE_FRAGGED_FIRE, attacker_name, kill_count_to_target, GetResource(attacker, RES_HEALTH), GetResource(attacker, RES_ARMOR), (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping));
+ return true;
+ }
+
+ return MUTATOR_CALLHOOK(FragCenterMessage, attacker, targ, deathtype, kill_count_to_attacker, kill_count_to_target);
+}
+
+void Obituary(entity attacker, entity inflictor, entity targ, int deathtype, .entity weaponentity)
+{
+ // Sanity check
+ if (!IS_PLAYER(targ)) { backtrace("Obituary called on non-player?!\n"); return; }
+
+ // Declarations
+ float notif_firstblood = false;
+ float kill_count_to_attacker, kill_count_to_target;
+ bool notif_anonymous = false;
+ string attacker_name = attacker.netname;
+
+ // Set final information for the death
+ targ.death_origin = targ.origin;
+ string deathlocation = (autocvar_notification_server_allows_location ? NearestLocation(targ.death_origin) : "");
+
+ // Abort now if a mutator requests it
+ if (MUTATOR_CALLHOOK(ClientObituary, inflictor, attacker, targ, deathtype, attacker.(weaponentity))) { CS(targ).killcount = 0; return; }
+ notif_anonymous = M_ARGV(5, bool);
+
+ if(notif_anonymous)
+ attacker_name = "Anonymous player";
+
+ #ifdef NOTIFICATIONS_DEBUG
+ Debug_Notification(
+ sprintf(
+ "Obituary(%s, %s, %s, %s = %d);\n",
+ attacker_name,
+ inflictor.netname,
+ targ.netname,
+ Deathtype_Name(deathtype),
+ deathtype
+ )
+ );
+ #endif
+
+ // =======
+ // SUICIDE
+ // =======
+ if(targ == attacker)
+ {
+ if(DEATH_ISSPECIAL(deathtype))
+ {
+ if(deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
+ {
+ Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", targ.team, 0, 0);
+ }
+ else
+ {
+ switch(DEATH_ENT(deathtype))
+ {
+ case DEATH_MIRRORDAMAGE:
+ {
+ Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
+ break;
+ }
+
+ default:
+ {
+ Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
+ break;
+ }
+ }
+ }
+ }
+ else if (!Obituary_WeaponDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0))
+ {
+ backtrace("SUICIDE: what the hell happened here?\n");
+ return;
+ }
+ LogDeath("suicide", deathtype, targ, targ);
+ if(deathtype != DEATH_AUTOTEAMCHANGE.m_id) // special case: don't negate frags if auto switched
+ GiveFrags(attacker, targ, -1, deathtype, weaponentity);
+ }
+
+ // ======
+ // MURDER
+ // ======
+ else if(IS_PLAYER(attacker))
+ {
+ if(SAME_TEAM(attacker, targ))
+ {
+ LogDeath("tk", deathtype, attacker, targ);
+ GiveFrags(attacker, targ, -1, deathtype, weaponentity);
+
+ CS(attacker).killcount = 0;
+
+ Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAG, targ.netname);
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAGGED, attacker_name);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(targ.team, INFO_DEATH_TEAMKILL), targ.netname, attacker_name, deathlocation, CS(targ).killcount);
+
+ // In this case, the death message will ALWAYS be "foo was betrayed by bar"
+ // No need for specific death/weapon messages...
+ }
+ else
+ {
+ LogDeath("frag", deathtype, attacker, targ);
+ GiveFrags(attacker, targ, 1, deathtype, weaponentity);
+
+ CS(attacker).taunt_soundtime = time + 1;
+ CS(attacker).killcount = CS(attacker).killcount + 1;
+
+ attacker.killsound += 1;
+
+ // TODO: improve SPREE_ITEM and KILL_SPREE_LIST
+ // these 2 macros are spread over multiple files
+ #define SPREE_ITEM(counta,countb,center,normal,gentle) \
+ case counta: \
+ Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
+ if (!warmup_stage) \
+ PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
+ break;
+
+ switch(CS(attacker).killcount)
+ {
+ KILL_SPREE_LIST
+ default: break;
+ }
+ #undef SPREE_ITEM
+
+ if(!warmup_stage && !checkrules_firstblood)
+ {
+ checkrules_firstblood = true;
+ notif_firstblood = true; // modify the current messages so that they too show firstblood information
+ PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
+ PlayerStats_GameReport_Event_Player(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
+
+ // tell spree_inf and spree_cen that this is a first-blood and first-victim event
+ kill_count_to_attacker = -1;
+ kill_count_to_target = -2;
+ }
+ else
+ {
+ kill_count_to_attacker = CS(attacker).killcount;
+ kill_count_to_target = 0;
+ }
+
+ if(targ.istypefrag)
+ {
+ Send_Notification(
+ NOTIF_ONE,
+ attacker,
+ MSG_CHOICE,
+ CHOICE_TYPEFRAG,
+ targ.netname,
+ kill_count_to_attacker,
+ (IS_BOT_CLIENT(targ) ? -1 : CS(targ).ping)
+ );
+ Send_Notification(
+ NOTIF_ONE,
+ targ,
+ MSG_CHOICE,
+ CHOICE_TYPEFRAGGED,
+ attacker_name,
+ kill_count_to_target,
+ GetResource(attacker, RES_HEALTH),
+ GetResource(attacker, RES_ARMOR),
+ (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping)
+ );
+ }
+ else if(!frag_centermessage_override(attacker, targ, deathtype, kill_count_to_attacker, kill_count_to_target, attacker_name))
+ {
+ Send_Notification(
+ NOTIF_ONE,
+ attacker,
+ MSG_CHOICE,
+ CHOICE_FRAG,
+ targ.netname,
+ kill_count_to_attacker,
+ (IS_BOT_CLIENT(targ) ? -1 : CS(targ).ping)
+ );
+ Send_Notification(
+ NOTIF_ONE,
+ targ,
+ MSG_CHOICE,
+ CHOICE_FRAGGED,
+ attacker_name,
+ kill_count_to_target,
+ GetResource(attacker, RES_HEALTH),
+ GetResource(attacker, RES_ARMOR),
+ (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping)
+ );
+ }
+
+ int f3 = 0;
+ if(deathtype == DEATH_BUFF.m_id)
+ f3 = buff_FirstFromFlags(STAT(BUFFS, attacker)).m_id;
+
+ if (!Obituary_WeaponDeath(targ, true, deathtype, targ.netname, attacker_name, deathlocation, CS(targ).killcount, kill_count_to_attacker))
+ Obituary_SpecialDeath(targ, true, deathtype, targ.netname, attacker_name, deathlocation, CS(targ).killcount, kill_count_to_attacker, f3);
+ }
+ }
+
+ // =============
+ // ACCIDENT/TRAP
+ // =============
+ else
+ {
+ switch(DEATH_ENT(deathtype))
+ {
+ // For now, we're just forcing HURTTRIGGER to behave as "DEATH_VOID" and giving it no special options...
+ // Later on you will only be able to make custom messages using DEATH_CUSTOM,
+ // and there will be a REAL DEATH_VOID implementation which mappers will use.
+ case DEATH_HURTTRIGGER:
+ {
+ Obituary_SpecialDeath(targ, false, deathtype,
+ targ.netname,
+ inflictor.message,
+ deathlocation,
+ CS(targ).killcount,
+ 0,
+ 0);
+ break;
+ }
+
+ case DEATH_CUSTOM:
+ {
+ Obituary_SpecialDeath(targ, false, deathtype,
+ targ.netname,
+ ((strstrofs(deathmessage, "%", 0) < 0) ? strcat("%s ", deathmessage) : deathmessage),
+ deathlocation,
+ CS(targ).killcount,
+ 0,
+ 0);
+ break;
+ }
+
+ default:
+ {
+ Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
+ break;
+ }
+ }
+
+ LogDeath("accident", deathtype, targ, targ);
+ GiveFrags(targ, targ, -1, deathtype, weaponentity);
+
+ if(GameRules_scoring_add(targ, SCORE, 0) == -5)
+ {
+ Send_Notification(NOTIF_ONE, targ, MSG_ANNCE, ANNCE_ACHIEVEMENT_BOTLIKE);
+ if (!warmup_stage)
+ {
+ PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
+ }
+ }
+ }
+
+ // reset target kill count
+ CS(targ).killcount = 0;
+}
+
+void Ice_Think(entity this)
+{
+ if(!STAT(FROZEN, this.owner) || this.owner.iceblock != this)
+ {
+ delete(this);
+ return;
+ }
+ vector ice_org = this.owner.origin - '0 0 16';
+ if (this.origin != ice_org)
+ setorigin(this, ice_org);
+ this.nextthink = time;
+}
+
+void Freeze(entity targ, float revivespeed, int frozen_type, bool show_waypoint)
+{
+ if(!IS_PLAYER(targ) && !IS_MONSTER(targ)) // TODO: only specified entities can be freezed
+ return;
+
+ if(STAT(FROZEN, targ))
+ return;
+
+ float targ_maxhealth = ((IS_MONSTER(targ)) ? targ.max_health : start_health);
+
+ STAT(FROZEN, targ) = frozen_type;
+ STAT(REVIVE_PROGRESS, targ) = ((frozen_type == FROZEN_TEMP_DYING) ? 1 : 0);
+ SetResource(targ, RES_HEALTH, ((frozen_type == FROZEN_TEMP_DYING) ? targ_maxhealth : 1));
+ targ.revive_speed = revivespeed;
+ if(targ.bot_attack)
+ IL_REMOVE(g_bot_targets, targ);
+ targ.bot_attack = false;
+ targ.freeze_time = time;
+
+ entity ice = new(ice);
+ ice.owner = targ;
+ ice.scale = targ.scale;
+ // set_movetype(ice, MOVETYPE_FOLLOW) would rotate the ice model with the player
+ setthink(ice, Ice_Think);
+ ice.nextthink = time;
+ ice.frame = floor(random() * 21); // ice model has 20 different looking frames
+ setmodel(ice, MDL_ICE);
+ ice.alpha = 1;
+ ice.colormod = Team_ColorRGB(targ.team);
+ ice.glowmod = ice.colormod;
+ targ.iceblock = ice;
+ targ.revival_time = 0;
+
+ Ice_Think(ice);
+
+ RemoveGrapplingHooks(targ);
+
+ FOREACH_CLIENT(IS_PLAYER(it),
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(it.(weaponentity).hook.aiment == targ)
+ RemoveHook(it.(weaponentity).hook);
+ }
+ });
+
+ // add waypoint
+ if(MUTATOR_CALLHOOK(Freeze, targ, revivespeed, frozen_type) || show_waypoint)
+ WaypointSprite_Spawn(WP_Frozen, 0, 0, targ, '0 0 64', NULL, targ.team, targ, waypointsprite_attached, true, RADARICON_WAYPOINT);
+}
+
+void Unfreeze(entity targ, bool reset_health)
+{
+ if(!STAT(FROZEN, targ))
+ return;
+
+ if (reset_health && STAT(FROZEN, targ) != FROZEN_TEMP_DYING)
+ SetResource(targ, RES_HEALTH, ((IS_PLAYER(targ)) ? start_health : targ.max_health));
+
+ targ.pauseregen_finished = time + autocvar_g_balance_pause_health_regen;
+
+ STAT(FROZEN, targ) = 0;
+ STAT(REVIVE_PROGRESS, targ) = 0;
+ targ.revival_time = time;
+ if(!targ.bot_attack)
+ IL_PUSH(g_bot_targets, targ);
+ targ.bot_attack = true;
+
+ WaypointSprite_Kill(targ.waypointsprite_attached);
+
+ FOREACH_CLIENT(IS_PLAYER(it),
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(it.(weaponentity).hook.aiment == targ)
+ RemoveHook(it.(weaponentity).hook);
+ }
+ });
+
+ // remove the ice block
+ if(targ.iceblock)
+ delete(targ.iceblock);
+ targ.iceblock = NULL;
+
+ MUTATOR_CALLHOOK(Unfreeze, targ);
+}
+
+void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
+{
+ float complainteamdamage = 0;
+ float mirrordamage = 0;
+ float mirrorforce = 0;
+
+ if (game_stopped || (IS_CLIENT(targ) && CS(targ).killcount == FRAGS_SPECTATOR))
+ return;
+
+ entity attacker_save = attacker;
+
+ // special rule: gravity bombs and sound-based attacks do not affect team mates (other than for disconnecting the hook)
+ if(DEATH_ISWEAPON(deathtype, WEP_HOOK) || (deathtype & HITTYPE_SOUND))
+ {
+ if(IS_PLAYER(targ) && SAME_TEAM(targ, attacker))
+ {
+ return;
+ }
+ }
+
+ if(deathtype == DEATH_KILL.m_id || deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
+ {
+ // exit the vehicle before killing (fixes a crash)
+ if(IS_PLAYER(targ) && targ.vehicle)
+ vehicles_exit(targ.vehicle, VHEF_RELEASE);
+
+ // These are ALWAYS lethal
+ // No damage modification here
+ // Instead, prepare the victim for his death...
+ SetResourceExplicit(targ, RES_ARMOR, 0);
+ targ.spawnshieldtime = 0;
+ SetResourceExplicit(targ, RES_HEALTH, 0.9); // this is < 1
+ targ.flags -= targ.flags & FL_GODMODE;
+ damage = 100000;
+ }
+ else if(deathtype == DEATH_MIRRORDAMAGE.m_id || deathtype == DEATH_NOAMMO.m_id)
+ {
+ // no processing
+ }
+ else
+ {
+ // nullify damage if teamplay is on
+ if(deathtype != DEATH_TELEFRAG.m_id)
+ if(IS_PLAYER(attacker))
+ {
+ if(IS_PLAYER(targ) && targ != attacker && (IS_INDEPENDENT_PLAYER(attacker) || IS_INDEPENDENT_PLAYER(targ)))
+ {
+ damage = 0;
+ force = '0 0 0';
+ }
+ else if(SAME_TEAM(attacker, targ))
+ {
+ if(autocvar_teamplay_mode == 1)
+ damage = 0;
+ else if(attacker != targ)
+ {
+ if(autocvar_teamplay_mode == 2)
+ {
+ if(IS_PLAYER(targ) && !IS_DEAD(targ))
+ {
+ attacker.dmg_team = attacker.dmg_team + damage;
+ complainteamdamage = attacker.dmg_team - autocvar_g_teamdamage_threshold;
+ }
+ }
+ else if(autocvar_teamplay_mode == 3)
+ damage = 0;
+ else if(autocvar_teamplay_mode == 4)
+ {
+ if(IS_PLAYER(targ) && !IS_DEAD(targ))
+ {
+ attacker.dmg_team = attacker.dmg_team + damage;
+ complainteamdamage = attacker.dmg_team - autocvar_g_teamdamage_threshold;
+ if(complainteamdamage > 0)
+ mirrordamage = autocvar_g_mirrordamage * complainteamdamage;
+ mirrorforce = autocvar_g_mirrordamage * vlen(force);
+ damage = autocvar_g_friendlyfire * damage;
+ // mirrordamage will be used LATER
+
+ if(autocvar_g_mirrordamage_virtual)
+ {
+ vector v = healtharmor_applydamage(GetResource(attacker, RES_ARMOR), autocvar_g_balance_armor_blockpercent, deathtype, mirrordamage);
+ attacker.dmg_take += v.x;
+ attacker.dmg_save += v.y;
+ attacker.dmg_inflictor = inflictor;
+ mirrordamage = v.z;
+ mirrorforce = 0;
+ }
+
+ if(autocvar_g_friendlyfire_virtual)
+ {
+ vector v = healtharmor_applydamage(GetResource(targ, RES_ARMOR), autocvar_g_balance_armor_blockpercent, deathtype, damage);
+ targ.dmg_take += v.x;
+ targ.dmg_save += v.y;
+ targ.dmg_inflictor = inflictor;
+ damage = 0;
+ if(!autocvar_g_friendlyfire_virtual_force)
+ force = '0 0 0';
+ }
+ }
+ else if(!targ.canteamdamage)
+ damage = 0;
+ }
+ }
+ }
+ }
+
+ if (!DEATH_ISSPECIAL(deathtype))
+ {
+ damage *= g_weapondamagefactor;
+ mirrordamage *= g_weapondamagefactor;
+ complainteamdamage *= g_weapondamagefactor;
+ force = force * g_weaponforcefactor;
+ mirrorforce *= g_weaponforcefactor;
+ }
+
+ // should this be changed at all? If so, in what way?
+ MUTATOR_CALLHOOK(Damage_Calculate, inflictor, attacker, targ, deathtype, damage, mirrordamage, force, attacker.(weaponentity));
+ damage = M_ARGV(4, float);
+ mirrordamage = M_ARGV(5, float);
+ force = M_ARGV(6, vector);
+
+ if(IS_PLAYER(targ) && damage > 0 && attacker)
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity went = weaponentities[slot];
+ if(targ.(went).hook && targ.(went).hook.aiment == attacker)
+ RemoveHook(targ.(went).hook);
+ }
+ }
+
+ if(STAT(FROZEN, targ) && !ITEM_DAMAGE_NEEDKILL(deathtype)
+ && deathtype != DEATH_TEAMCHANGE.m_id && deathtype != DEATH_AUTOTEAMCHANGE.m_id)
+ {
+ if(autocvar_g_frozen_revive_falldamage > 0 && deathtype == DEATH_FALL.m_id && damage >= autocvar_g_frozen_revive_falldamage)
+ {
+ Unfreeze(targ, false);
+ SetResource(targ, RES_HEALTH, autocvar_g_frozen_revive_falldamage_health);
+ Send_Effect(EFFECT_ICEORGLASS, targ.origin, '0 0 0', 3);
+ Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED_FALL, targ.netname);
+ Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF);
+ }
+
+ damage = 0;
+ force *= autocvar_g_frozen_force;
+ }
+
+ if(IS_PLAYER(targ) && STAT(FROZEN, targ)
+ && ITEM_DAMAGE_NEEDKILL(deathtype) && !autocvar_g_frozen_damage_trigger)
+ {
+ Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
+
+ entity spot = SelectSpawnPoint(targ, false);
+ if(spot)
+ {
+ damage = 0;
+ targ.deadflag = DEAD_NO;
+
+ targ.angles = spot.angles;
+
+ targ.effects = 0;
+ targ.effects |= EF_TELEPORT_BIT;
+
+ targ.angles_z = 0; // never spawn tilted even if the spot says to
+ targ.fixangle = true; // turn this way immediately
+ targ.velocity = '0 0 0';
+ targ.avelocity = '0 0 0';
+ targ.punchangle = '0 0 0';
+ targ.punchvector = '0 0 0';
+ targ.oldvelocity = targ.velocity;
+
+ targ.spawnorigin = spot.origin;
+ setorigin(targ, spot.origin + '0 0 1' * (1 - targ.mins.z - 24));
+ // don't reset back to last position, even if new position is stuck in solid
+ targ.oldorigin = targ.origin;
+
+ Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
+ }
+ }
+
+ if(!MUTATOR_IS_ENABLED(mutator_instagib))
+ {
+ // apply strength multiplier
+ if (attacker.items & ITEM_Strength.m_itemid)
+ {
+ if(targ == attacker)
+ {
+ damage = damage * autocvar_g_balance_powerup_strength_selfdamage;
+ force = force * autocvar_g_balance_powerup_strength_selfforce;
+ }
+ else
+ {
+ damage = damage * autocvar_g_balance_powerup_strength_damage;
+ force = force * autocvar_g_balance_powerup_strength_force;
+ }
+ }
+
+ // apply invincibility multiplier
+ if (targ.items & ITEM_Shield.m_itemid)
+ {
+ damage = damage * autocvar_g_balance_powerup_invincible_takedamage;
+ if (targ != attacker)
+ {
+ force = force * autocvar_g_balance_powerup_invincible_takeforce;
+ }
+ }
+ }
+
+ if (targ == attacker)
+ damage = damage * autocvar_g_balance_selfdamagepercent; // Partial damage if the attacker hits himself
+
+ // count the damage
+ if(attacker)
+ if(!IS_DEAD(targ))
+ if(deathtype != DEATH_BUFF.m_id)
+ if(targ.takedamage == DAMAGE_AIM)
+ if(targ != attacker)
+ {
+ entity victim;
+ if(IS_VEHICLE(targ) && targ.owner)
+ victim = targ.owner;
+ else
+ victim = targ;
+
+ if(IS_PLAYER(victim) || (IS_TURRET(victim) && victim.active == ACTIVE_ACTIVE) || IS_MONSTER(victim) || MUTATOR_CALLHOOK(PlayHitsound, victim, attacker))
+ {
+ if(DIFF_TEAM(victim, attacker) && !STAT(FROZEN, victim))
+ {
+ if(damage > 0)
+ {
+ if(deathtype != DEATH_FIRE.m_id)
+ {
+ if(PHYS_INPUT_BUTTON_CHAT(victim))
+ attacker.typehitsound += 1;
+ else
+ attacker.damage_dealt += damage;
+ }
+
+ damage_goodhits += 1;
+ damage_gooddamage += damage;
+
+ if (!DEATH_ISSPECIAL(deathtype))
+ {
+ if(IS_PLAYER(targ)) // don't do this for vehicles
+ if(IsFlying(victim))
+ yoda = 1;
+ }
+ }
+ }
+ else if(IS_PLAYER(attacker))
+ {
+ // if enemy gets frozen in this frame and receives other damage don't
+ // play the typehitsound e.g. when hit by multiple bullets of the shotgun
+ if (deathtype != DEATH_FIRE.m_id && (!STAT(FROZEN, victim) || time > victim.freeze_time))
+ {
+ attacker.typehitsound += 1;
+ }
+ if(complainteamdamage > 0)
+ if(time > CS(attacker).teamkill_complain)
+ {
+ CS(attacker).teamkill_complain = time + 5;
+ CS(attacker).teamkill_soundtime = time + 0.4;
+ CS(attacker).teamkill_soundsource = targ;
+ }
+ }
+ }
+ }
+ }
+
+ // apply push
+ if (targ.damageforcescale)
+ if (force)
+ if (!IS_PLAYER(targ) || time >= targ.spawnshieldtime || targ == attacker)
+ {
+ vector farce = damage_explosion_calcpush(targ.damageforcescale * force, targ.velocity, autocvar_g_balance_damagepush_speedfactor);
+ if(targ.move_movetype == MOVETYPE_PHYSICS)
+ {
+ entity farcent = new(farce);
+ farcent.enemy = targ;
+ farcent.movedir = farce * 10;
+ if(targ.mass)
+ farcent.movedir = farcent.movedir * targ.mass;
+ farcent.origin = hitloc;
+ farcent.forcetype = FORCETYPE_FORCEATPOS;
+ farcent.nextthink = time + 0.1;
+ setthink(farcent, SUB_Remove);
+ }
+ else if(targ.move_movetype != MOVETYPE_NOCLIP)
+ {
+ targ.velocity = targ.velocity + farce;
+ }
+ UNSET_ONGROUND(targ);
+ UpdateCSQCProjectile(targ);
+ }
+ // apply damage
+ if (damage != 0 || (targ.damageforcescale && force))
+ if (targ.event_damage)
+ targ.event_damage (targ, inflictor, attacker, damage, deathtype, weaponentity, hitloc, force);
+
+ // apply mirror damage if any
+ if(!autocvar_g_mirrordamage_onlyweapons || DEATH_WEAPONOF(deathtype) != WEP_Null)
+ if(mirrordamage > 0 || mirrorforce > 0)
+ {
+ attacker = attacker_save;
+
+ force = normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce;
+ Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE.m_id, weaponentity, attacker.origin, force);
+ }
+}
+
+float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe,
+ float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype, .entity weaponentity, entity directhitentity)
+ // Returns total damage applies to creatures
+{
+ entity targ;
+ vector force;
+ float total_damage_to_creatures;
+ entity next;
+ float tfloordmg;
+ float tfloorforce;
+
+ float stat_damagedone;
+
+ if(RadiusDamage_running)
+ {
+ backtrace("RadiusDamage called recursively! Expect stuff to go HORRIBLY wrong.");
+ return 0;
+ }
+
+ RadiusDamage_running = 1;
+
+ tfloordmg = autocvar_g_throughfloor_damage;
+ tfloorforce = autocvar_g_throughfloor_force;
+
+ total_damage_to_creatures = 0;
+
+ if(deathtype != (WEP_HOOK.m_id | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once
+ if(!(deathtype & HITTYPE_SOUND)) // do not send radial sound damage (bandwidth hog)
+ {
+ force = inflictorvelocity;
+ if(force == '0 0 0')
+ force = '0 0 -1';
+ else
+ force = normalize(force);
+ if(forceintensity >= 0)
+ Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
+ else
+ Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
+ }
+
+ stat_damagedone = 0;
+
+ targ = WarpZone_FindRadius (inflictororigin, rad + MAX_DAMAGEEXTRARADIUS, false);
+ while (targ)
+ {
+ next = targ.chain;
+ if ((targ != inflictor) || inflictorselfdamage)
+ if (((cantbe != targ) && !mustbe) || (mustbe == targ))
+ if (targ.takedamage)
+ {
+ vector nearest;
+ vector diff;
+ float power;
+
+ // LordHavoc: measure distance to nearest point on target (not origin)
+ // (this guarentees 100% damage on a touch impact)
+ nearest = targ.WarpZone_findradius_nearest;
+ diff = targ.WarpZone_findradius_dist;
+ // round up a little on the damage to ensure full damage on impacts
+ // and turn the distance into a fraction of the radius
+ power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad);
+ //bprint(" ");
+ //bprint(ftos(power));
+ //if (targ == attacker)
+ // print(ftos(power), "\n");
+ if (power > 0)
+ {
+ float finaldmg;
+ if (power > 1)
+ power = 1;
+ finaldmg = coredamage * power + edgedamage * (1 - power);
+ if (finaldmg > 0)
+ {
+ float a;
+ float c;
+ vector hitloc;
+ vector myblastorigin;
+ vector center;
+
+ myblastorigin = WarpZone_TransformOrigin(targ, inflictororigin);
+
+ // if it's a player, use the view origin as reference
+ center = CENTER_OR_VIEWOFS(targ);
+
+ force = normalize(center - myblastorigin);
+ force = force * (finaldmg / coredamage) * forceintensity;
+ hitloc = nearest;
+
+ // apply special scaling along the z axis if set
+ // NOTE: 0 value is not allowed for compatibility, in the case of weapon cvars not being set
+ if(forcezscale)
+ force.z *= forcezscale;
+
+ if(targ != directhitentity)
+ {
+ float hits;
+ float total;
+ float hitratio;
+ float mininv_f, mininv_d;
+
+ // test line of sight to multiple positions on box,
+ // and do damage if any of them hit
+ hits = 0;
+
+ // we know: max stddev of hitratio = 1 / (2 * sqrt(n))
+ // so for a given max stddev:
+ // n = (1 / (2 * max stddev of hitratio))^2
+
+ mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev;
+ mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
+
+ if(autocvar_g_throughfloor_debug)
+ LOG_INFOF("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f);
+
+
+ total = 0.25 * (max(mininv_f, mininv_d) ** 2);
+
+ if(autocvar_g_throughfloor_debug)
+ LOG_INFOF(" steps=%f", total);
+
+
+ if (IS_PLAYER(targ))
+ total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player));
+ else
+ total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other));
+
+ if(autocvar_g_throughfloor_debug)
+ LOG_INFOF(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)));
+
+ for(c = 0; c < total; ++c)
+ {
+ //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
+ WarpZone_TraceLine(inflictororigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
+ if (trace_fraction == 1 || trace_ent == targ)
+ {
+ ++hits;
+ if (hits > 1)
+ hitloc = hitloc + nearest;
+ else
+ hitloc = nearest;
+ }
+ nearest.x = targ.origin.x + targ.mins.x + random() * targ.size.x;
+ nearest.y = targ.origin.y + targ.mins.y + random() * targ.size.y;
+ nearest.z = targ.origin.z + targ.mins.z + random() * targ.size.z;
+ }
+
+ nearest = hitloc * (1 / max(1, hits));
+ hitratio = (hits / total);
+ a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1);
+ finaldmg = finaldmg * a;
+ a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1);
+ force = force * a;
+
+ if(autocvar_g_throughfloor_debug)
+ LOG_INFOF(" D=%f F=%f", finaldmg, vlen(force));
+ }
+
+ //if (targ == attacker)
+ //{
+ // print("hits ", ftos(hits), " / ", ftos(total));
+ // print(" finaldmg ", ftos(finaldmg), " force ", vtos(force));
+ // print(" (", ftos(a), ")\n");
+ //}
+ if(finaldmg || force)
+ {
+ if(targ.iscreature)
+ {
+ total_damage_to_creatures += finaldmg;
+
+ if(accuracy_isgooddamage(attacker, targ))
+ stat_damagedone += finaldmg;
+ }
+
+ if(targ == directhitentity || DEATH_ISSPECIAL(deathtype))
+ Damage(targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force);
+ else
+ Damage(targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, weaponentity, nearest, force);
+ }
+ }
+ }
+ }
+ targ = next;
+ }
+
+ RadiusDamage_running = 0;
+
+ if(!DEATH_ISSPECIAL(deathtype))
+ accuracy_add(attacker, DEATH_WEAPONOF(deathtype), 0, min(coredamage, stat_damagedone));
+
+ 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)
+{
+ return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad,
+ cantbe, mustbe, false, forceintensity, 1, deathtype, weaponentity, directhitentity);
+}
+
+bool Heal(entity targ, entity inflictor, float amount, float limit)
+{
+ if(game_stopped || (IS_CLIENT(targ) && CS(targ).killcount == FRAGS_SPECTATOR) || STAT(FROZEN, targ) || IS_DEAD(targ))
+ return false;
+
+ bool healed = false;
+ if(targ.event_heal)
+ healed = targ.event_heal(targ, inflictor, amount, limit);
+ // TODO: additional handling? what if the healing kills them? should this abort if healing would do so etc
+ // TODO: healing fx!
+ // TODO: armor healing?
+ return healed;
+}
+
+float Fire_IsBurning(entity e)
+{
+ return (time < e.fire_endtime);
+}
+
+float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
+{
+ float dps;
+ float maxtime, mintime, maxdamage, mindamage, maxdps, mindps, totaldamage, totaltime;
+
+ if(IS_PLAYER(e))
+ {
+ if(IS_DEAD(e))
+ return -1;
+ }
+ else
+ {
+ if(!e.fire_burner)
+ {
+ // print("adding a fire burner to ", e.classname, "\n");
+ e.fire_burner = new(fireburner);
+ setthink(e.fire_burner, fireburner_think);
+ e.fire_burner.nextthink = time;
+ e.fire_burner.owner = e;
+ }
+ }
+
+ t = max(t, 0.1);
+ dps = d / t;
+ if(Fire_IsBurning(e))
+ {
+ mintime = e.fire_endtime - time;
+ maxtime = max(mintime, t);
+
+ mindps = e.fire_damagepersec;
+ maxdps = max(mindps, dps);
+
+ if(maxtime > mintime || maxdps > mindps)
+ {
+ // Constraints:
+
+ // damage we have right now
+ mindamage = mindps * mintime;
+
+ // damage we want to get
+ maxdamage = mindamage + d;
+
+ // but we can't exceed maxtime * maxdps!
+ totaldamage = min(maxdamage, maxtime * maxdps);
+
+ // LEMMA:
+ // Look at:
+ // totaldamage = min(mindamage + d, maxtime * maxdps)
+ // We see:
+ // totaldamage <= maxtime * maxdps
+ // ==> totaldamage / maxdps <= maxtime.
+ // We also see:
+ // totaldamage / mindps = min(mindamage / mindps + d, maxtime * maxdps / mindps)
+ // >= min(mintime, maxtime)
+ // ==> totaldamage / maxdps >= mintime.
+
+ /*
+ // how long do we damage then?
+ // at least as long as before
+ // but, never exceed maxdps
+ totaltime = max(mintime, totaldamage / maxdps); // always <= maxtime due to lemma
+ */
+
+ // alternate:
+ // at most as long as maximum allowed
+ // but, never below mindps
+ totaltime = min(maxtime, totaldamage / mindps); // always >= mintime due to lemma
+
+ // assuming t > mintime, dps > mindps:
+ // we get d = t * dps = maxtime * maxdps
+ // totaldamage = min(maxdamage, maxtime * maxdps) = min(... + d, maxtime * maxdps) = maxtime * maxdps
+ // totaldamage / maxdps = maxtime
+ // totaldamage / mindps > totaldamage / maxdps = maxtime
+ // FROM THIS:
+ // a) totaltime = max(mintime, maxtime) = maxtime
+ // b) totaltime = min(maxtime, totaldamage / maxdps) = maxtime
+
+ // assuming t <= mintime:
+ // we get maxtime = mintime
+ // a) totaltime = max(mintime, ...) >= mintime, also totaltime <= maxtime by the lemma, therefore totaltime = mintime = maxtime
+ // b) totaltime = min(maxtime, ...) <= maxtime, also totaltime >= mintime by the lemma, therefore totaltime = mintime = maxtime
+
+ // assuming dps <= mindps:
+ // we get mindps = maxdps.
+ // With this, the lemma says that mintime <= totaldamage / mindps = totaldamage / maxdps <= maxtime.
+ // a) totaltime = max(mintime, totaldamage / maxdps) = totaldamage / maxdps
+ // b) totaltime = min(maxtime, totaldamage / mindps) = totaldamage / maxdps
+
+ e.fire_damagepersec = totaldamage / totaltime;
+ e.fire_endtime = time + totaltime;
+ if(totaldamage > 1.2 * mindamage)
+ {
+ e.fire_deathtype = dt;
+ if(e.fire_owner != o)
+ {
+ e.fire_owner = o;
+ e.fire_hitsound = false;
+ }
+ }
+ if(accuracy_isgooddamage(o, e))
+ accuracy_add(o, DEATH_WEAPONOF(dt), 0, max(0, totaldamage - mindamage));
+ return max(0, totaldamage - mindamage); // can never be negative, but to make sure
+ }
+ else
+ return 0;
+ }
+ else
+ {
+ e.fire_damagepersec = dps;
+ e.fire_endtime = time + t;
+ e.fire_deathtype = dt;
+ e.fire_owner = o;
+ e.fire_hitsound = false;
+ if(accuracy_isgooddamage(o, e))
+ accuracy_add(o, DEATH_WEAPONOF(dt), 0, d);
+ return d;
+ }
+}
+
+void Fire_ApplyDamage(entity e)
+{
+ float t, d, hi, ty;
+ entity o;
+
+ if (!Fire_IsBurning(e))
+ return;
+
+ for(t = 0, o = e.owner; o.owner && t < 16; o = o.owner, ++t);
+ if(IS_NOT_A_CLIENT(o))
+ o = e.fire_owner;
+
+ // water and slime stop fire
+ if(e.waterlevel)
+ if(e.watertype != CONTENT_LAVA)
+ e.fire_endtime = 0;
+
+ // ice stops fire
+ if(STAT(FROZEN, e))
+ e.fire_endtime = 0;
+
+ t = min(frametime, e.fire_endtime - time);
+ d = e.fire_damagepersec * t;
+
+ hi = e.fire_owner.damage_dealt;
+ ty = e.fire_owner.typehitsound;
+ Damage(e, e, e.fire_owner, d, e.fire_deathtype, DMG_NOWEP, e.origin, '0 0 0');
+ if(e.fire_hitsound && e.fire_owner)
+ {
+ e.fire_owner.damage_dealt = hi;
+ e.fire_owner.typehitsound = ty;
+ }
+ e.fire_hitsound = true;
+
+ if(!IS_INDEPENDENT_PLAYER(e) && !STAT(FROZEN, e))
+ {
+ IL_EACH(g_damagedbycontents, it.damagedbycontents && it != e,
+ {
+ if(!IS_DEAD(it) && it.takedamage && !IS_INDEPENDENT_PLAYER(it))
+ if(boxesoverlap(e.absmin, e.absmax, it.absmin, it.absmax))
+ {
+ t = autocvar_g_balance_firetransfer_time * (e.fire_endtime - time);
+ d = autocvar_g_balance_firetransfer_damage * e.fire_damagepersec * t;
+ Fire_AddDamage(it, o, d, t, DEATH_FIRE.m_id);
+ }
+ });
+ }
+}
+
+void Fire_ApplyEffect(entity e)
+{
+ if(Fire_IsBurning(e))
+ e.effects |= EF_FLAME;
+ else
+ e.effects &= ~EF_FLAME;
+}
+
+void fireburner_think(entity this)
+{
+ // for players, this is done in the regular loop
+ if(wasfreed(this.owner))
+ {
+ delete(this);
+ return;
+ }
+ Fire_ApplyEffect(this.owner);
+ if(!Fire_IsBurning(this.owner))
+ {
+ this.owner.fire_burner = NULL;
+ delete(this);
+ return;
+ }
+ Fire_ApplyDamage(this.owner);
+ this.nextthink = time;
+}
--- /dev/null
+#pragma once
+
+#if defined(CSQC)
+#elif defined(MENUQC)
+#elif defined(SVQC)
+ #include <common/weapons/_all.qh>
+ #include <common/stats.qh>
+ #include <server/items/items.qh>
+ #include <server/miscfunctions.qh>
+ #include <lib/warpzone/common.qh>
+ #include <common/constants.qh>
+ #include <common/teams.qh>
+ #include <common/util.qh>
+ #include <common/weapons/_all.qh>
+ #include "weapons/accuracy.qh"
+ #include "weapons/csqcprojectile.qh"
+ #include "weapons/selection.qh"
+ #include "autocvars.qh"
+ #include <common/notifications/all.qh>
+ #include <common/deathtypes/all.qh>
+ #include <server/mutators/_mod.qh>
+ #include <common/turrets/sv_turrets.qh>
+ #include <common/vehicles/all.qh>
+ #include <lib/csqcmodel/sv_model.qh>
+ #include <common/playerstats.qh>
+ #include "hook.qh"
+ #include "scores.qh"
+ #include "spawnpoints.qh"
+#endif
+
+.void(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) event_damage;
+
+.bool(entity targ, entity inflictor, float amount, float limit) event_heal;
+
+.float dmg;
+.float dmg_edge;
+.float dmg_force;
+.float dmg_radius;
+
+bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf);
+
+void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner);
+
+float checkrules_firstblood;
+
+.float damagedbycontents;
+.float damagedbytriggers;
+
+float yoda;
+float damage_goodhits;
+float damage_gooddamage;
+
+.float pain_finished; // Added by Supajoe
+
+.float dmg_team;
+.float teamkill_complain;
+.float teamkill_soundtime;
+.entity teamkill_soundsource;
+.entity pusher;
+.bool istypefrag;
+.float taunt_soundtime;
+
+.float spawnshieldtime;
+
+.int totalfrags;
+
+.bool canteamdamage;
+
+.vector death_origin;
+
+.float damage_dealt, typehitsound, killsound;
+
+// used for custom deathtype
+string deathmessage;
+
+float IsFlying(entity a);
+
+void UpdateFrags(entity player, int f);
+
+// NOTE: f=0 means still count as a (positive) kill, but count no frags for it
+void W_SwitchWeapon_Force(Player this, Weapon w, .entity weaponentity);
+void GiveFrags (entity attacker, entity targ, float f, int deathtype, .entity weaponentity);
+
+string AppendItemcodes(string s, entity player);
+
+void LogDeath(string mode, int deathtype, entity killer, entity killed);
+
+void Obituary_SpecialDeath(
+ entity notif_target,
+ float murder,
+ int deathtype,
+ string s1, string s2, string s3,
+ float f1, float f2, float f3);
+
+float w_deathtype;
+float Obituary_WeaponDeath(
+ entity notif_target,
+ float murder,
+ int deathtype,
+ string s1, string s2, string s3,
+ float f1, float f2);
+
+void Obituary(entity attacker, entity inflictor, entity targ, int deathtype, .entity weaponentity);
+
+// Frozen status effect
+//const int FROZEN_NOT = 0;
+const int FROZEN_NORMAL = 1;
+const int FROZEN_TEMP_REVIVING = 2;
+const int FROZEN_TEMP_DYING = 3;
+
+.float revival_time; // time at which player was last revived
+.float revive_speed; // NOTE: multiplier (anything above 1 is instaheal)
+.float freeze_time;
+.entity iceblock;
+.entity frozen_by; // for ice fields
+
+void Ice_Think(entity this);
+
+void Freeze(entity targ, float revivespeed, int frozen_type, bool show_waypoint);
+
+void Unfreeze(entity targ, bool reset_health);
+
+// WEAPONTODO
+#define DMG_NOWEP (weaponentities[0])
+
+// NOTE: the .weaponentity parameter can be set to DMG_NOWEP if the attack wasn't caused by a weapon or player
+void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
+
+float RadiusDamage_running;
+float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype, .entity weaponentity, entity directhitentity);
+ // Returns total damage applies 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 damageforcescale;
+const float MIN_DAMAGEEXTRARADIUS = 2;
+const float MAX_DAMAGEEXTRARADIUS = 16;
+.float damageextraradius;
+
+// Calls .event_heal on the target so that they can handle healing themselves
+// a limit of RES_LIMIT_NONE should be handled by the entity as its max health (if applicable)
+bool Heal(entity targ, entity inflictor, float amount, float limit);
+
+.float fire_damagepersec;
+.float fire_endtime;
+.float fire_deathtype;
+.entity fire_owner;
+.float fire_hitsound;
+.entity fire_burner;
+
+void fireburner_think(entity this);
+
+float Fire_IsBurning(entity e);
+
+float Fire_AddDamage(entity e, entity o, float d, float t, float dt);
+
+void Fire_ApplyDamage(entity e);
+
+void Fire_ApplyEffect(entity e);
+
+IntrusiveList g_damagedbycontents;
+STATIC_INIT(g_damagedbycontents) { g_damagedbycontents = IL_NEW(); }
+++ /dev/null
-#pragma once
-
-#include <common/weapons/_all.qh>
-#include <common/stats.qh>
-
-#define INDEPENDENT_ATTACK_FINISHED 1
-
-// Globals
-
-float g_footsteps, g_grappling_hook;
-float g_warmup_allguns;
-float g_warmup_allow_timeout;
-float warmup_stage;
-float g_jetpack;
-
-bool sv_ready_restart;
-bool sv_ready_restart_after_countdown;
-bool sv_ready_restart_repeatable;
-
-float sv_clones;
-float sv_foginterval;
-
-float player_count;
-float currentbots;
-float bots_would_leave;
-
-void UpdateFrags(entity player, int f);
-.int totalfrags;
-
-// flag set on worldspawn so that the code knows if it is dedicated or not
-float server_is_dedicated;
-
-// Fields
-
-.void(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force) event_damage;
-
-.bool(entity targ, entity inflictor, float amount, float limit) event_heal;
-
-//.string wad;
-//.string map;
-
-//.float worldtype;
-// Needed for dynamic clientwalls
-.bool inactive; // Clientwall disappears when inactive
-.float alpha_max, alpha_min;
-.float fade_start, fade_end, fade_vertical_offset;
-.float default_solid; // Variable to store default .solid for clientwalls
-
-.float pain_finished; //Added by Supajoe
-.float pain_frame; //"
-.float crouch; // Crouching or not?
-
-.float superweapons_finished; // NOTE: this field is used only by map entities, it does not directly apply the superweapons stat
-const .float air_finished = _STAT(AIR_FINISHED);
-
-.float cnt; // used in too many places
-.float count;
-//.float cnt2;
-
-.int respawn_flags;
-.float respawn_time;
-.float respawn_time_max;
-.float death_time;
-.float fade_time;
-.float fade_rate;
-
-void player_setupanimsformodel(entity this);
-
-.string mdl;
-
-.string playermodel;
-.string playerskin;
-
-.float species;
-
-.float scheduledrespawntime;
-.float respawntime;
-.float respawntimejitter;
-.float respawntimestart;
-//.float chasecam;
-
-.float damageforcescale;
-const float MIN_DAMAGEEXTRARADIUS = 2;
-const float MAX_DAMAGEEXTRARADIUS = 16;
-.float damageextraradius;
-
-//.float gravity;
-
-.float dmg;
-
-// for railgun damage (hitting multiple enemies)
-.bool railgunhit;
-.float railgunhitsolidbackup;
-.vector railgunhitloc;
-
-.float dmgtime;
-
-.float killcount;
-.float damage_dealt, typehitsound, killsound;
-
-.float watersound_finished;
-.float iscreature;
-.float damagedbycontents;
-.float damagedbytriggers;
-.float teleportable;
-.vector oldvelocity;
-
-.float pauseregen_finished;
-.float pauserothealth_finished;
-.float pauserotarmor_finished;
-.float pauserotfuel_finished;
-// string overrides entity
-.string item_pickupsound;
-.entity item_pickupsound_ent;
-.entity item_model_ent;
-
-// WEAPONTODO
-.float autoswitch;
-bool client_hasweapon(entity this, Weapon wpn, .entity weaponentity, float andammo, bool complain);
-void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire);
-void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire);
-// VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies)
-.float weapon_nextthink;
-.void(Weapon thiswep, entity actor, .entity weaponentity, int fire) weapon_think;
-
-
-// there is 2 weapon tics that can run in one server frame
-const int W_TICSPERFRAME = 2;
-
-void weapon_defaultspawnfunc(entity this, Weapon e);
-
-float intermission_running;
-float intermission_exittime;
-float alreadychangedlevel;
-
-// footstep interval
-.float nextstep;
-
-float blockSpectators; //if set, new or existing spectators or observers will be removed unless they become a player within g_maxplayers_spectator_blocktime seconds
-.float spectatortime; //point in time since the client is spectating or observing
-void checkSpectatorBlock(entity this);
-
-.float winning;
-.float jointime; // time of connecting
-.float startplaytime; // time of switching from spectator to player
-.float alivetime; // time of being alive
-.float motd_actived_time; // used for both motd and campaign_message
-
-int nJoinAllowed(entity this, entity ignore);
-
-.float spawnshieldtime;
-.float item_spawnshieldtime;
-
-.entity flagcarried;
-
-.int playerid;
-.float noalign; // if set to 1, the item or spawnpoint won't be dropped to the floor
-
-.vector death_origin;
-
-float default_player_alpha;
-float default_weapon_alpha;
-
-.float cvar_cl_handicap;
-.int cvar_cl_gunalign;
-.float cvar_cl_clippedspectating;
-.float cvar_cl_autoscreenshot;
-.float cvar_cl_jetpack_jump;
-.float cvar_cl_movement_track_canjump;
-.float cvar_cl_newusekeysupported;
-.float cvar_cl_cts_noautoswitch;
-.bool cvar_cl_weapon_switch_reload;
-.bool cvar_cl_weapon_switch_fallback_to_impulse;
-
-.string cvar_g_xonoticversion;
-.string cvar_cl_weaponpriority;
-.string cvar_cl_weaponpriorities[10];
-.float cvar_cl_noantilag;
-
-.string weaponorder_byimpulse;
-
-.float cvar_cl_allow_uid2name;
-.float cvar_cl_allow_uidtracking;
-.bool cvar_cl_allow_uidranking;
-.string stored_netname;
-
-string gamemode_name;
-
-string W_Apply_Weaponreplace(string in);
-
-void FixIntermissionClient(entity e);
-void FixClientCvars(entity e);
-
-.float respawn_countdown; // next number to count
-
-float bot_waypoints_for_items;
-
-.float attack_finished_for[REGISTRY_MAX(Weapons) * MAX_WEAPONSLOTS];
-.float attack_finished_single[MAX_WEAPONSLOTS];
-#if INDEPENDENT_ATTACK_FINISHED
-#define ATTACK_FINISHED_FOR(ent, w, slot) ((ent).(attack_finished_for[((w) - WEP_FIRST) * MAX_WEAPONSLOTS + (slot)]))
-#else
-#define ATTACK_FINISHED_FOR(ent, w, slot) ((ent).attack_finished_single[slot])
-#endif
-#define ATTACK_FINISHED(ent, w) ATTACK_FINISHED_FOR(ent, ent.(w).m_weapon.m_id, weaponslot(w))
-
-// speedrun: when 1, player auto teleports back when capture timeout happens
-.float speedrunning;
-
-// database
-float ServerProgsDB;
-float TemporaryDB;
-
-.int team_saved;
-
-bool some_spawn_has_been_used;
-int have_team_spawns; // 0 = no team spawns requested, -1 = team spawns requested but none found, 1 = team spawns requested and found
-int have_team_spawns_forteams; // if Xth bit is 1 then team X has spawns else it has no spawns; team 0 is the "no-team"
-
-.bool canteamdamage;
-
-void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
-
-// WEAPONTODO
-#define DMG_NOWEP (weaponentities[0])
-
-float sv_maxidle;
-float sv_maxidle_spectatorsareidle;
-int sv_maxidle_slots;
-bool sv_maxidle_slots_countbots;
-
-float tracebox_hits_trigger_hurt(vector start, vector mi, vector ma, vector end);
-
-float next_pingtime;
-
-// autotaunt system
-.float cvar_cl_autotaunt;
-.float cvar_cl_voice_directional;
-.float cvar_cl_voice_directional_taunt_attenuation;
-
-int autocvar__independent_players;
-bool independent_players;
-#define INDEPENDENT_PLAYERS (autocvar__independent_players ? (autocvar__independent_players > 0) : independent_players)
-#define IS_INDEPENDENT_PLAYER(e) ((e).solid == SOLID_TRIGGER)
-#define MAKE_INDEPENDENT_PLAYER(e) (((e).solid = SOLID_TRIGGER), ((e).frags = FRAGS_PLAYER_OUT_OF_GAME))
-
-string clientstuff;
-.float phase;
-.int pressedkeys;
-
-.string fog;
-
-string cvar_changes;
-string cvar_purechanges;
-float cvar_purechanges_count;
-
-//float game_starttime; //point in time when the countdown to game start is over
-//float round_starttime; //point in time when the countdown to round start is over
-
-void W_Porto_Remove (entity p);
-
-.int projectiledeathtype;
-
-.string message2;
-
-// reset to 0 on weapon switch
-// may be useful to all weapons
-.float bulletcounter;
-
-// Nexball
-float g_nexball_meter_period;
-
-.void(entity this) reset; // if set, an entity is reset using this
-.void(entity this) reset2; // if set, an entity is reset using this (after calling ALL the reset functions for other entities)
-
-void ClientData_Touch(entity e);
-
-//vector debug_shotorg; // if non-zero, overrides the shot origin of all weapons
-
-.bool wasplayer;
-
-float servertime, serverprevtime, serverframetime;
-
-.float ammo_fuel;
-
-//flood fields
-.float nickspamtime; // time of last nick change
-.float nickspamcount;
-.float floodcontrol_chat;
-.float floodcontrol_chatteam;
-.float floodcontrol_chattell;
-.float floodcontrol_voice;
-.float floodcontrol_voiceteam;
-
-string matchid;
-
-bool radar_showennemies;
-
-.float weapon_load[REGISTRY_MAX(Weapons)];
-.int ammo_none; // used by the reloading system, must always be 0
-.int clip_load;
-.int old_clip_load;
-.int clip_size;
-
-.int minelayer_mines;
-.float vortex_charge;
-.float vortex_charge_rottime;
-.float vortex_chargepool_ammo;
-.float oknex_charge;
-.float oknex_charge_rottime;
-.float oknex_chargepool_ammo;
-.int hagar_load;
-
-.int grab; // 0 = can't grab, 1 = owner can grab, 2 = owner and team mates can grab, 3 = anyone can grab
-
-#define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_CORPSE; (e).dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE
-// when doing this, hagar can go through clones
-// #define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_BBOX
-
-.int spectatee_status;
-.bool zoomstate;
-.int restriction;
-
-.entity clientdata;
-.entity personal;
-
-string deathmessage;
-
-.bool just_joined;
-
-.float cvar_cl_weaponimpulsemode;
-.int selectweapon; // last selected weapon of the player
-
-.float ballistics_density;
-
-//const int FROZEN_NOT = 0;
-const int FROZEN_NORMAL = 1;
-const int FROZEN_TEMP_REVIVING = 2;
-const int FROZEN_TEMP_DYING = 3;
-
-const int ACTIVE_NOT = 0;
-const int ACTIVE_ACTIVE = 1;
-const int ACTIVE_IDLE = 2;
-const int ACTIVE_BUSY = 2;
-const int ACTIVE_TOGGLE = 3;
-.int active;
-.void (entity this, int act_state) setactive;
-.entity realowner;
-
-//float serverflags;
-
-.bool player_blocked;
-
-.float revival_time; // time at which player was last revived
-.float revive_speed; // NOTE: multiplier (anything above 1 is instaheal)
-.float freeze_time;
-.entity iceblock;
-.entity frozen_by; // for ice fields
-
-.float misc_bulletcounter; // replaces uzi & hlac bullet counter.
-
-void PlayerUseKey(entity this);
-
-USING(spawn_evalfunc_t, vector(entity this, entity player, entity spot, vector current));
-.spawn_evalfunc_t spawn_evalfunc;
-
-string modname;
-
-.int missile_flags;
-const int MIF_SPLASH = BIT(1);
-const int MIF_ARC = BIT(2);
-const int MIF_PROXY = BIT(3);
-const int MIF_GUIDED_MANUAL = BIT(4);
-const int MIF_GUIDED_HEAT = BIT(5);
-const int MIF_GUIDED_LASER = BIT(6);
-const int MIF_GUIDED_AI = BIT(7);
-const int MIF_GUIDED_TAG = BIT(7);
-const int MIF_GUIDED_ALL = MIF_GUIDED_MANUAL | MIF_GUIDED_HEAT | MIF_GUIDED_LASER | MIF_GUIDED_AI | MIF_GUIDED_TAG;
-const int MIF_GUIDED_TRACKING = MIF_GUIDED_HEAT | MIF_GUIDED_LASER | MIF_GUIDED_AI | MIF_GUIDED_TAG;
-const int MIF_GUIDED_CONFUSABLE = MIF_GUIDED_HEAT | MIF_GUIDED_AI;
-
-#define MISSILE_IS_CONFUSABLE(m) ((m.missile_flags & MIF_GUIDED_CONFUSABLE) ? true : false)
-#define MISSILE_IS_GUIDED(m) ((m.missile_flags & MIF_GUIDED_ALL) ? true : false)
-#define MISSILE_IS_TRACKING(m) ((m.missile_flags & MIF_GUIDED_TRACKING) ? true : false)
-
-////
-
-.string cvar_cl_physics;
-
-.void(entity this, entity player) init_for_player;
-
-.WepSet dual_weapons;
-
-IntrusiveList g_monsters;
-IntrusiveList g_waypoints;
-IntrusiveList g_vehicles;
-IntrusiveList g_turrets;
-IntrusiveList g_mines;
-IntrusiveList g_projectiles;
-IntrusiveList g_items;
-IntrusiveList g_initforplayer;
-IntrusiveList g_clones;
-IntrusiveList g_spawnpoints;
-IntrusiveList g_bot_targets;
-IntrusiveList g_bot_dodge;
-IntrusiveList g_damagedbycontents;
-IntrusiveList g_railgunhit;
-IntrusiveList g_ladders;
-IntrusiveList g_locations;
-IntrusiveList g_saved_team;
-IntrusiveList g_monster_targets;
-IntrusiveList g_pathlib_nodes;
-IntrusiveList g_moveables;
-STATIC_INIT(defs)
-{
- g_monsters = IL_NEW();
- g_waypoints = IL_NEW();
- g_vehicles = IL_NEW();
- g_turrets = IL_NEW();
- g_mines = IL_NEW();
- g_projectiles = IL_NEW();
- g_items = IL_NEW();
- g_initforplayer = IL_NEW();
- g_clones = IL_NEW();
- g_spawnpoints = IL_NEW();
- g_bot_targets = IL_NEW();
- g_bot_dodge = IL_NEW();
- g_damagedbycontents = IL_NEW();
- g_railgunhit = IL_NEW();
- g_ladders = IL_NEW();
- g_locations = IL_NEW();
- g_saved_team = IL_NEW();
- g_monster_targets = IL_NEW();
- g_pathlib_nodes = IL_NEW();
- g_moveables = IL_NEW();
-}
+++ /dev/null
-#include "g_damage.qh"
-
-#include <common/effects/all.qh>
-#include "bot/api.qh"
-#include "g_hook.qh"
-#include <server/gamelog.qh>
-#include <server/mutators/_mod.qh>
-#include "teamplay.qh"
-#include "scores.qh"
-#include "spawnpoints.qh"
-#include "../common/state.qh"
-#include "../common/physics/player.qh"
-#include "../common/t_items.qh"
-#include "resources.qh"
-#include "../common/vehicles/all.qh"
-#include "../common/items/_mod.qh"
-#include "../common/mutators/mutator/waypoints/waypointsprites.qh"
-#include "../common/mutators/mutator/instagib/sv_instagib.qh"
-#include "../common/mutators/mutator/buffs/buffs.qh"
-#include "weapons/accuracy.qh"
-#include "weapons/csqcprojectile.qh"
-#include "weapons/selection.qh"
-#include "../common/constants.qh"
-#include "../common/deathtypes/all.qh"
-#include "../common/notifications/all.qh"
-#include "../common/physics/movetypes/movetypes.qh"
-#include "../common/playerstats.qh"
-#include "../common/teams.qh"
-#include "../common/util.qh"
-#include <common/gamemodes/_mod.qh>
-#include <common/gamemodes/rules.qh>
-#include <common/weapons/_all.qh>
-#include "../lib/csqcmodel/sv_model.qh"
-#include "../lib/warpzone/common.qh"
-
-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)
-{
- // TODO route through PlayerScores instead
- if(game_stopped) return;
-
- if(f < 0)
- {
- if(targ == attacker)
- {
- // suicide
- GameRules_scoring_add(attacker, SUICIDES, 1);
- }
- else
- {
- // teamkill
- GameRules_scoring_add(attacker, TEAMKILLS, 1);
- }
- }
- else
- {
- // regular frag
- GameRules_scoring_add(attacker, KILLS, 1);
- if(!warmup_stage && targ.playerid)
- PlayerStats_GameReport_Event_Player(attacker, sprintf("kills-%d", targ.playerid), 1);
- }
-
- GameRules_scoring_add(targ, DEATHS, 1);
-
- // FIXME fix the mess this is (we have REAL points now!)
- if(MUTATOR_CALLHOOK(GiveFragsForKill, attacker, targ, f, deathtype, attacker.(weaponentity)))
- f = M_ARGV(2, float);
-
- attacker.totalfrags += f;
-
- if(f)
- UpdateFrags(attacker, f);
-}
-
-string AppendItemcodes(string s, entity player)
-{
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- int w = player.(weaponentity).m_weapon.m_id;
- if(w == 0)
- w = player.(weaponentity).cnt; // previous weapon
- if(w != 0 || slot == 0)
- s = strcat(s, ftos(w));
- }
- if(time < STAT(STRENGTH_FINISHED, player))
- s = strcat(s, "S");
- if(time < STAT(INVINCIBLE_FINISHED, player))
- s = strcat(s, "I");
- if(PHYS_INPUT_BUTTON_CHAT(player))
- s = strcat(s, "T");
- // TODO: include these codes as a flag on the item itself
- MUTATOR_CALLHOOK(LogDeath_AppendItemCodes, player, s);
- s = M_ARGV(1, string);
- return s;
-}
-
-void LogDeath(string mode, int deathtype, entity killer, entity killed)
-{
- string s;
- if(!autocvar_sv_eventlog)
- return;
- s = strcat(":kill:", mode);
- s = strcat(s, ":", ftos(killer.playerid));
- s = strcat(s, ":", ftos(killed.playerid));
- s = strcat(s, ":type=", Deathtype_Name(deathtype));
- s = strcat(s, ":items=");
- s = AppendItemcodes(s, killer);
- if(killed != killer)
- {
- s = strcat(s, ":victimitems=");
- s = AppendItemcodes(s, killed);
- }
- GameLogEcho(s);
-}
-
-void Obituary_SpecialDeath(
- entity notif_target,
- float murder,
- int deathtype,
- string s1, string s2, string s3,
- float f1, float f2, float f3)
-{
- if(!DEATH_ISSPECIAL(deathtype))
- {
- backtrace("Obituary_SpecialDeath called without a special deathtype?\n");
- return;
- }
-
- entity deathent = REGISTRY_GET(Deathtypes, deathtype - DT_FIRST);
- if (!deathent)
- {
- backtrace("Obituary_SpecialDeath: Could not find deathtype entity!\n");
- return;
- }
-
- if(g_cts && deathtype == DEATH_KILL.m_id)
- return; // TODO: somehow put this in CTS gamemode file!
-
- Notification death_message = (murder) ? deathent.death_msgmurder : deathent.death_msgself;
- if(death_message)
- {
- Send_Notification_WOCOVA(
- NOTIF_ONE,
- notif_target,
- MSG_MULTI,
- death_message,
- s1, s2, s3, "",
- f1, f2, f3, 0
- );
- Send_Notification_WOCOVA(
- NOTIF_ALL_EXCEPT,
- notif_target,
- MSG_INFO,
- death_message.nent_msginfo,
- s1, s2, s3, "",
- f1, f2, f3, 0
- );
- }
-}
-
-float Obituary_WeaponDeath(
- entity notif_target,
- float murder,
- int deathtype,
- string s1, string s2, string s3,
- float f1, float f2)
-{
- Weapon death_weapon = DEATH_WEAPONOF(deathtype);
- if (death_weapon == WEP_Null)
- return false;
-
- w_deathtype = deathtype;
- Notification death_message = ((murder) ? death_weapon.wr_killmessage(death_weapon) : death_weapon.wr_suicidemessage(death_weapon));
- w_deathtype = false;
-
- if (death_message)
- {
- Send_Notification_WOCOVA(
- NOTIF_ONE,
- notif_target,
- MSG_MULTI,
- death_message,
- s1, s2, s3, "",
- f1, f2, 0, 0
- );
- // send the info part to everyone
- Send_Notification_WOCOVA(
- NOTIF_ALL_EXCEPT,
- notif_target,
- MSG_INFO,
- death_message.nent_msginfo,
- s1, s2, s3, "",
- f1, f2, 0, 0
- );
- }
- else
- {
- LOG_TRACEF(
- "Obituary_WeaponDeath(): ^1Deathtype ^7(%d)^1 has no notification for weapon %s!\n",
- deathtype,
- death_weapon.netname
- );
- }
-
- return true;
-}
-
-bool frag_centermessage_override(entity attacker, entity targ, int deathtype, int kill_count_to_attacker, int kill_count_to_target, string attacker_name)
-{
- if(deathtype == DEATH_FIRE.m_id)
- {
- Send_Notification(NOTIF_ONE, attacker, MSG_CHOICE, CHOICE_FRAG_FIRE, targ.netname, kill_count_to_attacker, (IS_BOT_CLIENT(targ) ? -1 : CS(targ).ping));
- Send_Notification(NOTIF_ONE, targ, MSG_CHOICE, CHOICE_FRAGGED_FIRE, attacker_name, kill_count_to_target, GetResource(attacker, RES_HEALTH), GetResource(attacker, RES_ARMOR), (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping));
- return true;
- }
-
- return MUTATOR_CALLHOOK(FragCenterMessage, attacker, targ, deathtype, kill_count_to_attacker, kill_count_to_target);
-}
-
-void Obituary(entity attacker, entity inflictor, entity targ, int deathtype, .entity weaponentity)
-{
- // Sanity check
- if (!IS_PLAYER(targ)) { backtrace("Obituary called on non-player?!\n"); return; }
-
- // Declarations
- float notif_firstblood = false;
- float kill_count_to_attacker, kill_count_to_target;
- bool notif_anonymous = false;
- string attacker_name = attacker.netname;
-
- // Set final information for the death
- targ.death_origin = targ.origin;
- string deathlocation = (autocvar_notification_server_allows_location ? NearestLocation(targ.death_origin) : "");
-
- // Abort now if a mutator requests it
- if (MUTATOR_CALLHOOK(ClientObituary, inflictor, attacker, targ, deathtype, attacker.(weaponentity))) { CS(targ).killcount = 0; return; }
- notif_anonymous = M_ARGV(5, bool);
-
- if(notif_anonymous)
- attacker_name = "Anonymous player";
-
- #ifdef NOTIFICATIONS_DEBUG
- Debug_Notification(
- sprintf(
- "Obituary(%s, %s, %s, %s = %d);\n",
- attacker_name,
- inflictor.netname,
- targ.netname,
- Deathtype_Name(deathtype),
- deathtype
- )
- );
- #endif
-
- // =======
- // SUICIDE
- // =======
- if(targ == attacker)
- {
- if(DEATH_ISSPECIAL(deathtype))
- {
- if(deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
- {
- Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", targ.team, 0, 0);
- }
- else
- {
- switch(DEATH_ENT(deathtype))
- {
- case DEATH_MIRRORDAMAGE:
- {
- Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
- break;
- }
-
- default:
- {
- Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
- break;
- }
- }
- }
- }
- else if (!Obituary_WeaponDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0))
- {
- backtrace("SUICIDE: what the hell happened here?\n");
- return;
- }
- LogDeath("suicide", deathtype, targ, targ);
- if(deathtype != DEATH_AUTOTEAMCHANGE.m_id) // special case: don't negate frags if auto switched
- GiveFrags(attacker, targ, -1, deathtype, weaponentity);
- }
-
- // ======
- // MURDER
- // ======
- else if(IS_PLAYER(attacker))
- {
- if(SAME_TEAM(attacker, targ))
- {
- LogDeath("tk", deathtype, attacker, targ);
- GiveFrags(attacker, targ, -1, deathtype, weaponentity);
-
- CS(attacker).killcount = 0;
-
- Send_Notification(NOTIF_ONE, attacker, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAG, targ.netname);
- Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_DEATH_TEAMKILL_FRAGGED, attacker_name);
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, APP_TEAM_NUM(targ.team, INFO_DEATH_TEAMKILL), targ.netname, attacker_name, deathlocation, CS(targ).killcount);
-
- // In this case, the death message will ALWAYS be "foo was betrayed by bar"
- // No need for specific death/weapon messages...
- }
- else
- {
- LogDeath("frag", deathtype, attacker, targ);
- GiveFrags(attacker, targ, 1, deathtype, weaponentity);
-
- CS(attacker).taunt_soundtime = time + 1;
- CS(attacker).killcount = CS(attacker).killcount + 1;
-
- attacker.killsound += 1;
-
- // TODO: improve SPREE_ITEM and KILL_SPREE_LIST
- // these 2 macros are spread over multiple files
- #define SPREE_ITEM(counta,countb,center,normal,gentle) \
- case counta: \
- Send_Notification(NOTIF_ONE, attacker, MSG_ANNCE, ANNCE_KILLSTREAK_##countb); \
- if (!warmup_stage) \
- PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_KILL_SPREE_##counta, 1); \
- break;
-
- switch(CS(attacker).killcount)
- {
- KILL_SPREE_LIST
- default: break;
- }
- #undef SPREE_ITEM
-
- if(!warmup_stage && !checkrules_firstblood)
- {
- checkrules_firstblood = true;
- notif_firstblood = true; // modify the current messages so that they too show firstblood information
- PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_FIRSTBLOOD, 1);
- PlayerStats_GameReport_Event_Player(targ, PLAYERSTATS_ACHIEVEMENT_FIRSTVICTIM, 1);
-
- // tell spree_inf and spree_cen that this is a first-blood and first-victim event
- kill_count_to_attacker = -1;
- kill_count_to_target = -2;
- }
- else
- {
- kill_count_to_attacker = CS(attacker).killcount;
- kill_count_to_target = 0;
- }
-
- if(targ.istypefrag)
- {
- Send_Notification(
- NOTIF_ONE,
- attacker,
- MSG_CHOICE,
- CHOICE_TYPEFRAG,
- targ.netname,
- kill_count_to_attacker,
- (IS_BOT_CLIENT(targ) ? -1 : CS(targ).ping)
- );
- Send_Notification(
- NOTIF_ONE,
- targ,
- MSG_CHOICE,
- CHOICE_TYPEFRAGGED,
- attacker_name,
- kill_count_to_target,
- GetResource(attacker, RES_HEALTH),
- GetResource(attacker, RES_ARMOR),
- (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping)
- );
- }
- else if(!frag_centermessage_override(attacker, targ, deathtype, kill_count_to_attacker, kill_count_to_target, attacker_name))
- {
- Send_Notification(
- NOTIF_ONE,
- attacker,
- MSG_CHOICE,
- CHOICE_FRAG,
- targ.netname,
- kill_count_to_attacker,
- (IS_BOT_CLIENT(targ) ? -1 : CS(targ).ping)
- );
- Send_Notification(
- NOTIF_ONE,
- targ,
- MSG_CHOICE,
- CHOICE_FRAGGED,
- attacker_name,
- kill_count_to_target,
- GetResource(attacker, RES_HEALTH),
- GetResource(attacker, RES_ARMOR),
- (IS_BOT_CLIENT(attacker) ? -1 : CS(attacker).ping)
- );
- }
-
- int f3 = 0;
- if(deathtype == DEATH_BUFF.m_id)
- f3 = buff_FirstFromFlags(STAT(BUFFS, attacker)).m_id;
-
- if (!Obituary_WeaponDeath(targ, true, deathtype, targ.netname, attacker_name, deathlocation, CS(targ).killcount, kill_count_to_attacker))
- Obituary_SpecialDeath(targ, true, deathtype, targ.netname, attacker_name, deathlocation, CS(targ).killcount, kill_count_to_attacker, f3);
- }
- }
-
- // =============
- // ACCIDENT/TRAP
- // =============
- else
- {
- switch(DEATH_ENT(deathtype))
- {
- // For now, we're just forcing HURTTRIGGER to behave as "DEATH_VOID" and giving it no special options...
- // Later on you will only be able to make custom messages using DEATH_CUSTOM,
- // and there will be a REAL DEATH_VOID implementation which mappers will use.
- case DEATH_HURTTRIGGER:
- {
- Obituary_SpecialDeath(targ, false, deathtype,
- targ.netname,
- inflictor.message,
- deathlocation,
- CS(targ).killcount,
- 0,
- 0);
- break;
- }
-
- case DEATH_CUSTOM:
- {
- Obituary_SpecialDeath(targ, false, deathtype,
- targ.netname,
- ((strstrofs(deathmessage, "%", 0) < 0) ? strcat("%s ", deathmessage) : deathmessage),
- deathlocation,
- CS(targ).killcount,
- 0,
- 0);
- break;
- }
-
- default:
- {
- Obituary_SpecialDeath(targ, false, deathtype, targ.netname, deathlocation, "", CS(targ).killcount, 0, 0);
- break;
- }
- }
-
- LogDeath("accident", deathtype, targ, targ);
- GiveFrags(targ, targ, -1, deathtype, weaponentity);
-
- if(GameRules_scoring_add(targ, SCORE, 0) == -5)
- {
- Send_Notification(NOTIF_ONE, targ, MSG_ANNCE, ANNCE_ACHIEVEMENT_BOTLIKE);
- if (!warmup_stage)
- {
- PlayerStats_GameReport_Event_Player(attacker, PLAYERSTATS_ACHIEVEMENT_BOTLIKE, 1);
- }
- }
- }
-
- // reset target kill count
- CS(targ).killcount = 0;
-}
-
-void Ice_Think(entity this)
-{
- if(!STAT(FROZEN, this.owner) || this.owner.iceblock != this)
- {
- delete(this);
- return;
- }
- vector ice_org = this.owner.origin - '0 0 16';
- if (this.origin != ice_org)
- setorigin(this, ice_org);
- this.nextthink = time;
-}
-
-void Freeze(entity targ, float revivespeed, int frozen_type, bool show_waypoint)
-{
- if(!IS_PLAYER(targ) && !IS_MONSTER(targ)) // TODO: only specified entities can be freezed
- return;
-
- if(STAT(FROZEN, targ))
- return;
-
- float targ_maxhealth = ((IS_MONSTER(targ)) ? targ.max_health : start_health);
-
- STAT(FROZEN, targ) = frozen_type;
- STAT(REVIVE_PROGRESS, targ) = ((frozen_type == FROZEN_TEMP_DYING) ? 1 : 0);
- SetResource(targ, RES_HEALTH, ((frozen_type == FROZEN_TEMP_DYING) ? targ_maxhealth : 1));
- targ.revive_speed = revivespeed;
- if(targ.bot_attack)
- IL_REMOVE(g_bot_targets, targ);
- targ.bot_attack = false;
- targ.freeze_time = time;
-
- entity ice = new(ice);
- ice.owner = targ;
- ice.scale = targ.scale;
- // set_movetype(ice, MOVETYPE_FOLLOW) would rotate the ice model with the player
- setthink(ice, Ice_Think);
- ice.nextthink = time;
- ice.frame = floor(random() * 21); // ice model has 20 different looking frames
- setmodel(ice, MDL_ICE);
- ice.alpha = 1;
- ice.colormod = Team_ColorRGB(targ.team);
- ice.glowmod = ice.colormod;
- targ.iceblock = ice;
- targ.revival_time = 0;
-
- Ice_Think(ice);
-
- RemoveGrapplingHooks(targ);
-
- FOREACH_CLIENT(IS_PLAYER(it),
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(it.(weaponentity).hook.aiment == targ)
- RemoveHook(it.(weaponentity).hook);
- }
- });
-
- // add waypoint
- if(MUTATOR_CALLHOOK(Freeze, targ, revivespeed, frozen_type) || show_waypoint)
- WaypointSprite_Spawn(WP_Frozen, 0, 0, targ, '0 0 64', NULL, targ.team, targ, waypointsprite_attached, true, RADARICON_WAYPOINT);
-}
-
-void Unfreeze(entity targ, bool reset_health)
-{
- if(!STAT(FROZEN, targ))
- return;
-
- if (reset_health && STAT(FROZEN, targ) != FROZEN_TEMP_DYING)
- SetResource(targ, RES_HEALTH, ((IS_PLAYER(targ)) ? start_health : targ.max_health));
-
- targ.pauseregen_finished = time + autocvar_g_balance_pause_health_regen;
-
- STAT(FROZEN, targ) = 0;
- STAT(REVIVE_PROGRESS, targ) = 0;
- targ.revival_time = time;
- if(!targ.bot_attack)
- IL_PUSH(g_bot_targets, targ);
- targ.bot_attack = true;
-
- WaypointSprite_Kill(targ.waypointsprite_attached);
-
- FOREACH_CLIENT(IS_PLAYER(it),
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(it.(weaponentity).hook.aiment == targ)
- RemoveHook(it.(weaponentity).hook);
- }
- });
-
- // remove the ice block
- if(targ.iceblock)
- delete(targ.iceblock);
- targ.iceblock = NULL;
-
- MUTATOR_CALLHOOK(Unfreeze, targ);
-}
-
-void Damage(entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
-{
- float complainteamdamage = 0;
- float mirrordamage = 0;
- float mirrorforce = 0;
-
- if (game_stopped || (IS_CLIENT(targ) && CS(targ).killcount == FRAGS_SPECTATOR))
- return;
-
- entity attacker_save = attacker;
-
- // special rule: gravity bombs and sound-based attacks do not affect team mates (other than for disconnecting the hook)
- if(DEATH_ISWEAPON(deathtype, WEP_HOOK) || (deathtype & HITTYPE_SOUND))
- {
- if(IS_PLAYER(targ) && SAME_TEAM(targ, attacker))
- {
- return;
- }
- }
-
- if(deathtype == DEATH_KILL.m_id || deathtype == DEATH_TEAMCHANGE.m_id || deathtype == DEATH_AUTOTEAMCHANGE.m_id)
- {
- // exit the vehicle before killing (fixes a crash)
- if(IS_PLAYER(targ) && targ.vehicle)
- vehicles_exit(targ.vehicle, VHEF_RELEASE);
-
- // These are ALWAYS lethal
- // No damage modification here
- // Instead, prepare the victim for his death...
- SetResourceExplicit(targ, RES_ARMOR, 0);
- targ.spawnshieldtime = 0;
- SetResourceExplicit(targ, RES_HEALTH, 0.9); // this is < 1
- targ.flags -= targ.flags & FL_GODMODE;
- damage = 100000;
- }
- else if(deathtype == DEATH_MIRRORDAMAGE.m_id || deathtype == DEATH_NOAMMO.m_id)
- {
- // no processing
- }
- else
- {
- // nullify damage if teamplay is on
- if(deathtype != DEATH_TELEFRAG.m_id)
- if(IS_PLAYER(attacker))
- {
- if(IS_PLAYER(targ) && targ != attacker && (IS_INDEPENDENT_PLAYER(attacker) || IS_INDEPENDENT_PLAYER(targ)))
- {
- damage = 0;
- force = '0 0 0';
- }
- else if(SAME_TEAM(attacker, targ))
- {
- if(autocvar_teamplay_mode == 1)
- damage = 0;
- else if(attacker != targ)
- {
- if(autocvar_teamplay_mode == 2)
- {
- if(IS_PLAYER(targ) && !IS_DEAD(targ))
- {
- attacker.dmg_team = attacker.dmg_team + damage;
- complainteamdamage = attacker.dmg_team - autocvar_g_teamdamage_threshold;
- }
- }
- else if(autocvar_teamplay_mode == 3)
- damage = 0;
- else if(autocvar_teamplay_mode == 4)
- {
- if(IS_PLAYER(targ) && !IS_DEAD(targ))
- {
- attacker.dmg_team = attacker.dmg_team + damage;
- complainteamdamage = attacker.dmg_team - autocvar_g_teamdamage_threshold;
- if(complainteamdamage > 0)
- mirrordamage = autocvar_g_mirrordamage * complainteamdamage;
- mirrorforce = autocvar_g_mirrordamage * vlen(force);
- damage = autocvar_g_friendlyfire * damage;
- // mirrordamage will be used LATER
-
- if(autocvar_g_mirrordamage_virtual)
- {
- vector v = healtharmor_applydamage(GetResource(attacker, RES_ARMOR), autocvar_g_balance_armor_blockpercent, deathtype, mirrordamage);
- attacker.dmg_take += v.x;
- attacker.dmg_save += v.y;
- attacker.dmg_inflictor = inflictor;
- mirrordamage = v.z;
- mirrorforce = 0;
- }
-
- if(autocvar_g_friendlyfire_virtual)
- {
- vector v = healtharmor_applydamage(GetResource(targ, RES_ARMOR), autocvar_g_balance_armor_blockpercent, deathtype, damage);
- targ.dmg_take += v.x;
- targ.dmg_save += v.y;
- targ.dmg_inflictor = inflictor;
- damage = 0;
- if(!autocvar_g_friendlyfire_virtual_force)
- force = '0 0 0';
- }
- }
- else if(!targ.canteamdamage)
- damage = 0;
- }
- }
- }
- }
-
- if (!DEATH_ISSPECIAL(deathtype))
- {
- damage *= g_weapondamagefactor;
- mirrordamage *= g_weapondamagefactor;
- complainteamdamage *= g_weapondamagefactor;
- force = force * g_weaponforcefactor;
- mirrorforce *= g_weaponforcefactor;
- }
-
- // should this be changed at all? If so, in what way?
- MUTATOR_CALLHOOK(Damage_Calculate, inflictor, attacker, targ, deathtype, damage, mirrordamage, force, attacker.(weaponentity));
- damage = M_ARGV(4, float);
- mirrordamage = M_ARGV(5, float);
- force = M_ARGV(6, vector);
-
- if(IS_PLAYER(targ) && damage > 0 && attacker)
- {
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity went = weaponentities[slot];
- if(targ.(went).hook && targ.(went).hook.aiment == attacker)
- RemoveHook(targ.(went).hook);
- }
- }
-
- if(STAT(FROZEN, targ) && !ITEM_DAMAGE_NEEDKILL(deathtype)
- && deathtype != DEATH_TEAMCHANGE.m_id && deathtype != DEATH_AUTOTEAMCHANGE.m_id)
- {
- if(autocvar_g_frozen_revive_falldamage > 0 && deathtype == DEATH_FALL.m_id && damage >= autocvar_g_frozen_revive_falldamage)
- {
- Unfreeze(targ, false);
- SetResource(targ, RES_HEALTH, autocvar_g_frozen_revive_falldamage_health);
- Send_Effect(EFFECT_ICEORGLASS, targ.origin, '0 0 0', 3);
- Send_Notification(NOTIF_ALL, NULL, MSG_INFO, INFO_FREEZETAG_REVIVED_FALL, targ.netname);
- Send_Notification(NOTIF_ONE, targ, MSG_CENTER, CENTER_FREEZETAG_REVIVE_SELF);
- }
-
- damage = 0;
- force *= autocvar_g_frozen_force;
- }
-
- if(IS_PLAYER(targ) && STAT(FROZEN, targ)
- && ITEM_DAMAGE_NEEDKILL(deathtype) && !autocvar_g_frozen_damage_trigger)
- {
- Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
-
- entity spot = SelectSpawnPoint(targ, false);
- if(spot)
- {
- damage = 0;
- targ.deadflag = DEAD_NO;
-
- targ.angles = spot.angles;
-
- targ.effects = 0;
- targ.effects |= EF_TELEPORT_BIT;
-
- targ.angles_z = 0; // never spawn tilted even if the spot says to
- targ.fixangle = true; // turn this way immediately
- targ.velocity = '0 0 0';
- targ.avelocity = '0 0 0';
- targ.punchangle = '0 0 0';
- targ.punchvector = '0 0 0';
- targ.oldvelocity = targ.velocity;
-
- targ.spawnorigin = spot.origin;
- setorigin(targ, spot.origin + '0 0 1' * (1 - targ.mins.z - 24));
- // don't reset back to last position, even if new position is stuck in solid
- targ.oldorigin = targ.origin;
-
- Send_Effect(EFFECT_TELEPORT, targ.origin, '0 0 0', 1);
- }
- }
-
- if(!MUTATOR_IS_ENABLED(mutator_instagib))
- {
- // apply strength multiplier
- if (attacker.items & ITEM_Strength.m_itemid)
- {
- if(targ == attacker)
- {
- damage = damage * autocvar_g_balance_powerup_strength_selfdamage;
- force = force * autocvar_g_balance_powerup_strength_selfforce;
- }
- else
- {
- damage = damage * autocvar_g_balance_powerup_strength_damage;
- force = force * autocvar_g_balance_powerup_strength_force;
- }
- }
-
- // apply invincibility multiplier
- if (targ.items & ITEM_Shield.m_itemid)
- {
- damage = damage * autocvar_g_balance_powerup_invincible_takedamage;
- if (targ != attacker)
- {
- force = force * autocvar_g_balance_powerup_invincible_takeforce;
- }
- }
- }
-
- if (targ == attacker)
- damage = damage * autocvar_g_balance_selfdamagepercent; // Partial damage if the attacker hits himself
-
- // count the damage
- if(attacker)
- if(!IS_DEAD(targ))
- if(deathtype != DEATH_BUFF.m_id)
- if(targ.takedamage == DAMAGE_AIM)
- if(targ != attacker)
- {
- entity victim;
- if(IS_VEHICLE(targ) && targ.owner)
- victim = targ.owner;
- else
- victim = targ;
-
- if(IS_PLAYER(victim) || (IS_TURRET(victim) && victim.active == ACTIVE_ACTIVE) || IS_MONSTER(victim) || MUTATOR_CALLHOOK(PlayHitsound, victim, attacker))
- {
- if(DIFF_TEAM(victim, attacker) && !STAT(FROZEN, victim))
- {
- if(damage > 0)
- {
- if(deathtype != DEATH_FIRE.m_id)
- {
- if(PHYS_INPUT_BUTTON_CHAT(victim))
- attacker.typehitsound += 1;
- else
- attacker.damage_dealt += damage;
- }
-
- damage_goodhits += 1;
- damage_gooddamage += damage;
-
- if (!DEATH_ISSPECIAL(deathtype))
- {
- if(IS_PLAYER(targ)) // don't do this for vehicles
- if(IsFlying(victim))
- yoda = 1;
- }
- }
- }
- else if(IS_PLAYER(attacker))
- {
- // if enemy gets frozen in this frame and receives other damage don't
- // play the typehitsound e.g. when hit by multiple bullets of the shotgun
- if (deathtype != DEATH_FIRE.m_id && (!STAT(FROZEN, victim) || time > victim.freeze_time))
- {
- attacker.typehitsound += 1;
- }
- if(complainteamdamage > 0)
- if(time > CS(attacker).teamkill_complain)
- {
- CS(attacker).teamkill_complain = time + 5;
- CS(attacker).teamkill_soundtime = time + 0.4;
- CS(attacker).teamkill_soundsource = targ;
- }
- }
- }
- }
- }
-
- // apply push
- if (targ.damageforcescale)
- if (force)
- if (!IS_PLAYER(targ) || time >= targ.spawnshieldtime || targ == attacker)
- {
- vector farce = damage_explosion_calcpush(targ.damageforcescale * force, targ.velocity, autocvar_g_balance_damagepush_speedfactor);
- if(targ.move_movetype == MOVETYPE_PHYSICS)
- {
- entity farcent = new(farce);
- farcent.enemy = targ;
- farcent.movedir = farce * 10;
- if(targ.mass)
- farcent.movedir = farcent.movedir * targ.mass;
- farcent.origin = hitloc;
- farcent.forcetype = FORCETYPE_FORCEATPOS;
- farcent.nextthink = time + 0.1;
- setthink(farcent, SUB_Remove);
- }
- else if(targ.move_movetype != MOVETYPE_NOCLIP)
- {
- targ.velocity = targ.velocity + farce;
- }
- UNSET_ONGROUND(targ);
- UpdateCSQCProjectile(targ);
- }
- // apply damage
- if (damage != 0 || (targ.damageforcescale && force))
- if (targ.event_damage)
- targ.event_damage (targ, inflictor, attacker, damage, deathtype, weaponentity, hitloc, force);
-
- // apply mirror damage if any
- if(!autocvar_g_mirrordamage_onlyweapons || DEATH_WEAPONOF(deathtype) != WEP_Null)
- if(mirrordamage > 0 || mirrorforce > 0)
- {
- attacker = attacker_save;
-
- force = normalize(attacker.origin + attacker.view_ofs - hitloc) * mirrorforce;
- Damage(attacker, inflictor, attacker, mirrordamage, DEATH_MIRRORDAMAGE.m_id, weaponentity, attacker.origin, force);
- }
-}
-
-float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe,
- float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype, .entity weaponentity, entity directhitentity)
- // Returns total damage applies to creatures
-{
- entity targ;
- vector force;
- float total_damage_to_creatures;
- entity next;
- float tfloordmg;
- float tfloorforce;
-
- float stat_damagedone;
-
- if(RadiusDamage_running)
- {
- backtrace("RadiusDamage called recursively! Expect stuff to go HORRIBLY wrong.");
- return 0;
- }
-
- RadiusDamage_running = 1;
-
- tfloordmg = autocvar_g_throughfloor_damage;
- tfloorforce = autocvar_g_throughfloor_force;
-
- total_damage_to_creatures = 0;
-
- if(deathtype != (WEP_HOOK.m_id | HITTYPE_SECONDARY | HITTYPE_BOUNCE)) // only send gravity bomb damage once
- if(!(deathtype & HITTYPE_SOUND)) // do not send radial sound damage (bandwidth hog)
- {
- force = inflictorvelocity;
- if(force == '0 0 0')
- force = '0 0 -1';
- else
- force = normalize(force);
- if(forceintensity >= 0)
- Damage_DamageInfo(inflictororigin, coredamage, edgedamage, rad, forceintensity * force, deathtype, 0, attacker);
- else
- Damage_DamageInfo(inflictororigin, coredamage, edgedamage, -rad, (-forceintensity) * force, deathtype, 0, attacker);
- }
-
- stat_damagedone = 0;
-
- targ = WarpZone_FindRadius (inflictororigin, rad + MAX_DAMAGEEXTRARADIUS, false);
- while (targ)
- {
- next = targ.chain;
- if ((targ != inflictor) || inflictorselfdamage)
- if (((cantbe != targ) && !mustbe) || (mustbe == targ))
- if (targ.takedamage)
- {
- vector nearest;
- vector diff;
- float power;
-
- // LordHavoc: measure distance to nearest point on target (not origin)
- // (this guarentees 100% damage on a touch impact)
- nearest = targ.WarpZone_findradius_nearest;
- diff = targ.WarpZone_findradius_dist;
- // round up a little on the damage to ensure full damage on impacts
- // and turn the distance into a fraction of the radius
- power = 1 - ((vlen (diff) - bound(MIN_DAMAGEEXTRARADIUS, targ.damageextraradius, MAX_DAMAGEEXTRARADIUS)) / rad);
- //bprint(" ");
- //bprint(ftos(power));
- //if (targ == attacker)
- // print(ftos(power), "\n");
- if (power > 0)
- {
- float finaldmg;
- if (power > 1)
- power = 1;
- finaldmg = coredamage * power + edgedamage * (1 - power);
- if (finaldmg > 0)
- {
- float a;
- float c;
- vector hitloc;
- vector myblastorigin;
- vector center;
-
- myblastorigin = WarpZone_TransformOrigin(targ, inflictororigin);
-
- // if it's a player, use the view origin as reference
- center = CENTER_OR_VIEWOFS(targ);
-
- force = normalize(center - myblastorigin);
- force = force * (finaldmg / coredamage) * forceintensity;
- hitloc = nearest;
-
- // apply special scaling along the z axis if set
- // NOTE: 0 value is not allowed for compatibility, in the case of weapon cvars not being set
- if(forcezscale)
- force.z *= forcezscale;
-
- if(targ != directhitentity)
- {
- float hits;
- float total;
- float hitratio;
- float mininv_f, mininv_d;
-
- // test line of sight to multiple positions on box,
- // and do damage if any of them hit
- hits = 0;
-
- // we know: max stddev of hitratio = 1 / (2 * sqrt(n))
- // so for a given max stddev:
- // n = (1 / (2 * max stddev of hitratio))^2
-
- mininv_d = (finaldmg * (1-tfloordmg)) / autocvar_g_throughfloor_damage_max_stddev;
- mininv_f = (vlen(force) * (1-tfloorforce)) / autocvar_g_throughfloor_force_max_stddev;
-
- if(autocvar_g_throughfloor_debug)
- LOG_INFOF("THROUGHFLOOR: D=%f F=%f max(dD)=1/%f max(dF)=1/%f", finaldmg, vlen(force), mininv_d, mininv_f);
-
-
- total = 0.25 * (max(mininv_f, mininv_d) ** 2);
-
- if(autocvar_g_throughfloor_debug)
- LOG_INFOF(" steps=%f", total);
-
-
- if (IS_PLAYER(targ))
- total = ceil(bound(autocvar_g_throughfloor_min_steps_player, total, autocvar_g_throughfloor_max_steps_player));
- else
- total = ceil(bound(autocvar_g_throughfloor_min_steps_other, total, autocvar_g_throughfloor_max_steps_other));
-
- if(autocvar_g_throughfloor_debug)
- LOG_INFOF(" steps=%f dD=%f dF=%f", total, finaldmg * (1-tfloordmg) / (2 * sqrt(total)), vlen(force) * (1-tfloorforce) / (2 * sqrt(total)));
-
- for(c = 0; c < total; ++c)
- {
- //traceline(targ.WarpZone_findradius_findorigin, nearest, MOVE_NOMONSTERS, inflictor);
- WarpZone_TraceLine(inflictororigin, WarpZone_UnTransformOrigin(targ, nearest), MOVE_NOMONSTERS, inflictor);
- if (trace_fraction == 1 || trace_ent == targ)
- {
- ++hits;
- if (hits > 1)
- hitloc = hitloc + nearest;
- else
- hitloc = nearest;
- }
- nearest.x = targ.origin.x + targ.mins.x + random() * targ.size.x;
- nearest.y = targ.origin.y + targ.mins.y + random() * targ.size.y;
- nearest.z = targ.origin.z + targ.mins.z + random() * targ.size.z;
- }
-
- nearest = hitloc * (1 / max(1, hits));
- hitratio = (hits / total);
- a = bound(0, tfloordmg + (1-tfloordmg) * hitratio, 1);
- finaldmg = finaldmg * a;
- a = bound(0, tfloorforce + (1-tfloorforce) * hitratio, 1);
- force = force * a;
-
- if(autocvar_g_throughfloor_debug)
- LOG_INFOF(" D=%f F=%f", finaldmg, vlen(force));
- }
-
- //if (targ == attacker)
- //{
- // print("hits ", ftos(hits), " / ", ftos(total));
- // print(" finaldmg ", ftos(finaldmg), " force ", vtos(force));
- // print(" (", ftos(a), ")\n");
- //}
- if(finaldmg || force)
- {
- if(targ.iscreature)
- {
- total_damage_to_creatures += finaldmg;
-
- if(accuracy_isgooddamage(attacker, targ))
- stat_damagedone += finaldmg;
- }
-
- if(targ == directhitentity || DEATH_ISSPECIAL(deathtype))
- Damage(targ, inflictor, attacker, finaldmg, deathtype, weaponentity, nearest, force);
- else
- Damage(targ, inflictor, attacker, finaldmg, deathtype | HITTYPE_SPLASH, weaponentity, nearest, force);
- }
- }
- }
- }
- targ = next;
- }
-
- RadiusDamage_running = 0;
-
- if(!DEATH_ISSPECIAL(deathtype))
- accuracy_add(attacker, DEATH_WEAPONOF(deathtype), 0, min(coredamage, stat_damagedone));
-
- 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)
-{
- return RadiusDamageForSource(inflictor, (inflictor.origin + (inflictor.mins + inflictor.maxs) * 0.5), inflictor.velocity, attacker, coredamage, edgedamage, rad,
- cantbe, mustbe, false, forceintensity, 1, deathtype, weaponentity, directhitentity);
-}
-
-bool Heal(entity targ, entity inflictor, float amount, float limit)
-{
- if(game_stopped || (IS_CLIENT(targ) && CS(targ).killcount == FRAGS_SPECTATOR) || STAT(FROZEN, targ) || IS_DEAD(targ))
- return false;
-
- bool healed = false;
- if(targ.event_heal)
- healed = targ.event_heal(targ, inflictor, amount, limit);
- // TODO: additional handling? what if the healing kills them? should this abort if healing would do so etc
- // TODO: healing fx!
- // TODO: armor healing?
- return healed;
-}
-
-float Fire_IsBurning(entity e)
-{
- return (time < e.fire_endtime);
-}
-
-float Fire_AddDamage(entity e, entity o, float d, float t, float dt)
-{
- float dps;
- float maxtime, mintime, maxdamage, mindamage, maxdps, mindps, totaldamage, totaltime;
-
- if(IS_PLAYER(e))
- {
- if(IS_DEAD(e))
- return -1;
- }
- else
- {
- if(!e.fire_burner)
- {
- // print("adding a fire burner to ", e.classname, "\n");
- e.fire_burner = new(fireburner);
- setthink(e.fire_burner, fireburner_think);
- e.fire_burner.nextthink = time;
- e.fire_burner.owner = e;
- }
- }
-
- t = max(t, 0.1);
- dps = d / t;
- if(Fire_IsBurning(e))
- {
- mintime = e.fire_endtime - time;
- maxtime = max(mintime, t);
-
- mindps = e.fire_damagepersec;
- maxdps = max(mindps, dps);
-
- if(maxtime > mintime || maxdps > mindps)
- {
- // Constraints:
-
- // damage we have right now
- mindamage = mindps * mintime;
-
- // damage we want to get
- maxdamage = mindamage + d;
-
- // but we can't exceed maxtime * maxdps!
- totaldamage = min(maxdamage, maxtime * maxdps);
-
- // LEMMA:
- // Look at:
- // totaldamage = min(mindamage + d, maxtime * maxdps)
- // We see:
- // totaldamage <= maxtime * maxdps
- // ==> totaldamage / maxdps <= maxtime.
- // We also see:
- // totaldamage / mindps = min(mindamage / mindps + d, maxtime * maxdps / mindps)
- // >= min(mintime, maxtime)
- // ==> totaldamage / maxdps >= mintime.
-
- /*
- // how long do we damage then?
- // at least as long as before
- // but, never exceed maxdps
- totaltime = max(mintime, totaldamage / maxdps); // always <= maxtime due to lemma
- */
-
- // alternate:
- // at most as long as maximum allowed
- // but, never below mindps
- totaltime = min(maxtime, totaldamage / mindps); // always >= mintime due to lemma
-
- // assuming t > mintime, dps > mindps:
- // we get d = t * dps = maxtime * maxdps
- // totaldamage = min(maxdamage, maxtime * maxdps) = min(... + d, maxtime * maxdps) = maxtime * maxdps
- // totaldamage / maxdps = maxtime
- // totaldamage / mindps > totaldamage / maxdps = maxtime
- // FROM THIS:
- // a) totaltime = max(mintime, maxtime) = maxtime
- // b) totaltime = min(maxtime, totaldamage / maxdps) = maxtime
-
- // assuming t <= mintime:
- // we get maxtime = mintime
- // a) totaltime = max(mintime, ...) >= mintime, also totaltime <= maxtime by the lemma, therefore totaltime = mintime = maxtime
- // b) totaltime = min(maxtime, ...) <= maxtime, also totaltime >= mintime by the lemma, therefore totaltime = mintime = maxtime
-
- // assuming dps <= mindps:
- // we get mindps = maxdps.
- // With this, the lemma says that mintime <= totaldamage / mindps = totaldamage / maxdps <= maxtime.
- // a) totaltime = max(mintime, totaldamage / maxdps) = totaldamage / maxdps
- // b) totaltime = min(maxtime, totaldamage / mindps) = totaldamage / maxdps
-
- e.fire_damagepersec = totaldamage / totaltime;
- e.fire_endtime = time + totaltime;
- if(totaldamage > 1.2 * mindamage)
- {
- e.fire_deathtype = dt;
- if(e.fire_owner != o)
- {
- e.fire_owner = o;
- e.fire_hitsound = false;
- }
- }
- if(accuracy_isgooddamage(o, e))
- accuracy_add(o, DEATH_WEAPONOF(dt), 0, max(0, totaldamage - mindamage));
- return max(0, totaldamage - mindamage); // can never be negative, but to make sure
- }
- else
- return 0;
- }
- else
- {
- e.fire_damagepersec = dps;
- e.fire_endtime = time + t;
- e.fire_deathtype = dt;
- e.fire_owner = o;
- e.fire_hitsound = false;
- if(accuracy_isgooddamage(o, e))
- accuracy_add(o, DEATH_WEAPONOF(dt), 0, d);
- return d;
- }
-}
-
-void Fire_ApplyDamage(entity e)
-{
- float t, d, hi, ty;
- entity o;
-
- if (!Fire_IsBurning(e))
- return;
-
- for(t = 0, o = e.owner; o.owner && t < 16; o = o.owner, ++t);
- if(IS_NOT_A_CLIENT(o))
- o = e.fire_owner;
-
- // water and slime stop fire
- if(e.waterlevel)
- if(e.watertype != CONTENT_LAVA)
- e.fire_endtime = 0;
-
- // ice stops fire
- if(STAT(FROZEN, e))
- e.fire_endtime = 0;
-
- t = min(frametime, e.fire_endtime - time);
- d = e.fire_damagepersec * t;
-
- hi = e.fire_owner.damage_dealt;
- ty = e.fire_owner.typehitsound;
- Damage(e, e, e.fire_owner, d, e.fire_deathtype, DMG_NOWEP, e.origin, '0 0 0');
- if(e.fire_hitsound && e.fire_owner)
- {
- e.fire_owner.damage_dealt = hi;
- e.fire_owner.typehitsound = ty;
- }
- e.fire_hitsound = true;
-
- if(!IS_INDEPENDENT_PLAYER(e) && !STAT(FROZEN, e))
- {
- IL_EACH(g_damagedbycontents, it.damagedbycontents && it != e,
- {
- if(!IS_DEAD(it) && it.takedamage && !IS_INDEPENDENT_PLAYER(it))
- if(boxesoverlap(e.absmin, e.absmax, it.absmin, it.absmax))
- {
- t = autocvar_g_balance_firetransfer_time * (e.fire_endtime - time);
- d = autocvar_g_balance_firetransfer_damage * e.fire_damagepersec * t;
- Fire_AddDamage(it, o, d, t, DEATH_FIRE.m_id);
- }
- });
- }
-}
-
-void Fire_ApplyEffect(entity e)
-{
- if(Fire_IsBurning(e))
- e.effects |= EF_FLAME;
- else
- e.effects &= ~EF_FLAME;
-}
-
-void fireburner_think(entity this)
-{
- // for players, this is done in the regular loop
- if(wasfreed(this.owner))
- {
- delete(this);
- return;
- }
- Fire_ApplyEffect(this.owner);
- if(!Fire_IsBurning(this.owner))
- {
- this.owner.fire_burner = NULL;
- delete(this);
- return;
- }
- Fire_ApplyDamage(this.owner);
- this.nextthink = time;
-}
+++ /dev/null
-#pragma once
-
-#if defined(CSQC)
-#elif defined(MENUQC)
-#elif defined(SVQC)
- #include <server/defs.qh>
- #include <server/miscfunctions.qh>
- #include <lib/warpzone/common.qh>
- #include <common/constants.qh>
- #include <common/teams.qh>
- #include <common/util.qh>
- #include <common/weapons/_all.qh>
- #include "weapons/accuracy.qh"
- #include "weapons/csqcprojectile.qh"
- #include "weapons/selection.qh"
- #include <common/t_items.qh>
- #include "autocvars.qh"
- #include "constants.qh"
- #include "defs.qh"
- #include <common/notifications/all.qh>
- #include <common/deathtypes/all.qh>
- #include <server/mutators/_mod.qh>
- #include <common/turrets/sv_turrets.qh>
- #include <common/vehicles/all.qh>
- #include <lib/csqcmodel/sv_model.qh>
- #include <common/playerstats.qh>
- #include "g_hook.qh"
- #include "scores.qh"
- #include "spawnpoints.qh"
-#endif
-
-.float dmg;
-.float dmg_edge;
-.float dmg_force;
-.float dmg_radius;
-
-bool Damage_DamageInfo_SendEntity(entity this, entity to, int sf);
-
-void Damage_DamageInfo(vector org, float coredamage, float edgedamage, float rad, vector force, int deathtype, float bloodtype, entity dmgowner);
-
-float checkrules_firstblood;
-
-float yoda;
-float damage_goodhits;
-float damage_gooddamage;
-
-.float dmg_team;
-.float teamkill_complain;
-.float teamkill_soundtime;
-.entity teamkill_soundsource;
-.entity pusher;
-.bool istypefrag;
-.float taunt_soundtime;
-
-float IsFlying(entity a);
-
-void UpdateFrags(entity player, int f);
-
-// NOTE: f=0 means still count as a (positive) kill, but count no frags for it
-void W_SwitchWeapon_Force(Player this, Weapon w, .entity weaponentity);
-void GiveFrags (entity attacker, entity targ, float f, int deathtype, .entity weaponentity);
-
-string AppendItemcodes(string s, entity player);
-
-void LogDeath(string mode, int deathtype, entity killer, entity killed);
-
-void Obituary_SpecialDeath(
- entity notif_target,
- float murder,
- int deathtype,
- string s1, string s2, string s3,
- float f1, float f2, float f3);
-
-float w_deathtype;
-float Obituary_WeaponDeath(
- entity notif_target,
- float murder,
- int deathtype,
- string s1, string s2, string s3,
- float f1, float f2);
-
-void Obituary(entity attacker, entity inflictor, entity targ, int deathtype, .entity weaponentity);
-
-void Ice_Think(entity this);
-
-void Freeze(entity targ, float freeze_time, int frozen_type, bool show_waypoint);
-
-void Unfreeze(entity targ, bool reset_health);
-
-// NOTE: the .weaponentity parameter can be set to DMG_NOWEP if the attack wasn't caused by a weapon or player
-void Damage (entity targ, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
-
-float RadiusDamage_running;
-float RadiusDamageForSource (entity inflictor, vector inflictororigin, vector inflictorvelocity, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float inflictorselfdamage, float forceintensity, float forcezscale, int deathtype, .entity weaponentity, entity directhitentity);
- // Returns total damage applies 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);
-
-// Calls .event_heal on the target so that they can handle healing themselves
-// a limit of RES_LIMIT_NONE should be handled by the entity as its max health (if applicable)
-bool Heal(entity targ, entity inflictor, float amount, float limit);
-
-.float fire_damagepersec;
-.float fire_endtime;
-.float fire_deathtype;
-.entity fire_owner;
-.float fire_hitsound;
-.entity fire_burner;
-
-void fireburner_think(entity this);
-
-float Fire_IsBurning(entity e);
-
-float Fire_AddDamage(entity e, entity o, float d, float t, float dt);
-
-void Fire_ApplyDamage(entity e);
-
-void Fire_ApplyEffect(entity e);
+++ /dev/null
-#include "g_hook.qh"
-
-#include <server/defs.qh>
-#include <server/miscfunctions.qh>
-#include <common/effects/all.qh>
-#include "weapons/common.qh"
-#include "weapons/csqcprojectile.qh"
-#include "weapons/weaponsystem.qh"
-#include "weapons/selection.qh"
-#include "weapons/tracing.qh"
-#include "player.qh"
-#include "command/common.qh"
-#include "round_handler.qh"
-#include "../common/state.qh"
-#include "../common/physics/player.qh"
-#include "../common/vehicles/all.qh"
-#include "../common/constants.qh"
-#include "../common/util.qh"
-#include <common/net_linked.qh>
-#include <common/weapons/_all.qh>
-#include "../lib/warpzone/common.qh"
-#include "../lib/warpzone/server.qh"
-
-/*============================================
-
- Wazat's Xonotic Grappling Hook
-
- Contact: Wazat1@gmail.com
-
-
-Installation instructions:
---------------------------
-
-1. Place hook.c in your gamec source directory with the other source files.
-
-2. Add this line to the bottom of progs.src:
-
-gamec/hook.c
-
-3. Open defs.h and add these lines to the very bottom:
-
-// Wazat's grappling hook
-.entity hook;
-void GrapplingHookFrame();
-void RemoveGrapplingHook(entity pl);
-void SetGrappleHookBindings();
-// hook impulses
-const float GRAPHOOK_FIRE = 20;
-const float GRAPHOOK_RELEASE = 21;
-// (note: you can change the hook impulse #'s to whatever you please)
-
-4. Open client.c and add this to the top of PutClientInServer():
-
- RemoveGrapplingHook(this); // Wazat's Grappling Hook
-
-5. Find ClientConnect() (in client.c) and add these lines to the bottom:
-
- // Wazat's grappling hook
- SetGrappleHookBindings();
-
-6. Still in client.c, find PlayerPreThink and add this line just above the call to W_WeaponFrame:
-
- GrapplingHookFrame();
-
-7. Build and test the mod. You'll want to bind a key to "+hook" like this:
-bind ctrl "+hook"
-
-And you should be done!
-
-
-============================================*/
-
-void RemoveGrapplingHooks(entity pl)
-{
- if(pl.move_movetype == MOVETYPE_FLY)
- set_movetype(pl, MOVETYPE_WALK);
-
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(!pl.(weaponentity))
- continue; // continue incase other slots exist?
- if(pl.(weaponentity).hook)
- delete(pl.(weaponentity).hook);
- pl.(weaponentity).hook = NULL;
- }
-
- //pl.disableclientprediction = false;
-}
-
-void RemoveHook(entity this)
-{
- entity player = this.realowner;
- .entity weaponentity = this.weaponentity_fld;
-
- if(player.(weaponentity).hook == this)
- player.(weaponentity).hook = NULL;
-
- if(player.move_movetype == MOVETYPE_FLY)
- set_movetype(player, MOVETYPE_WALK);
- delete(this);
-}
-
-void GrapplingHookReset(entity this)
-{
- RemoveHook(this);
-}
-
-void GrapplingHook_Stop(entity this)
-{
- Send_Effect(EFFECT_HOOK_IMPACT, this.origin, '0 0 0', 1);
- sound (this, CH_SHOTS, SND_HOOK_IMPACT, VOL_BASE, ATTEN_NORM);
-
- this.state = 1;
- setthink(this, GrapplingHookThink);
- this.nextthink = time;
- settouch(this, func_null);
- this.velocity = '0 0 0';
- set_movetype(this, MOVETYPE_NONE);
- this.hook_length = -1;
-}
-
-.vector hook_start, hook_end;
-bool GrapplingHookSend(entity this, entity to, int sf)
-{
- WriteHeader(MSG_ENTITY, ENT_CLIENT_HOOK);
- sf = sf & 0x7F;
- if(sound_allowed(MSG_BROADCAST, this.realowner))
- sf |= 0x80;
- WriteByte(MSG_ENTITY, sf);
- if(sf & 1)
- {
- WriteByte(MSG_ENTITY, etof(this.realowner));
- WriteByte(MSG_ENTITY, weaponslot(this.weaponentity_fld));
- }
- if(sf & 2)
- {
- WriteVector(MSG_ENTITY, this.hook_start);
- }
- if(sf & 4)
- {
- WriteVector(MSG_ENTITY, this.hook_end);
- }
- return true;
-}
-
-int autocvar_g_grappling_hook_tarzan;
-
-void GrapplingHookThink(entity this)
-{
- float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
- vector dir, org, end, v0, dv, v, myorg, vs;
- .entity weaponentity = this.weaponentity_fld;
- if(this.realowner.(weaponentity).hook != this) // how did that happen?
- {
- error("Owner lost the hook!\n");
- return;
- }
- if(LostMovetypeFollow(this) || game_stopped || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || ((this.aiment.flags & FL_PROJECTILE) && this.aiment.classname != "nade"))
- {
- RemoveHook(this);
- return;
- }
- if(this.aiment)
- WarpZone_RefSys_AddIncrementally(this, this.aiment);
-
- this.nextthink = time;
-
- int s = W_GunAlign(this.realowner.(weaponentity), STAT(GUNALIGN, this.realowner)) - 1;
- vs = hook_shotorigin[s];
-
- makevectors(this.realowner.v_angle);
- org = this.realowner.origin + this.realowner.view_ofs + v_forward * vs.x + v_right * -vs.y + v_up * vs.z;
- myorg = WarpZone_RefSys_TransformOrigin(this.realowner, this, org);
-
- if(this.hook_length < 0)
- this.hook_length = vlen(myorg - this.origin);
-
- int tarzan = autocvar_g_grappling_hook_tarzan;
- entity pull_entity = this.realowner;
- float velocity_multiplier = 1;
- MUTATOR_CALLHOOK(GrappleHookThink, this, tarzan, pull_entity, velocity_multiplier);
- tarzan = M_ARGV(1, int);
- pull_entity = M_ARGV(2, entity);
- velocity_multiplier = M_ARGV(3, float);
-
- if(this.state == 1)
- {
- pullspeed = autocvar_g_balance_grapplehook_speed_pull;//2000;
- // speed the rope is pulled with
-
- rubberforce = autocvar_g_balance_grapplehook_force_rubber;//2000;
- // force the rope will use if it is stretched
-
- rubberforce_overstretch = autocvar_g_balance_grapplehook_force_rubber_overstretch;//1000;
- // force the rope will use if it is stretched
-
- minlength = autocvar_g_balance_grapplehook_length_min;//100;
- // minimal rope length
- // if the rope goes below this length, it isn't pulled any more
-
- ropestretch = autocvar_g_balance_grapplehook_stretch;//400;
- // if the rope is stretched by more than this amount, more rope is
- // given to you again
-
- ropeairfriction = autocvar_g_balance_grapplehook_airfriction;//0.2
- // while hanging on the rope, this friction component will help you a
- // bit to control the rope
-
- bool frozen_pulling = (autocvar_g_grappling_hook_tarzan >= 2 && autocvar_g_balance_grapplehook_pull_frozen);
-
- dir = this.origin - myorg;
- dist = vlen(dir);
- dir = normalize(dir);
-
- if(tarzan)
- {
- v = v0 = WarpZone_RefSys_TransformVelocity(pull_entity, this, pull_entity.velocity);
-
- // first pull the rope...
- if(this.realowner.(weaponentity).hook_state & HOOK_PULLING)
- {
- newlength = this.hook_length;
- newlength = max(newlength - pullspeed * frametime, minlength);
-
- if(newlength < dist - ropestretch) // overstretched?
- {
- newlength = dist - ropestretch;
- if(v * dir < 0) // only if not already moving in hook direction
- v = v + frametime * dir * rubberforce_overstretch;
- }
-
- this.hook_length = newlength;
- }
-
- if(pull_entity.move_movetype == MOVETYPE_FLY)
- set_movetype(pull_entity, MOVETYPE_WALK);
-
- if(this.realowner.(weaponentity).hook_state & HOOK_RELEASING)
- {
- newlength = dist;
- this.hook_length = newlength;
- }
- else
- {
- // then pull the player
- spd = bound(0, (dist - this.hook_length) / ropestretch, 1);
- v = v * (1 - frametime * ropeairfriction);
- v = v + frametime * dir * spd * rubberforce;
-
- dv = ((v - v0) * dir) * dir;
- if(tarzan >= 2)
- {
- if(this.aiment.move_movetype == MOVETYPE_WALK || this.aiment.classname == "nade")
- {
- entity aim_ent = ((IS_VEHICLE(this.aiment) && this.aiment.owner) ? this.aiment.owner : this.aiment);
- v = v - dv * 0.5;
- if((frozen_pulling && STAT(FROZEN, this.aiment)) || !frozen_pulling)
- {
- this.aiment.velocity = this.aiment.velocity - dv * 0.5;
- UNSET_ONGROUND(this.aiment);
- if(this.aiment.flags & FL_PROJECTILE)
- UpdateCSQCProjectile(this.aiment);
- }
- if(this.aiment.classname == "nade")
- this.aiment.nextthink = time + autocvar_g_balance_grapplehook_nade_time; // set time after letting go?
- aim_ent.pusher = this.realowner;
- aim_ent.pushltime = time + autocvar_g_maxpushtime;
- aim_ent.istypefrag = PHYS_INPUT_BUTTON_CHAT(aim_ent);
- }
- }
-
- UNSET_ONGROUND(pull_entity);
- }
-
- if(!frozen_pulling && !(this.aiment.flags & FL_PROJECTILE))
- pull_entity.velocity = WarpZone_RefSys_TransformVelocity(this, pull_entity, v * velocity_multiplier);
-
- if(frozen_pulling && autocvar_g_balance_grapplehook_pull_frozen == 2 && !STAT(FROZEN, this.aiment))
- {
- RemoveHook(this);
- return;
- }
- }
- else
- {
- end = this.origin - dir*50;
- dist = vlen(end - myorg);
- if(dist < 200)
- spd = dist * (pullspeed / 200);
- else
- spd = pullspeed;
- if(spd < 50)
- spd = 0;
- this.realowner.velocity = dir*spd;
- set_movetype(this.realowner, MOVETYPE_FLY);
-
- UNSET_ONGROUND(this.realowner);
- }
- }
-
- makevectors(this.angles.x * '-1 0 0' + this.angles.y * '0 1 0');
- myorg = WarpZone_RefSys_TransformOrigin(this, this.realowner, this.origin); // + v_forward * (-9);
-
- if(myorg != this.hook_start)
- {
- this.SendFlags |= 2;
- this.hook_start = myorg;
- }
- if(org != this.hook_end)
- {
- this.SendFlags |= 4;
- this.hook_end = org;
- }
-}
-
-void GrapplingHookTouch(entity this, entity toucher)
-{
- if(toucher.move_movetype == MOVETYPE_FOLLOW)
- return;
- PROJECTILE_TOUCH(this, toucher);
-
- GrapplingHook_Stop(this);
-
- if(toucher)
- //if(toucher.move_movetype != MOVETYPE_NONE)
- {
- SetMovetypeFollow(this, toucher);
- WarpZone_RefSys_BeginAddingIncrementally(this, this.aiment);
- }
-
- //this.realowner.disableclientprediction = true;
-}
-
-void GrapplingHook_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
-{
- if(GetResource(this, RES_HEALTH) <= 0)
- return;
-
- if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions
- return; // g_balance_projectiledamage says to halt
-
- TakeResource(this, RES_HEALTH, damage);
-
- if (GetResource(this, RES_HEALTH) <= 0)
- {
- if(attacker != this.realowner)
- {
- this.realowner.pusher = attacker;
- this.realowner.pushltime = time + autocvar_g_maxpushtime;
- this.realowner.istypefrag = PHYS_INPUT_BUTTON_CHAT(this.realowner);
- }
- RemoveHook(this);
- }
-}
-
-void FireGrapplingHook(entity actor, .entity weaponentity)
-{
- if(weaponLocked(actor)) return;
- if(actor.vehicle) return;
-
- int s = W_GunAlign(actor.(weaponentity), STAT(GUNALIGN, actor)) - 1;
- vector vs = hook_shotorigin[s];
- vector oldmovedir = actor.(weaponentity).movedir;
- actor.(weaponentity).movedir = vs;
- W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', true, 0, SND_HOOK_FIRE, CH_WEAPON_B, 0, WEP_HOOK.m_id);
- W_MuzzleFlash(WEP_HOOK, actor, weaponentity, w_shotorg, '0 0 0');
- actor.(weaponentity).movedir = oldmovedir;
-
- entity missile = WarpZone_RefSys_SpawnSameRefSys(actor);
- missile.owner = missile.realowner = actor;
- actor.(weaponentity).hook = missile;
- missile.weaponentity_fld = weaponentity;
- missile.reset = GrapplingHookReset;
- missile.classname = "grapplinghook";
- missile.flags = FL_PROJECTILE;
- IL_PUSH(g_projectiles, missile);
- IL_PUSH(g_bot_dodge, missile);
-
- set_movetype(missile, ((autocvar_g_balance_grapplehook_gravity) ? MOVETYPE_TOSS : MOVETYPE_FLY));
- PROJECTILE_MAKETRIGGER(missile);
-
- //setmodel (missile, MDL_HOOK); // precision set below
- setsize (missile, '-3 -3 -3', '3 3 3');
- setorigin(missile, w_shotorg);
-
- missile.state = 0; // not latched onto anything
-
- W_SetupProjVelocity_Explicit(missile, w_shotdir, v_up, autocvar_g_balance_grapplehook_speed_fly, 0, 0, 0, false);
-
- missile.angles = vectoangles (missile.velocity);
- //missile.glow_color = 250; // 244, 250
- //missile.glow_size = 120;
- settouch(missile, GrapplingHookTouch);
- setthink(missile, GrapplingHookThink);
- missile.nextthink = time;
-
- missile.effects = /*EF_FULLBRIGHT | EF_ADDITIVE |*/ EF_LOWPRECISION;
-
- SetResourceExplicit(missile, RES_HEALTH, autocvar_g_balance_grapplehook_health);
- missile.event_damage = GrapplingHook_Damage;
- missile.takedamage = DAMAGE_AIM;
- missile.damageforcescale = 0;
- missile.damagedbycontents = (autocvar_g_balance_grapplehook_damagedbycontents);
- if(missile.damagedbycontents)
- IL_PUSH(g_damagedbycontents, missile);
-
- missile.hook_start = missile.hook_end = missile.origin;
-
- Net_LinkEntity(missile, false, 0, GrapplingHookSend);
-}
-
-void GrappleHookInit()
-{
- if(g_grappling_hook)
- {
- hook_shotorigin[0] = '8 8 -12';
- hook_shotorigin[1] = '8 8 -12';
- hook_shotorigin[2] = '8 8 -12';
- hook_shotorigin[3] = '8 8 -12';
- }
- else
- {
- Weapon w = WEP_HOOK;
- w.wr_init(w);
- hook_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 1);
- hook_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 2);
- hook_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 3);
- hook_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 4);
- }
-}
+++ /dev/null
-#pragma once
-
-// Wazat's grappling hook
-.entity hook;
-void GrapplingHookThink(entity this);
-void RemoveGrapplingHooks(entity pl);
-void RemoveHook(entity this);
-// (note: you can change the hook impulse #'s to whatever you please)
-.float hook_time;
-
-.float hook_length;
-
-const float HOOK_FIRING = BIT(0);
-const float HOOK_REMOVING = BIT(1);
-const float HOOK_PULLING = BIT(2);
-const float HOOK_RELEASING = BIT(3);
-const float HOOK_WAITING_FOR_RELEASE = BIT(4);
-.float hook_state;
-.int state;
-
-void GrappleHookInit();
-vector hook_shotorigin[4];
-
+++ /dev/null
-#include "g_world.qh"
-
-#include "anticheat.qh"
-#include "antilag.qh"
-#include "bot/api.qh"
-#include "campaign.qh"
-#include "cheats.qh"
-#include "client.qh"
-#include "command/common.qh"
-#include "command/getreplies.qh"
-#include "command/sv_cmd.qh"
-#include "command/vote.qh"
-#include "g_hook.qh"
-#include <server/gamelog.qh>
-#include "ipban.qh"
-#include "mapvoting.qh"
-#include <server/mutators/_mod.qh>
-#include "race.qh"
-#include "scores.qh"
-#include "scores_rules.qh"
-#include "teamplay.qh"
-#include "weapons/weaponstats.qh"
-#include "../common/constants.qh"
-#include <common/net_linked.qh>
-#include "../common/deathtypes/all.qh"
-#include <common/gamemodes/_mod.qh>
-#include "../common/gamemodes/sv_rules.qh"
-#include "../common/mapinfo.qh"
-#include "../common/monsters/_mod.qh"
-#include "../common/monsters/sv_monsters.qh"
-#include "../common/vehicles/all.qh"
-#include "../common/notifications/all.qh"
-#include "../common/physics/player.qh"
-#include "../common/playerstats.qh"
-#include "../common/stats.qh"
-#include "../common/teams.qh"
-#include "../common/mapobjects/trigger/secret.qh"
-#include "../common/mapobjects/target/music.qh"
-#include "../common/util.qh"
-#include "../common/items/_mod.qh"
-#include <common/weapons/_all.qh>
-#include "../common/state.qh"
-
-const float LATENCY_THINKRATE = 10;
-.float latency_sum;
-.float latency_cnt;
-.float latency_time;
-entity pingplreport;
-void PingPLReport_Think(entity this)
-{
- float delta;
- entity e;
-
- delta = 3 / maxclients;
- if(delta < sys_frametime)
- delta = 0;
- this.nextthink = time + delta;
-
- e = edict_num(this.cnt + 1);
- if(IS_CLIENT(e) && IS_REAL_CLIENT(e))
- {
- WriteHeader(MSG_BROADCAST, TE_CSQC_PINGPLREPORT);
- WriteByte(MSG_BROADCAST, this.cnt);
- WriteShort(MSG_BROADCAST, bound(1, CS(e).ping, 65535));
- WriteByte(MSG_BROADCAST, min(ceil(CS(e).ping_packetloss * 255), 255));
- WriteByte(MSG_BROADCAST, min(ceil(CS(e).ping_movementloss * 255), 255));
-
- // record latency times for clients throughout the match so we can report it to playerstats
- if(time > (CS(e).latency_time + LATENCY_THINKRATE))
- {
- CS(e).latency_sum += CS(e).ping;
- CS(e).latency_cnt += 1;
- CS(e).latency_time = time;
- //print("sum: ", ftos(CS(e).latency_sum), ", cnt: ", ftos(CS(e).latency_cnt), ", avg: ", ftos(CS(e).latency_sum / CS(e).latency_cnt), ".\n");
- }
- }
- else
- {
- WriteHeader(MSG_BROADCAST, TE_CSQC_PINGPLREPORT);
- WriteByte(MSG_BROADCAST, this.cnt);
- WriteShort(MSG_BROADCAST, 0);
- WriteByte(MSG_BROADCAST, 0);
- WriteByte(MSG_BROADCAST, 0);
- }
- this.cnt = (this.cnt + 1) % maxclients;
-}
-void PingPLReport_Spawn()
-{
- pingplreport = new_pure(pingplreport);
- setthink(pingplreport, PingPLReport_Think);
- pingplreport.nextthink = time;
-}
-
-const float SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS = 1;
-string redirection_target;
-float world_initialized;
-
-void SetDefaultAlpha()
-{
- if (!MUTATOR_CALLHOOK(SetDefaultAlpha))
- {
- default_player_alpha = autocvar_g_player_alpha;
- if(default_player_alpha == 0)
- default_player_alpha = 1;
- default_weapon_alpha = default_player_alpha;
- }
-}
-
-void GotoFirstMap(entity this)
-{
- float n;
- if(autocvar__sv_init)
- {
- // cvar_set("_sv_init", "0");
- // we do NOT set this to 0 any more, so someone "accidentally" changing
- // to this "init" map on a dedicated server will cause no permanent
- // harm
- if(autocvar_g_maplist_shuffle)
- ShuffleMaplist();
- n = tokenizebyseparator(autocvar_g_maplist, " ");
- cvar_set("g_maplist_index", ftos(n - 1)); // jump to map 0 in GotoNextMap
-
- MapInfo_Enumerate();
- MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
-
- if(!DoNextMapOverride(1))
- GotoNextMap(1);
-
- return;
- }
-
- if(time < 5)
- {
- this.nextthink = time;
- }
- else
- {
- this.nextthink = time + 1;
- LOG_INFO("Waiting for _sv_init being set to 1 by initialization scripts...");
- }
-}
-
-void cvar_changes_init()
-{
- float h;
- string k, v, d;
- float n, i, adding, pureadding;
-
- strfree(cvar_changes);
- strfree(cvar_purechanges);
- cvar_purechanges_count = 0;
-
- h = buf_create();
- buf_cvarlist(h, "", "_"); // exclude all _ cvars as they are temporary
- n = buf_getsize(h);
-
- adding = true;
- pureadding = true;
-
- for(i = 0; i < n; ++i)
- {
- k = bufstr_get(h, i);
-
-#define BADPREFIX(p) if(substring(k, 0, strlen(p)) == p) continue
-#define BADPRESUFFIX(p,s) if(substring(k, 0, strlen(p)) == p && substring(k, -strlen(s), -1) == s) continue
-#define BADCVAR(p) if(k == p) continue
-
- // general excludes and namespaces for server admin used cvars
- BADPREFIX("help_"); // PN's server has this listed as changed, let's not rat him out for THAT
-
- // internal
- BADPREFIX("csqc_");
- BADPREFIX("cvar_check_");
- BADCVAR("gamecfg");
- BADCVAR("g_configversion");
- BADCVAR("halflifebsp");
- BADCVAR("sv_mapformat_is_quake2");
- BADCVAR("sv_mapformat_is_quake3");
- BADPREFIX("sv_world");
-
- // client
- BADPREFIX("chase_");
- BADPREFIX("cl_");
- BADPREFIX("con_");
- BADPREFIX("scoreboard_");
- BADPREFIX("g_campaign");
- BADPREFIX("g_waypointsprite_");
- BADPREFIX("gl_");
- BADPREFIX("joy");
- BADPREFIX("hud_");
- BADPREFIX("m_");
- BADPREFIX("menu_");
- BADPREFIX("net_slist_");
- BADPREFIX("r_");
- BADPREFIX("sbar_");
- BADPREFIX("scr_");
- BADPREFIX("snd_");
- BADPREFIX("show");
- BADPREFIX("sensitivity");
- BADPREFIX("userbind");
- BADPREFIX("v_");
- BADPREFIX("vid_");
- BADPREFIX("crosshair");
- BADCVAR("mod_q3bsp_lightmapmergepower");
- BADCVAR("mod_q3bsp_nolightmaps");
- BADCVAR("fov");
- BADCVAR("mastervolume");
- BADCVAR("volume");
- BADCVAR("bgmvolume");
- BADCVAR("in_pitch_min");
- BADCVAR("in_pitch_max");
-
- // private
- BADCVAR("developer");
- BADCVAR("log_dest_udp");
- BADCVAR("net_address");
- BADCVAR("net_address_ipv6");
- BADCVAR("port");
- BADCVAR("savedgamecfg");
- BADCVAR("serverconfig");
- BADCVAR("sv_autoscreenshot");
- BADCVAR("sv_heartbeatperiod");
- BADCVAR("sv_vote_master_password");
- BADCVAR("sys_colortranslation");
- BADCVAR("sys_specialcharactertranslation");
- BADCVAR("timeformat");
- BADCVAR("timestamps");
- BADCVAR("g_require_stats");
- BADPREFIX("developer_");
- BADPREFIX("g_ban_");
- BADPREFIX("g_banned_list");
- BADPREFIX("g_require_stats_");
- BADPREFIX("g_chat_flood_");
- BADPREFIX("g_ghost_items");
- BADPREFIX("g_playerstats_");
- BADPREFIX("g_voice_flood_");
- BADPREFIX("log_file");
- BADPREFIX("quit_");
- BADPREFIX("rcon_");
- BADPREFIX("sv_allowdownloads");
- BADPREFIX("sv_autodemo");
- BADPREFIX("sv_curl_");
- BADPREFIX("sv_eventlog");
- BADPREFIX("sv_logscores_");
- BADPREFIX("sv_master");
- BADPREFIX("sv_weaponstats_");
- BADPREFIX("sv_waypointsprite_");
- BADCVAR("rescan_pending");
-
- // these can contain player IDs, so better hide
- BADPREFIX("g_forced_team_");
- BADCVAR("sv_muteban_list");
- BADCVAR("sv_voteban_list");
- BADCVAR("sv_allow_customplayermodels_idlist");
- BADCVAR("sv_allow_customplayermodels_speciallist");
-
- // mapinfo
- BADCVAR("fraglimit");
- BADCVAR("g_arena");
- BADCVAR("g_assault");
- BADCVAR("g_ca");
- BADCVAR("g_ca_teams");
- BADCVAR("g_conquest");
- BADCVAR("g_conquest_teams");
- BADCVAR("g_ctf");
- BADCVAR("g_cts");
- BADCVAR("g_dotc");
- BADCVAR("g_dm");
- BADCVAR("g_domination");
- BADCVAR("g_domination_default_teams");
- BADCVAR("g_duel");
- BADCVAR("g_duel_not_dm_maps");
- BADCVAR("g_freezetag");
- BADCVAR("g_freezetag_teams");
- BADCVAR("g_invasion_teams");
- BADCVAR("g_invasion_type");
- BADCVAR("g_jailbreak");
- BADCVAR("g_jailbreak_teams");
- BADCVAR("g_keepaway");
- BADCVAR("g_keyhunt");
- BADCVAR("g_keyhunt_teams");
- BADCVAR("g_lms");
- BADCVAR("g_nexball");
- BADCVAR("g_onslaught");
- BADCVAR("g_race");
- BADCVAR("g_race_laps_limit");
- BADCVAR("g_race_qualifying_timelimit");
- BADCVAR("g_race_qualifying_timelimit_override");
- BADCVAR("g_runematch");
- BADCVAR("g_shootfromeye");
- BADCVAR("g_snafu");
- BADCVAR("g_survival");
- BADCVAR("g_survival_not_dm_maps");
- BADCVAR("g_tdm");
- BADCVAR("g_tdm_on_dm_maps");
- BADCVAR("g_tdm_teams");
- BADCVAR("g_vip");
- BADCVAR("leadlimit");
- BADCVAR("nextmap");
- BADCVAR("teamplay");
- BADCVAR("timelimit");
- BADCVAR("g_mapinfo_settemp_acl");
- BADCVAR("g_mapinfo_ignore_warnings");
- BADCVAR("g_maplist_ignore_sizes");
- BADCVAR("g_maplist_sizes_count_bots");
-
- // long
- BADCVAR("hostname");
- BADCVAR("g_maplist");
- BADCVAR("g_maplist_mostrecent");
- BADCVAR("sv_motd");
-
- v = cvar_string(k);
- d = cvar_defstring(k);
- if(v == d)
- continue;
-
- if(adding)
- {
- cvar_changes = strcat(cvar_changes, k, " \"", v, "\" // \"", d, "\"\n");
- if(strlen(cvar_changes) > 16384)
- {
- cvar_changes = "// too many settings have been changed to show them here\n";
- adding = 0;
- }
- }
-
- // now check if the changes are actually gameplay relevant
-
- // does nothing gameplay relevant
- BADCVAR("captureleadlimit_override");
- BADCVAR("condump_stripcolors");
- BADCVAR("gameversion");
- BADCVAR("fs_gamedir");
- BADCVAR("g_allow_oldvortexbeam");
- BADCVAR("g_balance_kill_delay");
- BADCVAR("g_buffs_pickup_anyway");
- BADCVAR("g_buffs_randomize");
- BADCVAR("g_buffs_randomize_teamplay");
- BADCVAR("g_campcheck_distance");
- BADCVAR("g_chatsounds");
- BADCVAR("g_ca_point_leadlimit");
- BADCVAR("g_ca_point_limit");
- BADCVAR("g_ctf_captimerecord_always");
- BADCVAR("g_ctf_flag_glowtrails");
- BADCVAR("g_ctf_dynamiclights");
- BADCVAR("g_ctf_flag_pickup_verbosename");
- BADPRESUFFIX("g_ctf_flag_", "_model");
- BADPRESUFFIX("g_ctf_flag_", "_skin");
- BADCVAR("g_domination_point_leadlimit");
- BADCVAR("g_forced_respawn");
- BADCVAR("g_freezetag_point_leadlimit");
- BADCVAR("g_freezetag_point_limit");
- BADCVAR("g_glowtrails");
- BADCVAR("g_hats");
- BADCVAR("g_casings");
- BADCVAR("g_invasion_point_limit");
- BADCVAR("g_jump_grunt");
- BADCVAR("g_keepaway_ballcarrier_effects");
- BADCVAR("g_keepawayball_effects");
- BADCVAR("g_keyhunt_point_leadlimit");
- BADCVAR("g_nexball_goalleadlimit");
- BADCVAR("g_new_toys_autoreplace");
- BADCVAR("g_new_toys_use_pickupsound");
- BADCVAR("g_physics_predictall");
- BADCVAR("g_piggyback");
- BADCVAR("g_playerclip_collisions");
- BADCVAR("g_spawn_alloweffects");
- BADCVAR("g_tdm_point_leadlimit");
- BADCVAR("g_tdm_point_limit");
- BADCVAR("leadlimit_and_fraglimit");
- BADCVAR("leadlimit_override");
- BADCVAR("pausable");
- BADCVAR("sv_announcer");
- BADCVAR("sv_checkforpacketsduringsleep");
- BADCVAR("sv_damagetext");
- BADCVAR("sv_db_saveasdump");
- BADCVAR("sv_intermission_cdtrack");
- BADCVAR("sv_mapchange_delay");
- BADCVAR("sv_minigames");
- BADCVAR("sv_namechangetimer");
- BADCVAR("sv_precacheplayermodels");
- BADCVAR("sv_radio");
- BADCVAR("sv_stepheight");
- BADCVAR("sv_timeout");
- BADCVAR("sv_weapons_modeloverride");
- BADCVAR("w_prop_interval");
- BADPREFIX("chat_");
- BADPREFIX("crypto_");
- BADPREFIX("gameversion_");
- BADPREFIX("g_chat_");
- BADPREFIX("g_ctf_captimerecord_");
- BADPREFIX("g_hats_");
- BADPREFIX("g_maplist_");
- BADPREFIX("g_mod_");
- BADPREFIX("g_respawn_");
- BADPREFIX("net_");
- BADPREFIX("notification_");
- BADPREFIX("prvm_");
- BADPREFIX("skill_");
- BADPREFIX("sv_allow_");
- BADPREFIX("sv_cullentities_");
- BADPREFIX("sv_maxidle_");
- BADPREFIX("sv_minigames_");
- BADPREFIX("sv_radio_");
- BADPREFIX("sv_timeout_");
- BADPREFIX("sv_vote_");
- BADPREFIX("timelimit_");
-
- // allowed changes to server admins (please sync this to server.cfg)
- // vi commands:
- // :/"impure"/,$d
- // :g!,^\/\/[^ /],d
- // :%s,//\([^ ]*\).*,BADCVAR("\1");,
- // :%!sort
- // yes, this does contain some redundant stuff, don't really care
- BADPREFIX("bot_ai_");
- BADCVAR("bot_config_file");
- BADCVAR("bot_number");
- BADCVAR("bot_prefix");
- BADCVAR("bot_suffix");
- BADCVAR("capturelimit_override");
- BADCVAR("fraglimit_override");
- BADCVAR("gametype");
- BADCVAR("g_antilag");
- BADCVAR("g_balance_teams");
- BADCVAR("g_balance_teams_prevent_imbalance");
- BADCVAR("g_balance_teams_scorefactor");
- BADCVAR("g_ban_sync_trusted_servers");
- BADCVAR("g_ban_sync_uri");
- BADCVAR("g_buffs");
- BADCVAR("g_ca_teams_override");
- BADCVAR("g_ctf_fullbrightflags");
- BADCVAR("g_ctf_ignore_frags");
- BADCVAR("g_ctf_leaderboard");
- BADCVAR("g_domination_point_limit");
- BADCVAR("g_domination_teams_override");
- BADCVAR("g_freezetag_teams_override");
- BADCVAR("g_friendlyfire");
- BADCVAR("g_fullbrightitems");
- BADCVAR("g_fullbrightplayers");
- BADCVAR("g_keyhunt_point_limit");
- BADCVAR("g_keyhunt_teams_override");
- BADCVAR("g_lms_lives_override");
- BADCVAR("g_maplist");
- BADCVAR("g_maxplayers");
- BADCVAR("g_mirrordamage");
- BADCVAR("g_nexball_goallimit");
- BADCVAR("g_norecoil");
- BADCVAR("g_physics_clientselect");
- BADCVAR("g_pinata");
- BADCVAR("g_powerups");
- BADCVAR("g_player_brightness");
- BADCVAR("g_rocket_flying");
- BADCVAR("g_rocket_flying_disabledelays");
- BADCVAR("g_spawnshieldtime");
- BADCVAR("g_start_delay");
- BADCVAR("g_superspectate");
- BADCVAR("g_tdm_teams_override");
- BADCVAR("g_warmup");
- BADCVAR("g_weapon_stay"); BADPRESUFFIX("g_", "_weapon_stay");
- BADCVAR("hostname");
- BADCVAR("log_file");
- BADCVAR("maxplayers");
- BADCVAR("minplayers");
- BADCVAR("minplayers_per_team");
- BADCVAR("net_address");
- BADCVAR("port");
- BADCVAR("rcon_password");
- BADCVAR("rcon_restricted_commands");
- BADCVAR("rcon_restricted_password");
- BADCVAR("skill");
- BADCVAR("sv_adminnick");
- BADCVAR("sv_autoscreenshot");
- BADCVAR("sv_autotaunt");
- BADCVAR("sv_curl_defaulturl");
- BADCVAR("sv_defaultcharacter");
- BADCVAR("sv_defaultcharacterskin");
- BADCVAR("sv_defaultplayercolors");
- BADCVAR("sv_defaultplayermodel");
- BADCVAR("sv_defaultplayerskin");
- BADCVAR("sv_maxidle");
- BADCVAR("sv_maxrate");
- BADCVAR("sv_motd");
- BADCVAR("sv_public");
- BADCVAR("sv_ready_restart");
- BADCVAR("sv_status_privacy");
- BADCVAR("sv_taunt");
- BADCVAR("sv_vote_call");
- BADCVAR("sv_vote_commands");
- BADCVAR("sv_vote_majority_factor");
- BADCVAR("sv_vote_master");
- BADCVAR("sv_vote_master_commands");
- BADCVAR("sv_vote_master_password");
- BADCVAR("sv_vote_simple_majority_factor");
- BADCVAR("teamplay_mode");
- BADCVAR("timelimit_override");
- BADPREFIX("g_warmup_");
- BADPREFIX("sv_info_");
- BADPREFIX("sv_ready_restart_");
-
- // mutators that announce themselves properly to the server browser
- BADCVAR("g_instagib");
- BADCVAR("g_new_toys");
- BADCVAR("g_nix");
- BADCVAR("g_grappling_hook");
- BADCVAR("g_jetpack");
-
- // temporary for testing
- // TODO remove before 0.8.3 release
- BADCVAR("g_ca_weaponarena");
- BADCVAR("g_freezetag_weaponarena");
- BADCVAR("g_lms_weaponarena");
- BADCVAR("g_ctf_stalemate_time");
-
- if(cvar_string("g_mod_balance") == "Testing")
- {
- // (temporary) while using the Testing balance, any weapon balance cvars are allowed to be changed
- BADPREFIX("g_balance_");
- }
-
-#undef BADPRESUFFIX
-#undef BADPREFIX
-#undef BADCVAR
-
- if(pureadding)
- {
- cvar_purechanges = strcat(cvar_purechanges, k, " \"", v, "\" // \"", d, "\"\n");
- if(strlen(cvar_purechanges) > 16384)
- {
- cvar_purechanges = "// too many settings have been changed to show them here\n";
- pureadding = 0;
- }
- }
- ++cvar_purechanges_count;
- // WARNING: this variable is used for the server list
- // NEVER dare to skip this code!
- // Hacks to intentionally appearing as "pure server" even though you DO have
- // modified settings may be punished by removal from the server list.
- // You can do to the variables cvar_changes and cvar_purechanges all you want,
- // though.
- }
- buf_del(h);
- if(cvar_changes == "")
- cvar_changes = "// this server runs at default server settings\n";
- else
- cvar_changes = strcat("// this server runs at modified server settings:\n", cvar_changes);
- cvar_changes = strzone(cvar_changes);
- if(cvar_purechanges == "")
- cvar_purechanges = "// this server runs at default gameplay settings\n";
- else
- cvar_purechanges = strcat("// this server runs at modified gameplay settings:\n", cvar_purechanges);
- cvar_purechanges = strzone(cvar_purechanges);
-}
-
-entity randomseed;
-bool RandomSeed_Send(entity this, entity to, int sf)
-{
- WriteHeader(MSG_ENTITY, ENT_CLIENT_RANDOMSEED);
- WriteShort(MSG_ENTITY, this.cnt);
- return true;
-}
-void RandomSeed_Think(entity this)
-{
- this.cnt = bound(0, floor(random() * 65536), 65535);
- this.nextthink = time + 5;
-
- this.SendFlags |= 1;
-}
-void RandomSeed_Spawn()
-{
- randomseed = new_pure(randomseed);
- setthink(randomseed, RandomSeed_Think);
- Net_LinkEntity(randomseed, false, 0, RandomSeed_Send);
-
- getthink(randomseed)(randomseed); // sets random seed and nextthink
-}
-
-spawnfunc(__init_dedicated_server)
-{
- // handler for _init/_init map (only for dedicated server initialization)
-
- world_initialized = -1; // don't complain
-
- delete_fn = remove_unsafely;
-
- entity e = spawn();
- setthink(e, GotoFirstMap);
- e.nextthink = time; // this is usually 1 at this point
-
- e = new(info_player_deathmatch); // safeguard against player joining
-
- // assign reflectively to avoid "assignment to world" warning
- for (int i = 0, n = numentityfields(); i < n; ++i) {
- string k = entityfieldname(i);
- if (k == "classname") {
- // safeguard against various stuff ;)
- putentityfieldstring(i, this, "worldspawn");
- break;
- }
- }
-
- // needs to be done so early because of the constants they create
- static_init();
- static_init_late();
- static_init_precache();
-
- IL_PUSH(g_spawnpoints, e); // just incase
-
- MapInfo_Enumerate();
- MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
-}
-
-void __init_dedicated_server_shutdown() {
- MapInfo_Shutdown();
-}
-
-STATIC_INIT_EARLY(maxclients)
-{
- maxclients = 0;
- for (entity head = nextent(NULL); head; head = nextent(head)) {
- ++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)
-{
- server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated")));
-
- bool wantrestart = false;
- {
- if (!server_is_dedicated)
- {
- // force unloading of server pk3 files when starting a listen server
- // localcmd("\nfs_rescan\n"); // FIXME: does more harm than good, has unintended side effects. What we really want is to unload temporary pk3s only
- // restore csqc_progname too
- string expect = "csprogs.dat";
- wantrestart = cvar_string("csqc_progname") != expect;
- cvar_set("csqc_progname", expect);
- }
- else
- {
- // Try to use versioned csprogs from pk3
- // Only ever use versioned csprogs.dat files on dedicated servers;
- // we need to reset csqc_progname on clients ourselves, and it's easier if the client's release name is constant
- string pk3csprogs = "csprogs-" WATERMARK ".dat";
- // This always works; fall back to it if a versioned csprogs.dat is suddenly missing
- string select = "csprogs.dat";
- if (fexists(pk3csprogs)) select = pk3csprogs;
- if (cvar_string("csqc_progname") != select)
- {
- cvar_set("csqc_progname", select);
- wantrestart = true;
- }
- // Check for updates on startup
- // We do it this way for atomicity so that connecting clients still match the server progs and don't disconnect
- int sentinel = fopen("progs.txt", FILE_READ);
- if (sentinel >= 0)
- {
- string switchversion = fgets(sentinel);
- fclose(sentinel);
- if (switchversion != "" && switchversion != WATERMARK)
- {
- LOG_INFOF("Switching progs: " WATERMARK " -> %s", switchversion);
- // if it doesn't exist, assume either:
- // a) the current program was overwritten
- // b) this is a client only update
- string newprogs = sprintf("progs-%s.dat", switchversion);
- if (fexists(newprogs))
- {
- cvar_set("sv_progs", newprogs);
- wantrestart = true;
- }
- string newcsprogs = sprintf("csprogs-%s.dat", switchversion);
- if (fexists(newcsprogs))
- {
- cvar_set("csqc_progname", newcsprogs);
- wantrestart = true;
- }
- }
- }
- }
- if (wantrestart)
- {
- LOG_INFO("Restart requested");
- changelevel(mapname);
- // let initialization continue, shutdown depends on it
- }
- }
-
- if(world_already_spawned)
- error("world already spawned - you may have EXACTLY ONE worldspawn!");
- world_already_spawned = true;
-
- delete_fn = remove_safely; // during spawning, watch what you remove!
-
- cvar_changes_init(); // do this very early now so it REALLY matches the server config
-
- // needs to be done so early because of the constants they create
- static_init();
-
- ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
-
- TemporaryDB = db_create();
-
- // 0 normal
- lightstyle(0, "m");
-
- // 1 FLICKER (first variety)
- lightstyle(1, "mmnmmommommnonmmonqnmmo");
-
- // 2 SLOW STRONG PULSE
- lightstyle(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba");
-
- // 3 CANDLE (first variety)
- lightstyle(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg");
-
- // 4 FAST STROBE
- lightstyle(4, "mamamamamama");
-
- // 5 GENTLE PULSE 1
- lightstyle(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj");
-
- // 6 FLICKER (second variety)
- lightstyle(6, "nmonqnmomnmomomno");
-
- // 7 CANDLE (second variety)
- lightstyle(7, "mmmaaaabcdefgmmmmaaaammmaamm");
-
- // 8 CANDLE (third variety)
- lightstyle(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa");
-
- // 9 SLOW STROBE (fourth variety)
- lightstyle(9, "aaaaaaaazzzzzzzz");
-
- // 10 FLUORESCENT FLICKER
- lightstyle(10, "mmamammmmammamamaaamammma");
-
- // 11 SLOW PULSE NOT FADE TO BLACK
- lightstyle(11, "abcdefghijklmnopqrrqponmlkjihgfedcba");
-
- // styles 32-62 are assigned by the spawnfunc_light program for switchable lights
-
- // 63 testing
- lightstyle(63, "a");
-
- if(autocvar_g_campaign)
- CampaignPreInit();
-
- Map_MarkAsRecent(mapname);
-
- PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
-
- InitGameplayMode();
- static_init_late();
- static_init_precache();
- readlevelcvars();
- GrappleHookInit();
-
- GameRules_limit_fallbacks();
-
- if(warmup_limit == 0)
- warmup_limit = (autocvar_timelimit > 0) ? autocvar_timelimit * 60 : autocvar_timelimit;
-
- player_count = 0;
- bot_waypoints_for_items = autocvar_g_waypoints_for_items;
- if(bot_waypoints_for_items == 1)
- if(this.spawnflags & SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS)
- bot_waypoints_for_items = 0;
-
- WaypointSprite_Init();
-
- GameLogInit(); // prepare everything
- // NOTE for matchid:
- // changing the logic generating it is okay. But:
- // it HAS to stay <= 64 chars
- // character set: ASCII 33-126 without the following characters: : ; ' " \ $
- if(autocvar_sv_eventlog)
- {
- string s = sprintf("%s.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000));
- matchid = strzone(s);
-
- GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
- s = ":gameinfo:mutators:LIST";
-
- MUTATOR_CALLHOOK(BuildMutatorsString, s);
- s = M_ARGV(0, string);
-
- // initialiation stuff, not good in the mutator system
- if(!autocvar_g_use_ammunition)
- s = strcat(s, ":no_use_ammunition");
-
- // initialiation stuff, not good in the mutator system
- if(autocvar_g_pickup_items == 0)
- s = strcat(s, ":no_pickup_items");
- if(autocvar_g_pickup_items > 0)
- s = strcat(s, ":pickup_items");
-
- // initialiation stuff, not good in the mutator system
- if(autocvar_g_weaponarena != "0")
- s = strcat(s, ":", autocvar_g_weaponarena, " arena");
-
- // TODO to mutator system
- if(autocvar_g_norecoil)
- s = strcat(s, ":norecoil");
-
- // TODO to mutator system
- if(autocvar_g_powerups == 0)
- s = strcat(s, ":no_powerups");
- if(autocvar_g_powerups > 0)
- s = strcat(s, ":powerups");
-
- GameLogEcho(s);
- GameLogEcho(":gameinfo:end");
- }
- else
- matchid = strzone(ftos(random()));
-
- cvar_set("nextmap", "");
-
- SetDefaultAlpha();
-
- if(autocvar_g_campaign)
- CampaignPostInit();
-
- Ban_LoadBans();
-
- MapInfo_Enumerate();
- MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1);
-
- if(fexists(_MapInfo_FindArenaFile(mapname, ".arena")))
- cvar_settemp("sv_q3acompat_machineshotgunswap", "1");
-
- if(fexists(_MapInfo_FindArenaFile(mapname, ".defi")))
- cvar_settemp("sv_q3defragcompat", "1");
-
- // quake 3 music support
- if(world.music || world.noise)
- {
- // prefer .music over .noise
- string chosen_music;
- string oldstuff;
- if(world.music)
- chosen_music = world.music;
- else
- chosen_music = world.noise;
- if(
- substring(chosen_music, strlen(chosen_music) - 4, 4) == ".wav"
- ||
- substring(chosen_music, strlen(chosen_music) - 4, 4) == ".ogg"
- )
- oldstuff = strcat(clientstuff, "cd loop \"", chosen_music, "\"\n");
- else
- oldstuff = strcat(clientstuff, "cd loop \"", chosen_music, "\"\n");
-
- strcpy(clientstuff, oldstuff);
- }
-
- if(whichpack(strcat("maps/", mapname, ".cfg")) != "")
- {
- int fd = fopen(strcat("maps/", mapname, ".cfg"), FILE_READ);
- if(fd != -1)
- {
- string s;
- while((s = fgets(fd)))
- {
- int l = tokenize_console(s);
- if(l < 2)
- continue;
- if(argv(0) == "cd")
- {
- string trackname = argv(2);
- LOG_INFO("Found ^1UNSUPPORTED^7 cd loop command in .cfg file; put this line in mapinfo instead:");
- LOG_INFO(" cdtrack ", trackname);
- if (cvar_value_issafe(trackname))
- {
- string newstuff = strcat(clientstuff, "cd loop \"", trackname, "\"\n");
- strcpy(clientstuff, newstuff);
- }
- }
- else if(argv(0) == "fog")
- {
- LOG_INFO("Found ^1UNSUPPORTED^7 fog command in .cfg file; put this line in worldspawn in the .map/.bsp/.ent file instead:");
- LOG_INFO(" \"fog\" \"", s, "\"");
- }
- else if(argv(0) == "set")
- {
- LOG_INFO("Found ^1UNSUPPORTED^7 set command in .cfg file; put this line in mapinfo instead:");
- LOG_INFO(" clientsettemp_for_type all ", argv(1), " ", argv(2));
- }
- else if(argv(0) != "//")
- {
- LOG_INFO("Found ^1UNSUPPORTED^7 set command in .cfg file; put this line in mapinfo instead:");
- LOG_INFO(" clientsettemp_for_type all ", argv(0), " ", argv(1));
- }
- }
- fclose(fd);
- }
- }
-
- WeaponStats_Init();
-
- Nagger_Init();
-
- next_pingtime = time + 5;
-
- // set up information replies for clients and server to use
- maplist_reply = strzone(getmaplist());
- lsmaps_reply = strzone(getlsmaps());
- monsterlist_reply = strzone(getmonsterlist());
- for(int i = 0; i < 10; ++i)
- {
- string s = getrecords(i);
- if (s)
- records_reply[i] = strzone(s);
- }
- ladder_reply = strzone(getladder());
- rankings_reply = strzone(getrankings());
-
- // begin other init
- ClientInit_Spawn();
- RandomSeed_Spawn();
- PingPLReport_Spawn();
-
- CheatInit();
-
- if (!wantrestart) localcmd("\n_sv_hook_gamestart ", GetGametype(), "\n");
-
- // fill sv_curl_serverpackages from .serverpackage files
- if (autocvar_sv_curl_serverpackages_auto)
- {
- string s = "csprogs-" WATERMARK ".txt";
- // remove automatically managed files from the list to prevent duplicates
- for (int i = 0, n = tokenize_console(cvar_string("sv_curl_serverpackages")); i < n; ++i)
- {
- string pkg = argv(i);
- if (startsWith(pkg, "csprogs-")) continue;
- if (endsWith(pkg, "-serverpackage.txt")) continue;
- if (endsWith(pkg, ".serverpackage")) continue; // OLD legacy
- s = cons(s, pkg);
- }
- // add automatically managed files to the list
- #define X(match) MACRO_BEGIN \
- int fd = search_begin(match, true, false); \
- if (fd >= 0) \
- { \
- for (int i = 0, j = search_getsize(fd); i < j; ++i) \
- { \
- s = cons(s, search_getfilename(fd, i)); \
- } \
- search_end(fd); \
- } \
- MACRO_END
- X("*-serverpackage.txt");
- X("*.serverpackage");
- #undef X
- cvar_set("sv_curl_serverpackages", s);
- }
-
- // MOD AUTHORS: change this, and possibly remove a few of the blocks below to ignore certain changes
- modname = "Xonotic";
- // physics/balance/config changes that count as mod
- if(cvar_string("g_mod_physics") != cvar_defstring("g_mod_physics"))
- modname = cvar_string("g_mod_physics");
- if(cvar_string("g_mod_balance") != cvar_defstring("g_mod_balance") && cvar_string("g_mod_balance") != "Testing")
- modname = cvar_string("g_mod_balance");
- if(cvar_string("g_mod_config") != cvar_defstring("g_mod_config"))
- modname = cvar_string("g_mod_config");
- // extra mutators that deserve to count as mod
- MUTATOR_CALLHOOK(SetModname, modname);
- modname = M_ARGV(0, string);
-
- // save it for later
- modname = strzone(modname);
-
- WinningConditionHelper(this); // set worldstatus
-
- world_initialized = 1;
- __spawnfunc_spawn_all();
-}
-
-spawnfunc(light)
-{
- //makestatic (this); // Who the f___ did that?
- delete(this);
-}
-
-string GetGametype()
-{
- return MapInfo_Type_ToString(MapInfo_LoadedGametype);
-}
-
-string GetMapname()
-{
- return mapname;
-}
-
-float Map_Count, Map_Current;
-string Map_Current_Name;
-
-// NOTE: this now expects the map list to be already tokenized and the count in Map_Count
-int GetMaplistPosition()
-{
- string map = GetMapname();
- int idx = autocvar_g_maplist_index;
-
- if(idx >= 0)
- {
- if(idx < Map_Count)
- {
- if(map == argv(idx))
- {
- return idx;
- }
- }
- }
-
- for(int pos = 0; pos < Map_Count; ++pos)
- {
- if(map == argv(pos))
- return pos;
- }
-
- // resume normal maplist rotation if current map is not in g_maplist
- return idx;
-}
-
-bool MapHasRightSize(string map)
-{
- int minplayers = max(0, floor(autocvar_minplayers));
- if (teamplay)
- minplayers = max(0, floor(autocvar_minplayers_per_team) * AvailableTeams());
- if (autocvar_g_maplist_check_waypoints
- && (currentbots || autocvar_bot_number || player_count < minplayers))
- {
- string checkwp_msg = strcat("checkwp ", map);
- if(!fexists(strcat("maps/", map, ".waypoints")))
- {
- LOG_TRACE(checkwp_msg, ": no waypoints");
- return false;
- }
- LOG_TRACE(checkwp_msg, ": has waypoints");
- }
-
- if(autocvar_g_maplist_ignore_sizes)
- return true;
-
- // open map size restriction file
- string opensize_msg = strcat("opensize ", map);
- float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
- int player_limit = ((autocvar_g_maplist_sizes_count_maxplayers) ? GetPlayerLimit() : 0);
- int pcount = ((player_limit > 0) ? min(player_count, player_limit) : player_count); // bind it to the player limit so that forced spectators don't influence the limits
- if(!autocvar_g_maplist_sizes_count_bots)
- pcount -= currentbots;
- if(fh >= 0)
- {
- opensize_msg = strcat(opensize_msg, ": ok, ");
- int mapmin = stoi(fgets(fh));
- int mapmax = stoi(fgets(fh));
- fclose(fh);
- if(pcount < mapmin)
- {
- LOG_TRACE(opensize_msg, "not enough");
- return false;
- }
- if(mapmax && pcount > mapmax)
- {
- LOG_TRACE(opensize_msg, "too many");
- return false;
- }
- LOG_TRACE(opensize_msg, "right size");
- return true;
- }
- LOG_TRACE(opensize_msg, ": not found");
- return true;
-}
-
-string Map_Filename(float position)
-{
- return strcat("maps/", argv(position), ".bsp");
-}
-
-void Map_MarkAsRecent(string m)
-{
- cvar_set("g_maplist_mostrecent", strwords(cons(m, autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
-}
-
-float Map_IsRecent(string m)
-{
- return strhasword(autocvar_g_maplist_mostrecent, m);
-}
-
-float Map_Check(float position, float pass)
-{
- string filename;
- string map_next;
- map_next = argv(position);
- if(pass <= 1)
- {
- if(Map_IsRecent(map_next))
- return 0;
- }
- filename = Map_Filename(position);
- if(MapInfo_CheckMap(map_next))
- {
- if(pass == 2)
- return 1;
- if(MapHasRightSize(map_next))
- return 1;
- return 0;
- }
- else
- LOG_DEBUG( "Couldn't select '", filename, "'..." );
-
- return 0;
-}
-
-void Map_Goto_SetStr(string nextmapname)
-{
- if(getmapname_stored != "")
- strunzone(getmapname_stored);
- if(nextmapname == "")
- getmapname_stored = "";
- else
- getmapname_stored = strzone(nextmapname);
-}
-
-void Map_Goto_SetFloat(float position)
-{
- cvar_set("g_maplist_index", ftos(position));
- Map_Goto_SetStr(argv(position));
-}
-
-void Map_Goto(float reinit)
-{
- MapInfo_LoadMap(getmapname_stored, reinit);
-}
-
-// return codes of map selectors:
-// -1 = temporary failure (that is, try some method that is guaranteed to succeed)
-// -2 = permanent failure
-float MaplistMethod_Iterate() // usual method
-{
- float pass, i;
-
- LOG_TRACE("Trying MaplistMethod_Iterate");
-
- for(pass = 1; pass <= 2; ++pass)
- {
- for(i = 1; i < Map_Count; ++i)
- {
- float mapindex;
- mapindex = (i + Map_Current) % Map_Count;
- if(Map_Check(mapindex, pass))
- return mapindex;
- }
- }
- return -1;
-}
-
-float MaplistMethod_Repeat() // fallback method
-{
- LOG_TRACE("Trying MaplistMethod_Repeat");
-
- if(Map_Check(Map_Current, 2))
- return Map_Current;
- return -2;
-}
-
-float MaplistMethod_Random() // random map selection
-{
- float i, imax;
-
- LOG_TRACE("Trying MaplistMethod_Random");
-
- imax = 42;
-
- for(i = 0; i <= imax; ++i)
- {
- float mapindex;
- mapindex = (Map_Current + floor(random() * (Map_Count - 1) + 1)) % Map_Count; // any OTHER map
- if(Map_Check(mapindex, 1))
- return mapindex;
- }
- return -1;
-}
-
-float MaplistMethod_Shuffle(float exponent) // more clever shuffling
-// the exponent sets a bias on the map selection:
-// the higher the exponent, the less likely "shortly repeated" same maps are
-{
- float i, j, imax, insertpos;
-
- LOG_TRACE("Trying MaplistMethod_Shuffle");
-
- imax = 42;
-
- for(i = 0; i <= imax; ++i)
- {
- string newlist;
-
- // now reinsert this at another position
- insertpos = (random() ** (1 / exponent)); // ]0, 1]
- insertpos = insertpos * (Map_Count - 1); // ]0, Map_Count - 1]
- insertpos = ceil(insertpos) + 1; // {2, 3, 4, ..., Map_Count}
- LOG_TRACE("SHUFFLE: insert pos = ", ftos(insertpos));
-
- // insert the current map there
- newlist = "";
- for(j = 1; j < insertpos; ++j) // i == 1: no loop, will be inserted as first; however, i == 1 has been excluded above
- newlist = strcat(newlist, " ", argv(j));
- newlist = strcat(newlist, " ", argv(0)); // now insert the just selected map
- for(j = insertpos; j < Map_Count; ++j) // i == Map_Count: no loop, has just been inserted as last
- newlist = strcat(newlist, " ", argv(j));
- newlist = substring(newlist, 1, strlen(newlist) - 1);
- cvar_set("g_maplist", newlist);
- Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
-
- // NOTE: the selected map has just been inserted at (insertpos-1)th position
- Map_Current = insertpos - 1; // this is not really valid, but this way the fallback has a chance of working
- if(Map_Check(Map_Current, 1))
- return Map_Current;
- }
- return -1;
-}
-
-void Maplist_Init()
-{
- float i = Map_Count = 0;
- if(autocvar_g_maplist != "")
- {
- Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
- for (i = 0; i < Map_Count; ++i)
- {
- if (Map_Check(i, 2))
- break;
- }
- }
-
- if (i == Map_Count)
- {
- bprint( "Maplist contains no usable maps! Resetting it to default map list.\n" );
- cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags() | MAPINFO_FLAG_NOAUTOMAPLIST));
- if(autocvar_g_maplist_shuffle)
- ShuffleMaplist();
- if(!server_is_dedicated)
- localcmd("\nmenu_cmd sync\n");
- Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
- }
- if(Map_Count == 0)
- error("empty maplist, cannot select a new map");
- Map_Current = bound(0, GetMaplistPosition(), Map_Count - 1);
-
- strcpy(Map_Current_Name, argv(Map_Current)); // will be automatically freed on exit thanks to DP
- // this may or may not be correct, but who cares, in the worst case a map
- // isn't chosen in the first pass that should have been
-}
-
-string GetNextMap()
-{
- Maplist_Init();
- float nextMap = -1;
-
- if(nextMap == -1)
- if(autocvar_g_maplist_shuffle > 0)
- nextMap = MaplistMethod_Shuffle(autocvar_g_maplist_shuffle + 1);
-
- if(nextMap == -1)
- if(autocvar_g_maplist_selectrandom)
- nextMap = MaplistMethod_Random();
-
- if(nextMap == -1)
- nextMap = MaplistMethod_Iterate();
-
- if(nextMap == -1)
- nextMap = MaplistMethod_Repeat();
-
- if(nextMap >= 0)
- {
- Map_Goto_SetFloat(nextMap);
- return getmapname_stored;
- }
-
- return "";
-}
-
-float DoNextMapOverride(float reinit)
-{
- if(autocvar_g_campaign)
- {
- CampaignPostIntermission();
- alreadychangedlevel = true;
- return true;
- }
- if(autocvar_quit_when_empty)
- {
- if(player_count <= currentbots)
- {
- localcmd("quit\n");
- alreadychangedlevel = true;
- return true;
- }
- }
- if(autocvar_quit_and_redirect != "")
- {
- redirection_target = strzone(autocvar_quit_and_redirect);
- alreadychangedlevel = true;
- return true;
- }
- if (!reinit && autocvar_samelevel) // if samelevel is set, stay on same level
- {
- localcmd("restart\n");
- alreadychangedlevel = true;
- return true;
- }
- if(autocvar_nextmap != "")
- {
- string m;
- m = GameTypeVote_MapInfo_FixName(autocvar_nextmap);
- cvar_set("nextmap",m);
-
- if(!m || gametypevote)
- return false;
- if(autocvar_sv_vote_gametype)
- {
- Map_Goto_SetStr(m);
- return false;
- }
-
- if(MapInfo_CheckMap(m))
- {
- Map_Goto_SetStr(m);
- Map_Goto(reinit);
- alreadychangedlevel = true;
- return true;
- }
- }
- if(!reinit && autocvar_lastlevel)
- {
- cvar_settemp_restore();
- localcmd("set lastlevel 0\ntogglemenu 1\n");
- alreadychangedlevel = true;
- return true;
- }
- return false;
-}
-
-void GotoNextMap(float reinit)
-{
- //string nextmap;
- //float n, nummaps;
- //string s;
- if (alreadychangedlevel)
- return;
- alreadychangedlevel = true;
-
- string nextMap = GetNextMap();
- if(nextMap == "")
- error("Everything is broken - cannot find a next map. Please report this to the developers.");
- Map_Goto(reinit);
-}
-
-
-/*
-============
-IntermissionThink
-
-When the player presses attack or jump, change to the next level
-============
-*/
-.float autoscreenshot;
-void IntermissionThink(entity this)
-{
- FixIntermissionClient(this);
-
- float server_screenshot = (autocvar_sv_autoscreenshot && CS(this).cvar_cl_autoscreenshot);
- float client_screenshot = (CS(this).cvar_cl_autoscreenshot == 2);
-
- if( (server_screenshot || client_screenshot)
- && ((this.autoscreenshot > 0) && (time > this.autoscreenshot)) )
- {
- this.autoscreenshot = -1;
- if(IS_REAL_CLIENT(this)) { stuffcmd(this, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"\n", GetMapname(), strftime(false, "%s"))); }
- return;
- }
-
- if (time < intermission_exittime)
- return;
-
- if(!mapvote_initialized)
- if (time < intermission_exittime + 10 && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_ATCK2(this) || PHYS_INPUT_BUTTON_HOOK(this) || PHYS_INPUT_BUTTON_USE(this)))
- return;
-
- MapVote_Start();
-}
-
-/*
-===============================================================================
-
-RULES
-
-===============================================================================
-*/
-
-void DumpStats(float final)
-{
- float file;
- string s;
- float to_console;
- float to_eventlog;
- float to_file;
- float i;
-
- to_console = autocvar_sv_logscores_console;
- to_eventlog = autocvar_sv_eventlog;
- to_file = autocvar_sv_logscores_file;
-
- if(!final)
- {
- to_console = true; // always print printstats replies
- to_eventlog = false; // but never print them to the event log
- }
-
- if(to_eventlog)
- if(autocvar_sv_eventlog_console)
- to_console = false; // otherwise we get the output twice
-
- if(final)
- s = ":scores:";
- else
- s = ":status:";
- s = strcat(s, GetGametype(), "_", GetMapname(), ":", ftos(rint(time)));
-
- if(to_console)
- LOG_INFO(s);
- if(to_eventlog)
- GameLogEcho(s);
-
- file = -1;
- if(to_file)
- {
- file = fopen(autocvar_sv_logscores_filename, FILE_APPEND);
- if(file == -1)
- to_file = false;
- else
- fputs(file, strcat(s, "\n"));
- }
-
- s = strcat(":labels:player:", GetPlayerScoreString(NULL, 0));
- if(to_console)
- LOG_INFO(s);
- if(to_eventlog)
- GameLogEcho(s);
- if(to_file)
- fputs(file, strcat(s, "\n"));
-
- FOREACH_CLIENT(IS_REAL_CLIENT(it) || (IS_BOT_CLIENT(it) && autocvar_sv_logscores_bots), {
- s = strcat(":player:see-labels:", GetPlayerScoreString(it, 0), ":");
- s = strcat(s, ftos(rint(time - CS(it).jointime)), ":");
- if(IS_PLAYER(it) || MUTATOR_CALLHOOK(GetPlayerStatus, it))
- s = strcat(s, ftos(it.team), ":");
- else
- s = strcat(s, "spectator:");
-
- if(to_console)
- LOG_INFO(s, playername(it, false));
- if(to_eventlog)
- GameLogEcho(strcat(s, ftos(it.playerid), ":", playername(it, false)));
- if(to_file)
- fputs(file, strcat(s, playername(it, false), "\n"));
- });
-
- if(teamplay)
- {
- s = strcat(":labels:teamscores:", GetTeamScoreString(0, 0));
- if(to_console)
- LOG_INFO(s);
- if(to_eventlog)
- GameLogEcho(s);
- if(to_file)
- fputs(file, strcat(s, "\n"));
-
- for(i = 1; i < 16; ++i)
- {
- s = strcat(":teamscores:see-labels:", GetTeamScoreString(i, 0));
- s = strcat(s, ":", ftos(i));
- if(to_console)
- LOG_INFO(s);
- if(to_eventlog)
- GameLogEcho(s);
- if(to_file)
- fputs(file, strcat(s, "\n"));
- }
- }
-
- if(to_console)
- LOG_INFO(":end");
- if(to_eventlog)
- GameLogEcho(":end");
- if(to_file)
- {
- fputs(file, ":end\n");
- fclose(file);
- }
-}
-
-void FixIntermissionClient(entity e)
-{
- if(!e.autoscreenshot) // initial call
- {
- e.autoscreenshot = time + 0.8; // used for autoscreenshot
- SetResourceExplicit(e, RES_HEALTH, -2342);
- // first intermission phase; voting phase has positive health (used to decide whether to send SVC_FINALE or not)
- for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(e.(weaponentity))
- {
- e.(weaponentity).effects = EF_NODRAW;
- if (e.(weaponentity).weaponchild)
- e.(weaponentity).weaponchild.effects = EF_NODRAW;
- }
- }
- if(IS_REAL_CLIENT(e))
- {
- stuffcmd(e, "\nscr_printspeed 1000000\n");
- RandomSelection_Init();
- FOREACH_WORD(autocvar_sv_intermission_cdtrack, true, {
- RandomSelection_AddString(it, 1, 1);
- });
- if (RandomSelection_chosen_string != "")
- {
- stuffcmd(e, sprintf("\ncd loop %s\n", RandomSelection_chosen_string));
- }
- msg_entity = e;
- WriteByte(MSG_ONE, SVC_INTERMISSION);
- }
- }
-}
-
-/*
-go to the next level for deathmatch
-only called if a time or frag limit has expired
-*/
-void NextLevel()
-{
- game_stopped = true;
- intermission_running = 1; // game over
-
- // enforce a wait time before allowing changelevel
- if(player_count > 0)
- intermission_exittime = time + autocvar_sv_mapchange_delay;
- else
- intermission_exittime = -1;
-
- /*
- WriteByte (MSG_ALL, SVC_CDTRACK);
- WriteByte (MSG_ALL, 3);
- WriteByte (MSG_ALL, 3);
- // done in FixIntermission
- */
-
- //pos = FindIntermission ();
-
- VoteReset();
-
- DumpStats(true);
-
- // send statistics
- PlayerStats_GameReport(true);
- WeaponStats_Shutdown();
-
- Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_Null); // kill all centerprints now
-
- if(autocvar_sv_eventlog)
- GameLogEcho(":gameover");
-
- GameLogClose();
-
- FOREACH_CLIENT(IS_PLAYER(it), {
- FixIntermissionClient(it);
- if(it.winning)
- bprint(playername(it, false), " ^7wins.\n");
- });
-
- target_music_kill();
-
- if(autocvar_g_campaign)
- CampaignPreIntermission();
-
- MUTATOR_CALLHOOK(MatchEnd);
-
- localcmd("\nsv_hook_gameend\n");
-}
-
-
-float InitiateSuddenDeath()
-{
- // Check first whether normal overtimes could be added before initiating suddendeath mode
- // - for this timelimit_overtime needs to be >0 of course
- // - also check the winning condition calculated in the previous frame and only add normal overtime
- // again, if at the point at which timelimit would be extended again, still no winner was found
- if (!autocvar_g_campaign && checkrules_overtimesadded >= 0
- && (checkrules_overtimesadded < autocvar_timelimit_overtimes || autocvar_timelimit_overtimes < 0)
- && autocvar_timelimit_overtime && !(g_race && !g_race_qualifying))
- {
- return 1; // need to call InitiateOvertime later
- }
- else
- {
- if(!checkrules_suddendeathend)
- {
- if(autocvar_g_campaign)
- checkrules_suddendeathend = time; // no suddendeath in campaign
- else
- checkrules_suddendeathend = time + 60 * autocvar_timelimit_suddendeath;
- if(g_race && !g_race_qualifying)
- race_StartCompleting();
- }
- return 0;
- }
-}
-
-void InitiateOvertime() // ONLY call this if InitiateSuddenDeath returned true
-{
- ++checkrules_overtimesadded;
- //add one more overtime by simply extending the timelimit
- cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime));
- Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60);
-}
-
-float GetWinningCode(float fraglimitreached, float equality)
-{
- if(autocvar_g_campaign == 1)
- {
- if(fraglimitreached)
- return WINNING_YES;
- else
- return WINNING_NO;
- }
- else
- {
- if(equality)
- {
- if(fraglimitreached)
- return WINNING_STARTSUDDENDEATHOVERTIME;
- else
- return WINNING_NEVER;
- }
- else
- {
- if(fraglimitreached)
- return WINNING_YES;
- else
- return WINNING_NO;
- }
- }
-}
-
-// set the .winning flag for exactly those players with a given field value
-void SetWinners(.float field, float value)
-{
- FOREACH_CLIENT(IS_PLAYER(it), { it.winning = (it.(field) == value); });
-}
-
-// set the .winning flag for those players with a given field value
-void AddWinners(.float field, float value)
-{
- FOREACH_CLIENT(IS_PLAYER(it), {
- if(it.(field) == value)
- it.winning = 1;
- });
-}
-
-// clear the .winning flags
-void ClearWinners()
-{
- FOREACH_CLIENT(IS_PLAYER(it), { it.winning = 0; });
-}
-
-void ShuffleMaplist()
-{
- cvar_set("g_maplist", shufflewords(autocvar_g_maplist));
-}
-
-int fragsleft_last;
-float WinningCondition_Scores(float limit, float leadlimit)
-{
- // TODO make everything use THIS winning condition (except LMS)
- WinningConditionHelper(NULL);
-
- if(teamplay)
- {
- for (int i = 1; i < 5; ++i)
- {
- Team_SetTeamScore(Team_GetTeamFromIndex(i),
- TeamScore_GetCompareValue(Team_IndexToTeam(i)));
- }
- }
-
- ClearWinners();
- if(WinningConditionHelper_winner)
- WinningConditionHelper_winner.winning = 1;
- if(WinningConditionHelper_winnerteam >= 0)
- SetWinners(team, WinningConditionHelper_winnerteam);
-
- if(WinningConditionHelper_lowerisbetter)
- {
- WinningConditionHelper_topscore = -WinningConditionHelper_topscore;
- WinningConditionHelper_secondscore = -WinningConditionHelper_secondscore;
- limit = -limit;
- }
-
- if(WinningConditionHelper_zeroisworst)
- leadlimit = 0; // not supported in this mode
-
- if(MUTATOR_CALLHOOK(Scores_CountFragsRemaining))
- {
- float fragsleft;
- if (checkrules_suddendeathend && time >= checkrules_suddendeathend)
- {
- fragsleft = 1;
- }
- else
- {
- fragsleft = FLOAT_MAX;
- float leadingfragsleft = FLOAT_MAX;
- if (limit)
- fragsleft = limit - WinningConditionHelper_topscore;
- if (leadlimit)
- leadingfragsleft = WinningConditionHelper_secondscore + leadlimit - WinningConditionHelper_topscore;
-
- if (limit && leadlimit && autocvar_leadlimit_and_fraglimit)
- fragsleft = max(fragsleft, leadingfragsleft);
- else
- fragsleft = min(fragsleft, leadingfragsleft);
- }
-
- if (fragsleft_last != fragsleft) // do not announce same remaining frags multiple times
- {
- if (fragsleft == 1)
- Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_1);
- else if (fragsleft == 2)
- Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_2);
- else if (fragsleft == 3)
- Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_3);
-
- fragsleft_last = fragsleft;
- }
- }
-
- bool fraglimit_reached = (limit && WinningConditionHelper_topscore >= limit);
- bool leadlimit_reached = (leadlimit && WinningConditionHelper_topscore - WinningConditionHelper_secondscore >= leadlimit);
-
- bool limit_reached;
- // only respect leadlimit_and_fraglimit when both limits are set or the game will never end
- if (limit && leadlimit && autocvar_leadlimit_and_fraglimit)
- limit_reached = (fraglimit_reached && leadlimit_reached);
- else
- limit_reached = (fraglimit_reached || leadlimit_reached);
-
- return GetWinningCode(
- WinningConditionHelper_topscore && limit_reached,
- WinningConditionHelper_equality
- );
-}
-
-float WinningCondition_RanOutOfSpawns()
-{
- if(have_team_spawns <= 0)
- return WINNING_NO;
-
- if(!autocvar_g_spawn_useallspawns)
- return WINNING_NO;
-
- if(!some_spawn_has_been_used)
- return WINNING_NO;
-
- 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))
- {
- Team_SetTeamScore(Team_GetTeam(it.team), 1);
- }
- });
-
- IL_EACH(g_spawnpoints, true,
- {
- if (Team_IsValidTeam(it.team))
- {
- 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;
- return WINNING_YES;
- }
- else if(team1_score + team2_score + team3_score + team4_score == 1)
- {
- float t, i;
- if(team1_score)
- t = 1;
- else if(team2_score)
- t = 2;
- else if(team3_score)
- t = 3;
- else // if(team4_score)
- t = 4;
- entity balance = TeamBalance_CheckAllowedTeams(NULL);
- for(i = 0; i < MAX_TEAMSCORE; ++i)
- {
- 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);
- return WINNING_YES;
- }
- else
- return WINNING_NO;
-}
-
-/*
-============
-CheckRules_World
-
-Exit deathmatch games upon conditions
-============
-*/
-void CheckRules_World()
-{
- VoteThink();
- MapVote_Think();
-
- SetDefaultAlpha();
-
- if (intermission_running) // someone else quit the game already
- {
- if(player_count == 0) // Nobody there? Then let's go to the next map
- MapVote_Start();
- // this will actually check the player count in the next frame
- // again, but this shouldn't hurt
- return;
- }
-
- float timelimit = autocvar_timelimit * 60;
- float fraglimit = autocvar_fraglimit;
- float leadlimit = autocvar_leadlimit;
- if (leadlimit < 0) leadlimit = 0;
-
- if(warmup_stage || time <= game_starttime) // NOTE: this is <= to prevent problems in the very tic where the game starts
- {
- if(timelimit > 0)
- timelimit = 0; // timelimit is not made for warmup
- if(fraglimit > 0)
- fraglimit = 0; // no fraglimit for now
- leadlimit = 0; // no leadlimit for now
- }
-
- if(timelimit > 0)
- {
- timelimit += game_starttime;
- }
- else if (timelimit < 0)
- {
- // endmatch
- NextLevel();
- return;
- }
-
- float wantovertime;
- wantovertime = 0;
-
- if(checkrules_suddendeathend)
- {
- if(!checkrules_suddendeathwarning)
- {
- checkrules_suddendeathwarning = true;
- if(g_race && !g_race_qualifying)
- Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_RACE_FINISHLAP);
- else
- Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_FRAG);
- }
- }
- else
- {
- if (timelimit && time >= timelimit)
- {
- if(g_race && (g_race_qualifying == 2) && timelimit > 0)
- {
- float totalplayers;
- float playerswithlaps;
- float readyplayers;
- totalplayers = playerswithlaps = readyplayers = 0;
- FOREACH_CLIENT(IS_PLAYER(it), {
- ++totalplayers;
- if(GameRules_scoring_add(it, RACE_FASTEST, 0))
- ++playerswithlaps;
- if(it.ready)
- ++readyplayers;
- });
-
- // at least 2 of the players have completed a lap: start the RACE
- // otherwise, the players should end the qualifying on their own
- if(readyplayers || playerswithlaps >= 2)
- {
- checkrules_suddendeathend = 0;
- ReadyRestart(); // go to race
- return;
- }
- else
- wantovertime |= InitiateSuddenDeath();
- }
- else
- wantovertime |= InitiateSuddenDeath();
- }
- }
-
- if (checkrules_suddendeathend && time >= checkrules_suddendeathend)
- {
- NextLevel();
- return;
- }
-
- int checkrules_status = WinningCondition_RanOutOfSpawns();
- if(checkrules_status == WINNING_YES)
- bprint("Hey! Someone ran out of spawns!\n");
- else if(MUTATOR_CALLHOOK(CheckRules_World, checkrules_status, timelimit, fraglimit))
- checkrules_status = M_ARGV(0, float);
- else
- checkrules_status = WinningCondition_Scores(fraglimit, leadlimit);
-
- if(checkrules_status == WINNING_STARTSUDDENDEATHOVERTIME)
- {
- checkrules_status = WINNING_NEVER;
- checkrules_overtimesadded = -1;
- wantovertime |= InitiateSuddenDeath();
- }
-
- if(checkrules_status == WINNING_NEVER)
- // equality cases! Nobody wins if the overtime ends in a draw.
- ClearWinners();
-
- if(wantovertime)
- {
- if(checkrules_status == WINNING_NEVER)
- InitiateOvertime();
- else
- checkrules_status = WINNING_YES;
- }
-
- if(checkrules_suddendeathend)
- if(checkrules_status != WINNING_NEVER || time >= checkrules_suddendeathend)
- checkrules_status = WINNING_YES;
-
- if(checkrules_status == WINNING_YES)
- {
- //print("WINNING\n");
- NextLevel();
- }
-}
-
-string GotoMap(string m)
-{
- m = GameTypeVote_MapInfo_FixName(m);
- if (!m)
- return "The map you suggested is not available on this server.";
- if (!autocvar_sv_vote_gametype)
- if(!MapInfo_CheckMap(m))
- return "The map you suggested does not support the current game mode.";
- cvar_set("nextmap", m);
- cvar_set("timelimit", "-1");
- if(mapvote_initialized || alreadychangedlevel)
- {
- if(DoNextMapOverride(0))
- return "Map switch initiated.";
- else
- return "Hm... no. For some reason I like THIS map more.";
- }
- else
- return "Map switch will happen after scoreboard.";
-}
-
-bool autocvar_sv_gameplayfix_multiplethinksperframe = true;
-void RunThink(entity this)
-{
- // don't let things stay in the past.
- // it is possible to start that way by a trigger with a local time.
- if(this.nextthink <= 0 || this.nextthink > time + frametime)
- return;
-
- float oldtime = time; // do we need to save this?
-
- for (int iterations = 0; iterations < 128 && !wasfreed(this); iterations++)
- {
- time = max(oldtime, this.nextthink);
- this.nextthink = 0;
-
- if(getthink(this))
- getthink(this)(this);
- // mods often set nextthink to time to cause a think every frame,
- // we don't want to loop in that case, so exit if the new nextthink is
- // <= the time the qc was told, also exit if it is past the end of the
- // frame
- if(this.nextthink <= time || this.nextthink > oldtime + frametime || !autocvar_sv_gameplayfix_multiplethinksperframe)
- break;
- }
-
- time = oldtime;
-}
-
-bool autocvar_sv_freezenonclients;
-bool autocvar_sv_gameplayfix_delayprojectiles = false;
-void Physics_Frame()
-{
- if(autocvar_sv_freezenonclients)
- return;
-
- IL_EACH(g_moveables, true,
- {
- if(IS_CLIENT(it) || it.classname == "" || it.move_movetype == MOVETYPE_PHYSICS)
- continue;
-
- //set_movetype(it, it.move_movetype);
- // inline the set_movetype function, since this is called a lot
- it.movetype = (it.move_qcphysics) ? MOVETYPE_QCENTITY : it.move_movetype;
-
- if(it.move_qcphysics && it.move_movetype != MOVETYPE_NONE)
- Movetype_Physics_NoMatchTicrate(it, PHYS_INPUT_TIMELENGTH, false);
-
- if(it.movetype >= MOVETYPE_USER_FIRST && it.movetype <= MOVETYPE_USER_LAST) // these cases have no think handling
- {
- if(it.move_movetype == MOVETYPE_PUSH || it.move_movetype == MOVETYPE_FAKEPUSH)
- continue; // these movetypes have no regular think function
- // handle thinking here
- if (getthink(it) && it.nextthink > 0 && it.nextthink <= time + frametime)
- RunThink(it);
- }
- });
-
- if(autocvar_sv_gameplayfix_delayprojectiles >= 0)
- return;
-
- IL_EACH(g_moveables, it.move_qcphysics,
- {
- if(IS_CLIENT(it) || it.classname == "" || it.move_movetype == MOVETYPE_NONE)
- continue;
- Movetype_Physics_NoMatchTicrate(it, PHYS_INPUT_TIMELENGTH, false);
- });
-}
-
-void systems_update();
-void EndFrame()
-{
- anticheat_endframe();
-
- Physics_Frame();
-
- FOREACH_CLIENT(IS_REAL_CLIENT(it), {
- entity e = IS_SPEC(it) ? it.enemy : it;
- if (e.typehitsound) {
- STAT(TYPEHIT_TIME, it) = time;
- } else if (e.killsound) {
- STAT(KILL_TIME, it) = time;
- } else if (e.damage_dealt) {
- STAT(HIT_TIME, it) = time;
- STAT(DAMAGE_DEALT_TOTAL, it) += ceil(e.damage_dealt);
- }
- });
- // add 1 frametime because after this, engine SV_Physics
- // increases time by a frametime and then networks the frame
- // add another frametime because client shows everything with
- // 1 frame of lag (cl_nolerp 0). The last +1 however should not be
- // needed!
- float altime = time + frametime * (1 + autocvar_g_antilag_nudge);
- FOREACH_CLIENT(true, {
- it.typehitsound = false;
- it.damage_dealt = 0;
- it.killsound = false;
- antilag_record(it, CS(it), altime);
- });
- IL_EACH(g_monsters, true,
- {
- antilag_record(it, it, altime);
- });
- IL_EACH(g_projectiles, it.classname == "nade",
- {
- antilag_record(it, it, altime);
- });
- systems_update();
- IL_ENDFRAME();
-}
-
-
-/*
- * RedirectionThink:
- * returns true if redirecting
- */
-float redirection_timeout;
-float redirection_nextthink;
-float RedirectionThink()
-{
- float clients_found;
-
- if(redirection_target == "")
- return false;
-
- if(!redirection_timeout)
- {
- cvar_set("sv_public", "-2");
- redirection_timeout = time + 0.6; // this will only try twice... should be able to keep more clients
- if(redirection_target == "self")
- bprint("^3SERVER NOTICE:^7 restarting the server\n");
- else
- bprint("^3SERVER NOTICE:^7 redirecting everyone to ", redirection_target, "\n");
- }
-
- if(time < redirection_nextthink)
- return true;
-
- redirection_nextthink = time + 1;
-
- clients_found = 0;
- FOREACH_CLIENT(IS_REAL_CLIENT(it), {
- // TODO add timer
- LOG_INFO("Redirecting: sending connect command to ", it.netname);
- if(redirection_target == "self")
- stuffcmd(it, "\ndisconnect; defer ", ftos(autocvar_quit_and_redirect_timer), " reconnect\n");
- else
- stuffcmd(it, strcat("\ndisconnect; defer ", ftos(autocvar_quit_and_redirect_timer), " \"connect ", redirection_target, "\"\n"));
- ++clients_found;
- });
-
- LOG_INFO("Redirecting: ", ftos(clients_found), " clients left.");
-
- if(time > redirection_timeout || clients_found == 0)
- localcmd("\nwait; wait; wait; quit\n");
-
- return true;
-}
-
-void RestoreGame()
-{
- // Loaded from a save game
- // some things then break, so let's work around them...
-
- // Progs DB (capture records)
- ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
-
- // Mapinfo
- MapInfo_Shutdown();
- MapInfo_Enumerate();
- MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1);
- WeaponStats_Init();
-
- TargetMusic_RestoreGame();
-}
-
-void Shutdown()
-{
- game_stopped = 2;
-
- if(world_initialized > 0)
- {
- world_initialized = 0;
-
- // if a timeout is active, reset the slowmo value to normal
- if(timeout_status == TIMEOUT_ACTIVE)
- cvar_set("slowmo", ftos(orig_slowmo));
-
- LOG_TRACE("Saving persistent data...");
- Ban_SaveBans();
-
- // playerstats with unfinished match
- PlayerStats_GameReport(false);
-
- if(!cheatcount_total)
- {
- if(autocvar_sv_db_saveasdump)
- db_dump(ServerProgsDB, strcat("server.db", autocvar_sessionid));
- else
- db_save(ServerProgsDB, strcat("server.db", autocvar_sessionid));
- }
- if(autocvar_developer > 0)
- {
- if(autocvar_sv_db_saveasdump)
- db_dump(TemporaryDB, "server-temp.db");
- else
- db_save(TemporaryDB, "server-temp.db");
- }
- CheatShutdown(); // must be after cheatcount check
- db_close(ServerProgsDB);
- db_close(TemporaryDB);
- LOG_TRACE("Saving persistent data... done!");
- // tell the bot system the game is ending now
- bot_endgame();
-
- WeaponStats_Shutdown();
- MapInfo_Shutdown();
- }
- else if(world_initialized == 0)
- {
- LOG_INFO("NOTE: crashed before even initializing the world, not saving persistent data");
- }
- else
- {
- __init_dedicated_server_shutdown();
- }
-}
+++ /dev/null
-#pragma once
-
-float checkrules_equality;
-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
-const int WINNING_STARTSUDDENDEATHOVERTIME = 3; // no winner, enter suddendeath overtime NOW
-
-float WinningCondition_Scores(float limit, float leadlimit);
-void SetWinners(.float field, float value);
-void IntermissionThink(entity this);
-void GotoNextMap(float reinit);
-void ReadyRestart();
-
-string GetGametype();
-
-void DumpStats(float final);
-float Map_IsRecent(string m);
-string GetNextMap();
-void ShuffleMaplist();
-void Map_Goto_SetStr(string nextmapname);
-void Map_Goto(float reinit);
-void Map_MarkAsRecent(string m);
-float DoNextMapOverride(float reinit);
-void CheckRules_World();
-float RedirectionThink();
-
-// quake 3 music compatibility
-.string music;
-.string noise;
--- /dev/null
+#include "hook.qh"
+
+#include <server/bot/api.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/damage.qh>
+#include <server/miscfunctions.qh>
+#include <common/effects/all.qh>
+#include "weapons/common.qh"
+#include "weapons/csqcprojectile.qh"
+#include "weapons/weaponsystem.qh"
+#include "weapons/selection.qh"
+#include "weapons/tracing.qh"
+#include "player.qh"
+#include "command/common.qh"
+#include "command/vote.qh"
+#include "round_handler.qh"
+#include "../common/state.qh"
+#include "../common/physics/player.qh"
+#include "../common/vehicles/all.qh"
+#include "../common/constants.qh"
+#include "../common/util.qh"
+#include <common/net_linked.qh>
+#include <common/weapons/_all.qh>
+#include "../lib/warpzone/common.qh"
+#include "../lib/warpzone/server.qh"
+
+/*============================================
+
+ Wazat's Xonotic Grappling Hook
+
+ Contact: Wazat1@gmail.com
+
+
+Installation instructions:
+--------------------------
+
+1. Place hook.c in your gamec source directory with the other source files.
+
+2. Add this line to the bottom of progs.src:
+
+gamec/hook.c
+
+3. Open defs.h and add these lines to the very bottom:
+
+// Wazat's grappling hook
+.entity hook;
+void GrapplingHookFrame();
+void RemoveGrapplingHook(entity pl);
+void SetGrappleHookBindings();
+// hook impulses
+const float GRAPHOOK_FIRE = 20;
+const float GRAPHOOK_RELEASE = 21;
+// (note: you can change the hook impulse #'s to whatever you please)
+
+4. Open client.c and add this to the top of PutClientInServer():
+
+ RemoveGrapplingHook(this); // Wazat's Grappling Hook
+
+5. Find ClientConnect() (in client.c) and add these lines to the bottom:
+
+ // Wazat's grappling hook
+ SetGrappleHookBindings();
+
+6. Still in client.c, find PlayerPreThink and add this line just above the call to W_WeaponFrame:
+
+ GrapplingHookFrame();
+
+7. Build and test the mod. You'll want to bind a key to "+hook" like this:
+bind ctrl "+hook"
+
+And you should be done!
+
+
+============================================*/
+
+void RemoveGrapplingHooks(entity pl)
+{
+ if(pl.move_movetype == MOVETYPE_FLY)
+ set_movetype(pl, MOVETYPE_WALK);
+
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(!pl.(weaponentity))
+ continue; // continue incase other slots exist?
+ if(pl.(weaponentity).hook)
+ delete(pl.(weaponentity).hook);
+ pl.(weaponentity).hook = NULL;
+ }
+
+ //pl.disableclientprediction = false;
+}
+
+void RemoveHook(entity this)
+{
+ entity player = this.realowner;
+ .entity weaponentity = this.weaponentity_fld;
+
+ if(player.(weaponentity).hook == this)
+ player.(weaponentity).hook = NULL;
+
+ if(player.move_movetype == MOVETYPE_FLY)
+ set_movetype(player, MOVETYPE_WALK);
+ delete(this);
+}
+
+void GrapplingHookReset(entity this)
+{
+ RemoveHook(this);
+}
+
+void GrapplingHook_Stop(entity this)
+{
+ Send_Effect(EFFECT_HOOK_IMPACT, this.origin, '0 0 0', 1);
+ sound (this, CH_SHOTS, SND_HOOK_IMPACT, VOL_BASE, ATTEN_NORM);
+
+ this.state = 1;
+ setthink(this, GrapplingHookThink);
+ this.nextthink = time;
+ settouch(this, func_null);
+ this.velocity = '0 0 0';
+ set_movetype(this, MOVETYPE_NONE);
+ this.hook_length = -1;
+}
+
+.vector hook_start, hook_end;
+bool GrapplingHookSend(entity this, entity to, int sf)
+{
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_HOOK);
+ sf = sf & 0x7F;
+ if(sound_allowed(MSG_BROADCAST, this.realowner))
+ sf |= 0x80;
+ WriteByte(MSG_ENTITY, sf);
+ if(sf & 1)
+ {
+ WriteByte(MSG_ENTITY, etof(this.realowner));
+ WriteByte(MSG_ENTITY, weaponslot(this.weaponentity_fld));
+ }
+ if(sf & 2)
+ {
+ WriteVector(MSG_ENTITY, this.hook_start);
+ }
+ if(sf & 4)
+ {
+ WriteVector(MSG_ENTITY, this.hook_end);
+ }
+ return true;
+}
+
+int autocvar_g_grappling_hook_tarzan;
+
+void GrapplingHookThink(entity this)
+{
+ float spd, dist, minlength, pullspeed, ropestretch, ropeairfriction, rubberforce, newlength, rubberforce_overstretch;
+ vector dir, org, end, v0, dv, v, myorg, vs;
+ .entity weaponentity = this.weaponentity_fld;
+ if(this.realowner.(weaponentity).hook != this) // how did that happen?
+ {
+ error("Owner lost the hook!\n");
+ return;
+ }
+ if(LostMovetypeFollow(this) || game_stopped || (round_handler_IsActive() && !round_handler_IsRoundStarted()) || ((this.aiment.flags & FL_PROJECTILE) && this.aiment.classname != "nade"))
+ {
+ RemoveHook(this);
+ return;
+ }
+ if(this.aiment)
+ WarpZone_RefSys_AddIncrementally(this, this.aiment);
+
+ this.nextthink = time;
+
+ int s = W_GunAlign(this.realowner.(weaponentity), STAT(GUNALIGN, this.realowner)) - 1;
+ vs = hook_shotorigin[s];
+
+ makevectors(this.realowner.v_angle);
+ org = this.realowner.origin + this.realowner.view_ofs + v_forward * vs.x + v_right * -vs.y + v_up * vs.z;
+ myorg = WarpZone_RefSys_TransformOrigin(this.realowner, this, org);
+
+ if(this.hook_length < 0)
+ this.hook_length = vlen(myorg - this.origin);
+
+ int tarzan = autocvar_g_grappling_hook_tarzan;
+ entity pull_entity = this.realowner;
+ float velocity_multiplier = 1;
+ MUTATOR_CALLHOOK(GrappleHookThink, this, tarzan, pull_entity, velocity_multiplier);
+ tarzan = M_ARGV(1, int);
+ pull_entity = M_ARGV(2, entity);
+ velocity_multiplier = M_ARGV(3, float);
+
+ if(this.state == 1)
+ {
+ pullspeed = autocvar_g_balance_grapplehook_speed_pull;//2000;
+ // speed the rope is pulled with
+
+ rubberforce = autocvar_g_balance_grapplehook_force_rubber;//2000;
+ // force the rope will use if it is stretched
+
+ rubberforce_overstretch = autocvar_g_balance_grapplehook_force_rubber_overstretch;//1000;
+ // force the rope will use if it is stretched
+
+ minlength = autocvar_g_balance_grapplehook_length_min;//100;
+ // minimal rope length
+ // if the rope goes below this length, it isn't pulled any more
+
+ ropestretch = autocvar_g_balance_grapplehook_stretch;//400;
+ // if the rope is stretched by more than this amount, more rope is
+ // given to you again
+
+ ropeairfriction = autocvar_g_balance_grapplehook_airfriction;//0.2
+ // while hanging on the rope, this friction component will help you a
+ // bit to control the rope
+
+ bool frozen_pulling = (autocvar_g_grappling_hook_tarzan >= 2 && autocvar_g_balance_grapplehook_pull_frozen);
+
+ dir = this.origin - myorg;
+ dist = vlen(dir);
+ dir = normalize(dir);
+
+ if(tarzan)
+ {
+ v = v0 = WarpZone_RefSys_TransformVelocity(pull_entity, this, pull_entity.velocity);
+
+ // first pull the rope...
+ if(this.realowner.(weaponentity).hook_state & HOOK_PULLING)
+ {
+ newlength = this.hook_length;
+ newlength = max(newlength - pullspeed * frametime, minlength);
+
+ if(newlength < dist - ropestretch) // overstretched?
+ {
+ newlength = dist - ropestretch;
+ if(v * dir < 0) // only if not already moving in hook direction
+ v = v + frametime * dir * rubberforce_overstretch;
+ }
+
+ this.hook_length = newlength;
+ }
+
+ if(pull_entity.move_movetype == MOVETYPE_FLY)
+ set_movetype(pull_entity, MOVETYPE_WALK);
+
+ if(this.realowner.(weaponentity).hook_state & HOOK_RELEASING)
+ {
+ newlength = dist;
+ this.hook_length = newlength;
+ }
+ else
+ {
+ // then pull the player
+ spd = bound(0, (dist - this.hook_length) / ropestretch, 1);
+ v = v * (1 - frametime * ropeairfriction);
+ v = v + frametime * dir * spd * rubberforce;
+
+ dv = ((v - v0) * dir) * dir;
+ if(tarzan >= 2)
+ {
+ if(this.aiment.move_movetype == MOVETYPE_WALK || this.aiment.classname == "nade")
+ {
+ entity aim_ent = ((IS_VEHICLE(this.aiment) && this.aiment.owner) ? this.aiment.owner : this.aiment);
+ v = v - dv * 0.5;
+ if((frozen_pulling && STAT(FROZEN, this.aiment)) || !frozen_pulling)
+ {
+ this.aiment.velocity = this.aiment.velocity - dv * 0.5;
+ UNSET_ONGROUND(this.aiment);
+ if(this.aiment.flags & FL_PROJECTILE)
+ UpdateCSQCProjectile(this.aiment);
+ }
+ if(this.aiment.classname == "nade")
+ this.aiment.nextthink = time + autocvar_g_balance_grapplehook_nade_time; // set time after letting go?
+ aim_ent.pusher = this.realowner;
+ aim_ent.pushltime = time + autocvar_g_maxpushtime;
+ aim_ent.istypefrag = PHYS_INPUT_BUTTON_CHAT(aim_ent);
+ }
+ }
+
+ UNSET_ONGROUND(pull_entity);
+ }
+
+ if(!frozen_pulling && !(this.aiment.flags & FL_PROJECTILE))
+ pull_entity.velocity = WarpZone_RefSys_TransformVelocity(this, pull_entity, v * velocity_multiplier);
+
+ if(frozen_pulling && autocvar_g_balance_grapplehook_pull_frozen == 2 && !STAT(FROZEN, this.aiment))
+ {
+ RemoveHook(this);
+ return;
+ }
+ }
+ else
+ {
+ end = this.origin - dir*50;
+ dist = vlen(end - myorg);
+ if(dist < 200)
+ spd = dist * (pullspeed / 200);
+ else
+ spd = pullspeed;
+ if(spd < 50)
+ spd = 0;
+ this.realowner.velocity = dir*spd;
+ set_movetype(this.realowner, MOVETYPE_FLY);
+
+ UNSET_ONGROUND(this.realowner);
+ }
+ }
+
+ makevectors(this.angles.x * '-1 0 0' + this.angles.y * '0 1 0');
+ myorg = WarpZone_RefSys_TransformOrigin(this, this.realowner, this.origin); // + v_forward * (-9);
+
+ if(myorg != this.hook_start)
+ {
+ this.SendFlags |= 2;
+ this.hook_start = myorg;
+ }
+ if(org != this.hook_end)
+ {
+ this.SendFlags |= 4;
+ this.hook_end = org;
+ }
+}
+
+void GrapplingHookTouch(entity this, entity toucher)
+{
+ if(toucher.move_movetype == MOVETYPE_FOLLOW)
+ return;
+ PROJECTILE_TOUCH(this, toucher);
+
+ GrapplingHook_Stop(this);
+
+ if(toucher)
+ //if(toucher.move_movetype != MOVETYPE_NONE)
+ {
+ SetMovetypeFollow(this, toucher);
+ WarpZone_RefSys_BeginAddingIncrementally(this, this.aiment);
+ }
+
+ //this.realowner.disableclientprediction = true;
+}
+
+void GrapplingHook_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
+{
+ if(GetResource(this, RES_HEALTH) <= 0)
+ return;
+
+ if (!W_CheckProjectileDamage(inflictor.realowner, this.realowner, deathtype, -1)) // no exceptions
+ return; // g_balance_projectiledamage says to halt
+
+ TakeResource(this, RES_HEALTH, damage);
+
+ if (GetResource(this, RES_HEALTH) <= 0)
+ {
+ if(attacker != this.realowner)
+ {
+ this.realowner.pusher = attacker;
+ this.realowner.pushltime = time + autocvar_g_maxpushtime;
+ this.realowner.istypefrag = PHYS_INPUT_BUTTON_CHAT(this.realowner);
+ }
+ RemoveHook(this);
+ }
+}
+
+void FireGrapplingHook(entity actor, .entity weaponentity)
+{
+ if(weaponLocked(actor)) return;
+ if(actor.vehicle) return;
+
+ int s = W_GunAlign(actor.(weaponentity), STAT(GUNALIGN, actor)) - 1;
+ vector vs = hook_shotorigin[s];
+ vector oldmovedir = actor.(weaponentity).movedir;
+ actor.(weaponentity).movedir = vs;
+ W_SetupShot_ProjectileSize(actor, weaponentity, '-3 -3 -3', '3 3 3', true, 0, SND_HOOK_FIRE, CH_WEAPON_B, 0, WEP_HOOK.m_id);
+ W_MuzzleFlash(WEP_HOOK, actor, weaponentity, w_shotorg, '0 0 0');
+ actor.(weaponentity).movedir = oldmovedir;
+
+ entity missile = WarpZone_RefSys_SpawnSameRefSys(actor);
+ missile.owner = missile.realowner = actor;
+ actor.(weaponentity).hook = missile;
+ missile.weaponentity_fld = weaponentity;
+ missile.reset = GrapplingHookReset;
+ missile.classname = "grapplinghook";
+ missile.flags = FL_PROJECTILE;
+ IL_PUSH(g_projectiles, missile);
+ IL_PUSH(g_bot_dodge, missile);
+
+ set_movetype(missile, ((autocvar_g_balance_grapplehook_gravity) ? MOVETYPE_TOSS : MOVETYPE_FLY));
+ PROJECTILE_MAKETRIGGER(missile);
+
+ //setmodel (missile, MDL_HOOK); // precision set below
+ setsize (missile, '-3 -3 -3', '3 3 3');
+ setorigin(missile, w_shotorg);
+
+ missile.state = 0; // not latched onto anything
+
+ W_SetupProjVelocity_Explicit(missile, w_shotdir, v_up, autocvar_g_balance_grapplehook_speed_fly, 0, 0, 0, false);
+
+ missile.angles = vectoangles (missile.velocity);
+ //missile.glow_color = 250; // 244, 250
+ //missile.glow_size = 120;
+ settouch(missile, GrapplingHookTouch);
+ setthink(missile, GrapplingHookThink);
+ missile.nextthink = time;
+
+ missile.effects = /*EF_FULLBRIGHT | EF_ADDITIVE |*/ EF_LOWPRECISION;
+
+ SetResourceExplicit(missile, RES_HEALTH, autocvar_g_balance_grapplehook_health);
+ missile.event_damage = GrapplingHook_Damage;
+ missile.takedamage = DAMAGE_AIM;
+ missile.damageforcescale = 0;
+ missile.damagedbycontents = (autocvar_g_balance_grapplehook_damagedbycontents);
+ if(missile.damagedbycontents)
+ IL_PUSH(g_damagedbycontents, missile);
+
+ missile.hook_start = missile.hook_end = missile.origin;
+
+ Net_LinkEntity(missile, false, 0, GrapplingHookSend);
+}
+
+void GrappleHookInit()
+{
+ if(g_grappling_hook)
+ {
+ hook_shotorigin[0] = '8 8 -12';
+ hook_shotorigin[1] = '8 8 -12';
+ hook_shotorigin[2] = '8 8 -12';
+ hook_shotorigin[3] = '8 8 -12';
+ }
+ else
+ {
+ Weapon w = WEP_HOOK;
+ w.wr_init(w);
+ hook_shotorigin[0] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 1);
+ hook_shotorigin[1] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 2);
+ hook_shotorigin[2] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 3);
+ hook_shotorigin[3] = shotorg_adjust_values(CL_Weapon_GetShotOrg(WEP_HOOK.m_id), false, false, 4);
+ }
+}
--- /dev/null
+#pragma once
+
+// Wazat's grappling hook
+.entity hook;
+void GrapplingHookThink(entity this);
+void RemoveGrapplingHooks(entity pl);
+void RemoveHook(entity this);
+// (note: you can change the hook impulse #'s to whatever you please)
+.float hook_time;
+
+.float hook_length;
+
+const float HOOK_FIRING = BIT(0);
+const float HOOK_REMOVING = BIT(1);
+const float HOOK_PULLING = BIT(2);
+const float HOOK_RELEASING = BIT(3);
+const float HOOK_WAITING_FOR_RELEASE = BIT(4);
+.float hook_state;
+.int state;
+
+void GrappleHookInit();
+vector hook_shotorigin[4];
+
#include "weapons/throwing.qh"
#include "command/common.qh"
#include "cheats.qh"
+#include "client.qh"
#include "clientkill.qh"
+#include "damage.qh"
#include "weapons/selection.qh"
#include "weapons/tracing.qh"
#include "weapons/weaponsystem.qh"
{
if (this.vehicle) return;
if (IS_DEAD(this)) return;
+ bool is_dualwielding = W_DualWielding(this);
for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
{
.entity weaponentity = weaponentities[slot];
- W_ThrowWeapon(this, weaponentity, W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), '0 0 0', true);
-
- if(autocvar_g_weaponswitch_debug != 1)
- break;
+ vector md = this.(weaponentity).movedir;
+ vector vecs = ((md.x > 0) ? md : '0 0 0');
+ vector dv = v_right * -vecs.y;
+ if(!is_dualwielding)
+ dv = '0 0 0'; // don't override!
+ W_ThrowWeapon(this, weaponentity, W_CalculateProjectileVelocity(this, this.velocity, v_forward * 750, false), dv, true);
+
+ if(autocvar_g_weaponswitch_debug == 2)
+ break; // in this mode, the off-hand weapon is selected based on the primary weapon, don't drop it twice!
}
}
#include "ipban.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include "autocvars.qh"
#include "command/banning.qh"
-#include "defs.qh"
#include "../common/constants.qh"
#include "../common/util.qh"
+++ /dev/null
-#include "items.qh"
-
-/// \file
-/// \brief Source file that contains implementation of the functions related to
-/// game items.
-/// \copyright GNU GPLv2 or any later version.
-
-#include <server/mutators/_mod.qh>
-#include <common/weapons/all.qh>
-#include <common/mapobjects/subs.qh>
-
-.bool m_isloot; ///< Holds whether item is loot.
-/// \brief Holds whether strength, shield or superweapon timers expire while
-/// this item is on the ground.
-.bool m_isexpiring;
-
-entity Item_FindDefinition(string class_name)
-{
- FOREACH(Items, it.m_canonical_spawnfunc == class_name,
- {
- return it;
- });
- FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
- {
- return it.m_pickup;
- });
- return NULL;
-}
-
-bool Item_IsAllowed(string class_name)
-{
- entity definition = Item_FindDefinition(class_name);
- if (definition == NULL)
- {
- return false;
- }
- return Item_IsDefinitionAllowed(definition);
-}
-
-bool Item_IsDefinitionAllowed(entity definition)
-{
- return !MUTATOR_CALLHOOK(FilterItemDefinition, definition);
-}
-
-entity Item_Create(string class_name, vector position, bool no_align)
-{
- entity item = spawn();
- item.classname = class_name;
- item.spawnfunc_checked = true;
- setorigin(item, position);
- item.noalign = no_align;
- Item_Initialize(item, class_name);
- if (wasfreed(item))
- {
- return NULL;
- }
- return item;
-}
-
-void Item_Initialize(entity item, string class_name)
-{
- FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
- {
- weapon_defaultspawnfunc(item, it);
- return;
- });
- FOREACH(Items, it.m_canonical_spawnfunc == class_name,
- {
- StartItem(item, it);
- return;
- });
- LOG_FATALF("Item_Initialize: Invalid classname: %s", class_name);
-}
-
-entity Item_CreateLoot(string class_name, vector position, vector vel,
- float time_to_live)
-{
- entity item = spawn();
- if (!Item_InitializeLoot(item, class_name, position, vel, time_to_live))
- {
- return NULL;
- }
- return item;
-}
-
-bool Item_InitializeLoot(entity item, string class_name, vector position,
- vector vel, float time_to_live)
-{
- item.classname = class_name;
- Item_SetLoot(item, true);
- item.noalign = true;
- setorigin(item, position);
- item.pickup_anyway = true;
- item.spawnfunc_checked = true;
- Item_Initialize(item, class_name);
- if (wasfreed(item))
- {
- return false;
- }
- item.gravity = 1;
- item.velocity = vel;
- SUB_SetFade(item, time + time_to_live, 1);
- return true;
-}
-
-bool Item_IsLoot(entity item)
-{
- return item.m_isloot || item.classname == "droppedweapon";
-}
-
-void Item_SetLoot(entity item, bool loot)
-{
- item.m_isloot = loot;
-}
-
-bool Item_ShouldKeepPosition(entity item)
-{
- return item.noalign || (item.spawnflags & 1);
-}
-
-bool Item_IsExpiring(entity item)
-{
- return item.m_isexpiring;
-}
-
-void Item_SetExpiring(entity item, bool expiring)
-{
- item.m_isexpiring = expiring;
-}
-
-// Compatibility spawn functions
-
-// FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
-SPAWNFUNC_ITEM(item_armor1, ITEM_ArmorSmall)
-
-SPAWNFUNC_ITEM(item_armor25, ITEM_ArmorMega)
-
-SPAWNFUNC_ITEM(item_armor_large, ITEM_ArmorMega)
-
-SPAWNFUNC_ITEM(item_health1, ITEM_HealthSmall)
-
-SPAWNFUNC_ITEM(item_health25, ITEM_HealthMedium)
-
-SPAWNFUNC_ITEM(item_health_large, ITEM_HealthBig)
-
-SPAWNFUNC_ITEM(item_health100, ITEM_HealthMega)
-
-SPAWNFUNC_ITEM(item_quad, ITEM_Strength)
+++ /dev/null
-#pragma once
-
-/// \file
-/// \brief Header file that describes the functions related to game items.
-/// \copyright GNU GPLv2 or any later version.
-
-bool startitem_failed;
-
-/// \brief Returns the item definition corresponding to the given class name.
-/// \param[in] class_name Class name to search for.
-/// \return Item definition corresponding to the given class name or NULL is not
-/// found.
-entity Item_FindDefinition(string class_name);
-
-/// \brief Checks whether the items with the specified class name are allowed to
-/// spawn.
-/// \param[in] class_name Item class name to check.
-/// \return True items with the specified class name are allowed to spawn, false
-/// otherwise.
-bool Item_IsAllowed(string class_name);
-
-/// \brief Checks whether the items with the specified definition are allowed to
-/// spawn.
-/// \param[in] definition Item definition to check.
-/// \return True items with the specified definition are allowed to spawn, false
-/// otherwise.
-bool Item_IsDefinitionAllowed(entity definition);
-
-/// \brief Creates a new item.
-/// \param[in] class_name Class name of the item.
-/// \param[in] position Position of the item.
-/// \param[in] no_align True if item should be placed directly at specified
-/// position, false to let it drop to the ground.
-/// \return Item on success, NULL otherwise.
-entity Item_Create(string class_name, vector position, bool no_align);
-
-/// \brief Initializes the item according to class name.
-/// \param[in,out] item Item to initialize.
-/// \param[in] class_name Class name to use.
-/// \return No return.
-/// \nore This function is useful if you want to set some item properties before
-/// initialization.
-void Item_Initialize(entity item, string class_name);
-
-/// \brief Creates a loot item.
-/// \param[in] class_name Class name of the item.
-/// \param[in] position Position of the item.
-/// \param[in] velocity of the item.
-/// \param[in] time_to_live Amount of time after which the item will disappear.
-/// \return Item on success, NULL otherwise.
-entity Item_CreateLoot(string class_name, vector position, vector vel,
- float time_to_live);
-
-/// \brief Initializes the loot item.
-/// \param[in] class_name Class name of the item.
-/// \param[in] position Position of the item.
-/// \param[in] velocity of the item.
-/// \param[in] time_to_live Amount of time after which the item will disappear.
-/// \return True on success, false otherwise.
-/// \nore This function is useful if you want to set some item properties before
-/// initialization.
-bool Item_InitializeLoot(entity item, string class_name, vector position,
- vector vel, float time_to_live);
-
-/// \brief Returns whether the item is loot.
-/// \param[in] item Item to check.
-/// \return True if the item is loot, false otherwise.
-bool Item_IsLoot(entity item);
-
-/// \brief Sets the item loot status.
-/// \param[in,out] item Item to adjust.
-/// \param[in] loot Whether item is loot.
-/// \return No return.
-void Item_SetLoot(entity item, bool loot);
-
-/// \brief Returns whether item should keep its position or be dropped to the
-/// ground.
-/// \param[in] item Item to check.
-/// \return True if item should keep its position or false if it should be
-/// dropped to the ground.
-bool Item_ShouldKeepPosition(entity item);
-
-/// \brief Returns whether the item is expiring (i.e. its strength, shield and
-/// superweapon timers expire while it is on the ground).
-/// \param[in] item Item to check.
-/// \return True if the item is expiring, false otherwise.
-bool Item_IsExpiring(entity item);
-
-/// \brief Sets the item expiring status (i.e. whether its strength, shield
-/// and superweapon timers expire while it is on the ground).
-/// \param[in,out] item Item to adjust.
-/// \param[in] expiring Whether item is expiring.
-/// \return No return.
-void Item_SetExpiring(entity item, bool expiring);
--- /dev/null
+// generated file; do not modify
+#include <server/items/items.qc>
+#include <server/items/spawning.qc>
--- /dev/null
+// generated file; do not modify
+#include <server/items/items.qh>
+#include <server/items/spawning.qh>
--- /dev/null
+#include "items.qh"
+
+#include <common/items/_mod.qh>
+
+#include <server/bot/api.qh>
+
+#include <server/command/vote.qh>
+
+#include <server/damage.qh>
+
+#include <server/mutators/_mod.qh>
+
+#include <server/teamplay.qh>
+
+#include <server/weapons/common.qh>
+#include <server/weapons/selection.qh>
+#include <server/weapons/weaponsystem.qh>
+
+#include <common/constants.qh>
+#include <common/deathtypes/all.qh>
+#include <common/notifications/all.qh>
+#include <common/mapobjects/subs.qh>
+#include <common/mapobjects/triggers.qh>
+#include <common/util.qh>
+
+#include <common/monsters/_mod.qh>
+
+#include <common/wepent.qh>
+#include <common/weapons/_all.qh>
+
+#include <common/mutators/mutator/buffs/buffs.qh>
+#include <common/mutators/mutator/buffs/sv_buffs.qh>
+
+#include <lib/warpzone/util_server.qh>
+
+bool ItemSend(entity this, entity to, int sf)
+{
+ if(this.gravity)
+ sf |= ISF_DROP;
+ else
+ sf &= ~ISF_DROP;
+
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_ITEM);
+ WriteByte(MSG_ENTITY, sf);
+
+ //WriteByte(MSG_ENTITY, this.cnt);
+ if(sf & ISF_LOCATION)
+ {
+ WriteVector(MSG_ENTITY, this.origin);
+ }
+
+ if(sf & ISF_ANGLES)
+ {
+ WriteAngleVector(MSG_ENTITY, this.angles);
+ }
+
+ // sets size on the client, unused on server
+ //if(sf & ISF_SIZE)
+
+ if(sf & ISF_STATUS)
+ WriteByte(MSG_ENTITY, this.ItemStatus);
+
+ if(sf & ISF_MODEL)
+ {
+ WriteShort(MSG_ENTITY, this.fade_end);
+ WriteShort(MSG_ENTITY, this.fade_start);
+
+ if(this.mdl == "")
+ LOG_TRACE("^1WARNING!^7 this.mdl is unset for item ", this.classname, "expect a crash just about now");
+
+ WriteString(MSG_ENTITY, this.mdl);
+ }
+
+
+ if(sf & ISF_COLORMAP)
+ {
+ WriteShort(MSG_ENTITY, this.colormap);
+ WriteByte(MSG_ENTITY, this.glowmod.x * 255.0);
+ WriteByte(MSG_ENTITY, this.glowmod.y * 255.0);
+ WriteByte(MSG_ENTITY, this.glowmod.z * 255.0);
+ }
+
+ if(sf & ISF_DROP)
+ {
+ WriteVector(MSG_ENTITY, this.velocity);
+ }
+
+ return true;
+}
+
+void ItemUpdate(entity this)
+{
+ this.oldorigin = this.origin;
+ this.SendFlags |= ISF_LOCATION;
+}
+
+void UpdateItemAfterTeleport(entity this)
+{
+ if(getSendEntity(this) == ItemSend)
+ ItemUpdate(this);
+}
+
+bool have_pickup_item(entity this)
+{
+ if(this.itemdef.instanceOfPowerup)
+ {
+ if(autocvar_g_powerups > 0)
+ return true;
+ if(autocvar_g_powerups == 0)
+ return false;
+ }
+ else
+ {
+ if(autocvar_g_pickup_items > 0)
+ return true;
+ if(autocvar_g_pickup_items == 0)
+ return false;
+ if(g_weaponarena)
+ if(STAT(WEAPONS, this) || this.itemdef.instanceOfAmmo) // no item or ammo pickups in weaponarena
+ return false;
+ }
+ return true;
+}
+
+void Item_Show(entity e, int mode)
+{
+ e.effects &= ~(EF_ADDITIVE | EF_STARDUST | EF_FULLBRIGHT | EF_NODEPTHTEST);
+ e.ItemStatus &= ~ITS_STAYWEP;
+ entity def = e.itemdef;
+ if (mode > 0)
+ {
+ // make the item look normal, and be touchable
+ e.model = e.mdl;
+ e.solid = SOLID_TRIGGER;
+ e.spawnshieldtime = 1;
+ e.ItemStatus |= ITS_AVAILABLE;
+ }
+ else if (mode < 0)
+ {
+ // hide the item completely
+ e.model = string_null;
+ e.solid = SOLID_NOT;
+ e.spawnshieldtime = 1;
+ e.ItemStatus &= ~ITS_AVAILABLE;
+ }
+ else
+ {
+ bool nostay = def.instanceOfWeaponPickup ? !!(def.m_weapon.m_wepset & WEPSET_SUPERWEAPONS) : false // no weapon-stay on superweapons
+ || e.team // weapon stay isn't supported for teamed weapons
+ ;
+ if(def.instanceOfWeaponPickup && !nostay && g_weapon_stay)
+ {
+ // make the item translucent and not touchable
+ e.model = e.mdl;
+ e.solid = SOLID_TRIGGER; // can STILL be picked up!
+ e.effects |= EF_STARDUST;
+ e.spawnshieldtime = 0; // field indicates whether picking it up may give you anything other than the weapon
+ e.ItemStatus |= (ITS_AVAILABLE | ITS_STAYWEP);
+ }
+ else
+ {
+ //setmodel(e, "null");
+ e.solid = SOLID_NOT;
+ e.colormod = '0 0 0';
+ //e.glowmod = e.colormod;
+ e.spawnshieldtime = 1;
+ e.ItemStatus &= ~ITS_AVAILABLE;
+ }
+ }
+
+ if (def.m_glow)
+ e.ItemStatus |= ITS_GLOW;
+
+ if (autocvar_g_nodepthtestitems)
+ e.effects |= EF_NODEPTHTEST;
+
+ if (autocvar_g_fullbrightitems)
+ e.ItemStatus |= ITS_ALLOWFB;
+ else
+ e.ItemStatus &= ~ITS_ALLOWFB;
+
+ if (autocvar_sv_simple_items)
+ e.ItemStatus |= ITS_ALLOWSI;
+
+ // relink entity (because solid may have changed)
+ setorigin(e, e.origin);
+ e.SendFlags |= ISF_STATUS;
+}
+
+void Item_Think(entity this)
+{
+ this.nextthink = time;
+ if(this.origin != this.oldorigin)
+ ItemUpdate(this);
+}
+
+bool Item_ItemsTime_SpectatorOnly(GameItem it);
+bool Item_ItemsTime_Allow(GameItem it);
+float Item_ItemsTime_UpdateTime(entity e, float t);
+void Item_ItemsTime_SetTime(entity e, float t);
+void Item_ItemsTime_SetTimesForAllPlayers();
+
+void Item_Respawn(entity this)
+{
+ Item_Show(this, 1);
+ sound(this, CH_TRIGGER, this.itemdef.m_respawnsound, VOL_BASE, ATTEN_NORM); // play respawn sound
+ setorigin(this, this.origin);
+
+ if (Item_ItemsTime_Allow(this.itemdef) || (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS))
+ {
+ float t = Item_ItemsTime_UpdateTime(this, 0);
+ Item_ItemsTime_SetTime(this, t);
+ Item_ItemsTime_SetTimesForAllPlayers();
+ }
+
+ setthink(this, Item_Think);
+ this.nextthink = time;
+
+ //Send_Effect(EFFECT_ITEM_RESPAWN, this.origin + this.mins_z * '0 0 1' + '0 0 48', '0 0 0', 1);
+ Send_Effect(EFFECT_ITEM_RESPAWN, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
+}
+
+void Item_RespawnCountdown(entity this)
+{
+ if(this.item_respawncounter >= ITEM_RESPAWN_TICKS)
+ {
+ if(this.waypointsprite_attached)
+ WaypointSprite_Kill(this.waypointsprite_attached);
+ Item_Respawn(this);
+ }
+ else
+ {
+ this.nextthink = time + 1;
+ this.item_respawncounter += 1;
+ if(this.item_respawncounter == 1)
+ {
+ do {
+ {
+ entity wi = REGISTRY_GET(Weapons, this.weapon);
+ if (wi != WEP_Null) {
+ entity wp = WaypointSprite_Spawn(WP_Weapon, 0, 0, this, '0 0 64', NULL, 0, this, waypointsprite_attached, true, RADARICON_Weapon);
+ wp.wp_extra = wi.m_id;
+ break;
+ }
+ }
+ {
+ entity ii = this.itemdef;
+ if (ii != NULL) {
+ entity wp = WaypointSprite_Spawn(WP_Item, 0, 0, this, '0 0 64', NULL, 0, this, waypointsprite_attached, true, RADARICON_Item);
+ wp.wp_extra = ii.m_id;
+ break;
+ }
+ }
+ } while (0);
+ bool mutator_returnvalue = MUTATOR_CALLHOOK(Item_RespawnCountdown, this);
+ if(this.waypointsprite_attached)
+ {
+ GameItem def = this.itemdef;
+ if (Item_ItemsTime_SpectatorOnly(def) && !mutator_returnvalue)
+ WaypointSprite_UpdateRule(this.waypointsprite_attached, 0, SPRITERULE_SPECTATOR);
+ WaypointSprite_UpdateBuildFinished(this.waypointsprite_attached, time + ITEM_RESPAWN_TICKS);
+ }
+ }
+
+ if(this.waypointsprite_attached)
+ {
+ FOREACH_CLIENT(IS_REAL_CLIENT(it), {
+ if(this.waypointsprite_attached.waypointsprite_visible_for_player(this.waypointsprite_attached, it, it))
+ {
+ msg_entity = it;
+ soundto(MSG_ONE, this, CH_TRIGGER, SND(ITEMRESPAWNCOUNTDOWN), VOL_BASE, ATTEN_NORM, 0); // play respawn sound
+ }
+ });
+
+ WaypointSprite_Ping(this.waypointsprite_attached);
+ //WaypointSprite_UpdateHealth(this.waypointsprite_attached, this.item_respawncounter);
+ }
+ }
+}
+
+void Item_RespawnThink(entity this)
+{
+ this.nextthink = time;
+ if(this.origin != this.oldorigin)
+ ItemUpdate(this);
+
+ if(time >= this.wait)
+ Item_Respawn(this);
+}
+
+void Item_ScheduleRespawnIn(entity e, float t)
+{
+ // if the respawn time is longer than 10 seconds, show a waypoint, otherwise, just respawn normally
+ if ((Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS) || MUTATOR_CALLHOOK(Item_ScheduleRespawn, e, t)) && (t - ITEM_RESPAWN_TICKS) > 0)
+ {
+ setthink(e, Item_RespawnCountdown);
+ e.nextthink = time + max(0, t - ITEM_RESPAWN_TICKS);
+ e.scheduledrespawntime = e.nextthink + ITEM_RESPAWN_TICKS;
+ e.item_respawncounter = 0;
+ if(Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
+ {
+ t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime);
+ Item_ItemsTime_SetTime(e, t);
+ Item_ItemsTime_SetTimesForAllPlayers();
+ }
+ }
+ else
+ {
+ setthink(e, Item_RespawnThink);
+ e.nextthink = time;
+ e.scheduledrespawntime = time + t;
+ e.wait = time + t;
+
+ if(Item_ItemsTime_Allow(e.itemdef) || (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
+ {
+ t = Item_ItemsTime_UpdateTime(e, e.scheduledrespawntime);
+ Item_ItemsTime_SetTime(e, t);
+ Item_ItemsTime_SetTimesForAllPlayers();
+ }
+ }
+}
+
+AUTOCVAR(g_pickup_respawntime_scaling_reciprocal, float, 0.0, "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `reciprocal` (with `offset` and `linear` set to 0) can be used to achieve a constant number of items spawned *per player*");
+AUTOCVAR(g_pickup_respawntime_scaling_offset, float, 0.0, "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `offset` offsets the curve left or right - the results are not intuitive and I recommend plotting the respawn time and the number of items per player to see what's happening");
+AUTOCVAR(g_pickup_respawntime_scaling_linear, float, 1.0, "Multiply respawn time by `reciprocal / (p + offset) + linear` where `p` is the current number of players, takes effect with 2 or more players present, `linear` can be used to simply scale the respawn time linearly");
+
+/// Adjust respawn time according to the number of players.
+float adjust_respawntime(float normal_respawntime) {
+ float r = autocvar_g_pickup_respawntime_scaling_reciprocal;
+ float o = autocvar_g_pickup_respawntime_scaling_offset;
+ float l = autocvar_g_pickup_respawntime_scaling_linear;
+
+ if (r == 0 && l == 1) {
+ return normal_respawntime;
+ }
+
+ entity balance = TeamBalance_CheckAllowedTeams(NULL);
+ TeamBalance_GetTeamCounts(balance, NULL);
+ int players = 0;
+ 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 {
+ return normal_respawntime;
+ }
+}
+
+void Item_ScheduleRespawn(entity e)
+{
+ if(e.respawntime > 0)
+ {
+ Item_Show(e, 0);
+
+ float adjusted_respawntime = adjust_respawntime(e.respawntime);
+ //LOG_INFOF("item %s will respawn in %f", e.classname, adjusted_respawntime);
+
+ // range: adjusted_respawntime - respawntimejitter .. adjusted_respawntime + respawntimejitter
+ float respawn_in = adjusted_respawntime + crandom() * e.respawntimejitter;
+ Item_ScheduleRespawnIn(e, respawn_in);
+ }
+ else // if respawntime is -1, this item does not respawn
+ Item_Show(e, -1);
+}
+
+AUTOCVAR(g_pickup_respawntime_initial_random, int, 1,
+ "For items that don't start spawned: 0: spawn after their normal respawntime; 1: spawn after `random * respawntime` with the *same* random; 2: same as 1 but each item has separate random");
+
+void Item_ScheduleInitialRespawn(entity e)
+{
+ Item_Show(e, 0);
+
+ float spawn_in;
+ if (autocvar_g_pickup_respawntime_initial_random == 0)
+ {
+ // range: respawntime .. respawntime + respawntimejitter
+ spawn_in = e.respawntime + random() * e.respawntimejitter;
+ }
+ else
+ {
+ float rnd;
+ if (autocvar_g_pickup_respawntime_initial_random == 1)
+ {
+ static float shared_random = 0;
+ // NOTE this code works only if items are scheduled at the same time (normal case)
+ // NOTE2 random() can't return exactly 1 so this check always work as intended
+ if (!shared_random || floor(time) > shared_random)
+ shared_random = floor(time) + random();
+ rnd = shared_random - floor(time);
+ }
+ else
+ rnd = random();
+
+ // range:
+ // if respawntime >= ITEM_RESPAWN_TICKS: ITEM_RESPAWN_TICKS .. respawntime + respawntimejitter
+ // else: 0 .. ITEM_RESPAWN_TICKS
+ // this is to prevent powerups spawning unexpectedly without waypoints
+ spawn_in = ITEM_RESPAWN_TICKS + rnd * (e.respawntime + e.respawntimejitter - ITEM_RESPAWN_TICKS);
+ }
+
+ Item_ScheduleRespawnIn(e, max(0, game_starttime - time) + ((e.respawntimestart) ? e.respawntimestart : spawn_in));
+}
+
+void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names,
+ entity ammo_entity)
+{
+ if (num_weapons == 0)
+ {
+ return;
+ }
+ int num_potential_weapons = tokenize_console(weapon_names);
+ for (int give_attempt = 0; give_attempt < num_weapons; ++give_attempt)
+ {
+ RandomSelection_Init();
+ for (int weapon_index = 0; weapon_index < num_potential_weapons;
+ ++weapon_index)
+ {
+ string weapon = argv(weapon_index);
+ FOREACH(Weapons, it != WEP_Null,
+ {
+ // Finding a weapon which player doesn't have.
+ if (!(STAT(WEAPONS, receiver) & it.m_wepset) && (it.netname == weapon))
+ {
+ RandomSelection_AddEnt(it, 1, 1);
+ break;
+ }
+ });
+ }
+ if (RandomSelection_chosen_ent == NULL)
+ {
+ return;
+ }
+ STAT(WEAPONS, receiver) |= RandomSelection_chosen_ent.m_wepset;
+ if (RandomSelection_chosen_ent.ammo_type == RES_NONE)
+ {
+ continue;
+ }
+ if (GetResource(receiver,
+ RandomSelection_chosen_ent.ammo_type) != 0)
+ {
+ continue;
+ }
+ GiveResource(receiver, RandomSelection_chosen_ent.ammo_type,
+ GetResource(ammo_entity,
+ RandomSelection_chosen_ent.ammo_type));
+ }
+}
+
+bool Item_GiveAmmoTo(entity item, entity player, int res_type, float ammomax)
+{
+ float amount = GetResource(item, res_type);
+ if (amount == 0)
+ {
+ return false;
+ }
+ float player_amount = GetResource(player, res_type);
+ if (item.spawnshieldtime)
+ {
+ if ((player_amount >= ammomax) && (item.pickup_anyway <= 0))
+ return false;
+ }
+ else if (g_weapon_stay == 2)
+ {
+ ammomax = min(amount, ammomax);
+ if(player_amount >= ammomax)
+ return false;
+ }
+ else
+ return false;
+ if (amount < 0)
+ TakeResourceWithLimit(player, res_type, -amount, ammomax);
+ else
+ GiveResourceWithLimit(player, res_type, amount, ammomax);
+ return true;
+}
+
+bool Item_GiveTo(entity item, entity player)
+{
+ // if nothing happens to player, just return without taking the item
+ int _switchweapon = 0;
+ // in case the player has autoswitch enabled do the following:
+ // if the player is using their best weapon before items are given, they
+ // probably want to switch to an even better weapon after items are given
+
+ if(CS(player).autoswitch)
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+ {
+ if(player.(weaponentity).m_switchweapon == w_getbestweapon(player, weaponentity))
+ _switchweapon |= BIT(slot);
+
+ if(!(STAT(WEAPONS, player) & WepSet_FromWeapon(player.(weaponentity).m_switchweapon)))
+ _switchweapon |= BIT(slot);
+ }
+ }
+ }
+ bool pickedup = false;
+ pickedup |= Item_GiveAmmoTo(item, player, RES_HEALTH, item.max_health);
+ pickedup |= Item_GiveAmmoTo(item, player, RES_ARMOR, item.max_armorvalue);
+ pickedup |= Item_GiveAmmoTo(item, player, RES_SHELLS, g_pickup_shells_max);
+ pickedup |= Item_GiveAmmoTo(item, player, RES_BULLETS, g_pickup_nails_max);
+ pickedup |= Item_GiveAmmoTo(item, player, RES_ROCKETS, g_pickup_rockets_max);
+ pickedup |= Item_GiveAmmoTo(item, player, RES_CELLS, g_pickup_cells_max);
+ pickedup |= Item_GiveAmmoTo(item, player, RES_PLASMA, g_pickup_plasma_max);
+ pickedup |= Item_GiveAmmoTo(item, player, RES_FUEL, g_pickup_fuel_max);
+ if (item.itemdef.instanceOfWeaponPickup)
+ {
+ WepSet w;
+ w = STAT(WEAPONS, item);
+ w &= ~STAT(WEAPONS, player);
+
+ if (w || (item.spawnshieldtime && item.pickup_anyway > 0))
+ {
+ pickedup = true;
+ FOREACH(Weapons, it != WEP_Null, {
+ if(w & (it.m_wepset))
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+ W_DropEvent(wr_pickup, player, it.m_id, item, weaponentity);
+ }
+ W_GiveWeapon(player, it.m_id);
+ }
+ });
+ }
+ }
+
+ if (item.itemdef.instanceOfPowerup)
+ {
+ if ((item.itemdef == ITEM_JetpackRegen) && !(player.items & IT_FUEL_REGEN))
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_ITEM_FUELREGEN_GOT);
+ else if ((item.itemdef == ITEM_Jetpack) && !(player.items & IT_JETPACK))
+ Send_Notification(NOTIF_ONE, player, MSG_CENTER, CENTER_ITEM_JETPACK_GOT);
+ }
+
+ int its;
+ if((its = (item.items - (item.items & player.items)) & IT_PICKUPMASK))
+ {
+ pickedup = true;
+ player.items |= its;
+ // TODO: we probably want to show a message in the console, but not this one!
+ //Send_Notification(NOTIF_ONE, player, MSG_INFO, INFO_ITEM_WEAPON_GOT, item.netname);
+ }
+
+ if (item.strength_finished)
+ {
+ pickedup = true;
+ STAT(STRENGTH_FINISHED, player) = max(STAT(STRENGTH_FINISHED, player), time) + item.strength_finished;
+ }
+ if (item.invincible_finished)
+ {
+ pickedup = true;
+ STAT(INVINCIBLE_FINISHED, player) = max(STAT(INVINCIBLE_FINISHED, player), time) + item.invincible_finished;
+ }
+ if (item.superweapons_finished)
+ {
+ pickedup = true;
+ STAT(SUPERWEAPONS_FINISHED, player) = max(STAT(SUPERWEAPONS_FINISHED, player), time) + item.superweapons_finished;
+ }
+
+ // always eat teamed entities
+ if(item.team)
+ pickedup = true;
+
+ if (!pickedup)
+ return false;
+
+ // crude hack to enforce switching weapons
+ if(g_cts && item.itemdef.instanceOfWeaponPickup && !CS(player).cvar_cl_cts_noautoswitch)
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(player.(weaponentity).m_weapon != WEP_Null || slot == 0)
+ W_SwitchWeapon_Force(player, REGISTRY_GET(Weapons, item.weapon), weaponentity);
+ }
+ return true;
+ }
+
+ if(_switchweapon)
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(_switchweapon & BIT(slot))
+ if(player.(weaponentity).m_switchweapon != w_getbestweapon(player, weaponentity))
+ W_SwitchWeapon_Force(player, w_getbestweapon(player, weaponentity), weaponentity);
+ }
+ }
+
+ return true;
+}
+
+void Item_Touch(entity this, entity toucher)
+{
+ // remove the item if it's currnetly in a NODROP brush or hits a NOIMPACT surface (such as sky)
+ if (Item_IsLoot(this))
+ {
+ if (ITEM_TOUCH_NEEDKILL())
+ {
+ delete(this);
+ return;
+ }
+ }
+
+ if(!(toucher.flags & FL_PICKUPITEMS)
+ || STAT(FROZEN, toucher)
+ || IS_DEAD(toucher)
+ || (this.solid != SOLID_TRIGGER)
+ || (this.owner == toucher)
+ || (time < this.item_spawnshieldtime)
+ ) { return; }
+
+ switch (MUTATOR_CALLHOOK(ItemTouch, this, toucher))
+ {
+ case MUT_ITEMTOUCH_RETURN: { return; }
+ case MUT_ITEMTOUCH_PICKUP: { toucher = M_ARGV(1, entity); goto pickup; }
+ }
+
+ toucher = M_ARGV(1, entity);
+
+ if (Item_IsExpiring(this))
+ {
+ this.strength_finished = max(0, this.strength_finished - time);
+ this.invincible_finished = max(0, this.invincible_finished - time);
+ this.superweapons_finished = max(0, this.superweapons_finished - time);
+ }
+ bool gave = ITEM_HANDLE(Pickup, this.itemdef, this, toucher);
+ if (!gave)
+ {
+ if (Item_IsExpiring(this))
+ {
+ // undo what we did above
+ this.strength_finished += time;
+ this.invincible_finished += time;
+ this.superweapons_finished += time;
+ }
+ return;
+ }
+
+LABEL(pickup)
+
+ if(this.target && this.target != "" && this.target != "###item###") // defrag support
+ SUB_UseTargets(this, toucher, NULL);
+
+ STAT(LAST_PICKUP, toucher) = time;
+
+ Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
+ _sound (toucher, (this.itemdef.instanceOfPowerup ? CH_TRIGGER_SINGLE : CH_TRIGGER), (this.item_pickupsound ? this.item_pickupsound : Sound_fixpath(this.item_pickupsound_ent)), VOL_BASE, ATTEN_NORM);
+
+ MUTATOR_CALLHOOK(ItemTouched, this, toucher);
+ if (wasfreed(this))
+ {
+ return;
+ }
+
+ if (Item_IsLoot(this))
+ {
+ delete(this);
+ return;
+ }
+ if (!this.spawnshieldtime)
+ {
+ return;
+ }
+ entity e;
+ if (this.team)
+ {
+ RandomSelection_Init();
+ IL_EACH(g_items, it.team == this.team,
+ {
+ if (it.itemdef) // is a registered item
+ {
+ Item_Show(it, -1);
+ it.scheduledrespawntime = 0;
+ RandomSelection_AddEnt(it, it.cnt, 0);
+ }
+ });
+ e = RandomSelection_chosen_ent;
+ Item_Show(e, 1); // reset its state so it is visible (extra sendflags doesn't matter, this happens anyway)
+ }
+ else
+ e = this;
+ Item_ScheduleRespawn(e);
+}
+
+void Item_Reset(entity this)
+{
+ Item_Show(this, !this.state);
+ setorigin(this, this.origin);
+
+ if (Item_IsLoot(this))
+ {
+ return;
+ }
+ setthink(this, Item_Think);
+ this.nextthink = time;
+ if (this.waypointsprite_attached)
+ {
+ WaypointSprite_Kill(this.waypointsprite_attached);
+ }
+ if (this.itemdef.instanceOfPowerup || (STAT(WEAPONS, this) & WEPSET_SUPERWEAPONS)) // do not spawn powerups initially!
+ {
+ Item_ScheduleInitialRespawn(this);
+ }
+}
+
+void Item_FindTeam(entity this)
+{
+ entity e;
+
+ if(this.effects & EF_NODRAW)
+ {
+ // marker for item team search
+ LOG_TRACE("Initializing item team ", ftos(this.team));
+ RandomSelection_Init();
+ IL_EACH(g_items, it.team == this.team,
+ {
+ if(it.itemdef) // is a registered item
+ RandomSelection_AddEnt(it, it.cnt, 0);
+ });
+
+ e = RandomSelection_chosen_ent;
+ if (!e)
+ return;
+
+ IL_EACH(g_items, it.team == this.team,
+ {
+ if(it.itemdef) // is a registered item
+ {
+ if(it != e)
+ {
+ // make it non-spawned
+ Item_Show(it, -1);
+ it.state = 1; // state 1 = initially hidden item, apparently
+ }
+ else
+ Item_Reset(it);
+ it.effects &= ~EF_NODRAW;
+ }
+ });
+ }
+}
+
+// Savage: used for item garbage-collection
+void RemoveItem(entity this)
+{
+ if(wasfreed(this) || !this) { return; }
+ Send_Effect(EFFECT_ITEM_PICKUP, CENTER_OR_VIEWOFS(this), '0 0 0', 1);
+ delete(this);
+}
+
+// pickup evaluation functions
+// these functions decide how desirable an item is to the bots
+
+float generic_pickupevalfunc(entity player, entity item) {return item.bot_pickupbasevalue;}
+
+float weapon_pickupevalfunc(entity player, entity item)
+{
+ // See if I have it already
+ if(STAT(WEAPONS, player) & STAT(WEAPONS, item))
+ {
+ // If I can pick it up
+ if(!item.spawnshieldtime)
+ return 0;
+ return ammo_pickupevalfunc(player, item);
+ }
+
+ // reduce weapon value if bot already got a good arsenal
+ float c = 1;
+ int weapons_value = 0;
+ FOREACH(Weapons, it != WEP_Null && (STAT(WEAPONS, player) & it.m_wepset), {
+ weapons_value += it.bot_pickupbasevalue;
+ });
+ c -= bound(0, weapons_value / 20000, 1) * 0.5;
+
+ return item.bot_pickupbasevalue * c;
+}
+
+float ammo_pickupevalfunc(entity player, entity item)
+{
+ bool need_shells = false, need_nails = false, need_rockets = false, need_cells = false, need_plasma = false, need_fuel = false;
+ entity wpn = NULL;
+ float c = 0;
+ float rating = 0;
+
+ // Detect needed ammo
+ if(item.itemdef.instanceOfWeaponPickup)
+ {
+ entity ammo = NULL;
+ if(GetResource(item, RES_SHELLS)) { need_shells = true; ammo = ITEM_Shells; }
+ else if(GetResource(item, RES_BULLETS)) { need_nails = true; ammo = ITEM_Bullets; }
+ else if(GetResource(item, RES_ROCKETS)) { need_rockets = true; ammo = ITEM_Rockets; }
+ else if(GetResource(item, RES_CELLS)) { need_cells = true; ammo = ITEM_Cells; }
+ else if(GetResource(item, RES_PLASMA)) { need_plasma = true; ammo = ITEM_Plasma; }
+ else if(GetResource(item, RES_FUEL)) { need_fuel = true; ammo = ITEM_JetpackFuel; }
+
+ if(!ammo)
+ return 0;
+ wpn = item;
+ rating = ammo.m_botvalue;
+ }
+ else
+ {
+ FOREACH(Weapons, it != WEP_Null, {
+ if(!(STAT(WEAPONS, player) & (it.m_wepset)))
+ continue;
+
+ switch(it.ammo_type)
+ {
+ case RES_SHELLS: need_shells = true; break;
+ case RES_BULLETS: need_nails = true; break;
+ case RES_ROCKETS: need_rockets = true; break;
+ case RES_CELLS: need_cells = true; break;
+ case RES_PLASMA: need_plasma = true; break;
+ case RES_FUEL: need_fuel = true; break;
+ }
+ });
+ rating = item.bot_pickupbasevalue;
+ }
+
+ float noammorating = 0.5;
+
+ if ((need_shells) && GetResource(item, RES_SHELLS) && (GetResource(player, RES_SHELLS) < g_pickup_shells_max))
+ c = GetResource(item, RES_SHELLS) / max(noammorating, GetResource(player, RES_SHELLS));
+
+ if ((need_nails) && GetResource(item, RES_BULLETS) && (GetResource(player, RES_BULLETS) < g_pickup_nails_max))
+ c = GetResource(item, RES_BULLETS) / max(noammorating, GetResource(player, RES_BULLETS));
+
+ if ((need_rockets) && GetResource(item, RES_ROCKETS) && (GetResource(player, RES_ROCKETS) < g_pickup_rockets_max))
+ c = GetResource(item, RES_ROCKETS) / max(noammorating, GetResource(player, RES_ROCKETS));
+
+ if ((need_cells) && GetResource(item, RES_CELLS) && (GetResource(player, RES_CELLS) < g_pickup_cells_max))
+ c = GetResource(item, RES_CELLS) / max(noammorating, GetResource(player, RES_CELLS));
+
+ if ((need_plasma) && GetResource(item, RES_PLASMA) && (GetResource(player, RES_PLASMA) < g_pickup_plasma_max))
+ c = GetResource(item, RES_PLASMA) / max(noammorating, GetResource(player, RES_PLASMA));
+
+ if ((need_fuel) && GetResource(item, RES_FUEL) && (GetResource(player, RES_FUEL) < g_pickup_fuel_max))
+ c = GetResource(item, RES_FUEL) / max(noammorating, GetResource(player, RES_FUEL));
+
+ rating *= min(c, 2);
+ if(wpn)
+ rating += wpn.bot_pickupbasevalue * 0.1;
+ return rating;
+}
+
+float healtharmor_pickupevalfunc(entity player, entity item)
+{
+ float c = 0;
+ float rating = item.bot_pickupbasevalue;
+
+ float itemarmor = GetResource(item, RES_ARMOR);
+ float itemhealth = GetResource(item, RES_HEALTH);
+
+ if(item.item_group)
+ {
+ itemarmor *= min(4, item.item_group_count);
+ itemhealth *= min(4, item.item_group_count);
+ }
+
+ if (itemarmor && (GetResource(player, RES_ARMOR) < item.max_armorvalue))
+ c = itemarmor / max(1, GetResource(player, RES_ARMOR) * 2/3 + GetResource(player, RES_HEALTH) * 1/3);
+
+ if (itemhealth && (GetResource(player, RES_HEALTH) < item.max_health))
+ c = itemhealth / max(1, GetResource(player, RES_HEALTH));
+
+ rating *= min(2, c);
+ return rating;
+}
+
+void Item_Damage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
+{
+ if(ITEM_DAMAGE_NEEDKILL(deathtype))
+ RemoveItem(this);
+}
+
+void item_use(entity this, entity actor, entity trigger)
+{
+ // use the touch function to handle collection
+ gettouch(this)(this, actor);
+}
+
+void _StartItem(entity this, entity def, float defaultrespawntime, float defaultrespawntimejitter)
+{
+ string itemname = def.m_name;
+ Model itemmodel = def.m_model;
+ Sound pickupsound = def.m_sound;
+ float(entity player, entity item) pickupevalfunc = def.m_pickupevalfunc;
+ float pickupbasevalue = def.m_botvalue;
+ int itemflags = def.m_itemflags;
+
+ startitem_failed = false;
+
+ this.item_model_ent = itemmodel;
+ this.item_pickupsound_ent = pickupsound;
+
+ if(def.m_iteminit)
+ def.m_iteminit(def, this);
+
+ if(!this.respawntime) // both need to be set
+ {
+ this.respawntime = defaultrespawntime;
+ this.respawntimejitter = defaultrespawntimejitter;
+ }
+
+ if(!this.pickup_anyway && def.m_pickupanyway)
+ this.pickup_anyway = def.m_pickupanyway();
+
+ int itemid = def.m_itemid;
+ this.items = itemid;
+ int weaponid = def.instanceOfWeaponPickup ? def.m_weapon.m_id : 0;
+ this.weapon = weaponid;
+
+ if(!this.fade_end)
+ {
+ this.fade_start = autocvar_g_items_mindist;
+ this.fade_end = autocvar_g_items_maxdist;
+ }
+
+ if(weaponid)
+ STAT(WEAPONS, this) = WepSet_FromWeapon(REGISTRY_GET(Weapons, weaponid));
+
+ this.flags = FL_ITEM | itemflags;
+ IL_PUSH(g_items, this);
+
+ if(MUTATOR_CALLHOOK(FilterItem, this)) // error means we do not want the item
+ {
+ startitem_failed = true;
+ delete(this);
+ return;
+ }
+
+ precache_model(this.model);
+ precache_sound(this.item_pickupsound);
+
+ if (Item_IsLoot(this))
+ {
+ this.reset = SUB_Remove;
+ set_movetype(this, MOVETYPE_TOSS);
+
+ // Savage: remove thrown items after a certain period of time ("garbage collection")
+ setthink(this, RemoveItem);
+ this.nextthink = time + 20;
+
+ this.takedamage = DAMAGE_YES;
+ this.event_damage = Item_Damage;
+
+ if (Item_IsExpiring(this))
+ {
+ // if item is worthless after a timer, have it expire then
+ this.nextthink = max(this.strength_finished, this.invincible_finished, this.superweapons_finished);
+ }
+
+ // don't drop if in a NODROP zone (such as lava)
+ traceline(this.origin, this.origin, MOVE_NORMAL, this);
+ if (trace_dpstartcontents & DPCONTENTS_NODROP)
+ {
+ startitem_failed = true;
+ delete(this);
+ return;
+ }
+ }
+ else
+ {
+ if(!have_pickup_item(this))
+ {
+ startitem_failed = true;
+ delete(this);
+ return;
+ }
+
+ if(this.angles != '0 0 0')
+ this.SendFlags |= ISF_ANGLES;
+
+ this.reset = Item_Reset;
+ // it's a level item
+ if(this.spawnflags & 1)
+ this.noalign = 1;
+ if (this.noalign > 0)
+ set_movetype(this, MOVETYPE_NONE);
+ else
+ set_movetype(this, MOVETYPE_TOSS);
+ // do item filtering according to game mode and other things
+ if (this.noalign <= 0)
+ {
+ // first nudge it off the floor a little bit to avoid math errors
+ setorigin(this, this.origin + '0 0 1');
+ // set item size before we spawn a spawnfunc_waypoint
+ setsize(this, def.m_mins, def.m_maxs);
+ this.SendFlags |= ISF_SIZE;
+ // note droptofloor returns false if stuck/or would fall too far
+ if (!this.noalign)
+ droptofloor(this);
+ waypoint_spawnforitem(this);
+ }
+
+ /*
+ * can't do it that way, as it would break maps
+ * TODO make a target_give like entity another way, that perhaps has
+ * the weapon name in a key
+ if(this.targetname)
+ {
+ // target_give not yet supported; maybe later
+ print("removed targeted ", this.classname, "\n");
+ startitem_failed = true;
+ delete(this);
+ return;
+ }
+ */
+
+ if(this.targetname != "" && (this.spawnflags & 16))
+ this.use = item_use;
+
+ if(autocvar_spawn_debug >= 2)
+ {
+ // why not flags & fl_item?
+ FOREACH_ENTITY_RADIUS(this.origin, 3, it.is_item, {
+ LOG_TRACE("XXX Found duplicated item: ", itemname, vtos(this.origin));
+ LOG_TRACE(" vs ", it.netname, vtos(it.origin));
+ error("Mapper sucks.");
+ });
+ this.is_item = true;
+ }
+
+ weaponsInMap |= WepSet_FromWeapon(REGISTRY_GET(Weapons, weaponid));
+
+ if ( def.instanceOfPowerup
+ || def.instanceOfWeaponPickup
+ || (def.instanceOfHealth && def != ITEM_HealthSmall)
+ || (def.instanceOfArmor && def != ITEM_ArmorSmall)
+ || (itemid & (IT_KEY1 | IT_KEY2))
+ )
+ {
+ if(!this.target || this.target == "")
+ this.target = "###item###"; // for finding the nearest item using findnearest
+ }
+
+ Item_ItemsTime_SetTime(this, 0);
+ }
+
+ this.bot_pickup = true;
+ this.bot_pickupevalfunc = pickupevalfunc;
+ this.bot_pickupbasevalue = pickupbasevalue;
+ this.mdl = this.model ? this.model : strzone(this.item_model_ent.model_str());
+ this.netname = itemname;
+ settouch(this, Item_Touch);
+ setmodel(this, MDL_Null); // precision set below
+ //this.effects |= EF_LOWPRECISION;
+
+ setsize (this, this.pos1 = def.m_mins, this.pos2 = def.m_maxs);
+
+ this.SendFlags |= ISF_SIZE;
+
+ if (!(this.spawnflags & 1024)) {
+ if(def.instanceOfPowerup)
+ this.ItemStatus |= ITS_ANIMATE1;
+
+ if(GetResource(this, RES_ARMOR) || GetResource(this, RES_HEALTH))
+ this.ItemStatus |= ITS_ANIMATE2;
+ }
+
+ if(Item_IsLoot(this))
+ this.gravity = 1;
+
+ if(def.instanceOfWeaponPickup)
+ {
+ if (!Item_IsLoot(this)) // if dropped, colormap is already set up nicely
+ this.colormap = 1024; // color shirt=0 pants=0 grey
+ if (!(this.spawnflags & 1024))
+ this.ItemStatus |= ITS_ANIMATE1;
+ this.SendFlags |= ISF_COLORMAP;
+ }
+
+ this.state = 0;
+ if(this.team)
+ {
+ if(!this.cnt)
+ this.cnt = 1; // item probability weight
+
+ this.effects |= EF_NODRAW; // marker for item team search
+ InitializeEntity(this, Item_FindTeam, INITPRIO_FINDTARGET);
+ }
+ else
+ Item_Reset(this);
+
+ Net_LinkEntity(this, !(def.instanceOfPowerup || def.instanceOfHealth || def.instanceOfArmor), 0, ItemSend);
+
+ // call this hook after everything else has been done
+ if (MUTATOR_CALLHOOK(Item_Spawn, this))
+ {
+ startitem_failed = true;
+ delete(this);
+ return;
+ }
+
+ setItemGroup(this);
+}
+
+void StartItem(entity this, GameItem def)
+{
+ def = def.m_spawnfunc_hookreplace(def, this);
+ if (def.spawnflags & ITEM_FLAG_MUTATORBLOCKED)
+ {
+ delete(this);
+ return;
+ }
+ this.classname = def.m_canonical_spawnfunc;
+ _StartItem(
+ this,
+ this.itemdef = def,
+ def.m_respawntime(), // defaultrespawntime
+ def.m_respawntimejitter() // defaultrespawntimejitter
+ );
+}
+
+#define IS_SMALL(def) ((def.instanceOfHealth && def == ITEM_HealthSmall) || (def.instanceOfArmor && def == ITEM_ArmorSmall))
+int group_count = 1;
+
+void setItemGroup(entity this)
+{
+ if(!IS_SMALL(this.itemdef) || Item_IsLoot(this))
+ return;
+
+ FOREACH_ENTITY_RADIUS(this.origin, 120, (it != this) && IS_SMALL(it.itemdef),
+ {
+ if(!this.item_group)
+ {
+ if(!it.item_group)
+ {
+ it.item_group = group_count;
+ group_count++;
+ }
+ this.item_group = it.item_group;
+ }
+ else // spawning item is already part of a item_group X
+ {
+ if(!it.item_group)
+ it.item_group = this.item_group;
+ else if(it.item_group != this.item_group) // found an item near the spawning item that is part of a different item_group Y
+ {
+ int grY = it.item_group;
+ // move all items of item_group Y to item_group X
+ IL_EACH(g_items, IS_SMALL(it.itemdef),
+ {
+ if(it.item_group == grY)
+ it.item_group = this.item_group;
+ });
+ }
+ }
+ });
+}
+
+void setItemGroupCount()
+{
+ for (int k = 1; k <= group_count; k++)
+ {
+ int count = 0;
+ IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { count++; });
+ if (count)
+ IL_EACH(g_items, IS_SMALL(it.itemdef) && it.item_group == k, { it.item_group_count = count; });
+ }
+}
+
+void target_items_use(entity this, entity actor, entity trigger)
+{
+ if(Item_IsLoot(actor))
+ {
+ EXACTTRIGGER_TOUCH(this, trigger);
+ delete(actor);
+ return;
+ }
+
+ if (!IS_PLAYER(actor) || IS_DEAD(actor))
+ return;
+
+ if(trigger.solid == SOLID_TRIGGER)
+ {
+ EXACTTRIGGER_TOUCH(this, trigger);
+ }
+
+ IL_EACH(g_items, it.enemy == actor && Item_IsLoot(it),
+ {
+ delete(it);
+ });
+
+ if(GiveItems(actor, 0, tokenize_console(this.netname)))
+ centerprint(actor, this.message);
+}
+
+spawnfunc(target_items)
+{
+ this.use = target_items_use;
+ if(!this.strength_finished)
+ this.strength_finished = autocvar_g_balance_powerup_strength_time;
+ if(!this.invincible_finished)
+ this.invincible_finished = autocvar_g_balance_powerup_invincible_time;
+ if(!this.superweapons_finished)
+ this.superweapons_finished = autocvar_g_balance_superweapons_time;
+
+ string str;
+ int n = tokenize_console(this.netname);
+ if(argv(0) == "give")
+ {
+ str = substring(this.netname, argv_start_index(1), argv_end_index(-1) - argv_start_index(1));
+ }
+ else
+ {
+ for(int j = 0; j < n; ++j)
+ {
+ // this is from a time when unlimited superweapons were handled together with ammo in some parts of the code
+ if (argv(j) == "unlimited_ammo") this.items |= IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS;
+ else if(argv(j) == "unlimited_weapon_ammo") this.items |= IT_UNLIMITED_AMMO;
+ else if(argv(j) == "unlimited_superweapons") this.items |= IT_UNLIMITED_SUPERWEAPONS;
+ else if(argv(j) == "strength") this.items |= ITEM_Strength.m_itemid;
+ else if(argv(j) == "invincible") this.items |= ITEM_Shield.m_itemid;
+ else if(argv(j) == "superweapons") this.items |= IT_SUPERWEAPON;
+ else if(argv(j) == "jetpack") this.items |= ITEM_Jetpack.m_itemid;
+ else if(argv(j) == "fuel_regen") this.items |= ITEM_JetpackRegen.m_itemid;
+ else
+ {
+ FOREACH(Buffs, it != BUFF_Null,
+ {
+ string s = Buff_UndeprecateName(argv(j));
+ if(s == it.netname)
+ {
+ STAT(BUFFS, this) |= (it.m_itemid);
+ if(!STAT(BUFF_TIME, this))
+ STAT(BUFF_TIME, this) = it.m_time(it);
+ break;
+ }
+ });
+ FOREACH(Weapons, it != WEP_Null, {
+ string s = W_UndeprecateName(argv(j));
+ if(s == it.netname)
+ {
+ STAT(WEAPONS, this) |= (it.m_wepset);
+ if(this.spawnflags == 0 || this.spawnflags == 2)
+ it.wr_init(it);
+ break;
+ }
+ });
+ }
+ }
+
+ string itemprefix, valueprefix;
+ if(this.spawnflags == 0)
+ {
+ itemprefix = "";
+ valueprefix = "";
+ }
+ else if(this.spawnflags == 1)
+ {
+ itemprefix = "max ";
+ valueprefix = "max ";
+ }
+ else if(this.spawnflags == 2)
+ {
+ itemprefix = "min ";
+ valueprefix = "min ";
+ }
+ else if(this.spawnflags == 4)
+ {
+ itemprefix = "minus ";
+ valueprefix = "max ";
+ }
+ else
+ {
+ error("invalid spawnflags");
+ itemprefix = valueprefix = string_null;
+ }
+
+ str = "";
+ str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & IT_UNLIMITED_AMMO), "unlimited_weapon_ammo");
+ str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & IT_UNLIMITED_SUPERWEAPONS), "unlimited_superweapons");
+ str = sprintf("%s %s%d %s", str, valueprefix, this.strength_finished * boolean(this.items & ITEM_Strength.m_itemid), "strength");
+ str = sprintf("%s %s%d %s", str, valueprefix, this.invincible_finished * boolean(this.items & ITEM_Shield.m_itemid), "invincible");
+ str = sprintf("%s %s%d %s", str, valueprefix, this.superweapons_finished * boolean(this.items & IT_SUPERWEAPON), "superweapons");
+ str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & ITEM_Jetpack.m_itemid), "jetpack");
+ str = sprintf("%s %s%d %s", str, itemprefix, boolean(this.items & ITEM_JetpackRegen.m_itemid), "fuel_regen");
+ float res;
+ res = GetResource(this, RES_SHELLS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "shells");
+ res = GetResource(this, RES_BULLETS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "nails");
+ res = GetResource(this, RES_ROCKETS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "rockets");
+ res = GetResource(this, RES_CELLS); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "cells");
+ res = GetResource(this, RES_PLASMA); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "plasma");
+ res = GetResource(this, RES_FUEL); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "fuel");
+ res = GetResource(this, RES_HEALTH); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "health");
+ res = GetResource(this, RES_ARMOR); if(res != 0) str = sprintf("%s %s%d %s", str, valueprefix, max(0, res), "armor");
+ // HACK: buffs share a single timer, so we need to include enabled buffs AFTER disabled ones to avoid loss
+ FOREACH(Buffs, it != BUFF_Null && !(STAT(BUFFS, this) & it.m_itemid), str = sprintf("%s %s%d %s", str, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
+ FOREACH(Buffs, it != BUFF_Null && (STAT(BUFFS, this) & it.m_itemid), str = sprintf("%s %s%d %s", str, valueprefix, max(0, STAT(BUFF_TIME, this)), it.netname));
+ FOREACH(Weapons, it != WEP_Null, str = sprintf("%s %s%d %s", str, itemprefix, !!(STAT(WEAPONS, this) & (it.m_wepset)), it.netname));
+ }
+ this.netname = strzone(str);
+
+ n = tokenize_console(this.netname);
+ for(int j = 0; j < n; ++j)
+ {
+ FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(argv(j)) == it.netname, {
+ it.wr_init(it);
+ break;
+ });
+ }
+}
+
+float GiveWeapon(entity e, float wpn, float op, float val)
+{
+ WepSet v0, v1;
+ WepSet s = WepSet_FromWeapon(REGISTRY_GET(Weapons, wpn));
+ v0 = (STAT(WEAPONS, e) & s);
+ switch(op)
+ {
+ case OP_SET:
+ if(val > 0)
+ STAT(WEAPONS, e) |= s;
+ else
+ STAT(WEAPONS, e) &= ~s;
+ break;
+ case OP_MIN:
+ case OP_PLUS:
+ if(val > 0)
+ STAT(WEAPONS, e) |= s;
+ break;
+ case OP_MAX:
+ if(val <= 0)
+ STAT(WEAPONS, e) &= ~s;
+ break;
+ case OP_MINUS:
+ if(val > 0)
+ STAT(WEAPONS, e) &= ~s;
+ break;
+ }
+ v1 = (STAT(WEAPONS, e) & s);
+ return (v0 != v1);
+}
+
+bool GiveBuff(entity e, Buff thebuff, int op, int val)
+{
+ bool had_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
+ float new_buff_time = ((had_buff) ? STAT(BUFF_TIME, e) : 0);
+ switch (op)
+ {
+ case OP_SET:
+ new_buff_time = val;
+ break;
+ case OP_MIN:
+ new_buff_time = max(new_buff_time, val);
+ break;
+ case OP_MAX:
+ new_buff_time = min(new_buff_time, val);
+ break;
+ case OP_PLUS:
+ new_buff_time += val;
+ break;
+ case OP_MINUS:
+ new_buff_time -= val;
+ break;
+ }
+ if(new_buff_time <= 0)
+ {
+ if(had_buff)
+ STAT(BUFF_TIME, e) = new_buff_time;
+ STAT(BUFFS, e) &= ~thebuff.m_itemid;
+ }
+ else
+ {
+ STAT(BUFF_TIME, e) = new_buff_time;
+ STAT(BUFFS, e) = thebuff.m_itemid; // NOTE: replaces any existing buffs on the player!
+ }
+ bool have_buff = (STAT(BUFFS, e) & thebuff.m_itemid);
+ return (had_buff != have_buff);
+}
+
+void GiveSound(entity e, float v0, float v1, float t, Sound snd_incr, Sound snd_decr)
+{
+ if(v1 == v0)
+ return;
+ if(v1 <= v0 - t)
+ {
+ if(snd_decr != NULL)
+ sound (e, CH_TRIGGER, snd_decr, VOL_BASE, ATTEN_NORM);
+ }
+ else if(v0 >= v0 + t)
+ {
+ if(snd_incr != NULL)
+ sound (e, CH_TRIGGER, snd_incr, VOL_BASE, ATTEN_NORM);
+ }
+}
+
+void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .float regenfield, float regentime)
+{
+ if(v0 < v1)
+ e.(rotfield) = max(e.(rotfield), time + rottime);
+ else if(v0 > v1)
+ e.(regenfield) = max(e.(regenfield), time + regentime);
+}
+bool GiveResourceValue(entity e, int res_type, int op, int val)
+{
+ int v0 = GetResource(e, res_type);
+ float new_val = 0;
+ switch (op)
+ {
+ // min 100 cells = at least 100 cells
+ case OP_SET: new_val = val; break;
+ case OP_MIN: new_val = max(v0, val); break;
+ case OP_MAX: new_val = min(v0, val); break;
+ case OP_PLUS: new_val = v0 + val; break;
+ case OP_MINUS: new_val = v0 - val; break;
+ default: return false;
+ }
+
+ return SetResourceExplicit(e, res_type, new_val);
+}
+
+float GiveItems(entity e, float beginarg, float endarg)
+{
+ float got, i, val, op;
+ string cmd;
+
+ val = 999;
+ op = OP_SET;
+
+ got = 0;
+
+ int _switchweapon = 0;
+
+ if(CS(e).autoswitch)
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
+ if(e.(weaponentity).m_switchweapon == w_getbestweapon(e, weaponentity))
+ _switchweapon |= BIT(slot);
+ }
+ }
+
+ STAT(STRENGTH_FINISHED, e) = max(0, STAT(STRENGTH_FINISHED, e) - time);
+ STAT(INVINCIBLE_FINISHED, e) = max(0, STAT(INVINCIBLE_FINISHED, e) - time);
+ STAT(SUPERWEAPONS_FINISHED, e) = max(0, STAT(SUPERWEAPONS_FINISHED, e) - time);
+ STAT(BUFF_TIME, e) = max(0, STAT(BUFF_TIME, e) - time);
+
+ PREGIVE(e, items);
+ PREGIVE_WEAPONS(e);
+ PREGIVE(e, stat_STRENGTH_FINISHED);
+ PREGIVE(e, stat_INVINCIBLE_FINISHED);
+ PREGIVE(e, stat_SUPERWEAPONS_FINISHED);
+ PREGIVE_RESOURCE(e, RES_BULLETS);
+ PREGIVE_RESOURCE(e, RES_CELLS);
+ PREGIVE_RESOURCE(e, RES_PLASMA);
+ PREGIVE_RESOURCE(e, RES_SHELLS);
+ PREGIVE_RESOURCE(e, RES_ROCKETS);
+ PREGIVE_RESOURCE(e, RES_FUEL);
+ PREGIVE_RESOURCE(e, RES_ARMOR);
+ PREGIVE_RESOURCE(e, RES_HEALTH);
+
+ for(i = beginarg; i < endarg; ++i)
+ {
+ cmd = argv(i);
+
+ if(cmd == "0" || stof(cmd))
+ {
+ val = stof(cmd);
+ continue;
+ }
+ switch(cmd)
+ {
+ case "no":
+ op = OP_MAX;
+ val = 0;
+ continue;
+ case "max":
+ op = OP_MAX;
+ continue;
+ case "min":
+ op = OP_MIN;
+ continue;
+ case "plus":
+ op = OP_PLUS;
+ continue;
+ case "minus":
+ op = OP_MINUS;
+ continue;
+ case "ALL":
+ got += GiveBit(e, items, ITEM_JetpackRegen.m_itemid, op, val);
+ got += GiveValue(e, stat_STRENGTH_FINISHED, op, val);
+ got += GiveValue(e, stat_INVINCIBLE_FINISHED, op, val);
+ got += GiveValue(e, stat_SUPERWEAPONS_FINISHED, op, val);
+ got += GiveBit(e, items, IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS, op, val);
+ case "all":
+ got += GiveBit(e, items, ITEM_Jetpack.m_itemid, op, val);
+ got += GiveResourceValue(e, RES_HEALTH, op, val);
+ got += GiveResourceValue(e, RES_ARMOR, op, val);
+ case "allweapons":
+ FOREACH(Weapons, it != WEP_Null && !(it.spawnflags & (WEP_FLAG_MUTATORBLOCKED | WEP_FLAG_SPECIALATTACK)), got += GiveWeapon(e, it.m_id, op, val));
+ //case "allbuffs": // all buffs makes a player god, do not want!
+ //FOREACH(Buffs, it != BUFF_Null, got += GiveBuff(e, it.m_itemid, op, val));
+ case "allammo":
+ got += GiveResourceValue(e, RES_CELLS, op, val);
+ got += GiveResourceValue(e, RES_PLASMA, op, val);
+ got += GiveResourceValue(e, RES_SHELLS, op, val);
+ got += GiveResourceValue(e, RES_BULLETS, op, val);
+ got += GiveResourceValue(e, RES_ROCKETS, op, val);
+ got += GiveResourceValue(e, RES_FUEL, op, val);
+ break;
+ case "unlimited_ammo":
+ // this is from a time when unlimited superweapons were handled together with ammo in some parts of the code
+ got += GiveBit(e, items, IT_UNLIMITED_AMMO | IT_UNLIMITED_SUPERWEAPONS, op, val);
+ break;
+ case "unlimited_weapon_ammo":
+ got += GiveBit(e, items, IT_UNLIMITED_AMMO, op, val);
+ break;
+ case "unlimited_superweapons":
+ got += GiveBit(e, items, IT_UNLIMITED_SUPERWEAPONS, op, val);
+ break;
+ case "jetpack":
+ got += GiveBit(e, items, ITEM_Jetpack.m_itemid, op, val);
+ break;
+ case "fuel_regen":
+ got += GiveBit(e, items, ITEM_JetpackRegen.m_itemid, op, val);
+ break;
+ case "strength":
+ got += GiveValue(e, stat_STRENGTH_FINISHED, op, val);
+ break;
+ case "invincible":
+ got += GiveValue(e, stat_INVINCIBLE_FINISHED, op, val);
+ break;
+ case "superweapons":
+ got += GiveValue(e, stat_SUPERWEAPONS_FINISHED, op, val);
+ break;
+ case "cells":
+ got += GiveResourceValue(e, RES_CELLS, op, val);
+ break;
+ case "plasma":
+ got += GiveResourceValue(e, RES_PLASMA, op, val);
+ break;
+ case "shells":
+ got += GiveResourceValue(e, RES_SHELLS, op, val);
+ break;
+ case "nails":
+ case "bullets":
+ got += GiveResourceValue(e, RES_BULLETS, op, val);
+ break;
+ case "rockets":
+ got += GiveResourceValue(e, RES_ROCKETS, op, val);
+ break;
+ case "health":
+ got += GiveResourceValue(e, RES_HEALTH, op, val);
+ break;
+ case "armor":
+ got += GiveResourceValue(e, RES_ARMOR, op, val);
+ break;
+ case "fuel":
+ got += GiveResourceValue(e, RES_FUEL, op, val);
+ break;
+ default:
+ FOREACH(Buffs, it != BUFF_Null && buff_Available(it) && Buff_UndeprecateName(cmd) == it.netname,
+ {
+ got += GiveBuff(e, it, op, val);
+ break;
+ });
+ FOREACH(Weapons, it != WEP_Null && W_UndeprecateName(cmd) == it.netname, {
+ got += GiveWeapon(e, it.m_id, op, val);
+ break;
+ });
+ break;
+ }
+ val = 999;
+ op = OP_SET;
+ }
+
+ POSTGIVE_BIT(e, items, ITEM_JetpackRegen.m_itemid, SND_ITEMPICKUP, SND_Null);
+ POSTGIVE_BIT(e, items, IT_UNLIMITED_SUPERWEAPONS, SND_POWERUP, SND_POWEROFF);
+ POSTGIVE_BIT(e, items, IT_UNLIMITED_AMMO, SND_POWERUP, SND_POWEROFF);
+ POSTGIVE_BIT(e, items, ITEM_Jetpack.m_itemid, SND_ITEMPICKUP, SND_Null);
+ FOREACH(Weapons, it != WEP_Null, {
+ POSTGIVE_WEAPON(e, it, SND_WEAPONPICKUP, SND_Null);
+ if(!(save_weapons & (it.m_wepset)))
+ if(STAT(WEAPONS, e) & (it.m_wepset))
+ it.wr_init(it);
+ });
+ POSTGIVE_VALUE(e, stat_STRENGTH_FINISHED, 1, SND_POWERUP, SND_POWEROFF);
+ POSTGIVE_VALUE(e, stat_INVINCIBLE_FINISHED, 1, SND_Shield, SND_POWEROFF);
+ //POSTGIVE_VALUE(e, stat_SUPERWEAPONS_FINISHED, 1, SND_Null, SND_Null);
+ POSTGIVE_RESOURCE(e, RES_BULLETS, 0, SND_ITEMPICKUP, SND_Null);
+ POSTGIVE_RESOURCE(e, RES_CELLS, 0, SND_ITEMPICKUP, SND_Null);
+ POSTGIVE_RESOURCE(e, RES_PLASMA, 0, SND_ITEMPICKUP, SND_Null);
+ POSTGIVE_RESOURCE(e, RES_SHELLS, 0, SND_ITEMPICKUP, SND_Null);
+ POSTGIVE_RESOURCE(e, RES_ROCKETS, 0, SND_ITEMPICKUP, SND_Null);
+ POSTGIVE_RES_ROT(e, RES_FUEL, 1, pauserotfuel_finished, autocvar_g_balance_pause_fuel_rot, pauseregen_finished, autocvar_g_balance_pause_fuel_regen, SND_ITEMPICKUP, SND_Null);
+ POSTGIVE_RES_ROT(e, RES_ARMOR, 1, pauserotarmor_finished, autocvar_g_balance_pause_armor_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND_ARMOR25, SND_Null);
+ POSTGIVE_RES_ROT(e, RES_HEALTH, 1, pauserothealth_finished, autocvar_g_balance_pause_health_rot, pauseregen_finished, autocvar_g_balance_pause_health_regen, SND_MEGAHEALTH, SND_Null);
+
+ if(STAT(SUPERWEAPONS_FINISHED, e) <= 0)
+ if(!g_weaponarena && (STAT(WEAPONS, e) & WEPSET_SUPERWEAPONS))
+ STAT(SUPERWEAPONS_FINISHED, e) = autocvar_g_balance_superweapons_time;
+
+ if(STAT(STRENGTH_FINISHED, e) <= 0)
+ STAT(STRENGTH_FINISHED, e) = 0;
+ else
+ STAT(STRENGTH_FINISHED, e) += time;
+ if(STAT(INVINCIBLE_FINISHED, e) <= 0)
+ STAT(INVINCIBLE_FINISHED, e) = 0;
+ else
+ STAT(INVINCIBLE_FINISHED, e) += time;
+ if(STAT(SUPERWEAPONS_FINISHED, e) <= 0)
+ STAT(SUPERWEAPONS_FINISHED, e) = 0;
+ else
+ STAT(SUPERWEAPONS_FINISHED, e) += time;
+ if(STAT(BUFF_TIME, e) <= 0)
+ STAT(BUFF_TIME, e) = 0;
+ else
+ STAT(BUFF_TIME, e) += time;
+
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(e.(weaponentity).m_weapon != WEP_Null || slot == 0)
+ if(!(STAT(WEAPONS, e) & WepSet_FromWeapon(e.(weaponentity).m_switchweapon)))
+ _switchweapon |= BIT(slot);
+ }
+
+ if(_switchweapon)
+ {
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(_switchweapon & BIT(slot))
+ {
+ Weapon wep = w_getbestweapon(e, weaponentity);
+ if(wep != e.(weaponentity).m_switchweapon)
+ W_SwitchWeapon_Force(e, wep, weaponentity);
+ }
+ }
+ }
+
+ return got;
+}
--- /dev/null
+#pragma once
+
+#include <common/sounds/sound.qh>
+
+void StartItem(entity this, entity a);
+.int item_group;
+.int item_group_count;
+
+float autocvar_sv_simple_items;
+bool ItemSend(entity this, entity to, int sf);
+
+bool have_pickup_item(entity this);
+
+const float ITEM_RESPAWN_TICKS = 10;
+
+// string overrides entity
+.string item_pickupsound;
+.entity item_pickupsound_ent;
+.entity item_model_ent;
+
+.float max_armorvalue;
+.float pickup_anyway;
+
+.float scheduledrespawntime;
+.float respawntime;
+.float respawntimejitter;
+.float respawntimestart;
+
+.float item_respawncounter;
+
+.float noalign; // if set to 1, the item or spawnpoint won't be dropped to the floor
+
+.float superweapons_finished; // NOTE: this field is used only by map entities, it does not directly apply the superweapons stat
+
+// delay before this item can be picked up
+.float item_spawnshieldtime;
+
+void Item_Show (entity e, int mode);
+
+void Item_Respawn (entity this);
+
+void Item_RespawnCountdown(entity this);
+void Item_ScheduleRespawnIn(entity e, float t);
+
+void Item_ScheduleRespawn(entity e);
+
+void Item_ScheduleInitialRespawn(entity e);
+
+/// \brief Give several random weapons and ammo to the entity.
+/// \param[in,out] receiver Entity to give weapons to.
+/// \param[in] num_weapons Number of weapons to give.
+/// \param[in] weapon_names Names of weapons to give separated by spaces.
+/// \param[in] ammo Entity containing the ammo amount for each possible weapon.
+/// \return No return.
+void GiveRandomWeapons(entity receiver, int num_weapons, string weapon_names, entity ammo_entity);
+
+bool Item_GiveAmmoTo(entity item, entity player, int res_type, float ammomax);
+
+bool Item_GiveTo(entity item, entity player);
+
+void Item_Touch(entity this, entity toucher);
+
+void Item_Reset(entity this);
+
+void Item_FindTeam(entity this);
+// Savage: used for item garbage-collection
+
+bool ItemSend(entity this, entity to, int sf);
+void ItemUpdate(entity this);
+
+void UpdateItemAfterTeleport(entity this);
+
+// pickup evaluation functions
+// these functions decide how desirable an item is to the bots
+
+float generic_pickupevalfunc(entity player, entity item);// {return item.bot_pickupbasevalue;} // WEAPONTODO
+
+float weapon_pickupevalfunc(entity player, entity item);
+float ammo_pickupevalfunc(entity player, entity item);
+float healtharmor_pickupevalfunc(entity player, entity item);
+
+.bool is_item;
+.entity itemdef;
+void _StartItem(entity this, entity def, float defaultrespawntime, float defaultrespawntimejitter);
+
+void setItemGroup(entity this);
+void setItemGroupCount();
+
+float GiveWeapon(entity e, float wpn, float op, float val);
+
+float GiveBit(entity e, .float fld, float bit, float op, float val);
+
+float GiveValue(entity e, .float fld, float op, float val);
+
+void GiveSound(entity e, float v0, float v1, float t, Sound snd_incr, Sound snd_decr);
+
+void GiveRot(entity e, float v0, float v1, .float rotfield, float rottime, .float regenfield, float regentime);
+
+spawnfunc(target_items);
+
+#define PREGIVE_WEAPONS(e) WepSet save_weapons; save_weapons = STAT(WEAPONS, e)
+#define PREGIVE(e,f) float save_##f; save_##f = (e).f
+#define PREGIVE_RESOURCE(e,f) float save_##f = GetResource((e), (f))
+#define POSTGIVE_WEAPON(e,b,snd_incr,snd_decr) GiveSound((e), !!(save_weapons & WepSet_FromWeapon(b)), !!(STAT(WEAPONS, e) & WepSet_FromWeapon(b)), 0, snd_incr, snd_decr)
+#define POSTGIVE_BIT(e,f,b,snd_incr,snd_decr) GiveSound((e), save_##f & (b), (e).f & (b), 0, snd_incr, snd_decr)
+#define POSTGIVE_RESOURCE(e,f,t,snd_incr,snd_decr) GiveSound((e), save_##f, GetResource((e), (f)), t, snd_incr, snd_decr)
+#define POSTGIVE_RES_ROT(e,f,t,rotfield,rottime,regenfield,regentime,snd_incr,snd_decr) GiveRot((e),save_##f,GetResource((e),(f)),rotfield,rottime,regenfield,regentime);GiveSound((e),save_##f,GetResource((e),(f)),t,snd_incr,snd_decr)
+#define POSTGIVE_VALUE(e,f,t,snd_incr,snd_decr) GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr)
+#define POSTGIVE_VALUE_ROT(e,f,t,rotfield,rottime,regenfield,regentime,snd_incr,snd_decr) GiveRot((e), save_##f, (e).f, rotfield, rottime, regenfield, regentime); GiveSound((e), save_##f, (e).f, t, snd_incr, snd_decr)
+
+float GiveItems(entity e, float beginarg, float endarg);
+
+IntrusiveList g_items;
+STATIC_INIT(g_items) { g_items = IL_NEW(); }
--- /dev/null
+#include "spawning.qh"
+
+/// \file
+/// \brief Source file that contains implementation of the functions related to
+/// creation of game items.
+/// \copyright GNU GPLv2 or any later version.
+
+#include <server/items/items.qh>
+#include <server/mutators/_mod.qh>
+#include <server/weapons/spawning.qh>
+#include <common/weapons/all.qh>
+#include <common/mapobjects/subs.qh>
+
+.bool m_isloot; ///< Holds whether item is loot.
+/// \brief Holds whether strength, shield or superweapon timers expire while
+/// this item is on the ground.
+.bool m_isexpiring;
+
+entity Item_FindDefinition(string class_name)
+{
+ FOREACH(Items, it.m_canonical_spawnfunc == class_name,
+ {
+ return it;
+ });
+ FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
+ {
+ return it.m_pickup;
+ });
+ return NULL;
+}
+
+bool Item_IsAllowed(string class_name)
+{
+ entity definition = Item_FindDefinition(class_name);
+ if (definition == NULL)
+ {
+ return false;
+ }
+ return Item_IsDefinitionAllowed(definition);
+}
+
+bool Item_IsDefinitionAllowed(entity definition)
+{
+ return !MUTATOR_CALLHOOK(FilterItemDefinition, definition);
+}
+
+entity Item_Create(string class_name, vector position, bool no_align)
+{
+ entity item = spawn();
+ item.classname = class_name;
+ item.spawnfunc_checked = true;
+ setorigin(item, position);
+ item.noalign = no_align;
+ Item_Initialize(item, class_name);
+ if (wasfreed(item))
+ {
+ return NULL;
+ }
+ return item;
+}
+
+void Item_Initialize(entity item, string class_name)
+{
+ FOREACH(Weapons, it.m_canonical_spawnfunc == class_name,
+ {
+ weapon_defaultspawnfunc(item, it);
+ return;
+ });
+ FOREACH(Items, it.m_canonical_spawnfunc == class_name,
+ {
+ StartItem(item, it);
+ return;
+ });
+ LOG_FATALF("Item_Initialize: Invalid classname: %s", class_name);
+}
+
+entity Item_CreateLoot(string class_name, vector position, vector vel,
+ float time_to_live)
+{
+ entity item = spawn();
+ if (!Item_InitializeLoot(item, class_name, position, vel, time_to_live))
+ {
+ return NULL;
+ }
+ return item;
+}
+
+bool Item_InitializeLoot(entity item, string class_name, vector position,
+ vector vel, float time_to_live)
+{
+ item.classname = class_name;
+ Item_SetLoot(item, true);
+ item.noalign = true;
+ setorigin(item, position);
+ item.pickup_anyway = true;
+ item.spawnfunc_checked = true;
+ Item_Initialize(item, class_name);
+ if (wasfreed(item))
+ {
+ return false;
+ }
+ item.gravity = 1;
+ item.velocity = vel;
+ SUB_SetFade(item, time + time_to_live, 1);
+ return true;
+}
+
+bool Item_IsLoot(entity item)
+{
+ return item.m_isloot || item.classname == "droppedweapon";
+}
+
+void Item_SetLoot(entity item, bool loot)
+{
+ item.m_isloot = loot;
+}
+
+bool Item_ShouldKeepPosition(entity item)
+{
+ return item.noalign || (item.spawnflags & 1);
+}
+
+bool Item_IsExpiring(entity item)
+{
+ return item.m_isexpiring;
+}
+
+void Item_SetExpiring(entity item, bool expiring)
+{
+ item.m_isexpiring = expiring;
+}
+
+// Compatibility spawn functions
+
+// FIXME: in Quake this is green armor, in Xonotic maps it is an armor shard
+SPAWNFUNC_ITEM(item_armor1, ITEM_ArmorSmall)
+
+SPAWNFUNC_ITEM(item_armor25, ITEM_ArmorMega)
+
+SPAWNFUNC_ITEM(item_armor_large, ITEM_ArmorMega)
+
+SPAWNFUNC_ITEM(item_health1, ITEM_HealthSmall)
+
+SPAWNFUNC_ITEM(item_health25, ITEM_HealthMedium)
+
+SPAWNFUNC_ITEM(item_health_large, ITEM_HealthBig)
+
+SPAWNFUNC_ITEM(item_health100, ITEM_HealthMega)
+
+SPAWNFUNC_ITEM(item_quad, ITEM_Strength)
--- /dev/null
+#pragma once
+
+/// \file
+/// \brief Header file that describes the functions related to game items.
+/// \copyright GNU GPLv2 or any later version.
+
+bool startitem_failed;
+
+/// \brief Returns the item definition corresponding to the given class name.
+/// \param[in] class_name Class name to search for.
+/// \return Item definition corresponding to the given class name or NULL is not
+/// found.
+entity Item_FindDefinition(string class_name);
+
+/// \brief Checks whether the items with the specified class name are allowed to
+/// spawn.
+/// \param[in] class_name Item class name to check.
+/// \return True items with the specified class name are allowed to spawn, false
+/// otherwise.
+bool Item_IsAllowed(string class_name);
+
+/// \brief Checks whether the items with the specified definition are allowed to
+/// spawn.
+/// \param[in] definition Item definition to check.
+/// \return True items with the specified definition are allowed to spawn, false
+/// otherwise.
+bool Item_IsDefinitionAllowed(entity definition);
+
+/// \brief Creates a new item.
+/// \param[in] class_name Class name of the item.
+/// \param[in] position Position of the item.
+/// \param[in] no_align True if item should be placed directly at specified
+/// position, false to let it drop to the ground.
+/// \return Item on success, NULL otherwise.
+entity Item_Create(string class_name, vector position, bool no_align);
+
+/// \brief Initializes the item according to class name.
+/// \param[in,out] item Item to initialize.
+/// \param[in] class_name Class name to use.
+/// \return No return.
+/// \nore This function is useful if you want to set some item properties before
+/// initialization.
+void Item_Initialize(entity item, string class_name);
+
+/// \brief Creates a loot item.
+/// \param[in] class_name Class name of the item.
+/// \param[in] position Position of the item.
+/// \param[in] velocity of the item.
+/// \param[in] time_to_live Amount of time after which the item will disappear.
+/// \return Item on success, NULL otherwise.
+entity Item_CreateLoot(string class_name, vector position, vector vel,
+ float time_to_live);
+
+/// \brief Initializes the loot item.
+/// \param[in] class_name Class name of the item.
+/// \param[in] position Position of the item.
+/// \param[in] velocity of the item.
+/// \param[in] time_to_live Amount of time after which the item will disappear.
+/// \return True on success, false otherwise.
+/// \nore This function is useful if you want to set some item properties before
+/// initialization.
+bool Item_InitializeLoot(entity item, string class_name, vector position,
+ vector vel, float time_to_live);
+
+/// \brief Returns whether the item is loot.
+/// \param[in] item Item to check.
+/// \return True if the item is loot, false otherwise.
+bool Item_IsLoot(entity item);
+
+/// \brief Sets the item loot status.
+/// \param[in,out] item Item to adjust.
+/// \param[in] loot Whether item is loot.
+/// \return No return.
+void Item_SetLoot(entity item, bool loot);
+
+/// \brief Returns whether item should keep its position or be dropped to the
+/// ground.
+/// \param[in] item Item to check.
+/// \return True if item should keep its position or false if it should be
+/// dropped to the ground.
+bool Item_ShouldKeepPosition(entity item);
+
+/// \brief Returns whether the item is expiring (i.e. its strength, shield and
+/// superweapon timers expire while it is on the ground).
+/// \param[in] item Item to check.
+/// \return True if the item is expiring, false otherwise.
+bool Item_IsExpiring(entity item);
+
+/// \brief Sets the item expiring status (i.e. whether its strength, shield
+/// and superweapon timers expire while it is on the ground).
+/// \param[in,out] item Item to adjust.
+/// \param[in] expiring Whether item is expiring.
+/// \return No return.
+void Item_SetExpiring(entity item, bool expiring);
--- /dev/null
+#include "main.qh"
+
+#include "anticheat.qh"
+#include "hook.qh"
+#include "damage.qh"
+#include "world.qh"
+#include "spawnpoints.qh"
+#include <server/gamelog.qh>
+
+#include "bot/api.qh"
+
+#include "command/common.qh"
+
+#include <server/mutators/_mod.qh>
+#include "weapons/csqcprojectile.qh"
+#include <server/weapons/common.qh>
+#include <server/compat/quake3.qh>
+
+#include "../common/constants.qh"
+#include "../common/deathtypes/all.qh"
+#include "../common/debug.qh"
+#include "../common/mapinfo.qh"
+#include "../common/util.qh"
+
+#include "../common/vehicles/all.qh"
+#include <common/monsters/sv_monsters.qh>
+#include <common/weapons/_all.qh>
+
+#include "../lib/csqcmodel/sv_model.qh"
+
+#include "../lib/warpzone/common.qh"
+#include "../lib/warpzone/server.qh"
+
+void CreatureFrame_hotliquids(entity this)
+{
+ if (this.contents_damagetime >= time)
+ {
+ return;
+ }
+
+ this.contents_damagetime = time + autocvar_g_balance_contents_damagerate;
+
+ if (this.flags & FL_PROJECTILE)
+ {
+ if (this.watertype == CONTENT_LAVA)
+ Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ else if (this.watertype == CONTENT_SLIME)
+ Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ }
+ else
+ {
+ if (STAT(FROZEN, this))
+ {
+ if (this.watertype == CONTENT_LAVA)
+ Damage(this, NULL, NULL, 10000, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ else if (this.watertype == CONTENT_SLIME)
+ Damage(this, NULL, NULL, 10000, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ }
+ else if (this.watertype == CONTENT_LAVA)
+ {
+ if (this.watersound_finished < time)
+ {
+ this.watersound_finished = time + 0.5;
+ sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
+ }
+ Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ if(autocvar_g_balance_contents_playerdamage_lava_burn)
+ Fire_AddDamage(this, NULL, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
+ }
+ else if (this.watertype == CONTENT_SLIME)
+ {
+ if (this.watersound_finished < time)
+ {
+ this.watersound_finished = time + 0.5;
+ sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
+ }
+ Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ }
+ }
+}
+
+void CreatureFrame_Liquids(entity this)
+{
+ if (this.watertype <= CONTENT_WATER && this.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
+ {
+ if (!(this.flags & FL_INWATER))
+ {
+ this.flags |= FL_INWATER;
+ this.contents_damagetime = 0;
+ }
+
+ CreatureFrame_hotliquids(this);
+ }
+ else
+ {
+ if (this.flags & FL_INWATER)
+ {
+ // play leave water sound
+ this.flags &= ~FL_INWATER;
+ this.contents_damagetime = 0;
+ }
+ }
+}
+
+void CreatureFrame_FallDamage(entity this)
+{
+ if(IS_VEHICLE(this) || (this.flags & FL_PROJECTILE))
+ return; // vehicles and projectiles don't receive fall damage
+ if(!(this.velocity || this.oldvelocity))
+ return; // if the entity hasn't moved and isn't moving, then don't do anything
+
+ // check for falling damage
+ bool have_hook = false;
+ for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(this.(weaponentity).hook && this.(weaponentity).hook.state)
+ {
+ have_hook = true;
+ break;
+ }
+ }
+ if(!have_hook)
+ {
+ float dm; // dm is the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
+ if(autocvar_g_balance_falldamage_onlyvertical)
+ dm = fabs(this.oldvelocity.z) - vlen(this.velocity);
+ else
+ dm = vlen(this.oldvelocity) - vlen(this.velocity);
+ if (IS_DEAD(this))
+ dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
+ else
+ dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
+ if (dm > 0)
+ {
+ tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
+ if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODAMAGE))
+ Damage (this, NULL, NULL, dm, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
+ }
+ }
+
+ if(autocvar_g_maxspeed > 0 && vdist(this.velocity, >, autocvar_g_maxspeed))
+ Damage (this, NULL, NULL, 100000, DEATH_SHOOTING_STAR.m_id, DMG_NOWEP, this.origin, '0 0 0');
+}
+
+void CreatureFrame_All()
+{
+ if(game_stopped || time < game_starttime)
+ return;
+
+ IL_EACH(g_damagedbycontents, it.damagedbycontents,
+ {
+ if (it.move_movetype == MOVETYPE_NOCLIP) continue;
+ CreatureFrame_Liquids(it);
+ CreatureFrame_FallDamage(it);
+ it.oldvelocity = it.velocity;
+ });
+}
+
+void Pause_TryPause(bool ispaused)
+{
+ int n = 0;
+ FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), {
+ if (PHYS_INPUT_BUTTON_CHAT(it) != ispaused) return;
+ ++n;
+ });
+ if (!n) return;
+ setpause(ispaused);
+}
+
+void SV_PausedTic(float elapsedtime)
+{
+ if (!server_is_dedicated) Pause_TryPause(false);
+}
+
+/*
+=============
+StartFrame
+
+Called before each frame by the server
+=============
+*/
+
+bool game_delay_last;
+
+bool autocvar_sv_autopause = false;
+void systems_update();
+void sys_phys_update(entity this, float dt);
+void StartFrame()
+{
+ // TODO: if move is more than 50ms, split it into two moves (this matches QWSV behavior and the client prediction)
+ IL_EACH(g_players, IS_FAKE_CLIENT(it), sys_phys_update(it, frametime));
+ IL_EACH(g_players, IS_FAKE_CLIENT(it), PlayerPreThink(it));
+
+ execute_next_frame();
+ if (autocvar_sv_autopause && !server_is_dedicated) Pause_TryPause(true);
+
+ delete_fn = remove_unsafely; // not during spawning!
+ serverprevtime = servertime;
+ servertime = time;
+ serverframetime = frametime;
+
+#ifdef PROFILING
+ if(time > client_cefc_accumulatortime + 1)
+ {
+ float t = client_cefc_accumulator / (time - client_cefc_accumulatortime);
+ int c_seeing = 0;
+ int c_seen = 0;
+ FOREACH_CLIENT(true, {
+ if(IS_REAL_CLIENT(it))
+ ++c_seeing;
+ if(IS_PLAYER(it))
+ ++c_seen;
+ });
+ LOG_INFO(
+ "CEFC time: ", ftos(t * 1000), "ms; ",
+ "CEFC calls per second: ", ftos(c_seeing * (c_seen - 1) / t), "; ",
+ "CEFC 100% load at: ", ftos(solve_quadratic(t, -t, -1) * '0 1 0')
+ );
+ client_cefc_accumulatortime = time;
+ client_cefc_accumulator = 0;
+ }
+#endif
+
+ IL_EACH(g_projectiles, it.csqcprojectile_clientanimate, CSQCProjectile_Check(it));
+
+ if (RedirectionThink()) return;
+
+ UncustomizeEntitiesRun();
+ InitializeEntitiesRun();
+
+ WarpZone_StartFrame();
+
+ sys_frametime = autocvar_sys_ticrate * autocvar_slowmo;
+ if (sys_frametime <= 0) sys_frametime = 1.0 / 60.0; // somewhat safe fallback
+
+ if (timeout_status == TIMEOUT_LEADTIME) // just before the timeout (when timeout_status will be TIMEOUT_ACTIVE)
+ orig_slowmo = autocvar_slowmo; // slowmo will be restored after the timeout
+
+ // detect when the pre-game countdown (if any) has ended and the game has started
+ bool game_delay = (time < game_starttime);
+ if (autocvar_sv_eventlog && game_delay_last && !game_delay)
+ GameLogEcho(":startdelay_ended");
+ game_delay_last = game_delay;
+
+ CreatureFrame_All();
+ CheckRules_World();
+
+ if (warmup_stage && !game_stopped && warmup_limit > 0 && time >= warmup_limit) {
+ ReadyRestart();
+ return;
+ }
+
+ bot_serverframe();
+ anticheat_startframe();
+ MUTATOR_CALLHOOK(SV_StartFrame);
+
+ GlobalStats_updateglobal();
+ FOREACH_CLIENT(true, GlobalStats_update(it));
+ IL_EACH(g_players, IS_FAKE_CLIENT(it), PlayerPostThink(it));
+}
+
+.vector originjitter;
+.vector anglesjitter;
+.float anglejitter;
+.string gametypefilter;
+.string cvarfilter;
+
+/**
+ * Evaluate an expression of the form: [+ | -]? [var[op]val | [op]var | val | var] ...
+ * +: all must match. this is the default
+ * -: one must NOT match
+ *
+ * var>x
+ * var<x
+ * var>=x
+ * var<=x
+ * var==x
+ * var!=x
+ * var===x
+ * var!==x
+ */
+bool expr_evaluate(string s)
+{
+ bool ret = false;
+ if (str2chr(s, 0) == '+') {
+ s = substring(s, 1, -1);
+ } else if (str2chr(s, 0) == '-') {
+ ret = true;
+ s = substring(s, 1, -1);
+ }
+ bool expr_fail = false;
+ for (int i = 0, n = tokenize_console(s); i < n; ++i) {
+ int o;
+ string k, v;
+ s = argv(i);
+ #define X(expr) \
+ if (expr) \
+ continue; \
+ expr_fail = true; \
+ break;
+
+ #define BINOP(op, len, expr) \
+ if ((o = strstrofs(s, op, 0)) >= 0) { \
+ k = substring(s, 0, o); \
+ v = substring(s, o + len, -1); \
+ X(expr); \
+ }
+ BINOP(">=", 2, cvar(k) >= stof(v));
+ BINOP("<=", 2, cvar(k) <= stof(v));
+ BINOP(">", 1, cvar(k) > stof(v));
+ BINOP("<", 1, cvar(k) < stof(v));
+ BINOP("==", 2, cvar(k) == stof(v));
+ BINOP("!=", 2, cvar(k) != stof(v));
+ BINOP("===", 3, cvar_string(k) == v);
+ BINOP("!==", 3, cvar_string(k) != v);
+ {
+ k = s;
+ bool b = true;
+ if (str2chr(k, 0) == '!') {
+ k = substring(s, 1, -1);
+ b = false;
+ }
+ float f = stof(k);
+ bool isnum = ftos(f) == k;
+ X(boolean(isnum ? f : cvar(k)) == b);
+ }
+ #undef BINOP
+ #undef X
+ }
+ if (!expr_fail) {
+ ret = !ret;
+ }
+ // now ret is true if we want to keep the item, and false if we want to get rid of it
+ return ret;
+}
+
+void SV_OnEntityPreSpawnFunction(entity this)
+{
+ if (this)
+ if (this.gametypefilter != "")
+ if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, this.gametypefilter))
+ {
+ delete(this);
+ return;
+ }
+ if (this.cvarfilter != "" && !expr_evaluate(this.cvarfilter)) {
+ delete(this);
+ return;
+ }
+
+ if (DoesQ3ARemoveThisEntity(this)) {
+ delete(this);
+ return;
+ }
+
+ set_movetype(this, this.movetype);
+
+ if (this.monster_attack) {
+ IL_PUSH(g_monster_targets, this);
+ }
+
+ // support special -1 and -2 angle from radiant
+ if (this.angles == '0 -1 0') {
+ this.angles = '-90 0 0';
+ } else if (this.angles == '0 -2 0') {
+ this.angles = '+90 0 0';
+ }
+
+ #define X(out, in) MACRO_BEGIN \
+ if (in != 0) { out = out + (random() * 2 - 1) * in; } \
+ MACRO_END
+ X(this.origin.x, this.originjitter.x); X(this.origin.y, this.originjitter.y); X(this.origin.z, this.originjitter.z);
+ X(this.angles.x, this.anglesjitter.x); X(this.angles.y, this.anglesjitter.y); X(this.angles.z, this.anglesjitter.z);
+ X(this.angles.y, this.anglejitter);
+ #undef X
+
+ if (MUTATOR_CALLHOOK(OnEntityPreSpawn, this)) {
+ delete(this);
+ return;
+ }
+}
+
+void WarpZone_PostInitialize_Callback()
+{
+ // create waypoint links for warpzones
+ entity tracetest_ent = spawn();
+ setsize(tracetest_ent, PL_MIN_CONST, PL_MAX_CONST);
+ tracetest_ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
+ //for(entity e = warpzone_first; e; e = e.warpzone_next)
+ for(entity e = NULL; (e = find(e, classname, "trigger_warpzone")); )
+ waypoint_spawnforteleporter_wz(e, tracetest_ent);
+ delete(tracetest_ent);
+}
+
+/*
+==================
+main
+
+unused but required by the engine
+==================
+*/
+void main ()
+{
+
+}
--- /dev/null
+#pragma once
+
+bool expr_evaluate(string s);
+
+#ifdef PROFILING
+float client_cefc_accumulator;
+float client_cefc_accumulatortime;
+#endif
+
+float servertime, serverprevtime, serverframetime;
+
+.vector oldvelocity; // for fall damage
+
+.float watersound_finished;
+
+.bool iscreature;
+.float species;
+
+.float contents_damagetime;
+
+/*
+==================
+main
+
+unused but required by the engine
+==================
+*/
+void main ();
#include "mapvoting.qh"
-#include <server/defs.qh>
+#include <server/client.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/gamelog.qh>
#include <server/miscfunctions.qh>
-#include "g_world.qh"
+#include "world.qh"
#include "command/cmd.qh"
#include "command/getreplies.qh"
#include "../common/constants.qh"
#include "antilag.qh"
#include "command/common.qh"
-#include "constants.qh"
-#include "g_hook.qh"
+#include "client.qh"
+#include "damage.qh"
+#include "hook.qh"
+#include "world.qh"
#include <server/gamelog.qh>
#include "ipban.qh"
+#include <server/items/items.qh>
#include <server/mutators/_mod.qh>
-#include "../common/t_items.qh"
+#include <server/spawnpoints.qh>
+#include <server/main.qh>
#include "mapvoting.qh"
#include "resources.qh"
-#include "items.qh"
+#include <server/items/spawning.qh>
#include "player.qh"
#include "weapons/accuracy.qh"
+#include "weapons/common.qh"
#include "weapons/csqcprojectile.qh"
#include "weapons/selection.qh"
#include "../common/command/_mod.qh"
#include "../common/playerstats.qh"
#include "../common/teams.qh"
#include "../common/mapobjects/subs.qh"
+#include <common/mapobjects/trigger/hurt.qh>
+#include <common/mapobjects/target/location.qh>
#include "../common/util.qh"
#include "../common/turrets/sv_turrets.qh"
#include <common/weapons/_all.qh>
return o;
}
-REPLICATE(autoswitch, bool, "cl_autoswitch");
-
-REPLICATE(cvar_cl_allow_uid2name, bool, "cl_allow_uid2name");
-
-REPLICATE(cvar_cl_allow_uidranking, bool, "cl_allow_uidranking");
-
-REPLICATE(cvar_cl_autoscreenshot, int, "cl_autoscreenshot");
-
-REPLICATE(cvar_cl_autotaunt, float, "cl_autotaunt");
-
-REPLICATE(cvar_cl_clippedspectating, bool, "cl_clippedspectating");
-
-REPLICATE(cvar_cl_handicap, float, "cl_handicap");
-
-REPLICATE(cvar_cl_gunalign, int, "cl_gunalign");
-
-REPLICATE(cvar_cl_jetpack_jump, bool, "cl_jetpack_jump");
-
-REPLICATE(cvar_cl_movement_track_canjump, bool, "cl_movement_track_canjump");
-
-REPLICATE(cvar_cl_newusekeysupported, bool, "cl_newusekeysupported");
-
-REPLICATE(cvar_cl_noantilag, bool, "cl_noantilag");
-
-REPLICATE(cvar_cl_physics, string, "cl_physics");
-
-REPLICATE(cvar_cl_voice_directional, int, "cl_voice_directional");
-
-REPLICATE(cvar_cl_voice_directional_taunt_attenuation, float, "cl_voice_directional_taunt_attenuation");
-
-REPLICATE(cvar_cl_weaponimpulsemode, int, "cl_weaponimpulsemode");
-
-REPLICATE(cvar_g_xonoticversion, string, "g_xonoticversion");
-
-REPLICATE(cvar_cl_cts_noautoswitch, bool, "cl_cts_noautoswitch");
-
-REPLICATE(cvar_cl_weapon_switch_reload, bool, "cl_weapon_switch_reload");
-
-REPLICATE(cvar_cl_weapon_switch_fallback_to_impulse, bool, "cl_weapon_switch_fallback_to_impulse");
-
/**
* @param f -1: cleanup, 0: request, 1: receive
*/
#pragma once
-#include <server/defs.qh>
-#include <server/g_world.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/client.qh>
+#include <server/world.qh>
-#include <common/t_items.qh>
+#include <server/items/items.qh>
#include <server/mutators/_mod.qh>
float sv_autotaunt;
float sv_taunt;
+float g_footsteps, g_grappling_hook;
+float g_warmup_allguns;
+float g_warmup_allow_timeout;
+float warmup_stage;
+float g_jetpack;
+
+bool sv_ready_restart;
+bool sv_ready_restart_after_countdown;
+bool sv_ready_restart_repeatable;
+
+float sv_clones;
+float sv_foginterval;
+
void readlevelcvars()
{
if(cvar("sv_allow_fullbright"))
#include "loader.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
STATIC_INIT_LATE(Gametype) {
/**
- Manhattan Menas we expect to move up,down left or right
- No diagonal moves espected. (like moving bewteen city blocks)
+ Manhattan heuristic means we expect to move up, down left or right
+ No diagonal moves expected. (like moving between city blocks)
**/
-float pathlib_h_manhattan(vector a,vector b)
+float pathlib_h_manhattan(vector a, vector b)
{
//h(n) = D * (abs(n.x-goal.x) + abs(n.y-goal.y))
}
/**
- This heuristic consider both stright and disagonal moves
- to have teh same cost.
+ This heuristic consider both straight and diagonal moves
+ to have the same cost.
**/
-float pathlib_h_diagonal(vector a,vector b)
+float pathlib_h_diagonal(vector a, vector b)
{
//h(n) = D * max(abs(n.x-goal.x), abs(n.y-goal.y))
float hx = fabs(a.x - b.x);
float hy = fabs(a.y - b.y);
- float h = pathlib_movecost * max(hx,hy);
+ float h = pathlib_movecost * max(hx, hy);
return h;
}
/**
- This heuristic only considers the stright line distance.
- Will usualy mean a lower H then G meaning A* Will speand more
- and run slower.
+ This heuristic only considers the straight line distance.
+ Usually means a lower H then G, resulting in A* spreading more
+ (and running slower).
**/
-float pathlib_h_euclidean(vector a,vector b)
+float pathlib_h_euclidean(vector a, vector b)
{
return vlen(a - b);
}
/**
- This heuristic consider both stright and disagonal moves,
- But has a separate cost for diagonal moves.
+ This heuristic consider both straight and diagonal moves,
+ but has a separate cost for diagonal moves.
**/
float pathlib_h_diagonal2(vector a,vector b)
{
}
/**
- This heuristic consider both stright and disagonal moves,
+ This heuristic consider both straight and diagonal moves,
But has a separate cost for diagonal moves.
**/
-float pathlib_h_diagonal2sdp(vector preprev,vector prev,vector point,vector end)
+float pathlib_h_diagonal2sdp(vector preprev, vector prev, vector point, vector end)
{
//h_diagonal(n) = min(abs(n.x-goal.x), abs(n.y-goal.y))
//h_straight(n) = (abs(n.x-goal.x) + abs(n.y-goal.y))
vector d1 = normalize(preprev - point);
vector d2 = normalize(prev - point);
- float m = vlen(d1-d2);
+ float m = vlen(d1 - d2);
return h * m;
}
-float pathlib_h_diagonal3(vector a,vector b)
+float pathlib_h_diagonal3(vector a, vector b)
{
float hx = fabs(a.x - b.x);
float hy = fabs(a.y - b.y);
#include "pathlib.qh"
#include "utility.qh"
+/*
vector plib_points2[8];
vector plib_points[8];
float plib_fvals[8];
++fc2;
}
- /*
- nap = pathlib_nodeatpoint(plib_points[i]);
- if(nap)
- if not nap.owner == closedlist)
- {
- }
- */
+ //nap = pathlib_nodeatpoint(plib_points[i]);
+ //if(nap)
+ //if not nap.owner == closedlist)
+ //{
+ //}
}
pathlib_makenode(node, start, bp, goal, pathlib_gridsize);
return pathlib_open_cnt;
}
+*/
float pathlib_expandnode_star(entity node, vector start, vector goal)
{
return pathlib_open_cnt;
}
+/*
float pathlib_expandnode_octagon(entity node, vector start, vector goal)
{
vector point;
point = where + f + r;
pathlib_makenode(node, start, point, goal, pathlib_movecost);
-
// Forward-left
point = where + f - r;
pathlib_makenode(node, start, point, goal, pathlib_movecost);
-
// Back-right
point = where - f + r;
pathlib_makenode(node, start, point, goal, pathlib_movecost);
return pathlib_open_cnt;
}
+*/
float pathlib_expandnode_box(entity node, vector start, vector goal)
{
#include "main.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include "pathlib.qh"
#include "utility.qh"
#include "movenode.qh"
-#include <server/defs.qh>
+#include <common/mapobjects/triggers.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include "pathlib.qh"
#include "utility.qh"
float pathlib_wpp_expand(entity wp)
{
- if(wp.wp00) pathlib_wpp_open(wp,wp.wp00,wp.wp00mincost); else return 0;
- if(wp.wp01) pathlib_wpp_open(wp,wp.wp01,wp.wp01mincost); else return 1;
- if(wp.wp02) pathlib_wpp_open(wp,wp.wp02,wp.wp02mincost); else return 2;
- if(wp.wp03) pathlib_wpp_open(wp,wp.wp03,wp.wp03mincost); else return 3;
- if(wp.wp04) pathlib_wpp_open(wp,wp.wp04,wp.wp04mincost); else return 4;
- if(wp.wp05) pathlib_wpp_open(wp,wp.wp05,wp.wp05mincost); else return 5;
- if(wp.wp06) pathlib_wpp_open(wp,wp.wp06,wp.wp06mincost); else return 6;
- if(wp.wp07) pathlib_wpp_open(wp,wp.wp07,wp.wp07mincost); else return 7;
- if(wp.wp08) pathlib_wpp_open(wp,wp.wp08,wp.wp08mincost); else return 8;
- if(wp.wp09) pathlib_wpp_open(wp,wp.wp09,wp.wp09mincost); else return 9;
- if(wp.wp10) pathlib_wpp_open(wp,wp.wp10,wp.wp10mincost); else return 10;
- if(wp.wp11) pathlib_wpp_open(wp,wp.wp11,wp.wp11mincost); else return 11;
- if(wp.wp12) pathlib_wpp_open(wp,wp.wp12,wp.wp12mincost); else return 12;
- if(wp.wp13) pathlib_wpp_open(wp,wp.wp13,wp.wp13mincost); else return 13;
- if(wp.wp14) pathlib_wpp_open(wp,wp.wp14,wp.wp14mincost); else return 14;
- if(wp.wp15) pathlib_wpp_open(wp,wp.wp15,wp.wp15mincost); else return 15;
- if(wp.wp16) pathlib_wpp_open(wp,wp.wp16,wp.wp16mincost); else return 16;
- if(wp.wp17) pathlib_wpp_open(wp,wp.wp17,wp.wp17mincost); else return 17;
- if(wp.wp18) pathlib_wpp_open(wp,wp.wp18,wp.wp18mincost); else return 18;
- if(wp.wp19) pathlib_wpp_open(wp,wp.wp19,wp.wp19mincost); else return 19;
- if(wp.wp20) pathlib_wpp_open(wp,wp.wp20,wp.wp20mincost); else return 20;
- if(wp.wp21) pathlib_wpp_open(wp,wp.wp21,wp.wp21mincost); else return 21;
- if(wp.wp22) pathlib_wpp_open(wp,wp.wp22,wp.wp22mincost); else return 22;
- if(wp.wp23) pathlib_wpp_open(wp,wp.wp23,wp.wp23mincost); else return 23;
- if(wp.wp24) pathlib_wpp_open(wp,wp.wp24,wp.wp24mincost); else return 24;
- if(wp.wp25) pathlib_wpp_open(wp,wp.wp25,wp.wp25mincost); else return 25;
- if(wp.wp26) pathlib_wpp_open(wp,wp.wp26,wp.wp26mincost); else return 26;
- if(wp.wp27) pathlib_wpp_open(wp,wp.wp27,wp.wp27mincost); else return 27;
- if(wp.wp28) pathlib_wpp_open(wp,wp.wp28,wp.wp28mincost); else return 28;
- if(wp.wp29) pathlib_wpp_open(wp,wp.wp29,wp.wp29mincost); else return 29;
- if(wp.wp30) pathlib_wpp_open(wp,wp.wp30,wp.wp30mincost); else return 30;
- if(wp.wp31) pathlib_wpp_open(wp,wp.wp31,wp.wp31mincost); else return 31;
+ if(wp.wp00) pathlib_wpp_open(wp,wp.wp00, wp.wp00mincost); else return 0;
+ if(wp.wp01) pathlib_wpp_open(wp,wp.wp01, wp.wp01mincost); else return 1;
+ if(wp.wp02) pathlib_wpp_open(wp,wp.wp02, wp.wp02mincost); else return 2;
+ if(wp.wp03) pathlib_wpp_open(wp,wp.wp03, wp.wp03mincost); else return 3;
+ if(wp.wp04) pathlib_wpp_open(wp,wp.wp04, wp.wp04mincost); else return 4;
+ if(wp.wp05) pathlib_wpp_open(wp,wp.wp05, wp.wp05mincost); else return 5;
+ if(wp.wp06) pathlib_wpp_open(wp,wp.wp06, wp.wp06mincost); else return 6;
+ if(wp.wp07) pathlib_wpp_open(wp,wp.wp07, wp.wp07mincost); else return 7;
+ if(wp.wp08) pathlib_wpp_open(wp,wp.wp08, wp.wp08mincost); else return 8;
+ if(wp.wp09) pathlib_wpp_open(wp,wp.wp09, wp.wp09mincost); else return 9;
+ if(wp.wp10) pathlib_wpp_open(wp,wp.wp10, wp.wp10mincost); else return 10;
+ if(wp.wp11) pathlib_wpp_open(wp,wp.wp11, wp.wp11mincost); else return 11;
+ if(wp.wp12) pathlib_wpp_open(wp,wp.wp12, wp.wp12mincost); else return 12;
+ if(wp.wp13) pathlib_wpp_open(wp,wp.wp13, wp.wp13mincost); else return 13;
+ if(wp.wp14) pathlib_wpp_open(wp,wp.wp14, wp.wp14mincost); else return 14;
+ if(wp.wp15) pathlib_wpp_open(wp,wp.wp15, wp.wp15mincost); else return 15;
+ if(wp.wp16) pathlib_wpp_open(wp,wp.wp16, wp.wp16mincost); else return 16;
+ if(wp.wp17) pathlib_wpp_open(wp,wp.wp17, wp.wp17mincost); else return 17;
+ if(wp.wp18) pathlib_wpp_open(wp,wp.wp18, wp.wp18mincost); else return 18;
+ if(wp.wp19) pathlib_wpp_open(wp,wp.wp19, wp.wp19mincost); else return 19;
+ if(wp.wp20) pathlib_wpp_open(wp,wp.wp20, wp.wp20mincost); else return 20;
+ if(wp.wp21) pathlib_wpp_open(wp,wp.wp21, wp.wp21mincost); else return 21;
+ if(wp.wp22) pathlib_wpp_open(wp,wp.wp22, wp.wp22mincost); else return 22;
+ if(wp.wp23) pathlib_wpp_open(wp,wp.wp23, wp.wp23mincost); else return 23;
+ if(wp.wp24) pathlib_wpp_open(wp,wp.wp24, wp.wp24mincost); else return 24;
+ if(wp.wp25) pathlib_wpp_open(wp,wp.wp25, wp.wp25mincost); else return 25;
+ if(wp.wp26) pathlib_wpp_open(wp,wp.wp26, wp.wp26mincost); else return 26;
+ if(wp.wp27) pathlib_wpp_open(wp,wp.wp27, wp.wp27mincost); else return 27;
+ if(wp.wp28) pathlib_wpp_open(wp,wp.wp28, wp.wp28mincost); else return 28;
+ if(wp.wp29) pathlib_wpp_open(wp,wp.wp29, wp.wp29mincost); else return 29;
+ if(wp.wp30) pathlib_wpp_open(wp,wp.wp30, wp.wp30mincost); else return 30;
+ if(wp.wp31) pathlib_wpp_open(wp,wp.wp31, wp.wp31mincost); else return 31;
return 32;
}
else
pathlib_wpp_open = pathlib_wpp_openncb;
- pathlib_heuristic = pathlib_h_none;
+ pathlib_heuristic = pathlib_h_none; // We run Dijkstra, A* does not make sense with variable distanced nodes.
if (!openlist)
openlist = spawn();
vector pathlib_walknode(entity this, vector start, vector end, float doedge);
var vector pathlib_movenode(entity this, vector start, vector end, float doedge);
+//float pathlib_expandnode_starf(entity node, vector start, vector goal);
float pathlib_expandnode_star(entity node, vector start, vector goal);
float pathlib_expandnode_box(entity node, vector start, vector goal);
-float pathlib_expandnode_octagon(entity node, vector start, vector goal);
+//float pathlib_expandnode_octagon(entity node, vector start, vector goal);
var float pathlib_expandnode(entity node, vector start, vector goal);
float pathlib_g_static(entity parent, vector to, float static_cost);
var bool buildpath_nodefilter(vector n,vector c,vector p);
var float pathlib_wpp_waypointcallback(entity wp, entity wp_prev);
+
+IntrusiveList g_pathlib_nodes;
+STATIC_INIT(g_pathlib_nodes) { g_pathlib_nodes = IL_NEW(); }
#include "utility.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include "pathlib.qh"
#include <common/effects/all.qh>
#include "bot/api.qh"
#include "cheats.qh"
+#include "client.qh"
#include "clientkill.qh"
-#include "g_damage.qh"
+#include "damage.qh"
+#include "world.qh"
#include "handicap.qh"
#include "miscfunctions.qh"
#include "portals.qh"
#include "teamplay.qh"
+#include <server/main.qh>
+#include "weapons/common.qh"
#include "weapons/throwing.qh"
#include "command/common.qh"
+#include "command/vote.qh"
#include "../common/state.qh"
#include "../common/anim.qh"
#include "../common/animdecide.qh"
#include "../common/gamemodes/sv_rules.qh"
#include "../common/deathtypes/all.qh"
#include "../common/mapobjects/subs.qh"
+#include <common/mapobjects/teleporters.qh>
#include "../common/playerstats.qh"
#include "../lib/csqcmodel/sv_model.qh"
#include "../common/wepent.qh"
#include "weapons/weaponstats.qh"
+#include <server/weapons/weaponsystem.qh>
#include "../common/animdecide.qh"
animbits |= ANIMSTATE_FROZEN;
if(this.move_movetype == MOVETYPE_FOLLOW)
animbits |= ANIMSTATE_FOLLOW;
- if(this.crouch)
+ if(IS_DUCKED(this))
animbits |= ANIMSTATE_DUCK;
animdecide_setstate(this, animbits, false);
animdecide_setimplicitstate(this, IS_ONGROUND(this));
}
}
-void calculate_player_respawn_time(entity this)
-{
- if(MUTATOR_CALLHOOK(CalculateRespawnTime, this))
- return;
-
- float gametype_setting_tmp;
- float sdelay_max = GAMETYPE_DEFAULTED_SETTING(respawn_delay_max);
- float sdelay_small = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small);
- float sdelay_large = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large);
- float sdelay_small_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_small_count);
- float sdelay_large_count = GAMETYPE_DEFAULTED_SETTING(respawn_delay_large_count);
- float waves = GAMETYPE_DEFAULTED_SETTING(respawn_waves);
-
- float pcount = 1; // Include myself whether or not team is already set right and I'm a "player".
- if (teamplay)
- {
- FOREACH_CLIENT(IS_PLAYER(it) && it != this, {
- if(it.team == this.team)
- ++pcount;
- });
- if (sdelay_small_count == 0)
- sdelay_small_count = 1;
- if (sdelay_large_count == 0)
- sdelay_large_count = 1;
- }
- else
- {
- FOREACH_CLIENT(IS_PLAYER(it) && it != this, {
- ++pcount;
- });
- if (sdelay_small_count == 0)
- {
- if (IS_INDEPENDENT_PLAYER(this))
- {
- // Players play independently. No point in requiring enemies.
- sdelay_small_count = 1;
- }
- else
- {
- // Players play AGAINST each other. Enemies required.
- sdelay_small_count = 2;
- }
- }
- if (sdelay_large_count == 0)
- {
- if (IS_INDEPENDENT_PLAYER(this))
- {
- // Players play independently. No point in requiring enemies.
- sdelay_large_count = 1;
- }
- else
- {
- // Players play AGAINST each other. Enemies required.
- sdelay_large_count = 2;
- }
- }
- }
-
- float sdelay;
-
- if (pcount <= sdelay_small_count)
- sdelay = sdelay_small;
- else if (pcount >= sdelay_large_count)
- sdelay = sdelay_large;
- else // NOTE: this case implies sdelay_large_count > sdelay_small_count.
- sdelay = sdelay_small + (sdelay_large - sdelay_small) * (pcount - sdelay_small_count) / (sdelay_large_count - sdelay_small_count);
-
- if(waves)
- this.respawn_time = ceil((time + sdelay) / waves) * waves;
- else
- this.respawn_time = time + sdelay;
-
- if(sdelay < sdelay_max)
- this.respawn_time_max = time + sdelay_max;
- else
- this.respawn_time_max = this.respawn_time;
-
- if((sdelay + waves >= 5.0) && (this.respawn_time - time > 1.75))
- this.respawn_countdown = 10; // first number to count down from is 10
- else
- this.respawn_countdown = -1; // do not count down
-
- if(autocvar_g_forced_respawn)
- this.respawn_flags = this.respawn_flags | RESPAWN_FORCE;
-}
-
void PlayerDamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force)
{
vector v;
.float pushltime;
.bool istypefrag;
+.float death_time;
+
.float CopyBody_nextthink;
.void(entity this) CopyBody_think;
void CopyBody_Think(entity this);
void PlayerCorpseDamage(entity this, entity inflictor, entity attacker, float damage, int deathtype, .entity weaponentity, vector hitloc, vector force);
-// g_<gametype>_str:
-// If 0, default is used.
-// If <0, 0 is used.
-// Otherwise, g_str (default value) is used.
-// For consistency, negative values there are mapped to zero too.
-#define GAMETYPE_DEFAULTED_SETTING(str) \
- ((gametype_setting_tmp = cvar(strcat("g_", GetGametype(), "_" #str))), \
- (gametype_setting_tmp < 0) ? 0 \
- : (gametype_setting_tmp == 0 || autocvar_g_respawn_delay_forced) ? max(0, autocvar_g_##str) \
- : gametype_setting_tmp)
-
-void calculate_player_respawn_time(entity this);
-
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);
+
+IntrusiveList g_clones;
+STATIC_INIT(g_clones) { g_clones = IL_NEW(); }
#include "portals.qh"
#include <common/effects/all.qh>
-#include "g_hook.qh"
+#include "hook.qh"
#include "mutators/_mod.qh"
+#include <server/client.qh>
+#include <server/weapons/common.qh>
#include "../common/constants.qh"
#include "../common/deathtypes/all.qh"
#include "../common/notifications/all.qh"
#include "../common/mapobjects/teleporters.qh"
+#include <common/mapobjects/triggers.qh>
#include "../common/mapobjects/subs.qh"
#include "../common/util.qh"
#include <common/weapons/_all.qh>
#include "../lib/warpzone/common.qh"
#include "../common/vehicles/vehicle.qh"
#include "../common/vehicles/sv_vehicles.qh"
+#include <common/weapons/weapon/porto.qh>
#include <server/player.qh>
+#include <server/damage.qh>
#define PORTALS_ARE_NOT_SOLID
#include "race.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/damage.qh>
+#include <server/world.qh>
#include <server/miscfunctions.qh>
+#include <server/weapons/common.qh>
#include "client.qh"
+#include "cheats.qh"
#include "portals.qh"
#include "scores.qh"
#include "spawnpoints.qh"
#pragma once
+.string stored_netname; // TODO: store this information independently of race-based gamemodes
+
float race_teams;
// scores
#include "round_handler.qh"
-#include <server/defs.qh>
+#include <server/world.qh>
#include <server/miscfunctions.qh>
#include "campaign.qh"
#include "command/vote.qh"
+#include <common/mapobjects/triggers.qh>
#include "../common/util.qh"
void round_handler_Think(entity this)
#include "scores.qh"
#include "command/common.qh"
-#include "defs.qh"
-#include <server/g_world.qh>
+#include <common/weapons/_all.qh>
+#include "client.qh"
+#include <server/world.qh>
#include <server/miscfunctions.qh>
#include <server/mutators/_mod.qh>
#include <server/round_handler.qh>
#include "scores_rules.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
#include "client.qh"
#include "scores.qh"
#include "spawnpoints.qh"
#include <server/mutators/_mod.qh>
-#include "g_world.qh"
+#include "world.qh"
#include "miscfunctions.qh"
#include "race.qh"
-#include "defs.qh"
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include "../common/constants.qh"
#include <common/net_linked.qh>
#include "../common/teams.qh"
#include <common/gamemodes/_mod.qh>
#include "../common/mapobjects/subs.qh"
#include "../common/mapobjects/target/spawnpoint.qh"
+#include <common/mapobjects/triggers.qh>
#include "../common/util.qh"
#include "../lib/warpzone/common.qh"
#include "../lib/warpzone/util_server.qh"
#include <server/utils.qh>
+#include <server/command/vote.qh>
bool SpawnPoint_Send(entity this, entity to, int sf)
{
const int SPAWN_PRIO_RACE_PREVIOUS_SPAWN = 50;
const int SPAWN_PRIO_GOOD_DISTANCE = 10;
+bool some_spawn_has_been_used;
+int have_team_spawns; // 0 = no team spawns requested, -1 = team spawns requested but none found, 1 = team spawns requested and found
+int have_team_spawns_forteams; // if Xth bit is 1 then team X has spawns else it has no spawns; team 0 is the "no-team"
+
.vector spawnpoint_score;
float spawnpoint_nag;
bool SpawnEvent_Send(entity this, entity to, int sf);
entity SelectSpawnPoint(entity this, bool anypoint);
spawnfunc(info_player_deathmatch);
void spawnpoint_use(entity this, entity actor, entity trigger);
+
+USING(spawn_evalfunc_t, vector(entity this, entity player, entity spot, vector current));
+.spawn_evalfunc_t spawn_evalfunc;
+
+.int restriction;
+
+IntrusiveList g_spawnpoints;
+STATIC_INIT(g_spawnpoints) { g_spawnpoints = IL_NEW(); }
+++ /dev/null
-#include "sv_main.qh"
-
-#include "anticheat.qh"
-#include "g_hook.qh"
-#include "g_damage.qh"
-#include "g_world.qh"
-#include <server/gamelog.qh>
-
-#include "bot/api.qh"
-
-#include "command/common.qh"
-
-#include <server/mutators/_mod.qh>
-#include "weapons/csqcprojectile.qh"
-#include <server/compat/quake3.qh>
-
-#include "../common/constants.qh"
-#include "../common/deathtypes/all.qh"
-#include "../common/debug.qh"
-#include "../common/mapinfo.qh"
-#include "../common/util.qh"
-
-#include "../common/vehicles/all.qh"
-#include <common/monsters/sv_monsters.qh>
-#include <common/weapons/_all.qh>
-
-#include "../lib/csqcmodel/sv_model.qh"
-
-#include "../lib/warpzone/common.qh"
-#include "../lib/warpzone/server.qh"
-
-void CreatureFrame_hotliquids(entity this)
-{
- if (this.dmgtime >= time)
- {
- return;
- }
-
- this.dmgtime = time + autocvar_g_balance_contents_damagerate;
-
- if (this.flags & FL_PROJECTILE)
- {
- if (this.watertype == CONTENT_LAVA)
- Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
- else if (this.watertype == CONTENT_SLIME)
- Damage (this, NULL, NULL, autocvar_g_balance_contents_projectiledamage * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
- }
- else
- {
- if (STAT(FROZEN, this))
- {
- if (this.watertype == CONTENT_LAVA)
- Damage(this, NULL, NULL, 10000, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
- else if (this.watertype == CONTENT_SLIME)
- Damage(this, NULL, NULL, 10000, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
- }
- else if (this.watertype == CONTENT_LAVA)
- {
- if (this.watersound_finished < time)
- {
- this.watersound_finished = time + 0.5;
- sound (this, CH_PLAYER_SINGLE, SND_LAVA, VOL_BASE, ATTEN_NORM);
- }
- Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_lava * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_LAVA.m_id, DMG_NOWEP, this.origin, '0 0 0');
- if(autocvar_g_balance_contents_playerdamage_lava_burn)
- Fire_AddDamage(this, NULL, autocvar_g_balance_contents_playerdamage_lava_burn * this.waterlevel, autocvar_g_balance_contents_playerdamage_lava_burn_time * this.waterlevel, DEATH_LAVA.m_id);
- }
- else if (this.watertype == CONTENT_SLIME)
- {
- if (this.watersound_finished < time)
- {
- this.watersound_finished = time + 0.5;
- sound (this, CH_PLAYER_SINGLE, SND_SLIME, VOL_BASE, ATTEN_NORM);
- }
- Damage (this, NULL, NULL, autocvar_g_balance_contents_playerdamage_slime * autocvar_g_balance_contents_damagerate * this.waterlevel, DEATH_SLIME.m_id, DMG_NOWEP, this.origin, '0 0 0');
- }
- }
-}
-
-void CreatureFrame_Liquids(entity this)
-{
- if (this.watertype <= CONTENT_WATER && this.waterlevel > 0) // workaround a retarded bug made by id software :P (yes, it's that old of a bug)
- {
- if (!(this.flags & FL_INWATER))
- {
- this.flags |= FL_INWATER;
- this.dmgtime = 0;
- }
-
- CreatureFrame_hotliquids(this);
- }
- else
- {
- if (this.flags & FL_INWATER)
- {
- // play leave water sound
- this.flags &= ~FL_INWATER;
- this.dmgtime = 0;
- }
- }
-}
-
-void CreatureFrame_FallDamage(entity this)
-{
- if(IS_VEHICLE(this) || (this.flags & FL_PROJECTILE))
- return; // vehicles and projectiles don't receive fall damage
- if(!(this.velocity || this.oldvelocity))
- return; // if the entity hasn't moved and isn't moving, then don't do anything
-
- // check for falling damage
- bool have_hook = false;
- for(int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
- {
- .entity weaponentity = weaponentities[slot];
- if(this.(weaponentity).hook && this.(weaponentity).hook.state)
- {
- have_hook = true;
- break;
- }
- }
- if(!have_hook)
- {
- float dm; // dm is the velocity DECREASE. Velocity INCREASE should never cause a sound or any damage.
- if(autocvar_g_balance_falldamage_onlyvertical)
- dm = fabs(this.oldvelocity.z) - vlen(this.velocity);
- else
- dm = vlen(this.oldvelocity) - vlen(this.velocity);
- if (IS_DEAD(this))
- dm = (dm - autocvar_g_balance_falldamage_deadminspeed) * autocvar_g_balance_falldamage_factor;
- else
- dm = min((dm - autocvar_g_balance_falldamage_minspeed) * autocvar_g_balance_falldamage_factor, autocvar_g_balance_falldamage_maxdamage);
- if (dm > 0)
- {
- tracebox(this.origin, this.mins, this.maxs, this.origin - '0 0 1', MOVE_NOMONSTERS, this);
- if (!(trace_dphitq3surfaceflags & Q3SURFACEFLAG_NODAMAGE))
- Damage (this, NULL, NULL, dm, DEATH_FALL.m_id, DMG_NOWEP, this.origin, '0 0 0');
- }
- }
-
- if(autocvar_g_maxspeed > 0 && vdist(this.velocity, >, autocvar_g_maxspeed))
- Damage (this, NULL, NULL, 100000, DEATH_SHOOTING_STAR.m_id, DMG_NOWEP, this.origin, '0 0 0');
-}
-
-void CreatureFrame_All()
-{
- if(game_stopped || time < game_starttime)
- return;
-
- IL_EACH(g_damagedbycontents, it.damagedbycontents,
- {
- if (it.move_movetype == MOVETYPE_NOCLIP) continue;
- CreatureFrame_Liquids(it);
- CreatureFrame_FallDamage(it);
- it.oldvelocity = it.velocity;
- });
-}
-
-void Pause_TryPause(bool ispaused)
-{
- int n = 0;
- FOREACH_CLIENT(IS_PLAYER(it) && IS_REAL_CLIENT(it), {
- if (PHYS_INPUT_BUTTON_CHAT(it) != ispaused) return;
- ++n;
- });
- if (!n) return;
- setpause(ispaused);
-}
-
-void SV_PausedTic(float elapsedtime)
-{
- if (!server_is_dedicated) Pause_TryPause(false);
-}
-
-/*
-=============
-StartFrame
-
-Called before each frame by the server
-=============
-*/
-
-bool game_delay_last;
-
-bool autocvar_sv_autopause = false;
-void systems_update();
-void sys_phys_update(entity this, float dt);
-void StartFrame()
-{
- // TODO: if move is more than 50ms, split it into two moves (this matches QWSV behavior and the client prediction)
- IL_EACH(g_players, IS_FAKE_CLIENT(it), sys_phys_update(it, frametime));
- IL_EACH(g_players, IS_FAKE_CLIENT(it), PlayerPreThink(it));
-
- execute_next_frame();
- if (autocvar_sv_autopause && !server_is_dedicated) Pause_TryPause(true);
-
- delete_fn = remove_unsafely; // not during spawning!
- serverprevtime = servertime;
- servertime = time;
- serverframetime = frametime;
-
-#ifdef PROFILING
- if(time > client_cefc_accumulatortime + 1)
- {
- float t = client_cefc_accumulator / (time - client_cefc_accumulatortime);
- int c_seeing = 0;
- int c_seen = 0;
- FOREACH_CLIENT(true, {
- if(IS_REAL_CLIENT(it))
- ++c_seeing;
- if(IS_PLAYER(it))
- ++c_seen;
- });
- LOG_INFO(
- "CEFC time: ", ftos(t * 1000), "ms; ",
- "CEFC calls per second: ", ftos(c_seeing * (c_seen - 1) / t), "; ",
- "CEFC 100% load at: ", ftos(solve_quadratic(t, -t, -1) * '0 1 0')
- );
- client_cefc_accumulatortime = time;
- client_cefc_accumulator = 0;
- }
-#endif
-
- IL_EACH(g_projectiles, it.csqcprojectile_clientanimate, CSQCProjectile_Check(it));
-
- if (RedirectionThink()) return;
-
- UncustomizeEntitiesRun();
- InitializeEntitiesRun();
-
- WarpZone_StartFrame();
-
- sys_frametime = autocvar_sys_ticrate * autocvar_slowmo;
- if (sys_frametime <= 0) sys_frametime = 1.0 / 60.0; // somewhat safe fallback
-
- if (timeout_status == TIMEOUT_LEADTIME) // just before the timeout (when timeout_status will be TIMEOUT_ACTIVE)
- orig_slowmo = autocvar_slowmo; // slowmo will be restored after the timeout
-
- // detect when the pre-game countdown (if any) has ended and the game has started
- bool game_delay = (time < game_starttime);
- if (autocvar_sv_eventlog && game_delay_last && !game_delay)
- GameLogEcho(":startdelay_ended");
- game_delay_last = game_delay;
-
- CreatureFrame_All();
- CheckRules_World();
-
- if (warmup_stage && !game_stopped && warmup_limit > 0 && time >= warmup_limit) {
- ReadyRestart();
- return;
- }
-
- bot_serverframe();
- anticheat_startframe();
- MUTATOR_CALLHOOK(SV_StartFrame);
-
- GlobalStats_updateglobal();
- FOREACH_CLIENT(true, GlobalStats_update(it));
- IL_EACH(g_players, IS_FAKE_CLIENT(it), PlayerPostThink(it));
-}
-
-.vector originjitter;
-.vector anglesjitter;
-.float anglejitter;
-.string gametypefilter;
-.string cvarfilter;
-
-/**
- * Evaluate an expression of the form: [+ | -]? [var[op]val | [op]var | val | var] ...
- * +: all must match. this is the default
- * -: one must NOT match
- *
- * var>x
- * var<x
- * var>=x
- * var<=x
- * var==x
- * var!=x
- * var===x
- * var!==x
- */
-bool expr_evaluate(string s)
-{
- bool ret = false;
- if (str2chr(s, 0) == '+') {
- s = substring(s, 1, -1);
- } else if (str2chr(s, 0) == '-') {
- ret = true;
- s = substring(s, 1, -1);
- }
- bool expr_fail = false;
- for (int i = 0, n = tokenize_console(s); i < n; ++i) {
- int o;
- string k, v;
- s = argv(i);
- #define X(expr) \
- if (expr) \
- continue; \
- expr_fail = true; \
- break;
-
- #define BINOP(op, len, expr) \
- if ((o = strstrofs(s, op, 0)) >= 0) { \
- k = substring(s, 0, o); \
- v = substring(s, o + len, -1); \
- X(expr); \
- }
- BINOP(">=", 2, cvar(k) >= stof(v));
- BINOP("<=", 2, cvar(k) <= stof(v));
- BINOP(">", 1, cvar(k) > stof(v));
- BINOP("<", 1, cvar(k) < stof(v));
- BINOP("==", 2, cvar(k) == stof(v));
- BINOP("!=", 2, cvar(k) != stof(v));
- BINOP("===", 3, cvar_string(k) == v);
- BINOP("!==", 3, cvar_string(k) != v);
- {
- k = s;
- bool b = true;
- if (str2chr(k, 0) == '!') {
- k = substring(s, 1, -1);
- b = false;
- }
- float f = stof(k);
- bool isnum = ftos(f) == k;
- X(boolean(isnum ? f : cvar(k)) == b);
- }
- #undef BINOP
- #undef X
- }
- if (!expr_fail) {
- ret = !ret;
- }
- // now ret is true if we want to keep the item, and false if we want to get rid of it
- return ret;
-}
-
-void SV_OnEntityPreSpawnFunction(entity this)
-{
- if (this)
- if (this.gametypefilter != "")
- if (!isGametypeInFilter(MapInfo_LoadedGametype, teamplay, have_team_spawns, this.gametypefilter))
- {
- delete(this);
- return;
- }
- if (this.cvarfilter != "" && !expr_evaluate(this.cvarfilter)) {
- delete(this);
- return;
- }
-
- if (DoesQ3ARemoveThisEntity(this)) {
- delete(this);
- return;
- }
-
- set_movetype(this, this.movetype);
-
- if (this.monster_attack) {
- IL_PUSH(g_monster_targets, this);
- }
-
- // support special -1 and -2 angle from radiant
- if (this.angles == '0 -1 0') {
- this.angles = '-90 0 0';
- } else if (this.angles == '0 -2 0') {
- this.angles = '+90 0 0';
- }
-
- #define X(out, in) MACRO_BEGIN \
- if (in != 0) { out = out + (random() * 2 - 1) * in; } \
- MACRO_END
- X(this.origin.x, this.originjitter.x); X(this.origin.y, this.originjitter.y); X(this.origin.z, this.originjitter.z);
- X(this.angles.x, this.anglesjitter.x); X(this.angles.y, this.anglesjitter.y); X(this.angles.z, this.anglesjitter.z);
- X(this.angles.y, this.anglejitter);
- #undef X
-
- if (MUTATOR_CALLHOOK(OnEntityPreSpawn, this)) {
- delete(this);
- return;
- }
-}
-
-void WarpZone_PostInitialize_Callback()
-{
- // create waypoint links for warpzones
- entity tracetest_ent = spawn();
- setsize(tracetest_ent, PL_MIN_CONST, PL_MAX_CONST);
- tracetest_ent.dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_PLAYERCLIP | DPCONTENTS_BOTCLIP;
- //for(entity e = warpzone_first; e; e = e.warpzone_next)
- for(entity e = NULL; (e = find(e, classname, "trigger_warpzone")); )
- waypoint_spawnforteleporter_wz(e, tracetest_ent);
- delete(tracetest_ent);
-}
-
-/*
-==================
-main
-
-unused but required by the engine
-==================
-*/
-void main ()
-{
-
-}
+++ /dev/null
-#pragma once
-
-bool expr_evaluate(string s);
-
-#ifdef PROFILING
-float client_cefc_accumulator;
-float client_cefc_accumulatortime;
-#endif
-
-/*
-==================
-main
-
-unused but required by the engine
-==================
-*/
-void main ();
#undef IT_SUIT
#undef IT_QUAD
+#undef STATE_TOP
+#undef STATE_BOTTOM
+#undef STATE_UP
+#undef STATE_DOWN
+
#pragma noref 0
#define IT_SUIT _IT_SUIT /* BIT(21) */
#define IT_QUAD _IT_QUAD /* BIT(22) */
+#define STATE_TOP _STATE_TOP /* 0 */
+#define STATE_BOTTOM _STATE_BOTTOM /* 1 */
+#define STATE_UP _STATE_UP /* 2 */
+#define STATE_DOWN _STATE_DOWN /* 3 */
+
#pragma noref 1
#include "client.qh"
#include <server/gamelog.qh>
+#include <server/damage.qh>
#include "race.qh"
#include "scores.qh"
#include "scores_rules.qh"
#pragma once
-#include "defs.qh"
#include "miscfunctions.qh"
#include "autocvars.qh"
#include "client.qh"
#include "weapons/common.qh"
#include "weapons/selection.qh"
#include <common/items/item.qh>
+#include <common/mapobjects/defs.qh>
#include <common/physics/player.qh>
#include <common/weapons/_all.qh>
#include <common/vehicles/all.qh>
#include "accuracy.qh"
+#include <server/client.qh>
#include <server/mutators/_mod.qh>
+#include <server/damage.qh>
#include <common/constants.qh>
#include <common/net_linked.qh>
+#include <server/player.qh>
#include <common/teams.qh>
#include <common/util.qh>
#include <common/weapons/_all.qh>
#pragma once
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
.bool cvar_cl_accuracy_data_share;
#include "common.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/damage.qh>
+#include <server/items/items.qh>
#include <server/miscfunctions.qh>
-#include <common/t_items.qh>
#include <common/constants.qh>
#include <common/net_linked.qh>
#include <common/deathtypes/all.qh>
void W_PlayStrengthSound(entity player);
float W_CheckProjectileDamage(entity inflictor, entity projowner, int deathtype, float exception);
void W_PrepareExplosionByDamage(entity this, entity attacker, void(entity this) explode);
+
+.float misc_bulletcounter;
+
+.int projectiledeathtype;
+
+.float fade_time;
+.float fade_rate;
+
+.entity realowner;
+
+#define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_CORPSE; (e).dphitcontentsmask = DPCONTENTS_SOLID | DPCONTENTS_BODY | DPCONTENTS_CORPSE
+// when doing this, hagar can go through clones
+// #define PROJECTILE_MAKETRIGGER(e) (e).solid = SOLID_BBOX
+
+.int missile_flags;
+const int MIF_SPLASH = BIT(1);
+const int MIF_ARC = BIT(2);
+const int MIF_PROXY = BIT(3);
+const int MIF_GUIDED_MANUAL = BIT(4);
+const int MIF_GUIDED_HEAT = BIT(5);
+const int MIF_GUIDED_LASER = BIT(6);
+const int MIF_GUIDED_AI = BIT(7);
+const int MIF_GUIDED_TAG = BIT(7);
+const int MIF_GUIDED_ALL = MIF_GUIDED_MANUAL | MIF_GUIDED_HEAT | MIF_GUIDED_LASER | MIF_GUIDED_AI | MIF_GUIDED_TAG;
+const int MIF_GUIDED_TRACKING = MIF_GUIDED_HEAT | MIF_GUIDED_LASER | MIF_GUIDED_AI | MIF_GUIDED_TAG;
+const int MIF_GUIDED_CONFUSABLE = MIF_GUIDED_HEAT | MIF_GUIDED_AI;
+
+IntrusiveList g_projectiles;
+STATIC_INIT(g_projectiles) { g_projectiles = IL_NEW(); }
#include "csqcprojectile.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/items/items.qh>
#include <server/miscfunctions.qh>
-#include <common/t_items.qh>
#include "../command/common.qh"
#include "hitplot.qh"
-#include <server/defs.qh>
+#include <server/client.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
+#include <server/world.qh>
#include <server/miscfunctions.qh>
#include "../antilag.qh"
#include <common/weapons/_all.qh>
#include "selection.qh"
#include "weaponsystem.qh"
-#include <common/t_items.qh>
-#include <server/items.qh>
+#include <server/items/items.qh>
+#include <server/items/spawning.qh>
#include <common/constants.qh>
#include <common/net_linked.qh>
#include <common/util.qh>
#include <common/items/item.qh>
#include <common/weapons/_all.qh>
+#include <common/replicate.qh>
#include <common/state.qh>
+#include <common/mapobjects/triggers.qh>
#include <common/mutators/mutator/waypoints/waypointsprites.qh>
#include <common/wepent.qh>
#pragma once
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
+.int selectweapon; // last selected weapon of the player
+
+.WepSet dual_weapons;
+
// switch between weapons
void Send_WeaponComplain(entity e, float wpn, float type);
#include "weaponsystem.qh"
#include "../resources.qh"
#include <server/mutators/_mod.qh>
-#include <common/t_items.qh>
-#include <server/items.qh>
+#include <server/items/items.qh>
+#include <server/items/spawning.qh>
#include <common/weapons/_all.qh>
.bool m_isreplaced; ///< Holds whether the weapon has been replaced.
#pragma once
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
string W_Apply_Weaponreplace(string in);
#include "weaponsystem.qh"
#include "../resources.qh"
-#include "../items.qh"
+#include <server/items/spawning.qh>
#include <server/mutators/_mod.qh>
-#include <common/t_items.qh>
-#include "../g_damage.qh"
+#include <server/items/items.qh>
+#include "../damage.qh"
#include <common/items/item.qh>
#include <common/mapinfo.qh>
#include <common/notifications/all.qh>
#pragma once
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
.float savenextthink;
#include "hitplot.qh"
#include "weaponsystem.qh"
-#include "../g_damage.qh"
+#include "../damage.qh"
+#include <server/main.qh>
#include "../antilag.qh"
#include <common/constants.qh>
#pragma once
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
vector w_shotorg;
// Ballistics Tracing
// ====================
+.float ballistics_density;
+
+// for railgun damage (hitting multiple enemies)
+.bool railgunhit;
+.float railgunhitsolidbackup;
+.vector railgunhitloc;
+
+IntrusiveList g_railgunhit;
+STATIC_INIT(g_railgunhit) { g_railgunhit = IL_NEW(); }
+
.float railgundistance;
.vector railgunforce;
void FireRailgunBullet (entity this, .entity weaponentity, vector start, vector end, float bdamage, bool headshot_notify, float bforce, float mindist, float maxdist, float halflifedist, float forcehalflifedist, int deathtype);
#include "weaponstats.qh"
-#include <server/defs.qh>
+#include <common/weapons/_all.qh>
+#include <common/stats.qh>
#include <server/miscfunctions.qh>
-#include "../g_world.qh"
+#include "../world.qh"
#include <common/weapons/_all.qh>
#include "selection.qh"
#include "../command/common.qh"
+#include <server/client.qh>
+#include <server/damage.qh>
+#include <server/world.qh>
+#include <server/items/items.qh>
#include <server/mutators/_mod.qh>
#include "../round_handler.qh"
#include <server/cheats.qh>
#include <server/resources.qh>
-#include <common/t_items.qh>
#include <common/animdecide.qh>
#include <common/constants.qh>
+#include <common/items/_mod.qh>
#include <common/net_linked.qh>
+#include <common/mapobjects/platforms.qh>
#include <common/monsters/_mod.qh>
#include <common/notifications/all.qh>
#include <common/util.qh>
#pragma once
-#include <server/defs.qh>
#include <server/miscfunctions.qh>
+#define INDEPENDENT_ATTACK_FINISHED 1
+
+// there is 2 weapon tics that can run in one server frame
+const int W_TICSPERFRAME = 2;
+
+// VorteX: standalone think for weapons, so normal think on weaponentity can be reserved by weaponflashes (which needs update even player dies)
+.float weapon_nextthink;
+.void(Weapon thiswep, entity actor, .entity weaponentity, int fire) weapon_think;
+
float internalteam;
entity weapon_dropevent_item;
+// reset to 0 on weapon switch
+// may be useful to all weapons
+.float bulletcounter;
+
..entity weaponentity_fld;
+.float weapon_load[REGISTRY_MAX(Weapons)];
+.int ammo_none; // used by the reloading system, must always be 0
+.int clip_load;
+.int old_clip_load;
+.int clip_size;
+
+.float attack_finished_for[REGISTRY_MAX(Weapons) * MAX_WEAPONSLOTS];
+.float attack_finished_single[MAX_WEAPONSLOTS];
+#if INDEPENDENT_ATTACK_FINISHED
+#define ATTACK_FINISHED_FOR(ent, w, slot) ((ent).(attack_finished_for[((w) - WEP_FIRST) * MAX_WEAPONSLOTS + (slot)]))
+#else
+#define ATTACK_FINISHED_FOR(ent, w, slot) ((ent).attack_finished_single[slot])
+#endif
+#define ATTACK_FINISHED(ent, w) ATTACK_FINISHED_FOR(ent, ent.(w).m_weapon.m_id, weaponslot(w))
+
void CL_SpawnWeaponentity(entity e, .entity weaponentity);
+void w_clear(Weapon thiswep, entity actor, .entity weaponentity, int fire);
+
+void w_ready(Weapon thiswep, entity actor, .entity weaponentity, int fire);
+
vector CL_Weapon_GetShotOrg(float wpn);
bool weaponUseForbidden(entity player);
--- /dev/null
+#include "world.qh"
+
+#include "anticheat.qh"
+#include "antilag.qh"
+#include "bot/api.qh"
+#include "campaign.qh"
+#include "cheats.qh"
+#include "client.qh"
+#include "command/common.qh"
+#include "command/getreplies.qh"
+#include "command/sv_cmd.qh"
+#include "command/vote.qh"
+#include "hook.qh"
+#include <server/gamelog.qh>
+#include <server/damage.qh>
+#include "ipban.qh"
+#include "mapvoting.qh"
+#include <server/mutators/_mod.qh>
+#include "race.qh"
+#include "scores.qh"
+#include "scores_rules.qh"
+#include "spawnpoints.qh"
+#include "teamplay.qh"
+#include "weapons/weaponstats.qh"
+#include <server/weapons/common.qh>
+#include "../common/constants.qh"
+#include <common/net_linked.qh>
+#include "../common/deathtypes/all.qh"
+#include <common/gamemodes/_mod.qh>
+#include "../common/gamemodes/sv_rules.qh"
+#include "../common/mapinfo.qh"
+#include "../common/monsters/_mod.qh"
+#include "../common/monsters/sv_monsters.qh"
+#include "../common/vehicles/all.qh"
+#include "../common/notifications/all.qh"
+#include "../common/physics/player.qh"
+#include "../common/playerstats.qh"
+#include "../common/stats.qh"
+#include "../common/teams.qh"
+#include <common/mapobjects/triggers.qh>
+#include "../common/mapobjects/trigger/secret.qh"
+#include "../common/mapobjects/target/music.qh"
+#include "../common/util.qh"
+#include "../common/items/_mod.qh"
+#include <common/weapons/_all.qh>
+#include "../common/state.qh"
+
+const float LATENCY_THINKRATE = 10;
+.float latency_sum;
+.float latency_cnt;
+.float latency_time;
+entity pingplreport;
+void PingPLReport_Think(entity this)
+{
+ float delta;
+ entity e;
+
+ delta = 3 / maxclients;
+ if(delta < sys_frametime)
+ delta = 0;
+ this.nextthink = time + delta;
+
+ e = edict_num(this.cnt + 1);
+ if(IS_CLIENT(e) && IS_REAL_CLIENT(e))
+ {
+ WriteHeader(MSG_BROADCAST, TE_CSQC_PINGPLREPORT);
+ WriteByte(MSG_BROADCAST, this.cnt);
+ WriteShort(MSG_BROADCAST, bound(1, CS(e).ping, 65535));
+ WriteByte(MSG_BROADCAST, min(ceil(CS(e).ping_packetloss * 255), 255));
+ WriteByte(MSG_BROADCAST, min(ceil(CS(e).ping_movementloss * 255), 255));
+
+ // record latency times for clients throughout the match so we can report it to playerstats
+ if(time > (CS(e).latency_time + LATENCY_THINKRATE))
+ {
+ CS(e).latency_sum += CS(e).ping;
+ CS(e).latency_cnt += 1;
+ CS(e).latency_time = time;
+ //print("sum: ", ftos(CS(e).latency_sum), ", cnt: ", ftos(CS(e).latency_cnt), ", avg: ", ftos(CS(e).latency_sum / CS(e).latency_cnt), ".\n");
+ }
+ }
+ else
+ {
+ WriteHeader(MSG_BROADCAST, TE_CSQC_PINGPLREPORT);
+ WriteByte(MSG_BROADCAST, this.cnt);
+ WriteShort(MSG_BROADCAST, 0);
+ WriteByte(MSG_BROADCAST, 0);
+ WriteByte(MSG_BROADCAST, 0);
+ }
+ this.cnt = (this.cnt + 1) % maxclients;
+}
+void PingPLReport_Spawn()
+{
+ pingplreport = new_pure(pingplreport);
+ setthink(pingplreport, PingPLReport_Think);
+ pingplreport.nextthink = time;
+}
+
+const float SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS = 1;
+string redirection_target;
+float world_initialized;
+
+void SetDefaultAlpha()
+{
+ if (!MUTATOR_CALLHOOK(SetDefaultAlpha))
+ {
+ default_player_alpha = autocvar_g_player_alpha;
+ if(default_player_alpha == 0)
+ default_player_alpha = 1;
+ default_weapon_alpha = default_player_alpha;
+ }
+}
+
+void GotoFirstMap(entity this)
+{
+ float n;
+ if(autocvar__sv_init)
+ {
+ // cvar_set("_sv_init", "0");
+ // we do NOT set this to 0 any more, so someone "accidentally" changing
+ // to this "init" map on a dedicated server will cause no permanent
+ // harm
+ if(autocvar_g_maplist_shuffle)
+ ShuffleMaplist();
+ n = tokenizebyseparator(autocvar_g_maplist, " ");
+ cvar_set("g_maplist_index", ftos(n - 1)); // jump to map 0 in GotoNextMap
+
+ MapInfo_Enumerate();
+ MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
+
+ if(!DoNextMapOverride(1))
+ GotoNextMap(1);
+
+ return;
+ }
+
+ if(time < 5)
+ {
+ this.nextthink = time;
+ }
+ else
+ {
+ this.nextthink = time + 1;
+ LOG_INFO("Waiting for _sv_init being set to 1 by initialization scripts...");
+ }
+}
+
+void cvar_changes_init()
+{
+ float h;
+ string k, v, d;
+ float n, i, adding, pureadding;
+
+ strfree(cvar_changes);
+ strfree(cvar_purechanges);
+ cvar_purechanges_count = 0;
+
+ h = buf_create();
+ buf_cvarlist(h, "", "_"); // exclude all _ cvars as they are temporary
+ n = buf_getsize(h);
+
+ adding = true;
+ pureadding = true;
+
+ for(i = 0; i < n; ++i)
+ {
+ k = bufstr_get(h, i);
+
+#define BADPREFIX(p) if(substring(k, 0, strlen(p)) == p) continue
+#define BADPRESUFFIX(p,s) if(substring(k, 0, strlen(p)) == p && substring(k, -strlen(s), -1) == s) continue
+#define BADCVAR(p) if(k == p) continue
+
+ // general excludes and namespaces for server admin used cvars
+ BADPREFIX("help_"); // PN's server has this listed as changed, let's not rat him out for THAT
+
+ // internal
+ BADPREFIX("csqc_");
+ BADPREFIX("cvar_check_");
+ BADCVAR("gamecfg");
+ BADCVAR("g_configversion");
+ BADCVAR("halflifebsp");
+ BADCVAR("sv_mapformat_is_quake2");
+ BADCVAR("sv_mapformat_is_quake3");
+ BADPREFIX("sv_world");
+
+ // client
+ BADPREFIX("chase_");
+ BADPREFIX("cl_");
+ BADPREFIX("con_");
+ BADPREFIX("scoreboard_");
+ BADPREFIX("g_campaign");
+ BADPREFIX("g_waypointsprite_");
+ BADPREFIX("gl_");
+ BADPREFIX("joy");
+ BADPREFIX("hud_");
+ BADPREFIX("m_");
+ BADPREFIX("menu_");
+ BADPREFIX("net_slist_");
+ BADPREFIX("r_");
+ BADPREFIX("sbar_");
+ BADPREFIX("scr_");
+ BADPREFIX("snd_");
+ BADPREFIX("show");
+ BADPREFIX("sensitivity");
+ BADPREFIX("userbind");
+ BADPREFIX("v_");
+ BADPREFIX("vid_");
+ BADPREFIX("crosshair");
+ BADCVAR("mod_q3bsp_lightmapmergepower");
+ BADCVAR("mod_q3bsp_nolightmaps");
+ BADCVAR("fov");
+ BADCVAR("mastervolume");
+ BADCVAR("volume");
+ BADCVAR("bgmvolume");
+ BADCVAR("in_pitch_min");
+ BADCVAR("in_pitch_max");
+
+ // private
+ BADCVAR("developer");
+ BADCVAR("log_dest_udp");
+ BADCVAR("net_address");
+ BADCVAR("net_address_ipv6");
+ BADCVAR("port");
+ BADCVAR("savedgamecfg");
+ BADCVAR("serverconfig");
+ BADCVAR("sv_autoscreenshot");
+ BADCVAR("sv_heartbeatperiod");
+ BADCVAR("sv_vote_master_password");
+ BADCVAR("sys_colortranslation");
+ BADCVAR("sys_specialcharactertranslation");
+ BADCVAR("timeformat");
+ BADCVAR("timestamps");
+ BADCVAR("g_require_stats");
+ BADPREFIX("developer_");
+ BADPREFIX("g_ban_");
+ BADPREFIX("g_banned_list");
+ BADPREFIX("g_require_stats_");
+ BADPREFIX("g_chat_flood_");
+ BADPREFIX("g_ghost_items");
+ BADPREFIX("g_playerstats_");
+ BADPREFIX("g_voice_flood_");
+ BADPREFIX("log_file");
+ BADPREFIX("quit_");
+ BADPREFIX("rcon_");
+ BADPREFIX("sv_allowdownloads");
+ BADPREFIX("sv_autodemo");
+ BADPREFIX("sv_curl_");
+ BADPREFIX("sv_eventlog");
+ BADPREFIX("sv_logscores_");
+ BADPREFIX("sv_master");
+ BADPREFIX("sv_weaponstats_");
+ BADPREFIX("sv_waypointsprite_");
+ BADCVAR("rescan_pending");
+
+ // these can contain player IDs, so better hide
+ BADPREFIX("g_forced_team_");
+ BADCVAR("sv_muteban_list");
+ BADCVAR("sv_voteban_list");
+ BADCVAR("sv_allow_customplayermodels_idlist");
+ BADCVAR("sv_allow_customplayermodels_speciallist");
+
+ // mapinfo
+ BADCVAR("fraglimit");
+ BADCVAR("g_arena");
+ BADCVAR("g_assault");
+ BADCVAR("g_ca");
+ BADCVAR("g_ca_teams");
+ BADCVAR("g_conquest");
+ BADCVAR("g_conquest_teams");
+ BADCVAR("g_ctf");
+ BADCVAR("g_cts");
+ BADCVAR("g_dotc");
+ BADCVAR("g_dm");
+ BADCVAR("g_domination");
+ BADCVAR("g_domination_default_teams");
+ BADCVAR("g_duel");
+ BADCVAR("g_duel_not_dm_maps");
+ BADCVAR("g_freezetag");
+ BADCVAR("g_freezetag_teams");
+ BADCVAR("g_invasion_teams");
+ BADCVAR("g_invasion_type");
+ BADCVAR("g_jailbreak");
+ BADCVAR("g_jailbreak_teams");
+ BADCVAR("g_keepaway");
+ BADCVAR("g_keyhunt");
+ BADCVAR("g_keyhunt_teams");
+ BADCVAR("g_lms");
+ BADCVAR("g_nexball");
+ BADCVAR("g_onslaught");
+ BADCVAR("g_race");
+ BADCVAR("g_race_laps_limit");
+ BADCVAR("g_race_qualifying_timelimit");
+ BADCVAR("g_race_qualifying_timelimit_override");
+ BADCVAR("g_runematch");
+ BADCVAR("g_shootfromeye");
+ BADCVAR("g_snafu");
+ BADCVAR("g_survival");
+ BADCVAR("g_survival_not_dm_maps");
+ BADCVAR("g_tdm");
+ BADCVAR("g_tdm_on_dm_maps");
+ BADCVAR("g_tdm_teams");
+ BADCVAR("g_vip");
+ BADCVAR("leadlimit");
+ BADCVAR("nextmap");
+ BADCVAR("teamplay");
+ BADCVAR("timelimit");
+ BADCVAR("g_mapinfo_settemp_acl");
+ BADCVAR("g_mapinfo_ignore_warnings");
+ BADCVAR("g_maplist_ignore_sizes");
+ BADCVAR("g_maplist_sizes_count_bots");
+
+ // long
+ BADCVAR("hostname");
+ BADCVAR("g_maplist");
+ BADCVAR("g_maplist_mostrecent");
+ BADCVAR("sv_motd");
+
+ v = cvar_string(k);
+ d = cvar_defstring(k);
+ if(v == d)
+ continue;
+
+ if(adding)
+ {
+ cvar_changes = strcat(cvar_changes, k, " \"", v, "\" // \"", d, "\"\n");
+ if(strlen(cvar_changes) > 16384)
+ {
+ cvar_changes = "// too many settings have been changed to show them here\n";
+ adding = 0;
+ }
+ }
+
+ // now check if the changes are actually gameplay relevant
+
+ // does nothing gameplay relevant
+ BADCVAR("captureleadlimit_override");
+ BADCVAR("condump_stripcolors");
+ BADCVAR("gameversion");
+ BADCVAR("fs_gamedir");
+ BADCVAR("g_allow_oldvortexbeam");
+ BADCVAR("g_balance_kill_delay");
+ BADCVAR("g_buffs_pickup_anyway");
+ BADCVAR("g_buffs_randomize");
+ BADCVAR("g_buffs_randomize_teamplay");
+ BADCVAR("g_campcheck_distance");
+ BADCVAR("g_chatsounds");
+ BADCVAR("g_ca_point_leadlimit");
+ BADCVAR("g_ca_point_limit");
+ BADCVAR("g_ctf_captimerecord_always");
+ BADCVAR("g_ctf_flag_glowtrails");
+ BADCVAR("g_ctf_dynamiclights");
+ BADCVAR("g_ctf_flag_pickup_verbosename");
+ BADPRESUFFIX("g_ctf_flag_", "_model");
+ BADPRESUFFIX("g_ctf_flag_", "_skin");
+ BADCVAR("g_domination_point_leadlimit");
+ BADCVAR("g_forced_respawn");
+ BADCVAR("g_freezetag_point_leadlimit");
+ BADCVAR("g_freezetag_point_limit");
+ BADCVAR("g_glowtrails");
+ BADCVAR("g_hats");
+ BADCVAR("g_casings");
+ BADCVAR("g_invasion_point_limit");
+ BADCVAR("g_jump_grunt");
+ BADCVAR("g_keepaway_ballcarrier_effects");
+ BADCVAR("g_keepawayball_effects");
+ BADCVAR("g_keyhunt_point_leadlimit");
+ BADCVAR("g_nexball_goalleadlimit");
+ BADCVAR("g_new_toys_autoreplace");
+ BADCVAR("g_new_toys_use_pickupsound");
+ BADCVAR("g_physics_predictall");
+ BADCVAR("g_piggyback");
+ BADCVAR("g_playerclip_collisions");
+ BADCVAR("g_spawn_alloweffects");
+ BADCVAR("g_tdm_point_leadlimit");
+ BADCVAR("g_tdm_point_limit");
+ BADCVAR("leadlimit_and_fraglimit");
+ BADCVAR("leadlimit_override");
+ BADCVAR("pausable");
+ BADCVAR("sv_announcer");
+ BADCVAR("sv_checkforpacketsduringsleep");
+ BADCVAR("sv_damagetext");
+ BADCVAR("sv_db_saveasdump");
+ BADCVAR("sv_intermission_cdtrack");
+ BADCVAR("sv_mapchange_delay");
+ BADCVAR("sv_minigames");
+ BADCVAR("sv_namechangetimer");
+ BADCVAR("sv_precacheplayermodels");
+ BADCVAR("sv_radio");
+ BADCVAR("sv_stepheight");
+ BADCVAR("sv_timeout");
+ BADCVAR("sv_weapons_modeloverride");
+ BADCVAR("w_prop_interval");
+ BADPREFIX("chat_");
+ BADPREFIX("crypto_");
+ BADPREFIX("gameversion_");
+ BADPREFIX("g_chat_");
+ BADPREFIX("g_ctf_captimerecord_");
+ BADPREFIX("g_hats_");
+ BADPREFIX("g_maplist_");
+ BADPREFIX("g_mod_");
+ BADPREFIX("g_respawn_");
+ BADPREFIX("net_");
+ BADPREFIX("notification_");
+ BADPREFIX("prvm_");
+ BADPREFIX("skill_");
+ BADPREFIX("sv_allow_");
+ BADPREFIX("sv_cullentities_");
+ BADPREFIX("sv_maxidle_");
+ BADPREFIX("sv_minigames_");
+ BADPREFIX("sv_radio_");
+ BADPREFIX("sv_timeout_");
+ BADPREFIX("sv_vote_");
+ BADPREFIX("timelimit_");
+
+ // allowed changes to server admins (please sync this to server.cfg)
+ // vi commands:
+ // :/"impure"/,$d
+ // :g!,^\/\/[^ /],d
+ // :%s,//\([^ ]*\).*,BADCVAR("\1");,
+ // :%!sort
+ // yes, this does contain some redundant stuff, don't really care
+ BADPREFIX("bot_ai_");
+ BADCVAR("bot_config_file");
+ BADCVAR("bot_number");
+ BADCVAR("bot_prefix");
+ BADCVAR("bot_suffix");
+ BADCVAR("capturelimit_override");
+ BADCVAR("fraglimit_override");
+ BADCVAR("gametype");
+ BADCVAR("g_antilag");
+ BADCVAR("g_balance_teams");
+ BADCVAR("g_balance_teams_prevent_imbalance");
+ BADCVAR("g_balance_teams_scorefactor");
+ BADCVAR("g_ban_sync_trusted_servers");
+ BADCVAR("g_ban_sync_uri");
+ BADCVAR("g_buffs");
+ BADCVAR("g_ca_teams_override");
+ BADCVAR("g_ctf_fullbrightflags");
+ BADCVAR("g_ctf_ignore_frags");
+ BADCVAR("g_ctf_leaderboard");
+ BADCVAR("g_domination_point_limit");
+ BADCVAR("g_domination_teams_override");
+ BADCVAR("g_freezetag_teams_override");
+ BADCVAR("g_friendlyfire");
+ BADCVAR("g_fullbrightitems");
+ BADCVAR("g_fullbrightplayers");
+ BADCVAR("g_keyhunt_point_limit");
+ BADCVAR("g_keyhunt_teams_override");
+ BADCVAR("g_lms_lives_override");
+ BADCVAR("g_maplist");
+ BADCVAR("g_maxplayers");
+ BADCVAR("g_mirrordamage");
+ BADCVAR("g_nexball_goallimit");
+ BADCVAR("g_norecoil");
+ BADCVAR("g_physics_clientselect");
+ BADCVAR("g_pinata");
+ BADCVAR("g_powerups");
+ BADCVAR("g_player_brightness");
+ BADCVAR("g_rocket_flying");
+ BADCVAR("g_rocket_flying_disabledelays");
+ BADCVAR("g_spawnshieldtime");
+ BADCVAR("g_start_delay");
+ BADCVAR("g_superspectate");
+ BADCVAR("g_tdm_teams_override");
+ BADCVAR("g_warmup");
+ BADCVAR("g_weapon_stay"); BADPRESUFFIX("g_", "_weapon_stay");
+ BADCVAR("hostname");
+ BADCVAR("log_file");
+ BADCVAR("maxplayers");
+ BADCVAR("minplayers");
+ BADCVAR("minplayers_per_team");
+ BADCVAR("net_address");
+ BADCVAR("port");
+ BADCVAR("rcon_password");
+ BADCVAR("rcon_restricted_commands");
+ BADCVAR("rcon_restricted_password");
+ BADCVAR("skill");
+ BADCVAR("sv_adminnick");
+ BADCVAR("sv_autoscreenshot");
+ BADCVAR("sv_autotaunt");
+ BADCVAR("sv_curl_defaulturl");
+ BADCVAR("sv_defaultcharacter");
+ BADCVAR("sv_defaultcharacterskin");
+ BADCVAR("sv_defaultplayercolors");
+ BADCVAR("sv_defaultplayermodel");
+ BADCVAR("sv_defaultplayerskin");
+ BADCVAR("sv_maxidle");
+ BADCVAR("sv_maxrate");
+ BADCVAR("sv_motd");
+ BADCVAR("sv_public");
+ BADCVAR("sv_ready_restart");
+ BADCVAR("sv_status_privacy");
+ BADCVAR("sv_taunt");
+ BADCVAR("sv_vote_call");
+ BADCVAR("sv_vote_commands");
+ BADCVAR("sv_vote_majority_factor");
+ BADCVAR("sv_vote_master");
+ BADCVAR("sv_vote_master_commands");
+ BADCVAR("sv_vote_master_password");
+ BADCVAR("sv_vote_simple_majority_factor");
+ BADCVAR("teamplay_mode");
+ BADCVAR("timelimit_override");
+ BADPREFIX("g_warmup_");
+ BADPREFIX("sv_info_");
+ BADPREFIX("sv_ready_restart_");
+
+ // mutators that announce themselves properly to the server browser
+ BADCVAR("g_instagib");
+ BADCVAR("g_new_toys");
+ BADCVAR("g_nix");
+ BADCVAR("g_grappling_hook");
+ BADCVAR("g_jetpack");
+
+ // temporary for testing
+ // TODO remove before 0.8.3 release
+ BADCVAR("g_ca_weaponarena");
+ BADCVAR("g_freezetag_weaponarena");
+ BADCVAR("g_lms_weaponarena");
+ BADCVAR("g_ctf_stalemate_time");
+
+ if(cvar_string("g_mod_balance") == "Testing")
+ {
+ // (temporary) while using the Testing balance, any weapon balance cvars are allowed to be changed
+ BADPREFIX("g_balance_");
+ }
+
+#undef BADPRESUFFIX
+#undef BADPREFIX
+#undef BADCVAR
+
+ if(pureadding)
+ {
+ cvar_purechanges = strcat(cvar_purechanges, k, " \"", v, "\" // \"", d, "\"\n");
+ if(strlen(cvar_purechanges) > 16384)
+ {
+ cvar_purechanges = "// too many settings have been changed to show them here\n";
+ pureadding = 0;
+ }
+ }
+ ++cvar_purechanges_count;
+ // WARNING: this variable is used for the server list
+ // NEVER dare to skip this code!
+ // Hacks to intentionally appearing as "pure server" even though you DO have
+ // modified settings may be punished by removal from the server list.
+ // You can do to the variables cvar_changes and cvar_purechanges all you want,
+ // though.
+ }
+ buf_del(h);
+ if(cvar_changes == "")
+ cvar_changes = "// this server runs at default server settings\n";
+ else
+ cvar_changes = strcat("// this server runs at modified server settings:\n", cvar_changes);
+ cvar_changes = strzone(cvar_changes);
+ if(cvar_purechanges == "")
+ cvar_purechanges = "// this server runs at default gameplay settings\n";
+ else
+ cvar_purechanges = strcat("// this server runs at modified gameplay settings:\n", cvar_purechanges);
+ cvar_purechanges = strzone(cvar_purechanges);
+}
+
+entity randomseed;
+bool RandomSeed_Send(entity this, entity to, int sf)
+{
+ WriteHeader(MSG_ENTITY, ENT_CLIENT_RANDOMSEED);
+ WriteShort(MSG_ENTITY, this.cnt);
+ return true;
+}
+void RandomSeed_Think(entity this)
+{
+ this.cnt = bound(0, floor(random() * 65536), 65535);
+ this.nextthink = time + 5;
+
+ this.SendFlags |= 1;
+}
+void RandomSeed_Spawn()
+{
+ randomseed = new_pure(randomseed);
+ setthink(randomseed, RandomSeed_Think);
+ Net_LinkEntity(randomseed, false, 0, RandomSeed_Send);
+
+ getthink(randomseed)(randomseed); // sets random seed and nextthink
+}
+
+spawnfunc(__init_dedicated_server)
+{
+ // handler for _init/_init map (only for dedicated server initialization)
+
+ world_initialized = -1; // don't complain
+
+ delete_fn = remove_unsafely;
+
+ entity e = spawn();
+ setthink(e, GotoFirstMap);
+ e.nextthink = time; // this is usually 1 at this point
+
+ e = new(info_player_deathmatch); // safeguard against player joining
+
+ // assign reflectively to avoid "assignment to world" warning
+ for (int i = 0, n = numentityfields(); i < n; ++i) {
+ string k = entityfieldname(i);
+ if (k == "classname") {
+ // safeguard against various stuff ;)
+ putentityfieldstring(i, this, "worldspawn");
+ break;
+ }
+ }
+
+ // needs to be done so early because of the constants they create
+ static_init();
+ static_init_late();
+ static_init_precache();
+
+ IL_PUSH(g_spawnpoints, e); // just incase
+
+ MapInfo_Enumerate();
+ MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 0);
+}
+
+void __init_dedicated_server_shutdown() {
+ MapInfo_Shutdown();
+}
+
+STATIC_INIT_EARLY(maxclients)
+{
+ maxclients = 0;
+ for (entity head = nextent(NULL); head; head = nextent(head)) {
+ ++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)
+{
+ server_is_dedicated = boolean(stof(cvar_defstring("is_dedicated")));
+
+ bool wantrestart = false;
+ {
+ if (!server_is_dedicated)
+ {
+ // force unloading of server pk3 files when starting a listen server
+ // localcmd("\nfs_rescan\n"); // FIXME: does more harm than good, has unintended side effects. What we really want is to unload temporary pk3s only
+ // restore csqc_progname too
+ string expect = "csprogs.dat";
+ wantrestart = cvar_string("csqc_progname") != expect;
+ cvar_set("csqc_progname", expect);
+ }
+ else
+ {
+ // Try to use versioned csprogs from pk3
+ // Only ever use versioned csprogs.dat files on dedicated servers;
+ // we need to reset csqc_progname on clients ourselves, and it's easier if the client's release name is constant
+ string pk3csprogs = "csprogs-" WATERMARK ".dat";
+ // This always works; fall back to it if a versioned csprogs.dat is suddenly missing
+ string select = "csprogs.dat";
+ if (fexists(pk3csprogs)) select = pk3csprogs;
+ if (cvar_string("csqc_progname") != select)
+ {
+ cvar_set("csqc_progname", select);
+ wantrestart = true;
+ }
+ // Check for updates on startup
+ // We do it this way for atomicity so that connecting clients still match the server progs and don't disconnect
+ int sentinel = fopen("progs.txt", FILE_READ);
+ if (sentinel >= 0)
+ {
+ string switchversion = fgets(sentinel);
+ fclose(sentinel);
+ if (switchversion != "" && switchversion != WATERMARK)
+ {
+ LOG_INFOF("Switching progs: " WATERMARK " -> %s", switchversion);
+ // if it doesn't exist, assume either:
+ // a) the current program was overwritten
+ // b) this is a client only update
+ string newprogs = sprintf("progs-%s.dat", switchversion);
+ if (fexists(newprogs))
+ {
+ cvar_set("sv_progs", newprogs);
+ wantrestart = true;
+ }
+ string newcsprogs = sprintf("csprogs-%s.dat", switchversion);
+ if (fexists(newcsprogs))
+ {
+ cvar_set("csqc_progname", newcsprogs);
+ wantrestart = true;
+ }
+ }
+ }
+ }
+ if (wantrestart)
+ {
+ LOG_INFO("Restart requested");
+ changelevel(mapname);
+ // let initialization continue, shutdown depends on it
+ }
+ }
+
+ if(world_already_spawned)
+ error("world already spawned - you may have EXACTLY ONE worldspawn!");
+ world_already_spawned = true;
+
+ delete_fn = remove_safely; // during spawning, watch what you remove!
+
+ cvar_changes_init(); // do this very early now so it REALLY matches the server config
+
+ // needs to be done so early because of the constants they create
+ static_init();
+
+ ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
+
+ TemporaryDB = db_create();
+
+ // 0 normal
+ lightstyle(0, "m");
+
+ // 1 FLICKER (first variety)
+ lightstyle(1, "mmnmmommommnonmmonqnmmo");
+
+ // 2 SLOW STRONG PULSE
+ lightstyle(2, "abcdefghijklmnopqrstuvwxyzyxwvutsrqponmlkjihgfedcba");
+
+ // 3 CANDLE (first variety)
+ lightstyle(3, "mmmmmaaaaammmmmaaaaaabcdefgabcdefg");
+
+ // 4 FAST STROBE
+ lightstyle(4, "mamamamamama");
+
+ // 5 GENTLE PULSE 1
+ lightstyle(5,"jklmnopqrstuvwxyzyxwvutsrqponmlkj");
+
+ // 6 FLICKER (second variety)
+ lightstyle(6, "nmonqnmomnmomomno");
+
+ // 7 CANDLE (second variety)
+ lightstyle(7, "mmmaaaabcdefgmmmmaaaammmaamm");
+
+ // 8 CANDLE (third variety)
+ lightstyle(8, "mmmaaammmaaammmabcdefaaaammmmabcdefmmmaaaa");
+
+ // 9 SLOW STROBE (fourth variety)
+ lightstyle(9, "aaaaaaaazzzzzzzz");
+
+ // 10 FLUORESCENT FLICKER
+ lightstyle(10, "mmamammmmammamamaaamammma");
+
+ // 11 SLOW PULSE NOT FADE TO BLACK
+ lightstyle(11, "abcdefghijklmnopqrrqponmlkjihgfedcba");
+
+ // styles 32-62 are assigned by the spawnfunc_light program for switchable lights
+
+ // 63 testing
+ lightstyle(63, "a");
+
+ if(autocvar_g_campaign)
+ CampaignPreInit();
+
+ Map_MarkAsRecent(mapname);
+
+ PlayerStats_GameReport_Init(); // we need this to be initiated before InitGameplayMode
+
+ InitGameplayMode();
+ static_init_late();
+ static_init_precache();
+ readlevelcvars();
+ GrappleHookInit();
+
+ GameRules_limit_fallbacks();
+
+ if(warmup_limit == 0)
+ warmup_limit = (autocvar_timelimit > 0) ? autocvar_timelimit * 60 : autocvar_timelimit;
+
+ player_count = 0;
+ bot_waypoints_for_items = autocvar_g_waypoints_for_items;
+ if(bot_waypoints_for_items == 1)
+ if(this.spawnflags & SPAWNFLAG_NO_WAYPOINTS_FOR_ITEMS)
+ bot_waypoints_for_items = 0;
+
+ WaypointSprite_Init();
+
+ GameLogInit(); // prepare everything
+ // NOTE for matchid:
+ // changing the logic generating it is okay. But:
+ // it HAS to stay <= 64 chars
+ // character set: ASCII 33-126 without the following characters: : ; ' " \ $
+ if(autocvar_sv_eventlog)
+ {
+ string s = sprintf("%s.%s.%06d", itos(autocvar_sv_eventlog_files_counter), strftime(false, "%s"), floor(random() * 1000000));
+ matchid = strzone(s);
+
+ GameLogEcho(strcat(":gamestart:", GetGametype(), "_", GetMapname(), ":", s));
+ s = ":gameinfo:mutators:LIST";
+
+ MUTATOR_CALLHOOK(BuildMutatorsString, s);
+ s = M_ARGV(0, string);
+
+ // initialiation stuff, not good in the mutator system
+ if(!autocvar_g_use_ammunition)
+ s = strcat(s, ":no_use_ammunition");
+
+ // initialiation stuff, not good in the mutator system
+ if(autocvar_g_pickup_items == 0)
+ s = strcat(s, ":no_pickup_items");
+ if(autocvar_g_pickup_items > 0)
+ s = strcat(s, ":pickup_items");
+
+ // initialiation stuff, not good in the mutator system
+ if(autocvar_g_weaponarena != "0")
+ s = strcat(s, ":", autocvar_g_weaponarena, " arena");
+
+ // TODO to mutator system
+ if(autocvar_g_norecoil)
+ s = strcat(s, ":norecoil");
+
+ // TODO to mutator system
+ if(autocvar_g_powerups == 0)
+ s = strcat(s, ":no_powerups");
+ if(autocvar_g_powerups > 0)
+ s = strcat(s, ":powerups");
+
+ GameLogEcho(s);
+ GameLogEcho(":gameinfo:end");
+ }
+ else
+ matchid = strzone(ftos(random()));
+
+ cvar_set("nextmap", "");
+
+ SetDefaultAlpha();
+
+ if(autocvar_g_campaign)
+ CampaignPostInit();
+
+ Ban_LoadBans();
+
+ MapInfo_Enumerate();
+ MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1);
+
+ if(fexists(_MapInfo_FindArenaFile(mapname, ".arena")))
+ cvar_settemp("sv_q3acompat_machineshotgunswap", "1");
+
+ if(fexists(_MapInfo_FindArenaFile(mapname, ".defi")))
+ cvar_settemp("sv_q3defragcompat", "1");
+
+ // quake 3 music support
+ if(world.music || world.noise)
+ {
+ // prefer .music over .noise
+ string chosen_music;
+ string oldstuff;
+ if(world.music)
+ chosen_music = world.music;
+ else
+ chosen_music = world.noise;
+ if(
+ substring(chosen_music, strlen(chosen_music) - 4, 4) == ".wav"
+ ||
+ substring(chosen_music, strlen(chosen_music) - 4, 4) == ".ogg"
+ )
+ oldstuff = strcat(clientstuff, "cd loop \"", chosen_music, "\"\n");
+ else
+ oldstuff = strcat(clientstuff, "cd loop \"", chosen_music, "\"\n");
+
+ strcpy(clientstuff, oldstuff);
+ }
+
+ if(whichpack(strcat("maps/", mapname, ".cfg")) != "")
+ {
+ int fd = fopen(strcat("maps/", mapname, ".cfg"), FILE_READ);
+ if(fd != -1)
+ {
+ string s;
+ while((s = fgets(fd)))
+ {
+ int l = tokenize_console(s);
+ if(l < 2)
+ continue;
+ if(argv(0) == "cd")
+ {
+ string trackname = argv(2);
+ LOG_INFO("Found ^1UNSUPPORTED^7 cd loop command in .cfg file; put this line in mapinfo instead:");
+ LOG_INFO(" cdtrack ", trackname);
+ if (cvar_value_issafe(trackname))
+ {
+ string newstuff = strcat(clientstuff, "cd loop \"", trackname, "\"\n");
+ strcpy(clientstuff, newstuff);
+ }
+ }
+ else if(argv(0) == "fog")
+ {
+ LOG_INFO("Found ^1UNSUPPORTED^7 fog command in .cfg file; put this line in worldspawn in the .map/.bsp/.ent file instead:");
+ LOG_INFO(" \"fog\" \"", s, "\"");
+ }
+ else if(argv(0) == "set")
+ {
+ LOG_INFO("Found ^1UNSUPPORTED^7 set command in .cfg file; put this line in mapinfo instead:");
+ LOG_INFO(" clientsettemp_for_type all ", argv(1), " ", argv(2));
+ }
+ else if(argv(0) != "//")
+ {
+ LOG_INFO("Found ^1UNSUPPORTED^7 set command in .cfg file; put this line in mapinfo instead:");
+ LOG_INFO(" clientsettemp_for_type all ", argv(0), " ", argv(1));
+ }
+ }
+ fclose(fd);
+ }
+ }
+
+ WeaponStats_Init();
+
+ Nagger_Init();
+
+ // set up information replies for clients and server to use
+ maplist_reply = strzone(getmaplist());
+ lsmaps_reply = strzone(getlsmaps());
+ monsterlist_reply = strzone(getmonsterlist());
+ for(int i = 0; i < 10; ++i)
+ {
+ string s = getrecords(i);
+ if (s)
+ records_reply[i] = strzone(s);
+ }
+ ladder_reply = strzone(getladder());
+ rankings_reply = strzone(getrankings());
+
+ // begin other init
+ ClientInit_Spawn();
+ RandomSeed_Spawn();
+ PingPLReport_Spawn();
+
+ CheatInit();
+
+ if (!wantrestart) localcmd("\n_sv_hook_gamestart ", GetGametype(), "\n");
+
+ // fill sv_curl_serverpackages from .serverpackage files
+ if (autocvar_sv_curl_serverpackages_auto)
+ {
+ string s = "csprogs-" WATERMARK ".txt";
+ // remove automatically managed files from the list to prevent duplicates
+ for (int i = 0, n = tokenize_console(cvar_string("sv_curl_serverpackages")); i < n; ++i)
+ {
+ string pkg = argv(i);
+ if (startsWith(pkg, "csprogs-")) continue;
+ if (endsWith(pkg, "-serverpackage.txt")) continue;
+ if (endsWith(pkg, ".serverpackage")) continue; // OLD legacy
+ s = cons(s, pkg);
+ }
+ // add automatically managed files to the list
+ #define X(match) MACRO_BEGIN \
+ int fd = search_begin(match, true, false); \
+ if (fd >= 0) \
+ { \
+ for (int i = 0, j = search_getsize(fd); i < j; ++i) \
+ { \
+ s = cons(s, search_getfilename(fd, i)); \
+ } \
+ search_end(fd); \
+ } \
+ MACRO_END
+ X("*-serverpackage.txt");
+ X("*.serverpackage");
+ #undef X
+ cvar_set("sv_curl_serverpackages", s);
+ }
+
+ // MOD AUTHORS: change this, and possibly remove a few of the blocks below to ignore certain changes
+ modname = "Xonotic";
+ // physics/balance/config changes that count as mod
+ if(cvar_string("g_mod_physics") != cvar_defstring("g_mod_physics"))
+ modname = cvar_string("g_mod_physics");
+ if(cvar_string("g_mod_balance") != cvar_defstring("g_mod_balance") && cvar_string("g_mod_balance") != "Testing")
+ modname = cvar_string("g_mod_balance");
+ if(cvar_string("g_mod_config") != cvar_defstring("g_mod_config"))
+ modname = cvar_string("g_mod_config");
+ // extra mutators that deserve to count as mod
+ MUTATOR_CALLHOOK(SetModname, modname);
+ modname = M_ARGV(0, string);
+
+ // save it for later
+ modname = strzone(modname);
+
+ WinningConditionHelper(this); // set worldstatus
+
+ world_initialized = 1;
+ __spawnfunc_spawn_all();
+}
+
+spawnfunc(light)
+{
+ //makestatic (this); // Who the f___ did that?
+ delete(this);
+}
+
+string GetGametype()
+{
+ return MapInfo_Type_ToString(MapInfo_LoadedGametype);
+}
+
+string GetMapname()
+{
+ return mapname;
+}
+
+float Map_Count, Map_Current;
+string Map_Current_Name;
+
+// NOTE: this now expects the map list to be already tokenized and the count in Map_Count
+int GetMaplistPosition()
+{
+ string map = GetMapname();
+ int idx = autocvar_g_maplist_index;
+
+ if(idx >= 0)
+ {
+ if(idx < Map_Count)
+ {
+ if(map == argv(idx))
+ {
+ return idx;
+ }
+ }
+ }
+
+ for(int pos = 0; pos < Map_Count; ++pos)
+ {
+ if(map == argv(pos))
+ return pos;
+ }
+
+ // resume normal maplist rotation if current map is not in g_maplist
+ return idx;
+}
+
+bool MapHasRightSize(string map)
+{
+ int minplayers = max(0, floor(autocvar_minplayers));
+ if (teamplay)
+ minplayers = max(0, floor(autocvar_minplayers_per_team) * AvailableTeams());
+ if (autocvar_g_maplist_check_waypoints
+ && (currentbots || autocvar_bot_number || player_count < minplayers))
+ {
+ string checkwp_msg = strcat("checkwp ", map);
+ if(!fexists(strcat("maps/", map, ".waypoints")))
+ {
+ LOG_TRACE(checkwp_msg, ": no waypoints");
+ return false;
+ }
+ LOG_TRACE(checkwp_msg, ": has waypoints");
+ }
+
+ if(autocvar_g_maplist_ignore_sizes)
+ return true;
+
+ // open map size restriction file
+ string opensize_msg = strcat("opensize ", map);
+ float fh = fopen(strcat("maps/", map, ".sizes"), FILE_READ);
+ int player_limit = ((autocvar_g_maplist_sizes_count_maxplayers) ? GetPlayerLimit() : 0);
+ int pcount = ((player_limit > 0) ? min(player_count, player_limit) : player_count); // bind it to the player limit so that forced spectators don't influence the limits
+ if(!autocvar_g_maplist_sizes_count_bots)
+ pcount -= currentbots;
+ if(fh >= 0)
+ {
+ opensize_msg = strcat(opensize_msg, ": ok, ");
+ int mapmin = stoi(fgets(fh));
+ int mapmax = stoi(fgets(fh));
+ fclose(fh);
+ if(pcount < mapmin)
+ {
+ LOG_TRACE(opensize_msg, "not enough");
+ return false;
+ }
+ if(mapmax && pcount > mapmax)
+ {
+ LOG_TRACE(opensize_msg, "too many");
+ return false;
+ }
+ LOG_TRACE(opensize_msg, "right size");
+ return true;
+ }
+ LOG_TRACE(opensize_msg, ": not found");
+ return true;
+}
+
+string Map_Filename(float position)
+{
+ return strcat("maps/", argv(position), ".bsp");
+}
+
+void Map_MarkAsRecent(string m)
+{
+ cvar_set("g_maplist_mostrecent", strwords(cons(m, autocvar_g_maplist_mostrecent), max(0, autocvar_g_maplist_mostrecent_count)));
+}
+
+float Map_IsRecent(string m)
+{
+ return strhasword(autocvar_g_maplist_mostrecent, m);
+}
+
+float Map_Check(float position, float pass)
+{
+ string filename;
+ string map_next;
+ map_next = argv(position);
+ if(pass <= 1)
+ {
+ if(Map_IsRecent(map_next))
+ return 0;
+ }
+ filename = Map_Filename(position);
+ if(MapInfo_CheckMap(map_next))
+ {
+ if(pass == 2)
+ return 1;
+ if(MapHasRightSize(map_next))
+ return 1;
+ return 0;
+ }
+ else
+ LOG_DEBUG( "Couldn't select '", filename, "'..." );
+
+ return 0;
+}
+
+void Map_Goto_SetStr(string nextmapname)
+{
+ if(getmapname_stored != "")
+ strunzone(getmapname_stored);
+ if(nextmapname == "")
+ getmapname_stored = "";
+ else
+ getmapname_stored = strzone(nextmapname);
+}
+
+void Map_Goto_SetFloat(float position)
+{
+ cvar_set("g_maplist_index", ftos(position));
+ Map_Goto_SetStr(argv(position));
+}
+
+void Map_Goto(float reinit)
+{
+ MapInfo_LoadMap(getmapname_stored, reinit);
+}
+
+// return codes of map selectors:
+// -1 = temporary failure (that is, try some method that is guaranteed to succeed)
+// -2 = permanent failure
+float MaplistMethod_Iterate() // usual method
+{
+ float pass, i;
+
+ LOG_TRACE("Trying MaplistMethod_Iterate");
+
+ for(pass = 1; pass <= 2; ++pass)
+ {
+ for(i = 1; i < Map_Count; ++i)
+ {
+ float mapindex;
+ mapindex = (i + Map_Current) % Map_Count;
+ if(Map_Check(mapindex, pass))
+ return mapindex;
+ }
+ }
+ return -1;
+}
+
+float MaplistMethod_Repeat() // fallback method
+{
+ LOG_TRACE("Trying MaplistMethod_Repeat");
+
+ if(Map_Check(Map_Current, 2))
+ return Map_Current;
+ return -2;
+}
+
+float MaplistMethod_Random() // random map selection
+{
+ float i, imax;
+
+ LOG_TRACE("Trying MaplistMethod_Random");
+
+ imax = 42;
+
+ for(i = 0; i <= imax; ++i)
+ {
+ float mapindex;
+ mapindex = (Map_Current + floor(random() * (Map_Count - 1) + 1)) % Map_Count; // any OTHER map
+ if(Map_Check(mapindex, 1))
+ return mapindex;
+ }
+ return -1;
+}
+
+float MaplistMethod_Shuffle(float exponent) // more clever shuffling
+// the exponent sets a bias on the map selection:
+// the higher the exponent, the less likely "shortly repeated" same maps are
+{
+ float i, j, imax, insertpos;
+
+ LOG_TRACE("Trying MaplistMethod_Shuffle");
+
+ imax = 42;
+
+ for(i = 0; i <= imax; ++i)
+ {
+ string newlist;
+
+ // now reinsert this at another position
+ insertpos = (random() ** (1 / exponent)); // ]0, 1]
+ insertpos = insertpos * (Map_Count - 1); // ]0, Map_Count - 1]
+ insertpos = ceil(insertpos) + 1; // {2, 3, 4, ..., Map_Count}
+ LOG_TRACE("SHUFFLE: insert pos = ", ftos(insertpos));
+
+ // insert the current map there
+ newlist = "";
+ for(j = 1; j < insertpos; ++j) // i == 1: no loop, will be inserted as first; however, i == 1 has been excluded above
+ newlist = strcat(newlist, " ", argv(j));
+ newlist = strcat(newlist, " ", argv(0)); // now insert the just selected map
+ for(j = insertpos; j < Map_Count; ++j) // i == Map_Count: no loop, has just been inserted as last
+ newlist = strcat(newlist, " ", argv(j));
+ newlist = substring(newlist, 1, strlen(newlist) - 1);
+ cvar_set("g_maplist", newlist);
+ Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
+
+ // NOTE: the selected map has just been inserted at (insertpos-1)th position
+ Map_Current = insertpos - 1; // this is not really valid, but this way the fallback has a chance of working
+ if(Map_Check(Map_Current, 1))
+ return Map_Current;
+ }
+ return -1;
+}
+
+void Maplist_Init()
+{
+ float i = Map_Count = 0;
+ if(autocvar_g_maplist != "")
+ {
+ Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
+ for (i = 0; i < Map_Count; ++i)
+ {
+ if (Map_Check(i, 2))
+ break;
+ }
+ }
+
+ if (i == Map_Count)
+ {
+ bprint( "Maplist contains no usable maps! Resetting it to default map list.\n" );
+ cvar_set("g_maplist", MapInfo_ListAllAllowedMaps(MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags() | MAPINFO_FLAG_NOAUTOMAPLIST));
+ if(autocvar_g_maplist_shuffle)
+ ShuffleMaplist();
+ if(!server_is_dedicated)
+ localcmd("\nmenu_cmd sync\n");
+ Map_Count = tokenizebyseparator(autocvar_g_maplist, " ");
+ }
+ if(Map_Count == 0)
+ error("empty maplist, cannot select a new map");
+ Map_Current = bound(0, GetMaplistPosition(), Map_Count - 1);
+
+ strcpy(Map_Current_Name, argv(Map_Current)); // will be automatically freed on exit thanks to DP
+ // this may or may not be correct, but who cares, in the worst case a map
+ // isn't chosen in the first pass that should have been
+}
+
+string GetNextMap()
+{
+ Maplist_Init();
+ float nextMap = -1;
+
+ if(nextMap == -1)
+ if(autocvar_g_maplist_shuffle > 0)
+ nextMap = MaplistMethod_Shuffle(autocvar_g_maplist_shuffle + 1);
+
+ if(nextMap == -1)
+ if(autocvar_g_maplist_selectrandom)
+ nextMap = MaplistMethod_Random();
+
+ if(nextMap == -1)
+ nextMap = MaplistMethod_Iterate();
+
+ if(nextMap == -1)
+ nextMap = MaplistMethod_Repeat();
+
+ if(nextMap >= 0)
+ {
+ Map_Goto_SetFloat(nextMap);
+ return getmapname_stored;
+ }
+
+ return "";
+}
+
+float DoNextMapOverride(float reinit)
+{
+ if(autocvar_g_campaign)
+ {
+ CampaignPostIntermission();
+ alreadychangedlevel = true;
+ return true;
+ }
+ if(autocvar_quit_when_empty)
+ {
+ if(player_count <= currentbots)
+ {
+ localcmd("quit\n");
+ alreadychangedlevel = true;
+ return true;
+ }
+ }
+ if(autocvar_quit_and_redirect != "")
+ {
+ redirection_target = strzone(autocvar_quit_and_redirect);
+ alreadychangedlevel = true;
+ return true;
+ }
+ if (!reinit && autocvar_samelevel) // if samelevel is set, stay on same level
+ {
+ localcmd("restart\n");
+ alreadychangedlevel = true;
+ return true;
+ }
+ if(autocvar_nextmap != "")
+ {
+ string m;
+ m = GameTypeVote_MapInfo_FixName(autocvar_nextmap);
+ cvar_set("nextmap",m);
+
+ if(!m || gametypevote)
+ return false;
+ if(autocvar_sv_vote_gametype)
+ {
+ Map_Goto_SetStr(m);
+ return false;
+ }
+
+ if(MapInfo_CheckMap(m))
+ {
+ Map_Goto_SetStr(m);
+ Map_Goto(reinit);
+ alreadychangedlevel = true;
+ return true;
+ }
+ }
+ if(!reinit && autocvar_lastlevel)
+ {
+ cvar_settemp_restore();
+ localcmd("set lastlevel 0\ntogglemenu 1\n");
+ alreadychangedlevel = true;
+ return true;
+ }
+ return false;
+}
+
+void GotoNextMap(float reinit)
+{
+ //string nextmap;
+ //float n, nummaps;
+ //string s;
+ if (alreadychangedlevel)
+ return;
+ alreadychangedlevel = true;
+
+ string nextMap = GetNextMap();
+ if(nextMap == "")
+ error("Everything is broken - cannot find a next map. Please report this to the developers.");
+ Map_Goto(reinit);
+}
+
+
+/*
+============
+IntermissionThink
+
+When the player presses attack or jump, change to the next level
+============
+*/
+.float autoscreenshot;
+void IntermissionThink(entity this)
+{
+ FixIntermissionClient(this);
+
+ float server_screenshot = (autocvar_sv_autoscreenshot && CS(this).cvar_cl_autoscreenshot);
+ float client_screenshot = (CS(this).cvar_cl_autoscreenshot == 2);
+
+ if( (server_screenshot || client_screenshot)
+ && ((this.autoscreenshot > 0) && (time > this.autoscreenshot)) )
+ {
+ this.autoscreenshot = -1;
+ if(IS_REAL_CLIENT(this)) { stuffcmd(this, sprintf("\nscreenshot screenshots/autoscreenshot/%s-%s.jpg; echo \"^5A screenshot has been taken at request of the server.\"\n", GetMapname(), strftime(false, "%s"))); }
+ return;
+ }
+
+ if (time < intermission_exittime)
+ return;
+
+ if(!mapvote_initialized)
+ if (time < intermission_exittime + 10 && !(PHYS_INPUT_BUTTON_ATCK(this) || PHYS_INPUT_BUTTON_JUMP(this) || PHYS_INPUT_BUTTON_ATCK2(this) || PHYS_INPUT_BUTTON_HOOK(this) || PHYS_INPUT_BUTTON_USE(this)))
+ return;
+
+ MapVote_Start();
+}
+
+/*
+===============================================================================
+
+RULES
+
+===============================================================================
+*/
+
+void DumpStats(float final)
+{
+ float file;
+ string s;
+ float to_console;
+ float to_eventlog;
+ float to_file;
+ float i;
+
+ to_console = autocvar_sv_logscores_console;
+ to_eventlog = autocvar_sv_eventlog;
+ to_file = autocvar_sv_logscores_file;
+
+ if(!final)
+ {
+ to_console = true; // always print printstats replies
+ to_eventlog = false; // but never print them to the event log
+ }
+
+ if(to_eventlog)
+ if(autocvar_sv_eventlog_console)
+ to_console = false; // otherwise we get the output twice
+
+ if(final)
+ s = ":scores:";
+ else
+ s = ":status:";
+ s = strcat(s, GetGametype(), "_", GetMapname(), ":", ftos(rint(time)));
+
+ if(to_console)
+ LOG_INFO(s);
+ if(to_eventlog)
+ GameLogEcho(s);
+
+ file = -1;
+ if(to_file)
+ {
+ file = fopen(autocvar_sv_logscores_filename, FILE_APPEND);
+ if(file == -1)
+ to_file = false;
+ else
+ fputs(file, strcat(s, "\n"));
+ }
+
+ s = strcat(":labels:player:", GetPlayerScoreString(NULL, 0));
+ if(to_console)
+ LOG_INFO(s);
+ if(to_eventlog)
+ GameLogEcho(s);
+ if(to_file)
+ fputs(file, strcat(s, "\n"));
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it) || (IS_BOT_CLIENT(it) && autocvar_sv_logscores_bots), {
+ s = strcat(":player:see-labels:", GetPlayerScoreString(it, 0), ":");
+ s = strcat(s, ftos(rint(time - CS(it).jointime)), ":");
+ if(IS_PLAYER(it) || MUTATOR_CALLHOOK(GetPlayerStatus, it))
+ s = strcat(s, ftos(it.team), ":");
+ else
+ s = strcat(s, "spectator:");
+
+ if(to_console)
+ LOG_INFO(s, playername(it, false));
+ if(to_eventlog)
+ GameLogEcho(strcat(s, ftos(it.playerid), ":", playername(it, false)));
+ if(to_file)
+ fputs(file, strcat(s, playername(it, false), "\n"));
+ });
+
+ if(teamplay)
+ {
+ s = strcat(":labels:teamscores:", GetTeamScoreString(0, 0));
+ if(to_console)
+ LOG_INFO(s);
+ if(to_eventlog)
+ GameLogEcho(s);
+ if(to_file)
+ fputs(file, strcat(s, "\n"));
+
+ for(i = 1; i < 16; ++i)
+ {
+ s = strcat(":teamscores:see-labels:", GetTeamScoreString(i, 0));
+ s = strcat(s, ":", ftos(i));
+ if(to_console)
+ LOG_INFO(s);
+ if(to_eventlog)
+ GameLogEcho(s);
+ if(to_file)
+ fputs(file, strcat(s, "\n"));
+ }
+ }
+
+ if(to_console)
+ LOG_INFO(":end");
+ if(to_eventlog)
+ GameLogEcho(":end");
+ if(to_file)
+ {
+ fputs(file, ":end\n");
+ fclose(file);
+ }
+}
+
+void FixIntermissionClient(entity e)
+{
+ if(!e.autoscreenshot) // initial call
+ {
+ e.autoscreenshot = time + 0.8; // used for autoscreenshot
+ SetResourceExplicit(e, RES_HEALTH, -2342);
+ // first intermission phase; voting phase has positive health (used to decide whether to send SVC_FINALE or not)
+ for (int slot = 0; slot < MAX_WEAPONSLOTS; ++slot)
+ {
+ .entity weaponentity = weaponentities[slot];
+ if(e.(weaponentity))
+ {
+ e.(weaponentity).effects = EF_NODRAW;
+ if (e.(weaponentity).weaponchild)
+ e.(weaponentity).weaponchild.effects = EF_NODRAW;
+ }
+ }
+ if(IS_REAL_CLIENT(e))
+ {
+ stuffcmd(e, "\nscr_printspeed 1000000\n");
+ RandomSelection_Init();
+ FOREACH_WORD(autocvar_sv_intermission_cdtrack, true, {
+ RandomSelection_AddString(it, 1, 1);
+ });
+ if (RandomSelection_chosen_string != "")
+ {
+ stuffcmd(e, sprintf("\ncd loop %s\n", RandomSelection_chosen_string));
+ }
+ msg_entity = e;
+ WriteByte(MSG_ONE, SVC_INTERMISSION);
+ }
+ }
+}
+
+/*
+go to the next level for deathmatch
+only called if a time or frag limit has expired
+*/
+void NextLevel()
+{
+ game_stopped = true;
+ intermission_running = 1; // game over
+
+ // enforce a wait time before allowing changelevel
+ if(player_count > 0)
+ intermission_exittime = time + autocvar_sv_mapchange_delay;
+ else
+ intermission_exittime = -1;
+
+ /*
+ WriteByte (MSG_ALL, SVC_CDTRACK);
+ WriteByte (MSG_ALL, 3);
+ WriteByte (MSG_ALL, 3);
+ // done in FixIntermission
+ */
+
+ //pos = FindIntermission ();
+
+ VoteReset();
+
+ DumpStats(true);
+
+ // send statistics
+ PlayerStats_GameReport(true);
+ WeaponStats_Shutdown();
+
+ Kill_Notification(NOTIF_ALL, NULL, MSG_CENTER, CPID_Null); // kill all centerprints now
+
+ if(autocvar_sv_eventlog)
+ GameLogEcho(":gameover");
+
+ GameLogClose();
+
+ FOREACH_CLIENT(IS_PLAYER(it), {
+ FixIntermissionClient(it);
+ if(it.winning)
+ bprint(playername(it, false), " ^7wins.\n");
+ });
+
+ target_music_kill();
+
+ if(autocvar_g_campaign)
+ CampaignPreIntermission();
+
+ MUTATOR_CALLHOOK(MatchEnd);
+
+ localcmd("\nsv_hook_gameend\n");
+}
+
+
+float InitiateSuddenDeath()
+{
+ // Check first whether normal overtimes could be added before initiating suddendeath mode
+ // - for this timelimit_overtime needs to be >0 of course
+ // - also check the winning condition calculated in the previous frame and only add normal overtime
+ // again, if at the point at which timelimit would be extended again, still no winner was found
+ if (!autocvar_g_campaign && checkrules_overtimesadded >= 0
+ && (checkrules_overtimesadded < autocvar_timelimit_overtimes || autocvar_timelimit_overtimes < 0)
+ && autocvar_timelimit_overtime && !(g_race && !g_race_qualifying))
+ {
+ return 1; // need to call InitiateOvertime later
+ }
+ else
+ {
+ if(!checkrules_suddendeathend)
+ {
+ if(autocvar_g_campaign)
+ checkrules_suddendeathend = time; // no suddendeath in campaign
+ else
+ checkrules_suddendeathend = time + 60 * autocvar_timelimit_suddendeath;
+ if(g_race && !g_race_qualifying)
+ race_StartCompleting();
+ }
+ return 0;
+ }
+}
+
+void InitiateOvertime() // ONLY call this if InitiateSuddenDeath returned true
+{
+ ++checkrules_overtimesadded;
+ //add one more overtime by simply extending the timelimit
+ cvar_set("timelimit", ftos(autocvar_timelimit + autocvar_timelimit_overtime));
+ Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_TIME, autocvar_timelimit_overtime * 60);
+}
+
+float GetWinningCode(float fraglimitreached, float equality)
+{
+ if(autocvar_g_campaign == 1)
+ {
+ if(fraglimitreached)
+ return WINNING_YES;
+ else
+ return WINNING_NO;
+ }
+ else
+ {
+ if(equality)
+ {
+ if(fraglimitreached)
+ return WINNING_STARTSUDDENDEATHOVERTIME;
+ else
+ return WINNING_NEVER;
+ }
+ else
+ {
+ if(fraglimitreached)
+ return WINNING_YES;
+ else
+ return WINNING_NO;
+ }
+ }
+}
+
+// set the .winning flag for exactly those players with a given field value
+void SetWinners(.float field, float value)
+{
+ FOREACH_CLIENT(IS_PLAYER(it), { it.winning = (it.(field) == value); });
+}
+
+// set the .winning flag for those players with a given field value
+void AddWinners(.float field, float value)
+{
+ FOREACH_CLIENT(IS_PLAYER(it), {
+ if(it.(field) == value)
+ it.winning = 1;
+ });
+}
+
+// clear the .winning flags
+void ClearWinners()
+{
+ FOREACH_CLIENT(IS_PLAYER(it), { it.winning = 0; });
+}
+
+void ShuffleMaplist()
+{
+ cvar_set("g_maplist", shufflewords(autocvar_g_maplist));
+}
+
+int fragsleft_last;
+float WinningCondition_Scores(float limit, float leadlimit)
+{
+ // TODO make everything use THIS winning condition (except LMS)
+ WinningConditionHelper(NULL);
+
+ if(teamplay)
+ {
+ for (int i = 1; i < 5; ++i)
+ {
+ Team_SetTeamScore(Team_GetTeamFromIndex(i),
+ TeamScore_GetCompareValue(Team_IndexToTeam(i)));
+ }
+ }
+
+ ClearWinners();
+ if(WinningConditionHelper_winner)
+ WinningConditionHelper_winner.winning = 1;
+ if(WinningConditionHelper_winnerteam >= 0)
+ SetWinners(team, WinningConditionHelper_winnerteam);
+
+ if(WinningConditionHelper_lowerisbetter)
+ {
+ WinningConditionHelper_topscore = -WinningConditionHelper_topscore;
+ WinningConditionHelper_secondscore = -WinningConditionHelper_secondscore;
+ limit = -limit;
+ }
+
+ if(WinningConditionHelper_zeroisworst)
+ leadlimit = 0; // not supported in this mode
+
+ if(MUTATOR_CALLHOOK(Scores_CountFragsRemaining))
+ {
+ float fragsleft;
+ if (checkrules_suddendeathend && time >= checkrules_suddendeathend)
+ {
+ fragsleft = 1;
+ }
+ else
+ {
+ fragsleft = FLOAT_MAX;
+ float leadingfragsleft = FLOAT_MAX;
+ if (limit)
+ fragsleft = limit - WinningConditionHelper_topscore;
+ if (leadlimit)
+ leadingfragsleft = WinningConditionHelper_secondscore + leadlimit - WinningConditionHelper_topscore;
+
+ if (limit && leadlimit && autocvar_leadlimit_and_fraglimit)
+ fragsleft = max(fragsleft, leadingfragsleft);
+ else
+ fragsleft = min(fragsleft, leadingfragsleft);
+ }
+
+ if (fragsleft_last != fragsleft) // do not announce same remaining frags multiple times
+ {
+ if (fragsleft == 1)
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_1);
+ else if (fragsleft == 2)
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_2);
+ else if (fragsleft == 3)
+ Send_Notification(NOTIF_ALL, NULL, MSG_ANNCE, ANNCE_REMAINING_FRAG_3);
+
+ fragsleft_last = fragsleft;
+ }
+ }
+
+ bool fraglimit_reached = (limit && WinningConditionHelper_topscore >= limit);
+ bool leadlimit_reached = (leadlimit && WinningConditionHelper_topscore - WinningConditionHelper_secondscore >= leadlimit);
+
+ bool limit_reached;
+ // only respect leadlimit_and_fraglimit when both limits are set or the game will never end
+ if (limit && leadlimit && autocvar_leadlimit_and_fraglimit)
+ limit_reached = (fraglimit_reached && leadlimit_reached);
+ else
+ limit_reached = (fraglimit_reached || leadlimit_reached);
+
+ return GetWinningCode(
+ WinningConditionHelper_topscore && limit_reached,
+ WinningConditionHelper_equality
+ );
+}
+
+float WinningCondition_RanOutOfSpawns()
+{
+ if(have_team_spawns <= 0)
+ return WINNING_NO;
+
+ if(!autocvar_g_spawn_useallspawns)
+ return WINNING_NO;
+
+ if(!some_spawn_has_been_used)
+ return WINNING_NO;
+
+ 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))
+ {
+ Team_SetTeamScore(Team_GetTeam(it.team), 1);
+ }
+ });
+
+ IL_EACH(g_spawnpoints, true,
+ {
+ if (Team_IsValidTeam(it.team))
+ {
+ 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;
+ return WINNING_YES;
+ }
+ else if(team1_score + team2_score + team3_score + team4_score == 1)
+ {
+ float t, i;
+ if(team1_score)
+ t = 1;
+ else if(team2_score)
+ t = 2;
+ else if(team3_score)
+ t = 3;
+ else // if(team4_score)
+ t = 4;
+ entity balance = TeamBalance_CheckAllowedTeams(NULL);
+ for(i = 0; i < MAX_TEAMSCORE; ++i)
+ {
+ 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);
+ return WINNING_YES;
+ }
+ else
+ return WINNING_NO;
+}
+
+/*
+============
+CheckRules_World
+
+Exit deathmatch games upon conditions
+============
+*/
+void CheckRules_World()
+{
+ VoteThink();
+ MapVote_Think();
+
+ SetDefaultAlpha();
+
+ if (intermission_running) // someone else quit the game already
+ {
+ if(player_count == 0) // Nobody there? Then let's go to the next map
+ MapVote_Start();
+ // this will actually check the player count in the next frame
+ // again, but this shouldn't hurt
+ return;
+ }
+
+ float timelimit = autocvar_timelimit * 60;
+ float fraglimit = autocvar_fraglimit;
+ float leadlimit = autocvar_leadlimit;
+ if (leadlimit < 0) leadlimit = 0;
+
+ if(warmup_stage || time <= game_starttime) // NOTE: this is <= to prevent problems in the very tic where the game starts
+ {
+ if(timelimit > 0)
+ timelimit = 0; // timelimit is not made for warmup
+ if(fraglimit > 0)
+ fraglimit = 0; // no fraglimit for now
+ leadlimit = 0; // no leadlimit for now
+ }
+
+ if(timelimit > 0)
+ {
+ timelimit += game_starttime;
+ }
+ else if (timelimit < 0)
+ {
+ // endmatch
+ NextLevel();
+ return;
+ }
+
+ float wantovertime;
+ wantovertime = 0;
+
+ if(checkrules_suddendeathend)
+ {
+ if(!checkrules_suddendeathwarning)
+ {
+ checkrules_suddendeathwarning = true;
+ if(g_race && !g_race_qualifying)
+ Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_RACE_FINISHLAP);
+ else
+ Send_Notification(NOTIF_ALL, NULL, MSG_CENTER, CENTER_OVERTIME_FRAG);
+ }
+ }
+ else
+ {
+ if (timelimit && time >= timelimit)
+ {
+ if(g_race && (g_race_qualifying == 2) && timelimit > 0)
+ {
+ float totalplayers;
+ float playerswithlaps;
+ float readyplayers;
+ totalplayers = playerswithlaps = readyplayers = 0;
+ FOREACH_CLIENT(IS_PLAYER(it), {
+ ++totalplayers;
+ if(GameRules_scoring_add(it, RACE_FASTEST, 0))
+ ++playerswithlaps;
+ if(it.ready)
+ ++readyplayers;
+ });
+
+ // at least 2 of the players have completed a lap: start the RACE
+ // otherwise, the players should end the qualifying on their own
+ if(readyplayers || playerswithlaps >= 2)
+ {
+ checkrules_suddendeathend = 0;
+ ReadyRestart(); // go to race
+ return;
+ }
+ else
+ wantovertime |= InitiateSuddenDeath();
+ }
+ else
+ wantovertime |= InitiateSuddenDeath();
+ }
+ }
+
+ if (checkrules_suddendeathend && time >= checkrules_suddendeathend)
+ {
+ NextLevel();
+ return;
+ }
+
+ int checkrules_status = WinningCondition_RanOutOfSpawns();
+ if(checkrules_status == WINNING_YES)
+ bprint("Hey! Someone ran out of spawns!\n");
+ else if(MUTATOR_CALLHOOK(CheckRules_World, checkrules_status, timelimit, fraglimit))
+ checkrules_status = M_ARGV(0, float);
+ else
+ checkrules_status = WinningCondition_Scores(fraglimit, leadlimit);
+
+ if(checkrules_status == WINNING_STARTSUDDENDEATHOVERTIME)
+ {
+ checkrules_status = WINNING_NEVER;
+ checkrules_overtimesadded = -1;
+ wantovertime |= InitiateSuddenDeath();
+ }
+
+ if(checkrules_status == WINNING_NEVER)
+ // equality cases! Nobody wins if the overtime ends in a draw.
+ ClearWinners();
+
+ if(wantovertime)
+ {
+ if(checkrules_status == WINNING_NEVER)
+ InitiateOvertime();
+ else
+ checkrules_status = WINNING_YES;
+ }
+
+ if(checkrules_suddendeathend)
+ if(checkrules_status != WINNING_NEVER || time >= checkrules_suddendeathend)
+ checkrules_status = WINNING_YES;
+
+ if(checkrules_status == WINNING_YES)
+ {
+ //print("WINNING\n");
+ NextLevel();
+ }
+}
+
+string GotoMap(string m)
+{
+ m = GameTypeVote_MapInfo_FixName(m);
+ if (!m)
+ return "The map you suggested is not available on this server.";
+ if (!autocvar_sv_vote_gametype)
+ if(!MapInfo_CheckMap(m))
+ return "The map you suggested does not support the current game mode.";
+ cvar_set("nextmap", m);
+ cvar_set("timelimit", "-1");
+ if(mapvote_initialized || alreadychangedlevel)
+ {
+ if(DoNextMapOverride(0))
+ return "Map switch initiated.";
+ else
+ return "Hm... no. For some reason I like THIS map more.";
+ }
+ else
+ return "Map switch will happen after scoreboard.";
+}
+
+bool autocvar_sv_gameplayfix_multiplethinksperframe = true;
+void RunThink(entity this)
+{
+ // don't let things stay in the past.
+ // it is possible to start that way by a trigger with a local time.
+ if(this.nextthink <= 0 || this.nextthink > time + frametime)
+ return;
+
+ float oldtime = time; // do we need to save this?
+
+ for (int iterations = 0; iterations < 128 && !wasfreed(this); iterations++)
+ {
+ time = max(oldtime, this.nextthink);
+ this.nextthink = 0;
+
+ if(getthink(this))
+ getthink(this)(this);
+ // mods often set nextthink to time to cause a think every frame,
+ // we don't want to loop in that case, so exit if the new nextthink is
+ // <= the time the qc was told, also exit if it is past the end of the
+ // frame
+ if(this.nextthink <= time || this.nextthink > oldtime + frametime || !autocvar_sv_gameplayfix_multiplethinksperframe)
+ break;
+ }
+
+ time = oldtime;
+}
+
+bool autocvar_sv_freezenonclients;
+void Physics_Frame()
+{
+ if(autocvar_sv_freezenonclients)
+ return;
+
+ IL_EACH(g_moveables, true,
+ {
+ if(IS_CLIENT(it) || it.move_movetype == MOVETYPE_PHYSICS)
+ continue;
+
+ //set_movetype(it, it.move_movetype);
+ // inline the set_movetype function, since this is called a lot
+ it.movetype = (it.move_qcphysics) ? MOVETYPE_QCENTITY : it.move_movetype;
+
+ if(it.move_qcphysics && it.move_movetype != MOVETYPE_NONE)
+ Movetype_Physics_NoMatchTicrate(it, PHYS_INPUT_TIMELENGTH, false);
+
+ if(it.movetype >= MOVETYPE_USER_FIRST && it.movetype <= MOVETYPE_USER_LAST) // these cases have no think handling
+ {
+ if(it.move_movetype == MOVETYPE_PUSH || it.move_movetype == MOVETYPE_FAKEPUSH)
+ continue; // these movetypes have no regular think function
+ // handle thinking here
+ if (getthink(it) && it.nextthink > 0 && it.nextthink <= time + frametime)
+ RunThink(it);
+ }
+ });
+
+ if(autocvar_sv_gameplayfix_delayprojectiles >= 0)
+ return;
+
+ // make a second pass to see if any ents spawned this frame and make
+ // sure they run their move/think. this is verified by checking .move_time, which will never be 0 if the entity has moved
+ IL_EACH(g_moveables, it.move_qcphysics,
+ {
+ if(IS_CLIENT(it) || it.move_time || it.move_movetype == MOVETYPE_NONE || it.move_movetype == MOVETYPE_PHYSICS)
+ continue;
+ Movetype_Physics_NoMatchTicrate(it, PHYS_INPUT_TIMELENGTH, false);
+ });
+}
+
+void systems_update();
+void EndFrame()
+{
+ anticheat_endframe();
+
+ Physics_Frame();
+
+ FOREACH_CLIENT(IS_REAL_CLIENT(it), {
+ entity e = IS_SPEC(it) ? it.enemy : it;
+ if (e.typehitsound) {
+ STAT(TYPEHIT_TIME, it) = time;
+ } else if (e.killsound) {
+ STAT(KILL_TIME, it) = time;
+ } else if (e.damage_dealt) {
+ STAT(HIT_TIME, it) = time;
+ STAT(DAMAGE_DEALT_TOTAL, it) += ceil(e.damage_dealt);
+ }
+ });
+ // add 1 frametime because after this, engine SV_Physics
+ // increases time by a frametime and then networks the frame
+ // add another frametime because client shows everything with
+ // 1 frame of lag (cl_nolerp 0). The last +1 however should not be
+ // needed!
+ float altime = time + frametime * (1 + autocvar_g_antilag_nudge);
+ FOREACH_CLIENT(true, {
+ it.typehitsound = false;
+ it.damage_dealt = 0;
+ it.killsound = false;
+ antilag_record(it, CS(it), altime);
+ });
+ IL_EACH(g_monsters, true,
+ {
+ antilag_record(it, it, altime);
+ });
+ IL_EACH(g_projectiles, it.classname == "nade",
+ {
+ antilag_record(it, it, altime);
+ });
+ systems_update();
+ IL_ENDFRAME();
+}
+
+
+/*
+ * RedirectionThink:
+ * returns true if redirecting
+ */
+float redirection_timeout;
+float redirection_nextthink;
+float RedirectionThink()
+{
+ float clients_found;
+
+ if(redirection_target == "")
+ return false;
+
+ if(!redirection_timeout)
+ {
+ cvar_set("sv_public", "-2");
+ redirection_timeout = time + 0.6; // this will only try twice... should be able to keep more clients
+ if(redirection_target == "self")
+ bprint("^3SERVER NOTICE:^7 restarting the server\n");
+ else
+ bprint("^3SERVER NOTICE:^7 redirecting everyone to ", redirection_target, "\n");
+ }
+
+ if(time < redirection_nextthink)
+ return true;
+
+ redirection_nextthink = time + 1;
+
+ clients_found = 0;
+ FOREACH_CLIENT(IS_REAL_CLIENT(it), {
+ // TODO add timer
+ LOG_INFO("Redirecting: sending connect command to ", it.netname);
+ if(redirection_target == "self")
+ stuffcmd(it, "\ndisconnect; defer ", ftos(autocvar_quit_and_redirect_timer), " reconnect\n");
+ else
+ stuffcmd(it, strcat("\ndisconnect; defer ", ftos(autocvar_quit_and_redirect_timer), " \"connect ", redirection_target, "\"\n"));
+ ++clients_found;
+ });
+
+ LOG_INFO("Redirecting: ", ftos(clients_found), " clients left.");
+
+ if(time > redirection_timeout || clients_found == 0)
+ localcmd("\nwait; wait; wait; quit\n");
+
+ return true;
+}
+
+void RestoreGame()
+{
+ // Loaded from a save game
+ // some things then break, so let's work around them...
+
+ // Progs DB (capture records)
+ ServerProgsDB = db_load(strcat("server.db", autocvar_sessionid));
+
+ // Mapinfo
+ MapInfo_Shutdown();
+ MapInfo_Enumerate();
+ MapInfo_FilterGametype(MapInfo_CurrentGametype(), MapInfo_CurrentFeatures(), MapInfo_RequiredFlags(), MapInfo_ForbiddenFlags(), 1);
+ WeaponStats_Init();
+
+ TargetMusic_RestoreGame();
+}
+
+void Shutdown()
+{
+ game_stopped = 2;
+
+ if(world_initialized > 0)
+ {
+ world_initialized = 0;
+
+ // if a timeout is active, reset the slowmo value to normal
+ if(timeout_status == TIMEOUT_ACTIVE)
+ cvar_set("slowmo", ftos(orig_slowmo));
+
+ LOG_TRACE("Saving persistent data...");
+ Ban_SaveBans();
+
+ // playerstats with unfinished match
+ PlayerStats_GameReport(false);
+
+ if(!cheatcount_total)
+ {
+ if(autocvar_sv_db_saveasdump)
+ db_dump(ServerProgsDB, strcat("server.db", autocvar_sessionid));
+ else
+ db_save(ServerProgsDB, strcat("server.db", autocvar_sessionid));
+ }
+ if(autocvar_developer > 0)
+ {
+ if(autocvar_sv_db_saveasdump)
+ db_dump(TemporaryDB, "server-temp.db");
+ else
+ db_save(TemporaryDB, "server-temp.db");
+ }
+ CheatShutdown(); // must be after cheatcount check
+ db_close(ServerProgsDB);
+ db_close(TemporaryDB);
+ LOG_TRACE("Saving persistent data... done!");
+ // tell the bot system the game is ending now
+ bot_endgame();
+
+ WeaponStats_Shutdown();
+ MapInfo_Shutdown();
+ }
+ else if(world_initialized == 0)
+ {
+ LOG_INFO("NOTE: crashed before even initializing the world, not saving persistent data");
+ }
+ else
+ {
+ __init_dedicated_server_shutdown();
+ }
+}
--- /dev/null
+#pragma once
+
+float checkrules_equality;
+float checkrules_suddendeathwarning;
+float checkrules_suddendeathend;
+float checkrules_overtimesadded; //how many overtimes have been already added
+
+// flag set on worldspawn so that the code knows if it is dedicated or not
+bool server_is_dedicated;
+
+string cvar_changes;
+string cvar_purechanges;
+float cvar_purechanges_count;
+
+string modname;
+
+string gamemode_name;
+
+string clientstuff;
+
+string matchid;
+
+.string fog;
+
+float intermission_running;
+float intermission_exittime;
+float alreadychangedlevel;
+
+string cache_mutatormsg;
+string cache_lastmutatormsg;
+
+float default_player_alpha;
+float default_weapon_alpha;
+
+// database
+float ServerProgsDB;
+float TemporaryDB;
+
+.float winning;
+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
+const int WINNING_STARTSUDDENDEATHOVERTIME = 3; // no winner, enter suddendeath overtime NOW
+
+float WinningCondition_Scores(float limit, float leadlimit);
+void SetWinners(.float field, float value);
+void IntermissionThink(entity this);
+void GotoNextMap(float reinit);
+void ReadyRestart();
+
+string GetGametype();
+
+void DumpStats(float final);
+float Map_IsRecent(string m);
+string GetNextMap();
+void ShuffleMaplist();
+void Map_Goto_SetStr(string nextmapname);
+void Map_Goto(float reinit);
+void Map_MarkAsRecent(string m);
+float DoNextMapOverride(float reinit);
+void CheckRules_World();
+float RedirectionThink();
+
+// quake 3 music compatibility
+.string music;
+.string noise;
+
+IntrusiveList g_moveables;
+STATIC_INIT(g_moveables) { g_moveables = IL_NEW(); }
set developer_csqcentities 0 "csqc entity spam"
seta cl_forceplayermodels 0 "make everyone look like your own model (requires server to have sv_defaultcharacter 0)"
-seta cl_forceplayercolors 0 "make enemies look like your own color (requires server to have sv_defaultcharacter 0); set it to 2 to enable it even in teamplay (only when there is exactly one enemy team)"
+seta cl_forceplayercolors 0 "make enemies look like your own color (requires server to have sv_defaultcharacter 0); 2: enable it even in teamplay (only when there is exactly one enemy team); 3: enable it only playing Duel"
seta cl_forcemyplayermodel "" "set to the model file name you want to show yourself as (does not affect how enemies look with cl_forceplayermodels)"
seta cl_forcemyplayerskin 0 "set to the skin number you want to show yourself as (does not affect how enemies look with cl_forceplayermodels)"
seta cl_forcemyplayercolors 0 "set to the color value (encoding is same as _cl_color) for your own player model (ignored in teamplay; does not affect how enemies look with cl_forceplayermodels)"