Merge branch 'master' into pr-poc-mv-clean

This commit is contained in:
Vy0x2 2023-06-30 18:07:12 +02:00 committed by GitHub
commit 0b8ed51614
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
150 changed files with 4896 additions and 4220 deletions

View file

@ -44,6 +44,8 @@ jobs:
run: "! grep --exclude-dir rust-bridge -rE '^#include \"(antibot|base|engine|game|steam|test)/' src/"
- name: Check standard header includes
run: scripts/check_standard_headers.sh
- name: Check config variables
run: scripts/check_config_variables.py
# TODO: Enable on release branches
#- name: Out-of-date translations
# run: |

View file

@ -737,6 +737,7 @@ if(TARGET_OS STREQUAL "windows")
list(APPEND PLATFORM_LIBS bcrypt userenv) # for Rust (https://github.com/rust-lang/rust/issues/91974)
list(APPEND PLATFORM_LIBS ole32) # CoInitialize(Ex)
list(APPEND PLATFORM_LIBS shell32)
list(APPEND PLATFORM_LIBS ntdll) # https://github.com/ddnet/ddnet/issues/6725
elseif(TARGET_OS STREQUAL "mac")
find_library(CARBON Carbon)
find_library(COCOA Cocoa)
@ -1863,6 +1864,7 @@ add_custom_command(OUTPUT "src/game/generated/wordlist.h"
set_src(BASE GLOB_RECURSE src/base
bezier.cpp
bezier.h
color.cpp
color.h
detect.h
dynamic.h
@ -2260,6 +2262,8 @@ if(CLIENT)
pickup_data.h
prediction/entities/character.cpp
prediction/entities/character.h
prediction/entities/dragger.cpp
prediction/entities/dragger.h
prediction/entities/laser.cpp
prediction/entities/laser.h
prediction/entities/pickup.cpp

View file

@ -71,12 +71,6 @@ Clan
Client
== ﺖﻨﻳﻼﻛ
Close
== ﻕﻼﻏﺍ
Connect
== ﻝﺎﺼﺗﺍ
Connecting to
== ﻰﻟﺍ ﻝﺎﺼﺗﺍ
@ -747,9 +741,6 @@ Switch weapon when out of ammo
Grabs
== ﺕﺎﻜﺴﻣ
Select a name
== ﻢﺳﺍ ﺭﺎﻴﺘﺧﺍ
Automatically take game over screenshot
== ﺔﺷﺎﺸﻟﺍ ﺔﻄﻘﻟ ﻰﻠﻋ ﺍًﻴﺋﺎﻘﻠﺗ ﺔﺒﻌﻠﻟﺍ ﺬﺧﺃ
@ -762,9 +753,6 @@ Gameplay
Laser
== ﺭﺰﻴﻟ
Old mouse mode
== ﻢﻳﺪﻘﻟﺍ ﺱﻭﺎﻤﻟﺍ ﻊﺿﻭ
Follow
== ﻊﺒﺗﺃ
@ -780,9 +768,6 @@ Show tiles layers from BG map
Remove chat
== ﺕﺎﺸﻟﺍ ﻑﺬﺣ
Threaded sound loading
== ﺔﻳﺍﺪﺒﻟﺍ ﺕﻮﺼ
Frags
== ﻞﺑﺎﻨﻗ
@ -966,8 +951,8 @@ Replace video
DDraceNetwork is a cooperative online game where the goal is for you and your group of tees to reach the finish line of the map. As a newcomer you should start on Novice servers, which host the easiest maps. Consider the ping to choose a server close to you.
== DDraceNetwork ، ﻦﻴﺋﺪﺘﺒﻤﻟﺍ ﺕﺍﺮﻓﺮﻴﺳ ﻰﻠﻋ ﺃﺪﺒﺗ ﻥﺃ ﺐﺠﻳ ، ﺍًﺪﻳﺪﺟ ﺍًﻣﺩﺎﻗ ﻚﺘﻔﺼﺑ .ﺏﺎﻤﻟﺍ ﻰﻠﻋ ﺔﻳﺎﻬﻨﻟﺍ ﻂﺧ ﻰﻟﺇ ﺕﻼﻤﺤﻤﻟﺍ ﻦﻣ ﻚﺘﻋﻮﻤﺠﻣﻭ ﺖﻧﺃ ﻚﻟﻮﺻﻭ ﻮﻫ ﻑﺪﻬﻟﺍ ﻥﻮﻜﻳ ﺚﻴﺣ ﺖﻧﺮﺘﻧﻹﺍ ﺮﺒﻋ ﺔﻴﻧﻭﺎﻌﺗ ﺔﺒﻌﻟ ﻲﻫ
Default length: %d
== ﻲﺿﺍﺮﺘﻓﻻﺍ ﻝﻮﻄﻟﺍ: %d
Default length
== ﻲﺿﺍﺮﺘﻓﻻﺍ ﻝﻮﻄﻟﺍ
Pause
== ﺔﺒﻗﺍﺮﻣ
@ -1260,7 +1245,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1299,9 +1284,6 @@ CHN
Getting server list from master server
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -1311,6 +1293,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -1363,10 +1348,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1378,9 +1363,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1441,10 +1438,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1455,9 +1452,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1470,7 +1464,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1479,9 +1473,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1491,15 +1482,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1527,15 +1518,12 @@ default
custom
==
Graphics cards
Graphics card
==
auto
==
Sample rate
==
Appearance
==

View file

@ -77,12 +77,6 @@ Clan
Client
== Кліент
Close
== Выйсці
Connect
== Падлучыцца
Connecting to
== Падлучэнне да
@ -348,9 +342,6 @@ Rename demo
Reset filter
== Скінуць фільтр
Sample rate
== Чашчыня сэмпла
Score
== Ачкі
@ -830,9 +821,6 @@ Exclude
%d player
== %d гулец
Refreshing...
== Абнаўленне...
Are you sure that you want to disconnect and switch to a different server?
== Вы ўпэўненыя, што хочаце адлучыцца і пераключыцца на іншы сервер?
@ -863,9 +851,6 @@ Are you sure that you want to remove the player '%s' from your friends list?
Are you sure that you want to remove the clan '%s' from your friends list?
== Вы ўпэўненыя што хочаце выдаліць клан '%s' са спіса вашых сяброў?
Select a name
== Выберыце імя
Please use a different name
== Калі ласка, выкарыстайце іншае імя
@ -896,12 +881,6 @@ Slow down the demo
Speed up the demo
== Паскорыць дэма
Mark the beginning of a cut
== Пазначыць пачатак адрэзка
Mark the end of a cut
== Пазначыць канец адрэзка
Export cut as a separate demo
== Экспартаваць адрэзак як асобнае дэма
@ -1133,13 +1112,6 @@ Chat command
Enable controller
== Уключыць кантролер
Controller %d: %s
== Кантролер %d: %s
Click to cycle through all available controllers.
== Націсніце каб праглядзець усе дасяжныя кантролеры.
[Ingame controller mode]
Relative
== Адносны
@ -1162,18 +1134,12 @@ Controller jitter tolerance
No controller found. Plug in a controller.
== Кантролер не знойдзены. Падключыце кантролер.
Device
== Прылада
Status
== Статус
Aim bind
== Вось прыцэла
Controller Axis #%d
== Вось кантролера #%d
Mouse
== Мыш
@ -1228,9 +1194,6 @@ default
custom
== карыстацкі
Graphics cards
== Відэакарты
auto
== аўта
@ -1255,9 +1218,6 @@ Enable team chat sound
Enable highlighted chat sound
== Уключыць гук падсвечаных паведамленняў
Threaded sound loading
== Шматструменная загрузка гукаў
Game sound volume
== Гучнасць гульні
@ -1459,8 +1419,8 @@ Save the best demo of each race
Enable replays
== Уключыць запісы
Default length: %d
== Станд. працягласць: %d
Default length
== Станд. працягласць
When you cross the start line, show a ghost tee replicating the movements of your best time
== Пры перасячэнні стартавай лініі, паказваць прывід Tee, які паўтарае ваш лепшы час
@ -1513,9 +1473,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths
== АнтыПінг: прадказывать траекторыі гранат
Old mouse mode
== Рэжым старой мышы
Background
== Фон
@ -1694,6 +1651,12 @@ Grabs
9+ new mentions
== 9+ новых згадак
A demo with this name already exists
==
No server selected
==
Online players (%d)
==
@ -1718,3 +1681,27 @@ None
Add Clan
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -79,12 +79,6 @@ Clan
Client
== Klijent
Close
== Zatvori
Connect
== Konektuj
Connecting to
== Konektovanje na
@ -350,9 +344,6 @@ Rename demo
Reset filter
== Poništi filter
Sample rate
== Frekvencija
Score
== Rezultat
@ -703,9 +694,6 @@ Update now
Restart
== Restart
Select a name
== Izaberite ime
Please use a different name
== Molimo izaberite drugo ime
@ -868,9 +856,6 @@ Enable team chat sound
Enable highlighted chat sound
== Omogući zvuk označavanja u čatu
Threaded sound loading
== Učitavanje tredovanog zvuka
Map sound volume
== Glasnoća zvuka mape
@ -919,8 +904,8 @@ Client message
Save the best demo of each race
== Sačuvaj najbolji demo-snimak svake trke
Default length: %d
== Zadana dužina: %d
Default length
== Zadana dužina
Enable replays
== Omogući replay
@ -961,9 +946,6 @@ Show other players' hook collision lines
Show other players' key presses
== Prikaži tipke koje ostali igrači pritiskaju
Old mouse mode
== Stari način miša
Show tiles layers from BG map
== Prikaži slojeve od pozadinske mape
@ -1135,7 +1117,7 @@ Your nickname '%s' is already used (%d points). Do you still want to use it?
Checking for existing player with your name
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1192,9 +1174,6 @@ Getting server list from master server
%d player
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -1204,6 +1183,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -1256,10 +1238,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1271,9 +1253,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1364,10 +1358,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1378,9 +1372,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1393,7 +1384,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1402,9 +1393,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1414,15 +1402,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1450,7 +1438,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto

View file

@ -99,12 +99,6 @@ Clan
Client
== Cliente
Close
== Fechar
Connect
== Conectar
Connecting to
== Conectando a
@ -373,9 +367,6 @@ Rename demo
Reset filter
== Redefinir filtro
Sample rate
== Frequência do som
Score
== Pontos
@ -604,9 +595,6 @@ HUD
Show names in chat in team colors
== Mostrar nomes no chat com cores do time
Select a name
== Selecione um nome
Netversion:
== Netversion:
@ -652,9 +640,6 @@ Gameplay
Restart
== Reiniciar
Old mouse mode
== Modo antigo de mouse
Round
== Turno
@ -691,9 +676,6 @@ Ghost
Remove chat
== Remover chat
Threaded sound loading
== Carregamento de som em fluxos
Check now
== Verificar agora
@ -1006,8 +988,8 @@ Converse
Successfully saved the replay!
== A reprodução foi salva com sucesso
Default length: %d
== Duração padrão: %d
Default length
== Duração padrão
Replay feature is disabled!
== O Recurso de reprodução está desabilitado!
@ -1253,9 +1235,6 @@ https://ddnet.org/discord
Are you sure that you want to disconnect and switch to a different server?
== Tem certeza que deseja desconectar e trocar para um servidor diferente?
Refreshing...
== Atualizando...
Kill Messages
== Mensagens de kill
@ -1289,9 +1268,6 @@ default
custom
== personalizado
Graphics cards
== Placas de vídeo
auto
== auto
@ -1364,13 +1340,6 @@ Download community skins
Enable controller
== Habilitar controle
Controller %d: %s
== Controle %d: %s
Click to cycle through all available controllers.
== Clique para trocar entre todos os controles disponíveis.
[Ingame controller mode]
Relative
== Relativo
@ -1390,18 +1359,12 @@ UI controller sens.
Controller jitter tolerance
== Tolerância jitter do controle
Device
== Dispositivo
Status
== Status
Aim bind
== Associação de mira
Controller Axis #%d
== Eixo #%d do controle
Mouse
== Mouse
@ -1561,12 +1524,6 @@ Slow down the demo
Speed up the demo
== Acelerar a demo
Mark the beginning of a cut
== Marcar o início de um corte
Mark the end of a cut
== Marcar o fim de um corte
Export cut as a separate demo
== Exportar corte como uma demo separada
@ -1716,6 +1673,12 @@ Copy info
Create a random skin
== Criar uma skin aleatória
A demo with this name already exists
==
No server selected
==
Online players (%d)
==
@ -1740,3 +1703,27 @@ None
Add Clan
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -76,12 +76,6 @@ Clan
Client
== Клиент
Close
== Затвори
Connect
== Впиши
Connecting to
== Свързвам се с
@ -347,9 +341,6 @@ Rename demo
Reset filter
== Рестартирай филтрите
Sample rate
== Честота
Score
== Точки
@ -756,7 +747,7 @@ Your nickname '%s' is already used (%d points). Do you still want to use it?
Checking for existing player with your name
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -831,9 +822,6 @@ Exclude
%d player
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -858,6 +846,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -889,18 +880,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan
==
Select a name
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Remove chat
==
Play the current demo
==
@ -922,10 +901,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -937,9 +916,30 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Remove chat
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Loading demo files
==
@ -1162,10 +1162,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1176,9 +1176,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1191,7 +1188,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1200,9 +1197,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1212,15 +1206,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1236,10 +1230,10 @@ Windowed fullscreen
Desktop fullscreen
==
may cause delay
Screen
==
Screen
may cause delay
==
Allows maps to render with more detail
@ -1257,7 +1251,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto
@ -1284,9 +1278,6 @@ Enable team chat sound
Enable highlighted chat sound
==
Threaded sound loading
==
Game sound volume
==
@ -1488,7 +1479,7 @@ Save the best demo of each race
Enable replays
==
Default length: %d
Default length
==
When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1506,10 +1497,10 @@ Gameplay
Overlay entities
==
Size
Show text entities
==
Show text entities
Size
==
Opacity
@ -1542,9 +1533,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths
==
Old mouse mode
==
Background
==

View file

@ -72,12 +72,6 @@ Clan
Client
== Client
Close
== Tancar
Connect
== Connectar
Connecting to
== T'estàs unint a
@ -345,9 +339,6 @@ Rename demo
Reset filter
== Reiniciar el filtre
Sample rate
== Freqüència de la imatge
Score
== Punts
@ -642,9 +633,6 @@ Show votes window after voting
HUD
== HUD
Select a name
== Selecciona un nom
Enable team chat sound
== Activar el so del xat d'equip
@ -672,9 +660,6 @@ Gameplay
Restart
== Reiniciar
Old mouse mode
== Mode antic del ratolí
Browser
== Navegador
@ -708,9 +693,6 @@ Ghost
Remove chat
== Eliminar el xat
Threaded sound loading
== Càrrega de so en fils
Check now
== Comprova ara
@ -1002,8 +984,8 @@ Show HUD
Use high DPI
== Fer servir alt DPI
Default length: %d
== Llargada predeterminada: %d
Default length
== Llargada predeterminada
Enable replays
== Activar les repeticions
@ -1089,9 +1071,6 @@ Getting server list from master server
%d player
== %d jugador
Refreshing...
== Actualitzant...
Leak IP
== Fer la teva ip pública
@ -1261,9 +1240,6 @@ default
custom
== personalitzat
Graphics cards
== Tarjetes gràfiques
auto
== auto
@ -1377,7 +1353,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1389,6 +1365,9 @@ Loading menu images
Copy info
==
No server selected
==
Online players (%d)
==
@ -1441,10 +1420,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1456,9 +1435,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1510,10 +1501,10 @@ Open the directory to add custom skins
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1524,9 +1515,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1539,7 +1527,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1548,9 +1536,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1560,18 +1545,21 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Allows maps to render with more detail
==
Graphics card
==
Appearance
==

View file

@ -76,12 +76,6 @@ Clan
Client
== Клиент
Close
== Хупма
Connect
== Çых
Connecting to
== Çыхăну
@ -347,9 +341,6 @@ Rename demo
Reset filter
== Фильтрсене тасат
Sample rate
== Тăтăшлăх
Score
== Паллă
@ -759,7 +750,7 @@ Your nickname '%s' is already used (%d points). Do you still want to use it?
Checking for existing player with your name
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -834,9 +825,6 @@ Exclude
%d player
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -861,6 +849,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -892,18 +883,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan
==
Select a name
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Remove chat
==
Play the current demo
==
@ -925,10 +904,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -940,9 +919,30 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Remove chat
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Loading demo files
==
@ -1162,10 +1162,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1176,9 +1176,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1191,7 +1188,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1200,9 +1197,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1212,15 +1206,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1236,10 +1230,10 @@ Windowed fullscreen
Desktop fullscreen
==
may cause delay
Screen
==
Screen
may cause delay
==
Allows maps to render with more detail
@ -1257,7 +1251,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto
@ -1284,9 +1278,6 @@ Enable team chat sound
Enable highlighted chat sound
==
Threaded sound loading
==
Game sound volume
==
@ -1488,7 +1479,7 @@ Save the best demo of each race
Enable replays
==
Default length: %d
Default length
==
When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1506,10 +1497,10 @@ Gameplay
Overlay entities
==
Size
Show text entities
==
Show text entities
Size
==
Opacity
@ -1542,9 +1533,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths
==
Old mouse mode
==
Background
==

View file

@ -79,12 +79,6 @@ Clan
Client
== Klient
Close
== Zavřít
Connect
== Připojit
Connecting to
== Připojuji na
@ -346,9 +340,6 @@ Rename demo
Reset filter
== Vymazat filtr
Sample rate
== Vzorkování:
Score
== Skóre
@ -687,9 +678,6 @@ Update now
Restart
== Restartovat
Select a name
== Vyberte jméno
Please use a different name
== Použijte jiné jméno
@ -861,9 +849,6 @@ Enable team chat sound
Enable highlighted chat sound
== Povolit zvuk zvýrazněné zprávy
Threaded sound loading
== Načítání Threaded zvuku
Map sound volume
== Hlasitost zvuků mapy
@ -915,8 +900,8 @@ Normal message
Save the best demo of each race
== Uložte si nejlepší demo každého závodu
Default length: %d
== Výchozí délka: %d
Default length
== Výchozí délka
Enable replays
== Povolit záznamy
@ -963,9 +948,6 @@ Show other players' hook collision lines
Show other players' key presses
== Zobrazit stisknutí kláves ostatních hráčů
Old mouse mode
== Starý režim myši
Show tiles layers from BG map
== Zobrazit vrstvy dlaždic z mapy BG
@ -1273,7 +1255,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1312,9 +1294,6 @@ CHN
Getting server list from master server
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -1324,6 +1303,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -1376,10 +1358,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1391,9 +1373,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1454,10 +1448,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1468,9 +1462,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1483,7 +1474,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1492,9 +1483,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1504,15 +1492,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1540,7 +1528,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto

View file

@ -77,12 +77,6 @@ Clan
Client
== Klient
Close
== Luk
Connect
== Tilslut
Connecting to
== Forbinder til
@ -348,9 +342,6 @@ Rename demo
Reset filter
== Nulstil filter
Sample rate
== Sample frekvens
Score
== Score
@ -716,9 +707,6 @@ Countries
Types
== Typer
Select a name
== Vælg et navn
Please use a different name
== Brug et andet navn
@ -911,9 +899,6 @@ Enable team chat sound
Enable highlighted chat sound
== Aktivér fremhævet chatlyd
Threaded sound loading
== Trådet lydindlæsning
Game sound volume
== Spillydstyrke
@ -983,8 +968,8 @@ Client message
Save the best demo of each race
== Gem den bedste demo af hvert løb
Default length: %d
== Standardlængde: %d
Default length
== Standardlængde
Enable replays
== Aktivér gentagelser
@ -1031,9 +1016,6 @@ Show other players' hook collision lines
Show other players' key presses
== Vis andre spillers tastetryk
Old mouse mode
== Gammel musetilstand
Use current map as background
== Brug det aktuelle kort som baggrund
@ -1271,7 +1253,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1310,9 +1292,6 @@ CHN
Getting server list from master server
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -1322,6 +1301,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -1374,10 +1356,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1389,9 +1371,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1452,10 +1446,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1466,9 +1460,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1481,7 +1472,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1490,9 +1481,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1502,15 +1490,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1538,7 +1526,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto

View file

@ -89,12 +89,6 @@ Clan
Client
== Client
Close
== Sluiten
Connect
== Verbinden
Connecting to
== Verbinden met
@ -360,9 +354,6 @@ Rename demo
Reset filter
== Herstel filter
Sample rate
== Voorbeeldssnelheid
Score
== Score
@ -710,9 +701,6 @@ Update now
Restart
== Herstarten
Select a name
== Selecteer een naam
Please use a different name
== Gebruik a.u.b. een andere naam
@ -883,9 +871,6 @@ Enable team chat sound
Enable highlighted chat sound
== Schakel gemarkeerde chat geluiden in
Threaded sound loading
== Threaded geluid laden
Map sound volume
== Map geluid volume
@ -937,8 +922,8 @@ Normal message
Save the best demo of each race
== Sla de beste demo op van elke race
Default length: %d
== Standaard lengte: %d
Default length
== Standaard lengte
Enable replays
== Replays aanzetten
@ -985,9 +970,6 @@ Show other players' hook collision lines
Show other players' key presses
== Laat toetsaanslagen van andere spelers zien
Old mouse mode
== Oude muis modus
Show tiles layers from BG map
== Laat tegellagen van achtergrondmap zien
@ -1132,9 +1114,6 @@ Getting server list from master server
%d player
== %d speler
Refreshing...
== Aan het verversen...
Leak IP
== Lek IP
@ -1201,9 +1180,6 @@ default
custom
== custom
Graphics cards
== Grafische kaart
auto
== Automatisch
@ -1423,7 +1399,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1435,6 +1411,9 @@ Loading menu images
Copy info
==
No server selected
==
Online players (%d)
==
@ -1487,10 +1466,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1502,9 +1481,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1550,10 +1541,10 @@ Open the directory to add custom skins
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1564,9 +1555,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1579,7 +1567,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1588,9 +1576,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1600,15 +1585,18 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Graphics card
==
Appearance
==

View file

@ -255,12 +255,6 @@ Server address:
Refresh
== Aktualigi
Refreshing...
== Aktualas...
Connect
== Konektiĝi
Count players only
== Nur nombri ludantojn
@ -294,18 +288,12 @@ Add Friend
Filter
== Filtri
Select a name
== Elekti nomon
Please use a different name
== Bonvolu uzi malsaman nomon
Remove chat
== Malmontri la diskutejon
Close
== Fermi
Folder
== Dosierujo
@ -727,7 +715,7 @@ Use k key to kill (restart), q to pause and watch other players. See settings fo
It's recommended that you check the settings to adjust them to your liking before joining a server.
==
Cancel
A demo with this name already exists
==
Unable to rename the demo
@ -799,6 +787,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -836,9 +827,6 @@ Add Clan
Info
==
File already exists, do you want to overwrite it?
==
Play the current demo
==
@ -860,10 +848,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -875,12 +863,27 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Demofile: %s
==
Export demo cut
==
Cut interval
==
Cut length
==
File already exists, do you want to overwrite it?
==
Loading demo files
==
@ -1178,10 +1181,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1192,9 +1195,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1207,7 +1207,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1216,18 +1216,12 @@ Status
Aim bind
==
Controller Axis #%d
==
Ingame mouse sens.
==
UI mouse sens.
==
Controller
==
Movement
==
@ -1240,6 +1234,9 @@ Reset controls
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Voting
==
@ -1291,7 +1288,7 @@ Renderer
custom
==
Graphics cards
Graphics card
==
Play background music
@ -1321,12 +1318,6 @@ Enable team chat sound
Enable highlighted chat sound
==
Threaded sound loading
==
Sample rate
==
Sound volume
==
@ -1525,7 +1516,7 @@ Save the best demo of each race
Enable replays
==
Default length: %d
Default length
==
When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1543,10 +1534,10 @@ Gameplay
Overlay entities
==
Size
Show text entities
==
Show text entities
Size
==
Opacity
@ -1579,9 +1570,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths
==
Old mouse mode
==
Background
==

View file

@ -78,12 +78,6 @@ Clan
Client
== Asiakasohjelma
Close
== Sulje
Connect
== Yhdistä
Connecting to
== Yhdistetään
@ -349,9 +343,6 @@ Rename demo
Reset filter
== Nollaa suotimet
Sample rate
== Näytteenottotaajuus
Score
== Pisteet
@ -748,9 +739,6 @@ Types
Leak IP
== Vuoda IP
Select a name
== Valitse nimi
Please use a different name
== Ole hyvä ja käytä toista nimeä
@ -928,9 +916,6 @@ Enable team chat sound
Enable highlighted chat sound
== Ota korostetun chatin äänet käyttöön
Threaded sound loading
== Säikeistetty äänilataus
Game sound volume
== Pelin äänenvoimakkuus
@ -997,8 +982,8 @@ Preview
Save the best demo of each race
== Tallenna jokaisen kentän paras demo
Default length: %d
== Oletuspituus: %d
Default length
== Oletuspituus
Enable replays
== Luo uudelleentoistoja
@ -1036,9 +1021,6 @@ Show other players' hook collision lines
Show other players' key presses
== Näytä muiden pelaajien näppäinpainallukset
Old mouse mode
== Vanha hiiritila
Background
== Tausta
@ -1255,7 +1237,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1270,15 +1252,15 @@ Skip Tutorial
Loading menu images
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
Copy info
==
No server selected
==
Online players (%d)
==
@ -1331,10 +1313,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1346,9 +1328,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1433,10 +1427,10 @@ Show entities
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1447,9 +1441,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1462,7 +1453,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1471,9 +1462,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1483,15 +1471,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Windowed fullscreen
==
@ -1507,7 +1495,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto

View file

@ -100,12 +100,6 @@ Clan
Client
== Client
Close
== Fermer
Connect
== Se connecter
Connecting to
== Connexion à
@ -371,9 +365,6 @@ Rename demo
Reset filter
== Filtres par défaut
Sample rate
== Taux d'échantillonnage
Score
== Score
@ -691,9 +682,6 @@ Are you sure that you want to disconnect your dummy?
Reload
== Recharger
Old mouse mode
== Ancien mode de souris
Server best:
== Meilleur score du serveur
@ -787,9 +775,6 @@ Update failed! Check log...
Reset
== Défaut
Threaded sound loading
== Chargement des sons dans un thread spécifique
File already exists, do you want to overwrite it?
== Ce fichier existe déjà, voulez-vous l'écraser ?
@ -922,8 +907,8 @@ Show others
Unfinished map
== Carte non terminée
Default length: %d
== Durée par défaut : %d
Default length
== Durée par défaut
Highlighted message
== Message en surbrillance
@ -952,9 +937,6 @@ Ghost
Show kill messages
== Afficher les messages d'élimination
Select a name
== Choisissez un pseudonyme
Markers
== Marqueurs
@ -1259,9 +1241,6 @@ https://ddnet.org/discord
Are you sure that you want to disconnect and switch to a different server?
== Êtes vous sur de vouloir vous déconnecter et changer de serveur?
Refreshing...
== Actualisation...
Show local player's key presses
== Montrer les touches appuyées des autres joueurs
@ -1307,9 +1286,6 @@ default
custom
== Personnalisé
Graphics cards
== Carte graphique
auto
== Automatique
@ -1367,13 +1343,6 @@ Download community skins
Enable controller
== Activer la manette
Controller %d: %s
== Manette %d: %s
Click to cycle through all available controllers.
== Cliquez pour essayer toutes les manettes disponibles.
[Ingame controller mode]
Relative
== Relatif
@ -1393,18 +1362,12 @@ UI controller sens.
Controller jitter tolerance
== Tolérance gigue de la manette
Device
== Manette
Status
== Statut
Aim bind
== Touche visée
Controller Axis #%d
== Axe manette #%d
Mouse
== Souris
@ -1564,12 +1527,6 @@ Slow down the demo
Speed up the demo
== Accélérer la démo
Mark the beginning of a cut
== Marquer le début d'une coupe
Mark the end of a cut
== Marquer la fin d'une coupe
Export cut as a separate demo
== Exporter la coupe comme une démo séparée
@ -1743,3 +1700,33 @@ Add Clan
Create a random skin
== Créer un skin aléatoire
A demo with this name already exists
==
No server selected
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -91,15 +91,9 @@ Clan
Client
== Client
Close
== Schließ.
Colors of the hook collision line, in case of a possible collision with:
== Die Farbe der Hakenkollisionlinie bei einer möglichen Kollision mit:
Connect
== Verbinden
Connecting to
== Verbinden mit
@ -368,9 +362,6 @@ Rename demo
Reset filter
== Standardfilter
Sample rate
== Abtastrate
Score
== Punkte
@ -794,9 +785,6 @@ Switch weapon when out of ammo
Grabs
== Griffe
Select a name
== Namen wählen
Automatically take game over screenshot
== Automatisches Bildschirmfoto am Spielende
@ -809,9 +797,6 @@ Gameplay
Laser
== Laser
Old mouse mode
== Alter Mausmodus
Follow
== Folgen
@ -827,9 +812,6 @@ Show tiles layers from BG map
Remove chat
== Chat entfernen
Threaded sound loading
== Sounds in Threads laden
Frags
== Abschüsse
@ -1025,8 +1007,8 @@ Replace video
DDraceNetwork is a cooperative online game where the goal is for you and your group of tees to reach the finish line of the map. As a newcomer you should start on Novice servers, which host the easiest maps. Consider the ping to choose a server close to you.
== DDraceNetwork ist ein kooperatives Onlinespiel mit dem Ziel für dich und deine Gruppe von Tees das Ziel der Karte zu erreichen. Als Anfänger solltest du auf den Novice-Servern anfangen, auf denen die einfachsten Karten sind. Achte auf den Ping, um einen Server in deiner Nähe zu finden.
Default length: %d
== Standardlänge: %d
Default length
== Standardlänge
Pause
== Pause
@ -1290,9 +1272,6 @@ A Tee
Are you sure that you want to disconnect and switch to a different server?
== Bist du sicher, dass du die Verbindung trennen und zu einem anderen Server wechseln möchtest?
Refreshing...
== Aktualisieren...
Kill Messages
== Kill-Nachrichten
@ -1332,9 +1311,6 @@ default
custom
== eigene
Graphics cards
== Grafikkarte
auto
== Auto
@ -1398,9 +1374,6 @@ No answer from server yet.
Download community skins
== Community-Skins runterladen
Device
== Gerät
Status
== Status
@ -1434,13 +1407,6 @@ UI mouse sens.
Enable controller
== Controller aktivieren
Controller %d: %s
== Controller %d: %s
Click to cycle through all available controllers.
== Klicke um durch die verfügbaren Controller zu wechseln.
[Ingame controller mode]
Relative
== Relativ
@ -1460,9 +1426,6 @@ UI controller sens.
Controller jitter tolerance
== Jitter-Toleranz des Controllers
Controller Axis #%d
== Controller-Axe #%d
Controller
== Controller
@ -1589,12 +1552,6 @@ Freeze Laser Outline Color
Freeze Laser Inner Color
== Innenfarbe Einfrier-Laser
Mark the beginning of a cut
== Den Anfang eines Schnitts markieren
Mark the end of a cut
== Das Ende eines Schnitts markieren
Menu opened. Press Esc key again to close menu.
== Menü geöffnet. Erneut Esc-Taste drücken um Menü zu schließen.
@ -1733,3 +1690,33 @@ None
Add Clan
== Clan hinzufügen
A demo with this name already exists
== Eine Demo mit diesem Namen existiert bereits
No server selected
== Kein Server ausgewählt
Mark the beginning of a cut (right click to reset)
== Den Anfang eines Schnitts markieren (Rechtsklick zum Resetten)
Mark the end of a cut (right click to reset)
== Das Ende eines Schnitts markieren (Rechtsklick zum Resetten)
Close the demo player
== Den Demo-Player schließen
Export demo cut
== Demo-Schnitt exportieren
Cut interval
== Intervall des Schnitts
Cut length
== Länge des Schnitts
Axis
== Achse
Graphics card
== Grafikkarte

View file

@ -76,12 +76,6 @@ Clan
Client
== Πελάτης
Close
== Κλείσιμο
Connect
== Σύνδεση
Connecting to
== Σύνδεση με
@ -350,9 +344,6 @@ Rename demo
Reset filter
== Αφαίρεση φίλτρου
Sample rate
== Δειγματοληψία
Score
== Βαθμ.
@ -762,7 +753,7 @@ Your nickname '%s' is already used (%d points). Do you still want to use it?
Checking for existing player with your name
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -837,9 +828,6 @@ Exclude
%d player
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -864,6 +852,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -895,18 +886,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan
==
Select a name
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Remove chat
==
Play the current demo
==
@ -928,10 +907,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -943,9 +922,30 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Remove chat
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Loading demo files
==
@ -1165,10 +1165,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1179,9 +1179,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1194,7 +1191,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1203,9 +1200,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1215,15 +1209,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1239,10 +1233,10 @@ Windowed fullscreen
Desktop fullscreen
==
may cause delay
Screen
==
Screen
may cause delay
==
Allows maps to render with more detail
@ -1260,7 +1254,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto
@ -1287,9 +1281,6 @@ Enable team chat sound
Enable highlighted chat sound
==
Threaded sound loading
==
Game sound volume
==
@ -1488,7 +1479,7 @@ Save the best demo of each race
Enable replays
==
Default length: %d
Default length
==
When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1506,10 +1497,10 @@ Gameplay
Overlay entities
==
Size
Show text entities
==
Show text entities
Size
==
Opacity
@ -1542,9 +1533,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths
==
Old mouse mode
==
Background
==

View file

@ -78,12 +78,6 @@ Clan
Client
== Kliens
Close
== Bezárás
Connect
== Csatlakozás
Connecting to
== Csatlakozás...
@ -340,9 +334,6 @@ Rename demo
Reset filter
== Szűrő visszaállítása
Sample rate
== Mintavételi frekvencia
Score
== Pontszám
@ -625,9 +616,6 @@ Spectate next
Show names in chat in team colors
== Csapatszínben jelennek meg a játékosok a chatben
Select a name
== Válassz nevet
Enable team chat sound
== Csapat chat hang engedélyezése
@ -658,9 +646,6 @@ Restart
Game paused
== Játék megállítva
Old mouse mode
== Régi egér mód
Browser
== Böngésző
@ -856,9 +841,6 @@ Deactivate
Welcome to DDNet
== Üdvözlet a DDNet-en
Threaded sound loading
== Csavarmenetes hang betöltése
Activate
== Aktiválás
@ -976,8 +958,8 @@ Toggle dyncam
%d new mentions
== %d új értesítés
Default length: %d
== Átlagos hossz: %d
Default length
== Átlagos hossz
Show HUD
== HUD mutatása
@ -1223,9 +1205,6 @@ SA
CHN
== KíNA
Refreshing...
== Frissítés...
Kill Messages
== Halálüzenetek
@ -1283,9 +1262,6 @@ default
custom
== egyedi
Graphics cards
== Videókártyák
auto
== automatikus
@ -1343,13 +1319,6 @@ Download community skins
Enable controller
== Kontroller használata
Controller %d: %s
== Kontroller %d: %s
Click to cycle through all available controllers.
== Kattints, hogy váltogass az elérhető kontrollerek között.
[Ingame controller mode]
Relative
== Relatív
@ -1369,15 +1338,9 @@ UI controller sens.
Controller jitter tolerance
== Kontroller jitter tolerancia
Device
== Eszköz
Status
== Állapot
Controller Axis #%d
== Kontroller Tengely #%d
Mouse
== Egér
@ -1575,37 +1538,12 @@ File '%s' already exists, do you want to overwrite it?
Copy info
== Infó Másolása
Online players (%d)
==
Online clanmates (%d)
==
[friends (server browser)]
Offline (%d)
==
Click to select server. Double click to join your friend.
==
Click to remove this player from your friends list.
==
Click to remove this clan from your friends list.
==
None
==
Are you sure that you want to remove the player '%s' from your friends list?
== Biztos, hogy ki szeretnéd törölni '%s' Játékost a barátlistádból?
Are you sure that you want to remove the clan '%s' from your friends list?
== Biztos, hogy ki szeretnéd törölni '%s' Klánt a barátlistádból?
Add Clan
==
Play the current demo
== Jelenlegi Demó Lejátszása
@ -1627,12 +1565,6 @@ Slow down the demo
Speed up the demo
== Demó Felgyorsítása
Mark the beginning of a cut
== Jelöld be a vágás elejét
Mark the end of a cut
== Jelöld be a vágás végét
Export cut as a separate demo
== Exportáld a vágást, mint külön Demó
@ -1719,3 +1651,58 @@ Unregister protocol and file extensions
Open the directory to add custom assets
== Megnyitni az egyedi Képek helyét
A demo with this name already exists
==
No server selected
==
Online players (%d)
==
Online clanmates (%d)
==
[friends (server browser)]
Offline (%d)
==
Click to select server. Double click to join your friend.
==
Click to remove this player from your friends list.
==
Click to remove this clan from your friends list.
==
None
==
Add Clan
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -81,12 +81,6 @@ Clan
Client
== Client
Close
== Chiudi
Connect
== Connetti
Connecting to
== Connessione a
@ -352,9 +346,6 @@ Rename demo
Reset filter
== Azzera filtri
Sample rate
== Frequenza
Score
== Punti
@ -766,9 +757,6 @@ Countries
Types
== Tipi
Select a name
== Seleziona un nome
Please use a different name
== Per favore usa un nome differente
@ -943,9 +931,6 @@ Enable team chat sound
Enable highlighted chat sound
== Abilita suono della chat evidenziata
Threaded sound loading
== Suono filettato
Game sound volume
== Volume del gioco
@ -1015,8 +1000,8 @@ Client message
Save the best demo of each race
== Salva la miglior demo di ogni partita
Default length: %d
== Lunghezza predefinita: %d
Default length
== Lunghezza predefinita
Enable replays
== Abilita i replay
@ -1060,9 +1045,6 @@ Show other players' hook collision lines
Show other players' key presses
== Mostra i tasti degli altri giocatori
Old mouse mode
== Modalità mouse vecchio
Use current map as background
== Usa la mappa attuale come sfondo
@ -1289,7 +1271,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1328,9 +1310,6 @@ CHN
Getting server list from master server
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -1340,6 +1319,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -1392,10 +1374,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1407,9 +1389,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1482,10 +1476,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1496,9 +1490,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1511,7 +1502,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1520,9 +1511,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1532,15 +1520,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1568,7 +1556,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto

View file

@ -76,12 +76,6 @@ Clan
Client
== クライアント
Close
== 閉じる
Connect
== 接続
Connecting to
== 接続先
@ -344,9 +338,6 @@ Rename demo
Reset filter
== フィルタをリセット
Sample rate
== サンプルレート
Score
== スコア
@ -724,9 +715,6 @@ Types
Leak IP
== IP を漏洩する
Select a name
== 名前をつけて保存
Please use a different name
== 別の名前をつけてください
@ -937,9 +925,6 @@ Enable team chat sound
Enable highlighted chat sound
== メンション・メッセージ受信音
Threaded sound loading
== マルチスレッド音声読み込み
Game sound volume
== ゲーム SFX 音量
@ -1009,8 +994,8 @@ Preview
Save the best demo of each race
== レースの最高記録のデモを保存
Default length: %d
== デフォルト長さ%D
Default length
== デフォルト長さ
Enable replays
== リプレイ機能
@ -1057,9 +1042,6 @@ Show other players' hook collision lines
Show other players' key presses
== 他のプレーヤーの押したキーを表示
Old mouse mode
== 古いマウスモード
Background
== 背景
@ -1309,7 +1291,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1345,15 +1327,15 @@ SA
CHN
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
Copy info
==
No server selected
==
Online players (%d)
==
@ -1406,10 +1388,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1421,9 +1403,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1481,10 +1475,10 @@ Open the directory to add custom skins
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1495,9 +1489,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1510,7 +1501,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1519,9 +1510,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1531,15 +1519,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Windowed fullscreen
==
@ -1555,7 +1543,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto

View file

@ -88,12 +88,6 @@ Clan
Client
== 클라이언트
Close
== 닫기
Connect
== 연결
Connecting to
== 연결 중
@ -350,9 +344,6 @@ Rename demo
Reset filter
== 필터 초기화
Sample rate
== 샘플링 속도
Score
== 점수
@ -724,9 +715,6 @@ Exclude
%d player
== %d 플레이어
Refreshing...
== 새로고침 중...
Filter connecting players
== 접속 중인 플레이어 제외
@ -745,9 +733,6 @@ Types
Leak IP
== IP 노출하기
Select a name
== 다른 이름으로 저장
Please use a different name
== 다른 이름을 사용해 주십시오
@ -961,9 +946,6 @@ Enable team chat sound
Enable highlighted chat sound
== 언급된 채팅 소리 활성화
Threaded sound loading
== 다중 스레드 소리 로딩
Game sound volume
== 게임 음량
@ -1036,8 +1018,8 @@ Preview
Save the best demo of each race
== 레이스 최고 기록의 데모를 저장
Default length: %d
== 기본 길이: %d
Default length
== 기본 길이
Enable replays
== 리플레이 활성화
@ -1087,9 +1069,6 @@ Show other players' key presses
Show local player's key presses
== 주변 플레이어의 키 입력 표시
Old mouse mode
== 구식 마우스 모드
Background
== 배경
@ -1286,9 +1265,6 @@ default
custom
== 커스텀
Graphics cards
== 그래픽 카드
auto
== 자동
@ -1355,13 +1331,6 @@ Download community skins
Enable controller
== 컨트롤러 활성화
Controller %d: %s
== 컨트롤러 %d: %s
Click to cycle through all available controllers.
== 사용가능한 컨트롤러로 전환하려면 클릭하십시오.
[Ingame controller mode]
Relative
== 상대적
@ -1381,18 +1350,12 @@ UI controller sens.
Controller jitter tolerance
== 컨트롤러 신호 오차 허용 범위
Device
== 장치
Status
== 상태
Aim bind
== 조준 바인드
Controller Axis #%d
== 컨트롤러 축
Mouse
== 마우스
@ -1552,12 +1515,6 @@ Slow down the demo
Speed up the demo
== 데모 속도 높이기
Mark the beginning of a cut
== 영상 자르기의 시작 부분
Mark the end of a cut
== 영상 자르기의 끝 부분
Export cut as a separate demo
== 자른 부분을 다른 이름으로 저장
@ -1707,6 +1664,12 @@ Copy info
Create a random skin
== 무작위 스킨 생성
A demo with this name already exists
==
No server selected
==
Online players (%d)
==
@ -1731,3 +1694,27 @@ None
Add Clan
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -72,12 +72,6 @@ Clan
Client
== Клиент
Close
== Чыгуу
Connect
== Туташуу
Connecting to
== Туташтырылууда
@ -412,9 +406,6 @@ Laser
Round
== Раунду
Sample rate
== Жыштыгы
Sat.
== Канык.
@ -753,7 +744,7 @@ Your nickname '%s' is already used (%d points). Do you still want to use it?
Checking for existing player with your name
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -828,9 +819,6 @@ Exclude
%d player
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -855,6 +843,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -886,18 +877,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan
==
Select a name
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Remove chat
==
Play the current demo
==
@ -919,10 +898,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -934,9 +913,30 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Remove chat
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Loading demo files
==
@ -1156,10 +1156,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1170,9 +1170,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1185,7 +1182,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1194,9 +1191,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1206,15 +1200,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1230,10 +1224,10 @@ Windowed fullscreen
Desktop fullscreen
==
may cause delay
Screen
==
Screen
may cause delay
==
Allows maps to render with more detail
@ -1251,7 +1245,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto
@ -1278,9 +1272,6 @@ Enable team chat sound
Enable highlighted chat sound
==
Threaded sound loading
==
Game sound volume
==
@ -1479,7 +1470,7 @@ Save the best demo of each race
Enable replays
==
Default length: %d
Default length
==
When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1497,10 +1488,10 @@ Gameplay
Overlay entities
==
Size
Show text entities
==
Show text entities
Size
==
Opacity
@ -1533,9 +1524,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths
==
Old mouse mode
==
Background
==

View file

@ -78,12 +78,6 @@ Clan
Client
== Klient
Close
== Lukk
Connect
== Koble til
Connecting to
== Kobler til
@ -349,9 +343,6 @@ Rename demo
Reset filter
== Tilbakestill filter
Sample rate
== Samplingsrate
Score
== Poeng
@ -699,9 +690,6 @@ Update now
Restart
== Restart
Select a name
== Velg et navn
Please use a different name
== Vennligst velg et annet navn
@ -873,9 +861,6 @@ Enable team chat sound
Enable highlighted chat sound
== Lyd for uthevet samtale
Threaded sound loading
== Trådet lyd-innlasting
Map sound volume
== Lydvolum bane
@ -927,8 +912,8 @@ Normal message
Save the best demo of each race
== Lagre beste demo for hvert løp
Default length: %d
== Standard lengde: %d
Default length
== Standard lengde
Enable replays
== Aktiver opptak
@ -975,9 +960,6 @@ Show other players' hook collision lines
Show other players' key presses
== Vis andre spilleres tastetrykk
Old mouse mode
== Gammel musemodus
Show tiles layers from BG map
== Vis tile-lag fra BG-bane
@ -1272,7 +1254,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1311,9 +1293,6 @@ CHN
Getting server list from master server
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -1323,6 +1302,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -1375,10 +1357,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1390,9 +1372,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1453,10 +1447,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1467,9 +1461,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1482,7 +1473,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1491,9 +1482,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1503,15 +1491,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1539,7 +1527,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto

View file

@ -76,12 +76,6 @@ Clan
Client
== ﺖﻨﯾﻼﻛ
Close
== ﻦﺘﺴﺑ
Connect
== ﻝﺎﺼﺗﺍ
Connecting to
== ﻪﺑ ﻥﺪﺷ ﻞﺻﻭ
@ -478,9 +472,6 @@ Server address:
Refresh
== ﯼﺯﺎﺳ ﻩﺯﺎﺗ
Refreshing...
== ... ﯼﺯﺎﺳ ﻩﺯﺎﺗ ﻝﺎﺣ ﺭﺩ
Server filter
== ﺭﻭﺮﺳ ﺮﺘﻠﯿﻓ
@ -526,9 +517,6 @@ Remove
Info
== ﺕﺎﻋﻼﻃﺍ
Select a name
== ﻡﺎﻧ ﮏﯾ ﺏﺎﺨﺘﻧﺍ
Please use a different name
== ﻦﮐ ﻩﺩﺎﻔﺘﺳﺍ ﺕﻭﺎﻔﺘﻣ ﻡﺎﻧ ﮏﯾ ﺯﺍ ﺎﻔﻄﻟ
@ -1052,12 +1040,6 @@ Slow down the demo
Speed up the demo
== ﻮﻣﺩ ﺖﻋﺮﺳ ﻥﺩﺮﮐ ﺩﺎﯾﺯ
Mark the beginning of a cut
== ﺵﺮﺑ ﻉﻭﺮﺷ ﻥﺩﺯ ﺖﻣﻼﻋ
Mark the end of a cut
== ﺵﺮﺑ ﻥﺎﯾﺎﭘ ﻥﺩﺯ ﺖﻣﻼﻋ
Export cut as a separate demo
== ﻪﻧﺎﮔﺍﺪﺟ ﻮﻣﺩ ﻥﺍﻮﻨﻋ ﻪﺑ ﺵﺮﺑ ﻥﺩﺮﮐ ﺝﺭﺎﺧ
@ -1184,10 +1166,6 @@ Statboard
Enable controller
== ﻦﮐ ﻝﺎﻌﻓ ﺍﺭ ﺮﻟﺮﺘﻨﮐ
Click to cycle through all available controllers.
== ﺪﯿﻨﮐ ﮏﯿﻠﮐ ﺩﻮﺟﻮﻣ ﯼﺎﻫﺮﻟﺮﺘﻨﮐ ﻡﺎﻤﺗ ﺭﺩ ﺶﺧﺮﭼ ﯼﺍﺮﺑ
[Ingame controller mode]
Relative
== ﯽﺒﺴﻧ [ﯼﺯﺎﺑ ﺮﻟﺮﺘﻨﮐ ﺖﻟﺎﺣ]
@ -1210,9 +1188,6 @@ Controller jitter tolerance
No controller found. Plug in a controller.
== ﺪﯿﻨﮐ ﻞﺻﻭ ﺮﻟﺮﺘﻨﮐ ﮏﯾ .ﺪﺸﻧ ﺍﺪﯿﭘ ﯼﺮﻟﺮﺘﻨﮐ ﭻﯿﻫ
Device
== ﻩﺎﮕﺘﺳﺩ
Status
== ﺖﯿﻌﺿﻭ
@ -1273,9 +1248,6 @@ default
custom
== ﯽﺷﺭﺎﻔﺳ
Graphics cards
== ﮏﯿﻓﺍﺮﮔ ﯼﺎﻫ ﺕﺭﺎﮐ
auto
== ﺭﺎﮐﺩﻮﺧ
@ -1288,12 +1260,6 @@ Enable regular chat sound
Enable highlighted chat sound
== ﻩﺪﺷ ﺖﯾﻼﯾﺎﻫ ﺖﭼ ﯼﺍﺪﺻ ﻥﺩﺮﮐ ﻦﺷﻭﺭ
Threaded sound loading
== ﯼﺍ ﻪﺘﺷﺭ ﯼﺍﺪﺻ ﯼﺭﺍﺬﮔﺭﺎﺑ
Sample rate
== ﻪﻧﻮﻤﻧ ﺥﺮﻧ
Appearance
== ﺮﻫﺎﻇ
@ -1483,8 +1449,8 @@ Set all to Rifle
Save the best demo of each race
== ﻪﻘﺑﺎﺴﻣ ﺮﻫ ﻮﻣﺩ ﻦﯾﺮﺘﻬﺑ ﻩﺮﯿﺧﺫ
Default length: %d
== %d :ﺽﺮﻓ‌ﺶﯿﭘ ﻝﻮﻃ
Default length
== ﺽﺮﻓ‌ﺶﯿﭘ ﻝﻮﻃ
When you cross the start line, show a ghost tee replicating the movements of your best time
== ﺪﻨﮐ ﯽﻣ ﺭﺍﺮﮑﺗ ﺍﺭ ﺎﻤﺷ ﻥﺎﻣﺯ ﻦﯾﺮﺘﻬﺑ ﺕﺎﮐﺮﺣ ﻪﮐ ﻩﺪﺑ ﺶﯾﺎﻤﻧ ﺍﺭ ﺡﻭﺭ ،ﺪﯿﻨﮐ ﯽﻣ ﺭﻮﺒﻋ ﻉﻭﺮﺷ ﻂﺧ ﺯﺍ ﻪﮐ ﯽﻣﺎﮕﻨﻫ
@ -1528,9 +1494,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths
== ﮏﺠﻧﺭﺎﻧ ﺮﯿﺴﻣ ﯽﻨﯿﺑ‌ﺶﯿﭘ AntiPing:
Old mouse mode
== ﯽﻤﯾﺪﻗ ﺱﻮﻣ ﺖﻟﺎﺣ
Entities Background color
== ﺖﯾﺩﻮﺟﻮﻣ ﻪﻨﯿﻣﺯﺲﭘ ﮓﻧﺭ
@ -1668,9 +1631,15 @@ The format of texture %s is not RGBA which will cause visual bugs.
Initializing map logic
==
A demo with this name already exists
==
Copy info
==
No server selected
==
Online players (%d)
==
@ -1696,13 +1665,31 @@ None
Add Clan
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Create a random skin
==
Controller %d: %s
Axis
==
Controller Axis #%d
Graphics card
==
Unregister protocol and file extensions

View file

@ -80,12 +80,6 @@ Clan
Client
== Klient
Close
== Zamknij
Connect
== Połącz
Connecting to
== Łączenie z
@ -351,9 +345,6 @@ Rename demo
Reset filter
== Przywróć domyślne
Sample rate
== Częstotliwość próbkowania
Score
== Wynik
@ -653,9 +644,6 @@ Default zoom
Overlay entities
== Pokazuj entities
Select a name
== Wybierz nazwę
Switch weapon when out of ammo
== Zmień broń, gdy skończy się amunicja
@ -719,9 +707,6 @@ Enable team chat sound
Enable highlighted chat sound
== Włącz dźwięk wyróżnionej wiadomości
Threaded sound loading
== Wątkowe ładowanie dźwięku
Map sound volume
== Glośność dźwięków z map
@ -899,9 +884,6 @@ Toggle ghost
Replace video
== Zamień wideo
Old mouse mode
== Tryb starej myszki
Lock team
== Zablokuj drużynę
@ -953,8 +935,8 @@ Markers:
%d new mentions
== %d razy wspomniano o tobie
Default length: %d
== Domyślna długość: %d
Default length
== Domyślna długość
Refresh Rate
== Częstotliwość próbkowania
@ -1209,9 +1191,6 @@ CHN
Getting server list from master server
== Pobieranie listy serwerów z serwera głównego
Refreshing...
== Odświeżanie
Leak IP
== Ujawnij IP
@ -1257,9 +1236,6 @@ default
custom
== niestandardowy
Graphics cards
== Karty graficzne
auto
== automatyczny
@ -1415,7 +1391,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1427,6 +1403,9 @@ Loading menu images
Copy info
==
No server selected
==
Online players (%d)
==
@ -1479,10 +1458,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1494,9 +1473,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1542,10 +1533,10 @@ Open the directory to add custom skins
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1556,9 +1547,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1571,7 +1559,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1580,9 +1568,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1592,15 +1577,18 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Graphics card
==
Appearance
==

View file

@ -80,12 +80,6 @@ Clan
Client
== Cliente
Close
== Fechar
Connect
== Ligar
Connecting to
== A ligar ao endereço
@ -363,9 +357,6 @@ Reset
Reset filter
== Reiniciar filtro
Sample rate
== Frequencia de rate
Score
== Pontos
@ -642,9 +633,6 @@ HUD
Show names in chat in team colors
== Mostrar nomes no chat com cores da equipa
Select a name
== Escolha um nome
Enable team chat sound
== Ativar o som do chat de equipa
@ -669,9 +657,6 @@ Gameplay
Restart
== Reiniciar
Old mouse mode
== Modo de rato antigo
Browser
== Navegador
@ -858,9 +843,6 @@ Theme
%d player
== %d jogador
Refreshing...
== A atualizar...
Date
== Data
@ -1081,7 +1063,7 @@ DDraceNetwork is a cooperative online game where the goal is for you and your gr
Use k key to kill (restart), q to pause and watch other players. See settings for other key binds.
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1141,6 +1123,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -1193,10 +1178,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1208,9 +1193,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1361,10 +1358,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1375,9 +1372,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1390,7 +1384,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1399,9 +1393,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1411,15 +1402,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Windowed fullscreen
==
@ -1441,7 +1432,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto
@ -1450,9 +1441,6 @@ auto
Enable long pain sound (used when shooting in freeze)
==
Threaded sound loading
==
Appearance
==
@ -1585,7 +1573,7 @@ Set all to Rifle
Enable replays
==
Default length: %d
Default length
==
When you cross the start line, show a ghost tee replicating the movements of your best time

View file

@ -82,12 +82,6 @@ Clan
Client
== Clientul
Close
== Închide
Connect
== Conectează
Connecting to
== Conectare la
@ -356,9 +350,6 @@ Rename demo
Reset filter
== Filtru implicit
Sample rate
== Frecvența
Score
== Scor
@ -768,7 +759,7 @@ Your nickname '%s' is already used (%d points). Do you still want to use it?
Checking for existing player with your name
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -843,9 +834,6 @@ Exclude
%d player
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -870,6 +858,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -901,18 +892,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan
==
Select a name
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Remove chat
==
Play the current demo
==
@ -934,10 +913,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -949,9 +928,30 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Remove chat
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Loading demo files
==
@ -1171,10 +1171,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1185,9 +1185,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1200,7 +1197,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1209,9 +1206,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1221,15 +1215,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1245,10 +1239,10 @@ Windowed fullscreen
Desktop fullscreen
==
may cause delay
Screen
==
Screen
may cause delay
==
Allows maps to render with more detail
@ -1266,7 +1260,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto
@ -1293,9 +1287,6 @@ Enable team chat sound
Enable highlighted chat sound
==
Threaded sound loading
==
Game sound volume
==
@ -1494,7 +1485,7 @@ Save the best demo of each race
Enable replays
==
Default length: %d
Default length
==
When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1512,10 +1503,10 @@ Gameplay
Overlay entities
==
Size
Show text entities
==
Show text entities
Size
==
Opacity
@ -1548,9 +1539,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths
==
Old mouse mode
==
Background
==

View file

@ -89,12 +89,6 @@ Clan
Client
== Клиент
Close
== Закрыть
Connect
== Подключиться
Connecting to
== Подключение к
@ -360,9 +354,6 @@ Rename demo
Reset filter
== Сбросить фильтры
Sample rate
== Частота
Score
== Счёт
@ -540,9 +531,6 @@ Enable team chat sound
Enable highlighted chat sound
== Звуки подсвечиваемых сообщений
Threaded sound loading
== Фоновая загрузка музыки
Use DDRace Scoreboard
== Использовать DDRace таблицу счета
@ -672,9 +660,6 @@ Show ghost
No updates available
== Нет доступных обновлений
Select a name
== Выберите имя
Show other players' hook collision lines
== Показывать коллизии крюка других игроков
@ -690,9 +675,6 @@ Show others
Game paused
== Пауза
Old mouse mode
== Режим старой мыши
Team message
== Сообщение от команды
@ -948,8 +930,8 @@ Friend message
Save the best demo of each race
== Сохранять лучшее демо каждой карты
Default length: %d
== Станд. длина: %d
Default length
== Станд. длина
Enable replays
== Включить записи
@ -1243,9 +1225,6 @@ Desktop fullscreen
Are you sure that you want to disconnect and switch to a different server?
== Вы уверены, что хотите отключиться и перейти на другой сервер?
Refreshing...
== Обновление...
Kill Messages
== Сообщения о смерти
@ -1279,9 +1258,6 @@ default
custom
== перс.
Graphics cards
== Видеокарты
auto
== авто
@ -1330,13 +1306,6 @@ Choose default eyes when joining a server
Enable controller
== Включить контроллер
Controller %d: %s
== Контроллер %d: %s
Click to cycle through all available controllers.
== Нажмите для переключения между всеми доступными контроллерами.
[Ingame controller mode]
Relative
== Относительный
@ -1356,18 +1325,12 @@ UI controller sens.
Controller jitter tolerance
== Устойчивость к движению контроллера
Device
== Устройство
Status
== Состояние
Aim bind
== Привязка оси
Controller Axis #%d
== Ось контроллера #%d
Mouse
== Мышь
@ -1551,12 +1514,6 @@ Slow down the demo
Speed up the demo
== Ускорить демо
Mark the beginning of a cut
== Отметить начало участка
Mark the end of a cut
== Отметить конец участка
Export cut as a separate demo
== Экспортировать участок отдельно
@ -1728,3 +1685,33 @@ None
Add Clan
== Добавить клан
A demo with this name already exists
==
No server selected
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -80,12 +80,6 @@ Clan
Client
== Klijent
Close
== Zatvori
Connect
== Poveži se
Connecting to
== Povezujem se na
@ -347,9 +341,6 @@ Rename demo
Reset filter
== Povrati filter
Sample rate
== Frekfencija
Score
== Rezultat
@ -724,9 +715,6 @@ Countries
Types
== Tipovi
Select a name
== Izaberite ime
Please use a different name
== Izaberite drugo ime
@ -905,9 +893,6 @@ Enable team chat sound
Enable highlighted chat sound
== Omogući istaknuti zvuk dopisivanja
Threaded sound loading
== Učitavanje zvuka sa navojem
Map sound volume
== Jačina zvuka na mapi
@ -962,8 +947,8 @@ Client message
Save the best demo of each race
== Sačuvajte najbolji snimak svake trke
Default length: %d
== Podrazumevana dužina: %d
Default length
== Podrazumevana dužina
Enable replays
== Omogući ponovljene reprodukcije
@ -1007,9 +992,6 @@ Show other players' hook collision lines
Show other players' key presses
== Prikaži pritiske tastera drugih igrača
Old mouse mode
== Stari mod miša
Show tiles layers from BG map
== Prikaži slojeve pločica sa BG mape
@ -1242,9 +1224,6 @@ CHN
Getting server list from master server
== Dobijam listu servera sa master servera
Refreshing...
== Osvežavanje
Leak IP
== Provali adresu
@ -1281,13 +1260,6 @@ Chat command
Enable controller
== Uključi kontroler
Controller %d: %s
== Kontroler %d: %s
Click to cycle through all available controllers.
== Klikni da vidiš sve slobodne kontroleres
[Ingame controller mode]
Relative
== Relativno
@ -1307,18 +1279,12 @@ UI controller sens.
Controller jitter tolerance
== Tolerancija kontrolera
Device
== Uređaj
Status
== Status
Aim bind
== Nišan
Controller Axis #%d
== Stik %d.
Mouse
== Miš
@ -1358,9 +1324,6 @@ default
custom
== svoje
Graphics cards
== Grafička kartica
auto
== auto
@ -1567,7 +1530,7 @@ Could not save downloaded map. Try manually deleting this file: %s
Initializing components
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1579,6 +1542,9 @@ transmits your player name to info.ddnet.org
Copy info
==
No server selected
==
Online players (%d)
==
@ -1631,10 +1597,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1646,9 +1612,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Open the directory that contains the demo files
==
@ -1682,12 +1660,21 @@ Open the directory to add custom skins
No controller found. Plug in a controller.
==
Axis
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Graphics card
==
Weapons
==

View file

@ -76,12 +76,6 @@ Clan
Client
== Клијент
Close
== Затвори
Connect
== Повежи се
Connecting to
== Повезујем се на
@ -343,9 +337,6 @@ Rename demo
Reset filter
== Поврати филтер
Sample rate
== Фрекфенција
Score
== Резултат
@ -723,9 +714,6 @@ Countries
Types
== Типови
Select a name
== Изаберите име
Please use a different name
== Изаберите друго име
@ -904,9 +892,6 @@ Enable team chat sound
Enable highlighted chat sound
== Омогући истакнути звук дописивања
Threaded sound loading
== Учитавање звука са навојем
Map sound volume
== Јачина звука на мапи
@ -961,8 +946,8 @@ Client message
Save the best demo of each race
== Сачувајте најбољи снимак сваке трке
Default length: %d
== Подразумевана дужина: %d
Default length
== Подразумевана дужина
Enable replays
== Омогући поновљене репродукције
@ -1006,9 +991,6 @@ Show other players' hook collision lines
Show other players' key presses
== Прикажи притиске тастера других играча
Old mouse mode
== Стари мод миша
Show tiles layers from BG map
== Прикажи слојеве плочица са BG мапе
@ -1241,9 +1223,6 @@ CHN
Getting server list from master server
== Добијам листу сервера са мастер сервера
Refreshing...
== Освежавање
Leak IP
== Провали адресу
@ -1280,13 +1259,6 @@ Chat command
Enable controller
== Укључи контролер
Controller %d: %s
== Контролер %d: %s
Click to cycle through all available controllers.
== Кликни да видиш све слободне контролерес
[Ingame controller mode]
Relative
== Релативно
@ -1306,18 +1278,12 @@ UI controller sens.
Controller jitter tolerance
== Толеранција контролера
Device
== Уређај
Status
== Статус
Aim bind
== Нишан
Controller Axis #%d
== Стик %d.
Mouse
== Миш
@ -1357,9 +1323,6 @@ default
custom
== своје
Graphics cards
== Графичка картица
auto
== ауто
@ -1566,7 +1529,7 @@ Could not save downloaded map. Try manually deleting this file: %s
Initializing components
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1575,6 +1538,9 @@ File '%s' already exists, do you want to overwrite it?
Copy info
==
No server selected
==
Online players (%d)
==
@ -1627,10 +1593,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1642,9 +1608,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Open the directory that contains the demo files
==
@ -1678,12 +1656,21 @@ Open the directory to add custom skins
No controller found. Plug in a controller.
==
Axis
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Graphics card
==
Weapons
==

View file

@ -106,12 +106,6 @@ Clan
Client
== 客户端
Close
== 关闭
Connect
== 连接
Connecting to
== 正在连接到
@ -301,9 +295,6 @@ Enable team chat sound
Enable highlighted chat sound
== 启用聊天被提及消息提示音
Threaded sound loading
== 启用多线程音频加载
Name
== 名称
@ -407,9 +398,6 @@ Rename demo
Reset filter
== 重置筛选
Sample rate
== 采样率
Score
== 分数
@ -811,9 +799,6 @@ Grabs
DDNet
== DDNet
Select a name
== 另存为
Deaths
== 死亡数
@ -823,9 +808,6 @@ Please use a different name
Restart
== 重新开始
Old mouse mode
== 旧版鼠标模式
Follow
== 跟随
@ -1010,8 +992,8 @@ Show HUD
Hammerfly dummy
== 分身 Hammerfly 开关
Default length: %d
== 默认时长: %d
Default length
== 默认时长
Toggle ghost
== 影子记录开关
@ -1266,9 +1248,6 @@ Desktop fullscreen
Are you sure that you want to disconnect and switch to a different server?
== 你确定要断开此服务器连接并进入其他服务器吗?
Refreshing...
== 正在刷新...
Kill Messages
== 击杀消息
@ -1308,9 +1287,6 @@ default
custom
== 自定义
Graphics cards
== 显卡
auto
== 自动
@ -1377,13 +1353,6 @@ Download community skins
Enable controller
== 启用控制器
Controller %d: %s
== 控制器 %d: %s
Click to cycle through all available controllers.
== 点击以切换其他控制器
[Ingame controller mode]
Relative
== 相对
@ -1403,18 +1372,12 @@ UI controller sens.
Controller jitter tolerance
== 摇杆死区
Device
== 输入设备
Status
== 状态
Aim bind
== 操作轴绑定
Controller Axis #%d
== 摇杆 #%d
Mouse
== 鼠标
@ -1574,12 +1537,6 @@ Slow down the demo
Speed up the demo
== 加快播放速度
Mark the beginning of a cut
== 标记裁剪起点
Mark the end of a cut
== 标记裁剪终点
Export cut as a separate demo
== 另存为新回放文件
@ -1753,3 +1710,33 @@ None
Add Clan
== 添加战队
A demo with this name already exists
==
No server selected
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -76,12 +76,6 @@ Clan
Client
== Klient
Close
== Zavrieť
Connect
== Pripojiť
Connecting to
== Pripojujem sa k
@ -347,9 +341,6 @@ Rename demo
Reset filter
== Obnoviť filter
Sample rate
== Sample rate
Score
== Skóre
@ -759,7 +750,7 @@ Your nickname '%s' is already used (%d points). Do you still want to use it?
Checking for existing player with your name
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -834,9 +825,6 @@ Exclude
%d player
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -861,6 +849,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -892,18 +883,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan
==
Select a name
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Remove chat
==
Play the current demo
==
@ -925,10 +904,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -940,9 +919,30 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Remove chat
==
Please use a different name
==
File already exists, do you want to overwrite it?
==
Loading demo files
==
@ -1162,10 +1162,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1176,9 +1176,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1191,7 +1188,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1200,9 +1197,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1212,15 +1206,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1236,10 +1230,10 @@ Windowed fullscreen
Desktop fullscreen
==
may cause delay
Screen
==
Screen
may cause delay
==
Allows maps to render with more detail
@ -1257,7 +1251,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto
@ -1284,9 +1278,6 @@ Enable team chat sound
Enable highlighted chat sound
==
Threaded sound loading
==
Game sound volume
==
@ -1488,7 +1479,7 @@ Save the best demo of each race
Enable replays
==
Default length: %d
Default length
==
When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1506,10 +1497,10 @@ Gameplay
Overlay entities
==
Size
Show text entities
==
Show text entities
Size
==
Opacity
@ -1542,9 +1533,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths
==
Old mouse mode
==
Background
==

View file

@ -94,12 +94,6 @@ Clan
Client
== Cliente
Close
== Cerrar
Connect
== Conectar
Connecting to
== Conectando con
@ -368,9 +362,6 @@ Rename demo
Reset filter
== Resetear filtro
Sample rate
== Frecuencia de muestreo
Score
== Puntos
@ -718,9 +709,6 @@ Update now
Restart
== Reiniciar
Select a name
== Selecciona un nombre
Please use a different name
== Por favor usa un nombre diferente
@ -889,9 +877,6 @@ Enable team chat sound
Enable highlighted chat sound
== Habilitar sonido de chat resaltado
Threaded sound loading
== Carga de sonido en un hilo
Map sound volume
== Vol. del sonido del mapa
@ -943,8 +928,8 @@ Normal message
Save the best demo of each race
== Guardar la mejor demo de cada carrera
Default length: %d
== Longitud predeterminada: %d
Default length
== Longitud predeterminada
Enable replays
== Habilitar repeticiones
@ -991,9 +976,6 @@ Show other players' hook collision lines
Show other players' key presses
== Mostrar las pulsaciones de teclas de otros jugadores
Old mouse mode
== Modo de mouse viejo
Show tiles layers from BG map
== Mostrar capas de tiles del mapa de fondo
@ -1250,9 +1232,6 @@ https://ddnet.org/discord
Are you sure that you want to disconnect and switch to a different server?
== ¿Seguro que quieres desconectarte y cambiar de servidor?
Refreshing...
== Actualizando...
Kill Messages
== Mensajes de Muerte
@ -1292,9 +1271,6 @@ default
custom
== personalizado
Graphics cards
== Tarjetas de video
auto
== auto.
@ -1358,13 +1334,6 @@ Download community skins
Enable controller
== Habilitar mando
Controller %d: %s
== Mando %d: %s
Click to cycle through all available controllers.
== Click acá para recorrer todos los mandos disponibles.
[Ingame controller mode]
Relative
== Relativo
@ -1384,18 +1353,12 @@ UI controller sens.
Controller jitter tolerance
== Tolerancia a la fluctuación del mando
Device
== Dispositivo
Status
== Estado
Aim bind
== Apuntar
Controller Axis #%d
== Eje #%d del mando
Mouse
== Ratón
@ -1489,12 +1452,6 @@ Slow down the demo
Speed up the demo
== Acelerar la demo
Mark the beginning of a cut
== Marca el inicio de un corte
Mark the end of a cut
== Marca el final de un corte
Export cut as a separate demo
== Exportar corte como una demo diferente
@ -1737,3 +1694,33 @@ None
Add Clan
== Agregar clan
A demo with this name already exists
==
No server selected
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -80,12 +80,6 @@ Clan
Client
== Klient
Close
== Stäng
Connect
== Anslut
Connecting to
== Ansluter till
@ -351,9 +345,6 @@ Rename demo
Reset filter
== Återställ filter
Sample rate
== Samplingsfrekvens
Score
== Poäng
@ -597,9 +588,6 @@ Vanilla skins only
New random timeout code
== Ny slumpad timeout kod
Select a name
== Välj ett namn
Enable long pain sound (used when shooting in freeze)
== Aktivera ett långt ont ljud (använt vid sjutning i freeze)
@ -663,8 +651,8 @@ Save ghost
Browser
== Bläddraren
Default length: %d
== Standard längd: %d
Default length
== Standard längd
Switch weapon when out of ammo
== Byt vapen vid slut av ammunition
@ -744,9 +732,6 @@ Use high DPI
may cause delay
== kan orsaka fördröjning
Threaded sound loading
== Threaded ljud laddning
AntiPing
== AntiPing
@ -975,9 +960,6 @@ Automatically take statboard screenshot
Automatically create statboard csv
== Automatiskt skapa poänglista csv
Old mouse mode
== Gammal mus metod
Enable regular chat sound
== Aktivera vanligt chatt ljud
@ -1153,9 +1135,6 @@ CHN
Getting server list from master server
== Hämtar server lista från master server
Refreshing...
== Ladder om...
Leak IP
== Läck IP
@ -1359,7 +1338,7 @@ Getting game info
Requesting to join the game
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1377,6 +1356,9 @@ Loading menu images
Copy info
==
No server selected
==
Online players (%d)
==
@ -1429,10 +1411,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1444,9 +1426,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1498,10 +1492,10 @@ Open the directory to add custom skins
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1512,9 +1506,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1527,7 +1518,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1536,9 +1527,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1548,15 +1536,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Allows maps to render with more detail
==
@ -1569,7 +1557,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto

View file

@ -21,6 +21,7 @@
# 2022-12-11 cheeser0613
# 2023-01-11 cheeser0613
# 2023-04-01 cheeser0613
# 2023-05-25 cheeser0613
##### /authors #####
##### translated strings #####
@ -94,12 +95,6 @@ Clan
Client
== 客戶端
Close
== 關閉
Connect
== 連線
Connecting to
== 正在連線到
@ -289,9 +284,6 @@ Enable team chat sound
Enable highlighted chat sound
== 啟用被提及時的提示音
Threaded sound loading
== 啟用多執行緒音訊載入
Name
== 名稱
@ -395,9 +387,6 @@ Rename demo
Reset filter
== 重置過濾器
Sample rate
== 取樣率
Score
== 分數
@ -585,7 +574,7 @@ Join game
== 加入遊戲
FSAA samples
== 全屏抗鋸齒(FSAA)取樣倍數
== 全屏抗鋸齒 (FSAA) 取樣倍數
Sound volume
== 音量
@ -799,9 +788,6 @@ Grabs
DDNet
== DDNet
Select a name
== 另存為
Deaths
== 死亡數
@ -811,9 +797,6 @@ Please use a different name
Restart
== 重新開始
Old mouse mode
== 舊版滑鼠模式
Follow
== 跟隨
@ -998,8 +981,8 @@ Show HUD
Hammerfly dummy
== 分身Hammerfly開關
Default length: %d
== 預設長度: %d
Default length
== 預設長度
Toggle ghost
== 影子記錄開關
@ -1254,9 +1237,6 @@ https://ddnet.org/discord
Are you sure that you want to disconnect and switch to a different server?
== 你確定要中斷此伺服器并嘗試加入其他伺服器嗎?
Refreshing...
== 正在重整...
Kill Messages
== 擊殺訊息
@ -1296,9 +1276,6 @@ default
custom
== 自定義
Graphics cards
== 顯示卡
auto
== 自動
@ -1365,13 +1342,6 @@ Download community skins
Enable controller
== 啓用控制器
Controller %d: %s
== 控制器 %d: %s
Click to cycle through all available controllers.
== 點擊以切換其他控制器
[Ingame controller mode]
Relative
== 相對
@ -1383,34 +1353,28 @@ Ingame controller mode
== 游戲内控制器瞄準模式
Ingame controller sens.
== 搖桿靈敏度(游戲)
== 搖桿靈敏度 (游戲)
UI controller sens.
== 搖桿靈敏度(界面)
== 搖桿靈敏度 (界面)
Controller jitter tolerance
== 搖桿錯位容錯
Device
== 輸入設備
Status
== 狀態
Aim bind
== 操作軸綁定
Controller Axis #%d
== 搖桿 #%d
Mouse
== 滑鼠
Ingame mouse sens.
== 滑鼠靈敏度(游戲)
== 滑鼠靈敏度 (游戲)
UI mouse sens.
== 滑鼠靈敏度(界面)
== 滑鼠靈敏度 (界面)
Controller
== 控制器
@ -1503,7 +1467,7 @@ DDRace HUD
== DDRace HUD
Show client IDs in scoreboard
== 顯示客戶端 IDs (計分板中)
== 顯示客戶端 IDs (計分板中)
Show DDRace HUD
== 顯示 DDRace HUD
@ -1524,7 +1488,7 @@ Hook collision line opacity
== 輔助綫不透明度
Colors of the hook collision line, in case of a possible collision with:
== 輔助綫顔色(當瞄準以下實體物時)
== 輔助綫顔色 (當瞄準以下實體物時)
Your movements are not taken into account when calculating the line colors
== 移動所造成的瞄準偏移將不計入考量
@ -1562,12 +1526,6 @@ Slow down the demo
Speed up the demo
== 加快播放速度
Mark the beginning of a cut
== 標記裁剪起點
Mark the end of a cut
== 標記裁剪終點
Export cut as a separate demo
== 另存爲新回放檔案
@ -1647,11 +1605,11 @@ Are you sure that you want to reset the controls to their defaults?
[Graphics error]
Failed during initialization. Try to change gfx_backend to OpenGL or Vulkan in settings_ddnet.cfg in the config directory and try again.
== 初始化失敗。請嘗試打開配置目錄中的設定檔案settings_ddnet.cfg并將“gfx_backend OpenGL”修改為“gfx_backend Vulkan”若沒有前者則可直接輸入後者再重試。
== 初始化失敗。請嘗試打開配置目錄中的設定檔案 (settings_ddnet.cfg) 并將“gfx_backend OpenGL”修改為“gfx_backend Vulkan” (若沒有前者則可直接輸入後者) 再重試。
[Graphics error]
Out of VRAM. Try removing custom assets (skins, entities, etc.), especially those with high resolution.
== 顯存不足。請嘗試移除自定義材質(如外觀,實體層等等),尤其高分辨率的自定義材質。
== 顯存不足。請嘗試移除自定義材質 (如外觀,實體層等等),尤其高分辨率的自定義材質。
[Graphics error]
An error during command recording occurred. Try to update your GPU drivers.
@ -1671,7 +1629,7 @@ Failed to swap framebuffers. Try to update your GPU drivers.
[Graphics error]
Unknown error. Try to change gfx_backend to OpenGL or Vulkan in settings_ddnet.cfg in the config directory and try again.
== 未知錯誤。請嘗試打開配置目錄中的設定檔案settings_ddnet.cfg并將“gfx_backend OpenGL”修改為“gfx_backend Vulkan”若沒有前者則可直接輸入後者再重試。
== 未知錯誤。請嘗試打開配置目錄中的設定檔案 (settings_ddnet.cfg) 并將“gfx_backend OpenGL”修改為“gfx_backend Vulkan” (若沒有前者則可直接輸入後者) 再重試。
[Graphics error]
Could not initialize the given graphics backend, reverting to the default backend now.
@ -1681,7 +1639,7 @@ Open the directory that contains the demo files
== 打開存有回放檔案的資料夾路徑
Save power by lowering refresh rate (higher input latency)
== 節能模式(限制幀率上限以降低功耗但也將提高輸入延遲)
== 節能模式 (限制幀率上限以降低功耗但也將提高輸入延遲)
Open the settings file
== 打開設定檔案
@ -1690,10 +1648,10 @@ Open the directory that contains the configuration and user files
== 打開存有配置檔案與用戶檔案的資料夾路徑
Open the directory to add custom themes
== 打開用以添加自定義主題的資料夾路徑
== 打開用以新增自定義主題的資料夾路徑
Open the directory to add custom skins
== 打開用以添加自定義外觀的資料夾路徑
== 打開用以新增自定義外觀的資料夾路徑
No controller found. Plug in a controller.
== 未檢測到任何控制器。請嘗試重新連接控制器。
@ -1702,7 +1660,7 @@ Unregister protocol and file extensions
== 未注冊的協議與擴充檔案
Open the directory to add custom assets
== 打開用以添加自定義材質的資料夾路徑
== 打開用以新增自定義材質的資料夾路徑
[Graphics error]
Could not initialize the given graphics backend, this is probably because you didn't install the driver of the integrated graphics card.
@ -1718,26 +1676,56 @@ Create a random skin
== 隨機創造外觀
Online players (%d)
==
== 在綫玩家 (%d)
Online clanmates (%d)
==
== 在綫戰隊隊友 (%d)
[friends (server browser)]
Offline (%d)
==
== 離綫(%d
Click to select server. Double click to join your friend.
==
== 點擊以選擇伺服器,雙擊以直接加入好友所在伺服器
Click to remove this player from your friends list.
==
== 點擊以將此好友從好友列表中移除
Click to remove this clan from your friends list.
==
== 點擊以將此戰隊從好友列表中移除
None
==
==
Add Clan
== 新增戰隊
A demo with this name already exists
==
No server selected
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -81,12 +81,6 @@ Clan
Client
== İstemci
Close
== Kapat
Connect
== Bağlan
Connecting to
== Bağlanılıyor
@ -349,9 +343,6 @@ Rename demo
Reset filter
== Filtreleri sıfırla
Sample rate
== Örnekleme hızı
Score
== Skor
@ -705,9 +696,6 @@ Update now
Restart
== Yeniden başlat
Select a name
== Takma ad seç
Please use a different name
== Lütfen farklı takma ad kullanın
@ -879,9 +867,6 @@ Enable team chat sound
Enable highlighted chat sound
== Vurgulanmış mesaj sesini etkinleştir
Threaded sound loading
== Threaded ses yükleme
Map sound volume
== Harita ses seviyesi
@ -936,8 +921,8 @@ Client message
Save the best demo of each race
== Her yarış için en iyi demoyu kaydet
Default length: %d
== Uzunluk: %d
Default length
== Uzunluk
Enable replays
== Tekrar oynatmaları etkinleştir
@ -984,9 +969,6 @@ Show other players' hook collision lines
Show other players' key presses
== Diğer oyuncuların tuş basışlarını göster
Old mouse mode
== Eski mouse modu
Show tiles layers from BG map
== Yapı katmanlarını göster
@ -1184,7 +1166,7 @@ Your nickname '%s' is already used (%d points). Do you still want to use it?
Checking for existing player with your name
==
Cancel
A demo with this name already exists
==
File '%s' already exists, do you want to overwrite it?
@ -1241,9 +1223,6 @@ Getting server list from master server
%d player
==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server?
==
@ -1253,6 +1232,9 @@ Copy info
Leak IP
==
No server selected
==
Online players (%d)
==
@ -1305,10 +1287,10 @@ Slow down the demo
Speed up the demo
==
Mark the beginning of a cut
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut
Mark the end of a cut (right click to reset)
==
Export cut as a separate demo
@ -1320,9 +1302,21 @@ Go back one marker
Go forward one marker
==
Close the demo player
==
Toggle keyboard shortcuts
==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files
==
@ -1404,10 +1398,10 @@ Chat command
Enable controller
==
Controller %d: %s
Controller
==
Click to cycle through all available controllers.
Ingame controller mode
==
[Ingame controller mode]
@ -1418,9 +1412,6 @@ Relative
Absolute
==
Ingame controller mode
==
Ingame controller sens.
==
@ -1433,7 +1424,7 @@ Controller jitter tolerance
No controller found. Plug in a controller.
==
Device
Axis
==
Status
@ -1442,9 +1433,6 @@ Status
Aim bind
==
Controller Axis #%d
==
Mouse
==
@ -1454,15 +1442,15 @@ Ingame mouse sens.
UI mouse sens.
==
Controller
==
Reset controls
==
Are you sure that you want to reset the controls to their defaults?
==
Cancel
==
Dummy
==
@ -1490,7 +1478,7 @@ default
custom
==
Graphics cards
Graphics card
==
auto

View file

@ -37,12 +37,6 @@ Call vote
Chat
== Чат
Close
== Зачинити
Connect
== Під’єднатись
Connecting to
== Підключення до
@ -182,7 +176,7 @@ Movement
== Переміщення
Mute when not active
== Глушити звуки, коли гра неактивна
== Відключити звуки, коли гра неактивна
Name
== Ім'я
@ -215,7 +209,7 @@ Password
== Пароль
Password incorrect
== неправильний пароль
== Неправильний пароль
Ping
== Пінг
@ -234,7 +228,7 @@ Players
== Гравці
Please balance teams!
== Збалансуйте команди!
== Будь ласка збалансуйте команди!
Prev. weapon
== Попер. зброя
@ -260,9 +254,6 @@ Remote console
Reset filter
== Скинути фільтри
Sample rate
== Частота
Score
== бали
@ -306,10 +297,10 @@ Stop record
== Зупинити запис
Sudden Death
== Швидка смерть
== Раптова смерть
Switch weapon on pickup
== Перемикати зброю при підборі
== Взяти в руку підібравшу зброю
Team
== Команда
@ -336,7 +327,7 @@ Use sounds
== Використовувати звуки
V-Sync
== V-Sync
== Вертикальна синхронізація (V-Sync)
Version
== Версія
@ -485,7 +476,7 @@ Disconnect Dummy
== Відключити Dummy
Are you sure that you want to disconnect your dummy?
== Ви впевнені, що хочете відключити свого Dummy?
== Ви впевнені, що хочете відключити свого даммі?
Welcome to DDNet
== Ласкаво просимо в DDNet
@ -530,10 +521,10 @@ Video name:
== Назва відео
Show DDNet map finishes in server browser
== Показувати завершені карти DDNet в браузері сервера
== Показувати пройдені карти DDNet в браузері сервера
transmits your player name to info.ddnet.org
== передає Ваш нікнейм на info.ddnet.org
== передає ваш нікнейм на info.ddnet.org
Search
== Пошук
@ -604,9 +595,6 @@ Update now
Restart
== Перезавантажити
Select a name
== Оберіть ім'я
Please use a different name
== Будь ласка, використовуйте інше ім’я
@ -779,10 +767,10 @@ Kill
== Самогубство
Zoom in
== Збільшити
== Приблизити камеру
Zoom out
== Зменшити
== Віддалити камеру
Default zoom
== Стандартний масштаб
@ -800,7 +788,7 @@ Toggle dummy
== Переключити Даммі
Toggle ghost
== Переключити примару
== Переключити тінь
Dummy copy
== Повторення рухів Даммі
@ -865,9 +853,6 @@ Enable team chat sound
Enable highlighted chat sound
== Включити звуки виділених повідомлень
Threaded sound loading
== музика при завантаженні
Map sound volume
== Гучність звуку на карті
@ -893,7 +878,7 @@ Show kill messages
== Показувати список вбивств
Show votes window after voting
== Показувати голосування після вашого голосу
== Відображати вікно голосування після вашого голосу
Messages
== Повідомлення
@ -922,8 +907,8 @@ Client message
Save the best demo of each race
== Зберігати краще демо кожної гонки
Default length: %d
== Стандартна довжина: %d
Default length
== Стандартна довжина
Enable replays
== Включити повтори
@ -947,7 +932,7 @@ Show text entities
== Текстові текстури
Show others (own team only)
== Завжди показувати тільки вашу команду
== Показати інших гравців (Лише для комманди)
Show quads
== Показувати quads
@ -970,9 +955,6 @@ Show other players' hook collision lines
Show other players' key presses
== Показувати натискання кнопок інших гравців
Old mouse mode
== Режим старої мишки
Show tiles layers from BG map
== Показувати шари з тайлами з фонової карти
@ -980,7 +962,7 @@ DDNet %s is available:
== Доступний новий DDNet %s:
Updating...
== Оновлення ...
== Оновлення...
No updates available
== Немає доступних оновлень
@ -1049,7 +1031,7 @@ Replay
== Повтор
Saving ddnet-settings.cfg failed
== Збереження налаштувань невдалося
== Збереження налаштувань ddnet-settings.cfg невдалося
The width of texture %s is not divisible by %d, or the height is not divisible by %d, which might cause visual bugs.
== Ширина або висота текстури %s не поділяється на %d, що може викликати візуальні помилки
@ -1117,9 +1099,6 @@ Getting server list from master server
%d player
== %d Гравець
Refreshing...
== Оновлення...
Leak IP
== Стійке IP
@ -1157,7 +1136,7 @@ Windowed
== Віконний
Windowed borderless
== Віконний без меж
== Віконний без рамок
Desktop fullscreen
== Повний робочий стіл
@ -1316,7 +1295,7 @@ Speed:
== Швидкість:
Angle:
== Кут
== Кут:
Team %d
== Команда %d
@ -1334,7 +1313,7 @@ UDP and TCP IP addresses seem to be different. Try disabling VPN, proxy or netwo
== Здається, що IP-адреси UDP і TCP відрізняються. Спробуйте вимкнути VPN, проксі або мережеві прискорювачі.
No answer from server yet.
== Сервер ще не відповів
== Сервер ще не відповів...
Getting game info
== Отримання ігрової інформації
@ -1377,7 +1356,7 @@ Click to remove this player from your friends list.
== Натисніть, щоб видалити цього гравця зі списку друзів.
Click to remove this clan from your friends list.
== Натисніть, щоб видалити цей клан зі свого списку друзів.
== Натисніть, щоб видалити цей клан зі свого списку.
None
== Нічого
@ -1412,12 +1391,6 @@ Slow down the demo
Speed up the demo
== Прискорити димо
Mark the beginning of a cut
== Позначити початок вирізу
Mark the end of a cut
== Позначити кінець вирізу
Export cut as a separate demo
== Експортувати виріз як окреме демо
@ -1464,7 +1437,7 @@ Open the directory that contains the configuration and user files
== Відкрити каталог, який містить конфігураційні та користувацькі файли
Open the directory to add custom themes
== Відкрити каталог, щоб додати власні теми
== Відкрити каталог, щоб додати власні фони
Loading skin files
== Завантаження файлів скінів
@ -1487,13 +1460,6 @@ Open the directory to add custom skins
Enable controller
== Увімкнути контролер
Controller %d: %s
== Контролер %d: %s
Click to cycle through all available controllers.
== Натисніть, щоб переглянути всі активні контролери.
[Ingame controller mode]
Relative
== Relative
@ -1516,18 +1482,12 @@ Controller jitter tolerance
No controller found. Plug in a controller.
== Контролер не знайдено. Підключіть контролер.
Device
== Пристрій
Status
== Стан
Aim bind
== Прив'язка до цілі
Controller Axis #%d
== Ось контролера #%d
Mouse
== Мишка
@ -1561,9 +1521,6 @@ default
custom
== користувацькі
Graphics cards
== Відеокарти
auto
== авто
@ -1646,34 +1603,34 @@ Weapons
== Зброя
Rifle Laser Outline Color
== Колір контуру лазера
== Колір лазера
Rifle Laser Inner Color
== Внутрішній колір лазера
== Колір обводки лазера
Shotgun Laser Outline Color
== Колір контуру дробовика
== Колір лазера дробовика
Shotgun Laser Inner Color
== Внутрішній колір дробовика
== Колір обводки лазера дробовика
Door Laser Outline Color
== Колір контуру дверей
== Колір лазера-дверей
Door Laser Inner Color
== Внутрішній колір дверей
== Колір обводки лазера-дверей
Freeze Laser Outline Color
== Колір контуру фріз-лазерів
== Колір фріз-лазера
Freeze Laser Inner Color
== Внутрішній колір фріз-дверей
== Колір обводки фріз-лазера
Set all to Rifle
== Поставити все на колір зброї
== Всі кольори на колір лезера
When you cross the start line, show a ghost tee replicating the movements of your best time
== При перетинанні лінію старту, відображати tee-привида, який буде повторювати рухи свого найкращого часу
== При перетинанні лінію старту, відображати tee-привида, який буде повторювати рухи вашого найкращого часу
Opacity
== Непрозорість
@ -1719,3 +1676,33 @@ Super
Loading sound files
== Завантаження звукових файлів
A demo with this name already exists
==
No server selected
==
Mark the beginning of a cut (right click to reset)
==
Mark the end of a cut (right click to reset)
==
Close the demo player
==
Export demo cut
==
Cut interval
==
Cut length
==
Axis
==
Graphics card
==

View file

@ -1,6 +1,6 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2014 Sam Lantinga <slouken@libsdl.org>
Copyright (C) 1997-2023 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
@ -25,8 +25,8 @@
* Defines keyboard scancodes.
*/
#ifndef _SDL_scancode_h
#define _SDL_scancode_h
#ifndef SDL_scancode_h_
#define SDL_scancode_h_
#include "SDL_stdinc.h"
@ -38,7 +38,7 @@
* SDL_Event structure.
*
* The values in this enumeration are based on the USB usage page standard:
* http://www.usb.org/developers/devclass_docs/Hut1_12v2.pdf
* https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf
*/
typedef enum
{
@ -225,16 +225,16 @@ typedef enum
SDL_SCANCODE_F23 = 114,
SDL_SCANCODE_F24 = 115,
SDL_SCANCODE_EXECUTE = 116,
SDL_SCANCODE_HELP = 117,
SDL_SCANCODE_MENU = 118,
SDL_SCANCODE_HELP = 117, /**< AL Integrated Help Center */
SDL_SCANCODE_MENU = 118, /**< Menu (show menu) */
SDL_SCANCODE_SELECT = 119,
SDL_SCANCODE_STOP = 120,
SDL_SCANCODE_AGAIN = 121, /**< redo */
SDL_SCANCODE_UNDO = 122,
SDL_SCANCODE_CUT = 123,
SDL_SCANCODE_COPY = 124,
SDL_SCANCODE_PASTE = 125,
SDL_SCANCODE_FIND = 126,
SDL_SCANCODE_STOP = 120, /**< AC Stop */
SDL_SCANCODE_AGAIN = 121, /**< AC Redo/Repeat */
SDL_SCANCODE_UNDO = 122, /**< AC Undo */
SDL_SCANCODE_CUT = 123, /**< AC Cut */
SDL_SCANCODE_COPY = 124, /**< AC Copy */
SDL_SCANCODE_PASTE = 125, /**< AC Paste */
SDL_SCANCODE_FIND = 126, /**< AC Find */
SDL_SCANCODE_MUTE = 127,
SDL_SCANCODE_VOLUMEUP = 128,
SDL_SCANCODE_VOLUMEDOWN = 129,
@ -265,9 +265,9 @@ typedef enum
SDL_SCANCODE_LANG8 = 151, /**< reserved */
SDL_SCANCODE_LANG9 = 152, /**< reserved */
SDL_SCANCODE_ALTERASE = 153, /**< Erase-Eaze */
SDL_SCANCODE_ALTERASE = 153, /**< Erase-Eaze */
SDL_SCANCODE_SYSREQ = 154,
SDL_SCANCODE_CANCEL = 155,
SDL_SCANCODE_CANCEL = 155, /**< AC Cancel */
SDL_SCANCODE_CLEAR = 156,
SDL_SCANCODE_PRIOR = 157,
SDL_SCANCODE_RETURN2 = 158,
@ -345,6 +345,11 @@ typedef enum
* \name Usage page 0x0C
*
* These values are mapped from usage page 0x0C (USB consumer page).
* See https://usb.org/sites/default/files/hut1_2.pdf
*
* There are way more keys in the spec than we can represent in the
* current scancode range, so pick the ones that commonly come up in
* real world usage.
*/
/* @{ */
@ -354,17 +359,17 @@ typedef enum
SDL_SCANCODE_AUDIOPLAY = 261,
SDL_SCANCODE_AUDIOMUTE = 262,
SDL_SCANCODE_MEDIASELECT = 263,
SDL_SCANCODE_WWW = 264,
SDL_SCANCODE_WWW = 264, /**< AL Internet Browser */
SDL_SCANCODE_MAIL = 265,
SDL_SCANCODE_CALCULATOR = 266,
SDL_SCANCODE_CALCULATOR = 266, /**< AL Calculator */
SDL_SCANCODE_COMPUTER = 267,
SDL_SCANCODE_AC_SEARCH = 268,
SDL_SCANCODE_AC_HOME = 269,
SDL_SCANCODE_AC_BACK = 270,
SDL_SCANCODE_AC_FORWARD = 271,
SDL_SCANCODE_AC_STOP = 272,
SDL_SCANCODE_AC_REFRESH = 273,
SDL_SCANCODE_AC_BOOKMARKS = 274,
SDL_SCANCODE_AC_SEARCH = 268, /**< AC Search */
SDL_SCANCODE_AC_HOME = 269, /**< AC Home */
SDL_SCANCODE_AC_BACK = 270, /**< AC Back */
SDL_SCANCODE_AC_FORWARD = 271, /**< AC Forward */
SDL_SCANCODE_AC_STOP = 272, /**< AC Stop */
SDL_SCANCODE_AC_REFRESH = 273, /**< AC Refresh */
SDL_SCANCODE_AC_BOOKMARKS = 274, /**< AC Bookmarks */
/* @} *//* Usage page 0x0C */
@ -383,19 +388,51 @@ typedef enum
SDL_SCANCODE_KBDILLUMDOWN = 279,
SDL_SCANCODE_KBDILLUMUP = 280,
SDL_SCANCODE_EJECT = 281,
SDL_SCANCODE_SLEEP = 282,
SDL_SCANCODE_SLEEP = 282, /**< SC System Sleep */
SDL_SCANCODE_APP1 = 283,
SDL_SCANCODE_APP2 = 284,
/* @} *//* Walther keys */
/**
* \name Usage page 0x0C (additional media keys)
*
* These values are mapped from usage page 0x0C (USB consumer page).
*/
/* @{ */
SDL_SCANCODE_AUDIOREWIND = 285,
SDL_SCANCODE_AUDIOFASTFORWARD = 286,
/* @} *//* Usage page 0x0C (additional media keys) */
/**
* \name Mobile keys
*
* These are values that are often used on mobile phones.
*/
/* @{ */
SDL_SCANCODE_SOFTLEFT = 287, /**< Usually situated below the display on phones and
used as a multi-function feature key for selecting
a software defined function shown on the bottom left
of the display. */
SDL_SCANCODE_SOFTRIGHT = 288, /**< Usually situated below the display on phones and
used as a multi-function feature key for selecting
a software defined function shown on the bottom right
of the display. */
SDL_SCANCODE_CALL = 289, /**< Used for accepting phone calls. */
SDL_SCANCODE_ENDCALL = 290, /**< Used for rejecting phone calls. */
/* @} *//* Mobile keys */
/* Add any other keys here. */
SDL_NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes
for array bounds */
} SDL_Scancode;
#endif /* _SDL_scancode_h */
#endif /* SDL_scancode_h_ */
/* vi: set ts=4 sw=4 expandtab: */

View file

@ -0,0 +1,61 @@
#!/usr/bin/env python3
import os
import re
import sys
def read_all_lines(filename):
with open(filename, 'r', encoding='utf-8') as file:
return file.readlines()
def parse_config_variables(lines):
pattern = r'^MACRO_CONFIG_[A-Z]+\((.*?), (.*?),.*'
matches = {}
for line in lines:
match = re.match(pattern, line)
if match:
matches[match.group(1)] = match.group(2)
return matches
def generate_regex(variable_code):
return fr'(g_Config\.m_{variable_code}|Config\(\)->m_{variable_code}|m_pConfig->m_{variable_code})'
def find_config_variables(config_variables):
"""Returns the config variables which were not found."""
# Set of variables that have yet to be found.
variables_not_found = set(config_variables)
# Precompile regex for every config variable (~1.6x speedup).
regex_cache = {}
for variable_code in variables_not_found.copy():
regex_cache[variable_code] = re.compile(generate_regex(variable_code))
for root, _, files in os.walk('src'):
if not variables_not_found:
break
for file in files:
if not variables_not_found:
break
if file.endswith(('.cpp', '.h')) and not 'external' in root:
filepath = os.path.join(root, file)
with open(filepath, 'r', encoding='utf-8') as f:
content = f.read()
# Only variables not yet found are searched in the remaining files (~3.6x speedup).
# Copy set to remove elements while iterating, which is slightly faster than collecting
# the elements to remove in another set and removing them after the loop.
for variable_code in variables_not_found.copy():
if regex_cache[variable_code].search(content):
variables_not_found.remove(variable_code)
return variables_not_found
def main():
lines = read_all_lines('src/game/variables.h') + read_all_lines('src/engine/shared/config_variables.h')
config_variables = parse_config_variables(lines)
config_variables_not_found = find_config_variables(config_variables)
for variable_code in config_variables_not_found:
print(f'The config variable \'{config_variables[variable_code]}\' is unused.')
if config_variables_not_found:
print('Error: Unused config variables found.')
return 1
print('Success: No unused config variables found.')
return 0
if __name__ == '__main__':
sys.exit(main())

View file

@ -175,12 +175,13 @@ $tool ../DDNet \
player_name client1;
cl_download_skins 0;
gfx_fullscreen 0;
snd_enable 0;
logfile client1.log;
$client_args
connect localhost:$port" > stdout_client1.txt 2> stderr_client1.txt || fail client1 "$?" &
if [ "$arg_valgrind_memcheck" == "1" ]; then
wait_for_fifo client1.fifo 120
wait_for_fifo client1.fifo 180
sleep 20
else
wait_for_fifo client1.fifo 50
@ -198,12 +199,13 @@ $tool ../DDNet \
player_name client2;
cl_download_skins 0;
gfx_fullscreen 0;
snd_enable 0;
logfile client2.log;
$client_args
connect localhost:$port" > stdout_client2.txt 2> stderr_client2.txt || fail client2 "$?" &
if [ "$arg_valgrind_memcheck" == "1" ]; then
wait_for_fifo client2.fifo 120
wait_for_fifo client2.fifo 180
sleep 20
else
wait_for_fifo client2.fifo 50

48
src/base/color.cpp Normal file
View file

@ -0,0 +1,48 @@
#include "color.h"
#include "system.h"
template<typename T>
std::optional<T> color_parse(const char *pStr)
{
if(!str_isallnum_hex(pStr))
return {};
const unsigned Num = str_toulong_base(pStr, 16);
T Color;
switch(str_length(pStr))
{
case 3:
Color.x = (((Num >> 8) & 0x0F) + ((Num >> 4) & 0xF0)) / 255.0f;
Color.y = (((Num >> 4) & 0x0F) + ((Num >> 0) & 0xF0)) / 255.0f;
Color.z = (((Num >> 0) & 0x0F) + ((Num << 4) & 0xF0)) / 255.0f;
Color.a = 1.0f;
return Color;
case 4:
Color.x = (((Num >> 12) & 0x0F) + ((Num >> 8) & 0xF0)) / 255.0f;
Color.y = (((Num >> 8) & 0x0F) + ((Num >> 4) & 0xF0)) / 255.0f;
Color.z = (((Num >> 4) & 0x0F) + ((Num >> 0) & 0xF0)) / 255.0f;
Color.a = (((Num >> 0) & 0x0F) + ((Num << 4) & 0xF0)) / 255.0f;
return Color;
case 6:
Color.x = ((Num >> 16) & 0xFF) / 255.0f;
Color.y = ((Num >> 8) & 0xFF) / 255.0f;
Color.z = ((Num >> 0) & 0xFF) / 255.0f;
Color.a = 1.0f;
return Color;
case 8:
Color.x = ((Num >> 24) & 0xFF) / 255.0f;
Color.y = ((Num >> 16) & 0xFF) / 255.0f;
Color.z = ((Num >> 8) & 0xFF) / 255.0f;
Color.a = ((Num >> 0) & 0xFF) / 255.0f;
return Color;
default:
return {};
}
}
template std::optional<ColorRGBA> color_parse<ColorRGBA>(const char *);

View file

@ -5,6 +5,8 @@
#include <base/math.h>
#include <base/vmath.h>
#include <optional>
/*
Title: Color handling
*/
@ -114,12 +116,40 @@ public:
return (Alpha ? ((unsigned)round_to_int(a * 255.0f) << 24) : 0) + ((unsigned)round_to_int(x * 255.0f) << 16) + ((unsigned)round_to_int(y * 255.0f) << 8) + (unsigned)round_to_int(z * 255.0f);
}
unsigned PackAlphaLast(bool Alpha = true) const
{
if(Alpha)
return ((unsigned)round_to_int(x * 255.0f) << 24) + ((unsigned)round_to_int(y * 255.0f) << 16) + ((unsigned)round_to_int(z * 255.0f) << 8) + (unsigned)round_to_int(a * 255.0f);
return ((unsigned)round_to_int(x * 255.0f) << 16) + ((unsigned)round_to_int(y * 255.0f) << 8) + (unsigned)round_to_int(z * 255.0f);
}
DerivedT WithAlpha(float alpha) const
{
DerivedT col(static_cast<const DerivedT &>(*this));
col.a = alpha;
return col;
}
template<typename UnpackT>
static UnpackT UnpackAlphaLast(unsigned Color, bool Alpha = true)
{
UnpackT Result;
if(Alpha)
{
Result.x = ((Color >> 24) & 0xFF) / 255.0f;
Result.y = ((Color >> 16) & 0xFF) / 255.0f;
Result.z = ((Color >> 8) & 0xFF) / 255.0f;
Result.a = ((Color >> 0) & 0xFF) / 255.0f;
}
else
{
Result.x = ((Color >> 16) & 0xFF) / 255.0f;
Result.y = ((Color >> 8) & 0xFF) / 255.0f;
Result.z = ((Color >> 0) & 0xFF) / 255.0f;
Result.a = 1.0f;
}
return Result;
}
};
class ColorHSLA : public color4_base<ColorHSLA>
@ -228,14 +258,14 @@ template<>
inline ColorHSLA color_cast(const ColorHSVA &hsv)
{
float l = hsv.v * (1 - hsv.s * 0.5f);
return ColorHSLA(hsv.h, (l == 0.0f || l == 1.0f) ? 0 : (hsv.v - l) / minimum(l, 1 - l), l);
return ColorHSLA(hsv.h, (l == 0.0f || l == 1.0f) ? 0 : (hsv.v - l) / minimum(l, 1 - l), l, hsv.a);
}
template<>
inline ColorHSVA color_cast(const ColorHSLA &hsl)
{
float v = hsl.l + hsl.s * minimum(hsl.l, 1 - hsl.l);
return ColorHSVA(hsl.h, v == 0.0f ? 0 : 2 - (2 * hsl.l / v), v);
return ColorHSVA(hsl.h, v == 0.0f ? 0 : 2 - (2 * hsl.l / v), v, hsl.a);
}
template<>
@ -262,4 +292,7 @@ T color_invert(const T &col)
return T(1.0f - col.x, 1.0f - col.y, 1.0f - col.z, 1.0f - col.a);
}
template<typename T>
std::optional<T> color_parse(const char *pStr);
#endif

