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/" run: "! grep --exclude-dir rust-bridge -rE '^#include \"(antibot|base|engine|game|steam|test)/' src/"
- name: Check standard header includes - name: Check standard header includes
run: scripts/check_standard_headers.sh run: scripts/check_standard_headers.sh
- name: Check config variables
run: scripts/check_config_variables.py
# TODO: Enable on release branches # TODO: Enable on release branches
#- name: Out-of-date translations #- name: Out-of-date translations
# run: | # 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 bcrypt userenv) # for Rust (https://github.com/rust-lang/rust/issues/91974)
list(APPEND PLATFORM_LIBS ole32) # CoInitialize(Ex) list(APPEND PLATFORM_LIBS ole32) # CoInitialize(Ex)
list(APPEND PLATFORM_LIBS shell32) list(APPEND PLATFORM_LIBS shell32)
list(APPEND PLATFORM_LIBS ntdll) # https://github.com/ddnet/ddnet/issues/6725
elseif(TARGET_OS STREQUAL "mac") elseif(TARGET_OS STREQUAL "mac")
find_library(CARBON Carbon) find_library(CARBON Carbon)
find_library(COCOA Cocoa) find_library(COCOA Cocoa)
@ -1863,6 +1864,7 @@ add_custom_command(OUTPUT "src/game/generated/wordlist.h"
set_src(BASE GLOB_RECURSE src/base set_src(BASE GLOB_RECURSE src/base
bezier.cpp bezier.cpp
bezier.h bezier.h
color.cpp
color.h color.h
detect.h detect.h
dynamic.h dynamic.h
@ -2260,6 +2262,8 @@ if(CLIENT)
pickup_data.h pickup_data.h
prediction/entities/character.cpp prediction/entities/character.cpp
prediction/entities/character.h prediction/entities/character.h
prediction/entities/dragger.cpp
prediction/entities/dragger.h
prediction/entities/laser.cpp prediction/entities/laser.cpp
prediction/entities/laser.h prediction/entities/laser.h
prediction/entities/pickup.cpp prediction/entities/pickup.cpp

View file

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

View file

@ -77,12 +77,6 @@ Clan
Client Client
== Кліент == Кліент
Close
== Выйсці
Connect
== Падлучыцца
Connecting to Connecting to
== Падлучэнне да == Падлучэнне да
@ -348,9 +342,6 @@ Rename demo
Reset filter Reset filter
== Скінуць фільтр == Скінуць фільтр
Sample rate
== Чашчыня сэмпла
Score Score
== Ачкі == Ачкі
@ -830,9 +821,6 @@ Exclude
%d player %d player
== %d гулец == %d гулец
Refreshing...
== Абнаўленне...
Are you sure that you want to disconnect and switch to a different server? 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? Are you sure that you want to remove the clan '%s' from your friends list?
== Вы ўпэўненыя што хочаце выдаліць клан '%s' са спіса вашых сяброў? == Вы ўпэўненыя што хочаце выдаліць клан '%s' са спіса вашых сяброў?
Select a name
== Выберыце імя
Please use a different name Please use a different name
== Калі ласка, выкарыстайце іншае імя == Калі ласка, выкарыстайце іншае імя
@ -896,12 +881,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== Паскорыць дэма == Паскорыць дэма
Mark the beginning of a cut
== Пазначыць пачатак адрэзка
Mark the end of a cut
== Пазначыць канец адрэзка
Export cut as a separate demo Export cut as a separate demo
== Экспартаваць адрэзак як асобнае дэма == Экспартаваць адрэзак як асобнае дэма
@ -1133,13 +1112,6 @@ Chat command
Enable controller Enable controller
== Уключыць кантролер == Уключыць кантролер
Controller %d: %s
== Кантролер %d: %s
Click to cycle through all available controllers.
== Націсніце каб праглядзець усе дасяжныя кантролеры.
[Ingame controller mode]
Relative Relative
== Адносны == Адносны
@ -1162,18 +1134,12 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== Кантролер не знойдзены. Падключыце кантролер. == Кантролер не знойдзены. Падключыце кантролер.
Device
== Прылада
Status Status
== Статус == Статус
Aim bind Aim bind
== Вось прыцэла == Вось прыцэла
Controller Axis #%d
== Вось кантролера #%d
Mouse Mouse
== Мыш == Мыш
@ -1228,9 +1194,6 @@ default
custom custom
== карыстацкі == карыстацкі
Graphics cards
== Відэакарты
auto auto
== аўта == аўта
@ -1255,9 +1218,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== Уключыць гук падсвечаных паведамленняў == Уключыць гук падсвечаных паведамленняў
Threaded sound loading
== Шматструменная загрузка гукаў
Game sound volume Game sound volume
== Гучнасць гульні == Гучнасць гульні
@ -1459,8 +1419,8 @@ Save the best demo of each race
Enable replays Enable replays
== Уключыць запісы == Уключыць запісы
Default length: %d Default length
== Станд. працягласць: %d == Станд. працягласць
When you cross the start line, show a ghost tee replicating the movements of your best time When you cross the start line, show a ghost tee replicating the movements of your best time
== Пры перасячэнні стартавай лініі, паказваць прывід Tee, які паўтарае ваш лепшы час == Пры перасячэнні стартавай лініі, паказваць прывід Tee, які паўтарае ваш лепшы час
@ -1513,9 +1473,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths AntiPing: predict grenade paths
== АнтыПінг: прадказывать траекторыі гранат == АнтыПінг: прадказывать траекторыі гранат
Old mouse mode
== Рэжым старой мышы
Background Background
== Фон == Фон
@ -1694,6 +1651,12 @@ Grabs
9+ new mentions 9+ new mentions
== 9+ новых згадак == 9+ новых згадак
A demo with this name already exists
==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -1718,3 +1681,27 @@ None
Add Clan 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 Client
== Klijent == Klijent
Close
== Zatvori
Connect
== Konektuj
Connecting to Connecting to
== Konektovanje na == Konektovanje na
@ -350,9 +344,6 @@ Rename demo
Reset filter Reset filter
== Poništi filter == Poništi filter
Sample rate
== Frekvencija
Score Score
== Rezultat == Rezultat
@ -703,9 +694,6 @@ Update now
Restart Restart
== Restart == Restart
Select a name
== Izaberite ime
Please use a different name Please use a different name
== Molimo izaberite drugo ime == Molimo izaberite drugo ime
@ -868,9 +856,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== Omogući zvuk označavanja u čatu == Omogući zvuk označavanja u čatu
Threaded sound loading
== Učitavanje tredovanog zvuka
Map sound volume Map sound volume
== Glasnoća zvuka mape == Glasnoća zvuka mape
@ -919,8 +904,8 @@ Client message
Save the best demo of each race Save the best demo of each race
== Sačuvaj najbolji demo-snimak svake trke == Sačuvaj najbolji demo-snimak svake trke
Default length: %d Default length
== Zadana dužina: %d == Zadana dužina
Enable replays Enable replays
== Omogući replay == Omogući replay
@ -961,9 +946,6 @@ Show other players' hook collision lines
Show other players' key presses Show other players' key presses
== Prikaži tipke koje ostali igrači pritiskaju == Prikaži tipke koje ostali igrači pritiskaju
Old mouse mode
== Stari način miša
Show tiles layers from BG map Show tiles layers from BG map
== Prikaži slojeve od pozadinske mape == 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 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? File '%s' already exists, do you want to overwrite it?
@ -1192,9 +1174,6 @@ Getting server list from master server
%d player %d player
== ==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== ==
@ -1204,6 +1183,9 @@ Copy info
Leak IP Leak IP
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -1256,10 +1238,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -1271,9 +1253,21 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts Toggle keyboard shortcuts
== ==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files Loading demo files
== ==
@ -1364,10 +1358,10 @@ Chat command
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1378,9 +1372,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1393,7 +1384,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1402,9 +1393,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1414,15 +1402,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Dummy Dummy
== ==
@ -1450,7 +1438,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto

View file

@ -99,12 +99,6 @@ Clan
Client Client
== Cliente == Cliente
Close
== Fechar
Connect
== Conectar
Connecting to Connecting to
== Conectando a == Conectando a
@ -373,9 +367,6 @@ Rename demo
Reset filter Reset filter
== Redefinir filtro == Redefinir filtro
Sample rate
== Frequência do som
Score Score
== Pontos == Pontos
@ -604,9 +595,6 @@ HUD
Show names in chat in team colors Show names in chat in team colors
== Mostrar nomes no chat com cores do time == Mostrar nomes no chat com cores do time
Select a name
== Selecione um nome
Netversion: Netversion:
== Netversion: == Netversion:
@ -652,9 +640,6 @@ Gameplay
Restart Restart
== Reiniciar == Reiniciar
Old mouse mode
== Modo antigo de mouse
Round Round
== Turno == Turno
@ -691,9 +676,6 @@ Ghost
Remove chat Remove chat
== Remover chat == Remover chat
Threaded sound loading
== Carregamento de som em fluxos
Check now Check now
== Verificar agora == Verificar agora
@ -1006,8 +988,8 @@ Converse
Successfully saved the replay! Successfully saved the replay!
== A reprodução foi salva com sucesso == A reprodução foi salva com sucesso
Default length: %d Default length
== Duração padrão: %d == Duração padrão
Replay feature is disabled! Replay feature is disabled!
== O Recurso de reprodução está desabilitado! == 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? 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? == Tem certeza que deseja desconectar e trocar para um servidor diferente?
Refreshing...
== Atualizando...
Kill Messages Kill Messages
== Mensagens de kill == Mensagens de kill
@ -1289,9 +1268,6 @@ default
custom custom
== personalizado == personalizado
Graphics cards
== Placas de vídeo
auto auto
== auto == auto
@ -1364,13 +1340,6 @@ Download community skins
Enable controller Enable controller
== Habilitar controle == 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 Relative
== Relativo == Relativo
@ -1390,18 +1359,12 @@ UI controller sens.
Controller jitter tolerance Controller jitter tolerance
== Tolerância jitter do controle == Tolerância jitter do controle
Device
== Dispositivo
Status Status
== Status == Status
Aim bind Aim bind
== Associação de mira == Associação de mira
Controller Axis #%d
== Eixo #%d do controle
Mouse Mouse
== Mouse == Mouse
@ -1561,12 +1524,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== Acelerar a 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 Export cut as a separate demo
== Exportar corte como uma demo separada == Exportar corte como uma demo separada
@ -1716,6 +1673,12 @@ Copy info
Create a random skin Create a random skin
== Criar uma skin aleatória == Criar uma skin aleatória
A demo with this name already exists
==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -1740,3 +1703,27 @@ None
Add Clan 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 Client
== Клиент == Клиент
Close
== Затвори
Connect
== Впиши
Connecting to Connecting to
== Свързвам се с == Свързвам се с
@ -347,9 +341,6 @@ Rename demo
Reset filter Reset filter
== Рестартирай филтрите == Рестартирай филтрите
Sample rate
== Честота
Score 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 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? File '%s' already exists, do you want to overwrite it?
@ -831,9 +822,6 @@ Exclude
%d player %d player
== ==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== ==
@ -858,6 +846,9 @@ Copy info
Leak IP Leak IP
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -889,18 +880,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan 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 Play the current demo
== ==
@ -922,10 +901,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -937,9 +916,30 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts 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 Loading demo files
== ==
@ -1162,10 +1162,10 @@ Chat command
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1176,9 +1176,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1191,7 +1188,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1200,9 +1197,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1212,15 +1206,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Dummy Dummy
== ==
@ -1236,10 +1230,10 @@ Windowed fullscreen
Desktop fullscreen Desktop fullscreen
== ==
may cause delay Screen
== ==
Screen may cause delay
== ==
Allows maps to render with more detail Allows maps to render with more detail
@ -1257,7 +1251,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto
@ -1284,9 +1278,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== ==
Threaded sound loading
==
Game sound volume Game sound volume
== ==
@ -1488,7 +1479,7 @@ Save the best demo of each race
Enable replays Enable replays
== ==
Default length: %d Default length
== ==
When you cross the start line, show a ghost tee replicating the movements of your best time When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1506,10 +1497,10 @@ Gameplay
Overlay entities Overlay entities
== ==
Size Show text entities
== ==
Show text entities Size
== ==
Opacity Opacity
@ -1542,9 +1533,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths AntiPing: predict grenade paths
== ==
Old mouse mode
==
Background Background
== ==

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -100,12 +100,6 @@ Clan
Client Client
== Client == Client
Close
== Fermer
Connect
== Se connecter
Connecting to Connecting to
== Connexion à == Connexion à
@ -371,9 +365,6 @@ Rename demo
Reset filter Reset filter
== Filtres par défaut == Filtres par défaut
Sample rate
== Taux d'échantillonnage
Score Score
== Score == Score
@ -691,9 +682,6 @@ Are you sure that you want to disconnect your dummy?
Reload Reload
== Recharger == Recharger
Old mouse mode
== Ancien mode de souris
Server best: Server best:
== Meilleur score du serveur == Meilleur score du serveur
@ -787,9 +775,6 @@ Update failed! Check log...
Reset Reset
== Défaut == Défaut
Threaded sound loading
== Chargement des sons dans un thread spécifique
File already exists, do you want to overwrite it? File already exists, do you want to overwrite it?
== Ce fichier existe déjà, voulez-vous l'écraser ? == Ce fichier existe déjà, voulez-vous l'écraser ?
@ -922,8 +907,8 @@ Show others
Unfinished map Unfinished map
== Carte non terminée == Carte non terminée
Default length: %d Default length
== Durée par défaut : %d == Durée par défaut
Highlighted message Highlighted message
== Message en surbrillance == Message en surbrillance
@ -952,9 +937,6 @@ Ghost
Show kill messages Show kill messages
== Afficher les messages d'élimination == Afficher les messages d'élimination
Select a name
== Choisissez un pseudonyme
Markers Markers
== Marqueurs == Marqueurs
@ -1259,9 +1241,6 @@ https://ddnet.org/discord
Are you sure that you want to disconnect and switch to a different server? 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? == Êtes vous sur de vouloir vous déconnecter et changer de serveur?
Refreshing...
== Actualisation...
Show local player's key presses Show local player's key presses
== Montrer les touches appuyées des autres joueurs == Montrer les touches appuyées des autres joueurs
@ -1307,9 +1286,6 @@ default
custom custom
== Personnalisé == Personnalisé
Graphics cards
== Carte graphique
auto auto
== Automatique == Automatique
@ -1367,13 +1343,6 @@ Download community skins
Enable controller Enable controller
== Activer la manette == 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 Relative
== Relatif == Relatif
@ -1393,18 +1362,12 @@ UI controller sens.
Controller jitter tolerance Controller jitter tolerance
== Tolérance gigue de la manette == Tolérance gigue de la manette
Device
== Manette
Status Status
== Statut == Statut
Aim bind Aim bind
== Touche visée == Touche visée
Controller Axis #%d
== Axe manette #%d
Mouse Mouse
== Souris == Souris
@ -1564,12 +1527,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== Accélérer la démo == 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 Export cut as a separate demo
== Exporter la coupe comme une démo séparée == Exporter la coupe comme une démo séparée
@ -1743,3 +1700,33 @@ Add Clan
Create a random skin Create a random skin
== Créer un skin aléatoire == 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
== Client == Client
Close
== Schließ.
Colors of the hook collision line, in case of a possible collision with: Colors of the hook collision line, in case of a possible collision with:
== Die Farbe der Hakenkollisionlinie bei einer möglichen Kollision mit: == Die Farbe der Hakenkollisionlinie bei einer möglichen Kollision mit:
Connect
== Verbinden
Connecting to Connecting to
== Verbinden mit == Verbinden mit
@ -368,9 +362,6 @@ Rename demo
Reset filter Reset filter
== Standardfilter == Standardfilter
Sample rate
== Abtastrate
Score Score
== Punkte == Punkte
@ -794,9 +785,6 @@ Switch weapon when out of ammo
Grabs Grabs
== Griffe == Griffe
Select a name
== Namen wählen
Automatically take game over screenshot Automatically take game over screenshot
== Automatisches Bildschirmfoto am Spielende == Automatisches Bildschirmfoto am Spielende
@ -809,9 +797,6 @@ Gameplay
Laser Laser
== Laser == Laser
Old mouse mode
== Alter Mausmodus
Follow Follow
== Folgen == Folgen
@ -827,9 +812,6 @@ Show tiles layers from BG map
Remove chat Remove chat
== Chat entfernen == Chat entfernen
Threaded sound loading
== Sounds in Threads laden
Frags Frags
== Abschüsse == 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 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. == 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 Default length
== Standardlänge: %d == Standardlänge
Pause Pause
== Pause == Pause
@ -1290,9 +1272,6 @@ A Tee
Are you sure that you want to disconnect and switch to a different server? 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? == Bist du sicher, dass du die Verbindung trennen und zu einem anderen Server wechseln möchtest?
Refreshing...
== Aktualisieren...
Kill Messages Kill Messages
== Kill-Nachrichten == Kill-Nachrichten
@ -1332,9 +1311,6 @@ default
custom custom
== eigene == eigene
Graphics cards
== Grafikkarte
auto auto
== Auto == Auto
@ -1398,9 +1374,6 @@ No answer from server yet.
Download community skins Download community skins
== Community-Skins runterladen == Community-Skins runterladen
Device
== Gerät
Status Status
== Status == Status
@ -1434,13 +1407,6 @@ UI mouse sens.
Enable controller Enable controller
== Controller aktivieren == 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 Relative
== Relativ == Relativ
@ -1460,9 +1426,6 @@ UI controller sens.
Controller jitter tolerance Controller jitter tolerance
== Jitter-Toleranz des Controllers == Jitter-Toleranz des Controllers
Controller Axis #%d
== Controller-Axe #%d
Controller Controller
== Controller == Controller
@ -1589,12 +1552,6 @@ Freeze Laser Outline Color
Freeze Laser Inner Color Freeze Laser Inner Color
== Innenfarbe Einfrier-Laser == 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. Menu opened. Press Esc key again to close menu.
== Menü geöffnet. Erneut Esc-Taste drücken um Menü zu schließen. == Menü geöffnet. Erneut Esc-Taste drücken um Menü zu schließen.
@ -1733,3 +1690,33 @@ None
Add Clan Add Clan
== Clan hinzufügen == 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 Client
== Πελάτης == Πελάτης
Close
== Κλείσιμο
Connect
== Σύνδεση
Connecting to Connecting to
== Σύνδεση με == Σύνδεση με
@ -350,9 +344,6 @@ Rename demo
Reset filter Reset filter
== Αφαίρεση φίλτρου == Αφαίρεση φίλτρου
Sample rate
== Δειγματοληψία
Score 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 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? File '%s' already exists, do you want to overwrite it?
@ -837,9 +828,6 @@ Exclude
%d player %d player
== ==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== ==
@ -864,6 +852,9 @@ Copy info
Leak IP Leak IP
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -895,18 +886,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan 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 Play the current demo
== ==
@ -928,10 +907,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -943,9 +922,30 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts 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 Loading demo files
== ==
@ -1165,10 +1165,10 @@ Chat command
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1179,9 +1179,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1194,7 +1191,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1203,9 +1200,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1215,15 +1209,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Dummy Dummy
== ==
@ -1239,10 +1233,10 @@ Windowed fullscreen
Desktop fullscreen Desktop fullscreen
== ==
may cause delay Screen
== ==
Screen may cause delay
== ==
Allows maps to render with more detail Allows maps to render with more detail
@ -1260,7 +1254,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto
@ -1287,9 +1281,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== ==
Threaded sound loading
==
Game sound volume Game sound volume
== ==
@ -1488,7 +1479,7 @@ Save the best demo of each race
Enable replays Enable replays
== ==
Default length: %d Default length
== ==
When you cross the start line, show a ghost tee replicating the movements of your best time When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1506,10 +1497,10 @@ Gameplay
Overlay entities Overlay entities
== ==
Size Show text entities
== ==
Show text entities Size
== ==
Opacity Opacity
@ -1542,9 +1533,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths AntiPing: predict grenade paths
== ==
Old mouse mode
==
Background Background
== ==

View file

@ -78,12 +78,6 @@ Clan
Client Client
== Kliens == Kliens
Close
== Bezárás
Connect
== Csatlakozás
Connecting to Connecting to
== Csatlakozás... == Csatlakozás...
@ -340,9 +334,6 @@ Rename demo
Reset filter Reset filter
== Szűrő visszaállítása == Szűrő visszaállítása
Sample rate
== Mintavételi frekvencia
Score Score
== Pontszám == Pontszám
@ -625,9 +616,6 @@ Spectate next
Show names in chat in team colors Show names in chat in team colors
== Csapatszínben jelennek meg a játékosok a chatben == Csapatszínben jelennek meg a játékosok a chatben
Select a name
== Válassz nevet
Enable team chat sound Enable team chat sound
== Csapat chat hang engedélyezése == Csapat chat hang engedélyezése
@ -658,9 +646,6 @@ Restart
Game paused Game paused
== Játék megállítva == Játék megállítva
Old mouse mode
== Régi egér mód
Browser Browser
== Böngésző == Böngésző
@ -856,9 +841,6 @@ Deactivate
Welcome to DDNet Welcome to DDNet
== Üdvözlet a DDNet-en == Üdvözlet a DDNet-en
Threaded sound loading
== Csavarmenetes hang betöltése
Activate Activate
== Aktiválás == Aktiválás
@ -976,8 +958,8 @@ Toggle dyncam
%d new mentions %d new mentions
== %d új értesítés == %d új értesítés
Default length: %d Default length
== Átlagos hossz: %d == Átlagos hossz
Show HUD Show HUD
== HUD mutatása == HUD mutatása
@ -1223,9 +1205,6 @@ SA
CHN CHN
== KíNA == KíNA
Refreshing...
== Frissítés...
Kill Messages Kill Messages
== Halálüzenetek == Halálüzenetek
@ -1283,9 +1262,6 @@ default
custom custom
== egyedi == egyedi
Graphics cards
== Videókártyák
auto auto
== automatikus == automatikus
@ -1343,13 +1319,6 @@ Download community skins
Enable controller Enable controller
== Kontroller használata == 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 Relative
== Relatív == Relatív
@ -1369,15 +1338,9 @@ UI controller sens.
Controller jitter tolerance Controller jitter tolerance
== Kontroller jitter tolerancia == Kontroller jitter tolerancia
Device
== Eszköz
Status Status
== Állapot == Állapot
Controller Axis #%d
== Kontroller Tengely #%d
Mouse Mouse
== Egér == Egér
@ -1575,37 +1538,12 @@ File '%s' already exists, do you want to overwrite it?
Copy info Copy info
== Infó Másolása == 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? 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? == 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? 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? == Biztos, hogy ki szeretnéd törölni '%s' Klánt a barátlistádból?
Add Clan
==
Play the current demo Play the current demo
== Jelenlegi Demó Lejátszása == Jelenlegi Demó Lejátszása
@ -1627,12 +1565,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== Demó Felgyorsítása == 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 cut as a separate demo
== Exportáld a vágást, mint külön Demó == 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 Open the directory to add custom assets
== Megnyitni az egyedi Képek helyét == 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
== Client == Client
Close
== Chiudi
Connect
== Connetti
Connecting to Connecting to
== Connessione a == Connessione a
@ -352,9 +346,6 @@ Rename demo
Reset filter Reset filter
== Azzera filtri == Azzera filtri
Sample rate
== Frequenza
Score Score
== Punti == Punti
@ -766,9 +757,6 @@ Countries
Types Types
== Tipi == Tipi
Select a name
== Seleziona un nome
Please use a different name Please use a different name
== Per favore usa un nome differente == Per favore usa un nome differente
@ -943,9 +931,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== Abilita suono della chat evidenziata == Abilita suono della chat evidenziata
Threaded sound loading
== Suono filettato
Game sound volume Game sound volume
== Volume del gioco == Volume del gioco
@ -1015,8 +1000,8 @@ Client message
Save the best demo of each race Save the best demo of each race
== Salva la miglior demo di ogni partita == Salva la miglior demo di ogni partita
Default length: %d Default length
== Lunghezza predefinita: %d == Lunghezza predefinita
Enable replays Enable replays
== Abilita i replay == Abilita i replay
@ -1060,9 +1045,6 @@ Show other players' hook collision lines
Show other players' key presses Show other players' key presses
== Mostra i tasti degli altri giocatori == Mostra i tasti degli altri giocatori
Old mouse mode
== Modalità mouse vecchio
Use current map as background Use current map as background
== Usa la mappa attuale come sfondo == Usa la mappa attuale come sfondo
@ -1289,7 +1271,7 @@ Getting game info
Requesting to join the game Requesting to join the game
== ==
Cancel A demo with this name already exists
== ==
File '%s' already exists, do you want to overwrite it? File '%s' already exists, do you want to overwrite it?
@ -1328,9 +1310,6 @@ CHN
Getting server list from master server Getting server list from master server
== ==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== ==
@ -1340,6 +1319,9 @@ Copy info
Leak IP Leak IP
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -1392,10 +1374,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -1407,9 +1389,21 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts Toggle keyboard shortcuts
== ==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files Loading demo files
== ==
@ -1482,10 +1476,10 @@ Chat command
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1496,9 +1490,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1511,7 +1502,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1520,9 +1511,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1532,15 +1520,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Dummy Dummy
== ==
@ -1568,7 +1556,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto

View file

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

View file

@ -88,12 +88,6 @@ Clan
Client Client
== 클라이언트 == 클라이언트
Close
== 닫기
Connect
== 연결
Connecting to Connecting to
== 연결 중 == 연결 중
@ -350,9 +344,6 @@ Rename demo
Reset filter Reset filter
== 필터 초기화 == 필터 초기화
Sample rate
== 샘플링 속도
Score Score
== 점수 == 점수
@ -724,9 +715,6 @@ Exclude
%d player %d player
== %d 플레이어 == %d 플레이어
Refreshing...
== 새로고침 중...
Filter connecting players Filter connecting players
== 접속 중인 플레이어 제외 == 접속 중인 플레이어 제외
@ -745,9 +733,6 @@ Types
Leak IP Leak IP
== IP 노출하기 == IP 노출하기
Select a name
== 다른 이름으로 저장
Please use a different name Please use a different name
== 다른 이름을 사용해 주십시오 == 다른 이름을 사용해 주십시오
@ -961,9 +946,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== 언급된 채팅 소리 활성화 == 언급된 채팅 소리 활성화
Threaded sound loading
== 다중 스레드 소리 로딩
Game sound volume Game sound volume
== 게임 음량 == 게임 음량
@ -1036,8 +1018,8 @@ Preview
Save the best demo of each race Save the best demo of each race
== 레이스 최고 기록의 데모를 저장 == 레이스 최고 기록의 데모를 저장
Default length: %d Default length
== 기본 길이: %d == 기본 길이
Enable replays Enable replays
== 리플레이 활성화 == 리플레이 활성화
@ -1087,9 +1069,6 @@ Show other players' key presses
Show local player's key presses Show local player's key presses
== 주변 플레이어의 키 입력 표시 == 주변 플레이어의 키 입력 표시
Old mouse mode
== 구식 마우스 모드
Background Background
== 배경 == 배경
@ -1286,9 +1265,6 @@ default
custom custom
== 커스텀 == 커스텀
Graphics cards
== 그래픽 카드
auto auto
== 자동 == 자동
@ -1355,13 +1331,6 @@ Download community skins
Enable controller Enable controller
== 컨트롤러 활성화 == 컨트롤러 활성화
Controller %d: %s
== 컨트롤러 %d: %s
Click to cycle through all available controllers.
== 사용가능한 컨트롤러로 전환하려면 클릭하십시오.
[Ingame controller mode]
Relative Relative
== 상대적 == 상대적
@ -1381,18 +1350,12 @@ UI controller sens.
Controller jitter tolerance Controller jitter tolerance
== 컨트롤러 신호 오차 허용 범위 == 컨트롤러 신호 오차 허용 범위
Device
== 장치
Status Status
== 상태 == 상태
Aim bind Aim bind
== 조준 바인드 == 조준 바인드
Controller Axis #%d
== 컨트롤러 축
Mouse Mouse
== 마우스 == 마우스
@ -1552,12 +1515,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== 데모 속도 높이기 == 데모 속도 높이기
Mark the beginning of a cut
== 영상 자르기의 시작 부분
Mark the end of a cut
== 영상 자르기의 끝 부분
Export cut as a separate demo Export cut as a separate demo
== 자른 부분을 다른 이름으로 저장 == 자른 부분을 다른 이름으로 저장
@ -1707,6 +1664,12 @@ Copy info
Create a random skin Create a random skin
== 무작위 스킨 생성 == 무작위 스킨 생성
A demo with this name already exists
==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -1731,3 +1694,27 @@ None
Add Clan 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 Client
== Клиент == Клиент
Close
== Чыгуу
Connect
== Туташуу
Connecting to Connecting to
== Туташтырылууда == Туташтырылууда
@ -412,9 +406,6 @@ Laser
Round Round
== Раунду == Раунду
Sample rate
== Жыштыгы
Sat. 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 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? File '%s' already exists, do you want to overwrite it?
@ -828,9 +819,6 @@ Exclude
%d player %d player
== ==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== ==
@ -855,6 +843,9 @@ Copy info
Leak IP Leak IP
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -886,18 +877,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan 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 Play the current demo
== ==
@ -919,10 +898,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -934,9 +913,30 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts 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 Loading demo files
== ==
@ -1156,10 +1156,10 @@ Chat command
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1170,9 +1170,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1185,7 +1182,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1194,9 +1191,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1206,15 +1200,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Dummy Dummy
== ==
@ -1230,10 +1224,10 @@ Windowed fullscreen
Desktop fullscreen Desktop fullscreen
== ==
may cause delay Screen
== ==
Screen may cause delay
== ==
Allows maps to render with more detail Allows maps to render with more detail
@ -1251,7 +1245,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto
@ -1278,9 +1272,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== ==
Threaded sound loading
==
Game sound volume Game sound volume
== ==
@ -1479,7 +1470,7 @@ Save the best demo of each race
Enable replays Enable replays
== ==
Default length: %d Default length
== ==
When you cross the start line, show a ghost tee replicating the movements of your best time When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1497,10 +1488,10 @@ Gameplay
Overlay entities Overlay entities
== ==
Size Show text entities
== ==
Show text entities Size
== ==
Opacity Opacity
@ -1533,9 +1524,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths AntiPing: predict grenade paths
== ==
Old mouse mode
==
Background Background
== ==

View file

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

View file

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

View file

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

View file

@ -80,12 +80,6 @@ Clan
Client Client
== Cliente == Cliente
Close
== Fechar
Connect
== Ligar
Connecting to Connecting to
== A ligar ao endereço == A ligar ao endereço
@ -363,9 +357,6 @@ Reset
Reset filter Reset filter
== Reiniciar filtro == Reiniciar filtro
Sample rate
== Frequencia de rate
Score Score
== Pontos == Pontos
@ -642,9 +633,6 @@ HUD
Show names in chat in team colors Show names in chat in team colors
== Mostrar nomes no chat com cores da equipa == Mostrar nomes no chat com cores da equipa
Select a name
== Escolha um nome
Enable team chat sound Enable team chat sound
== Ativar o som do chat de equipa == Ativar o som do chat de equipa
@ -669,9 +657,6 @@ Gameplay
Restart Restart
== Reiniciar == Reiniciar
Old mouse mode
== Modo de rato antigo
Browser Browser
== Navegador == Navegador
@ -858,9 +843,6 @@ Theme
%d player %d player
== %d jogador == %d jogador
Refreshing...
== A atualizar...
Date Date
== Data == 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. 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? File '%s' already exists, do you want to overwrite it?
@ -1141,6 +1123,9 @@ Copy info
Leak IP Leak IP
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -1193,10 +1178,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -1208,9 +1193,21 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts Toggle keyboard shortcuts
== ==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files Loading demo files
== ==
@ -1361,10 +1358,10 @@ Chat command
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1375,9 +1372,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1390,7 +1384,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1399,9 +1393,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1411,15 +1402,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Windowed fullscreen Windowed fullscreen
== ==
@ -1441,7 +1432,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto
@ -1450,9 +1441,6 @@ auto
Enable long pain sound (used when shooting in freeze) Enable long pain sound (used when shooting in freeze)
== ==
Threaded sound loading
==
Appearance Appearance
== ==
@ -1585,7 +1573,7 @@ Set all to Rifle
Enable replays Enable replays
== ==
Default length: %d Default length
== ==
When you cross the start line, show a ghost tee replicating the movements of your best time 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 Client
== Clientul == Clientul
Close
== Închide
Connect
== Conectează
Connecting to Connecting to
== Conectare la == Conectare la
@ -356,9 +350,6 @@ Rename demo
Reset filter Reset filter
== Filtru implicit == Filtru implicit
Sample rate
== Frecvența
Score Score
== Scor == 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 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? File '%s' already exists, do you want to overwrite it?
@ -843,9 +834,6 @@ Exclude
%d player %d player
== ==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== ==
@ -870,6 +858,9 @@ Copy info
Leak IP Leak IP
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -901,18 +892,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan 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 Play the current demo
== ==
@ -934,10 +913,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -949,9 +928,30 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts 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 Loading demo files
== ==
@ -1171,10 +1171,10 @@ Chat command
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1185,9 +1185,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1200,7 +1197,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1209,9 +1206,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1221,15 +1215,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Dummy Dummy
== ==
@ -1245,10 +1239,10 @@ Windowed fullscreen
Desktop fullscreen Desktop fullscreen
== ==
may cause delay Screen
== ==
Screen may cause delay
== ==
Allows maps to render with more detail Allows maps to render with more detail
@ -1266,7 +1260,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto
@ -1293,9 +1287,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== ==
Threaded sound loading
==
Game sound volume Game sound volume
== ==
@ -1494,7 +1485,7 @@ Save the best demo of each race
Enable replays Enable replays
== ==
Default length: %d Default length
== ==
When you cross the start line, show a ghost tee replicating the movements of your best time When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1512,10 +1503,10 @@ Gameplay
Overlay entities Overlay entities
== ==
Size Show text entities
== ==
Show text entities Size
== ==
Opacity Opacity
@ -1548,9 +1539,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths AntiPing: predict grenade paths
== ==
Old mouse mode
==
Background Background
== ==

View file

@ -89,12 +89,6 @@ Clan
Client Client
== Клиент == Клиент
Close
== Закрыть
Connect
== Подключиться
Connecting to Connecting to
== Подключение к == Подключение к
@ -360,9 +354,6 @@ Rename demo
Reset filter Reset filter
== Сбросить фильтры == Сбросить фильтры
Sample rate
== Частота
Score Score
== Счёт == Счёт
@ -540,9 +531,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== Звуки подсвечиваемых сообщений == Звуки подсвечиваемых сообщений
Threaded sound loading
== Фоновая загрузка музыки
Use DDRace Scoreboard Use DDRace Scoreboard
== Использовать DDRace таблицу счета == Использовать DDRace таблицу счета
@ -672,9 +660,6 @@ Show ghost
No updates available No updates available
== Нет доступных обновлений == Нет доступных обновлений
Select a name
== Выберите имя
Show other players' hook collision lines Show other players' hook collision lines
== Показывать коллизии крюка других игроков == Показывать коллизии крюка других игроков
@ -690,9 +675,6 @@ Show others
Game paused Game paused
== Пауза == Пауза
Old mouse mode
== Режим старой мыши
Team message Team message
== Сообщение от команды == Сообщение от команды
@ -948,8 +930,8 @@ Friend message
Save the best demo of each race Save the best demo of each race
== Сохранять лучшее демо каждой карты == Сохранять лучшее демо каждой карты
Default length: %d Default length
== Станд. длина: %d == Станд. длина
Enable replays Enable replays
== Включить записи == Включить записи
@ -1243,9 +1225,6 @@ Desktop fullscreen
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== Вы уверены, что хотите отключиться и перейти на другой сервер? == Вы уверены, что хотите отключиться и перейти на другой сервер?
Refreshing...
== Обновление...
Kill Messages Kill Messages
== Сообщения о смерти == Сообщения о смерти
@ -1279,9 +1258,6 @@ default
custom custom
== перс. == перс.
Graphics cards
== Видеокарты
auto auto
== авто == авто
@ -1330,13 +1306,6 @@ Choose default eyes when joining a server
Enable controller Enable controller
== Включить контроллер == Включить контроллер
Controller %d: %s
== Контроллер %d: %s
Click to cycle through all available controllers.
== Нажмите для переключения между всеми доступными контроллерами.
[Ingame controller mode]
Relative Relative
== Относительный == Относительный
@ -1356,18 +1325,12 @@ UI controller sens.
Controller jitter tolerance Controller jitter tolerance
== Устойчивость к движению контроллера == Устойчивость к движению контроллера
Device
== Устройство
Status Status
== Состояние == Состояние
Aim bind Aim bind
== Привязка оси == Привязка оси
Controller Axis #%d
== Ось контроллера #%d
Mouse Mouse
== Мышь == Мышь
@ -1551,12 +1514,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== Ускорить демо == Ускорить демо
Mark the beginning of a cut
== Отметить начало участка
Mark the end of a cut
== Отметить конец участка
Export cut as a separate demo Export cut as a separate demo
== Экспортировать участок отдельно == Экспортировать участок отдельно
@ -1728,3 +1685,33 @@ None
Add Clan 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 Client
== Klijent == Klijent
Close
== Zatvori
Connect
== Poveži se
Connecting to Connecting to
== Povezujem se na == Povezujem se na
@ -347,9 +341,6 @@ Rename demo
Reset filter Reset filter
== Povrati filter == Povrati filter
Sample rate
== Frekfencija
Score Score
== Rezultat == Rezultat
@ -724,9 +715,6 @@ Countries
Types Types
== Tipovi == Tipovi
Select a name
== Izaberite ime
Please use a different name Please use a different name
== Izaberite drugo ime == Izaberite drugo ime
@ -905,9 +893,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== Omogući istaknuti zvuk dopisivanja == Omogući istaknuti zvuk dopisivanja
Threaded sound loading
== Učitavanje zvuka sa navojem
Map sound volume Map sound volume
== Jačina zvuka na mapi == Jačina zvuka na mapi
@ -962,8 +947,8 @@ Client message
Save the best demo of each race Save the best demo of each race
== Sačuvajte najbolji snimak svake trke == Sačuvajte najbolji snimak svake trke
Default length: %d Default length
== Podrazumevana dužina: %d == Podrazumevana dužina
Enable replays Enable replays
== Omogući ponovljene reprodukcije == Omogući ponovljene reprodukcije
@ -1007,9 +992,6 @@ Show other players' hook collision lines
Show other players' key presses Show other players' key presses
== Prikaži pritiske tastera drugih igrača == Prikaži pritiske tastera drugih igrača
Old mouse mode
== Stari mod miša
Show tiles layers from BG map Show tiles layers from BG map
== Prikaži slojeve pločica sa BG mape == Prikaži slojeve pločica sa BG mape
@ -1242,9 +1224,6 @@ CHN
Getting server list from master server Getting server list from master server
== Dobijam listu servera sa master servera == Dobijam listu servera sa master servera
Refreshing...
== Osvežavanje
Leak IP Leak IP
== Provali adresu == Provali adresu
@ -1281,13 +1260,6 @@ Chat command
Enable controller Enable controller
== Uključi kontroler == 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 Relative
== Relativno == Relativno
@ -1307,18 +1279,12 @@ UI controller sens.
Controller jitter tolerance Controller jitter tolerance
== Tolerancija kontrolera == Tolerancija kontrolera
Device
== Uređaj
Status Status
== Status == Status
Aim bind Aim bind
== Nišan == Nišan
Controller Axis #%d
== Stik %d.
Mouse Mouse
== Miš == Miš
@ -1358,9 +1324,6 @@ default
custom custom
== svoje == svoje
Graphics cards
== Grafička kartica
auto auto
== auto == auto
@ -1567,7 +1530,7 @@ Could not save downloaded map. Try manually deleting this file: %s
Initializing components Initializing components
== ==
Cancel A demo with this name already exists
== ==
File '%s' already exists, do you want to overwrite it? File '%s' already exists, do you want to overwrite it?
@ -1579,6 +1542,9 @@ transmits your player name to info.ddnet.org
Copy info Copy info
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -1631,10 +1597,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -1646,9 +1612,21 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts Toggle keyboard shortcuts
== ==
Export demo cut
==
Cut interval
==
Cut length
==
Open the directory that contains the demo files 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. No controller found. Plug in a controller.
== ==
Axis
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Graphics card
==
Weapons Weapons
== ==

View file

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

View file

@ -106,12 +106,6 @@ Clan
Client Client
== 客户端 == 客户端
Close
== 关闭
Connect
== 连接
Connecting to Connecting to
== 正在连接到 == 正在连接到
@ -301,9 +295,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== 启用聊天被提及消息提示音 == 启用聊天被提及消息提示音
Threaded sound loading
== 启用多线程音频加载
Name Name
== 名称 == 名称
@ -407,9 +398,6 @@ Rename demo
Reset filter Reset filter
== 重置筛选 == 重置筛选
Sample rate
== 采样率
Score Score
== 分数 == 分数
@ -811,9 +799,6 @@ Grabs
DDNet DDNet
== DDNet == DDNet
Select a name
== 另存为
Deaths Deaths
== 死亡数 == 死亡数
@ -823,9 +808,6 @@ Please use a different name
Restart Restart
== 重新开始 == 重新开始
Old mouse mode
== 旧版鼠标模式
Follow Follow
== 跟随 == 跟随
@ -1010,8 +992,8 @@ Show HUD
Hammerfly dummy Hammerfly dummy
== 分身 Hammerfly 开关 == 分身 Hammerfly 开关
Default length: %d Default length
== 默认时长: %d == 默认时长
Toggle ghost Toggle ghost
== 影子记录开关 == 影子记录开关
@ -1266,9 +1248,6 @@ Desktop fullscreen
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== 你确定要断开此服务器连接并进入其他服务器吗? == 你确定要断开此服务器连接并进入其他服务器吗?
Refreshing...
== 正在刷新...
Kill Messages Kill Messages
== 击杀消息 == 击杀消息
@ -1308,9 +1287,6 @@ default
custom custom
== 自定义 == 自定义
Graphics cards
== 显卡
auto auto
== 自动 == 自动
@ -1377,13 +1353,6 @@ Download community skins
Enable controller Enable controller
== 启用控制器 == 启用控制器
Controller %d: %s
== 控制器 %d: %s
Click to cycle through all available controllers.
== 点击以切换其他控制器
[Ingame controller mode]
Relative Relative
== 相对 == 相对
@ -1403,18 +1372,12 @@ UI controller sens.
Controller jitter tolerance Controller jitter tolerance
== 摇杆死区 == 摇杆死区
Device
== 输入设备
Status Status
== 状态 == 状态
Aim bind Aim bind
== 操作轴绑定 == 操作轴绑定
Controller Axis #%d
== 摇杆 #%d
Mouse Mouse
== 鼠标 == 鼠标
@ -1574,12 +1537,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== 加快播放速度 == 加快播放速度
Mark the beginning of a cut
== 标记裁剪起点
Mark the end of a cut
== 标记裁剪终点
Export cut as a separate demo Export cut as a separate demo
== 另存为新回放文件 == 另存为新回放文件
@ -1753,3 +1710,33 @@ None
Add Clan 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 Client
== Klient == Klient
Close
== Zavrieť
Connect
== Pripojiť
Connecting to Connecting to
== Pripojujem sa k == Pripojujem sa k
@ -347,9 +341,6 @@ Rename demo
Reset filter Reset filter
== Obnoviť filter == Obnoviť filter
Sample rate
== Sample rate
Score Score
== Skóre == 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 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? File '%s' already exists, do you want to overwrite it?
@ -834,9 +825,6 @@ Exclude
%d player %d player
== ==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== ==
@ -861,6 +849,9 @@ Copy info
Leak IP Leak IP
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -892,18 +883,6 @@ Are you sure that you want to remove the clan '%s' from your friends list?
Add Clan 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 Play the current demo
== ==
@ -925,10 +904,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -940,9 +919,30 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts 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 Loading demo files
== ==
@ -1162,10 +1162,10 @@ Chat command
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1176,9 +1176,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1191,7 +1188,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1200,9 +1197,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1212,15 +1206,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Dummy Dummy
== ==
@ -1236,10 +1230,10 @@ Windowed fullscreen
Desktop fullscreen Desktop fullscreen
== ==
may cause delay Screen
== ==
Screen may cause delay
== ==
Allows maps to render with more detail Allows maps to render with more detail
@ -1257,7 +1251,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto
@ -1284,9 +1278,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== ==
Threaded sound loading
==
Game sound volume Game sound volume
== ==
@ -1488,7 +1479,7 @@ Save the best demo of each race
Enable replays Enable replays
== ==
Default length: %d Default length
== ==
When you cross the start line, show a ghost tee replicating the movements of your best time When you cross the start line, show a ghost tee replicating the movements of your best time
@ -1506,10 +1497,10 @@ Gameplay
Overlay entities Overlay entities
== ==
Size Show text entities
== ==
Show text entities Size
== ==
Opacity Opacity
@ -1542,9 +1533,6 @@ AntiPing: predict weapons
AntiPing: predict grenade paths AntiPing: predict grenade paths
== ==
Old mouse mode
==
Background Background
== ==

View file

@ -94,12 +94,6 @@ Clan
Client Client
== Cliente == Cliente
Close
== Cerrar
Connect
== Conectar
Connecting to Connecting to
== Conectando con == Conectando con
@ -368,9 +362,6 @@ Rename demo
Reset filter Reset filter
== Resetear filtro == Resetear filtro
Sample rate
== Frecuencia de muestreo
Score Score
== Puntos == Puntos
@ -718,9 +709,6 @@ Update now
Restart Restart
== Reiniciar == Reiniciar
Select a name
== Selecciona un nombre
Please use a different name Please use a different name
== Por favor usa un nombre diferente == Por favor usa un nombre diferente
@ -889,9 +877,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== Habilitar sonido de chat resaltado == Habilitar sonido de chat resaltado
Threaded sound loading
== Carga de sonido en un hilo
Map sound volume Map sound volume
== Vol. del sonido del mapa == Vol. del sonido del mapa
@ -943,8 +928,8 @@ Normal message
Save the best demo of each race Save the best demo of each race
== Guardar la mejor demo de cada carrera == Guardar la mejor demo de cada carrera
Default length: %d Default length
== Longitud predeterminada: %d == Longitud predeterminada
Enable replays Enable replays
== Habilitar repeticiones == Habilitar repeticiones
@ -991,9 +976,6 @@ Show other players' hook collision lines
Show other players' key presses Show other players' key presses
== Mostrar las pulsaciones de teclas de otros jugadores == Mostrar las pulsaciones de teclas de otros jugadores
Old mouse mode
== Modo de mouse viejo
Show tiles layers from BG map Show tiles layers from BG map
== Mostrar capas de tiles del mapa de fondo == 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? Are you sure that you want to disconnect and switch to a different server?
== ¿Seguro que quieres desconectarte y cambiar de servidor? == ¿Seguro que quieres desconectarte y cambiar de servidor?
Refreshing...
== Actualizando...
Kill Messages Kill Messages
== Mensajes de Muerte == Mensajes de Muerte
@ -1292,9 +1271,6 @@ default
custom custom
== personalizado == personalizado
Graphics cards
== Tarjetas de video
auto auto
== auto. == auto.
@ -1358,13 +1334,6 @@ Download community skins
Enable controller Enable controller
== Habilitar mando == 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 Relative
== Relativo == Relativo
@ -1384,18 +1353,12 @@ UI controller sens.
Controller jitter tolerance Controller jitter tolerance
== Tolerancia a la fluctuación del mando == Tolerancia a la fluctuación del mando
Device
== Dispositivo
Status Status
== Estado == Estado
Aim bind Aim bind
== Apuntar == Apuntar
Controller Axis #%d
== Eje #%d del mando
Mouse Mouse
== Ratón == Ratón
@ -1489,12 +1452,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== Acelerar la 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 Export cut as a separate demo
== Exportar corte como una demo diferente == Exportar corte como una demo diferente
@ -1737,3 +1694,33 @@ None
Add Clan Add Clan
== Agregar 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 Client
== Klient == Klient
Close
== Stäng
Connect
== Anslut
Connecting to Connecting to
== Ansluter till == Ansluter till
@ -351,9 +345,6 @@ Rename demo
Reset filter Reset filter
== Återställ filter == Återställ filter
Sample rate
== Samplingsfrekvens
Score Score
== Poäng == Poäng
@ -597,9 +588,6 @@ Vanilla skins only
New random timeout code New random timeout code
== Ny slumpad timeout kod == Ny slumpad timeout kod
Select a name
== Välj ett namn
Enable long pain sound (used when shooting in freeze) Enable long pain sound (used when shooting in freeze)
== Aktivera ett långt ont ljud (använt vid sjutning i freeze) == Aktivera ett långt ont ljud (använt vid sjutning i freeze)
@ -663,8 +651,8 @@ Save ghost
Browser Browser
== Bläddraren == Bläddraren
Default length: %d Default length
== Standard längd: %d == Standard längd
Switch weapon when out of ammo Switch weapon when out of ammo
== Byt vapen vid slut av ammunition == Byt vapen vid slut av ammunition
@ -744,9 +732,6 @@ Use high DPI
may cause delay may cause delay
== kan orsaka fördröjning == kan orsaka fördröjning
Threaded sound loading
== Threaded ljud laddning
AntiPing AntiPing
== AntiPing == AntiPing
@ -975,9 +960,6 @@ Automatically take statboard screenshot
Automatically create statboard csv Automatically create statboard csv
== Automatiskt skapa poänglista csv == Automatiskt skapa poänglista csv
Old mouse mode
== Gammal mus metod
Enable regular chat sound Enable regular chat sound
== Aktivera vanligt chatt ljud == Aktivera vanligt chatt ljud
@ -1153,9 +1135,6 @@ CHN
Getting server list from master server Getting server list from master server
== Hämtar server lista från master server == Hämtar server lista från master server
Refreshing...
== Ladder om...
Leak IP Leak IP
== Läck IP == Läck IP
@ -1359,7 +1338,7 @@ Getting game info
Requesting to join the game Requesting to join the game
== ==
Cancel A demo with this name already exists
== ==
File '%s' already exists, do you want to overwrite it? File '%s' already exists, do you want to overwrite it?
@ -1377,6 +1356,9 @@ Loading menu images
Copy info Copy info
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -1429,10 +1411,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -1444,9 +1426,21 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts Toggle keyboard shortcuts
== ==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files Loading demo files
== ==
@ -1498,10 +1492,10 @@ Open the directory to add custom skins
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1512,9 +1506,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1527,7 +1518,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1536,9 +1527,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1548,15 +1536,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Allows maps to render with more detail Allows maps to render with more detail
== ==
@ -1569,7 +1557,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto

View file

@ -21,6 +21,7 @@
# 2022-12-11 cheeser0613 # 2022-12-11 cheeser0613
# 2023-01-11 cheeser0613 # 2023-01-11 cheeser0613
# 2023-04-01 cheeser0613 # 2023-04-01 cheeser0613
# 2023-05-25 cheeser0613
##### /authors ##### ##### /authors #####
##### translated strings ##### ##### translated strings #####
@ -94,12 +95,6 @@ Clan
Client Client
== 客戶端 == 客戶端
Close
== 關閉
Connect
== 連線
Connecting to Connecting to
== 正在連線到 == 正在連線到
@ -289,9 +284,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== 啟用被提及時的提示音 == 啟用被提及時的提示音
Threaded sound loading
== 啟用多執行緒音訊載入
Name Name
== 名稱 == 名稱
@ -395,9 +387,6 @@ Rename demo
Reset filter Reset filter
== 重置過濾器 == 重置過濾器
Sample rate
== 取樣率
Score Score
== 分數 == 分數
@ -585,7 +574,7 @@ Join game
== 加入遊戲 == 加入遊戲
FSAA samples FSAA samples
== 全屏抗鋸齒(FSAA)取樣倍數 == 全屏抗鋸齒 (FSAA) 取樣倍數
Sound volume Sound volume
== 音量 == 音量
@ -799,9 +788,6 @@ Grabs
DDNet DDNet
== DDNet == DDNet
Select a name
== 另存為
Deaths Deaths
== 死亡數 == 死亡數
@ -811,9 +797,6 @@ Please use a different name
Restart Restart
== 重新開始 == 重新開始
Old mouse mode
== 舊版滑鼠模式
Follow Follow
== 跟隨 == 跟隨
@ -998,8 +981,8 @@ Show HUD
Hammerfly dummy Hammerfly dummy
== 分身Hammerfly開關 == 分身Hammerfly開關
Default length: %d Default length
== 預設長度: %d == 預設長度
Toggle ghost Toggle ghost
== 影子記錄開關 == 影子記錄開關
@ -1254,9 +1237,6 @@ https://ddnet.org/discord
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== 你確定要中斷此伺服器并嘗試加入其他伺服器嗎? == 你確定要中斷此伺服器并嘗試加入其他伺服器嗎?
Refreshing...
== 正在重整...
Kill Messages Kill Messages
== 擊殺訊息 == 擊殺訊息
@ -1296,9 +1276,6 @@ default
custom custom
== 自定義 == 自定義
Graphics cards
== 顯示卡
auto auto
== 自動 == 自動
@ -1365,13 +1342,6 @@ Download community skins
Enable controller Enable controller
== 啓用控制器 == 啓用控制器
Controller %d: %s
== 控制器 %d: %s
Click to cycle through all available controllers.
== 點擊以切換其他控制器
[Ingame controller mode]
Relative Relative
== 相對 == 相對
@ -1383,34 +1353,28 @@ Ingame controller mode
== 游戲内控制器瞄準模式 == 游戲内控制器瞄準模式
Ingame controller sens. Ingame controller sens.
== 搖桿靈敏度(游戲) == 搖桿靈敏度 (游戲)
UI controller sens. UI controller sens.
== 搖桿靈敏度(界面) == 搖桿靈敏度 (界面)
Controller jitter tolerance Controller jitter tolerance
== 搖桿錯位容錯 == 搖桿錯位容錯
Device
== 輸入設備
Status Status
== 狀態 == 狀態
Aim bind Aim bind
== 操作軸綁定 == 操作軸綁定
Controller Axis #%d
== 搖桿 #%d
Mouse Mouse
== 滑鼠 == 滑鼠
Ingame mouse sens. Ingame mouse sens.
== 滑鼠靈敏度(游戲) == 滑鼠靈敏度 (游戲)
UI mouse sens. UI mouse sens.
== 滑鼠靈敏度(界面) == 滑鼠靈敏度 (界面)
Controller Controller
== 控制器 == 控制器
@ -1503,7 +1467,7 @@ DDRace HUD
== DDRace HUD == DDRace HUD
Show client IDs in scoreboard Show client IDs in scoreboard
== 顯示客戶端 IDs (計分板中) == 顯示客戶端 IDs (計分板中)
Show DDRace HUD Show DDRace HUD
== 顯示 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: 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 Your movements are not taken into account when calculating the line colors
== 移動所造成的瞄準偏移將不計入考量 == 移動所造成的瞄準偏移將不計入考量
@ -1562,12 +1526,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== 加快播放速度 == 加快播放速度
Mark the beginning of a cut
== 標記裁剪起點
Mark the end of a cut
== 標記裁剪終點
Export cut as a separate demo 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] [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. 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] [Graphics error]
Out of VRAM. Try removing custom assets (skins, entities, etc.), especially those with high resolution. Out of VRAM. Try removing custom assets (skins, entities, etc.), especially those with high resolution.
== 顯存不足。請嘗試移除自定義材質(如外觀,實體層等等),尤其高分辨率的自定義材質。 == 顯存不足。請嘗試移除自定義材質 (如外觀,實體層等等),尤其高分辨率的自定義材質。
[Graphics error] [Graphics error]
An error during command recording occurred. Try to update your GPU drivers. 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] [Graphics error]
Unknown error. Try to change gfx_backend to OpenGL or Vulkan in settings_ddnet.cfg in the config directory and try again. 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] [Graphics error]
Could not initialize the given graphics backend, reverting to the default backend now. 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) Save power by lowering refresh rate (higher input latency)
== 節能模式(限制幀率上限以降低功耗但也將提高輸入延遲) == 節能模式 (限制幀率上限以降低功耗但也將提高輸入延遲)
Open the settings file 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 themes
== 打開用以添加自定義主題的資料夾路徑 == 打開用以新增自定義主題的資料夾路徑
Open the directory to add custom skins Open the directory to add custom skins
== 打開用以添加自定義外觀的資料夾路徑 == 打開用以新增自定義外觀的資料夾路徑
No controller found. Plug in a controller. No controller found. Plug in a controller.
== 未檢測到任何控制器。請嘗試重新連接控制器。 == 未檢測到任何控制器。請嘗試重新連接控制器。
@ -1702,7 +1660,7 @@ Unregister protocol and file extensions
== 未注冊的協議與擴充檔案 == 未注冊的協議與擴充檔案
Open the directory to add custom assets Open the directory to add custom assets
== 打開用以添加自定義材質的資料夾路徑 == 打開用以新增自定義材質的資料夾路徑
[Graphics error] [Graphics error]
Could not initialize the given graphics backend, this is probably because you didn't install the driver of the integrated graphics card. 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) Online players (%d)
== == 在綫玩家 (%d)
Online clanmates (%d) Online clanmates (%d)
== == 在綫戰隊隊友 (%d)
[friends (server browser)] [friends (server browser)]
Offline (%d) Offline (%d)
== == 離綫(%d
Click to select server. Double click to join your friend. Click to select server. Double click to join your friend.
== == 點擊以選擇伺服器,雙擊以直接加入好友所在伺服器
Click to remove this player from your friends list. Click to remove this player from your friends list.
== == 點擊以將此好友從好友列表中移除
Click to remove this clan from your friends list. Click to remove this clan from your friends list.
== == 點擊以將此戰隊從好友列表中移除
None None
== ==
Add Clan 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 Client
== İstemci == İstemci
Close
== Kapat
Connect
== Bağlan
Connecting to Connecting to
== Bağlanılıyor == Bağlanılıyor
@ -349,9 +343,6 @@ Rename demo
Reset filter Reset filter
== Filtreleri sıfırla == Filtreleri sıfırla
Sample rate
== Örnekleme hızı
Score Score
== Skor == Skor
@ -705,9 +696,6 @@ Update now
Restart Restart
== Yeniden başlat == Yeniden başlat
Select a name
== Takma ad seç
Please use a different name Please use a different name
== Lütfen farklı takma ad kullanın == Lütfen farklı takma ad kullanın
@ -879,9 +867,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== Vurgulanmış mesaj sesini etkinleştir == Vurgulanmış mesaj sesini etkinleştir
Threaded sound loading
== Threaded ses yükleme
Map sound volume Map sound volume
== Harita ses seviyesi == Harita ses seviyesi
@ -936,8 +921,8 @@ Client message
Save the best demo of each race Save the best demo of each race
== Her yarış için en iyi demoyu kaydet == Her yarış için en iyi demoyu kaydet
Default length: %d Default length
== Uzunluk: %d == Uzunluk
Enable replays Enable replays
== Tekrar oynatmaları etkinleştir == Tekrar oynatmaları etkinleştir
@ -984,9 +969,6 @@ Show other players' hook collision lines
Show other players' key presses Show other players' key presses
== Diğer oyuncuların tuş basışlarını göster == Diğer oyuncuların tuş basışlarını göster
Old mouse mode
== Eski mouse modu
Show tiles layers from BG map Show tiles layers from BG map
== Yapı katmanlarını göster == 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 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? File '%s' already exists, do you want to overwrite it?
@ -1241,9 +1223,6 @@ Getting server list from master server
%d player %d player
== ==
Refreshing...
==
Are you sure that you want to disconnect and switch to a different server? Are you sure that you want to disconnect and switch to a different server?
== ==
@ -1253,6 +1232,9 @@ Copy info
Leak IP Leak IP
== ==
No server selected
==
Online players (%d) Online players (%d)
== ==
@ -1305,10 +1287,10 @@ Slow down the demo
Speed up 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 Export cut as a separate demo
@ -1320,9 +1302,21 @@ Go back one marker
Go forward one marker Go forward one marker
== ==
Close the demo player
==
Toggle keyboard shortcuts Toggle keyboard shortcuts
== ==
Export demo cut
==
Cut interval
==
Cut length
==
Loading demo files Loading demo files
== ==
@ -1404,10 +1398,10 @@ Chat command
Enable controller Enable controller
== ==
Controller %d: %s Controller
== ==
Click to cycle through all available controllers. Ingame controller mode
== ==
[Ingame controller mode] [Ingame controller mode]
@ -1418,9 +1412,6 @@ Relative
Absolute Absolute
== ==
Ingame controller mode
==
Ingame controller sens. Ingame controller sens.
== ==
@ -1433,7 +1424,7 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== ==
Device Axis
== ==
Status Status
@ -1442,9 +1433,6 @@ Status
Aim bind Aim bind
== ==
Controller Axis #%d
==
Mouse Mouse
== ==
@ -1454,15 +1442,15 @@ Ingame mouse sens.
UI mouse sens. UI mouse sens.
== ==
Controller
==
Reset controls Reset controls
== ==
Are you sure that you want to reset the controls to their defaults? Are you sure that you want to reset the controls to their defaults?
== ==
Cancel
==
Dummy Dummy
== ==
@ -1490,7 +1478,7 @@ default
custom custom
== ==
Graphics cards Graphics card
== ==
auto auto

View file

@ -37,12 +37,6 @@ Call vote
Chat Chat
== Чат == Чат
Close
== Зачинити
Connect
== Під’єднатись
Connecting to Connecting to
== Підключення до == Підключення до
@ -182,7 +176,7 @@ Movement
== Переміщення == Переміщення
Mute when not active Mute when not active
== Глушити звуки, коли гра неактивна == Відключити звуки, коли гра неактивна
Name Name
== Ім'я == Ім'я
@ -215,7 +209,7 @@ Password
== Пароль == Пароль
Password incorrect Password incorrect
== неправильний пароль == Неправильний пароль
Ping Ping
== Пінг == Пінг
@ -234,7 +228,7 @@ Players
== Гравці == Гравці
Please balance teams! Please balance teams!
== Збалансуйте команди! == Будь ласка збалансуйте команди!
Prev. weapon Prev. weapon
== Попер. зброя == Попер. зброя
@ -260,9 +254,6 @@ Remote console
Reset filter Reset filter
== Скинути фільтри == Скинути фільтри
Sample rate
== Частота
Score Score
== бали == бали
@ -306,10 +297,10 @@ Stop record
== Зупинити запис == Зупинити запис
Sudden Death Sudden Death
== Швидка смерть == Раптова смерть
Switch weapon on pickup Switch weapon on pickup
== Перемикати зброю при підборі == Взяти в руку підібравшу зброю
Team Team
== Команда == Команда
@ -336,7 +327,7 @@ Use sounds
== Використовувати звуки == Використовувати звуки
V-Sync V-Sync
== V-Sync == Вертикальна синхронізація (V-Sync)
Version Version
== Версія == Версія
@ -485,7 +476,7 @@ Disconnect Dummy
== Відключити Dummy == Відключити Dummy
Are you sure that you want to disconnect your dummy? Are you sure that you want to disconnect your dummy?
== Ви впевнені, що хочете відключити свого Dummy? == Ви впевнені, що хочете відключити свого даммі?
Welcome to DDNet Welcome to DDNet
== Ласкаво просимо в DDNet == Ласкаво просимо в DDNet
@ -530,10 +521,10 @@ Video name:
== Назва відео == Назва відео
Show DDNet map finishes in server browser Show DDNet map finishes in server browser
== Показувати завершені карти DDNet в браузері сервера == Показувати пройдені карти DDNet в браузері сервера
transmits your player name to info.ddnet.org transmits your player name to info.ddnet.org
== передає Ваш нікнейм на info.ddnet.org == передає ваш нікнейм на info.ddnet.org
Search Search
== Пошук == Пошук
@ -604,9 +595,6 @@ Update now
Restart Restart
== Перезавантажити == Перезавантажити
Select a name
== Оберіть ім'я
Please use a different name Please use a different name
== Будь ласка, використовуйте інше ім’я == Будь ласка, використовуйте інше ім’я
@ -779,10 +767,10 @@ Kill
== Самогубство == Самогубство
Zoom in Zoom in
== Збільшити == Приблизити камеру
Zoom out Zoom out
== Зменшити == Віддалити камеру
Default zoom Default zoom
== Стандартний масштаб == Стандартний масштаб
@ -800,7 +788,7 @@ Toggle dummy
== Переключити Даммі == Переключити Даммі
Toggle ghost Toggle ghost
== Переключити примару == Переключити тінь
Dummy copy Dummy copy
== Повторення рухів Даммі == Повторення рухів Даммі
@ -865,9 +853,6 @@ Enable team chat sound
Enable highlighted chat sound Enable highlighted chat sound
== Включити звуки виділених повідомлень == Включити звуки виділених повідомлень
Threaded sound loading
== музика при завантаженні
Map sound volume Map sound volume
== Гучність звуку на карті == Гучність звуку на карті
@ -893,7 +878,7 @@ Show kill messages
== Показувати список вбивств == Показувати список вбивств
Show votes window after voting Show votes window after voting
== Показувати голосування після вашого голосу == Відображати вікно голосування після вашого голосу
Messages Messages
== Повідомлення == Повідомлення
@ -922,8 +907,8 @@ Client message
Save the best demo of each race Save the best demo of each race
== Зберігати краще демо кожної гонки == Зберігати краще демо кожної гонки
Default length: %d Default length
== Стандартна довжина: %d == Стандартна довжина
Enable replays Enable replays
== Включити повтори == Включити повтори
@ -947,7 +932,7 @@ Show text entities
== Текстові текстури == Текстові текстури
Show others (own team only) Show others (own team only)
== Завжди показувати тільки вашу команду == Показати інших гравців (Лише для комманди)
Show quads Show quads
== Показувати quads == Показувати quads
@ -970,9 +955,6 @@ Show other players' hook collision lines
Show other players' key presses Show other players' key presses
== Показувати натискання кнопок інших гравців == Показувати натискання кнопок інших гравців
Old mouse mode
== Режим старої мишки
Show tiles layers from BG map Show tiles layers from BG map
== Показувати шари з тайлами з фонової карти == Показувати шари з тайлами з фонової карти
@ -980,7 +962,7 @@ DDNet %s is available:
== Доступний новий DDNet %s: == Доступний новий DDNet %s:
Updating... Updating...
== Оновлення ... == Оновлення...
No updates available No updates available
== Немає доступних оновлень == Немає доступних оновлень
@ -1049,7 +1031,7 @@ Replay
== Повтор == Повтор
Saving ddnet-settings.cfg failed 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. 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, що може викликати візуальні помилки == Ширина або висота текстури %s не поділяється на %d, що може викликати візуальні помилки
@ -1117,9 +1099,6 @@ Getting server list from master server
%d player %d player
== %d Гравець == %d Гравець
Refreshing...
== Оновлення...
Leak IP Leak IP
== Стійке IP == Стійке IP
@ -1157,7 +1136,7 @@ Windowed
== Віконний == Віконний
Windowed borderless Windowed borderless
== Віконний без меж == Віконний без рамок
Desktop fullscreen Desktop fullscreen
== Повний робочий стіл == Повний робочий стіл
@ -1316,7 +1295,7 @@ Speed:
== Швидкість: == Швидкість:
Angle: Angle:
== Кут == Кут:
Team %d Team %d
== Команда %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, проксі або мережеві прискорювачі. == Здається, що IP-адреси UDP і TCP відрізняються. Спробуйте вимкнути VPN, проксі або мережеві прискорювачі.
No answer from server yet. No answer from server yet.
== Сервер ще не відповів == Сервер ще не відповів...
Getting game info 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. Click to remove this clan from your friends list.
== Натисніть, щоб видалити цей клан зі свого списку друзів. == Натисніть, щоб видалити цей клан зі свого списку.
None None
== Нічого == Нічого
@ -1412,12 +1391,6 @@ Slow down the demo
Speed up the demo Speed up the demo
== Прискорити димо == Прискорити димо
Mark the beginning of a cut
== Позначити початок вирізу
Mark the end of a cut
== Позначити кінець вирізу
Export cut as a separate demo 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 Open the directory to add custom themes
== Відкрити каталог, щоб додати власні теми == Відкрити каталог, щоб додати власні фони
Loading skin files Loading skin files
== Завантаження файлів скінів == Завантаження файлів скінів
@ -1487,13 +1460,6 @@ Open the directory to add custom skins
Enable controller Enable controller
== Увімкнути контролер == Увімкнути контролер
Controller %d: %s
== Контролер %d: %s
Click to cycle through all available controllers.
== Натисніть, щоб переглянути всі активні контролери.
[Ingame controller mode]
Relative Relative
== Relative == Relative
@ -1516,18 +1482,12 @@ Controller jitter tolerance
No controller found. Plug in a controller. No controller found. Plug in a controller.
== Контролер не знайдено. Підключіть контролер. == Контролер не знайдено. Підключіть контролер.
Device
== Пристрій
Status Status
== Стан == Стан
Aim bind Aim bind
== Прив'язка до цілі == Прив'язка до цілі
Controller Axis #%d
== Ось контролера #%d
Mouse Mouse
== Мишка == Мишка
@ -1561,9 +1521,6 @@ default
custom custom
== користувацькі == користувацькі
Graphics cards
== Відеокарти
auto auto
== авто == авто
@ -1646,34 +1603,34 @@ Weapons
== Зброя == Зброя
Rifle Laser Outline Color Rifle Laser Outline Color
== Колір контуру лазера == Колір лазера
Rifle Laser Inner Color Rifle Laser Inner Color
== Внутрішній колір лазера == Колір обводки лазера
Shotgun Laser Outline Color Shotgun Laser Outline Color
== Колір контуру дробовика == Колір лазера дробовика
Shotgun Laser Inner Color Shotgun Laser Inner Color
== Внутрішній колір дробовика == Колір обводки лазера дробовика
Door Laser Outline Color Door Laser Outline Color
== Колір контуру дверей == Колір лазера-дверей
Door Laser Inner Color Door Laser Inner Color
== Внутрішній колір дверей == Колір обводки лазера-дверей
Freeze Laser Outline Color Freeze Laser Outline Color
== Колір контуру фріз-лазерів == Колір фріз-лазера
Freeze Laser Inner Color Freeze Laser Inner Color
== Внутрішній колір фріз-дверей == Колір обводки фріз-лазера
Set all to Rifle Set all to Rifle
== Поставити все на колір зброї == Всі кольори на колір лезера
When you cross the start line, show a ghost tee replicating the movements of your best time When you cross the start line, show a ghost tee replicating the movements of your best time
== При перетинанні лінію старту, відображати tee-привида, який буде повторювати рухи свого найкращого часу == При перетинанні лінію старту, відображати tee-привида, який буде повторювати рухи вашого найкращого часу
Opacity Opacity
== Непрозорість == Непрозорість
@ -1719,3 +1676,33 @@ Super
Loading sound files 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 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 This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -25,8 +25,8 @@
* Defines keyboard scancodes. * Defines keyboard scancodes.
*/ */
#ifndef _SDL_scancode_h #ifndef SDL_scancode_h_
#define _SDL_scancode_h #define SDL_scancode_h_
#include "SDL_stdinc.h" #include "SDL_stdinc.h"
@ -38,7 +38,7 @@
* SDL_Event structure. * SDL_Event structure.
* *
* The values in this enumeration are based on the USB usage page standard: * 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 typedef enum
{ {
@ -225,16 +225,16 @@ typedef enum
SDL_SCANCODE_F23 = 114, SDL_SCANCODE_F23 = 114,
SDL_SCANCODE_F24 = 115, SDL_SCANCODE_F24 = 115,
SDL_SCANCODE_EXECUTE = 116, SDL_SCANCODE_EXECUTE = 116,
SDL_SCANCODE_HELP = 117, SDL_SCANCODE_HELP = 117, /**< AL Integrated Help Center */
SDL_SCANCODE_MENU = 118, SDL_SCANCODE_MENU = 118, /**< Menu (show menu) */
SDL_SCANCODE_SELECT = 119, SDL_SCANCODE_SELECT = 119,
SDL_SCANCODE_STOP = 120, SDL_SCANCODE_STOP = 120, /**< AC Stop */
SDL_SCANCODE_AGAIN = 121, /**< redo */ SDL_SCANCODE_AGAIN = 121, /**< AC Redo/Repeat */
SDL_SCANCODE_UNDO = 122, SDL_SCANCODE_UNDO = 122, /**< AC Undo */
SDL_SCANCODE_CUT = 123, SDL_SCANCODE_CUT = 123, /**< AC Cut */
SDL_SCANCODE_COPY = 124, SDL_SCANCODE_COPY = 124, /**< AC Copy */
SDL_SCANCODE_PASTE = 125, SDL_SCANCODE_PASTE = 125, /**< AC Paste */
SDL_SCANCODE_FIND = 126, SDL_SCANCODE_FIND = 126, /**< AC Find */
SDL_SCANCODE_MUTE = 127, SDL_SCANCODE_MUTE = 127,
SDL_SCANCODE_VOLUMEUP = 128, SDL_SCANCODE_VOLUMEUP = 128,
SDL_SCANCODE_VOLUMEDOWN = 129, SDL_SCANCODE_VOLUMEDOWN = 129,
@ -265,9 +265,9 @@ typedef enum
SDL_SCANCODE_LANG8 = 151, /**< reserved */ SDL_SCANCODE_LANG8 = 151, /**< reserved */
SDL_SCANCODE_LANG9 = 152, /**< reserved */ SDL_SCANCODE_LANG9 = 152, /**< reserved */
SDL_SCANCODE_ALTERASE = 153, /**< Erase-Eaze */ SDL_SCANCODE_ALTERASE = 153, /**< Erase-Eaze */
SDL_SCANCODE_SYSREQ = 154, SDL_SCANCODE_SYSREQ = 154,
SDL_SCANCODE_CANCEL = 155, SDL_SCANCODE_CANCEL = 155, /**< AC Cancel */
SDL_SCANCODE_CLEAR = 156, SDL_SCANCODE_CLEAR = 156,
SDL_SCANCODE_PRIOR = 157, SDL_SCANCODE_PRIOR = 157,
SDL_SCANCODE_RETURN2 = 158, SDL_SCANCODE_RETURN2 = 158,
@ -345,6 +345,11 @@ typedef enum
* \name Usage page 0x0C * \name Usage page 0x0C
* *
* These values are mapped from usage page 0x0C (USB consumer page). * 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_AUDIOPLAY = 261,
SDL_SCANCODE_AUDIOMUTE = 262, SDL_SCANCODE_AUDIOMUTE = 262,
SDL_SCANCODE_MEDIASELECT = 263, SDL_SCANCODE_MEDIASELECT = 263,
SDL_SCANCODE_WWW = 264, SDL_SCANCODE_WWW = 264, /**< AL Internet Browser */
SDL_SCANCODE_MAIL = 265, SDL_SCANCODE_MAIL = 265,
SDL_SCANCODE_CALCULATOR = 266, SDL_SCANCODE_CALCULATOR = 266, /**< AL Calculator */
SDL_SCANCODE_COMPUTER = 267, SDL_SCANCODE_COMPUTER = 267,
SDL_SCANCODE_AC_SEARCH = 268, SDL_SCANCODE_AC_SEARCH = 268, /**< AC Search */
SDL_SCANCODE_AC_HOME = 269, SDL_SCANCODE_AC_HOME = 269, /**< AC Home */
SDL_SCANCODE_AC_BACK = 270, SDL_SCANCODE_AC_BACK = 270, /**< AC Back */
SDL_SCANCODE_AC_FORWARD = 271, SDL_SCANCODE_AC_FORWARD = 271, /**< AC Forward */
SDL_SCANCODE_AC_STOP = 272, SDL_SCANCODE_AC_STOP = 272, /**< AC Stop */
SDL_SCANCODE_AC_REFRESH = 273, SDL_SCANCODE_AC_REFRESH = 273, /**< AC Refresh */
SDL_SCANCODE_AC_BOOKMARKS = 274, SDL_SCANCODE_AC_BOOKMARKS = 274, /**< AC Bookmarks */
/* @} *//* Usage page 0x0C */ /* @} *//* Usage page 0x0C */
@ -383,19 +388,51 @@ typedef enum
SDL_SCANCODE_KBDILLUMDOWN = 279, SDL_SCANCODE_KBDILLUMDOWN = 279,
SDL_SCANCODE_KBDILLUMUP = 280, SDL_SCANCODE_KBDILLUMUP = 280,
SDL_SCANCODE_EJECT = 281, SDL_SCANCODE_EJECT = 281,
SDL_SCANCODE_SLEEP = 282, SDL_SCANCODE_SLEEP = 282, /**< SC System Sleep */
SDL_SCANCODE_APP1 = 283, SDL_SCANCODE_APP1 = 283,
SDL_SCANCODE_APP2 = 284, SDL_SCANCODE_APP2 = 284,
/* @} *//* Walther keys */ /* @} *//* 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. */ /* Add any other keys here. */
SDL_NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes SDL_NUM_SCANCODES = 512 /**< not a key, just marks the number of scancodes
for array bounds */ for array bounds */
} SDL_Scancode; } SDL_Scancode;
#endif /* _SDL_scancode_h */ #endif /* SDL_scancode_h_ */
/* vi: set ts=4 sw=4 expandtab: */ /* 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; player_name client1;
cl_download_skins 0; cl_download_skins 0;
gfx_fullscreen 0; gfx_fullscreen 0;
snd_enable 0;
logfile client1.log; logfile client1.log;
$client_args $client_args
connect localhost:$port" > stdout_client1.txt 2> stderr_client1.txt || fail client1 "$?" & connect localhost:$port" > stdout_client1.txt 2> stderr_client1.txt || fail client1 "$?" &
if [ "$arg_valgrind_memcheck" == "1" ]; then if [ "$arg_valgrind_memcheck" == "1" ]; then
wait_for_fifo client1.fifo 120 wait_for_fifo client1.fifo 180
sleep 20 sleep 20
else else
wait_for_fifo client1.fifo 50 wait_for_fifo client1.fifo 50
@ -198,12 +199,13 @@ $tool ../DDNet \
player_name client2; player_name client2;
cl_download_skins 0; cl_download_skins 0;
gfx_fullscreen 0; gfx_fullscreen 0;
snd_enable 0;
logfile client2.log; logfile client2.log;
$client_args $client_args
connect localhost:$port" > stdout_client2.txt 2> stderr_client2.txt || fail client2 "$?" & connect localhost:$port" > stdout_client2.txt 2> stderr_client2.txt || fail client2 "$?" &
if [ "$arg_valgrind_memcheck" == "1" ]; then if [ "$arg_valgrind_memcheck" == "1" ]; then
wait_for_fifo client2.fifo 120 wait_for_fifo client2.fifo 180
sleep 20 sleep 20
else else
wait_for_fifo client2.fifo 50 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/math.h>
#include <base/vmath.h> #include <base/vmath.h>
#include <optional>
/* /*
Title: Color handling 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); 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 WithAlpha(float alpha) const
{ {
DerivedT col(static_cast<const DerivedT &>(*this)); DerivedT col(static_cast<const DerivedT &>(*this));
col.a = alpha; col.a = alpha;
return col; 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> class ColorHSLA : public color4_base<ColorHSLA>
@ -228,14 +258,14 @@ template<>
inline ColorHSLA color_cast(const ColorHSVA &hsv) inline ColorHSLA color_cast(const ColorHSVA &hsv)
{ {
float l = hsv.v * (1 - hsv.s * 0.5f); 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<> template<>
inline ColorHSVA color_cast(const ColorHSLA &hsl) inline ColorHSVA color_cast(const ColorHSLA &hsl)
{ {
float v = hsl.l + hsl.s * minimum(hsl.l, 1 - hsl.l); 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<> 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); 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 #endif

View file

@ -833,12 +833,12 @@ void thread_detach(void *thread)
#endif #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); void *thread = thread_init(threadfunc, u, name);
if(thread) if(thread)
thread_detach(thread); thread_detach(thread);
return thread; return thread != nullptr;
} }
#if defined(CONF_FAMILY_UNIX) #if defined(CONF_FAMILY_UNIX)
@ -2396,6 +2396,39 @@ char *fs_getcwd(char *buffer, int buffer_size)
#endif #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) int fs_parent_dir(char *path)
{ {
char *parent = 0; char *parent = 0;
@ -3430,10 +3463,41 @@ int str_isallnum(const char *str)
return 1; return 1;
} }
int str_toint(const char *str) { return str_toint_base(str, 10); } int str_isallnum_hex(const char *str)
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); } while(*str)
float str_tofloat(const char *str) { return strtod(str, NULL); } {
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) 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))) if(!fs_getcwd(workingDir, sizeof(workingDir)))
return 0; return 0;
str_append(workingDir, "/", sizeof(workingDir)); str_append(workingDir, "/");
} }
else else
workingDir[0] = '\0'; workingDir[0] = '\0';

View file

@ -23,8 +23,10 @@
#ifdef __MINGW32__ #ifdef __MINGW32__
#undef PRId64 #undef PRId64
#undef PRIu64 #undef PRIu64
#undef PRIX64
#define PRId64 "I64d" #define PRId64 "I64d"
#define PRIu64 "I64u" #define PRIu64 "I64u"
#define PRIX64 "I64X"
#define PRIzu "Iu" #define PRIzu "Iu"
#else #else
#define PRIzu "zu" #define PRIzu "zu"
@ -601,9 +603,9 @@ void thread_detach(void *thread);
* @param user Pointer to pass to the thread. * @param user Pointer to pass to the thread.
* @param name Name describing the use of 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. // Enable thread safety attributes only with clang.
// The attributes can be safely erased when compiling with other compilers. // 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); 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. * 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); 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. * 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); 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. * 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(const char *str);
int str_toint_base(const char *str, int base); int str_toint_base(const char *str, int base);
unsigned long str_toulong_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); float str_tofloat(const char *str);
/** /**
@ -2149,7 +2219,11 @@ float str_tofloat(const char *str);
int str_isspace(char c); int str_isspace(char c);
char str_uppercase(char c); char str_uppercase(char c);
int str_isallnum(const char *str); int str_isallnum(const char *str);
int str_isallnum_hex(const char *str);
unsigned str_quickhash(const char *str); unsigned str_quickhash(const char *str);
enum enum
@ -2777,23 +2851,6 @@ bool shell_unregister_application(const char *executable, bool *updated);
void shell_update(); void shell_update();
#endif #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<> template<>
struct std::hash<NETADDR> struct std::hash<NETADDR>
{ {

View file

@ -293,6 +293,7 @@ public:
MESSAGE_BOX_TYPE_INFO, MESSAGE_BOX_TYPE_INFO,
}; };
virtual void ShowMessageBox(const char *pTitle, const char *pMessage, EMessageBoxType Type = MESSAGE_BOX_TYPE_ERROR) = 0; 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 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) bool CGraphicsBackend_SDL_GL::ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg)
{ {
if(m_pProcessor != nullptr) if(m_pProcessor != nullptr)
{
m_pProcessor->ErroneousCleanup(); m_pProcessor->ErroneousCleanup();
}
// TODO: Remove this workaround when https://github.com/libsdl-org/SDL/issues/3750 is // 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 // fixed and pass the window to SDL_ShowSimpleMessageBox to make the popup modal instead
// of destroying the window before opening the popup. // of destroying the window before opening the popup.
@ -880,6 +882,12 @@ bool CGraphicsBackend_SDL_GL::GetDriverVersion(EGraphicsDriverAgeType DriverAgeT
return false; 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) static void DisplayToVideoMode(CVideoMode *pVMode, SDL_DisplayMode *pMode, int HiDPIScale, int RefreshRate)
{ {
pVMode->m_CanvasWidth = pMode->w * HiDPIScale; 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( m_pWindow = SDL_CreateWindow(
pName, pName,
SDL_WINDOWPOS_CENTERED_DISPLAY(*pScreen), SDL_WINDOWPOS_CENTERED_DISPLAY(*pScreen),
@ -1604,7 +1609,8 @@ void CGraphicsBackend_SDL_GL::GetViewportSize(int &w, int &h)
void CGraphicsBackend_SDL_GL::NotifyWindow() 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) if(SDL_FlashWindow(m_pWindow, SDL_FlashOperation::SDL_FLASH_UNTIL_FOCUSED) != 0)
{ {
// fails if SDL hasn't implemented it // fails if SDL hasn't implemented it

View file

@ -253,6 +253,7 @@ public:
const TTWGraphicsGPUList &GetGPUs() const override; const TTWGraphicsGPUList &GetGPUs() const override;
int GetNumScreens() const override { return m_NumScreens; } 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 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; 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]) if(g_Config.m_ClRunOnJoin[0])
{ {
str_format(aBuf, sizeof(aBuf), ";%s", g_Config.m_ClRunOnJoin); 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) 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]) if(aBufEmote[0])
{ {
str_format(aBuf, sizeof(aBuf), ";%s", aBufEmote); str_format(aBuf, sizeof(aBuf), ";%s", aBufEmote);
str_append(aBufMsg, aBuf, sizeof(aBufMsg)); str_append(aBufMsg, aBuf);
} }
} }
MsgP.m_pMessage = aBufMsg; MsgP.m_pMessage = aBufMsg;
@ -3343,8 +3343,15 @@ void CClient::Run()
else if(g_Config.m_ClRefreshRate) else if(g_Config.m_ClRefreshRate)
{ {
SleepTimeInNanoSeconds = (std::chrono::nanoseconds(1s) / (int64_t)g_Config.m_ClRefreshRate) - (Now - LastTime); SleepTimeInNanoSeconds = (std::chrono::nanoseconds(1s) / (int64_t)g_Config.m_ClRefreshRate) - (Now - LastTime);
if(SleepTimeInNanoSeconds > 0ns) auto SleepTimeInNanoSecondsInner = SleepTimeInNanoSeconds;
net_socket_read_wait(m_aNetClient[CONN_MAIN].m_Socket, 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; Slept = true;
} }
if(Slept) if(Slept)
@ -4631,8 +4638,19 @@ int main(int argc, const char **argv)
char aVersionStr[128]; char aVersionStr[128];
if(!os_version_str(aVersionStr, sizeof(aVersionStr))) if(!os_version_str(aVersionStr, sizeof(aVersionStr)))
str_copy(aVersionStr, "unknown"); str_copy(aVersionStr, "unknown");
char aMessage[512]; char aGPUInfo[256];
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); 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); pClient->ShowMessageBox("Assertion Error", aMessage);
// Client will crash due to assertion, don't call PerformAllCleanup in this inconsistent state // 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); 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]) 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) if(Logfile)
{ {
pFutureFileLogger->Set(log_logger_file(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"); SDL_SetHint("SDL_MAC_OPENGL_ASYNC_DISPATCH", "1");
#endif #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 // init SDL
if(SDL_Init(0) < 0) if(SDL_Init(0) < 0)
{ {
@ -4874,8 +4899,8 @@ void CClient::RequestDDNetInfo()
{ {
char aEscaped[128]; char aEscaped[128];
EscapeUrl(aEscaped, sizeof(aEscaped), PlayerName()); EscapeUrl(aEscaped, sizeof(aEscaped), PlayerName());
str_append(aUrl, "?name=", sizeof(aUrl)); str_append(aUrl, "?name=");
str_append(aUrl, aEscaped, sizeof(aUrl)); str_append(aUrl, aEscaped);
} }
// Use ipv4 so we can know the ingame ip addresses of players before they join game servers // 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)) if(m_pGraphics == nullptr || !m_pGraphics->ShowMessageBox(GetSdlMessageBoxFlags(Type), pTitle, pMessage))
SDL_ShowSimpleMessageBox(GetSdlMessageBoxFlags(Type), pTitle, pMessage, nullptr); 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 #endif
void ShowMessageBox(const char *pTitle, const char *pMessage, EMessageBoxType Type = MESSAGE_BOX_TYPE_ERROR) override; void ShowMessageBox(const char *pTitle, const char *pMessage, EMessageBoxType Type = MESSAGE_BOX_TYPE_ERROR) override;
void GetGPUInfoString(char (&aGPUInfo)[256]) override;
}; };
#endif #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_copy(aBuf, pSelf->m_Foes ? "add_foe " : "add_friend ");
str_append(aBuf, "\"", sizeof(aBuf)); str_append(aBuf, "\"");
char *pDst = aBuf + str_length(aBuf); char *pDst = aBuf + str_length(aBuf);
str_escape(&pDst, pSelf->m_aFriends[i].m_aName, pEnd); str_escape(&pDst, pSelf->m_aFriends[i].m_aName, pEnd);
str_append(aBuf, "\" \"", sizeof(aBuf)); str_append(aBuf, "\" \"");
pDst = aBuf + str_length(aBuf); pDst = aBuf + str_length(aBuf);
str_escape(&pDst, pSelf->m_aFriends[i].m_aClan, pEnd); str_escape(&pDst, pSelf->m_aFriends[i].m_aClan, pEnd);
str_append(aBuf, "\"", sizeof(aBuf)); str_append(aBuf, "\"");
pConfigManager->WriteLine(aBuf); pConfigManager->WriteLine(aBuf);
} }

View file

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

View file

@ -731,6 +731,7 @@ public:
virtual void GetCurrentVideoMode(CVideoMode &CurMode, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int Screen) = 0; virtual void GetCurrentVideoMode(CVideoMode &CurMode, int HiDPIScale, int MaxWindowWidth, int MaxWindowHeight, int Screen) = 0;
virtual int GetNumScreens() const = 0; virtual int GetNumScreens() const = 0;
virtual const char *GetScreenName(int Screen) const = 0;
virtual void Minimize() = 0; virtual void Minimize() = 0;
virtual void Maximize() = 0; virtual void Maximize() = 0;
@ -1257,6 +1258,8 @@ public:
void IndicesNumRequiredNotify(unsigned int RequiredIndicesCount) override; void IndicesNumRequiredNotify(unsigned int RequiredIndicesCount) override;
int GetNumScreens() const override; int GetNumScreens() const override;
const char *GetScreenName(int Screen) const override;
void Minimize() override; void Minimize() override;
void Maximize() override; void Maximize() override;
void WarnPngliteIncompatibleImages(bool Warn) override; void WarnPngliteIncompatibleImages(bool Warn) override;
@ -1300,6 +1303,7 @@ public:
SWarning *GetCurWarning() override; SWarning *GetCurWarning() override;
bool ShowMessageBox(unsigned Type, const char *pTitle, const char *pMsg) 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 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(); } bool IsConfigModernAPI() override { return m_pBackend->IsConfigModernAPI(); }

View file

@ -187,14 +187,10 @@ void CInput::CloseJoysticks()
m_pActiveJoystick = nullptr; m_pActiveJoystick = nullptr;
} }
void CInput::SelectNextJoystick() void CInput::SetActiveJoystick(size_t Index)
{ {
const int Num = m_vJoysticks.size(); m_pActiveJoystick = &m_vJoysticks[Index];
if(Num > 1) str_copy(g_Config.m_InpControllerGUID, m_pActiveJoystick->GetGUID());
{
m_pActiveJoystick = &m_vJoysticks[(m_pActiveJoystick->GetIndex() + 1) % Num];
str_copy(g_Config.m_InpControllerGUID, m_pActiveJoystick->GetGUID());
}
} }
float CInput::CJoystick::GetAxisValue(int Axis) 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]; } 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(); } 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; } CJoystick *GetActiveJoystick() override { return m_pActiveJoystick; }
void SelectNextJoystick() override; void SetActiveJoystick(size_t Index) override;
bool MouseRelative(float *pX, float *pY) override; bool MouseRelative(float *pX, float *pY) override;
void MouseModeAbsolute() override; void MouseModeAbsolute() override;

View file

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

View file

@ -575,7 +575,7 @@ void CServerBrowser::SetInfo(CServerEntry *pEntry, const CServerInfo &Info)
class CPlayerScoreNameLess class CPlayerScoreNameLess
{ {
int ScoreKind; const int ScoreKind;
public: public:
CPlayerScoreNameLess(int ClientScoreKind) : 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) bool operator()(const CServerInfo::CClient &p0, const CServerInfo::CClient &p1)
{ {
// Sort players before non players
if(p0.m_Player && !p1.m_Player) if(p0.m_Player && !p1.m_Player)
return true; return true;
if(!p0.m_Player && p1.m_Player) 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 Score0 = p0.m_Score;
int Score1 = p1.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) // Sort unfinished (-9999) and still connecting players (-1) after others
// only positive times are meant to represent an actual time. if(Score0 < 0 && Score1 >= 0)
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)
return false; 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; return str_comp_nocase(p0.m_aName, p1.m_aName) < 0;
@ -1425,17 +1415,17 @@ int CServerBrowser::LoadingProgression() const
return 100.0f * Loaded / Servers; 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)) if(DDNetFiltered(pFilter, pName))
return; return;
char aBuf[128]; char aBuf[128];
str_format(aBuf, sizeof(aBuf), ",%s", pName); 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)) if(!DDNetFiltered(pFilter, pName))
return; return;
@ -1453,12 +1443,12 @@ void CServerBrowser::DDNetFilterRem(char *pFilter, const char *pName)
{ {
char aBuf2[128]; char aBuf2[128];
str_format(aBuf2, sizeof(aBuf2), ",%s", aToken); 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 return str_in_list(pFilter, ",", pName); // country not excluded
} }
@ -1478,7 +1468,7 @@ void CServerBrowser::CountryFilterClean(int Network)
{ {
char aBuf[128]; char aBuf[128];
str_format(aBuf, sizeof(aBuf), ",%s", pName); 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]; char aBuf[128];
str_format(aBuf, sizeof(aBuf), ",%s", pName); 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; } 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]; } const char *GetType(int Network, int Index) override { return m_aNetworks[Network].m_aTypes[Index]; }
void DDNetFilterAdd(char *pFilter, const char *pName) override; void DDNetFilterAdd(char *pFilter, int FilterSize, const char *pName) const override;
void DDNetFilterRem(char *pFilter, const char *pName) override; void DDNetFilterRem(char *pFilter, int FilterSize, const char *pName) const override;
bool DDNetFiltered(char *pFilter, const char *pName) override; bool DDNetFiltered(const char *pFilter, const char *pName) const override;
void CountryFilterClean(int Network) override; void CountryFilterClean(int Network) override;
void TypeFilterClean(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; 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 // don't waste memory on sound when we are stress testing
#ifdef CONF_DEBUG #ifdef CONF_DEBUG
@ -600,7 +600,7 @@ int CSound::LoadOpus(const char *pFilename)
void *pData; void *pData;
unsigned DataSize; 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); dbg_msg("sound/opus", "failed to open file. filename='%s'", pFilename);
return -1; return -1;
@ -618,7 +618,7 @@ int CSound::LoadOpus(const char *pFilename)
return SampleID; 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 // don't waste memory on sound when we are stress testing
#ifdef CONF_DEBUG #ifdef CONF_DEBUG
@ -642,7 +642,7 @@ int CSound::LoadWV(const char *pFilename)
void *pData; void *pData;
unsigned DataSize; 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); dbg_msg("sound/wv", "failed to open file. filename='%s'", pFilename);
return -1; return -1;

View file

@ -34,9 +34,9 @@ public:
bool IsSoundEnabled() override { return m_SoundEnabled; } 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 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; int LoadOpusFromMem(const void *pData, unsigned DataSize, bool FromEditor) override;
void UnloadSample(int SampleID) override; void UnloadSample(int SampleID) override;

View file

@ -132,9 +132,7 @@ public:
struct STextString struct STextString
{ {
int m_QuadBufferObjectIndex; int m_QuadBufferObjectIndex;
uint32_t m_DbgShadowBytes = 0x12345678;
int m_QuadBufferContainerIndex; int m_QuadBufferContainerIndex;
uint32_t m_DbgShadowBytes2 = 0x87654321;
size_t m_QuadNum; size_t m_QuadNum;
int m_SelectionQuadContainerIndex; int m_SelectionQuadContainerIndex;
@ -1033,7 +1031,7 @@ public:
void AppendTextContainer(STextContainerIndex TextContainerIndex, CTextCursor *pCursor, const char *pText, int Length = -1) override void AppendTextContainer(STextContainerIndex TextContainerIndex, CTextCursor *pCursor, const char *pText, int Length = -1) override
{ {
STextContainer &TextContainer = GetTextContainer(TextContainerIndex); 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 // calculate the font size of the displayed glyphs
float ScreenX0, ScreenY0, ScreenX1, ScreenY1; 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()); 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) 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"); dbg_assert(!HasNonEmptyTextContainer, "text container was not empty");

View file

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

View file

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

View file

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

View file

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

View file

@ -169,7 +169,7 @@ bool CAntibot::OnEngineClientMessage(int ClientID, const void *pData, int Size,
{ {
AntibotFlags |= ANTIBOT_MSGFLAG_NONVITAL; 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) 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; 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) 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; m_Ptr.m_Print.m_Mode = m;
} }
CDbConnectionPool::~CDbConnectionPool() = default;
void CDbConnectionPool::Print(IConsole *pConsole, Mode DatabaseMode) void CDbConnectionPool::Print(IConsole *pConsole, Mode DatabaseMode)
{ {
m_pShared->m_aQueries[m_InsertIdx++] = std::make_unique<CSqlExecData>(pConsole, 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() CDbConnectionPool::CDbConnectionPool()
{ {
m_pShared = std::make_shared<CSharedData>(); m_pShared = std::make_shared<CSharedData>();
m_pWorkerThread = thread_init(CWorker::Start, new CWorker(m_pShared), "database worker thread");
thread_init_and_detach(CWorker::Start, new CWorker(m_pShared), "database worker thread"); m_pBackupThread = thread_init(CBackup::Start, new CBackup(m_pShared), "database backup worker thread");
thread_init_and_detach(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; std::shared_ptr<CSharedData> m_pShared;
void *m_pWorkerThread = nullptr;
void *m_pBackupThread = nullptr;
}; };
#endif // ENGINE_SERVER_DATABASES_CONNECTION_POOL_H #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)"); 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); 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]) 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) if(Logfile)
{ {
pFutureFileLogger->Set(log_logger_file(Logfile)); pFutureFileLogger->Set(log_logger_file(Logfile));
@ -189,12 +190,12 @@ int main(int argc, const char **argv)
dbg_msg("server", "starting..."); dbg_msg("server", "starting...");
int Ret = pServer->Run(); int Ret = pServer->Run();
MysqlUninit();
secure_random_uninit();
pServerLogger->OnServerDeletion(); pServerLogger->OnServerDeletion();
// free // free
delete pKernel; delete pKernel;
MysqlUninit();
secure_random_uninit();
return Ret; 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, pLine, pStart - pLine + 1);
str_append(aLine, pStart + 2, pStart - pLine + pEnd - pStart - 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, pLine, pStart - pLine + 1);
str_append(aLineWithoutIps, "XXX", sizeof(aLineWithoutIps)); str_append(aLineWithoutIps, "XXX");
str_append(aLineWithoutIps, pEnd + 2, sizeof(aLineWithoutIps)); str_append(aLineWithoutIps, pEnd + 2);
pLine = aLine; pLine = aLine;
pLineWithoutIps = aLineWithoutIps; pLineWithoutIps = aLineWithoutIps;
@ -1366,6 +1366,38 @@ static inline int MsgFromSixup(int Msg, bool System)
return Msg; 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) void CServer::ProcessClientPacket(CNetChunk *pPacket)
{ {
int ClientID = pPacket->m_ClientID; int ClientID = pPacket->m_ClientID;
@ -1466,7 +1498,7 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
} }
// reserved slot // 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"); m_NetServer.Drop(ClientID, "This server is full");
return; return;
@ -2287,12 +2319,12 @@ void CServer::UpdateRegisterServerInfo()
m_aClients[i].m_Score.value_or(-9999), m_aClients[i].m_Score.value_or(-9999),
JsonBool(GameServer()->IsClientPlayer(i)), JsonBool(GameServer()->IsClientPlayer(i)),
aExtraPlayerInfo); aExtraPlayerInfo);
str_append(aInfo, aClientInfo, sizeof(aInfo)); str_append(aInfo, aClientInfo);
FirstPlayer = false; FirstPlayer = false;
} }
} }
str_append(aInfo, "]}", sizeof(aInfo)); str_append(aInfo, "]}");
m_pRegister->OnNewInfo(aInfo); m_pRegister->OnNewInfo(aInfo);
} }

View file

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

View file

@ -165,9 +165,9 @@ public:
virtual int NumTypes(int Network) = 0; virtual int NumTypes(int Network) = 0;
virtual const char *GetType(int Network, int Index) = 0; virtual const char *GetType(int Network, int Index) = 0;
virtual void DDNetFilterAdd(char *pFilter, const char *pName) = 0; virtual void DDNetFilterAdd(char *pFilter, int FilterSize, const char *pName) const = 0;
virtual void DDNetFilterRem(char *pFilter, const char *pName) = 0; virtual void DDNetFilterRem(char *pFilter, int FilterSize, const char *pName) const = 0;
virtual bool DDNetFiltered(char *pFilter, const char *pName) = 0; virtual bool DDNetFiltered(const char *pFilter, const char *pName) const = 0;
virtual void CountryFilterClean(int Network) = 0; virtual void CountryFilterClean(int Network) = 0;
virtual void TypeFilterClean(int Network) = 0; virtual void TypeFilterClean(int Network) = 0;
virtual int GetCurrentType() = 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(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_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(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(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(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).") 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(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(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(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(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(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(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(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") 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(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(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(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(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(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(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") 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_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") 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_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(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(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(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_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") 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(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(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(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(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)") 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 #ifdef CONF_DEBUG
MACRO_CONFIG_INT(DbgStress, dbg_stress, 0, 0, 0, CFGFLAG_CLIENT | CFGFLAG_SERVER, "Stress systems (Debug build only)") 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)") MACRO_CONFIG_STR(DbgStressServer, dbg_stress_server, 32, "localhost", CFGFLAG_CLIENT, "Server to stress (Debug build only)")
#endif #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_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_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_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(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(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)") 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(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(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(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") 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_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(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_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)") 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(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(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(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(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") 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 else if(*pStr == '$') // Hex RGB/RGBA
{ {
ColorRGBA Rgba = ColorRGBA(0, 0, 0, 1); return color_cast<ColorHSLA>(color_parse<ColorRGBA>(pStr + 1).value_or(ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)));
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);
} }
else if(!str_comp_nocase(pStr, "red")) else if(!str_comp_nocase(pStr, "red"))
return ColorHSLA(0.0f / 6.0f, 1, .5f); return ColorHSLA(0.0f / 6.0f, 1, .5f);
@ -732,9 +695,9 @@ void CConsole::ConCommandStatus(IResult *pResult, void *pUser)
if(Used > 0) if(Used > 0)
{ {
Used += 2; 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; Used += Length;
} }
else else
@ -927,7 +890,7 @@ void CConsole::ConToggle(IConsole::IResult *pResult, void *pUser)
str_format(aBuf, sizeof(aBuf), "%s \"", pResult->GetString(0)); str_format(aBuf, sizeof(aBuf), "%s \"", pResult->GetString(0));
char *pDst = aBuf + str_length(aBuf); char *pDst = aBuf + str_length(aBuf);
str_escape(&pDst, pStr, aBuf + sizeof(aBuf)); str_escape(&pDst, pStr, aBuf + sizeof(aBuf));
str_append(aBuf, "\"", sizeof(aBuf)); str_append(aBuf, "\"");
pConsole->ExecuteLine(aBuf); pConsole->ExecuteLine(aBuf);
aBuf[0] = 0; aBuf[0] = 0;
} }

View file

@ -525,16 +525,35 @@ CDataFileWriter::CDataFileWriter()
CDataFileWriter::~CDataFileWriter() CDataFileWriter::~CDataFileWriter()
{ {
if(m_File)
{
io_close(m_File);
m_File = 0;
}
free(m_pItemTypes); free(m_pItemTypes);
m_pItemTypes = nullptr; m_pItemTypes = nullptr;
for(int i = 0; i < m_NumItems; i++)
free(m_pItems[i].m_pData); if(m_pItems)
for(int i = 0; i < m_NumDatas; ++i) {
free(m_pDatas[i].m_pCompressedData); for(int i = 0; i < m_NumItems; i++)
free(m_pItems); {
m_pItems = nullptr; free(m_pItems[i].m_pData);
free(m_pDatas); }
m_pDatas = nullptr; 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) 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"); dbg_assert(m_NumDatas < 1024, "too much data");
CDataInfo *pInfo = &m_pDatas[m_NumDatas]; CDataInfo *pInfo = &m_pDatas[m_NumDatas];
unsigned long s = compressBound(Size); pInfo->m_pUncompressedData = malloc(Size);
void *pCompData = malloc(s); // temporary buffer that we use during compression mem_copy(pInfo->m_pUncompressedData, pData, Size);
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_UncompressedSize = Size; pInfo->m_UncompressedSize = Size;
pInfo->m_CompressedSize = (int)s; pInfo->m_pCompressedData = nullptr;
pInfo->m_pCompressedData = malloc(pInfo->m_CompressedSize); pInfo->m_CompressedSize = 0;
mem_copy(pInfo->m_pCompressedData, pCompData, pInfo->m_CompressedSize); pInfo->m_CompressionLevel = CompressionLevel;
free(pCompData);
m_NumDatas++; m_NumDatas++;
return m_NumDatas - 1; return m_NumDatas - 1;
@ -672,15 +682,31 @@ int CDataFileWriter::AddDataSwapped(int Size, void *pData)
#endif #endif
} }
int CDataFileWriter::Finish() void CDataFileWriter::Finish()
{ {
if(!m_File) dbg_assert((bool)m_File, "file not open");
return 1;
// we should now write this file! // we should now write this file!
if(DEBUG) if(DEBUG)
dbg_msg("datafile", "writing"); 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 // calculate sizes
int ItemSize = 0; int ItemSize = 0;
for(int i = 0; i < m_NumItems; i++) for(int i = 0; i < m_NumItems; i++)
@ -851,5 +877,4 @@ int CDataFileWriter::Finish()
if(DEBUG) if(DEBUG)
dbg_msg("datafile", "done"); dbg_msg("datafile", "done");
return 0;
} }

View file

@ -58,9 +58,11 @@ class CDataFileWriter
{ {
struct CDataInfo struct CDataInfo
{ {
void *m_pUncompressedData;
int m_UncompressedSize; int m_UncompressedSize;
int m_CompressedSize;
void *m_pCompressedData; void *m_pCompressedData;
int m_CompressedSize;
int m_CompressionLevel;
}; };
struct CItemInfo struct CItemInfo
@ -103,14 +105,31 @@ class CDataFileWriter
public: public:
CDataFileWriter(); 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(); ~CDataFileWriter();
void Init(); void Init();
bool OpenFile(class IStorage *pStorage, const char *pFilename, int StorageType = IStorage::TYPE_SAVE); 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); 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 AddData(int Size, void *pData, int CompressionLevel = Z_DEFAULT_COMPRESSION);
int AddDataSwapped(int Size, void *pData); int AddDataSwapped(int Size, void *pData);
int AddItem(int Type, int ID, int Size, void *pData); int AddItem(int Type, int ID, int Size, void *pData);
int Finish(); void Finish();
}; };
#endif #endif

View file

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

View file

@ -207,7 +207,7 @@ void CFileCollection::AddEntry(int64_t Timestamp)
} }
else else
{ {
char aBuf[512]; char aBuf[IO_MAX_PATH_LENGTH];
char aTimestring[TIMESTAMP_LENGTH]; char aTimestring[TIMESTAMP_LENGTH];
BuildTimestring(m_aTimestamps[0], aTimestring); BuildTimestring(m_aTimestamps[0], aTimestring);
@ -261,7 +261,7 @@ int CFileCollection::RemoveCallback(const char *pFilename, int IsDir, int Storag
if(Timestamp == pThis->m_Remove) 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); str_format(aBuf, sizeof(aBuf), "%s/%s", pThis->m_aPath, pFilename);
pThis->m_pStorage->RemoveFile(aBuf, IStorage::TYPE_SAVE); pThis->m_pStorage->RemoveFile(aBuf, IStorage::TYPE_SAVE);
pThis->m_Remove = -1; 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; int Needed = 0;
while(Size) while(Size)
{ {
*pOut = *pCurrent - *pPast; // subtraction with wrapping by casting to unsigned
*pOut = (unsigned)*pCurrent - (unsigned)*pPast;
Needed |= *pOut; Needed |= *pOut;
pOut++; pOut++;
pPast++; pPast++;

View file

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

View file

@ -6,6 +6,7 @@
#include "kernel.h" #include "kernel.h"
#include <engine/shared/video.h> #include <engine/shared/video.h>
#include <engine/storage.h>
class ISound : public IInterface class ISound : public IInterface
{ {
@ -63,8 +64,8 @@ public:
virtual bool IsSoundEnabled() = 0; virtual bool IsSoundEnabled() = 0;
virtual int LoadWV(const char *pFilename) = 0; virtual int LoadWV(const char *pFilename, int StorageType = IStorage::TYPE_ALL) = 0;
virtual int LoadOpus(const char *pFilename) = 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 LoadWVFromMem(const void *pData, unsigned DataSize, bool FromEditor = false) = 0;
virtual int LoadOpusFromMem(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; 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_STAR = "\xEF\x80\x85";
MAYBE_UNUSED static const char *FONT_ICON_CHECK = "\xEF\x80\x8C"; 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_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_LEFT = "\xEF\x83\xA2";
MAYBE_UNUSED static const char *FONT_ICON_ARROW_ROTATE_RIGHT = "\xEF\x80\x9E"; MAYBE_UNUSED static const char *FONT_ICON_ARROW_ROTATE_RIGHT = "\xEF\x80\x9E";
MAYBE_UNUSED static const char *FONT_ICON_CERTIFICATE = "\xEF\x82\xA3"; 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_BACKWARD_STEP = "\xEF\x81\x88";
MAYBE_UNUSED static const char *FONT_ICON_FORWARD_STEP = "\xEF\x81\x91"; 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_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 = "\xEF\x81\xBB";
MAYBE_UNUSED static const char *FONT_ICON_FOLDER_TREE = "\xEF\xA0\x82"; MAYBE_UNUSED static const char *FONT_ICON_FOLDER_TREE = "\xEF\xA0\x82";

View file

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

View file

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

View file

@ -138,7 +138,8 @@ bool CBinds::OnInput(const IInput::CEvent &Event)
{ {
if(Event.m_Flags & IInput::FLAG_PRESS) if(Event.m_Flags & IInput::FLAG_PRESS)
Console()->ExecuteLineStroked(1, m_aapKeyBindings[Mask][Event.m_Key]); 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]); Console()->ExecuteLineStroked(0, m_aapKeyBindings[Mask][Event.m_Key]);
ret = true; 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 // 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))) 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]); 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]); Console()->ExecuteLineStroked(0, m_aapKeyBindings[0][Event.m_Key]);
ret = true; ret = true;
} }
@ -253,7 +255,7 @@ void CBinds::OnConsoleInit()
if(pConfigManager) if(pConfigManager)
pConfigManager->RegisterCallback(ConfigSaveCallback, this); 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("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("unbind", "s[key]", CFGFLAG_CLIENT, ConUnbind, this, "Unbind key");
Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys"); Console()->Register("unbindall", "", CFGFLAG_CLIENT, ConUnbindAll, this, "Unbind all keys");
@ -277,6 +279,20 @@ void CBinds::ConBind(IConsole::IResult *pResult, void *pUserData)
return; 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); pBinds->Bind(KeyID, pResult->GetString(1), false, Modifier);
} }
@ -419,8 +435,8 @@ const char *CBinds::GetKeyBindModifiersName(int ModifierCombination)
{ {
if(ModifierCombination & (1 << k)) if(ModifierCombination & (1 << k))
{ {
str_append(aModifier, GetModifierName(k), sizeof(aModifier)); str_append(aModifier, GetModifierName(k));
str_append(aModifier, "+", sizeof(aModifier)); str_append(aModifier, "+");
} }
} }
return 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); str_truncate(aBuf, sizeof(aBuf), m_Input.GetString(), m_PlaceholderOffset);
// add the command // add the command
str_append(aBuf, "/", sizeof(aBuf)); str_append(aBuf, "/");
str_append(aBuf, pCompletionCommand->m_pName, sizeof(aBuf)); str_append(aBuf, pCompletionCommand->m_pName);
// add separator // add separator
const char *pSeparator = pCompletionCommand->m_pParams[0] == '\0' ? "" : " "; const char *pSeparator = pCompletionCommand->m_pParams[0] == '\0' ? "" : " ";
str_append(aBuf, pSeparator, sizeof(aBuf)); str_append(aBuf, pSeparator);
if(*pSeparator) if(*pSeparator)
str_append(aBuf, pSeparator, sizeof(aBuf)); str_append(aBuf, pSeparator);
// add part after the name // 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_PlaceholderLength = str_length(pSeparator) + str_length(pCompletionCommand->m_pName) + 1;
m_Input.Set(aBuf); 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); str_truncate(aBuf, sizeof(aBuf), m_Input.GetString(), m_PlaceholderOffset);
// add the name // add the name
str_append(aBuf, pCompletionString, sizeof(aBuf)); str_append(aBuf, pCompletionString);
// add separator // add separator
const char *pSeparator = ""; const char *pSeparator = "";
@ -369,10 +369,10 @@ bool CChat::OnInput(const IInput::CEvent &Event)
else if(m_PlaceholderOffset == 0) else if(m_PlaceholderOffset == 0)
pSeparator = ":"; pSeparator = ":";
if(*pSeparator) if(*pSeparator)
str_append(aBuf, pSeparator, sizeof(aBuf)); str_append(aBuf, pSeparator);
// add part after the name // 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_PlaceholderLength = str_length(pSeparator) + str_length(pCompletionString);
m_Input.Set(aBuf); m_Input.Set(aBuf);
@ -883,7 +883,7 @@ void CChat::OnPrepareLines()
str_format(aName, sizeof(aName), "%d: ", m_aLines[r].m_ClientID); 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]; char aCount[12];
if(m_aLines[r].m_ClientID < 0) if(m_aLines[r].m_ClientID < 0)
@ -1179,7 +1179,7 @@ void CChat::OnRender()
float OffsetTeeY = MESSAGE_TEE_SIZE / 2.0f; float OffsetTeeY = MESSAGE_TEE_SIZE / 2.0f;
float FullHeightMinusTee = RowHeight - MESSAGE_TEE_SIZE; float FullHeightMinusTee = RowHeight - MESSAGE_TEE_SIZE;
CAnimState *pIdleState = CAnimState::GetIdle(); const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid; vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &RenderInfo, OffsetToMid); RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &RenderInfo, OffsetToMid);
vec2 TeeRenderPos(x + (RealMsgPaddingX + MESSAGE_TEE_SIZE) / 2.0f, y + OffsetTeeY + FullHeightMinusTee / 2.0f + OffsetToMid.y); 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 // get command
char aBuf[512]; char aBuf[512];
StrCopyUntilSpace(aBuf, sizeof(aBuf), pInstance->GetString()); StrCopyUntilSpace(aBuf, sizeof(aBuf), pInstance->GetString());
str_append(aBuf, " ", sizeof(aBuf)); str_append(aBuf, " ");
// append argument // append argument
str_append(aBuf, pStr, sizeof(aBuf)); str_append(aBuf, pStr);
pInstance->m_Input.Set(aBuf); 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()]; 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()) if(pFlag->m_Texture.IsValid())
{ {
Graphics()->TextureSet(pFlag->m_Texture); Graphics()->TextureSet(pFlag->m_Texture);
Graphics()->SetColor(*pColor); Graphics()->SetColor(Color);
Graphics()->RenderQuadContainerEx(m_FlagsQuadContainerIndex, 0, -1, x, y, w, h); 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; size_t Num() const;
const CCountryFlag *GetByCountryCode(int CountryCode) const; const CCountryFlag *GetByCountryCode(int CountryCode) const;
const CCountryFlag *GetByIndex(size_t Index) 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: private:
enum enum

View file

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

View file

@ -269,7 +269,7 @@ void CHud::RenderScoreHud()
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[ID].m_RenderInfo; CTeeRenderInfo TeeInfo = m_pClient->m_aClients[ID].m_RenderInfo;
TeeInfo.m_Size = ScoreSingleBoxHeight; TeeInfo.m_Size = ScoreSingleBoxHeight;
CAnimState *pIdleState = CAnimState::GetIdle(); const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid; vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid); RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(m_Width - ScoreWidthMax - TeeInfo.m_Size / 2 - Split, StartY + (t * 20) + ScoreSingleBoxHeight / 2.0f + OffsetToMid.y); 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; CTeeRenderInfo TeeInfo = m_pClient->m_aClients[ID].m_RenderInfo;
TeeInfo.m_Size = ScoreSingleBoxHeight; TeeInfo.m_Size = ScoreSingleBoxHeight;
CAnimState *pIdleState = CAnimState::GetIdle(); const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid; vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid); RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(m_Width - ScoreWidthMax - TeeInfo.m_Size / 2 - Split, StartY + (t * 20) + ScoreSingleBoxHeight / 2.0f + OffsetToMid.y); 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; m_aKillmsgs[m_KillmsgCurrent] = Kill;
} }
else
{
TextRender()->DeleteTextContainer(Kill.m_VictimTextContainerIndex);
TextRender()->DeleteTextContainer(Kill.m_KillerTextContainerIndex);
}
Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
} }
@ -241,6 +246,11 @@ void CKillMessages::OnMessage(int MsgType, void *pRawMsg)
m_aKillmsgs[m_KillmsgCurrent] = Kill; m_aKillmsgs[m_KillmsgCurrent] = Kill;
} }
else
{
TextRender()->DeleteTextContainer(Kill.m_VictimTextContainerIndex);
TextRender()->DeleteTextContainer(Kill.m_KillerTextContainerIndex);
}
Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1); Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
} }
@ -310,7 +320,7 @@ void CKillMessages::OnRender()
{ {
CTeeRenderInfo TeeInfo = m_aKillmsgs[r].m_VictimRenderInfo[j]; CTeeRenderInfo TeeInfo = m_aKillmsgs[r].m_VictimRenderInfo[j];
CAnimState *pIdleState = CAnimState::GetIdle(); const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid; vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid); RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(x, y + 46.0f / 2.0f + OffsetToMid.y); vec2 TeeRenderPos(x, y + 46.0f / 2.0f + OffsetToMid.y);
@ -356,7 +366,7 @@ void CKillMessages::OnRender()
{ {
CTeeRenderInfo TeeInfo = m_aKillmsgs[r].m_KillerRenderInfo; CTeeRenderInfo TeeInfo = m_aKillmsgs[r].m_KillerRenderInfo;
CAnimState *pIdleState = CAnimState::GetIdle(); const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid; vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid); RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(x, y + 46.0f / 2.0f + OffsetToMid.y); vec2 TeeRenderPos(x, y + 46.0f / 2.0f + OffsetToMid.y);
@ -396,6 +406,10 @@ void CKillMessages::RefindSkins()
if(m_aKillmsgs[r].m_VictimID >= 0) 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]; const CGameClient::CClientData &Client = GameClient()->m_aClients[m_aKillmsgs[r].m_VictimID];
if(Client.m_aSkinName[0] != '\0') if(Client.m_aSkinName[0] != '\0')
m_aKillmsgs[r].m_VictimRenderInfo[0] = Client.m_RenderInfo; 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_ColorTabbarActiveIngame;
ColorRGBA CMenus::ms_ColorTabbarHoverIngame; ColorRGBA CMenus::ms_ColorTabbarHoverIngame;
SColorPicker CMenus::ms_ColorPicker;
bool CMenus::ms_ValueSelectorTextMode;
float CMenus::ms_ButtonHeight = 25.0f; float CMenus::ms_ButtonHeight = 25.0f;
float CMenus::ms_ListheaderHeight = 17.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; 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; 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); pRect->Draw(Color, Corners, r);
if(pImageName) if(pImageName)
@ -171,9 +154,6 @@ int CMenus::DoButton_Menu(CButtonContainer *pButtonContainer, const char *pText,
Text.HMargin((Text.h * FontFactor) / 2.0f, &Text); Text.HMargin((Text.h * FontFactor) / 2.0f, &Text);
UI()->DoLabel(&Text, pText, Text.h * CUI::ms_FontmodHeight, TEXTALIGN_MC); UI()->DoLabel(&Text, pText, Text.h * CUI::ms_FontmodHeight, TEXTALIGN_MC);
if(MouseInsideColorPicker)
return 0;
return UI()->DoButtonLogic(pButtonContainer, Checked, pRect); 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) 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; CUIRect Rect = *pRect;
if(pAnimator != NULL) 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; CUIRect Section, ColorPickerButton, ResetButton, Label;
@ -392,9 +372,9 @@ ColorHSLA CMenus::DoLine_ColorPicker(CButtonContainer *pResetID, const float Lin
if(DoButton_CheckBox(pCheckBoxValue, "", *pCheckBoxValue, &CheckBox)) if(DoButton_CheckBox(pCheckBoxValue, "", *pCheckBoxValue, &CheckBox))
*pCheckBoxValue ^= 1; *pCheckBoxValue ^= 1;
} }
Section.VSplitLeft(5.0f, nullptr, &Section);
} }
Section.VSplitLeft(5.0f, nullptr, &Section);
Section.VSplitMid(&Label, &Section, Section.h); Section.VSplitMid(&Label, &Section, Section.h);
Section.VSplitRight(60.0f, &Section, &ResetButton); Section.VSplitRight(60.0f, &Section, &ResetButton);
Section.VSplitRight(8.0f, &Section, nullptr); 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); 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); 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; 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) int CMenus::DoButton_CheckBoxAutoVMarginAndSet(const void *pID, const char *pText, int *pValue, CUIRect *pRect, float VMargin)
{ {
CUIRect CheckBoxRect; 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); 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) int CMenus::DoKeyReader(void *pID, const CUIRect *pRect, int Key, int ModifierCombination, int *pNewModifierCombination)
{ {
// process // process
@ -1070,196 +961,6 @@ bool CMenus::CanDisplayWarning()
return m_Popup == POPUP_NONE; 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() int CMenus::Render()
{ {
if(Client()->State() == IClient::STATE_DEMOPLAYBACK && m_Popup == POPUP_NONE) if(Client()->State() == IClient::STATE_DEMOPLAYBACK && m_Popup == POPUP_NONE)
@ -1342,11 +1043,6 @@ int CMenus::Render()
{ {
Screen.HSplitTop(24.0f, &TabBar, &MainView); Screen.HSplitTop(24.0f, &TabBar, &MainView);
if(Client()->State() == IClient::STATE_OFFLINE && UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
{
m_ShowStart = true;
}
// render news // render news
if(m_MenuPage < PAGE_NEWS || m_MenuPage > PAGE_SETTINGS || (Client()->State() == IClient::STATE_OFFLINE && m_MenuPage >= PAGE_GAME && m_MenuPage <= PAGE_CALLVOTE)) 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 *pTitle = "";
const char *pExtraText = ""; const char *pExtraText = "";
const char *pButtonText = ""; const char *pButtonText = "";
int ExtraAlign = 0; bool TopAlign = false;
bool UseIpLabel = false; bool UseIpLabel = false;
ColorRGBA BgColor = ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f); ColorRGBA BgColor = ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f);
@ -1513,7 +1209,6 @@ int CMenus::Render()
pExtraText = aBuf; pExtraText = aBuf;
pButtonText = Localize("Abort"); pButtonText = Localize("Abort");
} }
ExtraAlign = 0;
} }
else if(m_Popup == POPUP_RENAME_DEMO) else if(m_Popup == POPUP_RENAME_DEMO)
{ {
@ -1545,7 +1240,7 @@ int CMenus::Render()
Localize("Please enter your nickname below.")); Localize("Please enter your nickname below."));
pExtraText = aBuf; pExtraText = aBuf;
pButtonText = Localize("Ok"); pButtonText = Localize("Ok");
ExtraAlign = -1; TopAlign = true;
} }
else if(m_Popup == POPUP_POINTS) 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); 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; pExtraText = aBuf;
ExtraAlign = -1; TopAlign = true;
} }
else if(Client()->m_Points >= 0) else if(Client()->m_Points >= 0)
{ {
@ -1571,7 +1266,7 @@ int CMenus::Render()
pTitle = m_aMessageTopic; pTitle = m_aMessageTopic;
pExtraText = m_aMessageBody; pExtraText = m_aMessageBody;
pButtonText = m_aMessageButton; pButtonText = m_aMessageButton;
ExtraAlign = -1; TopAlign = true;
} }
CUIRect Box, Part; CUIRect Box, Part;
@ -1607,15 +1302,12 @@ int CMenus::Render()
} }
Props.m_MaxWidth = (int)Part.w; 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); UI()->DoLabel(&Part, pExtraText, FontSize, TEXTALIGN_ML, Props);
else else
{ UI()->DoLabel(&Part, pExtraText, FontSize, TEXTALIGN_MC);
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);
}
if(m_Popup == POPUP_MESSAGE || m_Popup == POPUP_CONFIRM) if(m_Popup == POPUP_MESSAGE || m_Popup == POPUP_CONFIRM)
{ {
@ -1830,14 +1522,24 @@ int CMenus::Render()
char aBufNew[IO_MAX_PATH_LENGTH]; char aBufNew[IO_MAX_PATH_LENGTH];
str_format(aBufNew, sizeof(aBufNew), "%s/%s", m_aCurrentDemoFolder, m_DemoRenameInput.GetString()); str_format(aBufNew, sizeof(aBufNew), "%s/%s", m_aCurrentDemoFolder, m_DemoRenameInput.GetString());
if(!str_endswith(aBufNew, ".demo")) if(!str_endswith(aBufNew, ".demo"))
str_append(aBufNew, ".demo", sizeof(aBufNew)); str_append(aBufNew, ".demo");
if(Storage()->RenameFile(aBufOld, aBufNew, m_vDemos[m_DemolistSelectedIndex].m_StorageType))
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(); DemolistPopulate();
DemolistOnUpdate(false); DemolistOnUpdate(false);
} }
else 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(); 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; return 0;
} }
@ -2100,7 +1808,7 @@ void CMenus::RenderThemeSelection(CUIRect MainView)
static CListBox s_ListBox; static CListBox s_ListBox;
s_ListBox.DoHeader(&MainView, Localize("Theme"), 20.0f); 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++) for(int i = 0; i < (int)vThemes.size(); i++)
{ {
@ -2159,7 +1867,6 @@ void CMenus::SetActive(bool Active)
{ {
if(Active != m_MenuActive) if(Active != m_MenuActive)
{ {
ms_ColorPicker.m_Active = false;
UI()->SetHotItem(nullptr); UI()->SetHotItem(nullptr);
UI()->SetActiveItem(nullptr); UI()->SetActiveItem(nullptr);
} }
@ -2204,23 +1911,15 @@ bool CMenus::OnCursorMove(float x, float y, IInput::ECursorType CursorType)
return false; return false;
UI()->ConvertMouseMove(&x, &y, CursorType); UI()->ConvertMouseMove(&x, &y, CursorType);
UI()->OnCursorMove(x, y);
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());
return true; return true;
} }
bool CMenus::OnInput(const IInput::CEvent &Event) bool CMenus::OnInput(const IInput::CEvent &Event)
{ {
// special handle esc and enter for popup purposes // Escape key is always handled to activate/deactivate menu
if(Event.m_Flags & IInput::FLAG_PRESS && Event.m_Key == KEY_ESCAPE) if((Event.m_Flags & IInput::FLAG_PRESS && Event.m_Key == KEY_ESCAPE) || IsActive())
{
SetActive(!IsActive());
UI()->OnInput(Event);
return true;
}
if(IsActive())
{ {
UI()->OnInput(Event); UI()->OnInput(Event);
return true; return true;
@ -2301,20 +2000,41 @@ void CMenus::OnRender()
if(!IsActive()) if(!IsActive())
{ {
if(UI()->ConsumeHotkey(CUI::HOTKEY_ESCAPE))
SetActive(true);
UI()->FinishCheck(); UI()->FinishCheck();
UI()->ClearHotkeys(); UI()->ClearHotkeys();
return; 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_GuiColor = color_cast<ColorRGBA>(ColorHSLA(g_Config.m_UiColor, true));
ms_ColorTabbarInactiveOutgame = ColorRGBA(0, 0, 0, 0.25f); ms_ColorTabbarInactiveOutgame = ColorRGBA(0.0f, 0.0f, 0.0f, 0.25f);
ms_ColorTabbarActiveOutgame = ColorRGBA(0, 0, 0, 0.5f); ms_ColorTabbarActiveOutgame = ColorRGBA(0.0f, 0.0f, 0.0f, 0.5f);
ms_ColorTabbarHoverOutgame = ColorRGBA(1, 1, 1, 0.25f); ms_ColorTabbarHoverOutgame = ColorRGBA(1.0f, 1.0f, 1.0f, 0.25f);
float ColorIngameScaleI = 0.5f; const float ColorIngameScaleI = 0.5f;
float ColorIngameAcaleA = 0.2f; const float ColorIngameAcaleA = 0.2f;
ms_ColorTabbarInactiveIngame = ColorRGBA( ms_ColorTabbarInactiveIngame = ColorRGBA(
ms_GuiColor.r * ColorIngameScaleI, ms_GuiColor.r * ColorIngameScaleI,
@ -2328,32 +2048,7 @@ void CMenus::OnRender()
ms_GuiColor.b * ColorIngameAcaleA, ms_GuiColor.b * ColorIngameAcaleA,
ms_GuiColor.a); ms_GuiColor.a);
ms_ColorTabbarHoverIngame = ColorRGBA(1, 1, 1, 0.75f); ms_ColorTabbarHoverIngame = ColorRGBA(1.0f, 1.0f, 1.0f, 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();
} }
void CMenus::RenderBackground() void CMenus::RenderBackground()

View file

@ -29,22 +29,6 @@ struct CServerProcess
PROCESS m_Process; 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 // component to fetch keypresses, override all other input
class CMenusKeyBinder : public CComponent class CMenusKeyBinder : public CComponent
{ {
@ -71,15 +55,9 @@ class CMenus : public CComponent
static ColorRGBA ms_ColorTabbarActive; static ColorRGBA ms_ColorTabbarActive;
static ColorRGBA ms_ColorTabbarHover; static ColorRGBA ms_ColorTabbarHover;
static SColorPicker ms_ColorPicker; int DoButton_FontIcon(CButtonContainer *pButtonContainer, const char *pText, int Checked, const CUIRect *pRect, int Corners = IGraphics::CORNER_ALL, bool Enabled = true);
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_Toggle(const void *pID, int Checked, const CUIRect *pRect, bool Active); 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_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); 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_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); 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); 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); 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); 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 DoJoystickAxisPicker(CUIRect View);
void DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, bool Active); void DoJoystickBar(const CUIRect *pRect, float Current, float Tolerance, bool Active);
void RenderColorPicker();
void RefreshSkins(); void RefreshSkins();
void RandomSkin(); 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 // menus_settings_assets.cpp
public: public:
struct SCustomItem struct SCustomItem
@ -267,7 +157,6 @@ protected:
int m_ActivePage; int m_ActivePage;
bool m_ShowStart; bool m_ShowStart;
bool m_MenuActive; bool m_MenuActive;
vec2 m_MousePos;
bool m_JoinTutorial; bool m_JoinTutorial;
char m_aNextServer[256]; char m_aNextServer[256];
@ -434,6 +323,7 @@ protected:
CLineInputBuffered<IO_MAX_PATH_LENGTH> m_DemoRenderInput; CLineInputBuffered<IO_MAX_PATH_LENGTH> m_DemoRenderInput;
int m_DemolistSelectedIndex; int m_DemolistSelectedIndex;
bool m_DemolistSelectedIsDir; bool m_DemolistSelectedIsDir;
bool m_DemolistSelectedReveal = false;
int m_DemolistStorageType; int m_DemolistStorageType;
int m_Speed = 4; int m_Speed = 4;
@ -526,11 +416,13 @@ protected:
void UpdateMusicState(); void UpdateMusicState();
// found in menus_demo.cpp // found in menus_demo.cpp
vec2 m_DemoControlsPositionOffset = vec2(0.0f, 0.0f);
static bool DemoFilterChat(const void *pData, int Size, void *pUser); static bool DemoFilterChat(const void *pData, int Size, void *pUser);
bool FetchHeader(CDemoItem &Item); bool FetchHeader(CDemoItem &Item);
void FetchAllHeaders(); void FetchAllHeaders();
void HandleDemoSeeking(float PositionToSeek, float TimeToSeek); void HandleDemoSeeking(float PositionToSeek, float TimeToSeek);
void RenderDemoPlayer(CUIRect MainView); void RenderDemoPlayer(CUIRect MainView);
void RenderDemoPlayerSliceSavePopup(CUIRect MainView);
void RenderDemoList(CUIRect MainView); void RenderDemoList(CUIRect MainView);
void PopupConfirmDeleteDemo(); void PopupConfirmDeleteDemo();
@ -596,6 +488,7 @@ protected:
void SetNeedSendInfo(); void SetNeedSendInfo();
void SetActive(bool Active); void SetActive(bool Active);
void UpdateColors();
IGraphics::CTextureHandle m_TextureBlob; IGraphics::CTextureHandle m_TextureBlob;
@ -734,7 +627,6 @@ public:
std::chrono::nanoseconds m_PopupWarningDuration; std::chrono::nanoseconds m_PopupWarningDuration;
int m_DemoPlayerState; int m_DemoPlayerState;
char m_aDemoPlayerPopupHint[256];
enum enum
{ {
@ -769,11 +661,8 @@ private:
// found in menus_settings.cpp // found in menus_settings.cpp
void RenderSettingsDDNet(CUIRect MainView); void RenderSettingsDDNet(CUIRect MainView);
void RenderSettingsAppearance(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); 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; CServerProcess m_ServerProcess;
}; };
#endif #endif

View file

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

View file

@ -28,13 +28,6 @@
using namespace FontIcons; using namespace FontIcons;
using namespace std::chrono_literals; 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) 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); 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_SuppressEvents = false;
m_pClient->m_MapLayersBackGround.EnvelopeUpdate(); m_pClient->m_MapLayersBackGround.EnvelopeUpdate();
m_pClient->m_MapLayersForeGround.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) void CMenus::RenderDemoPlayer(CUIRect MainView)
{ {
const IDemoPlayer::CInfo *pInfo = DemoPlayer()->BaseInfo(); 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; 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 // handle keyboard shortcuts independent of active menu
float PositionToSeek = -1.0f; float PositionToSeek = -1.0f;
float TimeToSeek = 0.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 // render speed info
if(g_Config.m_ClDemoShowSpeed && time_get() - s_LastSpeedChange < time_freq() * 1) if(g_Config.m_ClDemoShowSpeed && time_get() - s_LastSpeedChange < time_freq() * 1)
@ -321,20 +221,70 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
return; return;
} }
MainView.HSplitBottom(TotalHeight, 0, &MainView); CUIRect DemoControls;
MainView.VSplitLeft(50.0f, 0, &MainView); MainView.HSplitBottom(TotalHeight, nullptr, &DemoControls);
MainView.VSplitLeft(600.0f, &MainView, 0); DemoControls.VSplitLeft(50.0f, nullptr, &DemoControls);
DemoControls.VSplitLeft(600.0f, &DemoControls, nullptr);
MainView.Draw(ms_ColorTabbarActive, IGraphics::CORNER_T, 10.0f); const CUIRect DemoControlsOriginal = DemoControls;
DemoControls.x += m_DemoControlsPositionOffset.x;
MainView.Margin(5.0f, &MainView); 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; CUIRect SeekBar, ButtonBar, NameBar, SpeedBar;
DemoControls.Margin(5.0f, &DemoControls);
MainView.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar); DemoControls.HSplitTop(SeekBarHeight, &SeekBar, &ButtonBar);
ButtonBar.HSplitTop(Margins, 0, &ButtonBar); ButtonBar.HSplitTop(Margins, nullptr, &ButtonBar);
ButtonBar.HSplitBottom(NameBarHeight, &ButtonBar, &NameBar); 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 // do seekbar
{ {
@ -427,14 +377,14 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
if(Input()->ShiftIsPressed()) if(Input()->ShiftIsPressed())
{ {
AmountSeek = s_PrevAmount + (AmountSeek - s_PrevAmount) * 0.05f; 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; PositionToSeek = AmountSeek;
} }
} }
else 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; s_PrevAmount = AmountSeek;
PositionToSeek = 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")); GameClient()->m_Tooltips.DoToolTip(&s_PlayPauseButton, &Button, pInfo->m_Paused ? Localize("Play the current demo") : Localize("Pause the current demo"));
// stop button // stop button
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_ResetButton; static CButtonContainer s_ResetButton;
if(DoButton_FontIcon(&s_ResetButton, FONT_ICON_STOP, false, &Button, IGraphics::CORNER_ALL)) 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")); GameClient()->m_Tooltips.DoToolTip(&s_ResetButton, &Button, Localize("Stop the current demo"));
// one tick back // one tick back
ButtonBar.VSplitLeft(Margins + 10.0f, 0, &ButtonBar); ButtonBar.VSplitLeft(Margins + 10.0f, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneTickBackButton; static CButtonContainer s_OneTickBackButton;
if(DoButton_FontIcon(&s_OneTickBackButton, FONT_ICON_CHEVRON_LEFT, 0, &Button, IGraphics::CORNER_ALL)) 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")); GameClient()->m_Tooltips.DoToolTip(&s_OneTickBackButton, &Button, Localize("Go back one tick"));
// one tick forward // one tick forward
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneTickForwardButton; static CButtonContainer s_OneTickForwardButton;
if(DoButton_FontIcon(&s_OneTickForwardButton, FONT_ICON_CHEVRON_RIGHT, 0, &Button, IGraphics::CORNER_ALL)) 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 // slice begin button
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_SliceBeginButton; 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(); Client()->DemoSliceBegin();
if(CurrentTick > (g_Config.m_ClDemoSliceEnd - pInfo->m_FirstTick)) if(CurrentTick > (g_Config.m_ClDemoSliceEnd - pInfo->m_FirstTick))
g_Config.m_ClDemoSliceEnd = -1; 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 // slice end button
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_SliceEndButton; 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(); Client()->DemoSliceEnd();
if(CurrentTick < (g_Config.m_ClDemoSliceBegin - pInfo->m_FirstTick)) if(CurrentTick < (g_Config.m_ClDemoSliceBegin - pInfo->m_FirstTick))
g_Config.m_ClDemoSliceBegin = -1; 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 // slice save button
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_SliceSaveButton; static CButtonContainer s_SliceSaveButton;
if(DoButton_FontIcon(&s_SliceSaveButton, FONT_ICON_ARROW_UP_RIGHT_FROM_SQUARE, 0, &Button, IGraphics::CORNER_ALL)) 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.Set(aDemoName);
m_DemoSliceInput.Append(".demo"); m_DemoSliceInput.Append(".demo");
UI()->SetActiveItem(&m_DemoSliceInput); UI()->SetActiveItem(&m_DemoSliceInput);
m_aDemoPlayerPopupHint[0] = '\0';
m_DemoPlayerState = DEMOPLAYER_SLICE_SAVE; m_DemoPlayerState = DEMOPLAYER_SLICE_SAVE;
} }
GameClient()->m_Tooltips.DoToolTip(&s_SliceSaveButton, &Button, Localize("Export cut as a separate demo")); 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; const int Threshold = 10;
// one marker back // one marker back
ButtonBar.VSplitLeft(Margins + 20.0f, 0, &ButtonBar); ButtonBar.VSplitLeft(Margins + 20.0f, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneMarkerBackButton; static CButtonContainer s_OneMarkerBackButton;
if(DoButton_FontIcon(&s_OneMarkerBackButton, FONT_ICON_BACKWARD_STEP, 0, &Button, IGraphics::CORNER_ALL)) 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--) 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) 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; PositionToSeek = (float)(pInfo->m_aTimelineMarkers[i] - pInfo->m_FirstTick) / TotalTicks;
break; break;
} }
PositionToSeek = 0.0f;
} }
}
GameClient()->m_Tooltips.DoToolTip(&s_OneMarkerBackButton, &Button, Localize("Go back one marker")); GameClient()->m_Tooltips.DoToolTip(&s_OneMarkerBackButton, &Button, Localize("Go back one marker"));
// one marker forward // one marker forward
ButtonBar.VSplitLeft(Margins, 0, &ButtonBar); ButtonBar.VSplitLeft(Margins, nullptr, &ButtonBar);
ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar); ButtonBar.VSplitLeft(ButtonbarHeight, &Button, &ButtonBar);
static CButtonContainer s_OneMarkerForwardButton; static CButtonContainer s_OneMarkerForwardButton;
if(DoButton_FontIcon(&s_OneMarkerForwardButton, FONT_ICON_FORWARD_STEP, 0, &Button, IGraphics::CORNER_ALL)) 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++) 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) 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; PositionToSeek = (float)(pInfo->m_aTimelineMarkers[i] - pInfo->m_FirstTick) / TotalTicks;
break; break;
} }
PositionToSeek = 1.0f;
} }
}
GameClient()->m_Tooltips.DoToolTip(&s_OneMarkerForwardButton, &Button, Localize("Go forward one marker")); GameClient()->m_Tooltips.DoToolTip(&s_OneMarkerForwardButton, &Button, Localize("Go forward one marker"));
// close button // close button
ButtonBar.VSplitRight(ButtonbarHeight * 3, &ButtonBar, &Button); ButtonBar.VSplitRight(ButtonbarHeight, &ButtonBar, &Button);
static int s_ExitButton = 0; static CButtonContainer s_ExitButton;
if(DoButton_DemoPlayer(&s_ExitButton, Localize("Close"), 0, &Button) || (Input()->KeyPress(KEY_C) && m_pClient->m_GameConsole.IsClosed() && m_DemoPlayerState == DEMOPLAYER_NONE)) 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(); Client()->Disconnect();
DemolistOnUpdate(false); DemolistOnUpdate(false);
} }
GameClient()->m_Tooltips.DoToolTip(&s_ExitButton, &Button, Localize("Close the demo player"));
// toggle keyboard shortcuts button // toggle keyboard shortcuts button
ButtonBar.VSplitRight(Margins, &ButtonBar, 0); ButtonBar.VSplitRight(Margins, &ButtonBar, nullptr);
ButtonBar.VSplitRight(ButtonbarHeight, &ButtonBar, &Button); ButtonBar.VSplitRight(ButtonbarHeight, &ButtonBar, &Button);
static CButtonContainer s_KeyboardShortcutsButton; static CButtonContainer s_KeyboardShortcutsButton;
if(DoButton_FontIcon(&s_KeyboardShortcutsButton, FONT_ICON_KEYBOARD, 0, &Button, IGraphics::CORNER_ALL, g_Config.m_ClDemoKeyboardShortcuts != 0)) 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)); DemoPlayer()->GetDemoName(aDemoName, sizeof(aDemoName));
char aBuf[IO_MAX_PATH_LENGTH + 128]; char aBuf[IO_MAX_PATH_LENGTH + 128];
str_format(aBuf, sizeof(aBuf), Localize("Demofile: %s"), aDemoName); str_format(aBuf, sizeof(aBuf), Localize("Demofile: %s"), aDemoName);
CTextCursor Cursor; UI()->DoLabel(&NameBar, aBuf, Button.h * 0.5f, TEXTALIGN_ML);
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);
if(IncreaseDemoSpeed) if(IncreaseDemoSpeed)
{ {
@ -646,6 +607,135 @@ void CMenus::RenderDemoPlayer(CUIRect MainView)
} }
HandleDemoSeeking(PositionToSeek, TimeToSeek); 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) 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 = Reset ? !m_vDemos.empty() ? 0 : -1 :
m_DemolistSelectedIndex >= (int)m_vDemos.size() ? m_vDemos.size() - 1 : m_DemolistSelectedIndex; 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_DemolistSelectedIsDir = m_DemolistSelectedIndex < 0 ? false : m_vDemos[m_DemolistSelectedIndex].m_IsDir;
m_DemolistSelectedReveal = true;
} }
bool CMenus::FetchHeader(CDemoItem &Item) bool CMenus::FetchHeader(CDemoItem &Item)
@ -934,7 +1025,6 @@ void CMenus::RenderDemoList(CUIRect MainView)
if(i + 1 < NumCols) if(i + 1 < NumCols)
{ {
//Cols[i].flags |= SPACER;
Headers.VSplitLeft(2, &s_aCols[i].m_Spacer, &Headers); Headers.VSplitLeft(2, &s_aCols[i].m_Spacer, &Headers);
} }
} }
@ -976,6 +1066,11 @@ void CMenus::RenderDemoList(CUIRect MainView)
} }
static CListBox s_ListBox; 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); s_ListBox.DoStart(ms_ListheaderHeight, m_vDemos.size(), 1, 3, m_DemolistSelectedIndex, &ListBox, false);
int ItemIndex = -1; int ItemIndex = -1;
@ -1079,7 +1174,7 @@ void CMenus::RenderDemoList(CUIRect MainView)
} }
static CButtonContainer s_PlayButton; 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) if(m_DemolistSelectedIndex >= 0)
{ {
@ -1089,8 +1184,8 @@ void CMenus::RenderDemoList(CUIRect MainView)
fs_parent_dir(m_aCurrentDemoFolder); fs_parent_dir(m_aCurrentDemoFolder);
else // sub folder else // sub folder
{ {
str_append(m_aCurrentDemoFolder, "/", sizeof(m_aCurrentDemoFolder)); str_append(m_aCurrentDemoFolder, "/");
str_append(m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename, sizeof(m_aCurrentDemoFolder)); str_append(m_aCurrentDemoFolder, m_vDemos[m_DemolistSelectedIndex].m_aFilename);
m_DemolistStorageType = m_vDemos[m_DemolistSelectedIndex].m_StorageType; m_DemolistStorageType = m_vDemos[m_DemolistSelectedIndex].m_StorageType;
} }
DemolistPopulate(); DemolistPopulate();

View file

@ -301,7 +301,7 @@ void CMenus::RenderPlayers(CUIRect MainView)
CTeeRenderInfo TeeInfo = CurrentClient.m_RenderInfo; CTeeRenderInfo TeeInfo = CurrentClient.m_RenderInfo;
TeeInfo.m_Size = Button.h; TeeInfo.m_Size = Button.h;
CAnimState *pIdleState = CAnimState::GetIdle(); const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid; vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid); RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(Button.x + Button.h / 2, Button.y + Button.h / 2 + OffsetToMid.y); 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.HSplitTop(1.5f, nullptr, &Player);
Player.VSplitMid(&Player, &Button); Player.VSplitMid(&Player, &Button);
Row.VSplitRight(210.0f, &Button2, &Row); 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); UI()->DoLabel(&Player, CurrentClient.m_aName, 14.0f, TEXTALIGN_ML);
Cursor.m_LineWidth = Button.w; UI()->DoLabel(&Button, CurrentClient.m_aClan, 14.0f, TEXTALIGN_ML);
TextRender()->TextEx(&Cursor, CurrentClient.m_aClan, -1);
ColorRGBA Color(1.0f, 1.0f, 1.0f, 0.5f); m_pClient->m_CountryFlags.Render(CurrentClient.m_Country, ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f),
m_pClient->m_CountryFlags.Render(CurrentClient.m_Country, &Color,
Button2.x, Button2.y + Button2.h / 2.0f - 0.75f * Button2.h / 2.0f, 1.5f * Button2.h, 0.75f * Button2.h); 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 // ignore chat button
@ -604,7 +598,7 @@ bool CMenus::RenderServerControlKick(CUIRect MainView, bool FilterSpectators)
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[aPlayerIDs[i]].m_RenderInfo; CTeeRenderInfo TeeInfo = m_pClient->m_aClients[aPlayerIDs[i]].m_RenderInfo;
TeeInfo.m_Size = TeeRect.h; TeeInfo.m_Size = TeeRect.h;
CAnimState *pIdleState = CAnimState::GetIdle(); const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid; vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid); RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(TeeRect.x + TeeInfo.m_Size / 2, TeeRect.y + TeeInfo.m_Size / 2 + OffsetToMid.y); 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) else if(Id == COL_NAME)
{ {
CTextCursor Cursor; UI()->DoLabel(&Button, pGhost->m_aPlayer, 12.0f, TEXTALIGN_ML);
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);
} }
else if(Id == COL_TIME) 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]; char aBuf[64];
str_time(pGhost->m_Time / 10, TIME_HOURS_CENTISECS, aBuf, sizeof(aBuf)); 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/color.h>
#include <base/math.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; vec2 HandPos = CenterPos + Dir;
float Angle = angle(Dir); float Angle = angle(Dir);
@ -666,7 +666,7 @@ void CPlayers::RenderPlayer(
RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position, Alpha); RenderTools()->RenderTee(&State, &RenderInfo, Player.m_Emote, Direction, Position, Alpha);
float TeeAnimScale, TeeBaseSize; 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; vec2 BodyPos = Position + vec2(State.GetBody()->m_X, State.GetBody()->m_Y) * TeeAnimScale;
if(RenderInfo.m_TeeRenderFlags & TEE_EFFECT_FROZEN) if(RenderInfo.m_TeeRenderFlags & TEE_EFFECT_FROZEN)
{ {

View file

@ -13,7 +13,7 @@ class CPlayers : public CComponent
CTeeRenderInfo m_RenderInfoSpec; CTeeRenderInfo m_RenderInfoSpec;
CTeeRenderInfo m_aRenderInfo[MAX_CLIENTS]; 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( void RenderPlayer(
const CNetObj_Character *pPrevChar, const CNetObj_Character *pPrevChar,
const CNetObj_Character *pPlayerChar, 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) while(TextRender()->TextWidth(TitleFontsize, aBuf, -1, -1.0f) > TitleWidth)
aBuf[str_length(aBuf) - 1] = '\0'; aBuf[str_length(aBuf) - 1] = '\0';
if(str_comp(aBuf, Client()->GetCurrentMap())) if(str_comp(aBuf, Client()->GetCurrentMap()))
str_append(aBuf, "", sizeof(aBuf)); str_append(aBuf, "");
pTitle = aBuf; pTitle = aBuf;
} }
} }
@ -432,7 +432,7 @@ void CScoreboard::RenderScoreboard(float x, float y, float w, int Team, const ch
// avatar // avatar
CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientID].m_RenderInfo; CTeeRenderInfo TeeInfo = m_pClient->m_aClients[pInfo->m_ClientID].m_RenderInfo;
TeeInfo.m_Size *= TeeSizeMod; TeeInfo.m_Size *= TeeSizeMod;
CAnimState *pIdleState = CAnimState::GetIdle(); const CAnimState *pIdleState = CAnimState::GetIdle();
vec2 OffsetToMid; vec2 OffsetToMid;
RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid); RenderTools()->GetRenderTeeOffsetToRenderedTee(pIdleState, &TeeInfo, OffsetToMid);
vec2 TeeRenderPos(TeeOffset + TeeLength / 2, y + LineHeight / 2.0f + OffsetToMid.y); 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); TextRender()->TextColor(1.0f, 1.0f, 1.0f, 1.0f);
// country flag // 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, ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f),
m_pClient->m_CountryFlags.Render(m_pClient->m_aClients[pInfo->m_ClientID].m_Country, &Color,
CountryOffset, y + (Spacing + TeeSizeMod * 5.0f) / 2.0f, CountryLength, LineHeight - Spacing - TeeSizeMod * 5.0f); CountryOffset, y + (Spacing + TeeSizeMod * 5.0f) / 2.0f, CountryLength, LineHeight - Spacing - TeeSizeMod * 5.0f);
// ping // 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_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_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()) if(m_pClient->DemoRecorder(RECORDER_RACE)->IsRecording())
{ {
str_time((int64_t)m_pClient->DemoRecorder(RECORDER_RACE)->Length() * 100, TIME_HOURS, aTime, sizeof(aTime)); 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_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()) if(m_pClient->DemoRecorder(RECORDER_AUTO)->IsRecording())
{ {
str_time((int64_t)m_pClient->DemoRecorder(RECORDER_AUTO)->Length() * 100, TIME_HOURS, aTime, sizeof(aTime)); 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_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()) if(m_pClient->DemoRecorder(RECORDER_REPLAYS)->IsRecording())
{ {
str_time((int64_t)m_pClient->DemoRecorder(RECORDER_REPLAYS)->Length() * 100, TIME_HOURS, aTime, sizeof(aTime)); 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_format(aBuf2, sizeof(aBuf2), "%s %s ", Localize("Replay"), aTime);
str_append(aBuf, aBuf2, sizeof(aBuf)); str_append(aBuf, aBuf2);
} }
if(!aBuf[0]) if(!aBuf[0])

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