View file

@ -833,12 +833,12 @@ void thread_detach(void *thread)
#endif
}
void *thread_init_and_detach(void (*threadfunc)(void *), void *u, const char *name)
bool thread_init_and_detach(void (*threadfunc)(void *), void *u, const char *name)
{
void *thread = thread_init(threadfunc, u, name);
if(thread)
thread_detach(thread);
return thread;
return thread != nullptr;
}
#if defined(CONF_FAMILY_UNIX)
@ -2396,6 +2396,39 @@ char *fs_getcwd(char *buffer, int buffer_size)
#endif
}
const char *fs_filename(const char *path)
{
for(const char *filename = path + str_length(path); filename >= path; --filename)
{
if(filename[0] == '/' || filename[0] == '\\')
return filename + 1;
}
return path;
}
void fs_split_file_extension(const char *filename, char *name, size_t name_size, char *extension, size_t extension_size)
{
dbg_assert(name != nullptr || extension != nullptr, "name or extension parameter required");
dbg_assert(name == nullptr || name_size > 0, "name_size invalid");
dbg_assert(extension == nullptr || extension_size > 0, "extension_size invalid");
const char *last_dot = str_rchr(filename, '.');
if(last_dot == nullptr || last_dot == filename)
{
if(extension != nullptr)
extension[0] = '\0';
if(name != nullptr)
str_copy(name, filename, name_size);
}
else
{
if(extension != nullptr)
str_copy(extension, last_dot + 1, extension_size);
if(name != nullptr)
str_truncate(name, name_size, filename, last_dot - filename);
}
}
int fs_parent_dir(char *path)
{
char *parent = 0;
@ -3430,10 +3463,41 @@ int str_isallnum(const char *str)
return 1;
}
int str_toint(const char *str) { return str_toint_base(str, 10); }
int str_toint_base(const char *str, int base) { return strtol(str, NULL, base); }
unsigned long str_toulong_base(const char *str, int base) { return strtoul(str, NULL, base); }
float str_tofloat(const char *str) { return strtod(str, NULL); }
int str_isallnum_hex(const char *str)
{
while(*str)
{
if(!(*str >= '0' && *str <= '9') && !(*str >= 'a' && *str <= 'f') && !(*str >= 'A' && *str <= 'F'))
return 0;
str++;
}
return 1;
}
int str_toint(const char *str)
{
return str_toint_base(str, 10);
}
int str_toint_base(const char *str, int base)
{
return strtol(str, nullptr, base);
}
unsigned long str_toulong_base(const char *str, int base)
{
return strtoul(str, nullptr, base);
}
int64_t str_toint64_base(const char *str, int base)
{
return strtoll(str, nullptr, base);
}
float str_tofloat(const char *str)
{
return strtod(str, nullptr);
}
int str_utf8_comp_nocase(const char *a, const char *b)
{
@ -3971,7 +4035,7 @@ int open_file(const char *path)
{
if(!fs_getcwd(workingDir, sizeof(workingDir)))
return 0;
str_append(workingDir, "/", sizeof(workingDir));
str_append(workingDir, "/");
}
else
workingDir[0] = '\0';

View file

@ -23,8 +23,10 @@
#ifdef __MINGW32__
#undef PRId64
#undef PRIu64
#undef PRIX64
#define PRId64 "I64d"
#define PRIu64 "I64u"
#define PRIX64 "I64X"
#define PRIzu "Iu"
#else
#define PRIzu "zu"
@ -601,9 +603,9 @@ void thread_detach(void *thread);
* @param user Pointer to pass to the thread.
* @param name Name describing the use of the thread
*
* @return The thread if no error occurred, 0 on error.
* @return true on success, false on failure.
*/
void *thread_init_and_detach(void (*threadfunc)(void *), void *user, const char *name);
bool thread_init_and_detach(void (*threadfunc)(void *), void *user, const char *name);
// Enable thread safety attributes only with clang.
// The attributes can be safely erased when compiling with other compilers.
@ -1192,6 +1194,23 @@ std::string windows_format_system_message(unsigned long error);
*/
void str_append(char *dst, const char *src, int dst_size);
/**
* Appends a string to a fixed-size array of chars.
*
* @ingroup Strings
*
* @param dst Array that shall receive the string.
* @param src String to append.
*
* @remark The strings are treated as zero-terminated strings.
* @remark Guarantees that dst string will contain zero-termination.
*/
template<int N>
void str_append(char (&dst)[N], const char *src)
{
str_append(dst, src, N);
}
/**
* Copies a string to another.
*
@ -1208,6 +1227,23 @@ void str_append(char *dst, const char *src, int dst_size);
*/
int str_copy(char *dst, const char *src, int dst_size);
/**
* Copies a string to a fixed-size array of chars.
*
* @ingroup Strings
*
* @param dst Array that shall receive the string.
* @param src String to be copied.
*
* @remark The strings are treated as zero-terminated strings.
* @remark Guarantees that dst string will contain zero-termination.
*/
template<int N>
void str_copy(char (&dst)[N], const char *src)
{
str_copy(dst, src, N);
}
/**
* Truncates a utf8 encoded string to a given length.
*
@ -1990,6 +2026,39 @@ int fs_chdir(const char *path);
*/
char *fs_getcwd(char *buffer, int buffer_size);
/**
* Gets the name of a file or folder specified by a path,
* i.e. the last segment of the path.
*
* @ingroup Filesystem
*
* @param path Path from which to retrieve the filename.
*
* @return Filename of the path.
*
* @remark Supports forward and backward slashes as path segment separator.
* @remark No distinction between files and folders is being made.
* @remark The strings are treated as zero-terminated strings.
*/
const char *fs_filename(const char *path);
/**
* Splits a filename into name (without extension) and file extension.
*
* @ingroup Filesystem
*
* @param filename The filename to split.
* @param name Buffer that will receive the name without extension, may be nullptr.
* @param name_size Size of the name buffer (ignored if name is nullptr).
* @param extension Buffer that will receive the extension, may be nullptr.
* @param extension_size Size of the extension buffer (ignored if extension is nullptr).
*
* @remark Does NOT handle forward and backward slashes.
* @remark No distinction between files and folders is being made.
* @remark The strings are treated as zero-terminated strings.
*/
void fs_split_file_extension(const char *filename, char *name, size_t name_size, char *extension = nullptr, size_t extension_size = 0);
/**
* Get the parent directory of a directory.
*
@ -2133,6 +2202,7 @@ void net_stats(NETSTATS *stats);
int str_toint(const char *str);
int str_toint_base(const char *str, int base);
unsigned long str_toulong_base(const char *str, int base);
int64_t str_toint64_base(const char *str, int base = 10);
float str_tofloat(const char *str);
/**
@ -2149,7 +2219,11 @@ float str_tofloat(const char *str);
int str_isspace(char c);
char str_uppercase(char c);
int str_isallnum(const char *str);
int str_isallnum_hex(const char *str);
unsigned str_quickhash(const char *str);
enum
@ -2777,23 +2851,6 @@ bool shell_unregister_application(const char *executable, bool *updated);
void shell_update();
#endif
/**
* Copies a string to a fixed-size array of chars.
*
* @ingroup Strings
*
* @param dst Array that shall receive the string.
* @param src String to be copied.
*
* @remark The strings are treated as zero-terminated strings.
* @remark Guarantees that dst string will contain zero-termination.
*/
template<int N>
void str_copy(char (&dst)[N], const char *src)
{
str_copy(dst, src, N);
}
template<>
struct std::hash<NETADDR>
{

View file

@ -293,6 +293,7 @@ public:
MESSAGE_BOX_TYPE_INFO,
};
virtual void ShowMessageBox(const char *pTitle, const char *pMessage, EMessageBoxType Type = MESSAGE_BOX_TYPE_ERROR) = 0;
virtual void GetGPUInfoString(char (&aGPUInfo)[256]) = 0;
};
class IGameClient : public IInterface

View file

@ -777,7 +777,9 @@ void CGraphicsBackend_SDL_GL::ClampDriverVersion(EBackendType BackendType)
bool CGraphicsBackend_SDL_GL::ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg)
{
if(m_pProcessor != nullptr)
{
m_pProcessor->ErroneousCleanup();
}
// TODO: Remove this workaround when https://github.com/libsdl-org/SDL/issues/3750 is
// fixed and pass the window to SDL_ShowSimpleMessageBox to make the popup modal instead
// of destroying the window before opening the popup.
@ -880,6 +882,12 @@ bool CGraphicsBackend_SDL_GL::GetDriverVersion(EGraphicsDriverAgeType DriverAgeT
return false;
}
const char *CGraphicsBackend_SDL_GL::GetScreenName(int Screen) const
{
const char *pName = SDL_GetDisplayName(Screen);
return pName == nullptr ? "unknown/error" : pName;
}
static void DisplayToVideoMode(CVideoMode *pVMode, SDL_DisplayMode *pMode, int HiDPIScale, int RefreshRate)
{
pVMode->m_CanvasWidth = pMode->w * HiDPIScale;
@ -1178,9 +1186,6 @@ int CGraphicsBackend_SDL_GL::Init(const char *pName, int *pScreen, int *pWidth,
}
}
if(g_Config.m_InpMouseOld)
SDL_SetHint(SDL_HINT_MOUSE_RELATIVE_MODE_WARP, "1");
m_pWindow = SDL_CreateWindow(
pName,
SDL_WINDOWPOS_CENTERED_DISPLAY(*pScreen),
@ -1604,7 +1609,8 @@ void CGraphicsBackend_SDL_GL::GetViewportSize(int &w, int &h)
void CGraphicsBackend_SDL_GL::NotifyWindow()
{
#if SDL_MAJOR_VERSION > 2 || (SDL_MAJOR_VERSION == 2 && SDL_PATCHLEVEL >= 16)
// Minimum version 2.0.16, after version 2.0.22 the naming is changed to 2.24.0 etc.
#if SDL_MAJOR_VERSION > 2 || (SDL_MAJOR_VERSION == 2 && SDL_MINOR_VERSION == 0 && SDL_PATCHLEVEL >= 16) || (SDL_MAJOR_VERSION == 2 && SDL_MINOR_VERSION > 0)
if(SDL_FlashWindow(m_pWindow, SDL_FlashOperation::SDL_FLASH_UNTIL_FOCUSED) != 0)
{
// fails if SDL hasn't implemented it

View file

@ -253,6 +253,7 @@ public:
const TTWGraphicsGPUList &GetGPUs() const override;
int GetNumScreens() const override { return m_NumScreens; }
const char *GetScreenName(int Screen) const override;
void GetVideoModes(CVideoMode *pModes, int MaxModes, int *pNumModes, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int ScreenID) override;
void GetCurrentVideoMode(CVideoMode &CurMode, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int ScreenID) override;

View file

@ -2165,7 +2165,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
if(g_Config.m_ClRunOnJoin[0])
{
str_format(aBuf, sizeof(aBuf), ";%s", g_Config.m_ClRunOnJoin);
str_append(aBufMsg, aBuf, sizeof(aBufMsg));
str_append(aBufMsg, aBuf);
}
if(g_Config.m_ClDummyDefaultEyes || g_Config.m_ClPlayerDefaultEyes)
{
@ -2195,7 +2195,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket, int Conn, bool Dummy)
if(aBufEmote[0])
{
str_format(aBuf, sizeof(aBuf), ";%s", aBufEmote);
str_append(aBufMsg, aBuf, sizeof(aBufMsg));
str_append(aBufMsg, aBuf);
}
}
MsgP.m_pMessage = aBufMsg;
@ -3343,8 +3343,15 @@ void CClient::Run()
else if(g_Config.m_ClRefreshRate)
{
SleepTimeInNanoSeconds = (std::chrono::nanoseconds(1s) / (int64_t)g_Config.m_ClRefreshRate) - (Now - LastTime);
if(SleepTimeInNanoSeconds > 0ns)
net_socket_read_wait(m_aNetClient[CONN_MAIN].m_Socket, SleepTimeInNanoSeconds);
auto SleepTimeInNanoSecondsInner = SleepTimeInNanoSeconds;
auto NowInner = Now;
while((SleepTimeInNanoSecondsInner / std::chrono::nanoseconds(1us).count()) > 0ns)
{
net_socket_read_wait(m_aNetClient[CONN_MAIN].m_Socket, SleepTimeInNanoSecondsInner);
auto NowInnerCalc = time_get_nanoseconds();
SleepTimeInNanoSecondsInner -= (NowInnerCalc - NowInner);
NowInner = NowInnerCalc;
}
Slept = true;
}
if(Slept)
@ -4631,8 +4638,19 @@ int main(int argc, const char **argv)
char aVersionStr[128];
if(!os_version_str(aVersionStr, sizeof(aVersionStr)))
str_copy(aVersionStr, "unknown");
char aMessage[512];
str_format(aMessage, sizeof(aMessage), "An assertion error occured. Please write down or take a screenshot of the following information and report this error.\nPlease also share the assert log which you should find in the 'dumps' folder in your config directory.\n\n%s\n\nPlatform: %s\nGame version: %s %s\nOS version: %s", pMsg, CONF_PLATFORM_STRING, GAME_RELEASE_VERSION, GIT_SHORTREV_HASH != nullptr ? GIT_SHORTREV_HASH : "", aVersionStr);
char aGPUInfo[256];
pClient->GetGPUInfoString(aGPUInfo);
char aMessage[768];
str_format(aMessage, sizeof(aMessage),
"An assertion error occured. Please write down or take a screenshot of the following information and report this error.\n"
"Please also share the assert log which you should find in the 'dumps' folder in your config directory.\n\n"
"%s\n\n"
"Platform: %s\n"
"Game version: %s %s\n"
"OS version: %s\n\n"
"%s", // GPU info
pMsg, CONF_PLATFORM_STRING, GAME_RELEASE_VERSION, GIT_SHORTREV_HASH != nullptr ? GIT_SHORTREV_HASH : "", aVersionStr,
aGPUInfo);
pClient->ShowMessageBox("Assertion Error", aMessage);
// Client will crash due to assertion, don't call PerformAllCleanup in this inconsistent state
});
@ -4763,9 +4781,10 @@ int main(int argc, const char **argv)
}
log_set_loglevel((LEVEL)g_Config.m_Loglevel);
const int Mode = g_Config.m_Logappend ? IOFLAG_APPEND : IOFLAG_WRITE;
if(g_Config.m_Logfile[0])
{
IOHANDLE Logfile = pStorage->OpenFile(g_Config.m_Logfile, IOFLAG_WRITE, IStorage::TYPE_SAVE_OR_ABSOLUTE);
IOHANDLE Logfile = pStorage->OpenFile(g_Config.m_Logfile, Mode, IStorage::TYPE_SAVE_OR_ABSOLUTE);
if(Logfile)
{
pFutureFileLogger->Set(log_logger_file(Logfile));
@ -4787,6 +4806,12 @@ int main(int argc, const char **argv)
SDL_SetHint("SDL_MAC_OPENGL_ASYNC_DISPATCH", "1");
#endif
#if defined(CONF_FAMILY_WINDOWS)
SDL_SetHint("SDL_IME_SHOW_UI", g_Config.m_InpImeNativeUi ? "1" : "0");
#else
SDL_SetHint("SDL_IME_SHOW_UI", "1");
#endif
// init SDL
if(SDL_Init(0) < 0)
{
@ -4874,8 +4899,8 @@ void CClient::RequestDDNetInfo()
{
char aEscaped[128];
EscapeUrl(aEscaped, sizeof(aEscaped), PlayerName());
str_append(aUrl, "?name=", sizeof(aUrl));
str_append(aUrl, aEscaped, sizeof(aUrl));
str_append(aUrl, "?name=");
str_append(aUrl, aEscaped);
}
// Use ipv4 so we can know the ingame ip addresses of players before they join game servers
@ -5040,3 +5065,15 @@ void CClient::ShowMessageBox(const char *pTitle, const char *pMessage, EMessageB
if(m_pGraphics == nullptr || !m_pGraphics->ShowMessageBox(GetSdlMessageBoxFlags(Type), pTitle, pMessage))
SDL_ShowSimpleMessageBox(GetSdlMessageBoxFlags(Type), pTitle, pMessage, nullptr);
}
void CClient::GetGPUInfoString(char (&aGPUInfo)[256])
{
if(m_pGraphics != nullptr && m_pGraphics->IsBackendInitialized())
{
str_format(aGPUInfo, std::size(aGPUInfo), "GPU: %s - %s - %s", m_pGraphics->GetVendorString(), m_pGraphics->GetRendererString(), m_pGraphics->GetVersionString());
}
else
{
str_copy(aGPUInfo, "Graphics backend was not yet initialized.");
}
}

View file

@ -553,6 +553,7 @@ public:
#endif
void ShowMessageBox(const char *pTitle, const char *pMessage, EMessageBoxType Type = MESSAGE_BOX_TYPE_ERROR) override;
void GetGPUInfoString(char (&aGPUInfo)[256]) override;
};
#endif

View file

@ -168,13 +168,13 @@ void CFriends::ConfigSaveCallback(IConfigManager *pConfigManager, void *pUserDat
{
str_copy(aBuf, pSelf->m_Foes ? "add_foe " : "add_friend ");
str_append(aBuf, "\"", sizeof(aBuf));
str_append(aBuf, "\"");
char *pDst = aBuf + str_length(aBuf);
str_escape(&pDst, pSelf->m_aFriends[i].m_aName, pEnd);
str_append(aBuf, "\" \"", sizeof(aBuf));
str_append(aBuf, "\" \"");
pDst = aBuf + str_length(aBuf);
str_escape(&pDst, pSelf->m_aFriends[i].m_aClan, pEnd);
str_append(aBuf, "\"", sizeof(aBuf));
str_append(aBuf, "\"");
pConfigManager->WriteLine(aBuf);
}

View file

@ -672,13 +672,13 @@ int CGraphics_Threaded::LoadPNG(CImageInfo *pImg, const char *pFilename, int Sto
{
if(!First)
{
str_append(Warning.m_aWarningMsg, ", ", sizeof(Warning.m_aWarningMsg));
str_append(Warning.m_aWarningMsg, ", ");
}
str_append(Warning.m_aWarningMsg, EXPLANATION[i], sizeof(Warning.m_aWarningMsg));
str_append(Warning.m_aWarningMsg, EXPLANATION[i]);
First = false;
}
}
str_append(Warning.m_aWarningMsg, " unsupported", sizeof(Warning.m_aWarningMsg));
str_append(Warning.m_aWarningMsg, " unsupported");
m_vWarnings.emplace_back(Warning);
}
}
@ -2939,6 +2939,11 @@ int CGraphics_Threaded::GetNumScreens() const
return m_pBackend->GetNumScreens();
}
const char *CGraphics_Threaded::GetScreenName(int Screen) const
{
return m_pBackend->GetScreenName(Screen);
}
void CGraphics_Threaded::Minimize()
{
m_pBackend->Minimize();
@ -3283,9 +3288,15 @@ bool CGraphics_Threaded::ShowMessageBox(unsigned Type, const char *pTitle, const
{
if(m_pBackend == nullptr)
return false;
m_pBackend->WaitForIdle();
return m_pBackend->ShowMessageBox(Type, pTitle, pMsg);
}
bool CGraphics_Threaded::IsBackendInitialized()
{
return m_pBackend != nullptr;
}
const char *CGraphics_Threaded::GetVendorString()
{
return m_pBackend->GetVendorString();
@ -3310,20 +3321,13 @@ int CGraphics_Threaded::GetVideoModes(CVideoMode *pModes, int MaxModes, int Scre
{
if(g_Config.m_GfxDisplayAllVideoModes)
{
int Count = std::size(g_aFakeModes);
mem_copy(pModes, g_aFakeModes, sizeof(g_aFakeModes));
if(MaxModes < Count)
Count = MaxModes;
const int Count = minimum<size_t>(std::size(g_aFakeModes), MaxModes);
mem_copy(pModes, g_aFakeModes, Count * sizeof(CVideoMode));
return Count;
}
// add videomodes command
CImageInfo Image;
mem_zero(&Image, sizeof(Image));
int NumModes = 0;
m_pBackend->GetVideoModes(pModes, MaxModes, &NumModes, m_ScreenHiDPIScale, g_Config.m_GfxDesktopWidth, g_Config.m_GfxDesktopHeight, Screen);
return NumModes;
}

View file

@ -731,6 +731,7 @@ public:
virtual void GetCurrentVideoMode(CVideoMode &CurMode, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int Screen) = 0;
virtual int GetNumScreens() const = 0;
virtual const char *GetScreenName(int Screen) const = 0;
virtual void Minimize() = 0;
virtual void Maximize() = 0;
@ -1257,6 +1258,8 @@ public:
void IndicesNumRequiredNotify(unsigned int RequiredIndicesCount) override;
int GetNumScreens() const override;
const char *GetScreenName(int Screen) const override;
void Minimize() override;
void Maximize() override;
void WarnPngliteIncompatibleImages(bool Warn) override;
@ -1300,6 +1303,7 @@ public:
SWarning *GetCurWarning() override;
bool ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg) override;
bool IsBackendInitialized() override;
bool GetDriverVersion(EGraphicsDriverAgeType DriverAgeType, int &Major, int &Minor, int &Patch, const char *&pName, EBackendType BackendType) override { return m_pBackend->GetDriverVersion(DriverAgeType, Major, Minor, Patch, pName, BackendType); }
bool IsConfigModernAPI() override { return m_pBackend->IsConfigModernAPI(); }

View file

@ -187,14 +187,10 @@ void CInput::CloseJoysticks()
m_pActiveJoystick = nullptr;
}
void CInput::SelectNextJoystick()
void CInput::SetActiveJoystick(size_t Index)
{
const int Num = m_vJoysticks.size();
if(Num > 1)
{
m_pActiveJoystick = &m_vJoysticks[(m_pActiveJoystick->GetIndex() + 1) % Num];
str_copy(g_Config.m_InpControllerGUID, m_pActiveJoystick->GetGUID());
}
m_pActiveJoystick = &m_vJoysticks[Index];
str_copy(g_Config.m_InpControllerGUID, m_pActiveJoystick->GetGUID());
}
float CInput::CJoystick::GetAxisValue(int Axis)

View file

@ -122,8 +122,9 @@ public:
bool KeyPress(int Key, bool CheckCounter) const override { return CheckCounter ? (m_aInputCount[Key] == m_InputCounter) : m_aInputCount[Key]; }
size_t NumJoysticks() const override { return m_vJoysticks.size(); }
CJoystick *GetJoystick(size_t Index) override { return &m_vJoysticks[Index]; }
CJoystick *GetActiveJoystick() override { return m_pActiveJoystick; }
void SelectNextJoystick() override;
void SetActiveJoystick(size_t Index) override;
bool MouseRelative(float *pX, float *pY) override;
void MouseModeAbsolute() override;

View file

@ -291,6 +291,12 @@ const char g_aaKeyStrings[512][20] = // NOLINT(misc-definitions-in-headers)
"sleep",
"app1",
"app2",
"audiorewind",
"audiofastforward",
"softleft",
"softright",
"call",
"endcall",
"mouse1",
"mouse2",
"mouse3",
@ -348,12 +354,6 @@ const char g_aaKeyStrings[512][20] = // NOLINT(misc-definitions-in-headers)
"joy_axis10_right",
"joy_axis11_left",
"joy_axis11_right",
"&342",
"&343",
"&344",
"&345",
"&346",
"&347",
"&348",
"&349",
"&350",

View file

@ -575,7 +575,7 @@ void CServerBrowser::SetInfo(CServerEntry *pEntry, const CServerInfo &Info)
class CPlayerScoreNameLess
{
int ScoreKind;
const int ScoreKind;
public:
CPlayerScoreNameLess(int ClientScoreKind) :
@ -585,6 +585,7 @@ void CServerBrowser::SetInfo(CServerEntry *pEntry, const CServerInfo &Info)
bool operator()(const CServerInfo::CClient &p0, const CServerInfo::CClient &p1)
{
// Sort players before non players
if(p0.m_Player && !p1.m_Player)
return true;
if(!p0.m_Player && p1.m_Player)
@ -593,33 +594,22 @@ void CServerBrowser::SetInfo(CServerEntry *pEntry, const CServerInfo &Info)
int Score0 = p0.m_Score;
int Score1 = p1.m_Score;
if(ScoreKind == CServerInfo::CLIENT_SCORE_KIND_TIME)
if(ScoreKind == CServerInfo::CLIENT_SCORE_KIND_TIME || ScoreKind == CServerInfo::CLIENT_SCORE_KIND_TIME_BACKCOMPAT)
{
// time is sent as a positive value to the http master, counting 0, if there is a time (finished)
// only positive times are meant to represent an actual time.
if(Score0 != Score1)
{
if(Score0 < 0)
return false;
if(Score1 < 0)
return true;
return Score0 < Score1;
}
}
else
{
if(ScoreKind == CServerInfo::CLIENT_SCORE_KIND_TIME_BACKCOMPAT)
{
if(Score0 == -9999)
Score0 = INT_MIN;
if(Score1 == -9999)
Score1 = INT_MIN;
}
if(Score0 > Score1)
return true;
if(Score0 < Score1)
// Sort unfinished (-9999) and still connecting players (-1) after others
if(Score0 < 0 && Score1 >= 0)
return false;
if(Score0 >= 0 && Score1 < 0)
return true;
}
if(Score0 != Score1)
{
// Handle the sign change introduced with CLIENT_SCORE_KIND_TIME
if(ScoreKind == CServerInfo::CLIENT_SCORE_KIND_TIME)
return Score0 < Score1;
else
return Score0 > Score1;
}
return str_comp_nocase(p0.m_aName, p1.m_aName) < 0;
@ -1425,17 +1415,17 @@ int CServerBrowser::LoadingProgression() const
return 100.0f * Loaded / Servers;
}
void CServerBrowser::DDNetFilterAdd(char *pFilter, const char *pName)
void CServerBrowser::DDNetFilterAdd(char *pFilter, int FilterSize, const char *pName) const
{
if(DDNetFiltered(pFilter, pName))
return;
char aBuf[128];
str_format(aBuf, sizeof(aBuf), ",%s", pName);
str_append(pFilter, aBuf, 128);
str_append(pFilter, aBuf, FilterSize);
}
void CServerBrowser::DDNetFilterRem(char *pFilter, const char *pName)
void CServerBrowser::DDNetFilterRem(char *pFilter, int FilterSize, const char *pName) const
{
if(!DDNetFiltered(pFilter, pName))
return;
@ -1453,12 +1443,12 @@ void CServerBrowser::DDNetFilterRem(char *pFilter, const char *pName)
{
char aBuf2[128];
str_format(aBuf2, sizeof(aBuf2), ",%s", aToken);
str_append(pFilter, aBuf2, 128);
str_append(pFilter, aBuf2, FilterSize);
}
}
}
bool CServerBrowser::DDNetFiltered(char *pFilter, const char *pName)
bool CServerBrowser::DDNetFiltered(const char *pFilter, const char *pName) const
{
return str_in_list(pFilter, ",", pName); // country not excluded
}
@ -1478,7 +1468,7 @@ void CServerBrowser::CountryFilterClean(int Network)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), ",%s", pName);
str_append(aNewList, aBuf, sizeof(aNewList));
str_append(aNewList, aBuf);
}
}
}
@ -1499,7 +1489,7 @@ void CServerBrowser::TypeFilterClean(int Network)
{
char aBuf[128];
str_format(aBuf, sizeof(aBuf), ",%s", pName);
str_append(aNewList, aBuf, sizeof(aNewList));
str_append(aNewList, aBuf);
}
}

View file

@ -114,9 +114,9 @@ public:
int NumTypes(int Network) override { return m_aNetworks[Network].m_NumTypes; }
const char *GetType(int Network, int Index) override { return m_aNetworks[Network].m_aTypes[Index]; }
void DDNetFilterAdd(char *pFilter, const char *pName) override;
void DDNetFilterRem(char *pFilter, const char *pName) override;
bool DDNetFiltered(char *pFilter, const char *pName) override;
void DDNetFilterAdd(char *pFilter, int FilterSize, const char *pName) const override;
void DDNetFilterRem(char *pFilter, int FilterSize, const char *pName) const override;
bool DDNetFiltered(const char *pFilter, const char *pName) const override;
void CountryFilterClean(int Network) override;
void TypeFilterClean(int Network) override;

View file

@ -576,7 +576,7 @@ int CSound::DecodeWV(int SampleID, const void *pData, unsigned DataSize)
return SampleID;
}
int CSound::LoadOpus(const char *pFilename)
int CSound::LoadOpus(const char *pFilename, int StorageType)
{
// don't waste memory on sound when we are stress testing
#ifdef CONF_DEBUG
@ -600,7 +600,7 @@ int CSound::LoadOpus(const char *pFilename)
void *pData;
unsigned DataSize;
if(!m_pStorage->ReadFile(pFilename, IStorage::TYPE_ALL, &pData, &DataSize))
if(!m_pStorage->ReadFile(pFilename, StorageType, &pData, &DataSize))
{
dbg_msg("sound/opus", "failed to open file. filename='%s'", pFilename);
return -1;
@ -618,7 +618,7 @@ int CSound::LoadOpus(const char *pFilename)
return SampleID;
}
int CSound::LoadWV(const char *pFilename)
int CSound::LoadWV(const char *pFilename, int StorageType)
{
// don't waste memory on sound when we are stress testing
#ifdef CONF_DEBUG
@ -642,7 +642,7 @@ int CSound::LoadWV(const char *pFilename)
void *pData;
unsigned DataSize;
if(!m_pStorage->ReadFile(pFilename, IStorage::TYPE_ALL, &pData, &DataSize))
if(!m_pStorage->ReadFile(pFilename, StorageType, &pData, &DataSize))
{
dbg_msg("sound/wv", "failed to open file. filename='%s'", pFilename);
return -1;

View file

@ -34,9 +34,9 @@ public:
bool IsSoundEnabled() override { return m_SoundEnabled; }
int LoadWV(const char *pFilename) override;
int LoadWV(const char *pFilename, int StorageType = IStorage::TYPE_ALL) override;
int LoadWVFromMem(const void *pData, unsigned DataSize, bool FromEditor) override;
int LoadOpus(const char *pFilename) override;
int LoadOpus(const char *pFilename, int StorageType = IStorage::TYPE_ALL) override;
int LoadOpusFromMem(const void *pData, unsigned DataSize, bool FromEditor) override;
void UnloadSample(int SampleID) override;

View file

@ -132,9 +132,7 @@ public:
struct STextString
{
int m_QuadBufferObjectIndex;
uint32_t m_DbgShadowBytes = 0x12345678;
int m_QuadBufferContainerIndex;
uint32_t m_DbgShadowBytes2 = 0x87654321;
size_t m_QuadNum;
int m_SelectionQuadContainerIndex;
@ -1033,7 +1031,7 @@ public:
void AppendTextContainer(STextContainerIndex TextContainerIndex, CTextCursor *pCursor, const char *pText, int Length = -1) override
{
STextContainer &TextContainer = GetTextContainer(TextContainerIndex);
str_append(TextContainer.m_aDebugText, pText, sizeof(TextContainer.m_aDebugText));
str_append(TextContainer.m_aDebugText, pText);
// calculate the font size of the displayed glyphs
float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
@ -1993,7 +1991,6 @@ public:
dbg_msg("textrender", "The text container index was in use by %d ", (int)pTextContainer->m_ContainerIndex.m_UseCount.use_count());
HasNonEmptyTextContainer = true; // NOLINT(clang-analyzer-deadcode.DeadStores)
}
dbg_assert(pTextContainer->m_StringInfo.m_DbgShadowBytes == STextString{}.m_DbgShadowBytes && pTextContainer->m_StringInfo.m_DbgShadowBytes2 == STextString{}.m_DbgShadowBytes2, "shadow bytes were modified in text container.");
}
dbg_assert(!HasNonEmptyTextContainer, "text container was not empty");

View file

@ -315,7 +315,7 @@ void CUpdater::PerformUpdate()
char aBuf[512];
str_copy(aBuf, pFile, sizeof(aBuf)); // SDL
str_copy(aBuf + len - 4, "-" PLAT_NAME, sizeof(aBuf) - len + 4); // -win32
str_append(aBuf, pFile + len - 4, sizeof(aBuf)); // .dll
str_append(aBuf, pFile + len - 4); // .dll
FetchFile(aBuf, pFile);
#endif
// Ignore DLL downloads on other platforms
@ -326,7 +326,7 @@ void CUpdater::PerformUpdate()
char aBuf[512];
str_copy(aBuf, pFile, sizeof(aBuf)); // libsteam_api
str_copy(aBuf + len - 3, "-" PLAT_NAME, sizeof(aBuf) - len + 3); // -linux-x86_64
str_append(aBuf, pFile + len - 3, sizeof(aBuf)); // .so
str_append(aBuf, pFile + len - 3); // .so
FetchFile(aBuf, pFile);
#endif
// Ignore DLL downloads on other platforms, on Linux we statically link anyway

View file

@ -506,6 +506,7 @@ public:
virtual void Swap() = 0;
virtual int GetNumScreens() const = 0;
virtual const char *GetScreenName(int Screen) const = 0;
// synchronization
virtual void InsertSignal(class CSemaphore *pSemaphore) = 0;
@ -523,6 +524,7 @@ public:
// returns true if the error msg was shown
virtual bool ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg) = 0;
virtual bool IsBackendInitialized() = 0;
protected:
inline CTextureHandle CreateTextureHandle(int Index)

View file

@ -98,8 +98,9 @@ public:
virtual bool Absolute(float *pX, float *pY) = 0;
};
virtual size_t NumJoysticks() const = 0;
virtual IJoystick *GetJoystick(size_t Index) = 0;
virtual IJoystick *GetActiveJoystick() = 0;
virtual void SelectNextJoystick() = 0;
virtual void SetActiveJoystick(size_t Index) = 0;
// mouse
virtual void NativeMousePos(int *pX, int *pY) const = 0;

View file

@ -248,67 +248,73 @@ enum
KEY_SLEEP = 282,
KEY_APP1 = 283,
KEY_APP2 = 284,
KEY_AUDIOREWIND = 285,
KEY_AUDIOFASTFORWARD = 286,
KEY_SOFTLEFT = 287,
KEY_SOFTRIGHT = 288,
KEY_CALL = 289,
KEY_ENDCALL = 290,
KEY_MOUSE_1 = 285,
KEY_MOUSE_2 = 286,
KEY_MOUSE_3 = 287,
KEY_MOUSE_4 = 288,
KEY_MOUSE_5 = 289,
KEY_MOUSE_6 = 290,
KEY_MOUSE_7 = 291,
KEY_MOUSE_8 = 292,
KEY_MOUSE_9 = 293,
KEY_MOUSE_WHEEL_UP = 294,
KEY_MOUSE_WHEEL_DOWN = 295,
KEY_MOUSE_WHEEL_LEFT = 296,
KEY_MOUSE_WHEEL_RIGHT = 297,
KEY_MOUSE_1 = 291,
KEY_MOUSE_2 = 292,
KEY_MOUSE_3 = 293,
KEY_MOUSE_4 = 294,
KEY_MOUSE_5 = 295,
KEY_MOUSE_6 = 296,
KEY_MOUSE_7 = 297,
KEY_MOUSE_8 = 298,
KEY_MOUSE_9 = 299,
KEY_MOUSE_WHEEL_UP = 300,
KEY_MOUSE_WHEEL_DOWN = 301,
KEY_MOUSE_WHEEL_LEFT = 302,
KEY_MOUSE_WHEEL_RIGHT = 303,
KEY_JOYSTICK_BUTTON_0 = 298,
KEY_JOYSTICK_BUTTON_1 = 299,
KEY_JOYSTICK_BUTTON_2 = 300,
KEY_JOYSTICK_BUTTON_3 = 301,
KEY_JOYSTICK_BUTTON_4 = 302,
KEY_JOYSTICK_BUTTON_5 = 303,
KEY_JOYSTICK_BUTTON_6 = 304,
KEY_JOYSTICK_BUTTON_7 = 305,
KEY_JOYSTICK_BUTTON_8 = 306,
KEY_JOYSTICK_BUTTON_9 = 307,
KEY_JOYSTICK_BUTTON_10 = 308,
KEY_JOYSTICK_BUTTON_11 = 309,
KEY_JOYSTICK_BUTTON_0 = 304,
KEY_JOYSTICK_BUTTON_1 = 305,
KEY_JOYSTICK_BUTTON_2 = 306,
KEY_JOYSTICK_BUTTON_3 = 307,
KEY_JOYSTICK_BUTTON_4 = 308,
KEY_JOYSTICK_BUTTON_5 = 309,
KEY_JOYSTICK_BUTTON_6 = 310,
KEY_JOYSTICK_BUTTON_7 = 311,
KEY_JOYSTICK_BUTTON_8 = 312,
KEY_JOYSTICK_BUTTON_9 = 313,
KEY_JOYSTICK_BUTTON_10 = 314,
KEY_JOYSTICK_BUTTON_11 = 315,
KEY_JOY_HAT0_UP = 310,
KEY_JOY_HAT0_LEFT = 311,
KEY_JOY_HAT0_RIGHT = 312,
KEY_JOY_HAT0_DOWN = 313,
KEY_JOY_HAT1_UP = 314,
KEY_JOY_HAT1_LEFT = 315,
KEY_JOY_HAT1_RIGHT = 316,
KEY_JOY_HAT1_DOWN = 317,
KEY_JOY_HAT0_UP = 316,
KEY_JOY_HAT0_LEFT = 317,
KEY_JOY_HAT0_RIGHT = 318,
KEY_JOY_HAT0_DOWN = 319,
KEY_JOY_HAT1_UP = 320,
KEY_JOY_HAT1_LEFT = 321,
KEY_JOY_HAT1_RIGHT = 322,
KEY_JOY_HAT1_DOWN = 323,
KEY_JOY_AXIS_0_LEFT = 318,
KEY_JOY_AXIS_0_RIGHT = 319,
KEY_JOY_AXIS_1_LEFT = 320,
KEY_JOY_AXIS_1_RIGHT = 321,
KEY_JOY_AXIS_2_LEFT = 322,
KEY_JOY_AXIS_2_RIGHT = 323,
KEY_JOY_AXIS_3_LEFT = 324,
KEY_JOY_AXIS_3_RIGHT = 325,
KEY_JOY_AXIS_4_LEFT = 326,
KEY_JOY_AXIS_4_RIGHT = 327,
KEY_JOY_AXIS_5_LEFT = 328,
KEY_JOY_AXIS_5_RIGHT = 329,
KEY_JOY_AXIS_6_LEFT = 330,
KEY_JOY_AXIS_6_RIGHT = 331,
KEY_JOY_AXIS_7_LEFT = 332,
KEY_JOY_AXIS_7_RIGHT = 333,
KEY_JOY_AXIS_8_LEFT = 334,
KEY_JOY_AXIS_8_RIGHT = 335,
KEY_JOY_AXIS_9_LEFT = 336,
KEY_JOY_AXIS_9_RIGHT = 337,
KEY_JOY_AXIS_10_LEFT = 338,
KEY_JOY_AXIS_10_RIGHT = 339,
KEY_JOY_AXIS_11_LEFT = 340,
KEY_JOY_AXIS_11_RIGHT = 341,
KEY_JOY_AXIS_0_LEFT = 324,
KEY_JOY_AXIS_0_RIGHT = 325,
KEY_JOY_AXIS_1_LEFT = 326,
KEY_JOY_AXIS_1_RIGHT = 327,
KEY_JOY_AXIS_2_LEFT = 328,
KEY_JOY_AXIS_2_RIGHT = 329,
KEY_JOY_AXIS_3_LEFT = 330,
KEY_JOY_AXIS_3_RIGHT = 331,
KEY_JOY_AXIS_4_LEFT = 332,
KEY_JOY_AXIS_4_RIGHT = 333,
KEY_JOY_AXIS_5_LEFT = 334,
KEY_JOY_AXIS_5_RIGHT = 335,
KEY_JOY_AXIS_6_LEFT = 336,
KEY_JOY_AXIS_6_RIGHT = 337,
KEY_JOY_AXIS_7_LEFT = 338,
KEY_JOY_AXIS_7_RIGHT = 339,
KEY_JOY_AXIS_8_LEFT = 340,
KEY_JOY_AXIS_8_RIGHT = 341,
KEY_JOY_AXIS_9_LEFT = 342,
KEY_JOY_AXIS_9_RIGHT = 343,
KEY_JOY_AXIS_10_LEFT = 344,
KEY_JOY_AXIS_10_RIGHT = 345,
KEY_JOY_AXIS_11_LEFT = 346,
KEY_JOY_AXIS_11_RIGHT = 347,
KEY_LAST = 512,

View file

@ -169,7 +169,7 @@ bool CAntibot::OnEngineClientMessage(int ClientID, const void *pData, int Size,
{
AntibotFlags |= ANTIBOT_MSGFLAG_NONVITAL;
}
return AntibotOnEngineClientMessage(ClientID, pData, Size, Flags);
return AntibotOnEngineClientMessage(ClientID, pData, Size, AntibotFlags);
}
bool CAntibot::OnEngineServerMessage(int ClientID, const void *pData, int Size, int Flags)
{
@ -179,7 +179,7 @@ bool CAntibot::OnEngineServerMessage(int ClientID, const void *pData, int Size,
{
AntibotFlags |= ANTIBOT_MSGFLAG_NONVITAL;
}
return AntibotOnEngineServerMessage(ClientID, pData, Size, Flags);
return AntibotOnEngineServerMessage(ClientID, pData, Size, AntibotFlags);
}
bool CAntibot::OnEngineSimulateClientMessage(int *pClientID, void *pBuffer, int BufferSize, int *pOutSize, int *pFlags)
{

View file

@ -117,8 +117,6 @@ CSqlExecData::CSqlExecData(IConsole *pConsole, CDbConnectionPool::Mode m) :
m_Ptr.m_Print.m_Mode = m;
}
CDbConnectionPool::~CDbConnectionPool() = default;
void CDbConnectionPool::Print(IConsole *pConsole, Mode DatabaseMode)
{
m_pShared->m_aQueries[m_InsertIdx++] = std::make_unique<CSqlExecData>(pConsole, DatabaseMode);
@ -466,7 +464,14 @@ bool CDbConnectionPool::ExecSqlFunc(IDbConnection *pConnection, CSqlExecData *pD
CDbConnectionPool::CDbConnectionPool()
{
m_pShared = std::make_shared<CSharedData>();
thread_init_and_detach(CWorker::Start, new CWorker(m_pShared), "database worker thread");
thread_init_and_detach(CBackup::Start, new CBackup(m_pShared), "database backup worker thread");
m_pWorkerThread = thread_init(CWorker::Start, new CWorker(m_pShared), "database worker thread");
m_pBackupThread = thread_init(CBackup::Start, new CBackup(m_pShared), "database backup worker thread");
}
CDbConnectionPool::~CDbConnectionPool()
{
if(m_pWorkerThread)
thread_wait(m_pWorkerThread);
if(m_pBackupThread)
thread_wait(m_pBackupThread);
}

View file

@ -124,6 +124,8 @@ private:
};
std::shared_ptr<CSharedData> m_pShared;
void *m_pWorkerThread = nullptr;
void *m_pBackupThread = nullptr;
};
#endif // ENGINE_SERVER_DATABASES_CONNECTION_POOL_H

View file

@ -170,9 +170,10 @@ int main(int argc, const char **argv)
pConsole->Register("sv_rescue", "", CFGFLAG_SERVER, CServer::ConRescue, pConsole, "Allow /rescue command so players can teleport themselves out of freeze (setting only works in initial config)");
log_set_loglevel((LEVEL)g_Config.m_Loglevel);
const int Mode = g_Config.m_Logappend ? IOFLAG_APPEND : IOFLAG_WRITE;
if(g_Config.m_Logfile[0])
{
IOHANDLE Logfile = pStorage->OpenFile(g_Config.m_Logfile, IOFLAG_WRITE, IStorage::TYPE_SAVE_OR_ABSOLUTE);
IOHANDLE Logfile = pStorage->OpenFile(g_Config.m_Logfile, Mode, IStorage::TYPE_SAVE_OR_ABSOLUTE);
if(Logfile)
{
pFutureFileLogger->Set(log_logger_file(Logfile));
@ -189,12 +190,12 @@ int main(int argc, const char **argv)
dbg_msg("server", "starting...");
int Ret = pServer->Run();
MysqlUninit();
secure_random_uninit();
pServerLogger->OnServerDeletion();
// free
delete pKernel;
MysqlUninit();
secure_random_uninit();
return Ret;
}

View file

@ -1293,11 +1293,11 @@ void CServer::SendRconLogLine(int ClientID, const CLogMessage *pMessage)
{
str_append(aLine, pLine, pStart - pLine + 1);
str_append(aLine, pStart + 2, pStart - pLine + pEnd - pStart - 1);
str_append(aLine, pEnd + 2, sizeof(aLine));
str_append(aLine, pEnd + 2);
str_append(aLineWithoutIps, pLine, pStart - pLine + 1);
str_append(aLineWithoutIps, "XXX", sizeof(aLineWithoutIps));
str_append(aLineWithoutIps, pEnd + 2, sizeof(aLineWithoutIps));
str_append(aLineWithoutIps, "XXX");
str_append(aLineWithoutIps, pEnd + 2);
pLine = aLine;
pLineWithoutIps = aLineWithoutIps;
@ -1366,6 +1366,38 @@ static inline int MsgFromSixup(int Msg, bool System)
return Msg;
}
bool CServer::CheckReservedSlotAuth(int ClientID, const char *pPassword)
{
char aBuf[256];
if(Config()->m_SvReservedSlotsPass[0] && !str_comp(Config()->m_SvReservedSlotsPass, pPassword))
{
str_format(aBuf, sizeof(aBuf), "cid=%d joining reserved slot with reserved pass", ClientID);
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
return true;
}
// "^([^:]*):(.*)$"
if(Config()->m_SvReservedSlotsAuthLevel != 4)
{
char aName[sizeof(Config()->m_Password)];
const char *pInnerPassword = str_next_token(pPassword, ":", aName, sizeof(aName));
if(!pInnerPassword)
{
return false;
}
int Slot = m_AuthManager.FindKey(aName);
if(m_AuthManager.CheckKey(Slot, pInnerPassword + 1) && m_AuthManager.KeyLevel(Slot) >= Config()->m_SvReservedSlotsAuthLevel)
{
str_format(aBuf, sizeof(aBuf), "cid=%d joining reserved slot with key=%s", ClientID, m_AuthManager.KeyIdent(Slot));
Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "server", aBuf);
return true;
}
}
return false;
}
void CServer::ProcessClientPacket(CNetChunk *pPacket)
{
int ClientID = pPacket->m_ClientID;
@ -1466,7 +1498,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
}
// reserved slot
if(ClientID >= (Config()->m_SvMaxClients - Config()->m_SvReservedSlots) && Config()->m_SvReservedSlotsPass[0] != 0 && str_comp(Config()->m_SvReservedSlotsPass, pPassword) != 0)
if(ClientID >= Config()->m_SvMaxClients - Config()->m_SvReservedSlots && !CheckReservedSlotAuth(ClientID, pPassword))
{
m_NetServer.Drop(ClientID, "This server is full");
return;
@ -2287,12 +2319,12 @@ void CServer::UpdateRegisterServerInfo()
m_aClients[i].m_Score.value_or(-9999),
JsonBool(GameServer()->IsClientPlayer(i)),
aExtraPlayerInfo);
str_append(aInfo, aClientInfo, sizeof(aInfo));
str_append(aInfo, aClientInfo);
FirstPlayer = false;
}
}
str_append(aInfo, "]}", sizeof(aInfo));
str_append(aInfo, "]}");
m_pRegister->OnNewInfo(aInfo);
}

View file

@ -339,6 +339,7 @@ public:
void SendRconCmdRem(const IConsole::CCommandInfo *pCommandInfo, int ClientID);
void UpdateClientRconCommands();
bool CheckReservedSlotAuth(int ClientID, const char *pPassword);
void ProcessClientPacket(CNetChunk *pPacket);
class CCache

View file

@ -165,9 +165,9 @@ public:
virtual int NumTypes(int Network) = 0;
virtual const char *GetType(int Network, int Index) = 0;
virtual void DDNetFilterAdd(char *pFilter, const char *pName) = 0;
virtual void DDNetFilterRem(char *pFilter, const char *pName) = 0;
virtual bool DDNetFiltered(char *pFilter, const char *pName) = 0;
virtual void DDNetFilterAdd(char *pFilter, int FilterSize, const char *pName) const = 0;
virtual void DDNetFilterRem(char *pFilter, int FilterSize, const char *pName) const = 0;
virtual bool DDNetFiltered(const char *pFilter, const char *pName) const = 0;
virtual void CountryFilterClean(int Network) = 0;
virtual void TypeFilterClean(int Network) = 0;
virtual int GetCurrentType() = 0;

View file

@ -12,6 +12,7 @@ MACRO_CONFIG_INT(PlayerCountry, player_country, -1, -1, 1000, CFGFLAG_SAVE | CFG
MACRO_CONFIG_STR(Password, password, 32, "", CFGFLAG_CLIENT | CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC, "Password to the server")
MACRO_CONFIG_STR(Logfile, logfile, 128, "", CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Filename to log all output to")
MACRO_CONFIG_INT(Loglevel, loglevel, 2, 0, 4, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Log level (0 = Error, 1 = Warn, 2 = Info, 3 = Debug, 4 = Trace)")
MACRO_CONFIG_INT(Logappend, logappend, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Append to logfile instead of overwriting it every time")
MACRO_CONFIG_INT(ConsoleOutputLevel, console_output_level, 0, 0, 2, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Adjusts the amount of information in the console")
MACRO_CONFIG_INT(ConsoleEnableColors, console_enable_colors, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Enable colors in console output")
MACRO_CONFIG_INT(Events, events, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT | CFGFLAG_SERVER, "Enable triggering of events, (eye emotes on some holidays in server, christmas skins in client).")
@ -77,11 +78,10 @@ MACRO_CONFIG_INT(BrDemoSortOrder, br_demo_sort_order, 0, 0, 1, CFGFLAG_SAVE | CF
MACRO_CONFIG_INT(BrDemoFetchInfo, br_demo_fetch_info, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Whether to auto fetch demo infos on refresh")
MACRO_CONFIG_INT(SndBufferSize, snd_buffer_size, 512, 128, 32768, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Sound buffer size")
MACRO_CONFIG_INT(SndRate, snd_rate, 48000, 0, 0, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Sound mixing rate")
MACRO_CONFIG_INT(SndRate, snd_rate, 48000, 5512, 384000, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Sound mixing rate")
MACRO_CONFIG_INT(SndEnable, snd_enable, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Sound enable")
MACRO_CONFIG_INT(SndMusic, snd_enable_music, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Play background music")
MACRO_CONFIG_INT(SndVolume, snd_volume, 30, 0, 100, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Sound volume")
MACRO_CONFIG_INT(SndDevice, snd_device, -1, 0, 0, CFGFLAG_SAVE | CFGFLAG_CLIENT, "(deprecated) Sound device to use")
MACRO_CONFIG_INT(SndChatSoundVolume, snd_chat_volume, 30, 0, 100, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Chat sound volume")
MACRO_CONFIG_INT(SndGameSoundVolume, snd_game_volume, 30, 0, 100, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Game sound volume")
MACRO_CONFIG_INT(SndMapSoundVolume, snd_ambient_volume, 30, 0, 100, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Map Sound sound volume")
@ -125,13 +125,14 @@ MACRO_CONFIG_INT(GfxFinish, gfx_finish, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT,
MACRO_CONFIG_INT(GfxBackgroundRender, gfx_backgroundrender, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Render graphics when window is in background")
MACRO_CONFIG_INT(GfxTextOverlay, gfx_text_overlay, 10, 1, 100, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Stop rendering textoverlay in editor or with entities: high value = less details = more speed")
MACRO_CONFIG_INT(GfxAsyncRenderOld, gfx_asyncrender_old, 1, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Do rendering async from the the update")
MACRO_CONFIG_INT(GfxTuneOverlay, gfx_tune_overlay, 20, 1, 100, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Stop rendering text overlay in tuning zone in editor: high value = less details = more speed")
MACRO_CONFIG_INT(GfxQuadAsTriangle, gfx_quad_as_triangle, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Render quads as triangles (fixes quad coloring on some GPUs)")
MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 200, 1, 100000, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Mouse sensitivity")
MACRO_CONFIG_INT(InpMouseOld, inp_mouseold, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Use old mouse mode (warp mouse instead of raw input)")
MACRO_CONFIG_INT(InpTranslatedKeys, inp_translated_keys, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Translate keys before interpreting them, respects keyboard layouts")
MACRO_CONFIG_INT(InpIgnoredModifiers, inp_ignored_modifiers, 0, 0, 65536, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Ignored keyboard modifier mask")
#if defined(CONF_FAMILY_WINDOWS)
MACRO_CONFIG_INT(InpImeNativeUi, inp_ime_native_ui, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Use native UI for IME (may cause IME to not work in fullscreen mode) (changing requires restart)")
#endif
MACRO_CONFIG_INT(InpControllerEnable, inp_controller_enable, 0, 0, 1, CFGFLAG_SAVE | CFGFLAG_CLIENT, "Enable controller")
MACRO_CONFIG_STR(InpControllerGUID, inp_controller_guid, 34, "", CFGFLAG_SAVE | CFGFLAG_CLIENT, "Controller GUID which uniquely identifies the active controller")
@ -149,7 +150,6 @@ MACRO_CONFIG_STR(SvName, sv_name, 128, "unnamed server", CFGFLAG_SERVER, "Server
MACRO_CONFIG_STR(Bindaddr, bindaddr, 128, "", CFGFLAG_CLIENT | CFGFLAG_SERVER | CFGFLAG_MASTER, "Address to bind the client/server to")
MACRO_CONFIG_INT(SvIpv4Only, sv_ipv4only, 0, 0, 1, CFGFLAG_SERVER, "Whether to bind only to ipv4, otherwise bind to all available interfaces")
MACRO_CONFIG_INT(SvPort, sv_port, 0, 0, 0, CFGFLAG_SERVER, "Port to use for the server (Only ports 8303-8310 work in LAN server browser, 0 to automatically find a free port in 8303-8310)")
MACRO_CONFIG_INT(SvExternalPort, sv_external_port, 0, 0, 0, CFGFLAG_SERVER, "External port to report to the master servers")
MACRO_CONFIG_STR(SvHostname, sv_hostname, 128, "", CFGFLAG_SAVE | CFGFLAG_SERVER, "Server hostname (0.7 only)")
MACRO_CONFIG_STR(SvMap, sv_map, 128, "Sunny Side Up", CFGFLAG_SERVER, "Map to use on the server")
MACRO_CONFIG_INT(SvMaxClients, sv_max_clients, MAX_CLIENTS, 1, MAX_CLIENTS, CFGFLAG_SERVER, "Maximum number of clients that are allowed on a server")
@ -191,13 +191,11 @@ MACRO_CONFIG_INT(EcOutputLevel, ec_output_level, 1, 0, 2, CFGFLAG_ECON, "Adjusts
MACRO_CONFIG_INT(Debug, debug, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Debug mode")
MACRO_CONFIG_INT(DbgCurl, dbg_curl, 0, 0, 1, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Debug curl")
MACRO_CONFIG_INT(DbgPref, dbg_pref, 0, 0, 1, CFGFLAG_SERVER, "Performance outputs")
MACRO_CONFIG_INT(DbgGraphs, dbg_graphs, 0, 0, 1, CFGFLAG_CLIENT, "Performance graphs")
MACRO_CONFIG_INT(DbgHitch, dbg_hitch, 0, 0, 0, CFGFLAG_SERVER, "Hitch warnings")
MACRO_CONFIG_INT(DbgGfx, dbg_gfx, 0, 0, 4, CFGFLAG_CLIENT, "Show graphic library warnings and errors, if the GPU supports it (0: none, 1: minimal, 2: affects performance, 3: verbose, 4: all)")
#ifdef CONF_DEBUG
MACRO_CONFIG_INT(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Stress systems (Debug build only)")
MACRO_CONFIG_INT(DbgStressNetwork, dbg_stress_network, 0, 0, 0, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Stress network (Debug build only)")
MACRO_CONFIG_STR(DbgStressServer, dbg_stress_server, 32, "localhost", CFGFLAG_CLIENT, "Server to stress (Debug build only)")
#endif
@ -207,6 +205,7 @@ MACRO_CONFIG_INT(HttpAllowInsecure, http_allow_insecure, 0, 0, 1, CFGFLAG_CLIENT
MACRO_CONFIG_STR(SvWelcome, sv_welcome, 64, "", CFGFLAG_SERVER, "Message that will be displayed to players who join the server")
MACRO_CONFIG_INT(SvReservedSlots, sv_reserved_slots, 0, 0, MAX_CLIENTS, CFGFLAG_SERVER, "The number of slots that are reserved for special players")
MACRO_CONFIG_STR(SvReservedSlotsPass, sv_reserved_slots_pass, 32, "", CFGFLAG_SERVER | CFGFLAG_NONTEEHISTORIC, "The password that is required to use a reserved slot")
MACRO_CONFIG_INT(SvReservedSlotsAuthLevel, sv_reserved_slots_auth_level, 1, 1, 4, CFGFLAG_SERVER, "Minimum rcon auth level needed to use a reserved slot. 4 = rcon auth disabled")
MACRO_CONFIG_INT(SvHit, sv_hit, 1, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAME, "Whether players can hammer/grenade/laser each other or not")
MACRO_CONFIG_INT(SvEndlessDrag, sv_endless_drag, 0, 0, 1, CFGFLAG_SERVER | CFGFLAG_GAME, "Turns endless hooking on/off")
MACRO_CONFIG_INT(SvTestingCommands, sv_test_cmds, 0, 0, 1, CFGFLAG_SERVER, "Turns testing commands aka cheats on/off (setting only works in initial config)")
@ -223,7 +222,8 @@ MACRO_CONFIG_INT(SvInviteFrequency, sv_invite_frequency, 1, 0, 9999, CFGFLAG_SER
MACRO_CONFIG_INT(SvTeleOthersAuthLevel, sv_tele_others_auth_level, 1, 1, 3, CFGFLAG_SERVER, "The auth level you need to tele others")
MACRO_CONFIG_INT(SvEmotionalTees, sv_emotional_tees, 1, -1, 1, CFGFLAG_SERVER, "Whether eye change of tees is enabled with emoticons = 1, not = 0, -1 not at all")
MACRO_CONFIG_INT(SvEmoticonDelay, sv_emoticon_delay, 3, 0, 9999, CFGFLAG_SERVER, "The time in seconds between over-head emoticons")
MACRO_CONFIG_INT(SvEmoticonMsDelay, sv_emoticon_ms_delay, 3000, 20, 999999999, CFGFLAG_SERVER, "The time in ms a player has to wait before allowing the next over-head emoticons")
MACRO_CONFIG_INT(SvGlobalEmoticonMsDelay, sv_global_emoticon_ms_delay, 3000, 20, 999999999, CFGFLAG_SERVER, "The time in ms a player has to wait before allowing the next over-head emoticons that is send to all clients (this config must be higher or equal to sv_emoticon_ms_delay to have an effect)")
MACRO_CONFIG_INT(SvEyeEmoteChangeDelay, sv_eye_emote_change_delay, 1, 0, 9999, CFGFLAG_SERVER, "The time in seconds between eye emoticons change")
MACRO_CONFIG_INT(SvChatDelay, sv_chat_delay, 1, 0, 9999, CFGFLAG_SERVER, "The time in seconds between chat messages")
@ -245,8 +245,6 @@ MACRO_CONFIG_INT(SvFastDownload, sv_fast_download, 1, 0, 1, CFGFLAG_SERVER, "Ena
MACRO_CONFIG_INT(SvShotgunBulletSound, sv_shotgun_bullet_sound, 0, 0, 1, CFGFLAG_SERVER, "Crazy shotgun bullet sound on/off")
MACRO_CONFIG_STR(SvScoreFolder, sv_score_folder, 32, "records", CFGFLAG_SERVER, "Folder to save score files to")
MACRO_CONFIG_STR(SvRegionName, sv_region_name, 5, "UNK", CFGFLAG_SERVER, "Server region. Used for regional bans")
MACRO_CONFIG_STR(SvSqlServerName, sv_sql_servername, 5, "UNK", CFGFLAG_SERVER, "SQL Server name that is inserted into record table")
MACRO_CONFIG_INT(SvSaveGames, sv_savegames, 1, 0, 1, CFGFLAG_SERVER, "Enables savegames (/save and /load)")
@ -367,7 +365,6 @@ MACRO_CONFIG_INT(SvChatPenalty, sv_chat_penalty, 250, 50, 1000, CFGFLAG_SERVER,
MACRO_CONFIG_INT(SvChatThreshold, sv_chat_threshold, 1000, 50, 10000, CFGFLAG_SERVER, "if chats core exceeds this, the player will be muted for sv_spam_mute_duration seconds")
MACRO_CONFIG_INT(SvSpamMuteDuration, sv_spam_mute_duration, 60, 0, 3600, CFGFLAG_SERVER, "how many seconds to mute, if player triggers mute on spam. 0 = off")
MACRO_CONFIG_INT(SvRankCheats, sv_rank_cheats, 0, 0, 1, CFGFLAG_SERVER, "Enable ranks after cheats have been used (file based server only)")
MACRO_CONFIG_INT(SvShutdownWhenEmpty, sv_shutdown_when_empty, 0, 0, 1, CFGFLAG_SERVER, "Shutdown server as soon as no one is on it anymore")
MACRO_CONFIG_INT(SvReloadWhenEmpty, sv_reload_when_empty, 0, 0, 2, CFGFLAG_SERVER, "Reload map when server is empty (1 = reload once, 2 = reload every time server gets empty)")
MACRO_CONFIG_INT(SvKillProtection, sv_kill_protection, 20, 0, 9999, CFGFLAG_SERVER, "0 - Disable, 1-9999 minutes")

View file

@ -55,44 +55,7 @@ ColorHSLA CConsole::CResult::GetColor(unsigned Index, bool Light) const
}
else if(*pStr == '$') // Hex RGB/RGBA
{
ColorRGBA Rgba = ColorRGBA(0, 0, 0, 1);
const int Len = str_length(pStr);
if(Len == 4)
{
const unsigned Num = str_toulong_base(pStr + 1, 16);
Rgba.r = (((Num >> 8) & 0x0F) + ((Num >> 4) & 0xF0)) / 255.0f;
Rgba.g = (((Num >> 4) & 0x0F) + ((Num >> 0) & 0xF0)) / 255.0f;
Rgba.b = (((Num >> 0) & 0x0F) + ((Num << 4) & 0xF0)) / 255.0f;
}
else if(Len == 5)
{
const unsigned Num = str_toulong_base(pStr + 1, 16);
Rgba.r = (((Num >> 12) & 0x0F) + ((Num >> 8) & 0xF0)) / 255.0f;
Rgba.g = (((Num >> 8) & 0x0F) + ((Num >> 4) & 0xF0)) / 255.0f;
Rgba.b = (((Num >> 4) & 0x0F) + ((Num >> 0) & 0xF0)) / 255.0f;
Rgba.a = (((Num >> 0) & 0x0F) + ((Num << 4) & 0xF0)) / 255.0f;
}
else if(Len == 7)
{
const unsigned Num = str_toulong_base(pStr + 1, 16);
Rgba.r = ((Num >> 16) & 0xFF) / 255.0f;
Rgba.g = ((Num >> 8) & 0xFF) / 255.0f;
Rgba.b = ((Num >> 0) & 0xFF) / 255.0f;
}
else if(Len == 9)
{
const unsigned Num = str_toulong_base(pStr + 1, 16);
Rgba.r = ((Num >> 24) & 0xFF) / 255.0f;
Rgba.g = ((Num >> 16) & 0xFF) / 255.0f;
Rgba.b = ((Num >> 8) & 0xFF) / 255.0f;
Rgba.a = ((Num >> 0) & 0xFF) / 255.0f;
}
else
{
return ColorHSLA(0, 0, 0);
}
return color_cast<ColorHSLA>(Rgba);
return color_cast<ColorHSLA>(color_parse<ColorRGBA>(pStr + 1).value_or(ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)));
}
else if(!str_comp_nocase(pStr, "red"))
return ColorHSLA(0.0f / 6.0f, 1, .5f);
@ -732,9 +695,9 @@ void CConsole::ConCommandStatus(IResult *pResult, void *pUser)
if(Used > 0)
{
Used += 2;
str_append(aBuf, ", ", sizeof(aBuf));
str_append(aBuf, ", ");
}
str_append(aBuf, pCommand->m_pName, sizeof(aBuf));
str_append(aBuf, pCommand->m_pName);
Used += Length;
}
else
@ -927,7 +890,7 @@ void CConsole::ConToggle(IConsole::IResult *pResult, void *pUser)
str_format(aBuf, sizeof(aBuf), "%s \"", pResult->GetString(0));
char *pDst = aBuf + str_length(aBuf);
str_escape(&pDst, pStr, aBuf + sizeof(aBuf));
str_append(aBuf, "\"", sizeof(aBuf));
str_append(aBuf, "\"");
pConsole->ExecuteLine(aBuf);
aBuf[0] = 0;
}

View file

@ -525,16 +525,35 @@ CDataFileWriter::CDataFileWriter()
CDataFileWriter::~CDataFileWriter()
{
if(m_File)
{
io_close(m_File);
m_File = 0;
}
free(m_pItemTypes);
m_pItemTypes = nullptr;
for(int i = 0; i < m_NumItems; i++)
free(m_pItems[i].m_pData);
for(int i = 0; i < m_NumDatas; ++i)
free(m_pDatas[i].m_pCompressedData);
free(m_pItems);
m_pItems = nullptr;
free(m_pDatas);
m_pDatas = nullptr;
if(m_pItems)
{
for(int i = 0; i < m_NumItems; i++)
{
free(m_pItems[i].m_pData);
}
free(m_pItems);
m_pItems = nullptr;
}
if(m_pDatas)
{
for(int i = 0; i < m_NumDatas; ++i)
{
free(m_pDatas[i].m_pUncompressedData);
free(m_pDatas[i].m_pCompressedData);
}
free(m_pDatas);
m_pDatas = nullptr;
}
}
bool CDataFileWriter::OpenFile(class IStorage *pStorage, const char *pFilename, int StorageType)
@ -636,21 +655,12 @@ int CDataFileWriter::AddData(int Size, void *pData, int CompressionLevel)
dbg_assert(m_NumDatas < 1024, "too much data");
CDataInfo *pInfo = &m_pDatas[m_NumDatas];
unsigned long s = compressBound(Size);
void *pCompData = malloc(s); // temporary buffer that we use during compression
int Result = compress2((Bytef *)pCompData, &s, (Bytef *)pData, Size, CompressionLevel);
if(Result != Z_OK)
{
dbg_msg("datafile", "compression error %d", Result);
dbg_assert(0, "zlib error");
}
pInfo->m_pUncompressedData = malloc(Size);
mem_copy(pInfo->m_pUncompressedData, pData, Size);
pInfo->m_UncompressedSize = Size;
pInfo->m_CompressedSize = (int)s;
pInfo->m_pCompressedData = malloc(pInfo->m_CompressedSize);
mem_copy(pInfo->m_pCompressedData, pCompData, pInfo->m_CompressedSize);
free(pCompData);
pInfo->m_pCompressedData = nullptr;
pInfo->m_CompressedSize = 0;
pInfo->m_CompressionLevel = CompressionLevel;
m_NumDatas++;
return m_NumDatas - 1;
@ -672,15 +682,31 @@ int CDataFileWriter::AddDataSwapped(int Size, void *pData)
#endif
}
int CDataFileWriter::Finish()
void CDataFileWriter::Finish()
{
if(!m_File)
return 1;
dbg_assert((bool)m_File, "file not open");
// we should now write this file!
if(DEBUG)
dbg_msg("datafile", "writing");
// Compress data. This takes the majority of the time when saving a datafile,
// so it's delayed until the end so it can be off-loaded to another thread.
for(int i = 0; i < m_NumDatas; i++)
{
unsigned long CompressedSize = compressBound(m_pDatas[i].m_UncompressedSize);
m_pDatas[i].m_pCompressedData = malloc(CompressedSize);
const int Result = compress2((Bytef *)m_pDatas[i].m_pCompressedData, &CompressedSize, (Bytef *)m_pDatas[i].m_pUncompressedData, m_pDatas[i].m_UncompressedSize, m_pDatas[i].m_CompressionLevel);
m_pDatas[i].m_CompressedSize = CompressedSize;
free(m_pDatas[i].m_pUncompressedData);
m_pDatas[i].m_pUncompressedData = nullptr;
if(Result != Z_OK)
{
dbg_msg("datafile", "compression error %d", Result);
dbg_assert(false, "zlib error");
}
}
// calculate sizes
int ItemSize = 0;
for(int i = 0; i < m_NumItems; i++)
@ -851,5 +877,4 @@ int CDataFileWriter::Finish()
if(DEBUG)
dbg_msg("datafile", "done");
return 0;
}

View file

@ -58,9 +58,11 @@ class CDataFileWriter
{
struct CDataInfo
{
void *m_pUncompressedData;
int m_UncompressedSize;
int m_CompressedSize;
void *m_pCompressedData;
int m_CompressedSize;
int m_CompressionLevel;
};
struct CItemInfo
@ -103,14 +105,31 @@ class CDataFileWriter
public:
CDataFileWriter();
CDataFileWriter(CDataFileWriter &&Other) :
m_NumItems(Other.m_NumItems),
m_NumDatas(Other.m_NumDatas),
m_NumItemTypes(Other.m_NumItemTypes),
m_NumExtendedItemTypes(Other.m_NumExtendedItemTypes)
{
m_File = Other.m_File;
Other.m_File = 0;
m_pItemTypes = Other.m_pItemTypes;
Other.m_pItemTypes = nullptr;
m_pItems = Other.m_pItems;
Other.m_pItems = nullptr;
m_pDatas = Other.m_pDatas;
Other.m_pDatas = nullptr;
mem_copy(m_aExtendedItemTypes, Other.m_aExtendedItemTypes, sizeof(m_aExtendedItemTypes));
}
~CDataFileWriter();
void Init();
bool OpenFile(class IStorage *pStorage, const char *pFilename, int StorageType = IStorage::TYPE_SAVE);
bool Open(class IStorage *pStorage, const char *pFilename, int StorageType = IStorage::TYPE_SAVE);
int AddData(int Size, void *pData, int CompressionLevel = Z_DEFAULT_COMPRESSION);
int AddDataSwapped(int Size, void *pData);
int AddItem(int Type, int ID, int Size, void *pData);
int Finish();
void Finish();
};
#endif

View file

@ -92,7 +92,7 @@ void CFifo::Init(IConsole *pConsole, char *pFifoFile, int Flag)
}
str_copy(m_aFilename, "\\\\.\\pipe\\");
str_append(m_aFilename, pFifoFile, sizeof(m_aFilename));
str_append(m_aFilename, pFifoFile);
m_Flag = Flag;
const std::wstring WideFilename = windows_utf8_to_wide(m_aFilename);

View file

@ -207,7 +207,7 @@ void CFileCollection::AddEntry(int64_t Timestamp)
}
else
{
char aBuf[512];
char aBuf[IO_MAX_PATH_LENGTH];
char aTimestring[TIMESTAMP_LENGTH];
BuildTimestring(m_aTimestamps[0], aTimestring);
@ -261,7 +261,7 @@ int CFileCollection::RemoveCallback(const char *pFilename, int IsDir, int Storag
if(Timestamp == pThis->m_Remove)
{
char aBuf[512];
char aBuf[IO_MAX_PATH_LENGTH];
str_format(aBuf, sizeof(aBuf), "%s/%s", pThis->m_aPath, pFilename);
pThis->m_pStorage->RemoveFile(aBuf, IStorage::TYPE_SAVE);
pThis->m_Remove = -1;

View file

@ -203,7 +203,8 @@ int CSnapshotDelta::DiffItem(const int *pPast, const int *pCurrent, int *pOut, i
int Needed = 0;
while(Size)
{
*pOut = *pCurrent - *pPast;
// subtraction with wrapping by casting to unsigned
*pOut = (unsigned)*pCurrent - (unsigned)*pPast;
Needed |= *pOut;
pOut++;
pPast++;

View file

@ -68,6 +68,7 @@ public:
CreateFolder("screenshots/auto", TYPE_SAVE);
CreateFolder("screenshots/auto/stats", TYPE_SAVE);
CreateFolder("maps", TYPE_SAVE);
CreateFolder("maps/auto", TYPE_SAVE);
CreateFolder("mapres", TYPE_SAVE);
CreateFolder("downloadedmaps", TYPE_SAVE);
CreateFolder("skins", TYPE_SAVE);
@ -112,7 +113,7 @@ public:
{
char aBuffer[IO_MAX_PATH_LENGTH];
str_copy(aBuffer, pArgv0, Pos + 1);
str_append(aBuffer, "/storage.cfg", sizeof(aBuffer));
str_append(aBuffer, "/storage.cfg");
File = io_open(aBuffer, IOFLAG_READ | IOFLAG_SKIP_BOM);
}
@ -294,7 +295,7 @@ public:
return;
}
#if defined(CONF_PLATFORM_MACOS)
str_append(m_aBinarydir, "/../../../DDNet-Server.app/Contents/MacOS", sizeof(m_aBinarydir));
str_append(m_aBinarydir, "/../../../DDNet-Server.app/Contents/MacOS");
str_format(aBuf, sizeof(aBuf), "%s/" PLAT_SERVER_EXEC, m_aBinarydir);
if(fs_is_file(aBuf))
{

View file

@ -6,6 +6,7 @@
#include "kernel.h"
#include <engine/shared/video.h>
#include <engine/storage.h>
class ISound : public IInterface
{
@ -63,8 +64,8 @@ public:
virtual bool IsSoundEnabled() = 0;
virtual int LoadWV(const char *pFilename) = 0;
virtual int LoadOpus(const char *pFilename) = 0;
virtual int LoadWV(const char *pFilename, int StorageType = IStorage::TYPE_ALL) = 0;
virtual int LoadOpus(const char *pFilename, int StorageType = IStorage::TYPE_ALL) = 0;
virtual int LoadWVFromMem(const void *pData, unsigned DataSize, bool FromEditor = false) = 0;
virtual int LoadOpusFromMem(const void *pData, unsigned DataSize, bool FromEditor = false) = 0;
virtual void UnloadSample(int SampleID) = 0;

View file

@ -70,6 +70,7 @@ MAYBE_UNUSED static const char *FONT_ICON_HEART = "\xEF\x80\x84";
MAYBE_UNUSED static const char *FONT_ICON_STAR = "\xEF\x80\x85";
MAYBE_UNUSED static const char *FONT_ICON_CHECK = "\xEF\x80\x8C";
MAYBE_UNUSED static const char *FONT_ICON_XMARK = "\xEF\x80\x8D";
MAYBE_UNUSED static const char *FONT_ICON_CIRCLE = "\xEF\x84\x91";
MAYBE_UNUSED static const char *FONT_ICON_ARROW_ROTATE_LEFT = "\xEF\x83\xA2";
MAYBE_UNUSED static const char *FONT_ICON_ARROW_ROTATE_RIGHT = "\xEF\x80\x9E";
MAYBE_UNUSED static const char *FONT_ICON_CERTIFICATE = "\xEF\x82\xA3";
@ -101,6 +102,7 @@ MAYBE_UNUSED static const char *FONT_ICON_ARROW_UP_RIGHT_FROM_SQUARE = "\xEF\x82
MAYBE_UNUSED static const char *FONT_ICON_BACKWARD_STEP = "\xEF\x81\x88";
MAYBE_UNUSED static const char *FONT_ICON_FORWARD_STEP = "\xEF\x81\x91";
MAYBE_UNUSED static const char *FONT_ICON_KEYBOARD = "\xE2\x8C\xA8";
MAYBE_UNUSED static const char *FONT_ICON_ELLIPSIS = "\xEF\x85\x81";
MAYBE_UNUSED static const char *FONT_ICON_FOLDER = "\xEF\x81\xBB";
MAYBE_UNUSED static const char *FONT_ICON_FOLDER_TREE = "\xEF\xA0\x82";

View file

@ -6,7 +6,7 @@
#include "animstate.h"
static void AnimSeqEval(CAnimSequence *pSeq, float Time, CAnimKeyframe *pFrame)
static void AnimSeqEval(const CAnimSequence *pSeq, float Time, CAnimKeyframe *pFrame)
{
if(pSeq->m_NumFrames == 0)
{
@ -21,9 +21,8 @@ static void AnimSeqEval(CAnimSequence *pSeq, float Time, CAnimKeyframe *pFrame)
}
else
{
//time = maximum(0.0f, minimum(1.0f, time / duration)); // TODO: use clamp
CAnimKeyframe *pFrame1 = 0;
CAnimKeyframe *pFrame2 = 0;
CAnimKeyframe *pFrame1 = nullptr;
CAnimKeyframe *pFrame2 = nullptr;
float Blend = 0.0f;
// TODO: make this smarter.. binary search
@ -38,7 +37,7 @@ static void AnimSeqEval(CAnimSequence *pSeq, float Time, CAnimKeyframe *pFrame)
}
}
if(pFrame1 && pFrame2)
if(pFrame1 != nullptr && pFrame2 != nullptr)
{
pFrame->m_Time = Time;
pFrame->m_X = mix(pFrame1->m_X, pFrame2->m_X, Blend);
@ -48,7 +47,7 @@ static void AnimSeqEval(CAnimSequence *pSeq, float Time, CAnimKeyframe *pFrame)
}
}
static void AnimAddKeyframe(CAnimKeyframe *pSeq, CAnimKeyframe *pAdded, float Amount)
static void AnimAddKeyframe(CAnimKeyframe *pSeq, const CAnimKeyframe *pAdded, float Amount)
{
// AnimSeqEval fills m_X for any case, clang-analyzer assumes going into the
// final else branch with pSeq->m_NumFrames < 2, which is impossible.
@ -57,12 +56,12 @@ static void AnimAddKeyframe(CAnimKeyframe *pSeq, CAnimKeyframe *pAdded, float Am
pSeq->m_Angle += pAdded->m_Angle * Amount;
}
static void AnimAdd(CAnimState *pState, CAnimState *pAdded, float Amount)
void CAnimState::AnimAdd(CAnimState *pState, const CAnimState *pAdded, float Amount)
{
AnimAddKeyframe(pState->GetBody(), pAdded->GetBody(), Amount);
AnimAddKeyframe(pState->GetBackFoot(), pAdded->GetBackFoot(), Amount);
AnimAddKeyframe(pState->GetFrontFoot(), pAdded->GetFrontFoot(), Amount);
AnimAddKeyframe(pState->GetAttach(), pAdded->GetAttach(), Amount);
AnimAddKeyframe(&pState->m_Body, pAdded->GetBody(), Amount);
AnimAddKeyframe(&pState->m_BackFoot, pAdded->GetBackFoot(), Amount);
AnimAddKeyframe(&pState->m_FrontFoot, pAdded->GetFrontFoot(), Amount);
AnimAddKeyframe(&pState->m_Attach, pAdded->GetAttach(), Amount);
}
void CAnimState::Set(CAnimation *pAnim, float Time)
@ -80,17 +79,17 @@ void CAnimState::Add(CAnimation *pAnim, float Time, float Amount)
AnimAdd(this, &Add, Amount);
}
CAnimState *CAnimState::GetIdle()
const CAnimState *CAnimState::GetIdle()
{
static CAnimState State;
static bool Init = true;
static CAnimState s_State;
static bool s_Init = true;
if(Init)
if(s_Init)
{
State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0);
State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0, 1.0f);
Init = false;
s_State.Set(&g_pData->m_aAnimations[ANIM_BASE], 0.0f);
s_State.Add(&g_pData->m_aAnimations[ANIM_IDLE], 0.0f, 1.0f);
s_Init = false;
}
return &State;
return &s_State;
}

View file

@ -12,15 +12,17 @@ class CAnimState
CAnimKeyframe m_FrontFoot;
CAnimKeyframe m_Attach;
void AnimAdd(CAnimState *pState, const CAnimState *pAdded, float Amount);
public:
CAnimKeyframe *GetBody() { return &m_Body; }
CAnimKeyframe *GetBackFoot() { return &m_BackFoot; }
CAnimKeyframe *GetFrontFoot() { return &m_FrontFoot; }
CAnimKeyframe *GetAttach() { return &m_Attach; }
const CAnimKeyframe *GetBody() const { return &m_Body; }
const CAnimKeyframe *GetBackFoot() const { return &m_BackFoot; }
const CAnimKeyframe *GetFrontFoot() const { return &m_FrontFoot; }
const CAnimKeyframe *GetAttach() const { return &m_Attach; }
void Set(CAnimation *pAnim, float Time);
void Add(CAnimation *pAnim, float Time, float Amount);
static CAnimState *GetIdle();
const static CAnimState *GetIdle();
};
#endif

View file

@ -138,7 +138,8 @@ bool CBinds::OnInput(const IInput::CEvent &Event)
{
if(Event.m_Flags & IInput::FLAG_PRESS)
Console()->ExecuteLineStroked(1, m_aapKeyBindings[Mask][Event.m_Key]);
if(Event.m_Flags & IInput::FLAG_RELEASE)
// Have to check for nullptr again because the previous execute can unbind itself
if(Event.m_Flags & IInput::FLAG_RELEASE && m_aapKeyBindings[Mask][Event.m_Key])
Console()->ExecuteLineStroked(0, m_aapKeyBindings[Mask][Event.m_Key]);
ret = true;
}
@ -148,7 +149,8 @@ bool CBinds::OnInput(const IInput::CEvent &Event)
// When ctrl+shift are pressed (ctrl+shift binds and also the hard-coded ctrl+shift+d, ctrl+shift+g, ctrl+shift+e), ignore other +xxx binds
if(Event.m_Flags & IInput::FLAG_PRESS && Mask != ((1 << MODIFIER_CTRL) | (1 << MODIFIER_SHIFT)) && Mask != ((1 << MODIFIER_GUI) | (1 << MODIFIER_SHIFT)))
Console()->ExecuteLineStroked(1, m_aapKeyBindings[0][Event.m_Key]);
if(Event.m_Flags & IInput::FLAG_RELEASE)
// Have to check for nullptr again because the previous execute can unbind itself
if(Event.m_Flags & IInput::FLAG_RELEASE && m_aapKeyBindings[0][Event.m_Key])
Console()->ExecuteLineStroked(0, m_aapKeyBindings[0][Event.m_Key]);
ret = true;
}
@ -253,7 +255,7 @@ void CBinds::OnConsoleInit()
if(pConfigManager)
pConfigManager->RegisterCallback(ConfigSaveCallback, this);
Console()->Register("bind", "s[key] r[command]", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute the command");
Console()->Register("bind", "s[key] ?r[command]", CFGFLAG_CLIENT, ConBind, this, "Bind key to execute a command or view keybindings");
Console()->Register("binds", "?s[key]", CFGFLAG_CLIENT, ConBinds, this, "Print command executed by this keybinding or all binds");
Console()->Register("unbind", "s[key]", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key");
Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys");
@ -277,6 +279,20 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData)
return;
}
if(pResult->NumArguments() == 1)
{
char aBuf[256];
const char *pKeyName = pResult->GetString(0);
if(!pBinds->m_aapKeyBindings[Modifier][KeyID])
str_format(aBuf, sizeof(aBuf), "%s (%d) is not bound", pKeyName, KeyID);
else
str_format(aBuf, sizeof(aBuf), "%s (%d) = %s", pKeyName, KeyID, pBinds->m_aapKeyBindings[Modifier][KeyID]);
pBinds->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "binds", aBuf, gs_BindPrintColor);
return;
}
pBinds->Bind(KeyID, pResult->GetString(1), false, Modifier);
}
@ -419,8 +435,8 @@ const char *CBinds::GetKeyBindModifiersName(int ModifierCombination)
{
if(ModifierCombination & (1 << k))
{
str_append(aModifier, GetModifierName(k), sizeof(aModifier));
str_append(aModifier, "+", sizeof(aModifier));
str_append(aModifier, GetModifierName(k));
str_append(aModifier, "+");
}
}
return aModifier;

View file

@ -299,17 +299,17 @@ bool CChat::OnInput(const IInput::CEvent &Event)
str_truncate(aBuf, sizeof(aBuf), m_Input.GetString(), m_PlaceholderOffset);
// add the command
str_append(aBuf, "/", sizeof(aBuf));
str_append(aBuf, pCompletionCommand->m_pName, sizeof(aBuf));
str_append(aBuf, "/");
str_append(aBuf, pCompletionCommand->m_pName);
// add separator
const char *pSeparator = pCompletionCommand->m_pParams[0] == '\0' ? "" : " ";
str_append(aBuf, pSeparator, sizeof(aBuf));
str_append(aBuf, pSeparator);
if(*pSeparator)
str_append(aBuf, pSeparator, sizeof(aBuf));
str_append(aBuf, pSeparator);
// add part after the name
str_append(aBuf, m_Input.GetString() + m_PlaceholderOffset + m_PlaceholderLength, sizeof(aBuf));
str_append(aBuf, m_Input.GetString() + m_PlaceholderOffset + m_PlaceholderLength);
m_PlaceholderLength = str_length(pSeparator) + str_length(pCompletionCommand->m_pName) + 1;
m_Input.Set(aBuf);
@ -360,7 +360,7 @@ bool CChat::OnInput(const IInput::CEvent &Event)
str_truncate(aBuf, sizeof(aBuf), m_Input.GetString(), m_PlaceholderOffset);
// add the name
str_append(aBuf, pCompletionString, sizeof(aBuf));
str_append(aBuf, pCompletionString);
// add separator
const char *pSeparator = "";
@ -369,10 +369,10 @@ bool CChat::OnInput(const IInput::CEvent &Event)
else if(m_PlaceholderOffset == 0)
pSeparator = ":";
if(*pSeparator)
str_append(aBuf, pSeparator, sizeof(aBuf));
str_append(aBuf, pSeparator);
// add part after the name
str_append(aBuf, m_Input.GetString() + m_PlaceholderOffset + m_PlaceholderLength, sizeof(aBuf));
str_append(aBuf, m_Input.GetString() + m_PlaceholderOffset + m_PlaceholderLength);
m_PlaceholderLength = str_length(pSeparator) + str_length(pCompletionString);
m_Input.Set(aBuf);
@ -883,7 +883,7 @@ void CChat::OnPrepareLines()
str_format(aName, sizeof(aName), "%d: ", m_aLines[r].m_ClientID);
}
str_append(aName, m_aLines[r].m_aName, sizeof(aName));
str_append(aName, m_aLines[r].m_aName);
char aCount[12];
if(m_aLines[r].m_ClientID < 0)
@ -1179,7 +1179,7 @@ void CChat::OnRender()
float OffsetTeeY = MESSAGE_TEE_SIZE / 2.0f;
float FullHeightMinusTee = RowHeight - MESSAGE_TEE_SIZE;
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &RenderInfo, OffsetToMid);
vec2 TeeRenderPos(x + (RealMsgPaddingX + MESSAGE_TEE_SIZE) / 2.0f, y + OffsetTeeY + FullHeightMinusTee / 2.0f + OffsetToMid.y);

View file

@ -188,10 +188,10 @@ void CGameConsole::CInstance::PossibleArgumentsCompleteCallback(int Index, const
// get command
char aBuf[512];
StrCopyUntilSpace(aBuf, sizeof(aBuf), pInstance->GetString());
str_append(aBuf, " ", sizeof(aBuf));
str_append(aBuf, " ");
// append argument
str_append(aBuf, pStr, sizeof(aBuf));
str_append(aBuf, pStr);
pInstance->m_Input.Set(aBuf);
}
}

View file

@ -143,13 +143,17 @@ const CCountryFlags::CCountryFlag *CCountryFlags::GetByIndex(size_t Index) const
return &m_vCountryFlags[Index % m_vCountryFlags.size()];
}
void CCountryFlags::Render(int CountryCode, const ColorRGBA *pColor, float x, float y, float w, float h)
void CCountryFlags::Render(const CCountryFlag *pFlag, ColorRGBA Color, float x, float y, float w, float h)
{
const CCountryFlag *pFlag = GetByCountryCode(CountryCode);
if(pFlag->m_Texture.IsValid())
{
Graphics()->TextureSet(pFlag->m_Texture);
Graphics()->SetColor(*pColor);
Graphics()->SetColor(Color);
Graphics()->RenderQuadContainerEx(m_FlagsQuadContainerIndex, 0, -1, x, y, w, h);
}
}
void CCountryFlags::Render(int CountryCode, ColorRGBA Color, float x, float y, float w, float h)
{
Render(GetByCountryCode(CountryCode), Color, x, y, w, h);
}

View file

@ -24,7 +24,8 @@ public:
size_t Num() const;
const CCountryFlag *GetByCountryCode(int CountryCode) const;
const CCountryFlag *GetByIndex(size_t Index) const;
void Render(int CountryCode, const ColorRGBA *pColor, float x, float y, float w, float h);
void Render(const CCountryFlag *pFlag, ColorRGBA Color, float x, float y, float w, float h);
void Render(int CountryCode, ColorRGBA Color, float x, float y, float w, float h);
private:
enum

View file

@ -135,7 +135,7 @@ void CEmoticon::OnRender()
Graphics()->DrawCircle(Screen.w / 2, Screen.h / 2, 100.0f, 64);
Graphics()->QuadsEnd();
CTeeRenderInfo *pTeeInfo = &m_pClient->m_aClients[m_pClient->m_aLocalIDs[g_Config.m_ClDummy]].m_RenderInfo;
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[m_pClient->m_aLocalIDs[g_Config.m_ClDummy]].m_RenderInfo;
for(int i = 0; i < NUM_EMOTES; i++)
{
@ -143,12 +143,11 @@ void CEmoticon::OnRender()
if(Angle > pi)
Angle -= 2 * pi;
bool Selected = m_SelectedEyeEmote == i;
const bool Selected = m_SelectedEyeEmote == i;
const vec2 Nudge = direction(Angle) * 70.0f;
pTeeInfo->m_Size = Selected ? 64.0f : 48.0f;
RenderTools()->RenderTee(CAnimState::GetIdle(), pTeeInfo, i, vec2(-1, 0), vec2(Screen.w / 2 + Nudge.x, Screen.h / 2 + Nudge.y));
pTeeInfo->m_Size = 64.0f;
TeeInfo.m_Size = Selected ? 64.0f : 48.0f;
RenderTools()->RenderTee(CAnimState::GetIdle(), &TeeInfo, i, vec2(-1, 0), vec2(Screen.w / 2 + Nudge.x, Screen.h / 2 + Nudge.y));
}
Graphics()->TextureClear();

View file

@ -269,7 +269,7 @@ void CHud::RenderScoreHud()
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[ID].m_RenderInfo;
TeeInfo.m_Size = ScoreSingleBoxHeight;
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(m_Width - ScoreWidthMax - TeeInfo.m_Size / 2 - Split, StartY + (t * 20) + ScoreSingleBoxHeight / 2.0f + OffsetToMid.y);
@ -432,7 +432,7 @@ void CHud::RenderScoreHud()
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[ID].m_RenderInfo;
TeeInfo.m_Size = ScoreSingleBoxHeight;
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(m_Width - ScoreWidthMax - TeeInfo.m_Size / 2 - Split, StartY + (t * 20) + ScoreSingleBoxHeight / 2.0f + OffsetToMid.y);

View file

@ -179,6 +179,11 @@ void CKillMessages::OnMessage(int MsgType, void *pRawMsg)
m_aKillmsgs[m_KillmsgCurrent] = Kill;
}
else
{
TextRender()->DeleteTextContainer(Kill.m_VictimTextContainerIndex);
TextRender()->DeleteTextContainer(Kill.m_KillerTextContainerIndex);
}
Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
}
@ -241,6 +246,11 @@ void CKillMessages::OnMessage(int MsgType, void *pRawMsg)
m_aKillmsgs[m_KillmsgCurrent] = Kill;
}
else
{
TextRender()->DeleteTextContainer(Kill.m_VictimTextContainerIndex);
TextRender()->DeleteTextContainer(Kill.m_KillerTextContainerIndex);
}
Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
}
@ -310,7 +320,7 @@ void CKillMessages::OnRender()
{
CTeeRenderInfo TeeInfo = m_aKillmsgs[r].m_VictimRenderInfo[j];
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(x, y + 46.0f / 2.0f + OffsetToMid.y);
@ -356,7 +366,7 @@ void CKillMessages::OnRender()
{
CTeeRenderInfo TeeInfo = m_aKillmsgs[r].m_KillerRenderInfo;
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(x, y + 46.0f / 2.0f + OffsetToMid.y);
@ -396,6 +406,10 @@ void CKillMessages::RefindSkins()
if(m_aKillmsgs[r].m_VictimID >= 0)
{
for(auto &VictimRenderInfo : m_aKillmsgs[r].m_VictimRenderInfo)
{
VictimRenderInfo = {};
}
const CGameClient::CClientData &Client = GameClient()->m_aClients[m_aKillmsgs[r].m_VictimID];
if(Client.m_aSkinName[0] != '\0')
m_aKillmsgs[r].m_VictimRenderInfo[0] = Client.m_RenderInfo;

View file

@ -51,9 +51,6 @@ ColorRGBA CMenus::ms_ColorTabbarInactiveIngame;
ColorRGBA CMenus::ms_ColorTabbarActiveIngame;
ColorRGBA CMenus::ms_ColorTabbarHoverIngame;
SColorPicker CMenus::ms_ColorPicker;
bool CMenus::ms_ValueSelectorTextMode;
float CMenus::ms_ButtonHeight = 25.0f;
float CMenus::ms_ListheaderHeight = 17.0f;
@ -123,28 +120,14 @@ int CMenus::DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect,
return Active ? UI()->DoButtonLogic(pID, Checked, pRect) : 0;
}
int CMenus::DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName, int Corners, float r, float FontFactor, vec4 ColorHot, vec4 Color, bool CheckForActiveColorPicker)
int CMenus::DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName, int Corners, float r, float FontFactor, vec4 ColorHot, vec4 Color)
{
CUIRect Text = *pRect;
bool MouseInsideColorPicker = false;
if(Checked)
Color = ColorRGBA(0.6f, 0.6f, 0.6f, 0.5f);
Color.a *= UI()->ButtonColorMul(pButtonContainer);
if(CheckForActiveColorPicker)
{
if(ms_ColorPicker.m_Active)
{
CUIRect PickerRect;
PickerRect.x = ms_ColorPicker.m_X;
PickerRect.y = ms_ColorPicker.m_Y;
PickerRect.w = ms_ColorPicker.ms_Width;
PickerRect.h = ms_ColorPicker.ms_Height;
MouseInsideColorPicker = UI()->MouseInside(&PickerRect);
}
}
if(!MouseInsideColorPicker)
Color.a *= UI()->ButtonColorMul(pButtonContainer);
pRect->Draw(Color, Corners, r);
if(pImageName)
@ -171,9 +154,6 @@ int CMenus::DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText,
Text.HMargin((Text.h * FontFactor) / 2.0f, &Text);
UI()->DoLabel(&Text, pText, Text.h * CUI::ms_FontmodHeight, TEXTALIGN_MC);
if(MouseInsideColorPicker)
return 0;
return UI()->DoButtonLogic(pButtonContainer, Checked, pRect);
}
@ -187,7 +167,7 @@ void CMenus::DoButton_KeySelect(const void *pID, const char *pText, const CUIRec
int CMenus::DoButton_MenuTab(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, int Corners, SUIAnimator *pAnimator, const ColorRGBA *pDefaultColor, const ColorRGBA *pActiveColor, const ColorRGBA *pHoverColor, float EdgeRounding)
{
const bool MouseInside = UI()->MouseInside(pRect);
const bool MouseInside = UI()->HotItem() == pButtonContainer;
CUIRect Rect = *pRect;
if(pAnimator != NULL)
@ -375,7 +355,7 @@ void CMenus::DoLaserPreview(const CUIRect *pRect, const ColorHSLA LaserOutlineCo
}
}
ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float LineSize, const float LabelSize, const float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, const ColorRGBA DefaultColor, bool CheckBoxSpacing, int *pCheckBoxValue)
ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float LineSize, const float LabelSize, const float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, const ColorRGBA DefaultColor, bool CheckBoxSpacing, int *pCheckBoxValue, bool Alpha)
{
CUIRect Section, ColorPickerButton, ResetButton, Label;
@ -392,9 +372,9 @@ ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float Lin
if(DoButton_CheckBox(pCheckBoxValue, "", *pCheckBoxValue, &CheckBox))
*pCheckBoxValue ^= 1;
}
Section.VSplitLeft(5.0f, nullptr, &Section);
}
Section.VSplitLeft(5.0f, nullptr, &Section);
Section.VSplitMid(&Label, &Section, Section.h);
Section.VSplitRight(60.0f, &Section, &ResetButton);
Section.VSplitRight(8.0f, &Section, nullptr);
@ -402,17 +382,46 @@ ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float Lin
UI()->DoLabel(&Label, pText, LabelSize, TEXTALIGN_ML);
ColorHSLA PickedColor = RenderHSLColorPicker(&ColorPickerButton, pColorValue, false);
ColorHSLA PickedColor = DoButton_ColorPicker(&ColorPickerButton, pColorValue, Alpha);
ResetButton.HMargin(2.0f, &ResetButton);
if(DoButton_Menu(pResetID, Localize("Reset"), 0, &ResetButton, nullptr, IGraphics::CORNER_ALL, 8.0f, 0.0f, vec4(1, 1, 1, 0.5f), vec4(1, 1, 1, 0.25f), true))
if(DoButton_Menu(pResetID, Localize("Reset"), 0, &ResetButton, nullptr, IGraphics::CORNER_ALL, 8.0f, 0.0f, vec4(1, 1, 1, 0.5f), vec4(1, 1, 1, 0.25f)))
{
*pColorValue = color_cast<ColorHSLA>(DefaultColor).Pack(false);
*pColorValue = color_cast<ColorHSLA>(DefaultColor).Pack(Alpha);
}
return PickedColor;
}
ColorHSLA CMenus::DoButton_ColorPicker(const CUIRect *pRect, unsigned int *pHslaColor, bool Alpha)
{
ColorHSLA HslaColor = ColorHSLA(*pHslaColor, Alpha);
ColorRGBA Outline = ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f);
Outline.a *= UI()->ButtonColorMul(pHslaColor);
CUIRect Rect;
pRect->Margin(3.0f, &Rect);
pRect->Draw(Outline, IGraphics::CORNER_ALL, 4.0f);
Rect.Draw(color_cast<ColorRGBA>(HslaColor), IGraphics::CORNER_ALL, 4.0f);
static CUI::SColorPickerPopupContext s_ColorPickerPopupContext;
if(UI()->DoButtonLogic(pHslaColor, 0, pRect))
{
s_ColorPickerPopupContext.m_pHslaColor = pHslaColor;
s_ColorPickerPopupContext.m_HsvaColor = color_cast<ColorHSVA>(HslaColor);
s_ColorPickerPopupContext.m_Alpha = Alpha;
UI()->ShowPopupColorPicker(UI()->MouseX(), UI()->MouseY(), &s_ColorPickerPopupContext);
}
else if(UI()->IsPopupOpen(&s_ColorPickerPopupContext) && s_ColorPickerPopupContext.m_pHslaColor == pHslaColor)
{
HslaColor = color_cast<ColorHSLA>(s_ColorPickerPopupContext.m_HsvaColor);
}
return HslaColor;
}
int CMenus::DoButton_CheckBoxAutoVMarginAndSet(const void *pID, const char *pText, int *pValue, CUIRect *pRect, float VMargin)
{
CUIRect CheckBoxRect;
@ -438,124 +447,6 @@ int CMenus::DoButton_CheckBox_Number(const void *pID, const char *pText, int Che
return DoButton_CheckBox_Common(pID, pText, aBuf, pRect);
}
int CMenus::DoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, bool UseScroll, int Current, int Min, int Max, int Step, float Scale, bool IsHex, float Round, ColorRGBA *pColor)
{
// logic
static float s_Value;
static CLineInputNumber s_NumberInput;
static void *s_pLastTextpID = pID;
const bool Inside = UI()->MouseInside(pRect);
if(Inside)
UI()->SetHotItem(pID);
const int Base = IsHex ? 16 : 10;
if(UI()->MouseButtonReleased(1) && UI()->HotItem() == pID)
{
s_pLastTextpID = pID;
ms_ValueSelectorTextMode = true;
s_NumberInput.SetInteger(Current, Base);
}
if(UI()->CheckActiveItem(pID))
{
if(!UI()->MouseButton(0))
{
//m_LockMouse = false;
UI()->SetActiveItem(nullptr);
ms_ValueSelectorTextMode = false;
}
}
if(ms_ValueSelectorTextMode && s_pLastTextpID == pID)
{
UI()->DoEditBox(&s_NumberInput, pRect, 10.0f);
UI()->SetActiveItem(&s_NumberInput);
if(Input()->KeyIsPressed(KEY_RETURN) || Input()->KeyIsPressed(KEY_KP_ENTER) ||
((UI()->MouseButtonClicked(1) || UI()->MouseButtonClicked(0)) && !Inside))
{
Current = clamp(s_NumberInput.GetInteger(Base), Min, Max);
//m_LockMouse = false;
UI()->SetActiveItem(nullptr);
ms_ValueSelectorTextMode = false;
}
if(Input()->KeyIsPressed(KEY_ESCAPE))
{
//m_LockMouse = false;
UI()->SetActiveItem(nullptr);
ms_ValueSelectorTextMode = false;
}
}
else
{
if(UI()->CheckActiveItem(pID))
{
if(UseScroll)
{
if(UI()->MouseButton(0))
{
float delta = UI()->MouseDeltaX();
if(Input()->ShiftIsPressed())
s_Value += delta * 0.05f;
else
s_Value += delta;
if(absolute(s_Value) > Scale)
{
int Count = (int)(s_Value / Scale);
s_Value = std::fmod(s_Value, Scale);
Current += Step * Count;
Current = clamp(Current, Min, Max);
// Constrain to discrete steps
if(Count > 0)
Current = Current / Step * Step;
else
Current = std::ceil(Current / (float)Step) * Step;
}
}
}
}
else if(UI()->HotItem() == pID)
{
if(UI()->MouseButtonClicked(0))
{
//m_LockMouse = true;
s_Value = 0;
UI()->SetActiveItem(pID);
}
}
// render
char aBuf[128];
if(pLabel[0] != '\0')
{
if(IsHex)
str_format(aBuf, sizeof(aBuf), "%s #%06X", pLabel, Current);
else
str_format(aBuf, sizeof(aBuf), "%s %d", pLabel, Current);
}
else
{
if(IsHex)
str_format(aBuf, sizeof(aBuf), "#%06X", Current);
else
str_format(aBuf, sizeof(aBuf), "%d", Current);
}
pRect->Draw(*pColor, IGraphics::CORNER_ALL, Round);
UI()->DoLabel(pRect, aBuf, 10.0f, TEXTALIGN_MC);
}
if(!ms_ValueSelectorTextMode)
s_NumberInput.Clear();
return Current;
}
int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key, int ModifierCombination, int *pNewModifierCombination)
{
// process
@ -1070,196 +961,6 @@ bool CMenus::CanDisplayWarning()
return m_Popup == POPUP_NONE;
}
void CMenus::RenderColorPicker()
{
if(UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
{
ms_ColorPicker.m_Active = false;
ms_ValueSelectorTextMode = false;
UI()->SetActiveItem(nullptr);
}
if(!ms_ColorPicker.m_Active)
return;
// First check if we should disable color picker
CUIRect PickerRect;
PickerRect.x = ms_ColorPicker.m_X;
PickerRect.y = ms_ColorPicker.m_Y;
PickerRect.w = ms_ColorPicker.ms_Width;
PickerRect.h = ms_ColorPicker.ms_Height;
if(UI()->MouseButtonClicked(0) && !UI()->MouseInside(&PickerRect) && !UI()->MouseInside(&ms_ColorPicker.m_AttachedRect))
{
ms_ColorPicker.m_Active = false;
ms_ValueSelectorTextMode = false;
UI()->SetActiveItem(nullptr);
return;
}
// Prevent activation of UI elements outside of active color picker
if(UI()->MouseInside(&PickerRect))
UI()->SetHotItem(&ms_ColorPicker);
// Render
ColorRGBA BackgroundColor(0.1f, 0.1f, 0.1f, 1.0f);
PickerRect.Draw(BackgroundColor, 0, 0);
CUIRect ColorsArea, HueArea, ValuesHitbox, BottomArea, HueRect, SatRect, ValueRect, HexRect, AlphaRect;
PickerRect.Margin(3, &ColorsArea);
ColorsArea.HSplitBottom(ms_ColorPicker.ms_Height - 140.0f, &ColorsArea, &ValuesHitbox);
ColorsArea.VSplitRight(20, &ColorsArea, &HueArea);
BottomArea = ValuesHitbox;
BottomArea.HSplitTop(3, 0x0, &BottomArea);
HueArea.VSplitLeft(3, 0x0, &HueArea);
BottomArea.HSplitTop(20, &HueRect, &BottomArea);
BottomArea.HSplitTop(3, 0x0, &BottomArea);
constexpr float ValuePadding = 5.0f;
const float HsvValueWidth = (HueRect.w - ValuePadding * 2) / 3.0f;
const float HexValueWidth = HsvValueWidth * 2 + ValuePadding;
HueRect.VSplitLeft(HsvValueWidth, &HueRect, &SatRect);
SatRect.VSplitLeft(ValuePadding, 0x0, &SatRect);
SatRect.VSplitLeft(HsvValueWidth, &SatRect, &ValueRect);
ValueRect.VSplitLeft(ValuePadding, 0x0, &ValueRect);
BottomArea.HSplitTop(20, &HexRect, &BottomArea);
HexRect.VSplitLeft(HexValueWidth, &HexRect, &AlphaRect);
AlphaRect.VSplitLeft(ValuePadding, 0x0, &AlphaRect);
if(UI()->MouseButtonReleased(1) && !UI()->MouseInside(&ValuesHitbox))
{
ms_ColorPicker.m_Active = false;
ms_ValueSelectorTextMode = false;
UI()->SetActiveItem(nullptr);
return;
}
ColorRGBA BlackColor(0, 0, 0, 0.5f);
HueArea.Draw(BlackColor, 0, 0);
HueArea.Margin(1, &HueArea);
ColorsArea.Draw(BlackColor, 0, 0);
ColorsArea.Margin(1, &ColorsArea);
ColorHSVA PickerColorHSV(ms_ColorPicker.m_HSVColor);
unsigned H = (unsigned)(PickerColorHSV.x * 255.0f);
unsigned S = (unsigned)(PickerColorHSV.y * 255.0f);
unsigned V = (unsigned)(PickerColorHSV.z * 255.0f);
// Color Area
vec4 TL = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 0.0f, 1.0f));
vec4 TR = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 1.0f, 1.0f));
vec4 BL = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 0.0f, 1.0f));
vec4 BR = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 1.0f, 1.0f));
ColorsArea.Draw4(TL, TR, BL, BR, IGraphics::CORNER_NONE, 0.0f);
TL = vec4(0.0f, 0.0f, 0.0f, 0.0f);
TR = vec4(0.0f, 0.0f, 0.0f, 0.0f);
BL = vec4(0.0f, 0.0f, 0.0f, 1.0f);
BR = vec4(0.0f, 0.0f, 0.0f, 1.0f);
ColorsArea.Draw4(TL, TR, BL, BR, IGraphics::CORNER_NONE, 0.0f);
// Hue Area
static const float s_aColorIndices[7][3] = {
{1.0f, 0.0f, 0.0f}, // red
{1.0f, 0.0f, 1.0f}, // magenta
{0.0f, 0.0f, 1.0f}, // blue
{0.0f, 1.0f, 1.0f}, // cyan
{0.0f, 1.0f, 0.0f}, // green
{1.0f, 1.0f, 0.0f}, // yellow
{1.0f, 0.0f, 0.0f} // red
};
float HuePickerOffset = HueArea.h / 6.0f;
CUIRect HuePartialArea = HueArea;
HuePartialArea.h = HuePickerOffset;
for(int j = 0; j < 6; j++)
{
TL = vec4(s_aColorIndices[j][0], s_aColorIndices[j][1], s_aColorIndices[j][2], 1.0f);
BL = vec4(s_aColorIndices[j + 1][0], s_aColorIndices[j + 1][1], s_aColorIndices[j + 1][2], 1.0f);
HuePartialArea.y = HueArea.y + HuePickerOffset * j;
HuePartialArea.Draw4(TL, TL, BL, BL, IGraphics::CORNER_NONE, 0.0f);
}
// Editboxes Area
ColorRGBA EditboxBackground(0, 0, 0, 0.4f);
static int s_aValueSelectorIds[4];
H = DoValueSelector(&s_aValueSelectorIds[0], &HueRect, "H:", true, H, 0, 255, 1, 1, false, 5.0f, &EditboxBackground);
S = DoValueSelector(&s_aValueSelectorIds[1], &SatRect, "S:", true, S, 0, 255, 1, 1, false, 5.0f, &EditboxBackground);
V = DoValueSelector(&s_aValueSelectorIds[2], &ValueRect, "V:", true, V, 0, 255, 1, 1, false, 5.0f, &EditboxBackground);
PickerColorHSV = ColorHSVA(H / 255.0f, S / 255.0f, V / 255.0f);
unsigned int Hex = color_cast<ColorRGBA>(PickerColorHSV).Pack(false);
unsigned int NewHex = DoValueSelector(&s_aValueSelectorIds[3], &HexRect, "HEX:", false, Hex, 0, 0xFFFFFF, 1, 1, true, 5.0f, &EditboxBackground);
if(Hex != NewHex)
PickerColorHSV = color_cast<ColorHSVA>(ColorRGBA(NewHex));
// TODO : ALPHA SUPPORT
UI()->DoLabel(&AlphaRect, "A: 255", 10, TEXTALIGN_MC);
AlphaRect.Draw(ColorRGBA(0, 0, 0, 0.65f), IGraphics::CORNER_ALL, 5.0f);
// Logic
float PickerX, PickerY;
static int s_ColorPickerId = 0;
static int s_HuePickerId = 0;
if(UI()->DoPickerLogic(&s_ColorPickerId, &ColorsArea, &PickerX, &PickerY))
{
PickerColorHSV.y = PickerX / ColorsArea.w;
PickerColorHSV.z = 1.0f - PickerY / ColorsArea.h;
}
if(UI()->DoPickerLogic(&s_HuePickerId, &HueArea, &PickerX, &PickerY))
PickerColorHSV.x = 1.0f - PickerY / HueArea.h;
// Marker Color Area
float MarkerX = ColorsArea.x + ColorsArea.w * PickerColorHSV.y;
float MarkerY = ColorsArea.y + ColorsArea.h * (1.0f - PickerColorHSV.z);
const float MarkerOutlineInd = PickerColorHSV.z > 0.5f ? 0.0f : 1.0f;
ColorRGBA MarkerOutline(MarkerOutlineInd, MarkerOutlineInd, MarkerOutlineInd, 1.0f);
Graphics()->TextureClear();
Graphics()->QuadsBegin();
Graphics()->SetColor(MarkerOutline);
Graphics()->DrawCircle(MarkerX, MarkerY, 4.5f, 32);
Graphics()->SetColor(color_cast<ColorRGBA>(PickerColorHSV));
Graphics()->DrawCircle(MarkerX, MarkerY, 3.5f, 32);
Graphics()->QuadsEnd();
// Marker Hue Area
CUIRect HueMarker;
HueArea.Margin(-2.5f, &HueMarker);
HueMarker.h = 6.5f;
HueMarker.y = (HueArea.y + HueArea.h * (1.0f - PickerColorHSV.x)) - HueMarker.h / 2.0f;
ColorRGBA HueMarkerColor = color_cast<ColorRGBA>(ColorHSVA(PickerColorHSV.x, 1, 1, 1));
const float HueMarkerOutlineColor = PickerColorHSV.x > 0.75f ? 1.0f : 0.0f;
ColorRGBA HueMarkerOutline(HueMarkerOutlineColor, HueMarkerOutlineColor, HueMarkerOutlineColor, 1);
HueMarker.Draw(HueMarkerOutline, IGraphics::CORNER_ALL, 1.2f);
HueMarker.Margin(1.2f, &HueMarker);
HueMarker.Draw(HueMarkerColor, IGraphics::CORNER_ALL, 1.2f);
ms_ColorPicker.m_HSVColor = PickerColorHSV.Pack(false);
*ms_ColorPicker.m_pColor = color_cast<ColorHSLA>(PickerColorHSV).Pack(false);
}
int CMenus::Render()
{
if(Client()->State() == IClient::STATE_DEMOPLAYBACK && m_Popup == POPUP_NONE)
@ -1342,11 +1043,6 @@ int CMenus::Render()
{
Screen.HSplitTop(24.0f, &TabBar, &MainView);
if(Client()->State() == IClient::STATE_OFFLINE && UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
{
m_ShowStart = true;
}
// render news
if(m_MenuPage < PAGE_NEWS || m_MenuPage > PAGE_SETTINGS || (Client()->State() == IClient::STATE_OFFLINE && m_MenuPage >= PAGE_GAME && m_MenuPage <= PAGE_CALLVOTE))
{
@ -1435,7 +1131,7 @@ int CMenus::Render()
const char *pTitle = "";
const char *pExtraText = "";
const char *pButtonText = "";
int ExtraAlign = 0;
bool TopAlign = false;
bool UseIpLabel = false;
ColorRGBA BgColor = ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f);
@ -1513,7 +1209,6 @@ int CMenus::Render()
pExtraText = aBuf;
pButtonText = Localize("Abort");
}
ExtraAlign = 0;
}
else if(m_Popup == POPUP_RENAME_DEMO)
{
@ -1545,7 +1240,7 @@ int CMenus::Render()
Localize("Please enter your nickname below."));
pExtraText = aBuf;
pButtonText = Localize("Ok");
ExtraAlign = -1;
TopAlign = true;
}
else if(m_Popup == POPUP_POINTS)
{
@ -1554,7 +1249,7 @@ int CMenus::Render()
{
str_format(aBuf, sizeof(aBuf), Localize("Your nickname '%s' is already used (%d points). Do you still want to use it?"), Client()->PlayerName(), Client()->m_Points);
pExtraText = aBuf;
ExtraAlign = -1;
TopAlign = true;
}
else if(Client()->m_Points >= 0)
{
@ -1571,7 +1266,7 @@ int CMenus::Render()
pTitle = m_aMessageTopic;
pExtraText = m_aMessageBody;
pButtonText = m_aMessageButton;
ExtraAlign = -1;
TopAlign = true;
}
CUIRect Box, Part;
@ -1607,15 +1302,12 @@ int CMenus::Render()
}
Props.m_MaxWidth = (int)Part.w;
if(ExtraAlign == -1)
if(TopAlign)
UI()->DoLabel(&Part, pExtraText, FontSize, TEXTALIGN_TL, Props);
else if(TextRender()->TextWidth(FontSize, pExtraText, -1, -1.0f) > Part.w)
UI()->DoLabel(&Part, pExtraText, FontSize, TEXTALIGN_ML, Props);
else
{
if(TextRender()->TextWidth(FontSize, pExtraText, -1, -1.0f) > Part.w)
UI()->DoLabel(&Part, pExtraText, FontSize, TEXTALIGN_ML, Props);
else
UI()->DoLabel(&Part, pExtraText, FontSize, TEXTALIGN_MC);
}
UI()->DoLabel(&Part, pExtraText, FontSize, TEXTALIGN_MC);
if(m_Popup == POPUP_MESSAGE || m_Popup == POPUP_CONFIRM)
{
@ -1830,14 +1522,24 @@ int CMenus::Render()
char aBufNew[IO_MAX_PATH_LENGTH];
str_format(aBufNew, sizeof(aBufNew), "%s/%s", m_aCurrentDemoFolder, m_DemoRenameInput.GetString());
if(!str_endswith(aBufNew, ".demo"))
str_append(aBufNew, ".demo", sizeof(aBufNew));
if(Storage()->RenameFile(aBufOld, aBufNew, m_vDemos[m_DemolistSelectedIndex].m_StorageType))
str_append(aBufNew, ".demo");
if(Storage()->FileExists(aBufNew, m_vDemos[m_DemolistSelectedIndex].m_StorageType))
{
PopupMessage(Localize("Error"), Localize("A demo with this name already exists"), Localize("Ok"), POPUP_RENAME_DEMO);
}
else if(Storage()->RenameFile(aBufOld, aBufNew, m_vDemos[m_DemolistSelectedIndex].m_StorageType))
{
str_copy(g_Config.m_UiDemoSelected, m_DemoRenameInput.GetString());
if(str_endswith(g_Config.m_UiDemoSelected, ".demo"))
g_Config.m_UiDemoSelected[str_length(g_Config.m_UiDemoSelected) - str_length(".demo")] = '\0';
DemolistPopulate();
DemolistOnUpdate(false);
}
else
PopupMessage(Localize("Error"), Localize("Unable to rename the demo"), Localize("Ok"));
{
PopupMessage(Localize("Error"), Localize("Unable to rename the demo"), Localize("Ok"), POPUP_RENAME_DEMO);
}
}
}
@ -2068,6 +1770,12 @@ int CMenus::Render()
UI()->RenderPopupMenus();
// Handle this escape hotkey after popup menus
if(!m_ShowStart && Client()->State() == IClient::STATE_OFFLINE && UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
{
m_ShowStart = true;
}
return 0;
}
@ -2100,7 +1808,7 @@ void CMenus::RenderThemeSelection(CUIRect MainView)
static CListBox s_ListBox;
s_ListBox.DoHeader(&MainView, Localize("Theme"), 20.0f);
s_ListBox.DoStart(20.0f, vThemes.size(), 1, 3, SelectedTheme, nullptr, true);
s_ListBox.DoStart(20.0f, vThemes.size(), 1, 3, SelectedTheme);
for(int i = 0; i < (int)vThemes.size(); i++)
{
@ -2159,7 +1867,6 @@ void CMenus::SetActive(bool Active)
{
if(Active != m_MenuActive)
{
ms_ColorPicker.m_Active = false;
UI()->SetHotItem(nullptr);
UI()->SetActiveItem(nullptr);
}
@ -2204,23 +1911,15 @@ bool CMenus::OnCursorMove(float x, float y, IInput::ECursorType CursorType)
return false;
UI()->ConvertMouseMove(&x, &y, CursorType);
m_MousePos.x = clamp(m_MousePos.x + x, 0.f, (float)Graphics()->WindowWidth());
m_MousePos.y = clamp(m_MousePos.y + y, 0.f, (float)Graphics()->WindowHeight());
UI()->OnCursorMove(x, y);
return true;
}
bool CMenus::OnInput(const IInput::CEvent &Event)
{
// special handle esc and enter for popup purposes
if(Event.m_Flags & IInput::FLAG_PRESS && Event.m_Key == KEY_ESCAPE)
{
SetActive(!IsActive());
UI()->OnInput(Event);
return true;
}
if(IsActive())
// Escape key is always handled to activate/deactivate menu
if((Event.m_Flags & IInput::FLAG_PRESS && Event.m_Key == KEY_ESCAPE) || IsActive())
{
UI()->OnInput(Event);
return true;
@ -2301,20 +2000,41 @@ void CMenus::OnRender()
if(!IsActive())
{
if(UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
SetActive(true);
UI()->FinishCheck();
UI()->ClearHotkeys();
return;
}
// update colors
UpdateColors();
UI()->Update();
Render();
RenderTools()->RenderCursor(UI()->MousePos(), 24.0f);
// render debug information
if(g_Config.m_Debug)
UI()->DebugRender();
if(UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
SetActive(false);
UI()->FinishCheck();
UI()->ClearHotkeys();
}
void CMenus::UpdateColors()
{
ms_GuiColor = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_UiColor, true));
ms_ColorTabbarInactiveOutgame = ColorRGBA(0, 0, 0, 0.25f);
ms_ColorTabbarActiveOutgame = ColorRGBA(0, 0, 0, 0.5f);
ms_ColorTabbarHoverOutgame = ColorRGBA(1, 1, 1, 0.25f);
ms_ColorTabbarInactiveOutgame = ColorRGBA(0.0f, 0.0f, 0.0f, 0.25f);
ms_ColorTabbarActiveOutgame = ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f);
ms_ColorTabbarHoverOutgame = ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f);
float ColorIngameScaleI = 0.5f;
float ColorIngameAcaleA = 0.2f;
const float ColorIngameScaleI = 0.5f;
const float ColorIngameAcaleA = 0.2f;
ms_ColorTabbarInactiveIngame = ColorRGBA(
ms_GuiColor.r * ColorIngameScaleI,
@ -2328,32 +2048,7 @@ void CMenus::OnRender()
ms_GuiColor.b * ColorIngameAcaleA,
ms_GuiColor.a);
ms_ColorTabbarHoverIngame = ColorRGBA(1, 1, 1, 0.75f);
// update the ui
const CUIRect *pScreen = UI()->Screen();
float mx = (m_MousePos.x / (float)Graphics()->WindowWidth()) * pScreen->w;
float my = (m_MousePos.y / (float)Graphics()->WindowHeight()) * pScreen->h;
UI()->Update(mx, my, mx * 3.0f, my * 3.0f);
Render();
RenderTools()->RenderCursor(vec2(mx, my), 24.0f);
// render debug information
if(g_Config.m_Debug)
{
UI()->MapScreen();
char aBuf[512];
str_format(aBuf, sizeof(aBuf), "%p %p %p", UI()->HotItem(), UI()->ActiveItem(), UI()->LastActiveItem());
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, 10, 10, 10, TEXTFLAG_RENDER);
TextRender()->TextEx(&Cursor, aBuf, -1);
}
UI()->FinishCheck();
UI()->ClearHotkeys();
ms_ColorTabbarHoverIngame = ColorRGBA(1.0f, 1.0f, 1.0f, 0.75f);
}
void CMenus::RenderBackground()

View file

@ -29,22 +29,6 @@ struct CServerProcess
PROCESS m_Process;
};
struct SColorPicker
{
public:
const float ms_Width = 160.0f;
const float ms_Height = 186.0f;
float m_X;
float m_Y;
bool m_Active;
CUIRect m_AttachedRect;
unsigned int *m_pColor;
unsigned int m_HSVColor;
};
// component to fetch keypresses, override all other input
class CMenusKeyBinder : public CComponent
{
@ -71,15 +55,9 @@ class CMenus : public CComponent
static ColorRGBA ms_ColorTabbarActive;
static ColorRGBA ms_ColorTabbarHover;
static SColorPicker ms_ColorPicker;
static bool ms_ValueSelectorTextMode;
char m_aLocalStringHelper[1024];
int DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
int DoButton_FontIcon(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, int Corners, bool Enabled = true);
int DoButton_FontIcon(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, int Corners = IGraphics::CORNER_ALL, bool Enabled = true);
int DoButton_Toggle(const void *pID, int Checked, const CUIRect *pRect, bool Active);
int DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName = nullptr, int Corners = IGraphics::CORNER_ALL, float r = 5.0f, float FontFactor = 0.0f, vec4 ColorHot = vec4(1.0f, 1.0f, 1.0f, 0.75f), vec4 Color = vec4(1, 1, 1, 0.5f), bool CheckForActiveColorPicker = false);
int DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, const char *pImageName = nullptr, int Corners = IGraphics::CORNER_ALL, float r = 5.0f, float FontFactor = 0.0f, vec4 ColorHot = vec4(1.0f, 1.0f, 1.0f, 0.75f), vec4 Color = vec4(1, 1, 1, 0.5f));
int DoButton_MenuTab(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, int Corners, SUIAnimator *pAnimator = nullptr, const ColorRGBA *pDefaultColor = nullptr, const ColorRGBA *pActiveColor = nullptr, const ColorRGBA *pHoverColor = nullptr, float EdgeRounding = 10);
int DoButton_CheckBox_Common(const void *pID, const char *pText, const char *pBoxText, const CUIRect *pRect);
@ -87,9 +65,9 @@ class CMenus : public CComponent
int DoButton_CheckBoxAutoVMarginAndSet(const void *pID, const char *pText, int *pValue, CUIRect *pRect, float VMargin);
int DoButton_CheckBox_Number(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
ColorHSLA DoLine_ColorPicker(CButtonContainer *pResetID, float LineSize, float LabelSize, float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, ColorRGBA DefaultColor, bool CheckBoxSpacing = true, int *pCheckBoxValue = nullptr);
ColorHSLA DoLine_ColorPicker(CButtonContainer *pResetID, float LineSize, float LabelSize, float BottomMargin, CUIRect *pMainRect, const char *pText, unsigned int *pColorValue, ColorRGBA DefaultColor, bool CheckBoxSpacing = true, int *pCheckBoxValue = nullptr, bool Alpha = false);
ColorHSLA DoButton_ColorPicker(const CUIRect *pRect, unsigned int *pHslaColor, bool Alpha);
void DoLaserPreview(const CUIRect *pRect, ColorHSLA OutlineColor, ColorHSLA InnerColor, const int LaserType);
int DoValueSelector(void *pID, CUIRect *pRect, const char *pLabel, bool UseScroll, int Current, int Min, int Max, int Step, float Scale, bool IsHex, float Round, ColorRGBA *pColor);
int DoButton_GridHeader(const void *pID, const char *pText, int Checked, const CUIRect *pRect);
void DoButton_KeySelect(const void *pID, const char *pText, const CUIRect *pRect);
@ -101,98 +79,10 @@ class CMenus : public CComponent
void DoJoystickAxisPicker(CUIRect View);
void DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, bool Active);
void RenderColorPicker();
void RefreshSkins();
void RandomSkin();
// new gui with gui elements
template<typename T>
int DoButtonMenu(CUIElement &UIElement, const CButtonContainer *pID, T &&GetTextLambda, int Checked, const CUIRect *pRect, bool HintRequiresStringCheck, bool HintCanChangePositionOrSize = false, int Corners = IGraphics::CORNER_ALL, float r = 5.0f, float FontFactor = 0.0f, vec4 ColorHot = vec4(1.0f, 1.0f, 1.0f, 0.75f), vec4 Color = vec4(1, 1, 1, 0.5f))
{
CUIRect Text = *pRect;
Text.HMargin(pRect->h >= 20.0f ? 2.0f : 1.0f, &Text);
Text.HMargin((Text.h * FontFactor) / 2.0f, &Text);
if(!UIElement.AreRectsInit() || HintRequiresStringCheck || HintCanChangePositionOrSize || !UIElement.Rect(0)->m_UITextContainer.Valid())
{
bool NeedsRecalc = !UIElement.AreRectsInit() || !UIElement.Rect(0)->m_UITextContainer.Valid();
if(HintCanChangePositionOrSize)
{
if(UIElement.AreRectsInit())
{
if(UIElement.Rect(0)->m_X != pRect->x || UIElement.Rect(0)->m_Y != pRect->y || UIElement.Rect(0)->m_Width != pRect->w || UIElement.Rect(0)->m_Y != pRect->h)
{
NeedsRecalc = true;
}
}
}
const char *pText = nullptr;
if(HintRequiresStringCheck)
{
if(UIElement.AreRectsInit())
{
pText = GetTextLambda();
if(str_comp(UIElement.Rect(0)->m_Text.c_str(), pText) != 0)
{
NeedsRecalc = true;
}
}
}
if(NeedsRecalc)
{
if(!UIElement.AreRectsInit())
{
UIElement.InitRects(3);
}
UI()->ResetUIElement(UIElement);
vec4 RealColor = Color;
for(int i = 0; i < 3; ++i)
{
Color.a = RealColor.a;
if(i == 0)
Color.a *= UI()->ButtonColorMulActive();
else if(i == 1)
Color.a *= UI()->ButtonColorMulHot();
else if(i == 2)
Color.a *= UI()->ButtonColorMulDefault();
Graphics()->SetColor(Color);
CUIElement::SUIElementRect &NewRect = *UIElement.Rect(i);
NewRect.m_UIRectQuadContainer = Graphics()->CreateRectQuadContainer(pRect->x, pRect->y, pRect->w, pRect->h, r, Corners);
NewRect.m_X = pRect->x;
NewRect.m_Y = pRect->y;
NewRect.m_Width = pRect->w;
NewRect.m_Height = pRect->h;
if(i == 0)
{
if(pText == nullptr)
pText = GetTextLambda();
NewRect.m_Text = pText;
UI()->DoLabel(NewRect, &Text, pText, Text.h * CUI::ms_FontmodHeight, TEXTALIGN_MC);
}
}
Graphics()->SetColor(1, 1, 1, 1);
}
}
// render
size_t Index = 2;
if(UI()->CheckActiveItem(pID))
Index = 0;
else if(UI()->HotItem() == pID)
Index = 1;
Graphics()->TextureClear();
Graphics()->RenderQuadContainer(UIElement.Rect(Index)->m_UIRectQuadContainer, -1);
ColorRGBA ColorText(TextRender()->DefaultTextColor());
ColorRGBA ColorTextOutline(TextRender()->DefaultTextOutlineColor());
if(UIElement.Rect(0)->m_UITextContainer.Valid())
TextRender()->RenderTextContainer(UIElement.Rect(0)->m_UITextContainer, ColorText, ColorTextOutline);
return UI()->DoButtonLogic(pID, Checked, pRect);
}
// menus_settings_assets.cpp
public:
struct SCustomItem
@ -267,7 +157,6 @@ protected:
int m_ActivePage;
bool m_ShowStart;
bool m_MenuActive;
vec2 m_MousePos;
bool m_JoinTutorial;
char m_aNextServer[256];
@ -434,6 +323,7 @@ protected:
CLineInputBuffered<IO_MAX_PATH_LENGTH> m_DemoRenderInput;
int m_DemolistSelectedIndex;
bool m_DemolistSelectedIsDir;
bool m_DemolistSelectedReveal = false;
int m_DemolistStorageType;
int m_Speed = 4;
@ -526,11 +416,13 @@ protected:
void UpdateMusicState();
// found in menus_demo.cpp
vec2 m_DemoControlsPositionOffset = vec2(0.0f, 0.0f);
static bool DemoFilterChat(const void *pData, int Size, void *pUser);
bool FetchHeader(CDemoItem &Item);
void FetchAllHeaders();
void HandleDemoSeeking(float PositionToSeek, float TimeToSeek);
void RenderDemoPlayer(CUIRect MainView);
void RenderDemoPlayerSliceSavePopup(CUIRect MainView);
void RenderDemoList(CUIRect MainView);
void PopupConfirmDeleteDemo();
@ -596,6 +488,7 @@ protected:
void SetNeedSendInfo();
void SetActive(bool Active);
void UpdateColors();
IGraphics::CTextureHandle m_TextureBlob;
@ -734,7 +627,6 @@ public:
std::chrono::nanoseconds m_PopupWarningDuration;
int m_DemoPlayerState;
char m_aDemoPlayerPopupHint[256];
enum
{
@ -769,11 +661,8 @@ private:
// found in menus_settings.cpp
void RenderSettingsDDNet(CUIRect MainView);
void RenderSettingsAppearance(CUIRect MainView);
ColorHSLA RenderHSLColorPicker(const CUIRect *pRect, unsigned int *pColor, bool Alpha);
ColorHSLA RenderHSLScrollbars(CUIRect *pRect, unsigned int *pColor, bool Alpha = false, bool ClampedLight = false);
int RenderDropDown(int &CurDropDownState, CUIRect *pRect, int CurSelection, const void **pIDs, const char **pStr, int PickNum, CButtonContainer *pButtonContainer, float &ScrollVal);
CServerProcess m_ServerProcess;
};
#endif

View file

@ -184,10 +184,9 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
g_Config.m_UiToolboxPage = (g_Config.m_UiToolboxPage + 3 + Direction) % 3;
}
bool ListBoxUsed = !UI()->IsPopupOpen();
static CListBox s_ListBox;
s_ListBox.DoStart(ms_ListheaderHeight, NumServers, 1, 3, -1, &View, false, &ListBoxUsed);
s_ListBox.SetActive(!UI()->IsPopupOpen());
s_ListBox.DoStart(ms_ListheaderHeight, NumServers, 1, 3, -1, &View, false);
int NumPlayers = 0;
static int s_PrevSelectedIndex = -1;
@ -224,7 +223,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
pItem->m_pUIElement = UI()->GetNewUIElement(UIRectCount);
}
const CListboxItem ListItem = s_ListBox.DoNextItem(pItem, str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0, &ListBoxUsed);
const CListboxItem ListItem = s_ListBox.DoNextItem(pItem, str_comp(pItem->m_aAddress, g_Config.m_UiServerAddress) == 0);
if(ListItem.m_Selected)
m_SelectedIndex = i;
@ -451,12 +450,13 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
}
CUIRect SearchInfoAndAddr, ServersAndConnect, Status3;
Status.VSplitRight(250.0f, &SearchInfoAndAddr, &ServersAndConnect);
Status.VSplitRight(125.0f, &SearchInfoAndAddr, &ServersAndConnect);
if(SearchInfoAndAddr.w > 350.0f)
SearchInfoAndAddr.VSplitLeft(350.0f, &SearchInfoAndAddr, NULL);
CUIRect SearchAndInfo, ServerAddr, ConnectButtons;
SearchInfoAndAddr.HSplitTop(40.0f, &SearchAndInfo, &ServerAddr);
ServersAndConnect.HSplitTop(35.0f, &Status3, &ConnectButtons);
ConnectButtons.HSplitTop(5.0f, nullptr, &ConnectButtons);
CUIRect QuickSearch, QuickExclude;
SearchAndInfo.HSplitTop(20.f, &QuickSearch, &QuickExclude);
@ -544,8 +544,6 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
// status box
{
CUIRect ButtonRefresh, ButtonConnect, ButtonArea;
ServerAddr.Margin(2.0f, &ServerAddr);
// address info
@ -555,33 +553,44 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
UI()->DoClearableEditBox(&s_ServerAddressInput, &ServerAddr, 12.0f);
// button area
ButtonArea = ConnectButtons;
ButtonArea.VSplitMid(&ButtonRefresh, &ButtonConnect);
ButtonRefresh.HSplitTop(5.0f, NULL, &ButtonRefresh);
ButtonConnect.HSplitTop(5.0f, NULL, &ButtonConnect);
ButtonConnect.VSplitLeft(5.0f, NULL, &ButtonConnect);
CUIRect ButtonRefresh, ButtonConnect;
ConnectButtons.VSplitMid(&ButtonRefresh, &ButtonConnect, 5.0f);
auto RefreshLabelFunc = [this]() mutable -> const char * {
if(ServerBrowser()->IsRefreshing() || ServerBrowser()->IsGettingServerlist())
str_copy(m_aLocalStringHelper, Localize("Refreshing..."));
else
str_copy(m_aLocalStringHelper, Localize("Refresh"));
return m_aLocalStringHelper;
};
static CButtonContainer s_RefreshButton;
if(DoButtonMenu(m_RefreshButton, &s_RefreshButton, RefreshLabelFunc, 0, &ButtonRefresh, true, false, IGraphics::CORNER_ALL) || Input()->KeyPress(KEY_F5) || (Input()->KeyPress(KEY_R) && Input()->ModifierIsPressed()))
// refresh button
{
RefreshBrowserTab(g_Config.m_UiPage);
char aLabelBuf[32] = {0};
const auto RefreshLabelFunc = [this, aLabelBuf]() mutable {
if(ServerBrowser()->IsRefreshing() || ServerBrowser()->IsGettingServerlist())
str_format(aLabelBuf, sizeof(aLabelBuf), "%s%s", FONT_ICON_ARROW_ROTATE_RIGHT, FONT_ICON_ELLIPSIS);
else
str_copy(aLabelBuf, FONT_ICON_ARROW_ROTATE_RIGHT);
return aLabelBuf;
};
SMenuButtonProperties Props;
Props.m_HintRequiresStringCheck = true;
Props.m_UseIconFont = true;
static CButtonContainer s_RefreshButton;
if(UI()->DoButton_Menu(m_RefreshButton, &s_RefreshButton, RefreshLabelFunc, &ButtonRefresh, Props) || Input()->KeyPress(KEY_F5) || (Input()->KeyPress(KEY_R) && Input()->ModifierIsPressed()))
{
RefreshBrowserTab(g_Config.m_UiPage);
}
}
auto ConnectLabelFunc = []() -> const char * { return Localize("Connect"); };
static CButtonContainer s_ConnectButton;
if(DoButtonMenu(m_ConnectButton, &s_ConnectButton, ConnectLabelFunc, 0, &ButtonConnect, false, false, IGraphics::CORNER_ALL, 5.0f, 0.0f, vec4(0.7f, 1, 0.7f, 0.1f), vec4(0.7f, 1, 0.7f, 0.2f)))
// connect button
{
Connect(g_Config.m_UiServerAddress);
const auto ConnectLabelFunc = []() { return FONT_ICON_RIGHT_TO_BRACKET; };
SMenuButtonProperties Props;
Props.m_UseIconFont = true;
Props.m_Color = ColorRGBA(0.5f, 1.0f, 0.5f, 0.5f);
static CButtonContainer s_ConnectButton;
if(UI()->DoButton_Menu(m_ConnectButton, &s_ConnectButton, ConnectLabelFunc, &ButtonConnect, Props))
{
Connect(g_Config.m_UiServerAddress);
}
}
}
}
@ -606,7 +615,6 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
{
CUIRect ServerFilter = View, FilterHeader;
const float FontSize = 12.0f;
ServerFilter.HSplitBottom(0.0f, &ServerFilter, 0);
// server filter
ServerFilter.HSplitTop(ms_ListheaderHeight, &FilterHeader, &ServerFilter);
@ -675,8 +683,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
float OldWidth = Rect.w;
Rect.w = Rect.h * 2;
Rect.x += (OldWidth - Rect.w) / 2.0f;
ColorRGBA Color(1.0f, 1.0f, 1.0f, UI()->MouseHovered(&Rect) ? 1.0f : g_Config.m_BrFilterCountry ? 0.9f : 0.5f);
m_pClient->m_CountryFlags.Render(g_Config.m_BrFilterCountryIndex, &Color, Rect.x, Rect.y, Rect.w, Rect.h);
m_pClient->m_CountryFlags.Render(g_Config.m_BrFilterCountryIndex, ColorRGBA(1.0f, 1.0f, 1.0f, UI()->MouseHovered(&Rect) ? 1.0f : g_Config.m_BrFilterCountry ? 0.9f : 0.5f), Rect.x, Rect.y, Rect.w, Rect.h);
if(UI()->DoButtonLogic(&g_Config.m_BrFilterCountryIndex, 0, &Rect))
{
@ -753,6 +760,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
if(s_ActivePage == 1)
{
char *pFilterExcludeTypes = Network == IServerBrowser::NETWORK_DDNET ? g_Config.m_BrFilterExcludeTypes : g_Config.m_BrFilterExcludeTypesKoG;
const int FilterExcludeTypesSize = Network == IServerBrowser::NETWORK_DDNET ? sizeof(g_Config.m_BrFilterExcludeTypes) : sizeof(g_Config.m_BrFilterExcludeTypesKoG);
int MaxTypes = ServerBrowser()->NumTypes(Network);
int NumTypes = ServerBrowser()->NumTypes(Network);
int PerLine = 3;
@ -765,7 +773,8 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
CUIRect TypesRect, Left, Right;
static int s_aTypeButtons[64];
static std::vector<unsigned char> s_vTypeButtons;
s_vTypeButtons.resize(MaxTypes);
while(NumTypes > 0)
{
@ -791,17 +800,25 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
Rect.w = TypesWidth;
Rect.h = TypesHeight;
int Click = UI()->DoButtonLogic(&s_aTypeButtons[TypeIndex], 0, &Rect);
int Click = UI()->DoButtonLogic(&s_vTypeButtons[TypeIndex], 0, &Rect);
if(Click == 1 || Click == 2)
{
// left/right click to toggle filter
if(pFilterExcludeTypes[0] == '\0')
{
// when all are active, only activate one
for(int j = 0; j < MaxTypes; ++j)
if(Click == 1)
{
if(j != TypeIndex)
ServerBrowser()->DDNetFilterAdd(pFilterExcludeTypes, ServerBrowser()->GetType(Network, j));
// Left click: when all are active, only activate one
for(int j = 0; j < MaxTypes; ++j)
{
if(j != TypeIndex)
ServerBrowser()->DDNetFilterAdd(pFilterExcludeTypes, FilterExcludeTypesSize, ServerBrowser()->GetType(Network, j));
}
}
else if(Click == 2)
{
// Right click: when all are active, only deactivate one
ServerBrowser()->DDNetFilterAdd(pFilterExcludeTypes, FilterExcludeTypesSize, ServerBrowser()->GetType(Network, TypeIndex));
}
}
else
@ -822,11 +839,11 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
}
else if(Active)
{
ServerBrowser()->DDNetFilterAdd(pFilterExcludeTypes, pName);
ServerBrowser()->DDNetFilterAdd(pFilterExcludeTypes, FilterExcludeTypesSize, pName);
}
else
{
ServerBrowser()->DDNetFilterRem(pFilterExcludeTypes, pName);
ServerBrowser()->DDNetFilterRem(pFilterExcludeTypes, FilterExcludeTypesSize, pName);
}
}
@ -839,7 +856,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
ServerBrowser()->Refresh(ServerBrowser()->GetCurrentType());
}
TextRender()->TextColor(1.0f, 1.0f, 1.0f, Active ? 1.0f : 0.2f);
TextRender()->TextColor(1.0f, 1.0f, 1.0f, (Active ? 0.9f : 0.2f) + (UI()->HotItem() == &s_vTypeButtons[TypeIndex] ? 0.1f : 0.0f));
UI()->DoLabel(&Rect, pName, FontSize, TEXTALIGN_MC);
TextRender()->TextColor(1.0, 1.0, 1.0, 1.0f);
}
@ -848,6 +865,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
else
{
char *pFilterExcludeCountries = Network == IServerBrowser::NETWORK_DDNET ? g_Config.m_BrFilterExcludeCountries : g_Config.m_BrFilterExcludeCountriesKoG;
const int FilterExcludeCountriesSize = Network == IServerBrowser::NETWORK_DDNET ? sizeof(g_Config.m_BrFilterExcludeCountries) : sizeof(g_Config.m_BrFilterExcludeCountriesKoG);
ServerFilter.HSplitTop(15.0f, &ServerFilter, &ServerFilter);
const float FlagWidth = 40.0f;
@ -859,7 +877,8 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
CUIRect FlagsRect;
static int s_aFlagButtons[64];
static std::vector<unsigned char> s_vFlagButtons;
s_vFlagButtons.resize(MaxFlags);
while(NumFlags > 0)
{
@ -886,17 +905,25 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
Rect.w = FlagWidth;
Rect.h = FlagHeight;
int Click = UI()->DoButtonLogic(&s_aFlagButtons[CountryIndex], 0, &Rect);
int Click = UI()->DoButtonLogic(&s_vFlagButtons[CountryIndex], 0, &Rect);
if(Click == 1 || Click == 2)
{
// left/right click to toggle filter
if(pFilterExcludeCountries[0] == '\0')
{
// when all are active, only activate one
for(int j = 0; j < MaxFlags; ++j)
if(Click == 1)
{
if(j != CountryIndex)
ServerBrowser()->DDNetFilterAdd(pFilterExcludeCountries, ServerBrowser()->GetCountryName(Network, j));
// Left click: when all are active, only activate one
for(int j = 0; j < MaxFlags; ++j)
{
if(j != CountryIndex)
ServerBrowser()->DDNetFilterAdd(pFilterExcludeCountries, FilterExcludeCountriesSize, ServerBrowser()->GetCountryName(Network, j));
}
}
else if(Click == 2)
{
// Right click: when all are active, only deactivate one
ServerBrowser()->DDNetFilterAdd(pFilterExcludeCountries, FilterExcludeCountriesSize, ServerBrowser()->GetCountryName(Network, CountryIndex));
}
}
else
@ -917,11 +944,11 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
}
else if(Active)
{
ServerBrowser()->DDNetFilterAdd(pFilterExcludeCountries, pName);
ServerBrowser()->DDNetFilterAdd(pFilterExcludeCountries, FilterExcludeCountriesSize, pName);
}
else
{
ServerBrowser()->DDNetFilterRem(pFilterExcludeCountries, pName);
ServerBrowser()->DDNetFilterRem(pFilterExcludeCountries, FilterExcludeCountriesSize, pName);
}
}
@ -934,8 +961,7 @@ void CMenus::RenderServerbrowserFilters(CUIRect View)
ServerBrowser()->Refresh(ServerBrowser()->GetCurrentType());
}
ColorRGBA Color(1.0f, 1.0f, 1.0f, Active ? 1.0f : 0.2f);
m_pClient->m_CountryFlags.Render(FlagID, &Color, Pos.x, Pos.y, FlagWidth, FlagHeight);
m_pClient->m_CountryFlags.Render(FlagID, ColorRGBA(1.0f, 1.0f, 1.0f, (Active ? 0.9f : 0.2f) + (UI()->HotItem() == &s_vFlagButtons[CountryIndex] ? 0.1f : 0.0f)), Pos.x, Pos.y, FlagWidth, FlagHeight);
}
}
}
@ -972,11 +998,9 @@ CUI::EPopupMenuFunctionResult CMenus::PopupCountrySelection(void *pContext, CUIR
SPopupCountrySelectionContext *pPopupContext = static_cast<SPopupCountrySelectionContext *>(pContext);
CMenus *pMenus = pPopupContext->m_pMenus;
bool ListBoxUsed = Active;
static CListBox s_ListBox;
int OldSelected = -1;
s_ListBox.DoStart(50.0f, pMenus->m_pClient->m_CountryFlags.Num(), 8, 1, OldSelected, &View, false, &ListBoxUsed);
s_ListBox.SetActive(Active);
s_ListBox.DoStart(50.0f, pMenus->m_pClient->m_CountryFlags.Num(), 8, 1, -1, &View, false);
if(pPopupContext->m_New)
{
@ -987,10 +1011,8 @@ CUI::EPopupMenuFunctionResult CMenus::PopupCountrySelection(void *pContext, CUIR
for(size_t i = 0; i < pMenus->m_pClient->m_CountryFlags.Num(); ++i)
{
const CCountryFlags::CCountryFlag *pEntry = pMenus->m_pClient->m_CountryFlags.GetByIndex(i);
if(pEntry->m_CountryCode == pPopupContext->m_Selection)
OldSelected = i;
const CListboxItem Item = s_ListBox.DoNextItem(pEntry, OldSelected >= 0 && (size_t)OldSelected == i, &ListBoxUsed);
const CListboxItem Item = s_ListBox.DoNextItem(pEntry, pEntry->m_CountryCode == pPopupContext->m_Selection);
if(!Item.m_Visible)
continue;
@ -1001,14 +1023,13 @@ CUI::EPopupMenuFunctionResult CMenus::PopupCountrySelection(void *pContext, CUIR
const float OldWidth = FlagRect.w;
FlagRect.w = FlagRect.h * 2.0f;
FlagRect.x += (OldWidth - FlagRect.w) / 2.0f;
ColorRGBA Color(1.0f, 1.0f, 1.0f, 1.0f);
pMenus->m_pClient->m_CountryFlags.Render(pEntry->m_CountryCode, &Color, FlagRect.x, FlagRect.y, FlagRect.w, FlagRect.h);
pMenus->m_pClient->m_CountryFlags.Render(pEntry->m_CountryCode, ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f), FlagRect.x, FlagRect.y, FlagRect.w, FlagRect.h);
pMenus->UI()->DoLabel(&Label, pEntry->m_aCountryCodeString, 10.0f, TEXTALIGN_MC);
}
const int NewSelected = s_ListBox.DoEnd();
pPopupContext->m_Selection = pMenus->m_pClient->m_CountryFlags.GetByIndex(NewSelected)->m_CountryCode;
pPopupContext->m_Selection = NewSelected >= 0 ? pMenus->m_pClient->m_CountryFlags.GetByIndex(NewSelected)->m_CountryCode : -1;
if(s_ListBox.WasItemSelected() || s_ListBox.WasItemActivated())
{
g_Config.m_BrFilterCountry = 1;
@ -1031,7 +1052,6 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
ServerDetails.HSplitTop(110.0f, &ServerDetails, &ServerScoreBoard);
// server details
CTextCursor Cursor;
const float FontSize = 12.0f;
ServerDetails.HSplitTop(ms_ListheaderHeight, &ServerHeader, &ServerDetails);
ServerHeader.Draw(ColorRGBA(1, 1, 1, 0.25f), IGraphics::CORNER_T, 4.0f);
@ -1104,30 +1124,29 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
for(auto &Label : s_aLabels)
{
LeftColumn.HSplitTop(15.0f, &Row, &LeftColumn);
UI()->DoLabel(&Row, Localize(Label), FontSize, TEXTALIGN_ML);
UI()->DoLabel(&Row, Label, FontSize, TEXTALIGN_ML);
}
RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
TextRender()->SetCursor(&Cursor, Row.x, Row.y + (15.f - FontSize) / 2.f, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, pSelectedServer->m_aVersion, -1);
UI()->DoLabel(&Row, pSelectedServer->m_aVersion, FontSize, TEXTALIGN_ML);
RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
TextRender()->SetCursor(&Cursor, Row.x, Row.y + (15.f - FontSize) / 2.f, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, pSelectedServer->m_aGameType, -1);
UI()->DoLabel(&Row, pSelectedServer->m_aGameType, FontSize, TEXTALIGN_ML);
char aTemp[16];
FormatServerbrowserPing(aTemp, sizeof(aTemp), pSelectedServer);
RightColumn.HSplitTop(15.0f, &Row, &RightColumn);
TextRender()->SetCursor(&Cursor, Row.x, Row.y + (15.f - FontSize) / 2.f, FontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Row.w;
TextRender()->TextEx(&Cursor, aTemp, -1);
UI()->DoLabel(&Row, aTemp, FontSize, TEXTALIGN_ML);
}
else
{
UI()->DoLabel(&ServerDetails, Localize("No server selected"), FontSize, TEXTALIGN_MC);
}
// server scoreboard
ServerScoreBoard.HSplitBottom(23.0f, &ServerScoreBoard, 0x0);
CTextCursor Cursor;
if(pSelectedServer)
{
static CListBox s_ListBox;
@ -1198,13 +1217,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
}
}
float ScoreFontSize = 12.0f;
while(ScoreFontSize >= 4.0f && TextRender()->TextWidth(ScoreFontSize, aTemp, -1, -1.0f) > Score.w)
ScoreFontSize--;
TextRender()->SetCursor(&Cursor, Score.x, Score.y + (Score.h - ScoreFontSize) / 2.0f, ScoreFontSize, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Score.w;
TextRender()->TextEx(&Cursor, aTemp, -1);
UI()->DoLabel(&Score, aTemp, FontSize, TEXTALIGN_ML);
// render tee if available
if(HasTeeToRender)
@ -1227,7 +1240,7 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
}
TeeInfo.m_Size = minimum(Skin.w, Skin.h);
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(Skin.x + TeeInfo.m_Size / 2, Skin.y + Skin.h / 2 + OffsetToMid.y);
@ -1268,10 +1281,8 @@ void CMenus::RenderServerbrowserServerDetail(CUIRect View)
TextRender()->TextEx(&Cursor, pClan, -1);
// flag
ColorRGBA FColor(1.0f, 1.0f, 1.0f, 0.5f);
m_pClient->m_CountryFlags.Render(CurrentClient.m_Country, &FColor, Flag.x,
Flag.y + ((Flag.h - Flag.w / 2) / 2),
Flag.w, Flag.w / 2);
m_pClient->m_CountryFlags.Render(CurrentClient.m_Country, ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f),
Flag.x, Flag.y + ((Flag.h - Flag.w / 2) / 2), Flag.w, Flag.w / 2);
}
const int NewSelected = s_ListBox.DoEnd();
@ -1489,7 +1500,7 @@ void CMenus::RenderServerbrowserFriends(CUIRect View)
}
TeeInfo.m_Size = minimum(Skin.w, Skin.h);
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(Skin.x + Skin.w / 2.0f, Skin.y + Skin.h * 0.55f + OffsetToMid.y);
@ -1696,7 +1707,7 @@ void CMenus::RenderServerbrowser(CUIRect MainView)
ToolboxPage = 0;
static CButtonContainer s_InfoTab;
if(DoButton_MenuTab(&s_InfoTab, Localize("Info"), ToolboxPage == 1, &TabButton1, 0, NULL, NULL, NULL, NULL, 4.0f))
if(DoButton_MenuTab(&s_InfoTab, Localize("Info"), ToolboxPage == 1, &TabButton1, IGraphics::CORNER_NONE, NULL, NULL, NULL, NULL, 4.0f))
ToolboxPage = 1;
static CButtonContainer s_FriendsTab;

View file

@ -28,13 +28,6 @@
using namespace FontIcons;
using namespace std::chrono_literals;
int CMenus::DoButton_DemoPlayer(const void *pID, const char *pText, int Checked, const CUIRect *pRect)
{
pRect->Draw(ColorRGBA(1, 1, 1, (Checked ? 0.10f : 0.5f) * UI()->ButtonColorMul(pID)), IGraphics::CORNER_ALL, 5.0f);
UI()->DoLabel(pRect, pText, 14.0f, TEXTALIGN_MC);
return UI()->DoButtonLogic(pID, Checked, pRect);
}
int CMenus::DoButton_FontIcon(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, int Corners, bool Enabled)
{
pRect->Draw(ColorRGBA(1.0f, 1.0f, 1.0f, (Checked ? 0.10f : 0.5f) * UI()->ButtonColorMul(pButtonContainer)), Corners, 5.0f);
@ -96,6 +89,8 @@ void CMenus::HandleDemoSeeking(float PositionToSeek, float TimeToSeek)
m_pClient->m_SuppressEvents = false;
m_pClient->m_MapLayersBackGround.EnvelopeUpdate();
m_pClient->m_MapLayersForeGround.EnvelopeUpdate();
if(!DemoPlayer()->BaseInfo()->m_Paused && PositionToSeek == 1.0f)
DemoPlayer()->Pause();
}
}
@ -112,107 +107,8 @@ void CMenus::DemoSeekTick(IDemoPlayer::ETickOffset TickOffset)
void CMenus::RenderDemoPlayer(CUIRect MainView)
{
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
const float SeekBarHeight = 15.0f;
const float ButtonbarHeight = 20.0f;
const float NameBarHeight = 20.0f;
const float Margins = 5.0f;
static int64_t s_LastSpeedChange = 0;
// render popups
if(m_DemoPlayerState == DEMOPLAYER_SLICE_SAVE)
{
CUIRect Screen = *UI()->Screen();
CUIRect Box, Part, Part2;
Box = Screen;
Box.Margin(150.0f, &Box);
// render the box
Box.Draw(ColorRGBA(0, 0, 0, 0.5f), IGraphics::CORNER_ALL, 15.0f);
Box.HSplitTop(20.f, 0, &Box);
Box.HSplitTop(24.f, &Part, &Box);
UI()->DoLabel(&Part, Localize("Select a name"), 24.f, TEXTALIGN_MC);
Box.HSplitTop(20.f, 0, &Box);
Box.HSplitTop(20.f, &Part, &Box);
Part.VMargin(20.f, &Part);
UI()->DoLabel(&Part, m_aDemoPlayerPopupHint, 20.f, TEXTALIGN_MC);
Box.HSplitTop(20.f, 0, &Box);
CUIRect Label, TextBox, Ok, Abort;
Box.HSplitBottom(20.f, &Box, 0);
Box.HSplitBottom(24.f, &Box, &Part);
Part.VMargin(80.0f, &Part);
Part.VSplitMid(&Abort, &Ok);
Ok.VMargin(20.0f, &Ok);
Abort.VMargin(20.0f, &Abort);
static int s_RemoveChat = 0;
static CButtonContainer s_ButtonAbort;
if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &Abort) || UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
m_DemoPlayerState = DEMOPLAYER_NONE;
static CButtonContainer s_ButtonOk;
if(DoButton_Menu(&s_ButtonOk, Localize("Ok"), 0, &Ok) || UI()->ConsumeHotkey(CUI::HOTKEY_ENTER))
{
char aDemoName[IO_MAX_PATH_LENGTH];
DemoPlayer()->GetDemoName(aDemoName, sizeof(aDemoName));
str_append(aDemoName, ".demo", sizeof(aDemoName));
if(!str_endswith(m_DemoSliceInput.GetString(), ".demo"))
m_DemoSliceInput.Append(".demo");
if(str_comp(aDemoName, m_DemoSliceInput.GetString()) == 0)
str_copy(m_aDemoPlayerPopupHint, Localize("Please use a different name"));
else
{
char aPath[IO_MAX_PATH_LENGTH];
str_format(aPath, sizeof(aPath), "%s/%s", m_aCurrentDemoFolder, m_DemoSliceInput.GetString());
IOHANDLE DemoFile = Storage()->OpenFile(aPath, IOFLAG_READ, IStorage::TYPE_SAVE);
const char *pStr = Localize("File already exists, do you want to overwrite it?");
if(DemoFile && str_comp(m_aDemoPlayerPopupHint, pStr) != 0)
{
io_close(DemoFile);
str_copy(m_aDemoPlayerPopupHint, pStr);
}
else
{
if(DemoFile)
io_close(DemoFile);
m_DemoPlayerState = DEMOPLAYER_NONE;
Client()->DemoSlice(aPath, CMenus::DemoFilterChat, &s_RemoveChat);
DemolistPopulate();
DemolistOnUpdate(false);
}
}
}
Box.HSplitTop(24.f, &Part, &Box);
Box.HSplitTop(10.f, 0, &Box);
Box.HSplitTop(24.f, &Part2, &Box);
Part2.VSplitLeft(60.0f, 0, &Label);
if(DoButton_CheckBox(&s_RemoveChat, Localize("Remove chat"), s_RemoveChat, &Label))
{
s_RemoveChat ^= 1;
}
Part.VSplitLeft(60.0f, 0, &Label);
Label.VSplitLeft(120.0f, 0, &TextBox);
TextBox.VSplitLeft(20.0f, 0, &TextBox);
TextBox.VSplitRight(60.0f, &TextBox, 0);
UI()->DoLabel(&Label, Localize("New name:"), 18.0f, TEXTALIGN_ML);
if(UI()->DoEditBox(&m_DemoSliceInput, &TextBox, 12.0f))
{
m_aDemoPlayerPopupHint[0] = '\0';
}
}
// handle keyboard shortcuts independent of active menu
float PositionToSeek = -1.0f;
float TimeToSeek = 0.0f;
@ -294,7 +190,11 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
}
}
float TotalHeight = SeekBarHeight + ButtonbarHeight + NameBarHeight + Margins * 3;
const float SeekBarHeight = 15.0f;
const float ButtonbarHeight = 20.0f;
const float NameBarHeight = 20.0f;
const float Margins = 5.0f;
const float TotalHeight = SeekBarHeight + ButtonbarHeight + NameBarHeight + Margins * 3;
// render speed info
if(g_Config.m_ClDemoShowSpeed && time_get() - s_LastSpeedChange < time_freq() * 1)
@ -321,20 +221,70 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
return;
}
MainView.HSplitBottom(TotalHeight, 0, &MainView);
MainView.VSplitLeft(50.0f, 0, &MainView);
MainView.VSplitLeft(600.0f, &MainView, 0);
MainView.Draw(ms_ColorTabbarActive, IGraphics::CORNER_T, 10.0f);
MainView.Margin(5.0f, &MainView);
CUIRect DemoControls;
MainView.HSplitBottom(TotalHeight, nullptr, &DemoControls);
DemoControls.VSplitLeft(50.0f, nullptr, &DemoControls);
DemoControls.VSplitLeft(600.0f, &DemoControls, nullptr);
const CUIRect DemoControlsOriginal = DemoControls;
DemoControls.x += m_DemoControlsPositionOffset.x;
DemoControls.y += m_DemoControlsPositionOffset.y;
int Corners = IGraphics::CORNER_NONE;
if(DemoControls.x > 0.0f && DemoControls.y > 0.0f)
Corners |= IGraphics::CORNER_TL;
if(DemoControls.x < MainView.w - DemoControls.w && DemoControls.y > 0.0f)
Corners |= IGraphics::CORNER_TR;
if(DemoControls.x > 0.0f && DemoControls.y < MainView.h - DemoControls.h)
Corners |= IGraphics::CORNER_BL;
if(DemoControls.x < MainView.w - DemoControls.w && DemoControls.y < MainView.h - DemoControls.h)
Corners |= IGraphics::CORNER_BR;
DemoControls.Draw(ms_ColorTabbarActive, Corners, 10.0f);
const CUIRect DemoControlsDragRect = DemoControls;
CUIRect SeekBar, ButtonBar, NameBar, SpeedBar;
MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
ButtonBar.HSplitTop(Margins, 0, &ButtonBar);
DemoControls.Margin(5.0f, &DemoControls);
DemoControls.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
ButtonBar.HSplitTop(Margins, nullptr, &ButtonBar);
ButtonBar.HSplitBottom(NameBarHeight, &ButtonBar, &NameBar);
NameBar.HSplitTop(4.0f, 0, &NameBar);
NameBar.HSplitTop(4.0f, nullptr, &NameBar);
// handle draggable demo controls
{
enum EDragOperation
{
OP_NONE,
OP_DRAGGING,
OP_CLICKED
};
static EDragOperation s_Operation = OP_NONE;
static vec2 s_InitialMouse = vec2(0.0f, 0.0f);
bool Clicked;
bool Abrupted;
if(int Result = UI()->DoDraggableButtonLogic(&s_Operation, 8, &DemoControlsDragRect, &Clicked, &Abrupted))
{
if(s_Operation == OP_NONE && Result == 1)
{
s_InitialMouse = UI()->MousePos();
s_Operation = OP_CLICKED;
}
if(Clicked || Abrupted)
s_Operation = OP_NONE;
if(s_Operation == OP_CLICKED && length(UI()->MousePos() - s_InitialMouse) > 5.0f)
{
s_Operation = OP_DRAGGING;
s_InitialMouse -= m_DemoControlsPositionOffset;
}
if(s_Operation == OP_DRAGGING)
{
m_DemoControlsPositionOffset = UI()->MousePos() - s_InitialMouse;
m_DemoControlsPositionOffset.x = clamp(m_DemoControlsPositionOffset.x, -DemoControlsOriginal.x, MainView.w - DemoControlsDragRect.w - DemoControlsOriginal.x);
m_DemoControlsPositionOffset.y = clamp(m_DemoControlsPositionOffset.y, -DemoControlsOriginal.y, MainView.h - DemoControlsDragRect.h - DemoControlsOriginal.y);
}
}
}
// do seekbar
{
@ -427,14 +377,14 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
if(Input()->ShiftIsPressed())
{
AmountSeek = s_PrevAmount + (AmountSeek - s_PrevAmount) * 0.05f;
if(AmountSeek > 0.0f && AmountSeek < 1.0f && absolute(s_PrevAmount - AmountSeek) >= 0.0001f)
if(AmountSeek >= 0.0f && AmountSeek <= 1.0f && absolute(s_PrevAmount - AmountSeek) >= 0.0001f)
{
PositionToSeek = AmountSeek;
}
}
else
{
if(AmountSeek > 0.0f && AmountSeek < 1.0f && absolute(s_PrevAmount - AmountSeek) >= 0.001f)
if(AmountSeek >= 0.0f && AmountSeek <= 1.0f && absolute(s_PrevAmount - AmountSeek) >= 0.001f)
{
s_PrevAmount = AmountSeek;
PositionToSeek = AmountSeek;
@ -483,7 +433,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
GameClient()->m_Tooltips.DoToolTip(&s_PlayPauseButton, &Button, pInfo->m_Paused ? Localize("Play the current demo") : Localize("Pause the current demo"));
// stop button
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_ResetButton;
if(DoButton_FontIcon(&s_ResetButton, FONT_ICON_STOP, false, &Button, IGraphics::CORNER_ALL))
@ -494,7 +444,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
GameClient()->m_Tooltips.DoToolTip(&s_ResetButton, &Button, Localize("Stop the current demo"));
// one tick back
ButtonBar.VSplitLeft(Margins + 10.0f, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins + 10.0f, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneTickBackButton;
if(DoButton_FontIcon(&s_OneTickBackButton, FONT_ICON_CHEVRON_LEFT, 0, &Button, IGraphics::CORNER_ALL))
@ -502,7 +452,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
GameClient()->m_Tooltips.DoToolTip(&s_OneTickBackButton, &Button, Localize("Go back one tick"));
// one tick forward
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneTickForwardButton;
if(DoButton_FontIcon(&s_OneTickForwardButton, FONT_ICON_CHEVRON_RIGHT, 0, &Button, IGraphics::CORNER_ALL))
@ -534,28 +484,38 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
// slice begin button
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_SliceBeginButton;
if(DoButton_FontIcon(&s_SliceBeginButton, FONT_ICON_RIGHT_FROM_BRACKET, 0, &Button, IGraphics::CORNER_ALL))
const int SliceBeginButtonResult = DoButton_FontIcon(&s_SliceBeginButton, FONT_ICON_RIGHT_FROM_BRACKET, 0, &Button, IGraphics::CORNER_ALL);
if(SliceBeginButtonResult == 1)
{
Client()->DemoSliceBegin();
if(CurrentTick > (g_Config.m_ClDemoSliceEnd - pInfo->m_FirstTick))
g_Config.m_ClDemoSliceEnd = -1;
}
GameClient()->m_Tooltips.DoToolTip(&s_SliceBeginButton, &Button, Localize("Mark the beginning of a cut"));
else if(SliceBeginButtonResult == 2)
{
g_Config.m_ClDemoSliceBegin = -1;
}
GameClient()->m_Tooltips.DoToolTip(&s_SliceBeginButton, &Button, Localize("Mark the beginning of a cut (right click to reset)"));
// slice end button
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_SliceEndButton;
if(DoButton_FontIcon(&s_SliceEndButton, FONT_ICON_RIGHT_TO_BRACKET, 0, &Button, IGraphics::CORNER_ALL))
const int SliceEndButtonResult = DoButton_FontIcon(&s_SliceEndButton, FONT_ICON_RIGHT_TO_BRACKET, 0, &Button, IGraphics::CORNER_ALL);
if(SliceEndButtonResult == 1)
{
Client()->DemoSliceEnd();
if(CurrentTick < (g_Config.m_ClDemoSliceBegin - pInfo->m_FirstTick))
g_Config.m_ClDemoSliceBegin = -1;
}
GameClient()->m_Tooltips.DoToolTip(&s_SliceEndButton, &Button, Localize("Mark the end of a cut"));
else if(SliceEndButtonResult == 2)
{
g_Config.m_ClDemoSliceEnd = -1;
}
GameClient()->m_Tooltips.DoToolTip(&s_SliceEndButton, &Button, Localize("Mark the end of a cut (right click to reset)"));
// slice save button
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_SliceSaveButton;
if(DoButton_FontIcon(&s_SliceSaveButton, FONT_ICON_ARROW_UP_RIGHT_FROM_SQUARE, 0, &Button, IGraphics::CORNER_ALL))
@ -565,7 +525,6 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
m_DemoSliceInput.Set(aDemoName);
m_DemoSliceInput.Append(".demo");
UI()->SetActiveItem(&m_DemoSliceInput);
m_aDemoPlayerPopupHint[0] = '\0';
m_DemoPlayerState = DEMOPLAYER_SLICE_SAVE;
}
GameClient()->m_Tooltips.DoToolTip(&s_SliceSaveButton, &Button, Localize("Export cut as a separate demo"));
@ -574,10 +533,12 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
const int Threshold = 10;
// one marker back
ButtonBar.VSplitLeft(Margins + 20.0f, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins + 20.0f, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneMarkerBackButton;
if(DoButton_FontIcon(&s_OneMarkerBackButton, FONT_ICON_BACKWARD_STEP, 0, &Button, IGraphics::CORNER_ALL))
{
PositionToSeek = 0.0f;
for(int i = pInfo->m_NumTimelineMarkers - 1; i >= 0; i--)
{
if((pInfo->m_aTimelineMarkers[i] - pInfo->m_FirstTick) < CurrentTick && absolute(((pInfo->m_aTimelineMarkers[i] - pInfo->m_FirstTick) - CurrentTick)) > Threshold)
@ -585,15 +546,17 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
PositionToSeek = (float)(pInfo->m_aTimelineMarkers[i] - pInfo->m_FirstTick) / TotalTicks;
break;
}
PositionToSeek = 0.0f;
}
}
GameClient()->m_Tooltips.DoToolTip(&s_OneMarkerBackButton, &Button, Localize("Go back one marker"));
// one marker forward
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar);
ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneMarkerForwardButton;
if(DoButton_FontIcon(&s_OneMarkerForwardButton, FONT_ICON_FORWARD_STEP, 0, &Button, IGraphics::CORNER_ALL))
{
PositionToSeek = 1.0f;
for(int i = 0; i < pInfo->m_NumTimelineMarkers; i++)
{
if((pInfo->m_aTimelineMarkers[i] - pInfo->m_FirstTick) > CurrentTick && absolute(((pInfo->m_aTimelineMarkers[i] - pInfo->m_FirstTick) - CurrentTick)) > Threshold)
@ -601,21 +564,22 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
PositionToSeek = (float)(pInfo->m_aTimelineMarkers[i] - pInfo->m_FirstTick) / TotalTicks;
break;
}
PositionToSeek = 1.0f;
}
}
GameClient()->m_Tooltips.DoToolTip(&s_OneMarkerForwardButton, &Button, Localize("Go forward one marker"));
// close button
ButtonBar.VSplitRight(ButtonbarHeight * 3, &ButtonBar, &Button);
static int s_ExitButton = 0;
if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), 0, &Button) || (Input()->KeyPress(KEY_C) && m_pClient->m_GameConsole.IsClosed() && m_DemoPlayerState == DEMOPLAYER_NONE))
ButtonBar.VSplitRight(ButtonbarHeight, &ButtonBar, &Button);
static CButtonContainer s_ExitButton;
if(DoButton_FontIcon(&s_ExitButton, FONT_ICON_XMARK, 0, &Button) || (Input()->KeyPress(KEY_C) && m_pClient->m_GameConsole.IsClosed() && m_DemoPlayerState == DEMOPLAYER_NONE))
{
Client()->Disconnect();
DemolistOnUpdate(false);
}
GameClient()->m_Tooltips.DoToolTip(&s_ExitButton, &Button, Localize("Close the demo player"));
// toggle keyboard shortcuts button
ButtonBar.VSplitRight(Margins, &ButtonBar, 0);
ButtonBar.VSplitRight(Margins, &ButtonBar, nullptr);
ButtonBar.VSplitRight(ButtonbarHeight, &ButtonBar, &Button);
static CButtonContainer s_KeyboardShortcutsButton;
if(DoButton_FontIcon(&s_KeyboardShortcutsButton, FONT_ICON_KEYBOARD, 0, &Button, IGraphics::CORNER_ALL, g_Config.m_ClDemoKeyboardShortcuts != 0))
@ -629,10 +593,7 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
DemoPlayer()->GetDemoName(aDemoName, sizeof(aDemoName));
char aBuf[IO_MAX_PATH_LENGTH + 128];
str_format(aBuf, sizeof(aBuf), Localize("Demofile: %s"), aDemoName);
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, NameBar.x, NameBar.y + (NameBar.h - (Button.h * 0.5f)) / 2.f, Button.h * 0.5f, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = MainView.w;
TextRender()->TextEx(&Cursor, aBuf, -1);
UI()->DoLabel(&NameBar, aBuf, Button.h * 0.5f, TEXTALIGN_ML);
if(IncreaseDemoSpeed)
{
@ -646,6 +607,135 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
}
HandleDemoSeeking(PositionToSeek, TimeToSeek);
// render popups
if(m_DemoPlayerState != DEMOPLAYER_NONE)
{
// prevent element under the active popup from being activated
UI()->SetHotItem(nullptr);
}
if(m_DemoPlayerState == DEMOPLAYER_SLICE_SAVE)
{
RenderDemoPlayerSliceSavePopup(MainView);
}
UI()->RenderPopupMenus();
}
void CMenus::RenderDemoPlayerSliceSavePopup(CUIRect MainView)
{
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo();
CUIRect Box;
MainView.Margin(150.0f, &Box);
// background
Box.Draw(ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f), IGraphics::CORNER_ALL, 15.0f);
Box.Margin(24.0f, &Box);
// title
CUIRect Title;
Box.HSplitTop(24.0f, &Title, &Box);
Box.HSplitTop(20.0f, nullptr, &Box);
UI()->DoLabel(&Title, Localize("Export demo cut"), 24.0f, TEXTALIGN_MC);
// slice times
CUIRect SliceTimesBar, SliceInterval, SliceLength;
Box.HSplitTop(24.0f, &SliceTimesBar, &Box);
SliceTimesBar.VSplitMid(&SliceInterval, &SliceLength, 40.0f);
Box.HSplitTop(20.0f, nullptr, &Box);
const int64_t RealSliceBegin = g_Config.m_ClDemoSliceBegin == -1 ? 0 : (g_Config.m_ClDemoSliceBegin - pInfo->m_FirstTick);
const int64_t RealSliceEnd = (g_Config.m_ClDemoSliceEnd == -1 ? pInfo->m_LastTick : g_Config.m_ClDemoSliceEnd) - pInfo->m_FirstTick;
char aSliceBegin[32];
str_time(RealSliceBegin / SERVER_TICK_SPEED * 100, TIME_HOURS, aSliceBegin, sizeof(aSliceBegin));
char aSliceEnd[32];
str_time(RealSliceEnd / SERVER_TICK_SPEED * 100, TIME_HOURS, aSliceEnd, sizeof(aSliceEnd));
char aSliceLength[32];
str_time((RealSliceEnd - RealSliceBegin) / SERVER_TICK_SPEED * 100, TIME_HOURS, aSliceLength, sizeof(aSliceLength));
char aBuf[256];
str_format(aBuf, sizeof(aBuf), "%s: %s %s", Localize("Cut interval"), aSliceBegin, aSliceEnd);
UI()->DoLabel(&SliceInterval, aBuf, 18.0f, TEXTALIGN_ML);
str_format(aBuf, sizeof(aBuf), "%s: %s", Localize("Cut length"), aSliceLength);
UI()->DoLabel(&SliceLength, aBuf, 18.0f, TEXTALIGN_ML);
// file name
CUIRect NameLabel, NameBox;
Box.HSplitTop(24.0f, &NameLabel, &Box);
Box.HSplitTop(20.0f, nullptr, &Box);
NameLabel.VSplitLeft(150.0f, &NameLabel, &NameBox);
NameBox.VSplitLeft(20.0f, nullptr, &NameBox);
UI()->DoLabel(&NameLabel, Localize("New name:"), 18.0f, TEXTALIGN_ML);
UI()->DoEditBox(&m_DemoSliceInput, &NameBox, 12.0f);
// remove chat checkbox
static int s_RemoveChat = 0;
CUIRect RemoveChatCheckBox;
Box.HSplitTop(24.0f, &RemoveChatCheckBox, &Box);
Box.HSplitTop(20.0f, nullptr, &Box);
if(DoButton_CheckBox(&s_RemoveChat, Localize("Remove chat"), s_RemoveChat, &RemoveChatCheckBox))
{
s_RemoveChat ^= 1;
}
// buttons
CUIRect ButtonBar, AbortButton, OkButton;
Box.HSplitBottom(24.0f, &Box, &ButtonBar);
ButtonBar.VSplitMid(&AbortButton, &OkButton, 40.0f);
static CButtonContainer s_ButtonAbort;
if(DoButton_Menu(&s_ButtonAbort, Localize("Abort"), 0, &AbortButton) || (!UI()->IsPopupOpen() && UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE)))
m_DemoPlayerState = DEMOPLAYER_NONE;
static CUI::SConfirmPopupContext s_ConfirmPopupContext;
static CButtonContainer s_ButtonOk;
if(DoButton_Menu(&s_ButtonOk, Localize("Ok"), 0, &OkButton) || (!UI()->IsPopupOpen() && UI()->ConsumeHotkey(CUI::HOTKEY_ENTER)))
{
char aDemoName[IO_MAX_PATH_LENGTH];
DemoPlayer()->GetDemoName(aDemoName, sizeof(aDemoName));
str_append(aDemoName, ".demo");
if(!str_endswith(m_DemoSliceInput.GetString(), ".demo"))
m_DemoSliceInput.Append(".demo");
if(str_comp(aDemoName, m_DemoSliceInput.GetString()) == 0)
{
static CUI::SMessagePopupContext s_MessagePopupContext;
s_MessagePopupContext.ErrorColor();
str_copy(s_MessagePopupContext.m_aMessage, Localize("Please use a different name"));
UI()->ShowPopupMessage(UI()->MouseX(), OkButton.y + OkButton.h + 5.0f, &s_MessagePopupContext);
}
else
{
char aPath[IO_MAX_PATH_LENGTH];
str_format(aPath, sizeof(aPath), "%s/%s", m_aCurrentDemoFolder, m_DemoSliceInput.GetString());
if(Storage()->FileExists(aPath, IStorage::TYPE_SAVE))
{
s_ConfirmPopupContext.Reset();
s_ConfirmPopupContext.YesNoButtons();
str_copy(s_ConfirmPopupContext.m_aMessage, Localize("File already exists, do you want to overwrite it?"));
UI()->ShowPopupConfirm(UI()->MouseX(), OkButton.y + OkButton.h + 5.0f, &s_ConfirmPopupContext);
}
else
s_ConfirmPopupContext.m_Result = CUI::SConfirmPopupContext::CONFIRMED;
}
}
if(s_ConfirmPopupContext.m_Result == CUI::SConfirmPopupContext::CONFIRMED)
{
char aPath[IO_MAX_PATH_LENGTH];
str_format(aPath, sizeof(aPath), "%s/%s", m_aCurrentDemoFolder, m_DemoSliceInput.GetString());
str_copy(g_Config.m_UiDemoSelected, m_DemoSliceInput.GetString());
if(str_endswith(g_Config.m_UiDemoSelected, ".demo"))
g_Config.m_UiDemoSelected[str_length(g_Config.m_UiDemoSelected) - str_length(".demo")] = '\0';
m_DemoPlayerState = DEMOPLAYER_NONE;
Client()->DemoSlice(aPath, CMenus::DemoFilterChat, &s_RemoveChat);
DemolistPopulate();
DemolistOnUpdate(false);
}
if(s_ConfirmPopupContext.m_Result != CUI::SConfirmPopupContext::UNSET)
{
s_ConfirmPopupContext.Reset();
}
}
int CMenus::DemolistFetchCallback(const CFsFileInfo *pInfo, int IsDir, int StorageType, void *pUser)
@ -724,6 +814,7 @@ void CMenus::DemolistOnUpdate(bool Reset)
m_DemolistSelectedIndex = Reset ? !m_vDemos.empty() ? 0 : -1 :
m_DemolistSelectedIndex >= (int)m_vDemos.size() ? m_vDemos.size() - 1 : m_DemolistSelectedIndex;
m_DemolistSelectedIsDir = m_DemolistSelectedIndex < 0 ? false : m_vDemos[m_DemolistSelectedIndex].m_IsDir;
m_DemolistSelectedReveal = true;
}
bool CMenus::FetchHeader(CDemoItem &Item)
@ -934,7 +1025,6 @@ void CMenus::RenderDemoList(CUIRect MainView)
if(i + 1 < NumCols)
{
//Cols[i].flags |= SPACER;
Headers.VSplitLeft(2, &s_aCols[i].m_Spacer, &Headers);
}
}
@ -976,6 +1066,11 @@ void CMenus::RenderDemoList(CUIRect MainView)
}
static CListBox s_ListBox;
if(m_DemolistSelectedReveal)
{
s_ListBox.ScrollToSelected();
m_DemolistSelectedReveal = false;
}
s_ListBox.DoStart(ms_ListheaderHeight, m_vDemos.size(), 1, 3, m_DemolistSelectedIndex, &ListBox, false);
int ItemIndex = -1;
@ -1079,7 +1174,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
}
static CButtonContainer s_PlayButton;
if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir ? Localize("Open") : Localize("Play", "Demo browser"), 0, &PlayRect) || s_ListBox.WasItemActivated() || UI()->ConsumeHotkey(CUI::HOTKEY_ENTER) || (Input()->KeyPress(KEY_P) && m_pClient->m_GameConsole.IsClosed() && m_DemoPlayerState == DEMOPLAYER_NONE))
if(DoButton_Menu(&s_PlayButton, m_DemolistSelectedIsDir ? Localize("Open") : Localize("Play", "Demo browser"), 0, &PlayRect) || s_ListBox.WasItemActivated() || UI()->ConsumeHotkey(CUI::HOTKEY_ENTER) || (Input()->KeyPress(KEY_P) && m_pClient->m_GameConsole.IsClosed()))
{
if(m_DemolistSelectedIndex >= 0)
{
@ -1089,8 +1184,8 @@ void CMenus::RenderDemoList(CUIRect MainView)
fs_parent_dir(m_aCurrentDemoFolder);
else // sub folder
{
str_append(m_aCurrentDemoFolder, "/", sizeof(m_aCurrentDemoFolder));
str_append(m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename, sizeof(m_aCurrentDemoFolder));
str_append(m_aCurrentDemoFolder, "/");
str_append(m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename);
m_DemolistStorageType = m_vDemos[m_DemolistSelectedIndex].m_StorageType;
}
DemolistPopulate();

View file

@ -301,7 +301,7 @@ void CMenus::RenderPlayers(CUIRect MainView)
CTeeRenderInfo TeeInfo = CurrentClient.m_RenderInfo;
TeeInfo.m_Size = Button.h;
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(Button.x + Button.h / 2, Button.y + Button.h / 2 + OffsetToMid.y);
@ -311,17 +311,11 @@ void CMenus::RenderPlayers(CUIRect MainView)
Player.HSplitTop(1.5f, nullptr, &Player);
Player.VSplitMid(&Player, &Button);
Row.VSplitRight(210.0f, &Button2, &Row);
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, Player.x, Player.y + (Player.h - 14.f) / 2.f, 14.0f, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Player.w;
TextRender()->TextEx(&Cursor, CurrentClient.m_aName, -1);
TextRender()->SetCursor(&Cursor, Button.x, Button.y + (Button.h - 14.f) / 2.f, 14.0f, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Button.w;
TextRender()->TextEx(&Cursor, CurrentClient.m_aClan, -1);
UI()->DoLabel(&Player, CurrentClient.m_aName, 14.0f, TEXTALIGN_ML);
UI()->DoLabel(&Button, CurrentClient.m_aClan, 14.0f, TEXTALIGN_ML);
ColorRGBA Color(1.0f, 1.0f, 1.0f, 0.5f);
m_pClient->m_CountryFlags.Render(CurrentClient.m_Country, &Color,
m_pClient->m_CountryFlags.Render(CurrentClient.m_Country, ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f),
Button2.x, Button2.y + Button2.h / 2.0f - 0.75f * Button2.h / 2.0f, 1.5f * Button2.h, 0.75f * Button2.h);
// ignore chat button
@ -604,7 +598,7 @@ bool CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators)
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[aPlayerIDs[i]].m_RenderInfo;
TeeInfo.m_Size = TeeRect.h;
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(TeeRect.x + TeeInfo.m_Size / 2, TeeRect.y + TeeInfo.m_Size / 2 + OffsetToMid.y);
@ -1076,21 +1070,13 @@ void CMenus::RenderGhost(CUIRect MainView)
}
else if(Id == COL_NAME)
{
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, Button.x, Button.y + (Button.h - 12.0f) / 2.f, 12.0f, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Button.w;
TextRender()->TextEx(&Cursor, pGhost->m_aPlayer, -1);
UI()->DoLabel(&Button, pGhost->m_aPlayer, 12.0f, TEXTALIGN_ML);
}
else if(Id == COL_TIME)
{
CTextCursor Cursor;
TextRender()->SetCursor(&Cursor, Button.x, Button.y + (Button.h - 12.0f) / 2.f, 12.0f, TEXTFLAG_RENDER | TEXTFLAG_STOP_AT_END);
Cursor.m_LineWidth = Button.w;
char aBuf[64];
str_time(pGhost->m_Time / 10, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf));
TextRender()->TextEx(&Cursor, aBuf, -1);
UI()->DoLabel(&Button, aBuf, 12.0f, TEXTALIGN_ML);
}
}

File diff suppressed because it is too large Load diff

View file

@ -25,7 +25,7 @@
#include <base/color.h>
#include <base/math.h>
void CPlayers::RenderHand(CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset, float Alpha)
void CPlayers::RenderHand(const CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset, float Alpha)
{
vec2 HandPos = CenterPos + Dir;
float Angle = angle(Dir);
@ -666,7 +666,7 @@ void CPlayers::RenderPlayer(
RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position, Alpha);
float TeeAnimScale, TeeBaseSize;
RenderTools()->GetRenderTeeAnimScaleAndBaseSize(&State, &RenderInfo, TeeAnimScale, TeeBaseSize);
RenderTools()->GetRenderTeeAnimScaleAndBaseSize(&RenderInfo, TeeAnimScale, TeeBaseSize);
vec2 BodyPos = Position + vec2(State.GetBody()->m_X, State.GetBody()->m_Y) * TeeAnimScale;
if(RenderInfo.m_TeeRenderFlags & TEE_EFFECT_FROZEN)
{

View file

@ -13,7 +13,7 @@ class CPlayers : public CComponent
CTeeRenderInfo m_RenderInfoSpec;
CTeeRenderInfo m_aRenderInfo[MAX_CLIENTS];
void RenderHand(class CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset, float Alpha = 1.0f);
void RenderHand(const CTeeRenderInfo *pInfo, vec2 CenterPos, vec2 Dir, float AngleOffset, vec2 PostRotOffset, float Alpha = 1.0f);
void RenderPlayer(
const CNetObj_Character *pPrevChar,
const CNetObj_Character *pPlayerChar,

View file

@ -191,7 +191,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
while(TextRender()->TextWidth(TitleFontsize, aBuf, -1, -1.0f) > TitleWidth)
aBuf[str_length(aBuf) - 1] = '\0';
if(str_comp(aBuf, Client()->GetCurrentMap()))
str_append(aBuf, "", sizeof(aBuf));
str_append(aBuf, "");
pTitle = aBuf;
}
}
@ -432,7 +432,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
// avatar
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientID].m_RenderInfo;
TeeInfo.m_Size *= TeeSizeMod;
CAnimState *pIdleState = CAnimState::GetIdle();
const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(TeeOffset + TeeLength / 2, y + LineHeight / 2.0f + OffsetToMid.y);
@ -485,8 +485,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
// country flag
ColorRGBA Color(1.0f, 1.0f, 1.0f, 0.5f);
m_pClient->m_CountryFlags.Render(m_pClient->m_aClients[pInfo->m_ClientID].m_Country, &Color,
m_pClient->m_CountryFlags.Render(m_pClient->m_aClients[pInfo->m_ClientID].m_Country, ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f),
CountryOffset, y + (Spacing + TeeSizeMod * 5.0f) / 2.0f, CountryLength, LineHeight - Spacing - TeeSizeMod * 5.0f);
// ping
@ -532,25 +531,25 @@ void CScoreboard::RenderRecordingNotification(float x)
{
str_time((int64_t)m_pClient->DemoRecorder(RECORDER_MANUAL)->Length() * 100, TIME_HOURS, aTime, sizeof(aTime));
str_format(aBuf2, sizeof(aBuf2), "%s %s ", Localize("Manual"), aTime);
str_append(aBuf, aBuf2, sizeof(aBuf));
str_append(aBuf, aBuf2);
}
if(m_pClient->DemoRecorder(RECORDER_RACE)->IsRecording())
{
str_time((int64_t)m_pClient->DemoRecorder(RECORDER_RACE)->Length() * 100, TIME_HOURS, aTime, sizeof(aTime));
str_format(aBuf2, sizeof(aBuf2), "%s %s ", Localize("Race"), aTime);
str_append(aBuf, aBuf2, sizeof(aBuf));
str_append(aBuf, aBuf2);
}
if(m_pClient->DemoRecorder(RECORDER_AUTO)->IsRecording())
{
str_time((int64_t)m_pClient->DemoRecorder(RECORDER_AUTO)->Length() * 100, TIME_HOURS, aTime, sizeof(aTime));
str_format(aBuf2, sizeof(aBuf2), "%s %s ", Localize("Auto"), aTime);
str_append(aBuf, aBuf2, sizeof(aBuf));
str_append(aBuf, aBuf2);
}
if(m_pClient->DemoRecorder(RECORDER_REPLAYS)->IsRecording())
{
str_time((int64_t)m_pClient->DemoRecorder(RECORDER_REPLAYS)->Length() * 100, TIME_HOURS, aTime, sizeof(aTime));
str_format(aBuf2, sizeof(aBuf2), "%s %s ", Localize("Replay"), aTime);
str_append(aBuf, aBuf2, sizeof(aBuf));
str_append(aBuf, aBuf2);
}
if(!aBuf[0])

Some files were not shown because too many files have changed in this diff Show more