From dbde914a9bbc42bb5af41ef93f31cbe31a5adb29 Mon Sep 17 00:00:00 2001 From: oldmud0 <3421260-oldmud0@users.noreply.gitlab.com> Date: Sun, 17 May 2020 23:54:35 +0000 Subject: [PATCH 01/46] Bundle QtApng on Windows --- .gitlab-ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index bc15619..5c1da36 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -83,6 +83,9 @@ build windows i686: - git submodule init - git submodule update + # Print versions + - /opt/mxe/usr/${TARGET_SPEC}/qt5/bin/qmake --version + # Extract BASS - mkdir bass - cd bass @@ -94,6 +97,14 @@ build windows i686: - cp bassopus.dll ../lib - cd .. + # Extract QtApng + - mkdir qtapng + - cd qtapng + - curl -L https://github.com/Skycoder42/QtApng/releases/download/1.1.2-2/qtapng_mingw73_32_5.13.0.zip -o apng.zip + - unzip apng.zip + - cp mingw73_32/plugins/imageformats/qapng.dll ../lib + - cd .. + # Build - /opt/mxe/usr/${TARGET_SPEC}/qt5/bin/qmake "DEFINES += DISCORD BASSAUDIO" - make -j4 @@ -165,6 +176,8 @@ deploy windows i686: # Platform-specific - cp -a ../lib/*.dll . + - mkdir imageformats + - cp -a ../lib/imageformats/*.dll imageformats/ - cp -a ../bin/Attorney_Online.exe . # Zipping From c9b9822bdbf9d0ade3c516d4b63a6a2e73245610 Mon Sep 17 00:00:00 2001 From: oldmud0 <3421260-oldmud0@users.noreply.gitlab.com> Date: Mon, 18 May 2020 00:01:00 +0000 Subject: [PATCH 02/46] CI: Copy qapng.dll to correct location --- .gitlab-ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5c1da36..ae0f87a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -102,7 +102,8 @@ build windows i686: - cd qtapng - curl -L https://github.com/Skycoder42/QtApng/releases/download/1.1.2-2/qtapng_mingw73_32_5.13.0.zip -o apng.zip - unzip apng.zip - - cp mingw73_32/plugins/imageformats/qapng.dll ../lib + - mkdir ../lib/imageformats + - cp mingw73_32/plugins/imageformats/qapng.dll ../lib/imageformats/ - cd .. # Build From bc4fd2bccd1f62696c3da4f765684527fcbb8e50 Mon Sep 17 00:00:00 2001 From: oldmud0 <3421260-oldmud0@users.noreply.gitlab.com> Date: Tue, 19 May 2020 22:24:38 +0000 Subject: [PATCH 03/46] CI: Don't use dynamic QtApng on Windows --- .gitlab-ci.yml | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ae0f87a..116e340 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -98,13 +98,15 @@ build windows i686: - cd .. # Extract QtApng - - mkdir qtapng - - cd qtapng - - curl -L https://github.com/Skycoder42/QtApng/releases/download/1.1.2-2/qtapng_mingw73_32_5.13.0.zip -o apng.zip - - unzip apng.zip - - mkdir ../lib/imageformats - - cp mingw73_32/plugins/imageformats/qapng.dll ../lib/imageformats/ - - cd .. + # - mkdir qtapng + # - cd qtapng + # - curl -L https://github.com/Skycoder42/QtApng/releases/download/1.1.2-2/qtapng_mingw73_32_5.13.0.zip -o apng.zip + # - unzip apng.zip + # - mkdir ../lib/imageformats + # - cp mingw73_32/plugins/imageformats/qapng.dll ../lib/imageformats/ + # - cd .. + + - ls lib # Build - /opt/mxe/usr/${TARGET_SPEC}/qt5/bin/qmake "DEFINES += DISCORD BASSAUDIO" @@ -178,7 +180,7 @@ deploy windows i686: # Platform-specific - cp -a ../lib/*.dll . - mkdir imageformats - - cp -a ../lib/imageformats/*.dll imageformats/ + - cp -a ../lib/imageformats/*.dll imageformats/ || : - cp -a ../bin/Attorney_Online.exe . # Zipping From 4f8367bf2f5b3294d9a82ebf9fb08d6e3bf83b94 Mon Sep 17 00:00:00 2001 From: oldmud0 <3421260-oldmud0@users.noreply.gitlab.com> Date: Tue, 19 May 2020 22:28:21 +0000 Subject: [PATCH 04/46] CI: Fix YAML syntax error --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 116e340..01f69c3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -180,7 +180,7 @@ deploy windows i686: # Platform-specific - cp -a ../lib/*.dll . - mkdir imageformats - - cp -a ../lib/imageformats/*.dll imageformats/ || : + - 'cp -a ../lib/imageformats/*.dll imageformats/ || :' - cp -a ../bin/Attorney_Online.exe . # Zipping From 8989c4fbc944a9658bd7817d33ec52a3976172f9 Mon Sep 17 00:00:00 2001 From: oldmud0 <3421260-oldmud0@users.noreply.gitlab.com> Date: Tue, 19 May 2020 23:50:48 +0000 Subject: [PATCH 05/46] CI: Update Dockerfile --- scripts/windows/Dockerfile | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/scripts/windows/Dockerfile b/scripts/windows/Dockerfile index f4f1a83..b9a12d6 100644 --- a/scripts/windows/Dockerfile +++ b/scripts/windows/Dockerfile @@ -10,5 +10,12 @@ RUN /opt/mxe/usr/bin/${TARGET_SPEC}-cmake .. -DCMAKE_INSTALL_PREFIX=/opt/mxe/usr RUN /opt/mxe/usr/bin/${TARGET_SPEC}-cmake --build . --config Release --target install WORKDIR ../.. -# NOTE: Do not build QtApng statically! libpng contains a self-test entry point that -# takes precedence for some reason over the final build's entry point. +# Build QtApng statically +RUN git clone https://github.com/Skycoder42/QtApng +WORKDIR QtApng +# libpng contains a self-test entry point that takes precedence for some reason +# over the final build's entry point. +RUN sed -i "s/^main(/libpng_main(/g" src/3rdparty/libpng/src/pngtest.c +RUN /opt/mxe/usr/${TARGET_SPEC}/qt5/bin/qmake +RUN make && make install +WORKDIR .. \ No newline at end of file From 775417520678862a46e121efb8804a1998232228 Mon Sep 17 00:00:00 2001 From: oldmud0 <3421260-oldmud0@users.noreply.gitlab.com> Date: Wed, 20 May 2020 18:20:44 +0000 Subject: [PATCH 06/46] CI: use simpler release script --- .gitlab-ci.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 01f69c3..b11cfbd 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -213,8 +213,11 @@ publish linux x86_64: - deploy linux x86_64 when: manual script: + - apt-get update + - apt-get install --no-install-recommends -y awscli + - cd zip - - ../scripts/wasabi.sh + - ../scripts/wasabi_program.sh variables: MANIFEST: program_linux_x86_64.json ARTIFACT_SUFFIX: _linux_x64.tar.xz @@ -226,8 +229,11 @@ publish windows i686: - deploy windows i686 when: manual script: + - apt-get update + - apt-get install --no-install-recommends -y awscli + - cd zip - - ../scripts/wasabi.sh + - ../scripts/wasabi_program.sh variables: MANIFEST: program_winnt_i386.json ARTIFACT_SUFFIX: _windows_x86.zip From 2cf5a046cae02d6e0da283190f7c303f607e1c75 Mon Sep 17 00:00:00 2001 From: oldmud0 <3421260-oldmud0@users.noreply.gitlab.com> Date: Wed, 20 May 2020 19:08:38 +0000 Subject: [PATCH 07/46] wasabi_program.sh: use bash instead of sh --- scripts/wasabi_program.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/wasabi_program.sh b/scripts/wasabi_program.sh index 41e2e35..37feac6 100755 --- a/scripts/wasabi_program.sh +++ b/scripts/wasabi_program.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash # Updates the specified program manifest to a new archive and version # and uploads the new archive and manifest to S3/Wasabi. # From 8a4d5e88e0b9e917c5cb3e47fd10ded9d0484b68 Mon Sep 17 00:00:00 2001 From: oldmud0 <3421260-oldmud0@users.noreply.gitlab.com> Date: Wed, 20 May 2020 19:24:56 +0000 Subject: [PATCH 08/46] CI: install more dependencies for publish job --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b11cfbd..162d5d5 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -214,7 +214,7 @@ publish linux x86_64: when: manual script: - apt-get update - - apt-get install --no-install-recommends -y awscli + - apt-get install --no-install-recommends -y git nodejs awscli - cd zip - ../scripts/wasabi_program.sh @@ -230,7 +230,7 @@ publish windows i686: when: manual script: - apt-get update - - apt-get install --no-install-recommends -y awscli + - apt-get install --no-install-recommends -y git nodejs awscli - cd zip - ../scripts/wasabi_program.sh From 5a023e3e07c6d9f0649b5c6b915be9984508415c Mon Sep 17 00:00:00 2001 From: oldmud0 <3421260-oldmud0@users.noreply.gitlab.com> Date: Wed, 20 May 2020 19:38:23 +0000 Subject: [PATCH 09/46] CI: npm install before running script --- .gitlab-ci.yml | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 162d5d5..e9685de 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -214,13 +214,16 @@ publish linux x86_64: when: manual script: - apt-get update - - apt-get install --no-install-recommends -y git nodejs awscli + - apt-get install --no-install-recommends -y git nodejs npm awscli + - cd scripts + - npm install + - cd .. - cd zip - ../scripts/wasabi_program.sh variables: MANIFEST: program_linux_x86_64.json - ARTIFACT_SUFFIX: _linux_x64.tar.xz + ARTIFACT_SUFFIX: linux_x64.tar.xz publish windows i686: image: ubuntu @@ -230,10 +233,13 @@ publish windows i686: when: manual script: - apt-get update - - apt-get install --no-install-recommends -y git nodejs awscli + - apt-get install --no-install-recommends -y git nodejs npm awscli + - cd scripts + - npm install + - cd .. - cd zip - ../scripts/wasabi_program.sh variables: MANIFEST: program_winnt_i386.json - ARTIFACT_SUFFIX: _windows_x86.zip + ARTIFACT_SUFFIX: windows_x86.zip From 07e1127096d4e47f39facc43ecbf94007c8e08b8 Mon Sep 17 00:00:00 2001 From: windrammer <31085911+likeawindrammer@users.noreply.github.com> Date: Tue, 4 Aug 2020 09:03:40 -0600 Subject: [PATCH 10/46] Fix current_display_speed overflow (#232) --- src/courtroom.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 98b6a9c..d727b81 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -2914,6 +2914,12 @@ void Courtroom::chat_tick() next_character_is_not_special = false; } + // Keep the speed at bay. + if (current_display_speed < 0) + current_display_speed = 0; + else if (current_display_speed > 6) + current_display_speed = 6; + if ((message_display_speed[current_display_speed] <= 0 && tick_pos < f_message.size() - 1) || formatting_char) { @@ -2942,12 +2948,6 @@ void Courtroom::chat_tick() ui_vp_message->ensureCursorVisible(); - // Keep the speed at bay. - if (current_display_speed < 0) - current_display_speed = 0; - else if (current_display_speed > 6) - current_display_speed = 6; - // Blip player and real tick pos ticker if (!formatting_char && (f_character != ' ' || blank_blip)) { if (blip_ticker % blip_rate == 0) { From 630518020a385391469f0b710a8a59cd2984c2c7 Mon Sep 17 00:00:00 2001 From: windrammer <31085911+likeawindrammer@users.noreply.github.com> Date: Tue, 4 Aug 2020 09:09:27 -0600 Subject: [PATCH 11/46] Fix music display disappearing on theme reload (#233) --- src/courtroom.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index d727b81..8223024 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -636,6 +636,7 @@ void Courtroom::set_widgets() } ui_music_display->play("music_display"); + ui_music_display->set_play_once(false); if (is_ao2_bg) { set_size_and_pos(ui_ic_chat_message, "ao2_ic_chat_message"); From 0ce60d66a779ee91f85ebc9f92b2fe52c632b868 Mon Sep 17 00:00:00 2001 From: windrammer <31085911+likeawindrammer@users.noreply.github.com> Date: Wed, 5 Aug 2020 08:18:08 -0600 Subject: [PATCH 12/46] Fix not using custom chatbox's colors (#228) * Fix not using custom chatbox's colors Moved set_text_color_dropdown() to after current_char is actually updated with the selected char. Otherwise set_text_color_dropdown will try to update the colors with either nothing as character, or with the previously selected character. Use get_chat() so it actually gets the name of the custom chatbox instead of using the same name as the character. Remove the extra "c" since get_chat_color it's already called with this "c" in place. * Fix previous fix crashing the client on DRO servers For some reason the client would work just fine if set_text_color_dropdown() was called only once after updating the character selected by the user. But when joining a DRO server the client would crash just before loading the music. * Improve comment with where crash happens * Fix get_chat_markdown to get the custom chatbox on misc of the char instead of trying to find the character folder on misc * Fix client using the current character colors on other people's messages Also remove the comment explaining the crash if set_text_color_dropdown is removed from set_widgets * Fix loading custom colors loading after the message was added to the log --- src/courtroom.cpp | 14 ++++++++++++-- src/text_file_functions.cpp | 6 +++--- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 8223024..a0c7e2c 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1238,6 +1238,8 @@ void Courtroom::update_character(int p_cid) current_char = f_char; current_side = ao_app->get_char_side(current_char); + set_text_color_dropdown(); + current_emote_page = 0; current_emote = 0; @@ -1879,11 +1881,19 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) ic_chatlog_history.removeFirst(); } - append_ic_text(m_chatmessage[MESSAGE], f_showname, "", m_chatmessage[TEXT_COLOR].toInt()); - QString f_char = m_chatmessage[CHAR_NAME]; QString f_custom_theme = ao_app->get_char_shouts(f_char); + // Load the colors in case it's using a custom chatbox with custom colors. + // Or reload the default ones in case it's not using custom colors + color_rgb_list.clear(); + for (int c = 0; c < max_colors; ++c) { + QColor color = ao_app->get_chat_color("c" + QString::number(c), f_char); + color_rgb_list.append(color); + } + + append_ic_text(m_chatmessage[MESSAGE], f_showname, "", m_chatmessage[TEXT_COLOR].toInt()); + // if an objection is used if (objection_mod <= 4 && objection_mod >= 1) { switch (objection_mod) { diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 39754f3..4ceb29a 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -435,7 +435,7 @@ QString AOApplication::get_tagged_stylesheet(QString target_tag, QString p_file) QString AOApplication::get_chat_markdown(QString p_identifier, QString p_chat) { - QString design_ini_path = get_base_path() + "misc/" + p_chat + "/config.ini"; + QString design_ini_path = get_base_path() + "misc/" + get_chat(p_chat) + "/config.ini"; QString default_path = get_base_path() + "misc/default/config.ini"; QString f_result = read_design_ini(p_identifier, design_ini_path); @@ -449,9 +449,9 @@ QColor AOApplication::get_chat_color(QString p_identifier, QString p_chat) { QColor return_color(255, 255, 255); - QString design_ini_path = get_base_path() + "misc/" + p_chat + "/config.ini"; + QString design_ini_path = get_base_path() + "misc/" + get_chat(p_chat) + "/config.ini"; QString default_path = get_base_path() + "misc/default/config.ini"; - QString f_result = read_design_ini("c" + p_identifier, design_ini_path); + QString f_result = read_design_ini(p_identifier, design_ini_path); if (f_result == "") { f_result = read_design_ini(p_identifier, default_path); From b04b22b33ab7e1925b5f2a7d574e623c601717c5 Mon Sep 17 00:00:00 2001 From: Emiko <62057364+k-emiko@users.noreply.github.com> Date: Fri, 7 Aug 2020 03:20:20 +1100 Subject: [PATCH 13/46] Update Russian translation (excl. courtroom UI) (#239) Edited TL, added TL for tool tips and other untranslated strings. Courtroom UI elements were left in English to avoid cropping. --- resource/translations/ao_ru.ts | 887 +++++++++++++++++---------------- 1 file changed, 467 insertions(+), 420 deletions(-) diff --git a/resource/translations/ao_ru.ts b/resource/translations/ao_ru.ts index 3b0af42..9347436 100644 --- a/resource/translations/ao_ru.ts +++ b/resource/translations/ao_ru.ts @@ -6,97 +6,99 @@ Disconnected from server. - Соединение с сервером прервано. + Соединение с сервером разорвано. Error connecting to master server. Will try again in %1 seconds. - Ошибка соединения с главным сервером. Попытка пересоединения будет через %1 с. + Ошибка соединения с главным сервером. Повторная попытка соединения через %1 с. There was an error connecting to the master server. We deploy multiple master servers to mitigate any possible downtime, but the client appears to have exhausted all possible methods of finding and connecting to one. Please check your Internet connection and firewall, and please try again. - Произошла ошибка соединения с главным сервером. -Пожалуйста, проверьте ваши Интернет-соединение, настройки браундмауэра, и попробуйте перезайти. + Не удалось соединиться с главным сервером. +Мы используем несколько главных серверов для того, чтобы сократить время простоя, но клиент перепробовал все возможные варианты и не смог подключиться ни к одному из серверов. +Пожалуйста, проверьте ваши настройки браундмауэра и соединение с Интернетом попробуйте перезайти. Outdated version! Your version: %1 Please go to aceattorneyonline.com to update. - Устаревшая версия! У вас установлена %1 + Устаревшая версия! У вас установлена версия %1 Проследуйте на сайт aceattorneyonline.com для обновления. You have been exiled from AO. Have a nice day. - Из AO вас отправили в жизнь. -Хорошего дня. + Вас изгнали из AO. +Всего хорошего. - + Attorney Online 2 Attorney Online 2 - + Loading Загрузка - + Loading evidence: %1/%2 - Загрузка вещдоков: + Загрузка улик: %1/%2 - - + + Loading music: %1/%2 Загрузка музыки: %1/%2 - - + + Loading chars: %1/%2 Загрузка персонажей: %1/%2 - + You have been kicked from the server. Reason: %1 Вас выпнули с сервера. Причина: %1 - + You have been banned from the server. Reason: %1 - + Вы были забанены на сервере. +Причина: %1 - + You are banned on this server. Reason: %1 - Вас отправили в баню. + Вы забанены на этом сервере. Причина: %1 You have been kicked from the server. Reason: - Вас выпнули с сервера. + Вас выпнули с сервера. Причина: You are banned on this server. Reason: - Вас отправили в баню. + Вы забанены на этом сервере. Причина: @@ -105,37 +107,37 @@ Reason: Case Announcer - Материалы дела + Объявление о проведении заседания Case title: - Название: + Название дела: Defense needed - Сторона защиты + Нужна защита Prosecution needed - Сторона обвинения + Нужно обвинение Judge needed - Без судьи никак + Нужен судья Jurors needed - Суд присяжных + Нужны присяжные Stenographer needed - Нужен стенографист? + Нужен стенографист @@ -158,27 +160,29 @@ Reason: Sets the theme used in-game. If the new theme changes the lobby's look as well, you'll need to reload the lobby for the changes to take effect, such as by joining a server and leaving it. - Устанавливает внешний вид игры. Может понадобиться перезайти на сервер. + Определяет внешний вид игры. Для применения новой темы может понадобиться перезайти на сервер. Log goes downwards: - Портянку вниз: + История чата идёт вниз: If ticked, new messages will appear at the bottom (like the OOC chatlog). The traditional (AO1) behaviour is equivalent to this being unticked. - Отметьте галочку, если хотите, чтобы сообщения в игровом чате отображались снизу, а не сверху. + Показывать новые сообщения в игровом чате снизу (как в ООС-чате), а не сверху (как в AO1). Log length: - Длина игрового чата: + Размер истории игрового чата: The amount of messages the IC chatlog will keep before deleting older messages. A value of 0 or below counts as 'infinite'. - Количество сообщений, максимально хранимых в игровом чате. Значение, равное 0 или меньше, будет расценено как снятие такого ограничения. + Максимальное количество сообщений, сохраняемых в игровом чате. +При превышении лимита старые сообщения будут удаляться. +Поставьте 0 или отрицательное значение, чтобы снять ограничение. @@ -188,17 +192,18 @@ Reason: Your OOC name will be automatically set to this value when you join a server. - Псевдоним, используемый при соединении с сервером. В основном, его видно в чате сервера. + Псевдоним по умолчанию для ООС-чата. Custom shownames: - Произвольные имена: + Пользовательские имена: Gives the default value for the in-game 'Custom shownames' tickbox, which in turn determines whether the client should display custom in-character names. - Отображать произвольные имена персонажей, установленные самими игроками. + Задать значение по умолчанию для настройки отображения пользовательских имён, +которая определяет возможность показа в игровом чате имён персонажей, установленных самими игроками. @@ -208,7 +213,7 @@ Reason: If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address. - Отображать перечень серверов от главного сервера, указанного здесь, когда не удалось соединиться с первичным ГС. + Если клиент не сможет соединиться с встроенным главным сервером (ГС), он проверит адреса из этого списка. @@ -218,7 +223,7 @@ Reason: Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for. - Показать в Discord сервер, на котором вы играете, каким персонажем управляете и время игры. + Показывать в Discord сервер, на котором вы играете, вашего персонажа и продолжительность игры. @@ -228,282 +233,303 @@ Reason: Sets the language if you don't want to use your system language. - + Изменяет язык интерфейса программы, если вы не хотите использовать язык системы. - Keep current setting - - - - - Allow Screenshake: - + - сохранить текущие настройки - Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures. - + Allow Screenshake: + Встряска экрана: - - Allow Effects: - + + Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures. + Разрешить показ встрясок экрана. Отключите, если вы страдаете от светочувствительности и/или припадков. + Allow Effects: + Визуальные эффекты: + + + Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures. - + Разрешить показ визуальных эффектов. Отключите, если вы страдаете от светочувствительности и/или припадков. - + Network Frame Effects: - + Эффекты по сети: - + Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality. - - - - - Colors in IC Log: - + Разрешить отправку звуков, эффектов вспышек и встряски экрана по сети в соответствии с char.ini. +Работает только на серверах, поддерживающих данную функцию. - Use the markup colors in the server IC chatlog. - + Colors in IC Log: + Цвета в истории чата: - - Sticky Sounds: - + + Use the markup colors in the server IC chatlog. + Отображать цвета в истории игрового чата. - Turn this on to prevent the sound dropdown from clearing the sound after playing it. - + Sticky Sounds: + Закрепить звуки: - - Sticky Effects: - + + Turn this on to prevent the sound dropdown from clearing the sound after playing it. + Не сбрасывать выбранные настройки звука после его воспроизведения. - Turn this on to prevent the effects dropdown from clearing the effect after playing it. - + Sticky Effects: + Закрепить эффекты: - - Sticky Preanims: - + + Turn this on to prevent the effects dropdown from clearing the effect after playing it. + Не сбрасывать выбранные настройки эффекта после его воспроизведения. - Turn this on to prevent preanimation checkbox from clearing after playing the emote. - + Sticky Preanims: + Закрепить пред. анимации: - + + Turn this on to prevent preanimation checkbox from clearing after playing the emote. + Не сбрасывать настройки пред. анимации после её воспроизведения. + + + + Custom Chatboxes: + Пользовательские подложки: + + + + Turn this on to allow characters to define their own custom chat box designs. + Отображать дизайны подложек, заданные персонажами. + + + Callwords Позывные - + <html><head/><body>Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!<br>Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.</body></html> - <html><head/><body>Введите на отдельных строках свои позывные, при указании которых в сообщениях будет подан звуковой сигнал.</body></html> + <html><head/><body>Введите на отдельных строках свои позывные. Если кто-то в чате напишет их, вы услышите звуковой сигнал. Регистр символов не учитывается.<br>Не оставляйте в конце строк пробелы, иначе вы будете получать оповещения о каждом пробеле в чате.</body></html> - + Audio Аудио - + Audio device: Устройство воспроизведения: - + Sets the audio device for all sounds. - Куда вещать звук из игры. + Укажите устройство вывода всего аудио игры. - + Music: Музыка: - + Sets the music's default volume. Громкость музыки по умолчанию. - + SFX: Звук. эффекты: - + Sets the SFX's default volume. Interjections and actual sound effects count as 'SFX'. - Громкость звуковых эффектов по умолчанию. + Громкость звуковых эффектов по умолчанию. В категорию эффектов также входят возгласы. - + Blips: Сигналы: - + Sets the volume of the blips, the talking sound effects. Громкость сигналов, заменяющих голос, по умолчанию. - + Blip rate: - Пер. сигналов: + Частота сигналов: - + Sets the delay between playing the blip sounds. - Период между сигналами, заменяющими голос, по умолчанию. + Задержка по умолчанию между сигналами, заменяющими голос. - + Play a blip sound "once per every X symbols", where X is the blip rate. - + Проигрывать сигнал "каждые Х символов", где Х - частота. - + Blank blips: Пустые сигналы: - + If true, the game will play a blip sound even when a space is 'being said'. Проигрывать сигналы даже для пробелов. - + Enable Looping SFX: - + Повтор звук. эффектов: - + If true, the game will allow looping sound effects to play on preanimations. - + Разрешить воспроизведение зацикленных звуковых эффектов во время предварительной анимации. - + Kill Music On Objection: - + Тишина при протесте: - + If true, AO2 will stop the music for you when you or someone else does 'Objection!'. - + Останавливать музыку, когда кто-нибудь кричит "Objection!". - + Casing - Заседание + Заседания - + This server supports case alerts. - Этот сервер поддерживает объявление заседания. + Этот сервер поддерживает объявления заседаний. - + This server does not support case alerts. - Этот сервер не поддерживает объявление заседания. + Этот сервер не поддерживает объявления заседаний. - + Pretty self-explanatory. - Весьма доходчиво. + Дополнительные пояснения не требуются. - + Casing: - Новое дело: - - - - If checked, you will get alerts about case announcements. - При заведении дела вы получите уведомление. + Заседания: + If checked, you will get alerts about case announcements. + Вы получите уведомление, когда будет объявлено заседание. + + + Defense: Защита: - + If checked, you will get alerts about case announcements if a defense spot is open. - При заведении дела, в котором нужна сторона защиты, вы получите уведомление. + Вы получите уведомление при объявлении дела, в котором нужна сторона защиты. - + Prosecution: Обвинение: - + If checked, you will get alerts about case announcements if a prosecutor spot is open. - При заведении дела, в котором нужна сторона обвинения, вы получите уведомление. + Вы получите уведомление при объявлении дела, в котором нужна сторона обвинения. - + Judge: Судья: - + If checked, you will get alerts about case announcements if the judge spot is open. - При заведении дела, в котором нужен судья, вы получите уведомление. + Вы получите уведомление при объявлении дела, в котором нужен судья. - + Juror: - Присяжный: + Присяжные: - + If checked, you will get alerts about case announcements if a juror spot is open. - При заведении дела, в котором нужны присяжные заседатели, вы получите уведомление. + Вы получите уведомление при объявлении дела, в котором нужны присяжные заседатели. - + Stenographer: Стенографист: - + If checked, you will get alerts about case announcements if a stenographer spot is open. - При заведении дела, в котором нужна стенография, вы получите уведомление. + Вы получите уведомление при объявлении дела, в котором нужна стенография. - + CM: ПД: - - - If checked, you will appear amongst the potential CMs on the server. - Отметьте, если вы хотите состоять в числе производителей дел. - - - - Hosting cases: - ПД акт.: - + If checked, you will appear amongst the potential CMs on the server. + Отметьте, если хотите состоять в числе возможных производителей дел (ПД). + + + + Hosting cases: + Проведение дел: + + + If you're a CM, enter what cases you are willing to host. - Будучи производителем дела (ПД), вы можете войти в зону и заниматься её оркестровкой. + Если вы производитель дел (ПД), укажите, какими делами вы хотите заниматься. + + + + Automatic Logging: + Авт. сохранение истории: + + + + If checked, all logs will be automatically written in the /logs folder. + Автоматически сохранять всю историю чатов в папке /logs. @@ -516,7 +542,7 @@ Reason: Spectator - Наблюдатель + Зритель @@ -527,7 +553,7 @@ Reason: Passworded - Ограничен паролем + Защищён паролем @@ -535,7 +561,7 @@ Reason: Занят - + Generating chars: %1/%2 Генерация персонажей: @@ -544,7 +570,7 @@ Reason: Generating chars: - Генерация персонажей: + Генерация персонажей: @@ -565,17 +591,17 @@ Reason: Pre - Пред. + Flip - Разв. + Guard - Охрана + @@ -584,73 +610,73 @@ Reason: - + Casing - Дело + Shownames - Произв. имена + No Interrupt - Говорить сразу + White - Белый + Белый Green - Зелëный + Зелëный Red - Красный + Красный Orange - Оранжевый + Оранжевый Blue - Синий + Синий Yellow - Жëлтый + Жëлтый This does nothing, but there you go. - В общем-то, это ни на что не влияет... + В общем-то, это ни на что не влияет... - + You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini. Cases you can load: %1 - Укажите имя файла с делом (без расширения) для загрузки. Убедитесь, что оно расположено в папке `base/cases`. -Были найдены: %1 + Укажите имя файла с делом (без расширения) для загрузки. Убедитесь, что он расположен в папке `base/cases`, и что это правильно отформатированный файл .ini. +Вы можете загрузить следующие дела: %1 - + Case made by %1. - Дело завëл игрок: %1. + Автор дела: %1. - + Navigate to %1 for the CM doc. - Перейдите к %1 для получения материалов дела. + Откройте %1 для получения материалов дела. - + Your case "%1" was loaded! - Дело под кодовым названием "%1" готово! + Ваше дело "%1" было загружено! - - + + Server Сервер @@ -660,582 +686,600 @@ Cases you can load: %1 - + Hold It! - - - + + + When this is turned on, your next in-character message will be a shout! - + Когда эта опция включена, ваше следующее сообщение в игровом чате будет с возгласом! - + Objection! - + Take That! - + Toggle between server chat and global AO2 chat. - - - - - - - - This will display the animation in the viewport as soon as it is pressed. - - - - - Guilty! - + Переключатель между чатом сервера и общим чатом AO2. + + + + This will display the animation in the viewport as soon as it is pressed. + Показать анимацию в игровом чате сразу после нажатия. + + + + Guilty! + Виновен! + + + Bring up the Character Select Screen and change your character. - + Перейти на экран выбора и сменить персонажа. - + Refresh the theme and update all of the ui elements to match. - + Перезагрузить тему и обновить все элементы интерфейса. - + Request the attention of the current server's moderator. - + Привлечь внимание модератора сервера. - + Allows you to change various aspects of the client. - + Изменить параметры работы программы. - + An interface to help you announce a case (you have to be a CM first to be able to announce cases) - + Открыть окно, которое позволит вам объявить о деле +(для этого нужно быть производителем дел (ПД)) - + Switch between Areas and Music lists - + Переключатель между списками музыки и локаций - + Play a single-shot animation as defined by the emote when checked. - + Показать разовую анимацию, соответствующую выбранной эмоции. - + If preanim is checked, display the input text immediately as the animation plays concurrently. - + Если включена предварительная анимация: вывести текст, не дожидаясь окончания предварительной анимации. - + Mirror your character's emotes when checked. - + Отразить анимации персонажа по горизонтали. - + Add text to your last spoken message when checked. - + Добавлять текст к своему последнему сообщению. - + Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window. - + Заглушить вызовы модератора: вы не будете получать звуковые оповещения, а игра не будет привлекать к себе внимание. - + Lets you receive case alerts when enabled. (You can set your preferences in the Settings!) - + Получать уведомления о заседаниях. +(См. подробнее в меню опций) - + Display customized shownames for all users when checked. - + Показывать пользовательские имена для всех. - + Custom Shout! - + Пользовательский возглас! - + This will display the custom character-defined animation in the viewport as soon as it is pressed. To make one, your character's folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect - + Показать в игровом чате анимацию, уникальную для персонажа, сразу после нажатия. +Для добавления такой анимации поместите в папку персонажа свои изображения +в формате webp/apng/gif/png и звук в формате wav/ogg/opus - + Play realization sound and animation in the viewport on the next spoken message when checked. - + Показать вспышку и воспроизвести звук озарения во время вывода следующей реплики. - + Shake the screen on next spoken message when checked. - + Потрясти экран во время вывода следующей реплики. - + Display the list of character folders you wish to mute. - + Выбрать персонажей, которых нужно игнорировать. - - + + Increase the health bar. - + Поощрить. - - + + Decrease the health bar. - + Оштрафовать. - + Change the text color of the spoken message. You can also select a part of your currently typed message and use the dropdown to change its color! - + Изменить цвет текста сообщения. +Вы также можете выделить часть текста и изменить только её цвет в выпадающем меню. - + Back to Lobby Назад в лобби - - - + + + has played a song - + включил(а) композицию - + You will now pair up with %1 if they also choose your character in return. - + Вы встанете рядом с %1, если он(а) выберет вашего персонажа. Rainbow - Радужный + Радужный Pink - Розовый + Розовый Cyan - Голубой + Голубой - + % offset % сдвига - + To front - + Вперёд - + To behind - + Назад - + Select a character you wish to pair with. - + Выберите персонажа, с которым хотите встать рядом. - + Change the percentage offset of your character's position from the center of the screen. - + Изменить процент сдвига вашего персонажа относительно центра экрана. - + Change the order of appearance for your character. - + Переместить вашего персонажа вперёд или назад относительно партнёра. - + Display the list of characters to pair with. - + Показать список персонажей, с которыми можно встать рядом. - + Oops, you're muted! - + О нет, вас заглушили! - + Set your character's emote to play on your next message. - + Выберите эмоцию для отображения при выводе вашего следующего сообщения. - + Set your character's supplementary background. - + Установить фон для вашего персонажа. - + Set an 'iniswap', or an alternative character folder to refer to from your current character. Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/<charname>/iniswaps.ini - + Включить т.н. подмену ini – альтернативную папку персонажа, к которой будет обращаться текущий персонаж. +Введите имя персонажа и нажмите Enter; нажмите [X], чтобы удалить. +Изменения сохраняются по следующему пути: base/characters/<имя_персонажа>/iniswaps.ini - - + + Remove the currently selected iniswap from the list and return to the original character folder. - + Удалить выбранного для подмены ini персонажа и вернуться к папке изначально выбранного персонажа. - + Set a sound effect to play on your next 'Preanim'. Leaving it on Default will use the emote-defined sound (if any). Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/<charname>/soundlist.ini - + Выберите звук, который нужно воспроизвести со следующей пред. анимацией. +Если выбрано "по умолчанию", вы услышите звук, заданный пред. анимацией (если он есть). +Выберите или введите название звука и нажмите Enter; нажмите [X], чтобы удалить. +Изменения сохраняются по следующему пути: base/characters/<имя_персонажа>/soundlist.ini - + Choose an effect to play on your next spoken message. The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by char.ini [Options] category, effects = 'miscname' where it referes to misc/<miscname>/effects.ini to read the effects. + Выберите эффект, который нужно воспроизвести с вашим следующим сообщением. +Эффекты определяются файлом theme/effects/effects.ini. Ваш персонаж может задать собственные эффекты +в категории [Options] файла char.ini, effects = 'название', что отсылает к файлу misc/<название>/effects.ini. + + + + Music - - Music - Музыка - - - + Sfx - Звук. эффекты + - + Blips - Сигналы + - + Change character - + Reload theme - + Call mod - + Settings - Настройки - - - - A/M - + + A/M + Л/М + + + Preanim - + Return back to the server list. - + Вернуться к списку серверов. - + Become a spectator. You won't be able to interact with the in-character screen. - + Зайти в качестве зрителя. Вы не сможете взаимодействовать с игровым чатом. - + You were granted the Disable Modcalls button. - + Вам дали кнопку выключения вызова модератора. - - + + CLIENT - + КЛИЕНТ - + You have been banned. - + Вас забанили. You were granted the Guard button. - Теперь у вас есть кнопка "Охрана". + Теперь у вас есть кнопка "Охрана". - + You opened the settings menu. - Вы открыли меню настроек. + Вы открыли меню опций. You will now pair up with - Вы встанете парой с персонажем по имени + Вы встанете парой с персонажем по имени if they also choose your character in return. - (если он выберет вас в ответ). + (если он выберет вас в ответ). - + You are no longer paired with anyone. - Теперь вы не стоите в парах. + Вы больше не стоите рядом ни с кем. - + Are you sure you typed that well? The char ID could not be recognised. - Кажется, вам нужно поменять запрос: такой идентификатор персонажа не был найден. + Убедитесь в правильности введённой информации: персонаж с таким ID не найден. - + You have set your offset to Вы установили сдвиг персонажа на - + Your offset must be between -100% and 100%! Сдвиг персонажа должен быть между -100% и 100%! - + That offset does not look like one. Неверный сдвиг персонажа. - + You switched your music and area list. - Вы переключили перечень зон и музыки. + Вы переключили списки локаций и музыки. - + You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this. - Из-за того, что вы включили не поддержимаемые сервером возможности, он может не принять ваши сообщения. + Из-за того, что вы включили не поддерживаемые сервером возможности, он может не принять ваши сообщения. - + Your pre-animations interrupt again. - Персонаж будет говорить только после анимации. + Персонаж будет говорить только после предварительной анимации. - + Your pre-animations will not interrupt text. - Персонаж будет говорить и во время анимации. + Предварительные анимации не будут прерывать вывод текста. - + Couldn't open chatlog.txt to write into. - Не могу открыть `chatlog.txt` для записи лога. + Невозможно открыть `chatlog.txt` для записи. - + The IC chatlog has been saved. - Лог игрового чата сохранëн. + История игрового чата сохранена. - + You don't have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it's likely the case file you're looking for can't be found in there. - Файл с делом не найден. Если найдëте, положите его в папку `base/cases/`, которую мы для вас создали. + Файл с делом не найден. Если найдёте, положите его в папку `base/cases/`, которую мы для вас создали. - + Too many arguments to load a case! You only need one filename, without extension. Введите имя файла без расширения. - - - - + + + + UNKNOWN - + н/д - + You don't have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it's likely that you somehow deleted it. - Папка `base/cases/` отсутствует! + Папка `base/cases/` отсутствует. - + You need to give a filename to save (extension not needed) and the courtroom status! - Введите имя файла (без расширения) и предоставьте статус зоны. + Введите имя файла (без расширения) и укажите статус зала суда. - + Too many arguments to save a case! You only need a filename without extension and the courtroom status! - Убедитесь, что имя файла не содержит расширение. + Убедитесь, что имя файла указано без расширения. - + Succesfully saved, edit doc and cmdoc link on the ini! - Сохранение прошло успешно! + Сохранение прошло успешно. Ссылки на документы можно редактировать в ini. - + Master Мастер - + + Play Random Song + Включить случайную композицию + + + Expand All Categories - + Развернуть все категории - + Collapse All Categories - + Свернуть все категории - + Fade Out Previous - + Постепенное затухание предыдущей композиции - + Fade In - + Постепенное нарастание - + Synchronize - + Синхронизировать - + Default - + по умолчанию - + Reason: Причина: - + Call Moderator - Позвать модератора + Вызов модератора - - + + Error Ошибка - + You must provide a reason. Укажите причину. - + The message is too long. - Слишком длинный текст. + Слишком длинное сообщение. Choose... - Выбрать... + Выбрать... Present this piece of evidence to everyone on your next spoken message - + Показать эту улику всем присутствующим вместе с вашим следующим сообщением. Save evidence to an .ini file. - + Сохранить улику в файл .ini. Load evidence from an .ini file. - + Загрузить улику из файла .ini. Destroy this piece of evidence - + Уничтожить эту улику. Choose.. - + Выбрать... Close the evidence display/editing overlay. You will be prompted if there's any unsaved changes. - + Закрыть окно редактирования улики. +Если вы не сохранили изменения, вы увидите диалоговое окно. Save any changes made to this piece of evidence and send them to server. - + Сохранить все изменения, внесённые в улику, и отправить её на сервер. Double-click to edit. Press [X] to update your changes. - + Редактирование по двойному клику. Нажмите [X] для обновления. Bring up the Evidence screen. - + Открыть окно управления уликами. Switch evidence to private inventory. - + Перейти к своему списку. Switch evidence to global inventory. - + Перейти к общему списку. Transfer evidence to private inventory. - + Перенести улику в свой список. Transfer evidence to global inventory. - + Перенести улику в общий список. The piece of evidence you've been editing has changed. - + В улику, которую вы редактировали, были внесены изменения. Do you wish to keep your changes? - + Хотите сохранить внесённые изменения? @@ -1243,7 +1287,10 @@ You will be prompted if there's any unsaved changes. Image: %2 Description: %3 - + Название: %1 +Изображение: %2 +Описание: +%3 @@ -1255,7 +1302,7 @@ Description: Double-click to edit... - + Редактирование по двойному клику... @@ -1265,43 +1312,43 @@ Description: Evidence has been modified. - + Улика была изменена. Do you want to save your changes? - + Хотите сохранить внесённые изменения? Current evidence is global. Click to switch to private. - + Вы видите общий список улик. Нажмите здесь для просмотра своих улик. Current evidence is private. Click to switch to global. - + Вы видите свой список улик. Нажмите здесь для просмотра общих улик. "%1" has been transferred. - + Улика "%1" была перенесена. - + Save Inventory - + Сохранить список улик - - + + Ini Files (*.ini) - + Файлы ini (*.ini) - + Open Inventory - + Загрузить список улик @@ -1314,7 +1361,7 @@ Description: Search - Поиск + Поиск @@ -1325,8 +1372,8 @@ Description: It doesn't look like your client is set up correctly. Did you download all resources correctly from tiny.cc/getao, including the large 'base' folder? - Не похоже, что ваш клиент установлен правильно. -Скачали ли вы все ресурсы (tiny.cc/getao), включая огромную папку `base`? + Кажется, ваш клиент неправильно настроен. +Вы точно скачали все ресурсы отсюда tiny.cc/getao, включая огромную папку `base`? @@ -1336,12 +1383,12 @@ Did you download all resources correctly from tiny.cc/getao, including the large Settings - Настройки + Опции Allows you to change various aspects of the client. - + Изменить параметры работы программы. @@ -1354,29 +1401,29 @@ Did you download all resources correctly from tiny.cc/getao, including the large Отмена - - <h2>Attorney Online %1</h2>The courtroom drama simulator<p><b>Source code:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Major development:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter<p><b>2.8 Major Release development:</b><br>Crystalwarrior, Iamgoofball<p><b>2.8 Quality Assurance:</b><br>WillDean, Captain N, Mr M, Riel, Seimmet, Fury McFlurry,CedricDewitt, Chewable Tablets, Fantos, Futugaze,Geck, Minx, Pandae, Sierra, CrazyJC, CaseyMayCazy,GreenBowers, Robotic Overlord, Veritas, Gin-Gi<p><b>Special thanks:</b><br>Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy, the AO2 community, server hosts, game masters,case makers, content creators and players! - + + <h2>Attorney Online %1</h2>The courtroom drama simulator<p><b>Source code:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Major development:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Client development:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>QA testing:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Special thanks:</b><br>CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!<p>The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.<p>Running on Qt version %2 with the %3 audio engine.<p>Built on %4 + <h2>Attorney Online %1</h2>Симулятор драмы в зале суда<p><b>Исходный код:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Основная разработка:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Разработка клиента:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>Тестирование:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Благодарности:</b><br>CrazyJC (директор по выпуску версии 2.8) и MaximumVolty (продвижение версии 2.8); Remy, Hibiki, court-records.net (спрайты); Qubrick (webAO); Rue (вебсайт); Draxirch (дизайн интерфейса); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, и FanatSors (AO1); держатели серверов, ГМ, ПД, создатели контента, и всё сообщество AO2!<p>Проект сетевой визуальной новеллы Attorney Online (c) 2016-2020 разработчики Attorney Online. Применяется лицензия на открытое ПО. Все прочие файлы являются собственностью их владельцев.<p>Работает на Qt версии %2 с аудио-движком %3.<p>Сборка от %4 - + About - + О программе <h2>Attorney Online %1</h2>The courtroom drama simulator<p><b>Source code:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Major development:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter<p><b>Special thanks:</b><br>Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy - <h2>Attorney Online %1</h2>Симулятор судебной драмы<p><b>Исходный код:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Основной разработкой занимались:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter<p><b>Особенная благодарность:</b><br>Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (дизайн интерфейса), Draxirch (дизайн интерфейса), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy + <h2>Attorney Online %1</h2>Симулятор судебной драмы<p><b>Исходный код:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Основной разработкой занимались:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter<p><b>Особенная благодарность:</b><br>Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (дизайн интерфейса), Draxirch (дизайн интерфейса), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy - + Online: %1/%2 Онлайн: %1/%2 - + Offline - Вне сети + Не в сети @@ -1386,12 +1433,12 @@ Did you download all resources correctly from tiny.cc/getao, including the large UNKNOWN - + н/д - + has played a song: - + включил(а) композицию: @@ -1409,7 +1456,7 @@ Did you download all resources correctly from tiny.cc/getao, including the large Notice - На заметку + Уведомление From 593e9d7353f601f81bbe26925ace4966434e7370 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Wed, 17 Apr 2019 11:07:09 -0500 Subject: [PATCH 14/46] Miscellaneous changes to CI scripts --- scripts/update_manifest.js | 4 +--- scripts/windows/Dockerfile | 5 +++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/scripts/update_manifest.js b/scripts/update_manifest.js index 1a06a2d..bbd2a5f 100755 --- a/scripts/update_manifest.js +++ b/scripts/update_manifest.js @@ -101,9 +101,7 @@ const specialActions = changesFile ? // higher-level directories will succeed. .concat(Array.from(dirsDeleted.values()) .sort((a, b) => b.split("/").length - a.split("/").length) - .map(dir => { - return { action: "deleteDir", target: dir }; - })) + .map(dir => ({ action: "deleteDir", target: dir }))) : []; const urlBase = "https://s3.wasabisys.com/ao-downloads/"; diff --git a/scripts/windows/Dockerfile b/scripts/windows/Dockerfile index b9a12d6..9d3cca0 100644 --- a/scripts/windows/Dockerfile +++ b/scripts/windows/Dockerfile @@ -3,6 +3,11 @@ FROM oldmud0/mxe-qt:5.13.0-win32-static-posix ENV TARGET_SPEC i686-w64-mingw32.static.posix +# Build libarchive statically +WORKDIR /opt/mxe +RUN make -j4 MXE_TARGETS=${TARGET_SPEC} libarchive bzip2 xz lz4 zstd nettle expat libxml2 +WORKDIR / + # Build Discord RPC statically RUN git clone https://github.com/discordapp/discord-rpc WORKDIR discord-rpc/build From 8b44d4ae9599a90579c4fb974fab1704ace8d131 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sat, 15 Aug 2020 19:40:52 -0500 Subject: [PATCH 15/46] Only regenerate the area list once per ARUP packet --- include/courtroom.h | 1 - src/packet_distribution.cpp | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/include/courtroom.h b/include/courtroom.h index 182c2a6..e7a51d3 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -109,7 +109,6 @@ public: if (arup_locks.size() > place) arup_locks[place] = value; } - list_areas(); } void character_loading_finished(); diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index b543cfb..fd7453e 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -676,6 +676,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_courtroom->arup_modify(arup_type, n_element - 1, f_contents.at(n_element)); } + w_courtroom->list_areas(); } } else if (header == "IL") { From 102ca4d64143ecb9401fdb1627ada00194d58dd1 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sat, 15 Aug 2020 19:47:24 -0500 Subject: [PATCH 16/46] Create brushes for area list once --- include/courtroom.h | 8 ++++++++ src/courtroom.cpp | 17 ++++++++--------- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/include/courtroom.h b/include/courtroom.h index e7a51d3..f1cb026 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -457,6 +457,14 @@ private: QString current_background = "default"; QString current_side = ""; + QBrush free_brush; + QBrush lfp_brush; + QBrush casing_brush; + QBrush recess_brush; + QBrush rp_brush; + QBrush gaming_brush; + QBrush locked_brush; + AOMusicPlayer *music_player; AOSfxPlayer *sfx_player; AOSfxPlayer *objection_player; diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 98b6a9c..54034f8 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -70,6 +70,14 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_background = new AOImage(this, ao_app); + free_brush = *new QBrush(ao_app->get_color("area_free_color", "courtroom_design.ini")); + lfp_brush = *new QBrush(ao_app->get_color("area_lfp_color", "courtroom_design.ini")); + casing_brush = *new QBrush(ao_app->get_color("area_casing_color", "courtroom_design.ini")); + recess_brush = *new QBrush(ao_app->get_color("area_recess_color", "courtroom_design.ini")); + rp_brush = *new QBrush(ao_app->get_color("area_rp_color", "courtroom_design.ini")); + gaming_brush = *new QBrush(ao_app->get_color("area_gaming_color", "courtroom_design.ini")); + locked_brush = *new QBrush(ao_app->get_color("area_locked_color", "courtroom_design.ini")); + ui_viewport = new QWidget(this); ui_vp_background = new AOScene(ui_viewport, ao_app); ui_vp_speedlines = new AOMovie(ui_viewport, ao_app); @@ -1433,15 +1441,6 @@ void Courtroom::list_areas() ui_area_list->clear(); // ui_music_search->setText(""); - QString f_file = "courtroom_design.ini"; - - QBrush free_brush(ao_app->get_color("area_free_color", f_file)); - QBrush lfp_brush(ao_app->get_color("area_lfp_color", f_file)); - QBrush casing_brush(ao_app->get_color("area_casing_color", f_file)); - QBrush recess_brush(ao_app->get_color("area_recess_color", f_file)); - QBrush rp_brush(ao_app->get_color("area_rp_color", f_file)); - QBrush gaming_brush(ao_app->get_color("area_gaming_color", f_file)); - QBrush locked_brush(ao_app->get_color("area_locked_color", f_file)); int n_listed_areas = 0; From 002086343a19679b7fb8d8fed8302510456c05c2 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 04:03:56 -0500 Subject: [PATCH 17/46] Check for custom realization sound when using effects list --- src/text_file_functions.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 39754f3..d2ed20a 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -908,6 +908,11 @@ QString AOApplication::get_effect_sound(QString fx_name, QString p_char) f_result = read_design_ini(fx_name, default_path); } } + + if(fx_name == "realization"){ + f_result = get_custom_realization(p_char); + } + return f_result; } From 11250e13864dc5e3cdd799b02498905c58db55ea Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 06:50:19 -0500 Subject: [PATCH 18/46] Ensure consistent behavior in IC log, clarify showname logic, and define constants for minimum and maximum packet sizes --- include/courtroom.h | 6 ++++-- src/courtroom.cpp | 34 +++++++++++++++------------------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/include/courtroom.h b/include/courtroom.h index 182c2a6..6132ed9 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -349,8 +349,10 @@ private: // amount by which we multiply the delay when we parse punctuation chars const int punctuation_modifier = 3; - static const int chatmessage_size = 30; - QString m_chatmessage[chatmessage_size]; + // Minumum and maximum number of parameters in the MS packet + static const int MS_MINIMUM = 15; + static const int MS_MAXIMUM = 30; + QString m_chatmessage[MS_MAXIMUM]; bool chatmessage_is_empty = false; QString previous_ic_message = ""; diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 98b6a9c..5f7a613 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1765,19 +1765,16 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) // Instead of checking for whether a message has at least chatmessage_size // amount of packages, we'll check if it has at least 15. // That was the original chatmessage_size. - if (p_contents->size() < 15) + if (p_contents->size() < MS_MINIMUM) return; - for (int n_string = 0; n_string < chatmessage_size; ++n_string) { - // m_chatmessage[n_string] = p_contents->at(n_string); - + for (int n_string = 0; n_string < MS_MAXIMUM; ++n_string) { // Note that we have added stuff that vanilla clients and servers simply // won't send. So now, we have to check if the thing we want even exists // amongst the packet's content. We also have to check if the server even // supports CCCC's IC features, or if it's just japing us. Also, don't // forget! A size 15 message will have indices from 0 to 14. - if (n_string < p_contents->size() && - (n_string < 15 || ao_app->cccc_ic_support_enabled)) { + if (n_string < p_contents->size() && (n_string < MS_MINIMUM || ao_app->cccc_ic_support_enabled)) { m_chatmessage[n_string] = p_contents->at(n_string); } else { @@ -1786,27 +1783,26 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) } int f_char_id = m_chatmessage[CHAR_ID].toInt(); + const bool is_spectator = (f_char_id == -1); - if (f_char_id >= 0 && f_char_id >= char_list.size()) + if (f_char_id >= char_list.size()) return; - if (mute_map.value(m_chatmessage[CHAR_ID].toInt())) return; - QString f_showname; - if (f_char_id > -1 && - (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) { - f_showname = ao_app->get_showname(char_list.at(f_char_id).name); + QString f_displayname; + if (!is_spectator && (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) { + f_displayname = ao_app->get_showname(char_list.at(f_char_id).name); } else { - f_showname = m_chatmessage[SHOWNAME]; + f_displayname = m_chatmessage[SHOWNAME]; } - if (f_showname.trimmed() - .isEmpty()) // Pure whitespace showname, get outta here. - f_showname = m_chatmessage[CHAR_NAME]; + // If chatblank is enabled, use the character's name for logs + if (f_displayname.trimmed().isEmpty()) + f_displayname = ao_app->get_showname(char_list.at(f_char_id).name); - QString f_message = f_showname + ": " + m_chatmessage[MESSAGE] + '\n'; + QString f_message = f_displayname + ": " + m_chatmessage[MESSAGE] + '\n'; // Remove undesired newline chars m_chatmessage[MESSAGE].remove("\n"); chatmessage_is_empty = @@ -1868,7 +1864,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) f_charname = ao_app->get_showname(char_list.at(f_char_id).name); chatlogpiece *temp = - new chatlogpiece(f_charname, f_showname, m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt()); + new chatlogpiece(f_charname, f_displayname, m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt()); ic_chatlog_history.append(*temp); if (ao_app->get_auto_logging_enabled()) ao_app->append_to_file(temp->get_full(), ao_app->log_filename, true); @@ -1878,7 +1874,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) ic_chatlog_history.removeFirst(); } - append_ic_text(m_chatmessage[MESSAGE], f_showname, "", m_chatmessage[TEXT_COLOR].toInt()); + append_ic_text(m_chatmessage[MESSAGE], f_displayname, "", m_chatmessage[TEXT_COLOR].toInt()); QString f_char = m_chatmessage[CHAR_NAME]; QString f_custom_theme = ao_app->get_char_shouts(f_char); From 079ce93b85ecc25e338d61614318fb6ed6cce696 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 07:06:53 -0500 Subject: [PATCH 19/46] Remove clientside doublepost checking --- src/courtroom.cpp | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 5f7a613..f26645f 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1792,9 +1792,11 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) QString f_displayname; if (!is_spectator && (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) { + // If the users is not a spectator and showname is disabled, use the character's name f_displayname = ao_app->get_showname(char_list.at(f_char_id).name); } else { + // Otherwise, use the showname f_displayname = m_chatmessage[SHOWNAME]; } @@ -1803,20 +1805,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) f_displayname = ao_app->get_showname(char_list.at(f_char_id).name); QString f_message = f_displayname + ": " + m_chatmessage[MESSAGE] + '\n'; - // Remove undesired newline chars - m_chatmessage[MESSAGE].remove("\n"); - chatmessage_is_empty = - m_chatmessage[MESSAGE] == " " || m_chatmessage[MESSAGE] == ""; - if (f_char_id >= 0 && !chatmessage_is_empty && - f_message == previous_ic_message) // Not a system message - return; - - if (f_char_id <= -1) - previous_ic_message = - ""; // System messages don't care about repeating themselves - else - previous_ic_message = f_message; bool ok; int objection_mod = m_chatmessage[OBJECTION_MOD].toInt( &ok, 10); // checks if its a custom obj. From cd3ddfe16c423fede1164aa95a36b65caab100e4 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 07:21:49 -0500 Subject: [PATCH 20/46] Update brushes on theme reload --- src/courtroom.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 54034f8..0b0f622 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -70,14 +70,6 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_background = new AOImage(this, ao_app); - free_brush = *new QBrush(ao_app->get_color("area_free_color", "courtroom_design.ini")); - lfp_brush = *new QBrush(ao_app->get_color("area_lfp_color", "courtroom_design.ini")); - casing_brush = *new QBrush(ao_app->get_color("area_casing_color", "courtroom_design.ini")); - recess_brush = *new QBrush(ao_app->get_color("area_recess_color", "courtroom_design.ini")); - rp_brush = *new QBrush(ao_app->get_color("area_rp_color", "courtroom_design.ini")); - gaming_brush = *new QBrush(ao_app->get_color("area_gaming_color", "courtroom_design.ini")); - locked_brush = *new QBrush(ao_app->get_color("area_locked_color", "courtroom_design.ini")); - ui_viewport = new QWidget(this); ui_vp_background = new AOScene(ui_viewport, ao_app); ui_vp_speedlines = new AOMovie(ui_viewport, ao_app); @@ -942,6 +934,14 @@ void Courtroom::set_widgets() ui_spectator->setToolTip(tr("Become a spectator. You won't be able to " "interact with the in-character screen.")); + free_brush = *new QBrush(ao_app->get_color("area_free_color", "courtroom_design.ini")); + lfp_brush = *new QBrush(ao_app->get_color("area_lfp_color", "courtroom_design.ini")); + casing_brush = *new QBrush(ao_app->get_color("area_casing_color", "courtroom_design.ini")); + recess_brush = *new QBrush(ao_app->get_color("area_recess_color", "courtroom_design.ini")); + rp_brush = *new QBrush(ao_app->get_color("area_rp_color", "courtroom_design.ini")); + gaming_brush = *new QBrush(ao_app->get_color("area_gaming_color", "courtroom_design.ini")); + locked_brush = *new QBrush(ao_app->get_color("area_locked_color", "courtroom_design.ini")); + refresh_evidence(); } From 507180d164e2b96653522f81d737f9ef3d7b9483 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 08:37:12 -0500 Subject: [PATCH 21/46] Clean up logic in handle_chatmessage() --- src/courtroom.cpp | 47 ++++++++++++++++------------------------------- 1 file changed, 16 insertions(+), 31 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index f26645f..3f72397 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1804,29 +1804,27 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) if (f_displayname.trimmed().isEmpty()) f_displayname = ao_app->get_showname(char_list.at(f_char_id).name); - QString f_message = f_displayname + ": " + m_chatmessage[MESSAGE] + '\n'; - - bool ok; - int objection_mod = m_chatmessage[OBJECTION_MOD].toInt( - &ok, 10); // checks if its a custom obj. + // Check if a custom objection is in use + int objection_mod = 0; QString custom_objection = ""; - if (!ok && m_chatmessage[OBJECTION_MOD].contains("4&")) { + if (m_chatmessage[OBJECTION_MOD].contains("4&")) { objection_mod = 4; - custom_objection = m_chatmessage[OBJECTION_MOD].split( - "4&")[1]; // takes the name of custom objection. + custom_objection = m_chatmessage[OBJECTION_MOD].split("4&")[1]; // takes the name of custom objection. + } + else{ + objection_mod = m_chatmessage[OBJECTION_MOD].toInt(); } - // Stop the chat arrow from animating - ui_vp_chat_arrow->stop(); + // Reset IC display + ui_vp_chat_arrow->stop(); text_state = 0; anim_state = 0; ui_vp_objection->stop(); chat_tick_timer->stop(); ui_vp_evidence_display->reset(); - // Hey, our message showed up! Cool! - if (m_chatmessage[MESSAGE] == ui_ic_chat_message->text().remove("\n") && - m_chatmessage[CHAR_ID].toInt() == m_cid) { + // Reset UI elements after client message gets sent + if (m_chatmessage[CHAR_ID].toInt() == m_cid) { ui_ic_chat_message->clear(); if (ui_additive->isChecked()) ui_ic_chat_message->insert(" "); @@ -1848,12 +1846,8 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) // Let the server handle actually checking if they're allowed to do this. is_additive = m_chatmessage[ADDITIVE].toInt() == 1; - QString f_charname = ""; - if (f_char_id >= 0) - f_charname = ao_app->get_showname(char_list.at(f_char_id).name); - chatlogpiece *temp = - new chatlogpiece(f_charname, f_displayname, m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt()); + new chatlogpiece(f_displayname, f_displayname, m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt()); ic_chatlog_history.append(*temp); if (ao_app->get_auto_logging_enabled()) ao_app->append_to_file(temp->get_full(), ao_app->log_filename, true); @@ -1888,26 +1882,17 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) // case 4 is AO2 only case 4: if (custom_objection != "") { - ui_vp_objection->play("custom_objections/" + custom_objection, f_char, - f_custom_theme, shout_stay_time); - objection_player->play("custom_objections/" + - custom_objection.split('.')[0], - f_char, f_custom_theme); + ui_vp_objection->play("custom_objections/" + custom_objection, f_char, f_custom_theme, shout_stay_time); + objection_player->play("custom_objections/" + custom_objection.split('.')[0], f_char, f_custom_theme); } else { - ui_vp_objection->play("custom", f_char, f_custom_theme, - shout_stay_time); + ui_vp_objection->play("custom", f_char, f_custom_theme, shout_stay_time); objection_player->play("custom", f_char, f_custom_theme); } break; - default: - qDebug() << "W: Logic error in objection switch statement!"; + m_chatmessage[EMOTE_MOD] = 1; } sfx_player->clear(); // Objection played! Cut all sfx. - int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); - - if (emote_mod == 0) - m_chatmessage[EMOTE_MOD] = 1; } else handle_chatmessage_2(); From 42d939614f2ebe30b087405bed49dd7f3ebc172a Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 10:59:06 -0500 Subject: [PATCH 22/46] Fix improper bolding behavior due to malformed string literal --- src/courtroom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 98b6a9c..de1273b 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -975,7 +975,7 @@ void Courtroom::set_font(QWidget *widget, QString class_name, } } bool bold = ao_app->get_design_element(p_identifier + "_bold", design_file, p_char) == - 1; // is the font bold or not? + "1"; // is the font bold or not? bool antialias = ao_app->get_design_element(p_identifier + "_sharp", design_file, p_char) != "1"; // is the font anti-aliased or not? From 1c5b097f654d16e0dde47f7ae62d236427077cb7 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 12:43:26 -0500 Subject: [PATCH 23/46] further cleanup of chat handler --- include/courtroom.h | 2 ++ src/courtroom.cpp | 58 ++++++++++++++++++++++++++------------------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/include/courtroom.h b/include/courtroom.h index a4bacc2..ca271a4 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -648,6 +648,8 @@ private: void refresh_evidence(); void set_evidence_page(); + void reset_ic(); + void reset_ui(); public slots: void objection_done(); void preanim_done(); diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 3b3f699..bc8405c 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1762,6 +1762,36 @@ void Courtroom::on_chat_return_pressed() ao_app->send_server_packet(new AOPacket("MS", packet_contents)); } +void Courtroom::reset_ic(){ + ui_vp_chat_arrow->stop(); + text_state = 0; + anim_state = 0; + ui_vp_objection->stop(); + chat_tick_timer->stop(); + ui_vp_evidence_display->reset(); +} + +void Courtroom::reset_ui(){ + if (m_chatmessage[CHAR_ID].toInt() == m_cid) { + ui_ic_chat_message->clear(); + if (ui_additive->isChecked()) + ui_ic_chat_message->insert(" "); + objection_state = 0; + realization_state = 0; + screenshake_state = 0; + is_presenting_evidence = false; + if (!ao_app->is_stickypres_enabled()) + ui_pre->setChecked(false); + ui_hold_it->set_image("holdit"); + ui_objection->set_image("objection"); + ui_take_that->set_image("takethat"); + ui_custom_objection->set_image("custom"); + ui_realization->set_image("realization"); + ui_screenshake->set_image("screenshake"); + ui_evidence_present->set_image("present"); + } +} + void Courtroom::handle_chatmessage(QStringList *p_contents) { // Instead of checking for whether a message has at least chatmessage_size @@ -1818,32 +1848,10 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) } // Reset IC display - ui_vp_chat_arrow->stop(); - text_state = 0; - anim_state = 0; - ui_vp_objection->stop(); - chat_tick_timer->stop(); - ui_vp_evidence_display->reset(); + reset_ic(); // Reset UI elements after client message gets sent - if (m_chatmessage[CHAR_ID].toInt() == m_cid) { - ui_ic_chat_message->clear(); - if (ui_additive->isChecked()) - ui_ic_chat_message->insert(" "); - objection_state = 0; - realization_state = 0; - screenshake_state = 0; - is_presenting_evidence = false; - if (!ao_app->is_stickypres_enabled()) - ui_pre->setChecked(false); - ui_hold_it->set_image("holdit"); - ui_objection->set_image("objection"); - ui_take_that->set_image("takethat"); - ui_custom_objection->set_image("custom"); - ui_realization->set_image("realization"); - ui_screenshake->set_image("screenshake"); - ui_evidence_present->set_image("present"); - } + reset_ui(); // Let the server handle actually checking if they're allowed to do this. is_additive = m_chatmessage[ADDITIVE].toInt() == 1; @@ -1870,7 +1878,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) color_rgb_list.append(color); } - append_ic_text(m_chatmessage[MESSAGE], f_showname, "", m_chatmessage[TEXT_COLOR].toInt()); + append_ic_text(m_chatmessage[MESSAGE], f_displayname, "", m_chatmessage[TEXT_COLOR].toInt()); // if an objection is used if (objection_mod <= 4 && objection_mod >= 1) { From 95725eb129f72231b0615a35cee2299c74c9a6a8 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 13:53:16 -0500 Subject: [PATCH 24/46] fix incorrect emote modifier --- src/courtroom.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index bc8405c..04a7960 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1613,7 +1613,7 @@ void Courtroom::on_chat_return_pressed() if (f_emote_mod == 0) f_emote_mod = 1; else if (f_emote_mod == 5 && ao_app->prezoom_enabled) - f_emote_mod = 4; + f_emote_mod = 6; } else { if (f_emote_mod == 1) @@ -1772,7 +1772,6 @@ void Courtroom::reset_ic(){ } void Courtroom::reset_ui(){ - if (m_chatmessage[CHAR_ID].toInt() == m_cid) { ui_ic_chat_message->clear(); if (ui_additive->isChecked()) ui_ic_chat_message->insert(" "); @@ -1789,7 +1788,6 @@ void Courtroom::reset_ui(){ ui_realization->set_image("realization"); ui_screenshake->set_image("screenshake"); ui_evidence_present->set_image("present"); - } } void Courtroom::handle_chatmessage(QStringList *p_contents) @@ -1851,7 +1849,9 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) reset_ic(); // Reset UI elements after client message gets sent - reset_ui(); + if (m_chatmessage[CHAR_ID].toInt() == m_cid) { + reset_ui(); + } // Let the server handle actually checking if they're allowed to do this. is_additive = m_chatmessage[ADDITIVE].toInt() == 1; From 3c031db2ea3bfe56072b32ce240875b597014c16 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 14:14:26 -0500 Subject: [PATCH 25/46] fix check for negative char_id --- src/courtroom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 04a7960..943c2d4 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1815,7 +1815,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) int f_char_id = m_chatmessage[CHAR_ID].toInt(); const bool is_spectator = (f_char_id == -1); - if (f_char_id >= char_list.size()) + if (f_char_id < 0 || f_char_id >= char_list.size()) return; if (mute_map.value(m_chatmessage[CHAR_ID].toInt())) return; From 4b7efc8536f4ea518eb43483e3805255f36ada75 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 14:17:58 -0500 Subject: [PATCH 26/46] allow -1 charid for system messages --- src/courtroom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 943c2d4..fa55ba8 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1815,7 +1815,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) int f_char_id = m_chatmessage[CHAR_ID].toInt(); const bool is_spectator = (f_char_id == -1); - if (f_char_id < 0 || f_char_id >= char_list.size()) + if (f_char_id < -1 || f_char_id >= char_list.size()) return; if (mute_map.value(m_chatmessage[CHAR_ID].toInt())) return; From 8712ed3ca14dfe571101dcc35c3b3a7206aaa1fc Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 17:47:05 -0500 Subject: [PATCH 27/46] Don't hang IC due to invalid emote mod --- src/courtroom.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index fa55ba8..164537d 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -2058,6 +2058,13 @@ void Courtroom::handle_chatmessage_2() set_scene(m_chatmessage[DESK_MOD], m_chatmessage[SIDE]); int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); + // Deal with invalid emote modifiers + if(emote_mod < 0 || (emote_mod > 2 && emote_mod < 5) || emote_mod > 6){ + if(emote_mod == 4) + emote_mod = 6; // Addresses issue with an old bug that sent the wrong emote modifier for zoompre + else + emote_mod = 0; + } if (ao_app->flipping_enabled && m_chatmessage[FLIP].toInt() == 1) ui_vp_player_char->set_flipped(true); From c5f8fc8f96a58d6059781136c6ea37f332ea2ead Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 21:48:50 -0500 Subject: [PATCH 28/46] make suggested changes from code review --- src/courtroom.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 164537d..a31bd0a 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -2059,8 +2059,9 @@ void Courtroom::handle_chatmessage_2() int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); // Deal with invalid emote modifiers - if(emote_mod < 0 || (emote_mod > 2 && emote_mod < 5) || emote_mod > 6){ - if(emote_mod == 4) + if (emote_mod != 0 && emote_mod != 1 && emote_mod != 2 \ + && emote_mod != 5 && emote_mod != 6) { + if (emote_mod == 4) emote_mod = 6; // Addresses issue with an old bug that sent the wrong emote modifier for zoompre else emote_mod = 0; From ae7c36e609d5571afc62193e5158f98c6cf5b4e7 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 21:53:05 -0500 Subject: [PATCH 29/46] use proper syntax to instansiate qbrush --- src/courtroom.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index a31bd0a..b0699cb 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -935,13 +935,13 @@ void Courtroom::set_widgets() ui_spectator->setToolTip(tr("Become a spectator. You won't be able to " "interact with the in-character screen.")); - free_brush = *new QBrush(ao_app->get_color("area_free_color", "courtroom_design.ini")); - lfp_brush = *new QBrush(ao_app->get_color("area_lfp_color", "courtroom_design.ini")); - casing_brush = *new QBrush(ao_app->get_color("area_casing_color", "courtroom_design.ini")); - recess_brush = *new QBrush(ao_app->get_color("area_recess_color", "courtroom_design.ini")); - rp_brush = *new QBrush(ao_app->get_color("area_rp_color", "courtroom_design.ini")); - gaming_brush = *new QBrush(ao_app->get_color("area_gaming_color", "courtroom_design.ini")); - locked_brush = *new QBrush(ao_app->get_color("area_locked_color", "courtroom_design.ini")); + free_brush = QBrush(ao_app->get_color("area_free_color", "courtroom_design.ini")); + lfp_brush = QBrush(ao_app->get_color("area_lfp_color", "courtroom_design.ini")); + casing_brush = QBrush(ao_app->get_color("area_casing_color", "courtroom_design.ini")); + recess_brush = QBrush(ao_app->get_color("area_recess_color", "courtroom_design.ini")); + rp_brush = QBrush(ao_app->get_color("area_rp_color", "courtroom_design.ini")); + gaming_brush = QBrush(ao_app->get_color("area_gaming_color", "courtroom_design.ini")); + locked_brush = QBrush(ao_app->get_color("area_locked_color", "courtroom_design.ini")); refresh_evidence(); } From 359cad73d40fff68ee51a8a81d37e9d18a8b7407 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 21:55:14 -0500 Subject: [PATCH 30/46] use shownames in log properly --- src/courtroom.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index b0699cb..5100ee8 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1856,8 +1856,12 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) // Let the server handle actually checking if they're allowed to do this. is_additive = m_chatmessage[ADDITIVE].toInt() == 1; + QString f_charname = ""; + if (f_char_id >= 0) + f_charname = ao_app->get_showname(char_list.at(f_char_id).name); + chatlogpiece *temp = - new chatlogpiece(f_displayname, f_displayname, m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt()); + new chatlogpiece(f_charname, f_displayname, m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt()); ic_chatlog_history.append(*temp); if (ao_app->get_auto_logging_enabled()) ao_app->append_to_file(temp->get_full(), ao_app->log_filename, true); From ecb0ee42a3a399c092eafdf2ac60faaad4bf119f Mon Sep 17 00:00:00 2001 From: scatterflower Date: Sun, 16 Aug 2020 21:59:44 -0500 Subject: [PATCH 31/46] clang format --- include/courtroom.h | 9 +- src/courtroom.cpp | 196 +++++++++++++++++++----------------- src/packet_distribution.cpp | 22 ++-- src/text_file_functions.cpp | 16 +-- 4 files changed, 132 insertions(+), 111 deletions(-) diff --git a/include/courtroom.h b/include/courtroom.h index ca271a4..898e8ba 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -117,7 +117,9 @@ public: void set_widgets(); // sets font size based on theme ini files - void set_font(QWidget *widget, QString class_name, QString p_identifier, QString p_char="", QString font_name="", int f_pointsize=0); + void set_font(QWidget *widget, QString class_name, QString p_identifier, + QString p_char = "", QString font_name = "", + int f_pointsize = 0); // Get the properly constructed font QFont get_qfont(QString font_name, int f_pointsize, bool antialias = true); @@ -127,7 +129,7 @@ public: QColor f_color = Qt::black, bool bold = false); // helper function that calls above function on the relevant widgets - void set_fonts(QString p_char=""); + void set_fonts(QString p_char = ""); // sets dropdown menu stylesheet void set_dropdown(QWidget *widget); @@ -220,7 +222,8 @@ public: // this function keeps the chatlog scrolled to the top unless there's text // selected // or the user isn't already scrolled to the top - void append_ic_text(QString p_text, QString p_name = "", QString action = "", int color = 0); + void append_ic_text(QString p_text, QString p_name = "", QString action = "", + int color = 0); // prints who played the song to IC chat and plays said song(if found on local // filesystem) takes in a list where the first element is the song name and diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 5100ee8..be7588a 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -935,13 +935,19 @@ void Courtroom::set_widgets() ui_spectator->setToolTip(tr("Become a spectator. You won't be able to " "interact with the in-character screen.")); - free_brush = QBrush(ao_app->get_color("area_free_color", "courtroom_design.ini")); - lfp_brush = QBrush(ao_app->get_color("area_lfp_color", "courtroom_design.ini")); - casing_brush = QBrush(ao_app->get_color("area_casing_color", "courtroom_design.ini")); - recess_brush = QBrush(ao_app->get_color("area_recess_color", "courtroom_design.ini")); + free_brush = + QBrush(ao_app->get_color("area_free_color", "courtroom_design.ini")); + lfp_brush = + QBrush(ao_app->get_color("area_lfp_color", "courtroom_design.ini")); + casing_brush = + QBrush(ao_app->get_color("area_casing_color", "courtroom_design.ini")); + recess_brush = + QBrush(ao_app->get_color("area_recess_color", "courtroom_design.ini")); rp_brush = QBrush(ao_app->get_color("area_rp_color", "courtroom_design.ini")); - gaming_brush = QBrush(ao_app->get_color("area_gaming_color", "courtroom_design.ini")); - locked_brush = QBrush(ao_app->get_color("area_locked_color", "courtroom_design.ini")); + gaming_brush = + QBrush(ao_app->get_color("area_gaming_color", "courtroom_design.ini")); + locked_brush = + QBrush(ao_app->get_color("area_locked_color", "courtroom_design.ini")); refresh_evidence(); } @@ -966,28 +972,29 @@ void Courtroom::set_font(QWidget *widget, QString class_name, { QString design_file = "courtroom_fonts.ini"; if (f_pointsize <= 0) - f_pointsize = ao_app->get_design_element(p_identifier, design_file, p_char).toInt(); + f_pointsize = + ao_app->get_design_element(p_identifier, design_file, p_char).toInt(); if (font_name == "") font_name = - ao_app->get_design_element(p_identifier + "_font", design_file, p_char); - QString f_color_result = ao_app->get_design_element(p_identifier + "_color", design_file, p_char); + ao_app->get_design_element(p_identifier + "_font", design_file, p_char); + QString f_color_result = + ao_app->get_design_element(p_identifier + "_color", design_file, p_char); QColor f_color(0, 0, 0); - if (f_color_result != "") - { + if (f_color_result != "") { QStringList color_list = f_color_result.split(","); - if (color_list.size() >= 3) - { + if (color_list.size() >= 3) { f_color.setRed(color_list.at(0).toInt()); f_color.setGreen(color_list.at(1).toInt()); f_color.setBlue(color_list.at(2).toInt()); } } - bool bold = ao_app->get_design_element(p_identifier + "_bold", design_file, p_char) == - "1"; // is the font bold or not? - bool antialias = - ao_app->get_design_element(p_identifier + "_sharp", design_file, p_char) != - "1"; // is the font anti-aliased or not? + bool bold = + ao_app->get_design_element(p_identifier + "_bold", design_file, p_char) == + "1"; // is the font bold or not? + bool antialias = ao_app->get_design_element(p_identifier + "_sharp", + design_file, p_char) != + "1"; // is the font anti-aliased or not? this->set_qfont(widget, class_name, get_qfont(font_name, f_pointsize, antialias), f_color, bold); @@ -1138,8 +1145,8 @@ void Courtroom::set_background(QString p_background, bool display) // Populate the dropdown list with all pos that exist on this bg QStringList pos_list = {}; for (QString key : default_pos.keys()) { - if (file_exists(ao_app->get_image_suffix( - ao_app->get_background_path(key)))) { + if (file_exists( + ao_app->get_image_suffix(ao_app->get_background_path(key)))) { pos_list.append(default_pos[key]); } } @@ -1293,8 +1300,7 @@ void Courtroom::update_character(int p_cid) { custom_obj_menu->clear(); if (file_exists(ao_app->get_image_suffix( - ao_app->get_character_path(current_char, "custom")))) - { + ao_app->get_character_path(current_char, "custom")))) { ui_custom_objection->show(); QAction *action = custom_obj_menu->addAction("Default"); custom_obj_menu->setDefaultAction(action); @@ -1312,8 +1318,7 @@ void Courtroom::update_character(int p_cid) QDir::Files); for (const QString &filename : custom_obj) { QAction *action = custom_obj_menu->addAction(filename); - if (custom_obj_menu->defaultAction() == nullptr) - { + if (custom_obj_menu->defaultAction() == nullptr) { custom_obj_menu->setDefaultAction(action); objection_custom = action->text(); } @@ -1444,7 +1449,6 @@ void Courtroom::list_areas() ui_area_list->clear(); // ui_music_search->setText(""); - int n_listed_areas = 0; for (int n_area = 0; n_area < area_list.size(); ++n_area) { @@ -1762,32 +1766,34 @@ void Courtroom::on_chat_return_pressed() ao_app->send_server_packet(new AOPacket("MS", packet_contents)); } -void Courtroom::reset_ic(){ - ui_vp_chat_arrow->stop(); - text_state = 0; - anim_state = 0; - ui_vp_objection->stop(); - chat_tick_timer->stop(); - ui_vp_evidence_display->reset(); +void Courtroom::reset_ic() +{ + ui_vp_chat_arrow->stop(); + text_state = 0; + anim_state = 0; + ui_vp_objection->stop(); + chat_tick_timer->stop(); + ui_vp_evidence_display->reset(); } -void Courtroom::reset_ui(){ - ui_ic_chat_message->clear(); - if (ui_additive->isChecked()) - ui_ic_chat_message->insert(" "); - objection_state = 0; - realization_state = 0; - screenshake_state = 0; - is_presenting_evidence = false; - if (!ao_app->is_stickypres_enabled()) - ui_pre->setChecked(false); - ui_hold_it->set_image("holdit"); - ui_objection->set_image("objection"); - ui_take_that->set_image("takethat"); - ui_custom_objection->set_image("custom"); - ui_realization->set_image("realization"); - ui_screenshake->set_image("screenshake"); - ui_evidence_present->set_image("present"); +void Courtroom::reset_ui() +{ + ui_ic_chat_message->clear(); + if (ui_additive->isChecked()) + ui_ic_chat_message->insert(" "); + objection_state = 0; + realization_state = 0; + screenshake_state = 0; + is_presenting_evidence = false; + if (!ao_app->is_stickypres_enabled()) + ui_pre->setChecked(false); + ui_hold_it->set_image("holdit"); + ui_objection->set_image("objection"); + ui_take_that->set_image("takethat"); + ui_custom_objection->set_image("custom"); + ui_realization->set_image("realization"); + ui_screenshake->set_image("screenshake"); + ui_evidence_present->set_image("present"); } void Courtroom::handle_chatmessage(QStringList *p_contents) @@ -1804,7 +1810,8 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) // amongst the packet's content. We also have to check if the server even // supports CCCC's IC features, or if it's just japing us. Also, don't // forget! A size 15 message will have indices from 0 to 14. - if (n_string < p_contents->size() && (n_string < MS_MINIMUM || ao_app->cccc_ic_support_enabled)) { + if (n_string < p_contents->size() && + (n_string < MS_MINIMUM || ao_app->cccc_ic_support_enabled)) { m_chatmessage[n_string] = p_contents->at(n_string); } else { @@ -1821,8 +1828,10 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) return; QString f_displayname; - if (!is_spectator && (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) { - // If the users is not a spectator and showname is disabled, use the character's name + if (!is_spectator && + (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) { + // If the users is not a spectator and showname is disabled, use the + // character's name f_displayname = ao_app->get_showname(char_list.at(f_char_id).name); } else { @@ -1839,10 +1848,11 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) QString custom_objection = ""; if (m_chatmessage[OBJECTION_MOD].contains("4&")) { objection_mod = 4; - custom_objection = m_chatmessage[OBJECTION_MOD].split("4&")[1]; // takes the name of custom objection. + custom_objection = m_chatmessage[OBJECTION_MOD].split( + "4&")[1]; // takes the name of custom objection. } - else{ - objection_mod = m_chatmessage[OBJECTION_MOD].toInt(); + else { + objection_mod = m_chatmessage[OBJECTION_MOD].toInt(); } // Reset IC display @@ -1861,7 +1871,8 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) f_charname = ao_app->get_showname(char_list.at(f_char_id).name); chatlogpiece *temp = - new chatlogpiece(f_charname, f_displayname, m_chatmessage[MESSAGE], false, m_chatmessage[TEXT_COLOR].toInt()); + new chatlogpiece(f_charname, f_displayname, m_chatmessage[MESSAGE], false, + m_chatmessage[TEXT_COLOR].toInt()); ic_chatlog_history.append(*temp); if (ao_app->get_auto_logging_enabled()) ao_app->append_to_file(temp->get_full(), ao_app->log_filename, true); @@ -1870,7 +1881,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) log_maximum_blocks > 0) { ic_chatlog_history.removeFirst(); } - + QString f_char = m_chatmessage[CHAR_NAME]; QString f_custom_theme = ao_app->get_char_shouts(f_char); @@ -1882,7 +1893,8 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) color_rgb_list.append(color); } - append_ic_text(m_chatmessage[MESSAGE], f_displayname, "", m_chatmessage[TEXT_COLOR].toInt()); + append_ic_text(m_chatmessage[MESSAGE], f_displayname, "", + m_chatmessage[TEXT_COLOR].toInt()); // if an objection is used if (objection_mod <= 4 && objection_mod >= 1) { @@ -1904,11 +1916,15 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) // case 4 is AO2 only case 4: if (custom_objection != "") { - ui_vp_objection->play("custom_objections/" + custom_objection, f_char, f_custom_theme, shout_stay_time); - objection_player->play("custom_objections/" + custom_objection.split('.')[0], f_char, f_custom_theme); + ui_vp_objection->play("custom_objections/" + custom_objection, f_char, + f_custom_theme, shout_stay_time); + objection_player->play("custom_objections/" + + custom_objection.split('.')[0], + f_char, f_custom_theme); } else { - ui_vp_objection->play("custom", f_char, f_custom_theme, shout_stay_time); + ui_vp_objection->play("custom", f_char, f_custom_theme, + shout_stay_time); objection_player->play("custom", f_char, f_custom_theme); } break; @@ -2003,11 +2019,10 @@ void Courtroom::handle_chatmessage_2() ->get_design_element("showname_extra_width", "courtroom_design.ini", customchar) .toInt(); - QString align = - ao_app - ->get_design_element("showname_align", "courtroom_design.ini", - customchar) - .toLower(); + QString align = ao_app + ->get_design_element("showname_align", + "courtroom_design.ini", customchar) + .toLower(); if (align == "right") ui_vp_showname->setAlignment(Qt::AlignRight); else if (align == "center") @@ -2039,8 +2054,7 @@ void Courtroom::handle_chatmessage_2() set_font(ui_vp_showname, "", "showname", customchar); } - else - { + else { ui_vp_showname->resize(default_width.width, ui_vp_showname->height()); } } @@ -2063,12 +2077,13 @@ void Courtroom::handle_chatmessage_2() int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); // Deal with invalid emote modifiers - if (emote_mod != 0 && emote_mod != 1 && emote_mod != 2 \ - && emote_mod != 5 && emote_mod != 6) { - if (emote_mod == 4) - emote_mod = 6; // Addresses issue with an old bug that sent the wrong emote modifier for zoompre - else - emote_mod = 0; + if (emote_mod != 0 && emote_mod != 1 && emote_mod != 2 && emote_mod != 5 && + emote_mod != 6) { + if (emote_mod == 4) + emote_mod = 6; // Addresses issue with an old bug that sent the wrong + // emote modifier for zoompre + else + emote_mod = 0; } if (ao_app->flipping_enabled && m_chatmessage[FLIP].toInt() == 1) @@ -2574,7 +2589,8 @@ QString Courtroom::filter_ic_text(QString p_text, bool html, int target_pos, return p_text_escaped; } -void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action, int color) +void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action, + int color) { QTextCharFormat bold; QTextCharFormat normal; @@ -2586,8 +2602,7 @@ void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action, const int old_scrollbar_value = ui_ic_chatlog->verticalScrollBar()->value(); if (p_action == "") - p_text = filter_ic_text(p_text, ao_app->is_colorlog_enabled(), -1, - color); + p_text = filter_ic_text(p_text, ao_app->is_colorlog_enabled(), -1, color); if (log_goes_downwards) { const bool is_scrolled_down = @@ -2810,8 +2825,7 @@ void Courtroom::chat_tick() } QString f_char; QString f_custom_theme; - if (ao_app->is_customchat_enabled()) - { + if (ao_app->is_customchat_enabled()) { f_char = m_chatmessage[CHAR_NAME]; f_custom_theme = ao_app->get_chat(f_char); } @@ -3174,7 +3188,8 @@ void Courtroom::handle_song(QStringList *p_contents) } if (!mute_map.value(n_char)) { - chatlogpiece *temp = new chatlogpiece(str_char, str_show, f_song, true, m_chatmessage[TEXT_COLOR].toInt()); + chatlogpiece *temp = new chatlogpiece(str_char, str_show, f_song, true, + m_chatmessage[TEXT_COLOR].toInt()); ic_chatlog_history.append(*temp); if (ao_app->get_auto_logging_enabled()) ao_app->append_to_file(temp->get_full(), ao_app->log_filename, true); @@ -4100,8 +4115,7 @@ void Courtroom::on_music_list_context_menu_requested(const QPoint &pos) { QMenu *menu = new QMenu(); - menu->addAction(QString(tr("Play Random Song")), this, - SLOT(music_random())); + menu->addAction(QString(tr("Play Random Song")), this, SLOT(music_random())); menu->addSeparator(); menu->addAction(QString(tr("Expand All Categories")), this, SLOT(music_list_expand_all())); @@ -4157,7 +4171,9 @@ void Courtroom::music_synchronize(bool toggle) void Courtroom::music_random() { QList clist; - QTreeWidgetItemIterator it(ui_music_list, QTreeWidgetItemIterator::NotHidden | QTreeWidgetItemIterator::NoChildren); + QTreeWidgetItemIterator it(ui_music_list, + QTreeWidgetItemIterator::NotHidden | + QTreeWidgetItemIterator::NoChildren); while (*it) { clist += (*it); ++it; @@ -4402,7 +4418,8 @@ void Courtroom::set_text_color_dropdown() // Update markdown colors. TODO: make a loading function that only loads the // config file once instead of several times for (int c = 0; c < max_colors; ++c) { - QColor color = ao_app->get_chat_color("c" + QString::number(c), current_char); + QColor color = + ao_app->get_chat_color("c" + QString::number(c), current_char); color_rgb_list.append(color); color_markdown_start_list.append(ao_app->get_chat_markdown( "c" + QString::number(c) + "_start", current_char)); @@ -4578,10 +4595,7 @@ void Courtroom::on_char_select_right_clicked() set_char_select_page(); } -void Courtroom::on_spectator_clicked() -{ - char_clicked(-1); -} +void Courtroom::on_spectator_clicked() { char_clicked(-1); } void Courtroom::on_call_mod_clicked() { @@ -4654,14 +4668,16 @@ void Courtroom::on_showname_enable_clicked() append_ic_text(item.get_message(), item.get_showname(), tr("has played a song")); else - append_ic_text(item.get_message(), item.get_showname(), "", item.get_chat_color()); + append_ic_text(item.get_message(), item.get_showname(), "", + item.get_chat_color()); } else { if (item.is_song()) append_ic_text(item.get_message(), item.get_name(), tr("has played a song")); else - append_ic_text(item.get_message(), item.get_name(), "", item.get_chat_color()); + append_ic_text(item.get_message(), item.get_name(), "", + item.get_chat_color()); } } diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index fd7453e..e4e5d5c 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -176,7 +176,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) } } else if (header == "FL") { -// encryption_needed = true; + // encryption_needed = true; yellow_text_enabled = false; prezoom_enabled = false; flipping_enabled = false; @@ -292,14 +292,14 @@ void AOApplication::server_packet_received(AOPacket *p_packet) // Remove any characters not accepted in folder names for the server_name // here - if (AOApplication::get_auto_logging_enabled()){ - this->log_filename = QDateTime::currentDateTime().toUTC().toString( - "'logs/" + server_name.remove(QRegExp("[\\\\/:*?\"<>|\']")) + - "/'ddd MMMM yyyy hh.mm.ss t'.log'"); - this->write_to_file("Joined server " + server_name + " on address " + - server_address + " on " + - QDateTime::currentDateTime().toUTC().toString(), - log_filename, true); + if (AOApplication::get_auto_logging_enabled()) { + this->log_filename = QDateTime::currentDateTime().toUTC().toString( + "'logs/" + server_name.remove(QRegExp("[\\\\/:*?\"<>|\']")) + + "/'ddd MMMM yyyy hh.mm.ss t'.log'"); + this->write_to_file("Joined server " + server_name + " on address " + + server_address + " on " + + QDateTime::currentDateTime().toUTC().toString(), + log_filename, true); } QCryptographicHash hash(QCryptographicHash::Algorithm::Sha256); @@ -335,8 +335,8 @@ void AOApplication::server_packet_received(AOPacket *p_packet) ++loaded_chars; w_lobby->set_loading_text(tr("Loading chars:\n%1/%2") - .arg(QString::number(loaded_chars)) - .arg(QString::number(char_list_size))); + .arg(QString::number(loaded_chars)) + .arg(QString::number(char_list_size))); w_courtroom->append_char(f_char); diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 45dd34f..33a18d5 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -435,7 +435,8 @@ QString AOApplication::get_tagged_stylesheet(QString target_tag, QString p_file) QString AOApplication::get_chat_markdown(QString p_identifier, QString p_chat) { - QString design_ini_path = get_base_path() + "misc/" + get_chat(p_chat) + "/config.ini"; + QString design_ini_path = + get_base_path() + "misc/" + get_chat(p_chat) + "/config.ini"; QString default_path = get_base_path() + "misc/default/config.ini"; QString f_result = read_design_ini(p_identifier, design_ini_path); @@ -449,7 +450,8 @@ QColor AOApplication::get_chat_color(QString p_identifier, QString p_chat) { QColor return_color(255, 255, 255); - QString design_ini_path = get_base_path() + "misc/" + get_chat(p_chat) + "/config.ini"; + QString design_ini_path = + get_base_path() + "misc/" + get_chat(p_chat) + "/config.ini"; QString default_path = get_base_path() + "misc/default/config.ini"; QString f_result = read_design_ini(p_identifier, design_ini_path); @@ -909,8 +911,8 @@ QString AOApplication::get_effect_sound(QString fx_name, QString p_char) } } - if(fx_name == "realization"){ - f_result = get_custom_realization(p_char); + if (fx_name == "realization") { + f_result = get_custom_realization(p_char); } return f_result; @@ -1056,7 +1058,7 @@ QString AOApplication::get_casing_can_host_cases() } bool AOApplication::get_auto_logging_enabled() { - QString result = - configini->value("automatic_logging_enabled", "true").value(); - return result.startsWith("true"); + QString result = + configini->value("automatic_logging_enabled", "true").value(); + return result.startsWith("true"); } From da002085abf3deab2c51cbabcfb910e78c81656e Mon Sep 17 00:00:00 2001 From: scatterflower Date: Mon, 17 Aug 2020 07:05:37 -0500 Subject: [PATCH 32/46] Do not update colors in log for each IC message --- src/courtroom.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index be7588a..978cc04 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1885,14 +1885,6 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) QString f_char = m_chatmessage[CHAR_NAME]; QString f_custom_theme = ao_app->get_char_shouts(f_char); - // Load the colors in case it's using a custom chatbox with custom colors. - // Or reload the default ones in case it's not using custom colors - color_rgb_list.clear(); - for (int c = 0; c < max_colors; ++c) { - QColor color = ao_app->get_chat_color("c" + QString::number(c), f_char); - color_rgb_list.append(color); - } - append_ic_text(m_chatmessage[MESSAGE], f_displayname, "", m_chatmessage[TEXT_COLOR].toInt()); From 4ada75a3bd0cf57007458b2af6f44c76ac33e575 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Mon, 17 Aug 2020 13:06:35 -0500 Subject: [PATCH 33/46] fix statement after break; from case --- src/courtroom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 978cc04..cc35a7b 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1919,8 +1919,8 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) shout_stay_time); objection_player->play("custom", f_char, f_custom_theme); } - break; m_chatmessage[EMOTE_MOD] = 1; + break; } sfx_player->clear(); // Objection played! Cut all sfx. } From 475a572c3bdb0f1d4a7353b9c61bbfac71888ef9 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Tue, 18 Aug 2020 18:02:53 +0300 Subject: [PATCH 34/46] Improved blankposting (#256) * Consolidate blankposting into singular log entries of "no message" instead of spamming the logs repeatedly when someone decides to keep switching emotes Return proper blankpost checking to 2.8.5 (chatmessage_is_empty bool makes sure the chatbox doesn't appear - branch broke that behavior by never setting it) More robust blankpost checking, meaning that passing a competely empty "" string will also count as a blankpost Fix screenshake not working with blankposting by moving it before the chatmessage_is_empty check in start_chack_ticking() stage of the message parsing * Allow user to send blankposts without even having to input a single spacebar, but only if last m_chatmessage CID matches ours. * Reviews are cool and good:ok_hand: allow sending no-text chat message to server without weird cid checks (let the server validate if they want to do STR_OR_EMPTY or just STR) - doesn't break existing behavior and lets servers introduce the new one if they want to Treat all blank/whitespace messages as blankposting and not just single-whitespace. Remove chatmessage_is_empty bool because why the fuck would you even need it if you have m_chatmessage[MESSAGE] already Simplify chatlogpiece log entry to not be a *temp pointer by suggestion * another useless bool destroyed Make "additive" have a very awesome emergent behavior with blankposting - keep showing the chatbox+message while only changing the emotes. Works with preanims too! --- include/courtroom.h | 4 ---- src/courtroom.cpp | 54 ++++++++++++++++++++++++++------------------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/include/courtroom.h b/include/courtroom.h index 898e8ba..df75cce 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -315,9 +315,6 @@ private: bool rainbow_appended = false; bool blank_blip = false; - // Whether or not is this message additive to the previous one - bool is_additive = false; - // Used for getting the current maximum blocks allowed in the IC chatlog. int log_maximum_blocks = 0; @@ -355,7 +352,6 @@ private: static const int MS_MINIMUM = 15; static const int MS_MAXIMUM = 30; QString m_chatmessage[MS_MAXIMUM]; - bool chatmessage_is_empty = false; QString previous_ic_message = ""; QString additive_previous = ""; diff --git a/src/courtroom.cpp b/src/courtroom.cpp index cc35a7b..b76a4a6 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1538,7 +1538,7 @@ void Courtroom::append_server_chatmessage(QString p_name, QString p_message, void Courtroom::on_chat_return_pressed() { - if (ui_ic_chat_message->text() == "" || is_muted) + if (is_muted) return; if ((anim_state < 3 || text_state < 2) && objection_state == 0) @@ -1863,31 +1863,35 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) reset_ui(); } - // Let the server handle actually checking if they're allowed to do this. - is_additive = m_chatmessage[ADDITIVE].toInt() == 1; - QString f_charname = ""; if (f_char_id >= 0) f_charname = ao_app->get_showname(char_list.at(f_char_id).name); - chatlogpiece *temp = - new chatlogpiece(f_charname, f_displayname, m_chatmessage[MESSAGE], false, - m_chatmessage[TEXT_COLOR].toInt()); - ic_chatlog_history.append(*temp); - if (ao_app->get_auto_logging_enabled()) - ao_app->append_to_file(temp->get_full(), ao_app->log_filename, true); + if (m_chatmessage[MESSAGE].trimmed().isEmpty()) // User-created blankpost + { + m_chatmessage[MESSAGE] = ""; // Turn it into true blankpost + } - while (ic_chatlog_history.size() > log_maximum_blocks && - log_maximum_blocks > 0) { - ic_chatlog_history.removeFirst(); + if (!m_chatmessage[MESSAGE].isEmpty() || ic_chatlog_history.isEmpty() || ic_chatlog_history.last().get_message() != "") + { + chatlogpiece log_entry(f_charname, f_displayname, m_chatmessage[MESSAGE], false, + m_chatmessage[TEXT_COLOR].toInt()); + ic_chatlog_history.append(log_entry); + if (ao_app->get_auto_logging_enabled()) + ao_app->append_to_file(log_entry.get_full(), ao_app->log_filename, true); + + while (ic_chatlog_history.size() > log_maximum_blocks && + log_maximum_blocks > 0) { + ic_chatlog_history.removeFirst(); + } + + append_ic_text(m_chatmessage[MESSAGE], f_displayname, "", + m_chatmessage[TEXT_COLOR].toInt()); } QString f_char = m_chatmessage[CHAR_NAME]; QString f_custom_theme = ao_app->get_char_shouts(f_char); - append_ic_text(m_chatmessage[MESSAGE], f_displayname, "", - m_chatmessage[TEXT_COLOR].toInt()); - // if an objection is used if (objection_mod <= 4 && objection_mod >= 1) { switch (objection_mod) { @@ -2763,16 +2767,25 @@ void Courtroom::start_chat_ticking() this->do_flash(); sfx_player->play(ao_app->get_custom_realization(m_chatmessage[CHAR_NAME])); } - if (chatmessage_is_empty) { + int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); // text meme bonanza + if ((emote_mod == 0 || emote_mod == 5) && m_chatmessage[SCREENSHAKE] == "1") { + this->do_screenshake(); + } + if (m_chatmessage[MESSAGE].isEmpty()) { // since the message is empty, it's technically done ticking text_state = 2; + if (m_chatmessage[ADDITIVE] == "1") { + // Cool behavior + ui_vp_chatbox->show(); + ui_vp_message->show(); + } return; } ui_vp_chatbox->show(); ui_vp_message->show(); - if (!is_additive) { + if (m_chatmessage[ADDITIVE] != "1") { ui_vp_message->clear(); real_tick_pos = 0; additive_previous = ""; @@ -2789,11 +2802,6 @@ void Courtroom::start_chat_ticking() blip_player->set_blips(f_gender); - int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); // text meme bonanza - if ((emote_mod == 0 || emote_mod == 5) && m_chatmessage[SCREENSHAKE] == "1") { - this->do_screenshake(); - } - // means text is currently ticking text_state = 1; } From 76af6c030f337d97117331bb7c66bc8e37782d1a Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Tue, 18 Aug 2020 12:39:58 -0500 Subject: [PATCH 35/46] CI: Pin Linux target to Ubuntu 16.04 (Qt 5.9.5) --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e0b0886..faa01d4 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -15,7 +15,7 @@ before_script: - echo Current working directory is $(pwd) build linux x86_64: - image: ubuntu + image: ubuntu:18.04 stage: build tags: - docker From d10ad44ff9656e6128b63cf932289b1bf875bc3e Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Tue, 18 Aug 2020 14:24:15 -0500 Subject: [PATCH 36/46] CI: Build QtApng on Linux - Set lib as artifact instead of cache (to avoid race condition described in https://gitlab.com/gitlab-org/gitlab/-/issues/21409) - Delete _Unadapted folder and .git files when exporting artifact (yuck! should probably have never incorporated AO2-Themes as a separate repo; it should probably have stayed part of the vanilla repo.) --- .gitlab-ci.yml | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index faa01d4..6cb63b3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -5,8 +5,6 @@ stages: cache: key: ${CI_COMMIT_REF_SLUG} - paths: - - lib/ variables: DEBIAN_FRONTEND: noninteractive @@ -53,11 +51,21 @@ build linux x86_64: - cd .. # Extract QtApng - - mkdir qtapng - - cd qtapng - - curl -L https://github.com/Skycoder42/QtApng/releases/download/1.1.0-5/build_gcc_64_5.12.0.tar.xz -o apng.tar.xz - - tar -xvf apng.tar.xz - - cp gcc_64/plugins/imageformats/libqapng.so ../lib + #- mkdir qtapng + #- cd qtapng + #- curl -L https://github.com/Skycoder42/QtApng/releases/download/1.1.0-5/build_gcc_64_5.12.0.tar.xz -o apng.tar.xz + #- tar -xvf apng.tar.xz + #- cp gcc_64/plugins/imageformats/libqapng.so ../lib + #- cd .. + + # Build QtApng + - git clone https://github.com/Skycoder42/QtApng + - cd QtApng + - qmake -spec linux-clang + # Don't make examples - they're not compatible with Qt 5.9 + - make -j4 sub-src + #- make sub-src-install_subtargets + - cp plugins/imageformats/libqapng.so ../lib - cd .. # Build @@ -68,6 +76,7 @@ build linux x86_64: - upx --lzma -9 --force bin/Attorney_Online artifacts: paths: + - lib/ - bin/ build windows i686: @@ -116,12 +125,15 @@ build windows i686: - upx --lzma -9 --force bin/Attorney_Online.exe artifacts: paths: + - lib/ - bin/ # Base folder .deploy_base: &deploy_base | mkdir base cp -a ../base/ base/ + rm -rf base/themes/_Unadapted/ + rm base/themes/.gitattributes base/themes/.git # Miscellaneous files .deploy_misc: &deploy_misc | From a9ca555ec532f46a5e5b29404434ae7295814163 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Tue, 18 Aug 2020 15:22:58 -0500 Subject: [PATCH 37/46] CI: Fix nested base folders in artifact --- .gitlab-ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6cb63b3..85bf7f3 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -130,7 +130,6 @@ build windows i686: # Base folder .deploy_base: &deploy_base | - mkdir base cp -a ../base/ base/ rm -rf base/themes/_Unadapted/ rm base/themes/.gitattributes base/themes/.git From c984c57102bd269fed48a6b84fa9546f48e23dc9 Mon Sep 17 00:00:00 2001 From: likeawindrammer <31085911+likeawindrammer@users.noreply.github.com> Date: Tue, 18 Aug 2020 18:36:37 -0600 Subject: [PATCH 38/46] Update themes reference --- base/themes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/themes b/base/themes index 8de30fc..8ad1c0a 160000 --- a/base/themes +++ b/base/themes @@ -1 +1 @@ -Subproject commit 8de30fc0fa0e1492a29dad0e839764ca44168cb3 +Subproject commit 8ad1c0af3f5b0cf0657f43389cca87b24dba61ba From cef0ebc6eb2ac549a5475bee332be35ab7f565fc Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 19 Aug 2020 19:16:41 +0300 Subject: [PATCH 39/46] IC log rewrite (#259) * Rewrite the IC Log code to drastically reduce code duplication and have both downward and upward mode in the same function Regenerate the IC Log in set_widgets() function, making sure the maximum_blocks is accounted for and clearing the log to prepare for different log mode (upwards/downwards) if it's different from previous Add placeholder text telling the user the direction in which the log will go Remove useless first_message_sent global boolean, a remnant from a w e a k e r c o d e r m a n * Add log_colors boolean to reduce color I/O happening in append_ic_text (optimization meme) Clear the IC log when log_colors setting changes and reload theme is pressed Fix https://github.com/AttorneyOnline/AO2-Client/issues/221 * Add configurable margin between IC log entries Add configurable newline/singleline log mode Options in settings for these * Add optional timestamps * Un-hardcode "played music" from the chatlogpiece and introduce the "action" argument so that "presented evidence" is fully supported now Translate "has presented evidence" Regenerate IC chatlog instead of clearing it, properly updating every element with the new configurations * Go away *temp, code duplication making me shid and cry rn Why is this not done in append_ic_text, or why isn't there a dedicated ic logging func aAAAaaaaAAAaa Fix presenting evidence not being properly logged Fix timestamp being UTC instead of local time (local time will not be as confusing) * okok it was a joke a big ol bamboozle you got gnomed haha rick rolled beaned stickbugged I did NOT copy paste code, no, I actually intended to fix copy pasted code all along. log_ic_text was always planned. (Fix copypasted code for ic_chatlog_history and consolidate it into a single log_ic_text func) --- include/aoapplication.h | 9 ++ include/aooptionsdialog.h | 6 + include/chatlogpiece.h | 8 +- include/courtroom.h | 19 ++- src/aooptionsdialog.cpp | 46 +++++++ src/chatlogpiece.cpp | 28 +++-- src/courtroom.cpp | 237 +++++++++++++++++------------------- src/text_file_functions.cpp | 20 +++ 8 files changed, 230 insertions(+), 143 deletions(-) diff --git a/include/aoapplication.h b/include/aoapplication.h index f4685ec..b44c8a8 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -213,6 +213,15 @@ public: // or downwards (vanilla behaviour). bool get_log_goes_downwards(); + // Returns whether the log should separate name from text via newline or : + bool get_log_newline(); + + // Get spacing between IC log entries. + int get_log_margin(); + + // Returns whether the log should have a timestamp. + bool get_log_timestamp(); + // Returns the username the user may have set in config.ini. QString get_default_username(); diff --git a/include/aooptionsdialog.h b/include/aooptionsdialog.h index 2b8c879..fe99626 100644 --- a/include/aooptionsdialog.h +++ b/include/aooptionsdialog.h @@ -46,6 +46,12 @@ private: QCheckBox *ui_downwards_cb; QLabel *ui_length_lbl; QSpinBox *ui_length_spinbox; + QLabel *ui_log_newline_lbl; + QCheckBox *ui_log_newline_cb; + QLabel *ui_log_margin_lbl; + QSpinBox *ui_log_margin_spinbox; + QLabel *ui_log_timestamp_lbl; + QCheckBox *ui_log_timestamp_cb; QFrame *ui_log_names_divider; QLineEdit *ui_username_textbox; QLabel *ui_username_lbl; diff --git a/include/chatlogpiece.h b/include/chatlogpiece.h index 14d4b34..da78d0d 100644 --- a/include/chatlogpiece.h +++ b/include/chatlogpiece.h @@ -10,14 +10,14 @@ class chatlogpiece { public: chatlogpiece(); chatlogpiece(QString p_name, QString p_showname, QString p_message, - bool p_song,int color); + QString p_action,int color); chatlogpiece(QString p_name, QString p_showname, QString p_message, - bool p_song, int color, QDateTime p_datetime); + QString p_action, int color, QDateTime p_datetime); QString get_name(); QString get_showname(); QString get_message(); - bool is_song(); + QString get_action(); QDateTime get_datetime(); QString get_datetime_as_string(); int get_chat_color(); @@ -27,9 +27,9 @@ private: QString name; QString showname; QString message; + QString action; QDateTime datetime; int color; - bool p_is_song; }; #endif // CHATLOGPIECE_H diff --git a/include/courtroom.h b/include/courtroom.h index df75cce..979650a 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -218,6 +218,8 @@ public: QString filter_ic_text(QString p_text, bool colorize = false, int pos = -1, int default_color = 0); + void log_ic_text(QString p_name, QString p_showname, QString p_message, QString p_action="", int p_color=0); + // adds text to the IC chatlog. p_name first as bold then p_text then a newlin // this function keeps the chatlog scrolled to the top unless there's text // selected @@ -262,7 +264,6 @@ private: int m_viewport_width = 256; int m_viewport_height = 192; - bool first_message_sent = false; int maximumMessages = 0; QParallelAnimationGroup *screenshake_animation_group = @@ -319,7 +320,19 @@ private: int log_maximum_blocks = 0; // True, if the log should go downwards. - bool log_goes_downwards = false; + bool log_goes_downwards = true; + + // True, if log should display colors. + bool log_colors = true; + + // True, if the log should display the message like name
text instead of name: text + bool log_newline = false; + + // Margin in pixels between log entries for the IC log. + int log_margin = 0; + + // True, if the log should have a timestamp. + bool log_timestamp = false; // delay before chat messages starts ticking QTimer *text_delay_timer; @@ -649,6 +662,8 @@ private: void reset_ic(); void reset_ui(); + + void regenerate_ic_chatlog(); public slots: void objection_done(); void preanim_done(); diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp index 6cedee8..4e6aca6 100644 --- a/src/aooptionsdialog.cpp +++ b/src/aooptionsdialog.cpp @@ -120,6 +120,49 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app) ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_length_spinbox); + row += 1; + ui_log_newline_lbl = new QLabel(ui_form_layout_widget); + ui_log_newline_lbl->setText(tr("Log newline:")); + ui_log_newline_lbl->setToolTip( + tr("If ticked, new messages will appear separated, " + "with the message coming on the next line after the name. " + "When unticked, it displays it as 'name: message'.")); + + ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_log_newline_lbl); + + ui_log_newline_cb = new QCheckBox(ui_form_layout_widget); + ui_log_newline_cb->setChecked(p_ao_app->get_log_newline()); + + ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_log_newline_cb); + + row += 1; + ui_log_margin_lbl = new QLabel(ui_form_layout_widget); + ui_log_margin_lbl->setText(tr("Log margin:")); + ui_log_margin_lbl->setToolTip(tr( + "The distance in pixels between each entry in the IC log. " + "Default: 0.")); + + ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_log_margin_lbl); + + ui_log_margin_spinbox = new QSpinBox(ui_form_layout_widget); + ui_log_margin_spinbox->setMaximum(1000); + ui_log_margin_spinbox->setValue(p_ao_app->get_log_margin()); + + ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_log_margin_spinbox); + + row += 1; + ui_log_timestamp_lbl = new QLabel(ui_form_layout_widget); + ui_log_timestamp_lbl->setText(tr("Log timestamp:")); + ui_log_timestamp_lbl->setToolTip( + tr("If ticked, log will contain a timestamp in UTC before the name.")); + + ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_log_timestamp_lbl); + + ui_log_timestamp_cb = new QCheckBox(ui_form_layout_widget); + ui_log_timestamp_cb->setChecked(p_ao_app->get_log_timestamp()); + + ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_log_timestamp_cb); + row += 1; ui_log_names_divider = new QFrame(ui_form_layout_widget); ui_log_names_divider->setFrameShape(QFrame::HLine); @@ -726,6 +769,9 @@ void AOOptionsDialog::save_pressed() configini->setValue("theme", ui_theme_combobox->currentText()); configini->setValue("log_goes_downwards", ui_downwards_cb->isChecked()); configini->setValue("log_maximum", ui_length_spinbox->value()); + configini->setValue("log_newline", ui_log_newline_cb->isChecked()); + configini->setValue("log_margin", ui_log_margin_spinbox->value()); + configini->setValue("log_timestamp", ui_log_timestamp_cb->isChecked()); configini->setValue("default_username", ui_username_textbox->text()); configini->setValue("show_custom_shownames", ui_showname_cb->isChecked()); configini->setValue("master", ui_ms_textbox->text()); diff --git a/src/chatlogpiece.cpp b/src/chatlogpiece.cpp index 2a041f1..05a924c 100644 --- a/src/chatlogpiece.cpp +++ b/src/chatlogpiece.cpp @@ -6,29 +6,29 @@ chatlogpiece::chatlogpiece() showname = tr("UNKNOWN"); message = tr("UNKNOWN"); color = 0; - p_is_song = false; + action = ""; datetime = QDateTime::currentDateTime().toUTC(); } chatlogpiece::chatlogpiece(QString p_name, QString p_showname, - QString p_message, bool p_song, int p_color) + QString p_message, QString p_action, int p_color) { name = p_name; showname = p_showname; message = p_message; - p_is_song = p_song; + action = p_action; color = p_color; datetime = QDateTime::currentDateTime().toUTC(); } chatlogpiece::chatlogpiece(QString p_name, QString p_showname, - QString p_message, bool p_song, int p_color, + QString p_message, QString p_action, int p_color, QDateTime p_datetime) { name = p_name; showname = p_showname; message = p_message; - p_is_song = p_song; + action = p_action; color = p_color; datetime = p_datetime.toUTC(); } @@ -41,7 +41,7 @@ QString chatlogpiece::get_message() { return message; } QDateTime chatlogpiece::get_datetime() { return datetime; } -bool chatlogpiece::is_song() { return p_is_song; } +QString chatlogpiece::get_action() { return action; } QString chatlogpiece::get_datetime_as_string() { return datetime.toString(); } @@ -54,13 +54,15 @@ QString chatlogpiece::get_full() full.append(get_datetime_as_string()); full.append("] "); full.append(get_showname()); - full.append(" ("); - full.append(get_name()); - full.append(")"); - if (p_is_song) - full.append(tr(" has played a song: ")); - else - full.append(": "); + if (get_showname() != get_name()) + { + full.append(" ("); + full.append(get_name()); + full.append(")"); + } + if (!get_action().isEmpty()) + full.append(" " + get_action()); + full.append(": "); full.append(get_message()); return full; diff --git a/src/courtroom.cpp b/src/courtroom.cpp index b76a4a6..fe10e13 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -109,6 +109,10 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() log_maximum_blocks = ao_app->get_max_log_size(); log_goes_downwards = ao_app->get_log_goes_downwards(); + log_colors = ao_app->is_colorlog_enabled(); + log_newline = ao_app->get_log_newline(); + log_margin = ao_app->get_log_margin(); + log_timestamp = ao_app->get_log_timestamp(); ui_ms_chatlog = new AOTextArea(this); ui_ms_chatlog->setReadOnly(true); @@ -581,8 +585,20 @@ void Courtroom::set_widgets() ui_vp_objection->move(ui_viewport->x(), ui_viewport->y()); ui_vp_objection->combo_resize(ui_viewport->width(), ui_viewport->height()); + log_maximum_blocks = ao_app->get_max_log_size(); + + bool regenerate = log_goes_downwards != ao_app->get_log_goes_downwards() || log_colors != ao_app->is_colorlog_enabled() || log_newline != ao_app->get_log_newline() || log_margin != ao_app->get_log_margin() || log_timestamp != ao_app->get_log_timestamp(); + log_goes_downwards = ao_app->get_log_goes_downwards(); + log_colors = ao_app->is_colorlog_enabled(); + log_newline = ao_app->get_log_newline(); + log_margin = ao_app->get_log_margin(); + log_timestamp = ao_app->get_log_timestamp(); + if (regenerate) + regenerate_ic_chatlog(); + set_size_and_pos(ui_ic_chatlog, "ic_chatlog"); ui_ic_chatlog->setFrameShape(QFrame::NoFrame); + ui_ic_chatlog->setPlaceholderText(log_goes_downwards ? "▼ Log goes down ▼" : "▲ Log goes up ▲"); set_size_and_pos(ui_ms_chatlog, "ms_chatlog"); ui_ms_chatlog->setFrameShape(QFrame::NoFrame); @@ -1874,17 +1890,8 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) if (!m_chatmessage[MESSAGE].isEmpty() || ic_chatlog_history.isEmpty() || ic_chatlog_history.last().get_message() != "") { - chatlogpiece log_entry(f_charname, f_displayname, m_chatmessage[MESSAGE], false, + log_ic_text(f_charname, f_displayname, m_chatmessage[MESSAGE], "", m_chatmessage[TEXT_COLOR].toInt()); - ic_chatlog_history.append(log_entry); - if (ao_app->get_auto_logging_enabled()) - ao_app->append_to_file(log_entry.get_full(), ao_app->log_filename, true); - - while (ic_chatlog_history.size() > log_maximum_blocks && - log_maximum_blocks > 0) { - ic_chatlog_history.removeFirst(); - } - append_ic_text(m_chatmessage[MESSAGE], f_displayname, "", m_chatmessage[TEXT_COLOR].toInt()); } @@ -2275,13 +2282,16 @@ void Courtroom::handle_chatmessage_3() if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) { // shifted by 1 because 0 is no evidence per legacy standards QString f_image = local_evidence_list.at(f_evi_id - 1).image; - QString f_name = local_evidence_list.at(f_evi_id - 1).name; + QString f_evi_name = local_evidence_list.at(f_evi_id - 1).name; // def jud and hlp should display the evidence icon on the RIGHT side bool is_left_side = !(f_side == "def" || f_side == "hlp" || f_side == "jud" || f_side == "jur"); ui_vp_evidence_display->show_evidence(f_image, is_left_side, ui_sfx_slider->value()); - append_ic_text(f_name, f_showname, "has presented evidence"); + + log_ic_text(m_chatmessage[CHAR_NAME], m_chatmessage[SHOWNAME], f_evi_name, tr("has presented evidence"), + m_chatmessage[TEXT_COLOR].toInt()); + append_ic_text(f_evi_name, f_showname, tr("has presented evidence")); } int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); @@ -2585,107 +2595,107 @@ QString Courtroom::filter_ic_text(QString p_text, bool html, int target_pos, return p_text_escaped; } +void Courtroom::log_ic_text(QString p_name, QString p_showname, + QString p_message, QString p_action, int p_color) +{ + chatlogpiece log_entry(p_name, p_showname, p_message, p_action, + p_color); + ic_chatlog_history.append(log_entry); + if (ao_app->get_auto_logging_enabled()) + ao_app->append_to_file(log_entry.get_full(), ao_app->log_filename, true); + + while (ic_chatlog_history.size() > log_maximum_blocks && + log_maximum_blocks > 0) { + ic_chatlog_history.removeFirst(); + } +} + void Courtroom::append_ic_text(QString p_text, QString p_name, QString p_action, int color) { QTextCharFormat bold; QTextCharFormat normal; QTextCharFormat italics; + QTextBlockFormat format; bold.setFontWeight(QFont::Bold); normal.setFontWeight(QFont::Normal); italics.setFontItalic(true); + format.setTopMargin(log_margin); const QTextCursor old_cursor = ui_ic_chatlog->textCursor(); const int old_scrollbar_value = ui_ic_chatlog->verticalScrollBar()->value(); + const bool need_newline = !ui_ic_chatlog->document()->isEmpty(); + const int scrollbar_target_value = log_goes_downwards ? ui_ic_chatlog->verticalScrollBar()->maximum() : ui_ic_chatlog->verticalScrollBar()->minimum(); - if (p_action == "") - p_text = filter_ic_text(p_text, ao_app->is_colorlog_enabled(), -1, color); + ui_ic_chatlog->moveCursor(log_goes_downwards ? QTextCursor::End : QTextCursor::Start); - if (log_goes_downwards) { - const bool is_scrolled_down = - old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->maximum(); + // Only prepend with newline if log goes downwards + if (log_goes_downwards && need_newline) { + ui_ic_chatlog->textCursor().insertBlock(format); + } - ui_ic_chatlog->moveCursor(QTextCursor::End); + // Timestamp if we're doing that meme + if (log_timestamp) + ui_ic_chatlog->textCursor().insertText("[" + QDateTime::currentDateTime().toString("h:mm:ss AP") + "] ", normal); - if (!first_message_sent) { - ui_ic_chatlog->textCursor().insertText(p_name, bold); - first_message_sent = true; - } - else { - ui_ic_chatlog->textCursor().insertText('\n' + p_name, bold); - } - - if (p_action != "") { - ui_ic_chatlog->textCursor().insertText(" " + p_action + ": ", normal); - ui_ic_chatlog->textCursor().insertText(p_text + ".", italics); - } - else { + // Format the name of the actor + ui_ic_chatlog->textCursor().insertText(p_name, bold); + // If action not blank: + if (p_action != "") { + // Format the action in normal + ui_ic_chatlog->textCursor().insertText(" " + p_action, normal); + if (log_newline) + // For some reason, we're forced to use
instead of the more sensible \n. + // Why? Because \n is treated as a new Block instead of a soft newline within a paragraph! + ui_ic_chatlog->textCursor().insertHtml("
"); + else ui_ic_chatlog->textCursor().insertText(": ", normal); - ui_ic_chatlog->textCursor().insertHtml(p_text); - } - - // If we got too many blocks in the current log, delete some from the top. - while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks && - log_maximum_blocks > 0) { - ui_ic_chatlog->moveCursor(QTextCursor::Start); - ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor); - ui_ic_chatlog->textCursor().removeSelectedText(); - ui_ic_chatlog->textCursor().deleteChar(); - } - - if (old_cursor.hasSelection() || !is_scrolled_down) { - // The user has selected text or scrolled away from the bottom: maintain - // position. - ui_ic_chatlog->setTextCursor(old_cursor); - ui_ic_chatlog->verticalScrollBar()->setValue(old_scrollbar_value); - } - else { - // The user hasn't selected any text and the scrollbar is at the bottom: - // scroll to the bottom. - ui_ic_chatlog->moveCursor(QTextCursor::End); - ui_ic_chatlog->verticalScrollBar()->setValue( - ui_ic_chatlog->verticalScrollBar()->maximum()); - } + // Format the result in italics + ui_ic_chatlog->textCursor().insertText(p_text + ".", italics); } else { - const bool is_scrolled_up = - old_scrollbar_value == ui_ic_chatlog->verticalScrollBar()->minimum(); - - ui_ic_chatlog->moveCursor(QTextCursor::Start); - - ui_ic_chatlog->textCursor().insertText(p_name, bold); - - if (p_action != "") { - ui_ic_chatlog->textCursor().insertText(" " + p_action + ": ", normal); - ui_ic_chatlog->textCursor().insertText(p_text + "." + '\n', italics); - } - else { + if (log_newline) + // For some reason, we're forced to use
instead of the more sensible \n. + // Why? Because \n is treated as a new Block instead of a soft newline within a paragraph! + ui_ic_chatlog->textCursor().insertHtml("
"); + else ui_ic_chatlog->textCursor().insertText(": ", normal); - ui_ic_chatlog->textCursor().insertHtml(p_text + "
"); - } + // Format the result according to html + if (log_colors) + ui_ic_chatlog->textCursor().insertHtml(filter_ic_text(p_text, true, -1, color)); + else + ui_ic_chatlog->textCursor().insertText(filter_ic_text(p_text, false), normal); + } - // If we got too many blocks in the current log, delete some from the - // bottom. - while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks && - log_maximum_blocks > 0) { - ui_ic_chatlog->moveCursor(QTextCursor::End); - ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor); - ui_ic_chatlog->textCursor().removeSelectedText(); + // Only append with newline if log goes upwards + if (!log_goes_downwards && need_newline) { + ui_ic_chatlog->textCursor().insertBlock(format); + } + + // If we got too many blocks in the current log, delete some. + while (ui_ic_chatlog->document()->blockCount() > log_maximum_blocks && + log_maximum_blocks > 0) { + ui_ic_chatlog->moveCursor(log_goes_downwards ? QTextCursor::Start : QTextCursor::End); + ui_ic_chatlog->textCursor().select(QTextCursor::BlockUnderCursor); + ui_ic_chatlog->textCursor().removeSelectedText(); + if (log_goes_downwards) + ui_ic_chatlog->textCursor().deleteChar(); + else ui_ic_chatlog->textCursor().deletePreviousChar(); - } + } - if (old_cursor.hasSelection() || !is_scrolled_up) { - // The user has selected text or scrolled away from the top: maintain - // position. - ui_ic_chatlog->setTextCursor(old_cursor); - ui_ic_chatlog->verticalScrollBar()->setValue(old_scrollbar_value); - } - else { - // The user hasn't selected any text and the scrollbar is at the top: - // scroll to the top. - ui_ic_chatlog->moveCursor(QTextCursor::Start); - ui_ic_chatlog->verticalScrollBar()->setValue( - ui_ic_chatlog->verticalScrollBar()->minimum()); - } + // Finally, scroll the scrollbar to the correct position. + if (old_cursor.hasSelection() || old_scrollbar_value != scrollbar_target_value) { + // The user has selected text or scrolled away from the bottom: maintain + // position. + ui_ic_chatlog->setTextCursor(old_cursor); + ui_ic_chatlog->verticalScrollBar()->setValue(old_scrollbar_value); + } + else { + // The user hasn't selected any text and the scrollbar is at the bottom: + // scroll to the bottom. + ui_ic_chatlog->moveCursor(log_goes_downwards ? QTextCursor::End : QTextCursor::Start); + ui_ic_chatlog->verticalScrollBar()->setValue( + ui_ic_chatlog->verticalScrollBar()->maximum()); } } @@ -3188,17 +3198,8 @@ void Courtroom::handle_song(QStringList *p_contents) } if (!mute_map.value(n_char)) { - chatlogpiece *temp = new chatlogpiece(str_char, str_show, f_song, true, - m_chatmessage[TEXT_COLOR].toInt()); - ic_chatlog_history.append(*temp); - if (ao_app->get_auto_logging_enabled()) - ao_app->append_to_file(temp->get_full(), ao_app->log_filename, true); - - while (ic_chatlog_history.size() > log_maximum_blocks && - log_maximum_blocks > 0) { - ic_chatlog_history.removeFirst(); - } - + log_ic_text(str_char, str_show, f_song, tr("has played a song"), + m_chatmessage[TEXT_COLOR].toInt()); append_ic_text(f_song_clear, str_show, tr("has played a song")); music_player->play(f_song, channel, looping, effect_flags); @@ -4659,31 +4660,19 @@ void Courtroom::on_guard_clicked() { ui_ic_chat_message->setFocus(); } void Courtroom::on_showname_enable_clicked() { - ui_ic_chatlog->clear(); - first_message_sent = false; - - foreach (chatlogpiece item, ic_chatlog_history) { - if (ui_showname_enable->isChecked()) { - if (item.is_song()) - append_ic_text(item.get_message(), item.get_showname(), - tr("has played a song")); - else - append_ic_text(item.get_message(), item.get_showname(), "", - item.get_chat_color()); - } - else { - if (item.is_song()) - append_ic_text(item.get_message(), item.get_name(), - tr("has played a song")); - else - append_ic_text(item.get_message(), item.get_name(), "", - item.get_chat_color()); - } - } - + regenerate_ic_chatlog(); ui_ic_chat_message->setFocus(); } +void Courtroom::regenerate_ic_chatlog() +{ + ui_ic_chatlog->clear(); + foreach (chatlogpiece item, ic_chatlog_history) { + append_ic_text(item.get_message(), ui_showname_enable->isChecked() ? item.get_showname() : item.get_name(), + item.get_action(), item.get_chat_color()); + } +} + void Courtroom::on_evidence_button_clicked() { if (ui_evidence->isHidden()) { diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 33a18d5..8247fd8 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -53,6 +53,26 @@ bool AOApplication::get_log_goes_downwards() return result.startsWith("true"); } +bool AOApplication::get_log_newline() +{ + QString result = + configini->value("log_newline", "false").value(); + return result.startsWith("true"); +} + +int AOApplication::get_log_margin() +{ + int result = configini->value("log_margin", 0).toInt(); + return result; +} + +bool AOApplication::get_log_timestamp() +{ + QString result = + configini->value("log_timestamp", "false").value(); + return result.startsWith("true"); +} + bool AOApplication::get_showname_enabled_by_default() { QString result = From 9eb0f53db1ae87058458eae267f2a72e3a0a8091 Mon Sep 17 00:00:00 2001 From: scatterflower <2956568+scatterflower@users.noreply.github.com> Date: Wed, 19 Aug 2020 16:40:37 -0500 Subject: [PATCH 40/46] Reset BASS when switching devices; drop Qt Multimedia support (#262) * Allow changing audio device on the fly while in a server * Use default audio device if device in config doesn't exist * Automatically change audio device to default when current one is invalid * Destroy Qt Multimedia support It was decided that there was not enough attention being given to Qt Multimedia support to justify its continued maintenance simply as a libre alternative to BASS. While substantial changes to audio were being made in 2.8, the Qt Multimedia support code fell behind in disrepair. It's clear that there is no vested interest in implementing audio features twice for the sake of licensing. When it's time to switch to another audio library, it will be done unilaterally. * CI: Use BASS for Linux build Co-authored-by: oldmud0 --- .gitlab-ci.yml | 22 ++++---- Attorney_Online.pro | 32 +++--------- include/aoapplication.h | 18 ++++--- include/aoblipplayer.h | 8 --- include/aomusicplayer.h | 8 --- include/aosfxplayer.h | 8 --- include/courtroom.h | 2 - src/aoapplication.cpp | 61 +++++++++++++++++++++++ src/aoblipplayer.cpp | 57 +++------------------ src/aomusicplayer.cpp | 69 ++++--------------------- src/aooptionsdialog.cpp | 11 +--- src/aosfxplayer.cpp | 108 +++------------------------------------- src/courtroom.cpp | 62 +---------------------- src/lobby.cpp | 15 +++--- 14 files changed, 122 insertions(+), 359 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e0b0886..72f7903 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,15 +34,15 @@ build linux x86_64: - clang --version # Extract BASS - #- mkdir bass - #- cd bass - #- curl http://www.un4seen.com/files/bass24-linux.zip -o bass.zip - #- unzip bass.zip - #- cp x64/libbass.so ../lib - #- curl http://www.un4seen.com/files/bassopus24-linux.zip -o bassopus.zip - #- unzip bassopus.zip - #- cp x64/libbassopus.so ../lib - #- cd .. + - mkdir bass + - cd bass + - curl http://www.un4seen.com/files/bass24-linux.zip -o bass.zip + - unzip bass.zip + - cp x64/libbass.so ../lib + - curl http://www.un4seen.com/files/bassopus24-linux.zip -o bassopus.zip + - unzip bassopus.zip + - cp x64/libbassopus.so ../lib + - cd .. # Extract Discord RPC - mkdir discord-rpc @@ -61,7 +61,7 @@ build linux x86_64: - cd .. # Build - - qmake -spec linux-clang "DEFINES += DISCORD QTAUDIO" + - qmake -spec linux-clang "DEFINES += DISCORD" - make -j4 # Post-processing @@ -109,7 +109,7 @@ build windows i686: - ls lib # Build - - /opt/mxe/usr/${TARGET_SPEC}/qt5/bin/qmake "DEFINES += DISCORD BASSAUDIO" + - /opt/mxe/usr/${TARGET_SPEC}/qt5/bin/qmake "DEFINES += DISCORD" - make -j4 # Post-processing diff --git a/Attorney_Online.pro b/Attorney_Online.pro index 28a1e7c..a1f01d4 100644 --- a/Attorney_Online.pro +++ b/Attorney_Online.pro @@ -22,35 +22,15 @@ contains(DEFINES, DISCORD) { LIBS += -ldiscord-rpc } -# Uncomment to enable the BASS audio engine -# (Recommended for Windows) -# DEFINES += BASSAUDIO - -contains(DEFINES, BASSAUDIO) { - LIBS += -lbass - LIBS += -lbassopus -} - -# Uncomment to enable the Qt audio engine -# (Recommended for non-Windows platforms) -# DEFINES += QTAUDIO - -contains(DEFINES, QTAUDIO) { - QT += multimedia -} - -AUDIO_DEFINES = $$find(DEFINES, BASSAUDIO) $$find(DEFINES, QTAUDIO) -count(AUDIO_DEFINES, 0) { - warning("No audio system selected. Your build will not have audio.") -} - -count(AUDIO_DEFINES, 2) { - error("More than one audio system selected.") -} +# As of 2.8.5, BASS and BASSOPUS are required for all platforms. Qt Multimedia +# is no longer an option due to outdated code and lack of versatility. +# Download at un4seen.com and place the DLLs in the "lib" and "bin" folders. +DEFINES += BASSAUDIO +LIBS += -lbass +LIBS += -lbassopus macx:LIBS += -framework CoreFoundation -framework Foundation -framework CoreServices - CONFIG += c++14 RESOURCES += resources.qrc diff --git a/include/aoapplication.h b/include/aoapplication.h index b44c8a8..f0e0545 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -5,6 +5,9 @@ #include "datatypes.h" #include "discord_rich_presence.h" +#include "bass.h" +#include "bassopus.h" + #include #include #include @@ -23,9 +26,6 @@ #include #include #include -#ifdef QTAUDIO -#include -#endif class NetworkManager; class Lobby; @@ -202,7 +202,8 @@ public: // Returns the value of whether custom chatboxes should be a thing. // from the config.ini. - // I am increasingly maddened by the lack of dynamic auto-generation system for settings. + // I am increasingly maddened by the lack of dynamic auto-generation system + // for settings. bool is_customchat_enabled(); // Returns the value of the maximum amount of lines the IC chatlog @@ -227,9 +228,6 @@ public: // Returns the audio device used for the client. QString get_audio_output_device(); -#ifdef QTAUDIO - QAudioDeviceInfo QtAudioDevice; -#endif // Returns whether the user would like to have custom shownames on by default. bool get_showname_enabled_by_default(); @@ -442,6 +440,12 @@ public: // The file name of the log file in base/logs. QString log_filename; + void initBASS(); + static void load_bass_opus_plugin(); + static void CALLBACK BASSreset(HSTREAM handle, DWORD channel, DWORD data, + void *user); + static void doBASSreset(); + private: const int RELEASE = 2; const int MAJOR_VERSION = 8; diff --git a/include/aoblipplayer.h b/include/aoblipplayer.h index 5a10471..4d3b5f1 100644 --- a/include/aoblipplayer.h +++ b/include/aoblipplayer.h @@ -1,12 +1,8 @@ #ifndef AOBLIPPLAYER_H #define AOBLIPPLAYER_H -#if defined(BASSAUDIO) #include "bass.h" #include "bassopus.h" -#elif defined(QTAUDIO) -#include -#endif #include "aoapplication.h" @@ -35,11 +31,7 @@ private: void set_volume_internal(qreal p_volume); -#if defined(BASSAUDIO) HSTREAM m_stream_list[5]; -#elif defined(QTAUDIO) - QSoundEffect m_blips; -#endif }; #endif // AOBLIPPLAYER_H diff --git a/include/aomusicplayer.h b/include/aomusicplayer.h index 82751b6..36031f1 100644 --- a/include/aomusicplayer.h +++ b/include/aomusicplayer.h @@ -2,12 +2,8 @@ #define AOMUSICPLAYER_H #include "file_functions.h" -#if defined(BASSAUDIO) #include "bass.h" #include "bassopus.h" -#elif defined(QTAUDIO) -#include -#endif #include "aoapplication.h" @@ -44,12 +40,8 @@ private: // Channel 1 = ambience // Channel 2 = extra // Channel 3 = extra - #if defined(BASSAUDIO) HSTREAM m_stream_list[4]; HSYNC loop_sync[4]; - #elif defined(QTAUDIO) - QMediaPlayer m_stream_list[4]; - #endif }; #endif // AOMUSICPLAYER_H diff --git a/include/aosfxplayer.h b/include/aosfxplayer.h index 9918871..0a5fffa 100644 --- a/include/aosfxplayer.h +++ b/include/aosfxplayer.h @@ -1,12 +1,8 @@ #ifndef AOSFXPLAYER_H #define AOSFXPLAYER_H -#if defined(BASSAUDIO) #include "bass.h" #include "bassopus.h" -#elif defined(QTAUDIO) -#include -#endif #include "aoapplication.h" @@ -37,11 +33,7 @@ private: const int m_channelmax = 5; -#if defined(BASSAUDIO) HSTREAM m_stream_list[5]; -#elif defined(QTAUDIO) - QSoundEffect m_stream_list[5]; -#endif }; #endif // AOSFXPLAYER_H diff --git a/include/courtroom.h b/include/courtroom.h index 979650a..5b5ff6c 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -828,8 +828,6 @@ private slots: void on_casing_clicked(); void ping_server(); - - void load_bass_opus_plugin(); }; #endif // COURTROOM_H diff --git a/src/aoapplication.cpp b/src/aoapplication.cpp index e1e9e7f..fa58ab8 100644 --- a/src/aoapplication.cpp +++ b/src/aoapplication.cpp @@ -177,3 +177,64 @@ void AOApplication::call_announce_menu(Courtroom *court) AOCaseAnnouncerDialog announcer(nullptr, this, court); announcer.exec(); } + +// Callback for when BASS device is lost +void CALLBACK AOApplication::BASSreset(HSTREAM handle, DWORD channel, + DWORD data, void *user) +{ + doBASSreset(); +} + +void AOApplication::doBASSreset() +{ + BASS_Free(); + BASS_Init(-1, 48000, BASS_DEVICE_LATENCY, nullptr, nullptr); + load_bass_opus_plugin(); +} + +void AOApplication::initBASS() +{ + BASS_Free(); + // Change the default audio output device to be the one the user has given + // in his config.ini file for now. + unsigned int a = 0; + BASS_DEVICEINFO info; + + if (get_audio_output_device() == "default") { + BASS_Init(-1, 48000, BASS_DEVICE_LATENCY, nullptr, nullptr); + load_bass_opus_plugin(); + } + else { + for (a = 0; BASS_GetDeviceInfo(a, &info); a++) { + if (get_audio_output_device() == info.name) { + BASS_SetDevice(a); + BASS_Init(static_cast(a), 48000, BASS_DEVICE_LATENCY, nullptr, + nullptr); + load_bass_opus_plugin(); + qDebug() << info.name << "was set as the default audio output device."; + return; + } + } + BASS_Init(-1, 48000, BASS_DEVICE_LATENCY, nullptr, nullptr); + load_bass_opus_plugin(); + } +} + +#if (defined(_WIN32) || defined(_WIN64)) +void AOApplication::load_bass_opus_plugin() +{ + BASS_PluginLoad("bassopus.dll", 0); +} +#elif (defined(LINUX) || defined(__linux__)) +void AOApplication::load_bass_opus_plugin() +{ + BASS_PluginLoad("libbassopus.so", 0); +} +#elif defined __APPLE__ +void AOApplication::load_bass_opus_plugin() +{ + BASS_PluginLoad("libbassopus.dylib", 0); +} +#else +#error This operating system is unsupported for BASS plugins. +#endif diff --git a/src/aoblipplayer.cpp b/src/aoblipplayer.cpp index 57b2d27..5b4d625 100644 --- a/src/aoblipplayer.cpp +++ b/src/aoblipplayer.cpp @@ -1,6 +1,5 @@ #include "aoblipplayer.h" -#if defined(BASSAUDIO) // Using bass.dll for the blips AOBlipPlayer::AOBlipPlayer(QWidget *parent, AOApplication *p_ao_app) { m_parent = parent; @@ -37,8 +36,14 @@ void AOBlipPlayer::blip_tick() m_cycle = 0; HSTREAM f_stream = m_stream_list[f_cycle]; - if (ao_app->get_audio_output_device() != "default") + + BASS_ChannelSetDevice(f_stream, BASS_GetDevice()); + int f_bass_error = BASS_ErrorGetCode(); + if (f_bass_error == BASS_ERROR_DEVICE) { + ao_app->doBASSreset(); BASS_ChannelSetDevice(f_stream, BASS_GetDevice()); + } + BASS_ChannelPlay(f_stream, false); } @@ -56,51 +61,3 @@ void AOBlipPlayer::set_volume_internal(qreal p_value) BASS_ChannelSetAttribute(m_stream_list[n_stream], BASS_ATTRIB_VOL, volume); } } -#elif defined(QTAUDIO) // Using Qt's QSoundEffect class -AOBlipPlayer::AOBlipPlayer(QWidget *parent, AOApplication *p_ao_app) -{ - m_parent = parent; - ao_app = p_ao_app; -} - -void AOBlipPlayer::set_blips(QString p_sfx) -{ - QString f_path = ao_app->get_sounds_path(p_sfx); - - for (int n_stream = 0; n_stream < 5; ++n_stream) { - m_blips.setSource(QUrl::fromLocalFile(f_path)); - } - - set_volume(m_volume); -} - -void AOBlipPlayer::blip_tick() -{ - int f_cycle = m_cycle++; - - if (m_cycle == 5) - m_cycle = 0; - - m_blips.play(); -} - -void AOBlipPlayer::set_volume(int p_value) -{ - m_volume = p_value; - m_blips.setVolume(m_volume); -} -#else // No audio -AOBlipPlayer::AOBlipPlayer(QWidget *parent, AOApplication *p_ao_app) -{ - m_parent = parent; - ao_app = p_ao_app; -} - -void AOBlipPlayer::set_blips(QString p_sfx) {} - -void AOBlipPlayer::blip_tick() {} - -void AOBlipPlayer::set_volume(int p_value) {} - -void AOBlipPlayer::set_volume_internal(qreal p_value) {} -#endif diff --git a/src/aomusicplayer.cpp b/src/aomusicplayer.cpp index 249e01e..6c61b9a 100644 --- a/src/aomusicplayer.cpp +++ b/src/aomusicplayer.cpp @@ -1,14 +1,11 @@ #include "aomusicplayer.h" - AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app) { m_parent = parent; ao_app = p_ao_app; } -#ifdef BASSAUDIO - AOMusicPlayer::~AOMusicPlayer() { for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) { @@ -111,8 +108,11 @@ void AOMusicPlayer::play(QString p_song, int channel, bool loop, else this->set_volume(m_volume[channel], channel); + BASS_ChannelSetSync(m_stream_list[channel], BASS_SYNC_DEV_FAIL, 0, + ao_app->BASSreset, 0); + this->set_looping(loop, channel); // Have to do this here due to any - // crossfading-related changes, etc. + // crossfading-related changes, etc. } void AOMusicPlayer::stop(int channel) @@ -164,62 +164,13 @@ void AOMusicPlayer::set_looping(bool toggle, int channel) } if (loop_start[channel] > 0) { if (loop_end[channel] == 0) - loop_end[channel] = BASS_ChannelGetLength(m_stream_list[channel], BASS_POS_BYTE); - if (loop_end[channel] > 0) // Don't loop zero length songs even if we're asked to + loop_end[channel] = + BASS_ChannelGetLength(m_stream_list[channel], BASS_POS_BYTE); + if (loop_end[channel] > + 0) // Don't loop zero length songs even if we're asked to loop_sync[channel] = BASS_ChannelSetSync( - m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME, loop_end[channel], - loopProc, &loop_start[channel]); + m_stream_list[channel], BASS_SYNC_POS | BASS_SYNC_MIXTIME, + loop_end[channel], loopProc, &loop_start[channel]); } } } -#elif defined(QTAUDIO) - -AOMusicPlayer::~AOMusicPlayer() { - for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) { - m_stream_list[n_stream].stop(); - } -} - -void AOMusicPlayer::play(QString p_song, int channel, bool loop, - int effect_flags) -{ - channel = channel % m_channelmax; - if (channel < 0) // wtf? - return; - QString f_path = ao_app->get_music_path(p_song); - - m_stream_list[channel].stop(); - - m_stream_list[channel].setMedia(QUrl::fromLocalFile(f_path)); - - this->set_volume(m_volume[channel], channel); - - m_stream_list[channel].play(); -} - -void AOMusicPlayer::stop(int channel) -{ - m_stream_list[channel].stop(); -} - -void AOMusicPlayer::set_volume(int p_value, int channel) -{ - m_volume[channel] = p_value; - m_stream_list[channel].setVolume(m_volume[channel]); -} - -#else - -AOMusicPlayer::~AOMusicPlayer() {} - -void AOMusicPlayer::play(QString p_song, int channel, bool loop, - int effect_flags) {} - -void AOMusicPlayer::stop(int channel) {} - -void AOMusicPlayer::set_volume(int p_value, int channel) {} - -void loopProc(int handle, int channel, int data, int *user) {} - -void AOMusicPlayer::set_looping(bool toggle, int channel) {} -#endif diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp index 4e6aca6..6fc4d03 100644 --- a/src/aooptionsdialog.cpp +++ b/src/aooptionsdialog.cpp @@ -445,7 +445,6 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app) ui_audio_device_combobox->addItem("default"); //TODO translate this without breaking the default audio device } -#ifdef BASSAUDIO BASS_DEVICEINFO info; for (a = 0; BASS_GetDeviceInfo(a, &info); a++) { ui_audio_device_combobox->addItem(info.name); @@ -453,15 +452,6 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app) ui_audio_device_combobox->setCurrentIndex( ui_audio_device_combobox->count() - 1); } -#elif defined QTAUDIO - foreach (const QAudioDeviceInfo &deviceInfo, - QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) { - ui_audio_device_combobox->addItem(deviceInfo.deviceName()); - if (p_ao_app->get_audio_output_device() == deviceInfo.deviceName()) - ui_audio_device_combobox->setCurrentIndex( - ui_audio_device_combobox->count() - 1); - } -#endif ui_audio_layout->setWidget(row, QFormLayout::FieldRole, ui_audio_device_combobox); @@ -816,6 +806,7 @@ void AOOptionsDialog::save_pressed() configini->setValue("casing_can_host_cases", ui_casing_cm_cases_textbox->text()); + ao_app->initBASS(); callwordsini->close(); done(0); } diff --git a/src/aosfxplayer.cpp b/src/aosfxplayer.cpp index 127bda6..8c4f3c8 100644 --- a/src/aosfxplayer.cpp +++ b/src/aosfxplayer.cpp @@ -1,14 +1,12 @@ #include "aosfxplayer.h" #include "file_functions.h" - AOSfxPlayer::AOSfxPlayer(QWidget *parent, AOApplication *p_ao_app) { m_parent = parent; ao_app = p_ao_app; } -#if defined(BASSAUDIO) // Using bass.dll for sfx void AOSfxPlayer::clear() { for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) { @@ -68,9 +66,16 @@ void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout, set_volume_internal(m_volume); - if (ao_app->get_audio_output_device() != "default") + BASS_ChannelSetDevice(m_stream_list[m_channel], BASS_GetDevice()); + int f_bass_error = BASS_ErrorGetCode(); + if (f_bass_error == BASS_ERROR_DEVICE) { + ao_app->doBASSreset(); BASS_ChannelSetDevice(m_stream_list[m_channel], BASS_GetDevice()); + } + BASS_ChannelPlay(m_stream_list[m_channel], false); + BASS_ChannelSetSync(m_stream_list[channel], BASS_SYNC_DEV_FAIL, 0, + ao_app->BASSreset, 0); } void AOSfxPlayer::stop(int channel) @@ -112,100 +117,3 @@ void AOSfxPlayer::set_looping(bool toggle, int channel) BASS_SAMPLE_LOOP); // set the LOOP flag } } -#elif defined(QTAUDIO) // Using Qt's QSoundEffect class - -void AOSfxPlayer::clear() -{ - for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) { - m_stream_list[n_stream].stop(); - } - set_volume_internal(m_volume); -} - -void AOSfxPlayer::loop_clear() -{ - for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) { - m_stream_list[n_stream].stop(); - } - set_volume_internal(m_volume); -} - -void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout, - int channel) -{ - m_stream_list[channel].stop(); - - QString misc_path = ""; - QString char_path = ""; - QString sound_path = ao_app->get_sounds_path(p_sfx); - - if (shout != "") - misc_path = ao_app->get_base_path() + "misc/" + shout + "/" + p_sfx; - if (p_char != "") - char_path = ao_app->get_character_path(p_char, p_sfx); - - QString f_path; - - if (file_exists(char_path)) - f_path = char_path; - else if (file_exists(misc_path)) - f_path = misc_path; - else - f_path = sound_path; - - if (file_exists(f_path)) // if its missing, it will glitch out - { - m_stream_list[channel].setSource(QUrl::fromLocalFile(f_path)); - - set_volume_internal(m_volume); - - m_stream_list[channel].play(); - } -} - -void AOSfxPlayer::stop(int channel) -{ - if (channel == -1) { - channel = m_channel; - } - m_stream_list[channel].stop(); -} - -void AOSfxPlayer::set_volume(qreal p_value) -{ - m_volume = p_value / 100; - set_volume_internal(m_volume); -} - -void AOSfxPlayer::set_volume_internal(qreal p_value) -{ - float volume = static_cast(p_value); - for (int n_stream = 0; n_stream < m_channelmax; ++n_stream) { - m_stream_list[n_stream].setVolume(volume); - } -} - -void AOSfxPlayer::set_looping(bool toggle, int channel) -{ - if (channel == -1) { - channel = m_channel; - } - m_looping = toggle; - // TODO -} -#else -void AOSfxPlayer::clear() {} - -void AOSfxPlayer::loop_clear() {} - -void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout, - int channel) {} - -void AOSfxPlayer::stop(int channel) {} - -void AOSfxPlayer::set_volume(qreal p_value) {} - -void AOSfxPlayer::set_volume_internal(qreal p_value) {} - -void AOSfxPlayer::set_looping(bool toggle, int channel) {} -#endif diff --git a/src/courtroom.cpp b/src/courtroom.cpp index fe10e13..2484bcb 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3,42 +3,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() { ao_app = p_ao_app; -#ifdef BASSAUDIO - // Change the default audio output device to be the one the user has given - // in his config.ini file for now. - unsigned int a = 0; - BASS_DEVICEINFO info; - - if (ao_app->get_audio_output_device() == "default") { - BASS_Init(-1, 48000, BASS_DEVICE_LATENCY, nullptr, nullptr); - load_bass_opus_plugin(); - } - else { - for (a = 0; BASS_GetDeviceInfo(a, &info); a++) { - if (ao_app->get_audio_output_device() == info.name) { - BASS_SetDevice(a); - BASS_Init(static_cast(a), 48000, BASS_DEVICE_LATENCY, nullptr, - nullptr); - load_bass_opus_plugin(); - qDebug() << info.name << "was set as the default audio output device."; - break; - } - } - } -#elif defined QTAUDIO - - if (ao_app->get_audio_output_device() != "default") { - foreach (const QAudioDeviceInfo &deviceInfo, - QAudioDeviceInfo::availableDevices(QAudio::AudioOutput)) { - if (ao_app->get_audio_output_device() == deviceInfo.deviceName()) { - ao_app->QtAudioDevice = deviceInfo; - qDebug() << deviceInfo.deviceName() - << "was set as the default audio output device."; - break; - } - } - } -#endif + ao_app->initBASS(); qsrand(static_cast(QDateTime::currentMSecsSinceEpoch() / 1000)); @@ -4750,28 +4715,3 @@ Courtroom::~Courtroom() delete objection_player; delete blip_player; } - -#if (defined(_WIN32) || defined(_WIN64)) -void Courtroom::load_bass_opus_plugin() -{ -#ifdef BASSAUDIO - BASS_PluginLoad("bassopus.dll", 0); -#endif -} -#elif (defined(LINUX) || defined(__linux__)) -void Courtroom::load_bass_opus_plugin() -{ -#ifdef BASSAUDIO - BASS_PluginLoad("libbassopus.so", 0); -#endif -} -#elif defined __APPLE__ -void Courtroom::load_bass_opus_plugin() -{ -#ifdef BASSAUDIO - BASS_PluginLoad("libbassopus.dylib", 0); -#endif -} -#else -#error This operating system is unsupported for bass plugins. -#endif diff --git a/src/lobby.cpp b/src/lobby.cpp index 3aa488a..093b0f7 100644 --- a/src/lobby.cpp +++ b/src/lobby.cpp @@ -5,6 +5,8 @@ #include "debug_functions.h" #include "networkmanager.h" +#include + Lobby::Lobby(AOApplication *p_ao_app) : QMainWindow() { ao_app = p_ao_app; @@ -353,13 +355,7 @@ void Lobby::on_connect_released() void Lobby::on_about_clicked() { -#ifdef BASSAUDIO - const QString audio = "BASS"; -#elif defined(QTAUDIO) - const QString audio = "Qt Multimedia"; -#else - const QString audio = "null"; -#endif + const bool hasApng = QImageReader::supportedImageFormats().contains("APNG"); QString msg = tr("

Attorney Online %1

" @@ -389,11 +385,12 @@ void Lobby::on_about_clicked() "is copyright (c) 2016-2020 Attorney Online developers. Open-source " "licenses apply. All other assets are the property of their " "respective owners." - "

Running on Qt version %2 with the %3 audio engine." + "

Running on Qt version %2 with the BASS audio engine.
" + "APNG plugin loaded: %3" "

Built on %4") .arg(ao_app->get_version_string()) .arg(QLatin1String(QT_VERSION_STR)) - .arg(audio) + .arg(hasApng ? tr("Yes") : tr("No")) .arg(QLatin1String(__DATE__)); QMessageBox::about(this, tr("About"), msg); } From 7cd0fa0c6e9875c0f199c6d7448e0a031dd8e631 Mon Sep 17 00:00:00 2001 From: scatterflower Date: Wed, 19 Aug 2020 22:56:36 -0500 Subject: [PATCH 41/46] version bump to 2.8.5 --- Attorney_Online.pro | 2 +- include/aoapplication.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Attorney_Online.pro b/Attorney_Online.pro index a1f01d4..d2c2062 100644 --- a/Attorney_Online.pro +++ b/Attorney_Online.pro @@ -3,7 +3,7 @@ QT += core gui widgets network TARGET = Attorney_Online TEMPLATE = app -VERSION = 2.8.4.0 +VERSION = 2.8.5.0 INCLUDEPATH += $$PWD/include DESTDIR = $$PWD/bin diff --git a/include/aoapplication.h b/include/aoapplication.h index f0e0545..60d945e 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -449,7 +449,7 @@ public: private: const int RELEASE = 2; const int MAJOR_VERSION = 8; - const int MINOR_VERSION = 4; + const int MINOR_VERSION = 5; QString current_theme = "default"; From a7a33eb5cfb34d7851f545f204618dc54737476f Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Thu, 20 Aug 2020 15:02:58 -0500 Subject: [PATCH 42/46] Update themes submodule --- base/themes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/themes b/base/themes index 8ad1c0a..15b0cc4 160000 --- a/base/themes +++ b/base/themes @@ -1 +1 @@ -Subproject commit 8ad1c0af3f5b0cf0657f43389cca87b24dba61ba +Subproject commit 15b0cc4aa1241a9b740fb1ce8a61c7f699a80de5 From accca95c719595d4008e776e25ed449aa2222079 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Thu, 20 Aug 2020 15:03:30 -0500 Subject: [PATCH 43/46] Rename serverlist.txt -> serverlist.sample.txt We don't want to accidentally overwrite players' server lists when performing trivial updates. (The launcher should remove the 'sample' qualifier when it is performing a full install, though that is not implemented right now and the move operation is sadly broken.) --- base/{serverlist.txt => serverlist.sample.txt} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename base/{serverlist.txt => serverlist.sample.txt} (100%) diff --git a/base/serverlist.txt b/base/serverlist.sample.txt similarity index 100% rename from base/serverlist.txt rename to base/serverlist.sample.txt From 385f4762699a5c4b559e92cb7b9db31d64d0f884 Mon Sep 17 00:00:00 2001 From: likeawindrammer <31085911+likeawindrammer@users.noreply.github.com> Date: Fri, 21 Aug 2020 00:03:00 -0600 Subject: [PATCH 44/46] gitignore: Ignore base/serverlist.txt --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index fedae9d..ca7eb58 100644 --- a/.gitignore +++ b/.gitignore @@ -22,6 +22,7 @@ base/characters base/sounds base/callwords.ini base/config.ini +base/serverlist.txt .qmake.stash From 894abc04db87f416757557adc8f9d4aa34abc8ab Mon Sep 17 00:00:00 2001 From: likeawindrammer <31085911+likeawindrammer@users.noreply.github.com> Date: Fri, 21 Aug 2020 04:12:40 -0600 Subject: [PATCH 45/46] Translations: Update Spanish --- resource/translations/ao_es.qm | Bin 47385 -> 49363 bytes resource/translations/ao_es.ts | 501 +++++++++++++++++++-------------- 2 files changed, 282 insertions(+), 219 deletions(-) diff --git a/resource/translations/ao_es.qm b/resource/translations/ao_es.qm index 7b238e797fc04142fdb00d5a06802707b3f83aa6..7b5e6f252bb324eaa69ccf2eb98929aa33b7bf3c 100644 GIT binary patch delta 3850 zcmah~2~<;O7XGrYB%^|;EI!<5Ee5O`0-_)aS`5e{YTcgX5n{7I5*9ZiE=959_FRxs zRBCNyMr|8Zw3fCy$1~MxtJra=Rk76`9k*7;YFp{tmniK_&zw0N^8fFD_rLdk-~H}= zn|~0uR!Tex&8BY0?$&KM5fS>)tZg5DoeU^r09gjGZz+&60vNv^NK*q{RY2Y{z?}e0 zIR`9R2+TYJ>^}f$D*$sNWNAYHyVbw$n+n;aF@WPAkj*~`4DJl2xCLk!f-p@4-K)SL zPaQc9sYB|}9s{~H zV(aikVA2V^RZj*Og#G*Jx$*>#UbqBAoyV!?+kvpNco0z!tbZs{I@SWqWFqB}TDq?h zXqNG--vXndsKBOF&kR=z)NA#uwrM zo&p=YizAj0#X-Zx{SVxvKoAdE6bNj8QJm&z0ZKm>zr29#=T8u`_l)S3F-q_1+;~@ku4{Mi242kao)S1M%JgyQvg~;-g;@Q-PPo*IOHaiC4ux zdg(c4f+R6w5NTtmBwa#|r|*ztl#-u$ngkrM2BU78t88c|uLi!KbN z1X`qvpG=|m8PZqx7yyk~T6K{a&}T^3Dc>hCekNVV)l$F*QeHuUf?B0D;|>wC-J~^J zQ^}vlw|bDZLs};%glQ9`pU3Nf8l&{|T|ypmL3-sOsoA|)`p;-J5WPqG(0vIAy(pp+E!QmQC8T0cf5qVSnJ zN$#qt0M_-9FS$s_$DfnGT78~W|5(0qZw{3#UHpcl{UaOe)RTDWZR?Hk#3{+iK%xNV@)+R+oXL`S4 zmty78UBt+A1s`4yEZ(WuHQ7$3NL923QX&bzC@zj@0eVUmS9;L=$Um=m9RCx|lLJaa zIh8KUpiC&Gl6B8jj?$CeYNyiaNoc1baznYel>(~{D_8ai2kHxzn=|QLzem~l&9^|& zZKbzgJ<#`@vU$gNpk$WvcuWN_b)NF#zbNoa@yaWTL^@xql4f)QLR0%?fvmU8N+>N6WrK-lPYo{(RPSxPAAb6ju zJ(5ZqSgDRkp!;bL)qU@;0y-JgF@x^_e4c;Zf5D^9d_oQ-;p+KgvZ(f7tCv05Nr+!p z*Quxtw=wFSwOfJBx76=8?FG^m>O-%&iLpfW*=!0BeN+9-)j*&)QhhCz0uQ{beiSSv z(S>OOBWPTw-_-OsRR9~iYX%*m1ZEpGH6!eR>A2=?^LJ$DxvptEB_?qk)9m?BM1i6C zY4Vo)0Mxeh%^QeNJXML#+X(xwc&S_)IF9E} zugxm&0`8Lj6Bdhf}Yto=Ylvwp-; z|GFg4zwS3`KXlduTZ*+;cG3k$AMMr4xrE%KeLQ0~P@Nwjok?PPB{M*8qyVwk0@A|< z5`ct&$u;!6?odE&rtod34LGxbCTZ=JfV00)z+RgIuCJa$0Ivt!dVB;Pm~#W31oR@6 znsr@zwgW?>bWwTKuYiB`-qyuP-lEa`g)YXH2&4w<;%pQkyFr(-n8Xx4LRWGABqb22 ztNPAFBG&0v+%wYGv0k@jO+A$$-oJX2b?>Y%BL*^b@4Z0w$!B!$FS|qi->*&A^cqpG z=%V{L{(I{CLfsc{tOA^^x{F_vVZ=<`_p!8=t98GAL~0fv(u>6rz?wJoo#JNDM`XM{ zdIj0nU(=@w-x4NTpVmB;M3|w^Jx`*YF<(FHD%lNA))%a&gr=tG?V}0M(uMk(&!+Yv zYX7R=)06tul%@CXYNWO}qdz*5s4MX5j}N;9^ggUVtv3P#e$uyE5`p2z^*5?pXg;X) zcXMgdRc+NjsB9xuFVH`Ur@*?Osim41^TV3@c)Kduz@+Dp1rBCd;DQ@YIKY5K3GE%Q zp^a7x@@XHZ6lj;zf9IqUx5LJ|E%{8k!))f+@Gx&#=+AOdBOe_T#;@ru=fn4Qi~PMy z7ddrN7={9skb5UgzTY<3`I7Oy`G&gCJSzn;la-+(Q0lk>Cclu&e}yweF|5_fSRG~; zQ)Z#vY>r`{WkGM|GG$JS+s)Y-i=A;7a!j<(w7_9C@dIB9^*VdsP>OauOV7i>N~t*i zfLp+6C&V26n&^ESS(VV9rPbz3IN!H7`Jf2QaCBZow;10Y2D!+=XnJCw`VoK&)rhg=micZ=R;{{ZJakL zYJo^ADnvG=Bc$QtD|-j=o+u^1A*%C8I|1NON}+{RSV~r4pQDm;K7e*Q6)NLDXDM01 zGKx;;3f}n4>Y%Vc-g*Yt3YI^$G+1TDZGy+q(|f7G1OEdoof^o~XkXn0TK!}RViV{U z$Z_$VOkE}j^%rOs^7Ttmpj{}5&G#nqHv-8b&SxtW%0-Cg&`IR)INi*59ni<);)+-& z>lV~gW^ot#C?hgmteIo-9X5;I%sBjVv2*2a#%i&XstVkkvx8g%lUGQhDzQH+kj2fI zEUqFeJJ-d~o^>&iLJ{Jar+y<13hEGjQbtCRo4*yJ_qGfeAs-lu2|n7*l%_zq|JN`0 z-}*{J-Ne{fr`clXCx-Qi?+4@4;t51_Q2amdYlZuEu8eT-nPDMg4Ns%~Kh6Gk9y-BK zhwQv%u#0{GBw8%r|3SdLgxv@utbT&7m4kda(~JsH8EMN-Q=(_+5E@bgS^eo+#p2`#?Z}Deo@s( zUcJ7X*S5ScG?aR&ki0O|uL89~=L$6Y`j+ww?AhVAYaxlV$jP~g9nQpXr4|!s&*x7q z?;=)R@t)njP&G1{aA(t>0SP|*iO8fZOMD*#A?GA|HX@aF0vacs`{#pDq`nx$PuV>{ zbj@3}`!CX{@E+OsoT#&uvbf!mx?~FH;-i|n^X1Lk{tYu&Dii|M ziajbKLBfeT%Bl_S;)278OLP=xqLC0{q8^uV*SO+54*5~%)vND)Z@uqUhef*mnZ)dO zICb#($CX=tbQyLs>AMrZOaTNu&)JTih!(8Adb#flz{C3kn9Xu@OU7t zyH7S8fNWL}kRA%z@}q#)B5;ycU`G&~R4zc{QH-r5e~x-g-+C6PO-Hc#=tsa#h7j*u zAjF2S?J2Y3aZ54n+J)`PKqy%J)5IO@egfaag1)?V~6N<=w)?_AQ$WXxN zEt6ID2e8)4m@Fnr^e(e_JSA2b!z_Lu15}!sO~q7rU3Dz;y#_I?KH1tuQu#c^}tAEqp1_SSf+&=@OUK)MC4v689tbDPW=`IJ*_dz9dOl zLH0`$tp8&i%pQ{UZUun?7c_x6)U?5)jPU-?Ml^7q>^S+>=%yr=AVjS_}+Y$3{310{BdJ)z9N7uoqkSA&$=H zuwOS)`l>W`Z6}o{hO?Ww0|bBocC)bpm^hQQDl#asrEGb~aq8b9w!C^e`E%)$VT0I8 zITbefTlTWA05i%G+3r^a(X37EgV9Q=OkiIv=^_ZOkU7>6I*58VD#?%JL&~0Lcv5j&XbT46J&r$mk$P^G7NQ29QDF2}Q}8dg{nRh1IzVSbj)RA8P_a zTNE93l*pIyicbGlz^P2pJv1Dc6QX$I`xfAia9(*dvahN*zhyM4!GCfABH67g{JWh&l$%;5^r*=fH0<0V?sUHlKtM}T=P{Oh9vvB^IET{?lx zAy(<)M;E3{Q;v9E3iS6qO?k?Q4|HGZtc+^8M$6l+Tpl!&c5#TZ=)+zr zOjK6#v|Sb6%DolUz~=YLrsftPD8{TjzF`S1Z-eruNCJmPi1PPac64Ef^7eEJJj!4B z+JPl-IjQVicwm}N<(^sqY;;qNZKFgIT2~UhWOdXwNI`v_Q}R# z^@*G+pxmPF-b?li%GI}iji!PhtKTFx&}dfYYS_61mejKv(O@FJovI0Q`hqfV(!`dN zUUE@W5kZ8$K+s&*b zo2qC=C4I8CLfG#?c7CqHfucu%t5Im)KrL1b6i)d*B?9Uc{{3w!u<$pb^B1xk{!n=8 zLvrz8;p0gHspPmQk+=Zs>&5=ML?ZlnarF99+W&1Y#p%7w?|fVgK1@V2=&2ZegFqSc zKuo$thF;a;{C`j)kMojXiCBKol{%yq8;AF<-x<+XzmM$3i0zZ8Q%RqS7ryKQ zJ_#4EiUzx>+T>vjwa$-)g->K4ET*uyg~fnOM!)Vv@`p)wotCf z&gSX#PHyubagVc&9-YG24vx{wZ7(P4Mcd?1qlT%n?ukibOxAvmj#k&oq1NgIrOi9m z$nbhhMhbFZv|1KA@LDWFGHJ=yCZ)aYO59cZA?^r-5xH1K2PS%(M^6svM%&@++q_Mh zA7#(a!c;oVLW(VM Cargando - + Loading evidence: %1/%2 Cargando evidencia: %1/%2 - - + + Loading music: %1/%2 Cargando música: %1/%2 - - + + Loading chars: %1/%2 Cargando personajes: %1/%2 - + You have been kicked from the server. Reason: %1 Has sido expulsado del servidor. Razón: %1 - + You have been banned from the server. Reason: %1 Has sido bloqueado de este servidor. Razón: %1 - + You are banned on this server. Reason: %1 Has sido bloqueado en este servidor. @@ -186,42 +186,72 @@ Razón: La cantidad de mensajes que mantendrá el historial del chat IC antes de eliminar mensajes más antiguos. 0 significa 'infinito'. - + + Log newline: + Nueva línea en log: + + + + If ticked, new messages will appear separated, with the message coming on the next line after the name. When unticked, it displays it as 'name: message'. + Si es marcado, los mensajes nuevos aparecerán separados, y el mensaje aparecerá en la siguiente línea después del nombre. Cuando está desmarcado, lo muestra como 'nombre: mensaje'. + + + + Log margin: + Margen en log: + + + + The distance in pixels between each entry in the IC log. Default: 0. + La distancia en píxeles entre cada entrada en el registro de IC. Predeterminado: 0. + + + + Log timestamp: + Marca de tiempo en log: + + + + If ticked, log will contain a timestamp in UTC before the name. + Si está marcado, el registro contendrá una marca de tiempo en UTC antes del nombre. + + + Default username: Usuario predeterminado: - + Your OOC name will be automatically set to this value when you join a server. Su nombre OOC se establecerá automáticamente a este cuando se una a un servidor. - + Custom shownames: Mostrar nombres: - + Gives the default value for the in-game 'Custom shownames' tickbox, which in turn determines whether the client should display custom in-character names. Activa la casilla 'Mostrar nombres' de forma predeterminada en el juego, que a su vez determina si el cliente debe mostrar nombres personalizados en los personajes. - + Backup MS: Master SV de respaldo: - + If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address. Si la lista de servidores predeterminada falla, el juego probará la dirección proporcionada aquí. - + Discord: Discord: - + Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for. Permite a otros en Discord ver en qué servidor estás, qué personaje juegas y cuánto tiempo has estado jugando. @@ -234,12 +264,12 @@ Razón: Permite el movimiento de la pantalla y el parpadeo. Desactive esto si tiene inquietudes o problemas con la fotosensibilidad y/o convulsiones. - + Language: Idioma: - + Sets the language if you don't want to use your system language. Establece el idioma si no desea utilizar el idioma de su sistema. @@ -248,47 +278,47 @@ Razón: Habilítelo para agregar una pequeña pausa en los signos de puntuación. - + Callwords Palabras clave - + <html><head/><body>Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!<br>Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.</body></html> <html><head/><body>Ingrese tantas palabras de llamada como desee.<br>Esto no distingue entre mayúsculas y minúsculas. ¡Asegúrese de dejar cada palabra en su propia línea!<br>No deje una línea con un espacio al final; recibirá una alerta cada vez que alguien use un espacio en sus mensajes.</body></html> - + Audio Audio - + Audio device: Dispositivo: - + Sets the audio device for all sounds. Establece el dispositivo de audio. - + Music: Música: - + Sets the music's default volume. Establece el volumen predeterminado de la música. - + SFX: SFX: - + Sets the SFX's default volume. Interjections and actual sound effects count as 'SFX'. Establece el volumen predeterminado de SFX. Las interjecciones y los efectos de sonido reales cuentan como 'SFX'. @@ -317,47 +347,47 @@ Razón: Establece el volumen predeterminado para sonidos SFX, como las interjecciones y otros efectos de sonido de personajes. - + Blips: Blips: - + Sets the volume of the blips, the talking sound effects. Establece el volumen de los blips, el sonido al hablar. - + Blip rate: Tasa de blips: - + Sets the delay between playing the blip sounds. Establece el retraso entre la reproducción de los sonidos blip. - + Blank blips: Blips en blanco: - + If true, the game will play a blip sound even when a space is 'being said'. Si está marcada, el juego reproducirá un sonido blip incluso cuando se 'dice' un espacio. - + Enable Looping SFX: Habilitar repetición de SFX: - + If true, the game will allow looping sound effects to play on preanimations. Si está habilitado, el juego permitirá que se reproduzcan efectos de sonido en bucle en preanimaciones. - + Kill Music On Objection: Parar la música al objetar: @@ -366,190 +396,200 @@ Razón: Si está habilitado, el juego detendrá la música cuando alguien haga una objeción, como en los juegos. - + - Keep current setting - Mantener la configuración actual - + Allow Screenshake: Permitir screenshake: - + Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures. Permite el movimiento de la pantalla (ADVERTENCIA: esto podría inducir convulsiones debido a imágenes parpadeantes). - + Allow Effects: Permitir efectos: - + Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures. Permite efectos de pantalla (ADVERTENCIA: esto podría inducir convulsiones debido a imágenes parpadeantes). - + Network Frame Effects: Enviar efectos al servidor: - + Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality. Envíe temblores de pantalla, destellos y sonidos como se define en char.ini a través de la red. Solo funciona para servidores que admiten esta funcionalidad. - + Colors in IC Log: Colores en el registro IC: - + Use the markup colors in the server IC chatlog. Permite colores en el chat IC del servidor. - + Sticky Sounds: Mantener sonidos: - + Turn this on to prevent the sound dropdown from clearing the sound after playing it. Actívelo para evitar que el menú desplegable de sonido borre el sonido después de reproducirlo. - + Sticky Effects: Mantener efectos: - + Turn this on to prevent the effects dropdown from clearing the effect after playing it. Actívelo para evitar que el menú desplegable de efectos elimine el efecto después de reproducirlo. - + Sticky Preanims: Mantener preanims: - + Turn this on to prevent preanimation checkbox from clearing after playing the emote. Actívelo para evitar que la casilla preanimation se desactive después de reproducir el emote. - + Custom Chatboxes: Chatboxes personalizados: - + Turn this on to allow characters to define their own custom chat box designs. Actívelo para permitir que los personajes definan sus propios diseños de cuadros de chat personalizados. - + Play a blip sound "once per every X symbols", where X is the blip rate. Reproduce un sonido de blip "una vez por cada X símbolos", donde X es la tasa de blip. - + If true, AO2 will stop the music for you when you or someone else does 'Objection!'. Si es activado, AO2 detendrá la música por ti cuando tú u otra persona hagan un '¡Protesto!'. - + Casing Caso - + This server supports case alerts. Este servidor admite alertas de casos. - + This server does not support case alerts. Este servidor no admite alertas de casos. - + Pretty self-explanatory. Bastante autoexplicativo. - + Casing: Caso: - + If checked, you will get alerts about case announcements. Si está marcado, recibirá anuncios de casos. - + Defense: Abogado: - + If checked, you will get alerts about case announcements if a defense spot is open. Si está marcado, recibirá alertas sobre anuncios de casos si hay un lugar de abogado libre. - + Prosecution: Fiscal: - + If checked, you will get alerts about case announcements if a prosecutor spot is open. Si está marcada, recibirá alertas sobre anuncios de casos si hay un puesto de fiscal libre. - + Judge: Juez: - + If checked, you will get alerts about case announcements if the judge spot is open. Si está marcado, recibirá alertas sobre anuncios de casos si el puesto de juez está libre. - + Juror: Jurado: - + If checked, you will get alerts about case announcements if a juror spot is open. Si está marcado, recibirá alertas sobre anuncios de casos si hay un puesto de jurado libre. - + Stenographer: Taquígrafo: - + If checked, you will get alerts about case announcements if a stenographer spot is open. Si está marcado, recibirá alertas sobre anuncios de casos si hay un lugar de taquígrafo libre. - + CM: CM: - + If checked, you will appear amongst the potential CMs on the server. Si está marcado, aparecerá entre los posibles CM en el servidor. + + + Automatic Logging: + Registro automático: + + + + If checked, all logs will be automatically written in the /logs folder. + Si está marcado, todos los registros se guardarán automáticamente en la carpeta logs. + Witness: Testigo: @@ -559,12 +599,12 @@ Razón: Si está marcado, aparecerá entre los posibles testigos en el servidor. - + Hosting cases: Casos: - + If you're a CM, enter what cases you are willing to host. Si eres un CM, ingresa qué casos estás dispuesto a organizar. @@ -619,7 +659,7 @@ Razón: - + Search Buscar @@ -639,7 +679,7 @@ Razón: No se pudo encontrar %1 - + Generating chars: %1/%2 Generando personajes: @@ -652,53 +692,53 @@ Razón: - + Showname A translation wouldn't fit because of the shitty theme system. - + Message Mensaje - + Name Nombre - + Pre A translation wouldn't fit because of the shitty theme system. - + Flip A translation wouldn't fit because of the shitty theme system. - + Guard Guardia - - + + Casing This could be translated as 'caso' and it wouldn't get cut, but there are so many other buttons that can't be translated on the courtroom window that might as well leave this also untranslated so it's at least consistent. - + Shownames A translation wouldn't fit because of the shitty theme system. - + No Interrupt A translation wouldn't fit because of the shitty theme system. @@ -740,68 +780,68 @@ Razón: Cian - + % offset % desplazamiento - + Music - + Sfx - + Blips - + Change character - + Reload theme - + Call mod - + Settings - + A/M - + Preanim - + Back to Lobby 'Volver al lobby' got cut, changed to just Lobby Lobby - + You were granted the Disable Modcalls button. Se le concedió el botón para deshabilitar llamadas a moderadores. - + You have been banned. Has sido vetado. @@ -814,7 +854,7 @@ Razón: Esto no hace nada, pero ahí lo tienes. - + You opened the settings menu. Abriste el menú de configuración. @@ -827,82 +867,82 @@ Razón: si ellos también eligen a tu personaje a cambio. - + None Nada - + Additive Aditivo - + To front Al frente - + To behind Al fondo - + Select a character you wish to pair with. Seleccione un personaje con el que desee emparejarse. - + Change the percentage offset of your character's position from the center of the screen. Cambia el desplazamiento porcentual de la posición de tu personaje desde el centro de la pantalla. - + Change the order of appearance for your character. Cambia el orden de aparición de tu personaje. - + Display the list of characters to pair with. Muestra la lista de personajes para emparejar. - + Oops, you're muted! ¡Ups, estas silenciado! - + Set your character's emote to play on your next message. Configura el emote de tu personaje para usar en tu próximo mensaje. - + Set your character's supplementary background. Establece el fondo suplementario de tu personaje. - + Set an 'iniswap', or an alternative character folder to refer to from your current character. Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/<charname>/iniswaps.ini Establece un 'iniswap', o una carpeta de caracteres alternativa para consultar desde su personaje actual. Edite escribiendo y presionando Enter, [X] para eliminar. Esto es guardado en base/characters/<charname>/iniswaps.ini - - + + Remove the currently selected iniswap from the list and return to the original character folder. Elimina el iniswap seleccionado actualmente de la lista y regresa a la carpeta de caracteres original. - + Set a sound effect to play on your next 'Preanim'. Leaving it on Default will use the emote-defined sound (if any). Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/<charname>/soundlist.ini Establece un efecto de sonido para jugar en su próximo 'Preanim'. Dejarlo en Predeterminado usará el sonido definido por emoticones (si hay). Edite escribiendo y presionando Enter, [X] para eliminar. Esto es guardado en base/characters/<charname>/iniswaps.ini - + Choose an effect to play on your next spoken message. The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by char.ini [Options] category, effects = 'miscname' where it referes to misc/<miscname>/effects.ini to read the effects. @@ -911,304 +951,314 @@ Los efectos se definen en theme/effects/effects.ini. Tu personaje puede definir char.ini [Opciones] categoría, effects = 'miscname' donde se refiere a misc/<miscname>/effects.ini para leer los efectos. - + Hold It! ¡Un Momento! - - - + + + When this is turned on, your next in-character message will be a shout! Why the exclamation? Cuando esto es activado, tu próximo mensaje del personaje será un grito. - + Objection! ¡Protesto! - + Take That! ¡Toma Eso! - + Toggle between server chat and global AO2 chat. Alternar entre el chat del servidor y el chat global. - - - - + + + + This will display the animation in the viewport as soon as it is pressed. Esto mostrará la animación en el viewport tan pronto como se presione. - + Guilty! ¡Culpable! - + Bring up the Character Select Screen and change your character. Abre la pantalla de selección de personaje y cambia tu personaje. - + Refresh the theme and update all of the ui elements to match. Actualiza el tema y todos los elementos de la interfaz de usuario para que coincidan. - + Request the attention of the current server's moderator. Solicite la atención del moderador actual del servidor. - + Allows you to change various aspects of the client. Le permite cambiar varios aspectos del cliente. - + An interface to help you announce a case (you have to be a CM first to be able to announce cases) Una interfaz para ayudarlo a anunciar un caso (debe ser un CM para poder anunciar casos) - + Switch between Areas and Music lists Cambiar entre áreas y listas de música - + Play a single-shot animation as defined by the emote when checked. Reproduzca una animación de un solo disparo según lo definido por el emote cuando esté marcado. - + If preanim is checked, display the input text immediately as the animation plays concurrently. Si se marca preanim, muestre el texto de entrada inmediatamente mientras la animación se reproduce simultáneamente. - + Mirror your character's emotes when checked. Refleja los gestos de tu personaje cuando esté marcado. - + Add text to your last spoken message when checked. Agregar texto a su último mensaje hablado cuando esté marcado. - + Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window. No escucha llamadas de moderación cuando esté marcado, evitando que reproduzcan sonidos o centrando la atención en la ventana. - + Lets you receive case alerts when enabled. (You can set your preferences in the Settings!) Le permite recibir alertas de casos cuando está habilitado. (¡Puedes configurar tus preferencias en la Configuración!) - + Display customized shownames for all users when checked. Mostrar nombres personalizados para todos los usuarios cuando esté marcado. - + Custom Shout! ¡Grito personalizado! - + This will display the custom character-defined animation in the viewport as soon as it is pressed. To make one, your character's folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect Esto mostrará la animación de personaje personalizada definida en el viewport tan pronto como se presione. Para hacer una, la carpeta de tu personaje debe contener efectos personalizados [webp/apng/gif/png]. Y efectos personalizados de sonido [wav/ogg/opus] - + Play realization sound and animation in the viewport on the next spoken message when checked. Reproduzca sonido y animación de realización en la ventana gráfica en el siguiente mensaje hablado cuando esté marcado. - + Shake the screen on next spoken message when checked. Agite la pantalla en el siguiente mensaje hablado cuando esté marcado. - + Display the list of character folders you wish to mute. Muestra la lista de carpetas de caracteres que desea silenciar. - - + + Increase the health bar. Aumenta la barra de salud. - - + + Decrease the health bar. Disminuye la barra de salud. - + Change the text color of the spoken message. You can also select a part of your currently typed message and use the dropdown to change its color! Cambia el color del texto en el chat IC. ¡También puede seleccionar una parte de su mensaje escrito actualmente y usar el menú desplegable para cambiar su color! - + Return back to the server list. Regresar a la lista de servidores. - + Become a spectator. You won't be able to interact with the in-character screen. - Conviértete en espectador. No podrás interactuar con la pantalla del personaje. + Conviértete en espectador. No podrás interactuar como personaje. - - + + CLIENT - - - + + + has presented evidence + ha presentado evidencia + + + + has played a song ha reproducido la canción - + You will now pair up with %1 if they also choose your character in return. Ahora se emparejará con %1 si también eligen a su personaje. - + You are no longer paired with anyone. Ya no estás emparejado con nadie. - + Are you sure you typed that well? The char ID could not be recognised. ¿Estás seguro de que lo escribiste bien? El ID de personaje no pudo ser reconocido. - + You have set your offset to Ha configurado su desplazamiento en - + Your offset must be between -100% and 100%! ¡Su desplazamiento debe estar entre -100% y 100%! - + That offset does not look like one. Ese desplazamiento no se parece a uno. - + You switched your music and area list. Cambiaste tu lista de música y área. - + You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this. Ha habilitado forzosamente funciones que el servidor puede no admitir. Es posible que no pueda hablar IC, o peor, debido a esto. - + Your pre-animations interrupt again. Sus pre-animaciones interrumpen de nuevo. - + Your pre-animations will not interrupt text. Sus pre-animaciones no interrumpirán el texto. - + Couldn't open chatlog.txt to write into. No se pudo abrir chatlog.txt para escribir. - + The IC chatlog has been saved. El chat IC se ha guardado. - + You don't have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it's likely the case file you're looking for can't be found in there. ¡No tienes una carpeta `base/cases /`! Ha sido creada para ti. Pero debido a que no existia la carpeta, tampoco habían casos guardados ahí. - + You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini. Cases you can load: %1 ¡Debe dar un nombre de archivo para cargar (no se necesita extensión)! Asegúrese de que esté en la carpeta `base/cases/` y de que tenga el formato correcto. Casos que puede cargar: %1 - + Case made by %1. Caso hecho por %1. - + Navigate to %1 for the CM doc. Navegue a %1 para el documento del CM. - - + + UNKNOWN - + Your case "%1" was loaded! Su caso "%1" fue cargado! - + + Play Random Song + Reproducir canción aleatoria + + + Expand All Categories Expandir todas las categorías - + Collapse All Categories Contraer todas las categorías - + Fade Out Previous - Desvanecerse Anterior + Desvanecer Anterior - + Fade In Fundirse - + Synchronize Sincronizar - + Default Predeterminado @@ -1219,7 +1269,7 @@ Cases you can load: Casos que puede cargar: - + Too many arguments to load a case! You only need one filename, without extension. ¡Demasiados argumentos para cargar un caso! Solo necesita un nombre de archivo, sin extensión. @@ -1244,34 +1294,34 @@ Casos que puede cargar: " fue cargado! - + You don't have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it's likely that you somehow deleted it. ¡No tienes una carpeta `base/cases /`! Fue creada para ti. - + You need to give a filename to save (extension not needed) and the courtroom status! ¡Debe dar un nombre de archivo para guardar (no se necesita la extensión) y el estado de la sala del tribunal! - + Too many arguments to save a case! You only need a filename without extension and the courtroom status! why two exclamations, seems excesive. ¡Demasiados argumentos para salvar un caso! Solo necesita un nombre de archivo sin extensión y el estado de la sala del tribunal. - + Succesfully saved, edit doc and cmdoc link on the ini! ¡Guardado con éxito, puede editar el doc y doc link en el archivo ini! - + Master - - + + Server @@ -1284,28 +1334,28 @@ Casos que puede cargar: ¡Demasiados argumentos para salvar un caso! Solo necesita un nombre de archivo sin extensión y el estado de la sala del tribunal. - + Reason: Razón: - + Call Moderator Llamar Moderador - - + + Error Error - + You must provide a reason. Debes proporcionar una razón. - + The message is too long. El mensaje es muy largo. @@ -1358,12 +1408,12 @@ Se le preguntará si hay cambios no guardados. Bring up the Evidence screen. - Abre la ventana para evidencia. + Abrir la ventana de evidencia. Switch evidence to private inventory. - Cambiar la evidencia al inventario privado. + Enviar la evidencia al inventario privado. @@ -1465,63 +1515,77 @@ Descripción: Lobby - + Attorney Online 2 - + Search Buscar - + Name Nombre - + It doesn't look like your client is set up correctly. Did you download all resources correctly from tiny.cc/getao, including the large 'base' folder? No parece que su cliente esté configurado correctamente. ¿Descargó todos los recursos correctamente desde tiny.cc/getao, incluida la gran carpeta 'base'? - + Version: %1 Versión: %1 - + Settings Ajustes - + Allows you to change various aspects of the client. Le permite cambiar varios aspectos del cliente. - + Loading Cargando - + Cancel Cancelar - + + <h2>Attorney Online %1</h2>The courtroom drama simulator<p><b>Source code:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Major development:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Client development:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>QA testing:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Special thanks:</b><br>CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!<p>The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.<p>Running on Qt version %2 with the BASS audio engine.<br>APNG plugin loaded: %3<p>Built on %4 + <h2>Attorney Online %1</h2>El simulador de drama legal<p><b>Código fuente:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Desarrollo mayor:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Desarrollo del cliente:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>Prueba de control de calidad:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Agradecimiento especial:</b><br>CrazyJC y MaximumVolty (versión 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, creadores de contenido y toda la comunidad AO2.<p>El proyecto Attorney Online novela visual en red tiene copyright (c) 2016-2020 Attorney Online developers. Se aplican licencias de código abierto. Todos los demás activos son propiedad de sus respectivos dueños.<p>Usando Qt versión %2 con el motor de audio BASS.<br>Plugin APNG cargado: %3<p>Compilado el %4 + + + + Yes + + + + + No + + + <h2>Attorney Online %1</h2>The courtroom drama simulator<p><b>Source code:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Major development:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Client development:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>QA testing:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Special thanks:</b><br>CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!<p>The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.<p>Running on Qt version %2 with the %3 audio engine.<p>Built on %4 - <h2>Attorney Online %1</h2>El simulador de drama legal<p><b>Código fuente:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Desarrollo mayor:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Desarrollo del cliente:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>Prueba de control de calidad:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Agradecimiento especial:</b><br>CrazyJC y MaximumVolty (versión 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, creadores de contenido y toda la comunidad AO2.<p>El proyecto Attorney Online novela visual en red tiene copyright (c) 2016-2020 Attorney Online developers. Se aplican licencias de código abierto. Todos los demás activos son propiedad de sus respectivos dueños.<p>Usando Qt versión %2 con el motor de audio %3.<p>Compilado el %4 + <h2>Attorney Online %1</h2>El simulador de drama legal<p><b>Código fuente:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Desarrollo mayor:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Desarrollo del cliente:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>Prueba de control de calidad:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Agradecimiento especial:</b><br>CrazyJC y MaximumVolty (versión 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, creadores de contenido y toda la comunidad AO2.<p>El proyecto Attorney Online novela visual en red tiene copyright (c) 2016-2020 Attorney Online developers. Se aplican licencias de código abierto. Todos los demás activos son propiedad de sus respectivos dueños.<p>Usando Qt versión %2 con el motor de audio %3.<p>Compilado el %4 <h2>Attorney Online %1</h2>The courtroom drama simulator<p><b>Source code:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Major development:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Client development:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>QA testing:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Special thanks:</b><br>CrazyJC and MaximumVolty (2.8 release); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!<p>The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.<p>Running on Qt version %2 with the %3 audio engine.<p>Built on %4 <h2>Attorney Online %1</h2>El simulador de drama legal<p><b>Código fuente:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Desarrollo mayor:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Desarrollo del cliente:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>Prueba de control de calidad:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Agradecimiento especial:</b><br>CrazyJC y MaximumVolty (versión 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, creadores de contenido y toda la comunidad AO2.<p>El proyecto Attorney Online novela visual en red tiene copyright (c) 2016-2020 Attorney Online developers. Se aplican licencias de código abierto. Todos los demás activos son propiedad de sus respectivos dueños.<p>Usando Qt versión %2 con el motor de audio %3.<p>Compilado el %4 - + About Acerca de @@ -1534,13 +1598,13 @@ Did you download all resources correctly from tiny.cc/getao, including the large <h2>Attorney Online %1</h2>El simulador de drama legal<p><b>Código fuente:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https: //github.com/AttorneyOnline/AO2-Client</a><p><b>Desarrollo mayor:</b> <br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter<p><b>Agradecimiento especial:</b><br>Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (diseño de interfaz de usuario), Draxirch (diseño de interfaz de usuario), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy - + Online: %1/%2 En línea: %1/%2 - - + + Offline Fuera de línea @@ -1555,9 +1619,8 @@ Did you download all resources correctly from tiny.cc/getao, including the large - has played a song: - ha comenzado a reproducir la canción: + ha comenzado a reproducir la canción: From af1e76022568af1f146e2b49e96af85eb06521b9 Mon Sep 17 00:00:00 2001 From: likeawindrammer <31085911+likeawindrammer@users.noreply.github.com> Date: Fri, 21 Aug 2020 04:14:29 -0600 Subject: [PATCH 46/46] Translations: Update Portuguese --- resource/translations/ao_pt.qm | Bin 47069 -> 48985 bytes resource/translations/ao_pt.ts | 699 ++++++++++++++++++--------------- 2 files changed, 381 insertions(+), 318 deletions(-) diff --git a/resource/translations/ao_pt.qm b/resource/translations/ao_pt.qm index dc8bc70db97bc21ef5f2b86fa0855cbe18c8de93..1ff023904c3d28bb42abc629f352498b646eb272 100644 GIT binary patch delta 3918 zcmZWq2~?Ej8h-xSH)c|CK?HxyFiR05tN>921B}Ze66HQHzc@Av&J2Q7j#{pD-F`DP zMYFo49Wxy@Tcky=r))Lq+G3>Ha$7EHdP^(uJ|ClWPWR0D=iA=zU7q)O-|vglnom14 z;jI0xK1WV(eB|Avey>h{{J5vxQNX30G zAb;H7Zrg>2wyp;nZ%258=LpcJ2wQH; z1}f_DR5JyTh8JGoI{Y#Yf7S*Jc@{?pcK``-IG@xEtT`^3{HuY5UrMHf8-U(BC2Q+c zz*8gH$CUx)%~CgLfr-nd5sN54X|psdt}ih1Ny)qVYvAE&l5c^J4j&Cmv(r}qOERU| ze^dfnC27@iBCz{I>B-_8LN!1-T-6T5#Y-O*aU7T<{dA-aD9e)0i%6#|)x@YYTy$EK z^Z+4_J*m0j#UE(MqDh}0OMTC13j8fVU0=Mv|3(%}=D`{I@} zx5G8d2G0X>pVTaSeF5;;Cz>_!9rW}u&EBEUF%?rahd(A#vFkP8wr&MV4{3glaGh$@ zW+$cb{s-D3Efr6mr7f95Jq@pFE1&NTNb92Go^4w9*hV^5u08T7Ipn!X`}vYtL^ySV z_WWJ#z>N#EzkErugwE)2h6t2;Kb8Zl(iUbPF%t z&GWEs@y-;$TBuucoCr8Z>DHKblOv0DYm^N%ctNKcX{hI1T~pyJM0TsLX-hu!#dVHh zl&#QhG%&*a1l{|YcHq%#bRV8(}%6IwRwQ$Zhd2U0MO*>A6weQ6kHkiuG4Sa z_(qs49H4*hAQg`OkN(}%o-Dg$L-GWYtESvAbVN2w@2sKBPs5K-F-*^3PL~xJf=%;) zm7f_NIL^om_Zb#1|CFqM*YMEZ2~64bhNs&ozb4nP&(lGK42G{Wn4*RE8!n7W1f~}l zbw6JO?oT)N&kS>8eIH{*o`uGF-Fd#`3FAW# z?jRzs8r8&RVE#(uj=OwJ#c*S5EFH=G!+3mT3y^rH@kC$tkE&|p#mwK>PaZI(G%$5# zy-Znin6f^{Orsr?`};UkAe_|!Onua}u$6|*t4t5|O$0VwV_ILzeaB|g_ERhu{}ZN2 zax;)@Fzx@xI3Re~^mghzHlbA0@&D5BxCGM)V>b7HHS0>c0fthuzM>7t9%CN*78{z> zYR(cVE<0f!c{+onJ!c-frh`>(Glz>-x`AS&d9rmX@SxYMte}E@yUfdVKaeDMn70l} z1lAoezufyMU|eZFeEB`r^{?hP_q<5RGo^Bfhs~+>{OE471%ngm1wE zU)Uy0VSgywZL9bxkq%w9DT8QmwAt3Mf_iEzY>lB7KzYL!{+Z|D;w;qg4wd|=> zZGSEEEbBhe{=udd!0bu(<6lrvK4m|9E5|uS_RFu5&6+(9jV1|L5p;CRn94_FjAPg` z%5Pfj$QN%(|J9Cy{S!&vj~x}ClC)FO9n-&}Tw1$h##%ab*DnrVE(2Ov>1cXq;y^-H z>)6>})awaHWXE<2-sda~0C8L)A!VfX`@T7*TlrGEpg)`*pnM(CNiff4M^mt^C zza}WxyE&^;Wam}4crsV654b}i#V5Oca%iR^59<`2;rFpQH+kDb_Pdpqj6RHeIX}faPr8j1Vc`5tq7@NLM}s|;SVUC(fOQS z_3`xh$mStcl0nKsITUr3yQlj45INo1395*!nqMdU^g^UUfF0oH;wOBG`Y3#t)x@IS z>dymW^RK2QfOBZ*j5wMaH>GFto`|iMXCg8YcUN4Tmk})yIU`ojj_s*tCmZfim{x(6 zm(o$f2_1r9Vn@cHE)5x-Qo<`ilp5ah^0W&ttXC%v9T*NOwa$PuBnVOO4$bUDgE$49 zHHuvA_mZ5lKgs}~(h!n8ZXbyO@nC?*=M08!{y_#a|ji7w;pYJk_2 zl9lp!r_bg0%H@7`-qquKMBbkLT&#IK#?tg0xYcRixX7l($qBu1J(bi_h43MoFF)$k z(T%Zc)^xMI*Gy8oHlPFvrs7g3O^>%&bjV^^--K*+_OnTm_9p`7v13S!a{f~I%VNI^ zAe#yFFk10w_~>sA*Tu-^EE-RgdLqSqHn@8o(o|)~Q0be9y5m{hkTE&sa|F$x@<$ez5?$ a4zzbGLDAgxMgFR)x$3Gl@oK>fkNgkk$T4~V delta 2400 zcmX9zazQ6PPp6@xo8-wi4 zN36xSF>y@Wql&%Xxw)KO{b|$9`GEX7uwX6_@D3291V$|cB6k3(u0S+>%YF{71HfuM zq(QF($@asx<_M%KDRylpq+3n_9$8SZ%|Q7Qj8(Y-wSR+G1>rfBBe3*5P`v>`mQyc* zku?bR%m9K%A!L675O-+U)+Hje@jW`|0z!Wk$nSyh3%$UaCy2=-)#CxY?T6UQ zm4LyBjEZ8wSBKnvp}?$nP*k-a$Y@1*Y8&9tgM)AAfn^4KUP<5K1Uir zHK7L>)5Kg2Av^vq^PsH@STc!uHgv;CGxH+)I8k_y)mSNkMc=S)c|@^&9y{gaZ@`@M zY*1P=U@B+d+Dh@}e%8<%3UHq6roL)oxSQSTSV-|5Y{BFlU~V>B@O3V**Al~)I1d8( zW7!7xS}K7z+xi1hWv^p@>8Ju0*Rub$(RymLMDONBS};pOBm}%NT(WE<0h#?Ik;feX zrgYfWWJrt)vxxzXq-`H*W{q0%EUE{1&0F%vEz*W5ox@|=S2mwhJZ`2Eu3yRpmr`b< z$8%v0Bno~ux9!JSbZ{ZJeIOc0f63+7c>t*X%%1Yl1I*Zl{HHZ_s^eYz4BOr6C2k=aG6 zye@UFp+u$xNnJ`~$ZnN-SN{V@`j0f^039$*C0$v!7pOZWHAof!%4li!3Nye4NI!nR zjF@N{wzYa`MFs84sFK#U5S~wq^gGW{Kux=BQaEYJ;4X8Ytq11+Q?@*<%R=pOOSam_ z9@yR{%P1pi3Swn>opj@XU9$Yb8>H^TvZ97?5>vJ8a2F+7^o{Jx)InkeO_YgBpptjkQzEm!ly}Z;23-2(-A>DZ*roD*-TweZp28!G zO11)?HdYPzJ2 zUsytb?yY>tZX*zQlaE!!0q;KKlZt6y-3NRj_Zw;9Az$^HE7jhQKkaaZ2HbAG^<_J? z?QP!jZT(3gp_lJFCD4Fr=l^dck&S+;bn~SR{$u|?y4eh61yAj@f0puS`9Ug$lk#|d15MSF$}_t%shzJY zudN_$Of^`PKi{#Z4K>PpfpqY+0A-&8N0dEL*}L(;!jDu_5_5oJJC#=pB@%O8RW{cI ztnybKPQFhf{8m+cg{1*CK~>kp(CDpHU0OAT235W4`^O$M;SQ?0n?r#~YE@qjt)o|| zod*d|e@5+{)dkG398&wt)B`%HdeO8NqHdKsd{q@uTcM74;7SRdRA&_vfbj=)c4jjW ze?)D0O8%e`>eCF3>^V8ZHv96htxZ=qnJa;Pht=IjDL(m}`p&Hg(t@M9KdzRvc2UE{ zlU5R;5kpNRMlW6yGIj=Keq9q)Mvj6Pn({E3@yUA4)x9(st!mA+7j&TZlIEA)DI_u{ z&4YeQH2%3}Kr^01I71jYZV>Ry5vD~_I|9S@n7`n;P7nCq7JSwbZirb}u-%8+x?ae+ z(GJWE6?WcFr2bd@TPS!ON^LY+IIyRZYV>f}R#ystpGtwcFN702dVmQ>h5B7YvFwp> zPWOZcP@nLxPl|z*pM=hv6gMtkc;Zbq?UL~FEQyq@7g^Q~*!f(v^NFLIo)@PVQ2f4; zV&KqQ;5thTYK)=&AH7M8xIwCn94D^6LxCPg#5EsLB5!t!rhv~Wv1?-4r3u8)VzF-A zQ2Vutwwh{+n=Q8b5mWJV#fx*g=*^Id-;1HZsJ!9m=Y;SB1l$5*bRzY`tP|wBFpMwpl)K8mr{b!xw8Y6MCzi z&CRAgX6B_6>HYVxUaNO!F4&|E$GE>t^wJtOBpTDSNv33@Dapgud2*w~mf7UMNXFCM t!m3@y!v|W$kjiBAXRlpr$k3*z8a5{-Y7N?qG*hyV)_Sg4Yi(@)^iKrk%t!zL diff --git a/resource/translations/ao_pt.ts b/resource/translations/ao_pt.ts index a3991f8..2548d83 100644 --- a/resource/translations/ao_pt.ts +++ b/resource/translations/ao_pt.ts @@ -44,44 +44,44 @@ Tenha um bom dia. Carregando - - + + Loading chars: %1/%2 Carregando personagens: %1/%2 - + Loading evidence: %1/%2 Carregando evidências: %1/%2 - - + + Loading music: %1/%2 Carregando músicas: %1/%2 - + You have been kicked from the server. Reason: %1 Você foi expulso do servidor. Motivo: %1 - + You have been banned from the server. Reason: %1 Você foi banido do servidor. Motivo: %1 - + You are banned on this server. Reason: %1 Você foi banido neste servidor. @@ -174,43 +174,73 @@ Motivo: %1 A quantidade de mensagens que o chat do IC manterá antes de excluir as mensagens mais antigas. Um valor igual ou inferior a 0 conta como 'infinito'. - + + Log newline: + Nova linha no log: + + + + If ticked, new messages will appear separated, with the message coming on the next line after the name. When unticked, it displays it as 'name: message'. + Se marcada, novas mensagens aparecerão separadamente e a mensagem aparecerá na próxima linha após o nome. Quando desmarcado, ele mostra como 'nome: mensagem'. + + + + Log margin: + Margem no log: + + + + The distance in pixels between each entry in the IC log. Default: 0. + A distância em pixels entre cada entrada no log IC. Padrão: 0. + + + + Log timestamp: + Timestamp no registro: + + + + If ticked, log will contain a timestamp in UTC before the name. + Se marcado, o registro conterá um carimbo de tempo em UTC antes do nome. + + + Default username: Nome de usuário padrão: - + Your OOC name will be automatically set to this value when you join a server. Seu nome OOC será automaticamente definido com esse valor quando você ingressar em um servidor. - + Custom shownames: Nomes personalizados: - + Gives the default value for the in-game 'Custom shownames' tickbox, which in turn determines whether the client should display custom in-character names. 'Custom shownames' changed to 'Shownames' because that's the actual name Fornece o valor padrão para a caixa de seleção 'Shownames' no jogo, que determina se o cliente deve exibir nomes personalizados nos personagens. - + Backup MS: MS de backup: - + If the built-in server lookups fail, the game will try the address given here and use it as a backup master server address. Se as pesquisas internas do servidor falharem, o jogo tentará o endereço fornecido aqui e o usará como um endereço de servidor principal de backup. - + Discord: - + Allows others on Discord to see what server you are in, what character are you playing, and how long you have been playing for. Permite que outras pessoas no Discord vejam em que servidor você está, qual personagem está jogando e há quanto tempo está jogando. @@ -223,12 +253,12 @@ Motivo: %1 Permite agitar e piscar. Desative isso se você tiver preocupações ou problemas com fotosensibilidade e/ou convulsões. - + Language: Língua: - + Sets the language if you don't want to use your system language. Define o idioma se você não quiser usar o idioma do sistema. @@ -237,47 +267,47 @@ Motivo: %1 Habilite para adicionar uma pequena pausa nos sinais de pontuação. - + Callwords Palavras-chave - + <html><head/><body>Enter as many callwords as you would like. These are case insensitive. Make sure to leave every callword in its own line!<br>Do not leave a line with a space at the end -- you will be alerted everytime someone uses a space in their messages.</body></html> <html><head/><body>Digite quantas palavras-chave você desejar. Estes não diferenciam maiúsculas de minúsculas. Certifique-se de deixar cada palavra chave em sua própria linha!<br>Não deixe uma linha com um espaço no final - você será alertado toda vez que alguém usar um espaço em suas mensagens.</body></html> - + Audio Áudio - + Audio device: Dispositivo de áudio: - + Sets the audio device for all sounds. Define o dispositivo de áudio para todos os sons. - + Music: Música: - + Sets the music's default volume. Define o volume padrão da música. - + SFX: SFX: - + Sets the SFX's default volume. Interjections and actual sound effects count as 'SFX'. Define o volume padrão do SFX. Interjeições e efeitos sonoros reais contam como 'SFX'. @@ -306,47 +336,47 @@ Motivo: %1 Define o volume padrão para sons SFX, como interjeições ou outros efeitos sonoros de personagens. - + Blips: - + Sets the volume of the blips, the talking sound effects. Define o volume dos blips, os efeitos sonoros de fala. - + Blip rate: Taxa de blip: - + Sets the delay between playing the blip sounds. Define o atraso entre a reprodução dos sons de blip. - + Blank blips: Blips em branco: - + If true, the game will play a blip sound even when a space is 'being said'. Se ativado, o jogo emitirá um sinal sonoro, mesmo quando um espaço estiver sendo "dito". - + Enable Looping SFX: Ative o SFX em loop: - + If true, the game will allow looping sound effects to play on preanimations. Se ativado, o jogo permitirá que efeitos sonoros em loop sejam reproduzidos em pré-animações. - + Kill Music On Objection: Parar a música no protesto: @@ -355,190 +385,200 @@ Motivo: %1 Se ativado, o jogo interrompe a música quando alguém protestar , como nos jogos reais. - + - Keep current setting - Mantenha as configurações atuais - + Allow Screenshake: Permitir screenshake: - + Allows screenshaking. Disable this if you have concerns or issues with photosensitivity and/or seizures. Permite o tremor de tela (AVISO: Pode causar convulsões devido à imagens tremidas). - + Allow Effects: Permitir efeitos: - + Allows screen effects. Disable this if you have concerns or issues with photosensitivity and/or seizures. Permite efeitos de tela (AVISO: Pode causar convulsões devido à imagens tremidas).. - + Network Frame Effects: Envie efeitos para o servidor: - + Send screen-shaking, flashes and sounds as defined in the char.ini over the network. Only works for servers that support this functionality. Envie vibrações, flashes e sons na tela, conforme definido no char.ini pela rede. Funciona apenas para servidores que suportam essa funcionalidade. - + Colors in IC Log: Cores no Log IC: - + Use the markup colors in the server IC chatlog. Permitir cores no chat do IC no servidor. - - - Sticky Sounds: - Manter sons: - - - - Turn this on to prevent the sound dropdown from clearing the sound after playing it. - Marque para evitar que o som do menu suspenso apague o som após a reprodução. - - - - Sticky Effects: - Manter efeitos: - - - - Turn this on to prevent the effects dropdown from clearing the effect after playing it. - Ative-o para impedir que o menu suspenso de efeito exclua o efeito após reproduzi-lo. - - - - Sticky Preanims: - Manter preanims: - - - - Turn this on to prevent preanimation checkbox from clearing after playing the emote. - Ative-o para impedir que a caixa de seleção de pré-animação seja desmarcada após a execução do emote. - + Sticky Sounds: + Manter sons: + + + + Turn this on to prevent the sound dropdown from clearing the sound after playing it. + Marque para evitar que o som do menu suspenso apague o som após a reprodução. + + + + Sticky Effects: + Manter efeitos: + + + + Turn this on to prevent the effects dropdown from clearing the effect after playing it. + Ative-o para impedir que o menu suspenso de efeito exclua o efeito após reproduzi-lo. + + + + Sticky Preanims: + Manter preanims: + + + + Turn this on to prevent preanimation checkbox from clearing after playing the emote. + Ative-o para impedir que a caixa de seleção de pré-animação seja desmarcada após a execução do emote. + + + Custom Chatboxes: Caixas de bate-papo personalizadas: - + Turn this on to allow characters to define their own custom chat box designs. Ative isso para permitir que os personagens tenham as suas próprias caixas de bate-papo personalizadas. - + Play a blip sound "once per every X symbols", where X is the blip rate. Reproduz um som de blip "uma vez para cada símbolo X", em que X é a taxa de blip. - + If true, AO2 will stop the music for you when you or someone else does 'Objection!'. Se ativado, o AO2 interromperá a música quando você ou outra pessoa fizer uma 'Protesto!'. - + Casing Caso - + This server supports case alerts. Este servidor suporta anúncios de casos. - + This server does not support case alerts. Este servidor não suporta alertas de caso. - + Pretty self-explanatory. Bastante auto-explicativo. - + Casing: Caso: - + If checked, you will get alerts about case announcements. Se marcado, você será alertado quando houverem anúncios de casos. - + Defense: Defesa: - + If checked, you will get alerts about case announcements if a defense spot is open. Se marcado, você receberá alertas sobre os anúncios de casos, se um ponto de defesa estiver aberto. - + Prosecution: Promotor: - + If checked, you will get alerts about case announcements if a prosecutor spot is open. Se marcado, você receberá alertas sobre os anúncios de casos, se uma posição de promotor estiver disponível. - + Judge: Juíz: - + If checked, you will get alerts about case announcements if the judge spot is open. Se marcado, você receberá alertas sobre os anúncios de casos, se o local do juíz: estiver aberto. - + Juror: Jurado: - + If checked, you will get alerts about case announcements if a juror spot is open. Se marcado, você receberá alertas sobre os anúncios de casos, se um local do jurado estiver aberto. - + Stenographer: Estenógrafo: - + If checked, you will get alerts about case announcements if a stenographer spot is open. Se marcado, você receberá alertas sobre anúncios de casos, se um local de estenógrafo estiver aberto. - + CM: CM: - + If checked, you will appear amongst the potential CMs on the server. Se marcado, você aparecerá entre os CMs possíveis no servidor. + + + Automatic Logging: + Registro automático: + + + + If checked, all logs will be automatically written in the /logs folder. + Se marcado, todos os registros serão automaticamente salvos na pasta logs. + Witness: Testemunha: @@ -548,12 +588,12 @@ Motivo: %1 Se marcado, você aparecerá entre as testemunhas em potencial no servidor. - + Hosting cases: Casos: - + If you're a CM, enter what cases you are willing to host. Se você é um CM, insira os casos que deseja hospedar. @@ -596,7 +636,7 @@ Motivo: %1 - + Search Pesquisar @@ -612,7 +652,7 @@ Motivo: %1 Em uso - + Generating chars: %1/%2 Gerando personagens: @@ -623,13 +663,13 @@ Motivo: %1 Não foi possível encontrar %1 - + Showname A translation wouldn't fit because of the shitty theme system. - + Message Mensagem @@ -638,37 +678,37 @@ Motivo: %1 Mensagem OOC - + Name Nome - + Pre A translation wouldn't fit because of the shitty theme system. - + Flip A translation wouldn't fit because of the shitty theme system. - - + + Casing A translation wouldn't fit because of the shitty theme system. - + Shownames A translation wouldn't fit because of the shitty theme system. - + No Interrupt A translation wouldn't fit because of the shitty theme system. @@ -710,74 +750,74 @@ Motivo: %1 Ciano - + % offset % deslocamento - + Music - + Sfx - + Blips - - + + Server - + Change character - + Reload theme - + Call mod - + Settings - + A/M - + Preanim - + Back to Lobby A translation wouldn't fit because of the shitty theme system. Lobby - + You were granted the Disable Modcalls button. Você recebeu o botão Desativar Modcalls. - + You have been banned. Você foi banido. @@ -786,7 +826,7 @@ Motivo: %1 Isso não faz nada, mas lá vai você. - + You opened the settings menu. Você abriu o menu de configurações. @@ -799,377 +839,382 @@ Motivo: %1 se eles também escolherem seu personagem em troca. - + None Nada - + Guard Guarda - + Additive Aditivo - + To front - Para frente + Para frente - + To behind - Ao fundo + Ao fundo - + Select a character you wish to pair with. - Selecione um personagem com o qual deseja parear. + Selecione um personagem com o qual deseja parear. - + Change the percentage offset of your character's position from the center of the screen. - Altere o deslocamento percentual da posição do seu personagem no centro da tela. + Altere o deslocamento percentual da posição do seu personagem no centro da tela. - + Change the order of appearance for your character. - Mude a ordem de aparência do seu personagem. + Mude a ordem de aparência do seu personagem. - + Display the list of characters to pair with. - Exibe a lista de caracteres para corresponder. + Exibe a lista de caracteres para corresponder. - + Oops, you're muted! - Opa, você está mudo! + Opa, você está mudo! - + Set your character's emote to play on your next message. - Defina o emote do seu personagem para usar na próxima mensagem. + Defina o emote do seu personagem para usar na próxima mensagem. - + Set your character's supplementary background. - Defina o plano de fundo suplementar para o seu personagem. + Defina o plano de fundo suplementar para o seu personagem. - + Set an 'iniswap', or an alternative character folder to refer to from your current character. Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/<charname>/iniswaps.ini - Defina um 'iniswap' ou uma pasta de caracteres alternativa para consultar seu personagem atual. + Defina um 'iniswap' ou uma pasta de caracteres alternativa para consultar seu personagem atual. Edite digitando e pressionando Enter, [X] para excluir. Isso é salvo em base/characters/<charname>/iniswaps.ini - - + + Remove the currently selected iniswap from the list and return to the original character folder. - Remova o iniswap atualmente selecionado da lista e retorne à pasta de caracteres original. + Remova o iniswap atualmente selecionado da lista e retorne à pasta de caracteres original. - + Set a sound effect to play on your next 'Preanim'. Leaving it on Default will use the emote-defined sound (if any). Edit by typing and pressing Enter, [X] to remove. This saves to your base/characters/<charname>/soundlist.ini - Configure um efeito sonoro para tocar no seu próximo 'Preanim'. Deixá-lo no padrão usará o som definido pelos emoticons (caso existam). + Configure um efeito sonoro para tocar no seu próximo 'Preanim'. Deixá-lo no padrão usará o som definido pelos emoticons (caso existam). Edite digitando e pressionando Enter, [X] para excluir. Isso é salvo em base/characters/<charname>/soundlist.ini - + Choose an effect to play on your next spoken message. The effects are defined in your theme/effects/effects.ini. Your character can define custom effects by char.ini [Options] category, effects = 'miscname' where it referes to misc/<miscname>/effects.ini to read the effects. - Escolha um efeito para reproduzir na sua próxima mensagem falada. + Escolha um efeito para reproduzir na sua próxima mensagem falada. Os efeitos são definidos em theme / effects / effects.ini. Seu personagem pode definir efeitos personalizados ao categoria char.ini [Opções], effects = 'miscname', onde se refere a misc/<miscname>/effects.ini to read the effects. - + Hold It! - Um momento! + Um momento! - - - + + + When this is turned on, your next in-character message will be a shout! Quando isso estiver ativado, sua próxima mensagem do personagem será um grito. - + Objection! - Protesto! + Protesto! - + Take That! - Tome isso! + Tome isso! - + Toggle between server chat and global AO2 chat. - Alterne entre o bate-papo do servidor e o global. + Alterne entre o bate-papo do servidor e o global. - - - - + + + + This will display the animation in the viewport as soon as it is pressed. - Isso exibirá a animação na janela de visualização assim que for pressionada. + Isso exibirá a animação na janela de visualização assim que for pressionada. - + Guilty! - Culpado! + Culpado! - + Bring up the Character Select Screen and change your character. - Abra a tela de seleção de personagem e mude seu personagem. + Abra a tela de seleção de personagem e mude seu personagem. - + Refresh the theme and update all of the ui elements to match. - Atualize o tema e todos os elementos da interface do usuário para corresponder. + Atualize o tema e todos os elementos da interface do usuário para corresponder. - + Request the attention of the current server's moderator. - Solicite a atenção do moderador do servidor atual. + Solicite a atenção do moderador do servidor atual. - + Allows you to change various aspects of the client. - Permite alterar vários aspectos do cliente. + Permite alterar vários aspectos do cliente. + + + + An interface to help you announce a case (you have to be a CM first to be able to announce cases) + Uma interface para ajudá-lo a anunciar um caso (deve ser um CM para poder anunciar casos) + + + + Switch between Areas and Music lists + Alterne entre áreas e listas de músicas - An interface to help you announce a case (you have to be a CM first to be able to announce cases) - Uma interface para ajudá-lo a anunciar um caso (deve ser um CM para poder anunciar casos) - - - - Switch between Areas and Music lists - Alterne entre áreas e listas de músicas - - - Play a single-shot animation as defined by the emote when checked. - Reproduza uma animação de tiro único, conforme definido pelo emote, quando marcada. + Reproduza uma animação de tiro único, conforme definido pelo emote, quando marcada. - + If preanim is checked, display the input text immediately as the animation plays concurrently. - Se pré-impressão estiver marcada, exiba o texto de entrada imediatamente enquanto a animação estiver sendo reproduzida simultaneamente. + Se pré-impressão estiver marcada, exiba o texto de entrada imediatamente enquanto a animação estiver sendo reproduzida simultaneamente. - + Mirror your character's emotes when checked. - Reflita os gestos do seu personagem quando marcado. + Reflita os gestos do seu personagem quando marcado. - + Add text to your last spoken message when checked. - Adicione texto à sua última mensagem falada quando marcado. + Adicione texto à sua última mensagem falada quando marcado. - + Do not listen to mod calls when checked, preventing them from playing sounds or focusing attention on the window. - Você não ouve chamadas de moderação quando marcado, impedindo-os de tocar sons ou concentrando a atenção na janela. + Você não ouve chamadas de moderação quando marcado, impedindo-os de tocar sons ou concentrando a atenção na janela. - + Lets you receive case alerts when enabled. (You can set your preferences in the Settings!) - Permite que você receba alertas de caso quando ativado. + Permite que você receba alertas de caso quando ativado. (Você pode configurar suas preferências em Configurações!) - + Display customized shownames for all users when checked. - Mostrar nomes personalizados para todos os usuários quando marcado. + Mostrar nomes personalizados para todos os usuários quando marcado. - + Custom Shout! - Grito personalizado! + Grito personalizado! - + This will display the custom character-defined animation in the viewport as soon as it is pressed. To make one, your character's folder must contain custom.[webp/apng/gif/png] and custom.[wav/ogg/opus] sound effect - Isso exibirá a animação de caracteres personalizados definida na viewport assim que for pressionada. + Isso exibirá a animação de caracteres personalizados definida na viewport assim que for pressionada. Para criar uma, a pasta do seu personagem deve conter efeitos personalizados [webp/apng/gif/png]. E efeitos sonoros personalizados [wav/ogg/opus] - + Play realization sound and animation in the viewport on the next spoken message when checked. - Tocar animação de som e performance na janela de desenho na seguinte mensagem falada quando marcada. + Tocar animação de som e performance na janela de desenho na seguinte mensagem falada quando marcada. - + Shake the screen on next spoken message when checked. - Agite a tela na próxima mensagem falada quando marcada. + Agite a tela na próxima mensagem falada quando marcada. - + Display the list of character folders you wish to mute. - Exibe a lista de pastas de caracteres que você deseja silenciar. + Exibe a lista de pastas de caracteres que você deseja silenciar. - - + + Increase the health bar. - Aumente a barra de saúde. + Aumente a barra de saúde. - - + + Decrease the health bar. - Abaixe a barra de saúde. + Abaixe a barra de saúde. - + Change the text color of the spoken message. You can also select a part of your currently typed message and use the dropdown to change its color! - Mude a cor do texto no chat IC. + Mude a cor do texto no chat IC. Você também pode selecionar uma parte da sua mensagem escrita no momento e usar o menu suspenso para alterar sua cor! - + Return back to the server list. - Retorne à lista de servidores. + Retorne à lista de servidores. - + Become a spectator. You won't be able to interact with the in-character screen. - Torne-se um espectador. Você não poderá interagir com a tela do personagem. + Torne-se um espectador. Você não será capaz de interagir como personagem. - - + + CLIENT - - - + + + has presented evidence + apresentou evidência + + + + has played a song - tocou a música + tocou a música - + You will now pair up with %1 if they also choose your character in return. - Agora você será emparelhado com %1 se também escolher seu personagem. + Agora você será emparelhado com %1 se também escolher seu personagem. - + You are no longer paired with anyone. Você não está mais fazendo par com ninguém. - + Are you sure you typed that well? The char ID could not be recognised. Você tem certeza que você escreveu isso certo? O ID do personagem não pôde ser encontrado. - + You have set your offset to Você definiu seu deslocamento como - + Your offset must be between -100% and 100%! Seu deslocamento deve estar entre -100% e 100%! - + That offset does not look like one. Esse deslocamento não se parece com um. - + You switched your music and area list. Você mudou sua lista de músicas e áreas. - + You have forcefully enabled features that the server may not support. You may not be able to talk IC, or worse, because of this. Você forçou recursos que o servidor pode não suportar. Você pode não conseguir falar de IC, ou pior, por causa disso. - + Your pre-animations interrupt again. Suas pré-animações interrompem novamente. - + Your pre-animations will not interrupt text. Suas pré-animações não interromperão o texto. - + Couldn't open chatlog.txt to write into. Não foi possível abrir o chatlog.txt para gravar. - + The IC chatlog has been saved. O chat do IC foi salvo. - + You don't have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it's likely the case file you're looking for can't be found in there. Você não possui uma pasta `base/cases/`! Foi feito para você, mas, como foi feito para você, provavelmente o arquivo do caso que você está procurando não pode ser encontrado lá. - + You need to give a filename to load (extension not needed)! Make sure that it is in the `base/cases/` folder, and that it is a correctly formatted ini. Cases you can load: %1 Você precisa fornecer um nome de arquivo para carregar (extensão não necessária)! Verifique se está na pasta `base/cases/` e se é um ini formatado corretamente. Casos que você pode carregar: %1 - + Too many arguments to load a case! You only need one filename, without extension. Muitos argumentos para carregar um caso! Você só precisa de um nome de arquivo, sem extensão. - + Case made by %1. Caso feito por %1. - + Navigate to %1 for the CM doc. Navegue para %1 para o documento do CM. - - + + UNKNOWN - + Your case "%1" was loaded! Seu caso "%1" foi carregado! - + You don't have a `base/cases/` folder! It was just made for you, but seeing as it WAS just made for you, it's likely that you somehow deleted it. Você não possui uma pasta `base/cases/`! Foi feito para você, mas, como foi feito para você, é provável que você o tenha excluído. - + You need to give a filename to save (extension not needed) and the courtroom status! Você deve fornecer um nome de arquivo para salvar (sem extensão necessária) e o estado do tribunal! @@ -1178,73 +1223,78 @@ Casos que você pode carregar: %1 Muitos argumentos para salvar um caso! Você só precisa de um nome de arquivo sem extensão e o estado do tribunal. - + Too many arguments to save a case! You only need a filename without extension and the courtroom status! Muitos argumentos para salvar um caso! Você só precisa de um nome de arquivo sem extensão e o estado do tribunal. - + Succesfully saved, edit doc and cmdoc link on the ini! Salvo com sucesso, você pode editar o documento e o link do documento no arquivo ini! - + Master - + + Play Random Song + Tocar música aleatória + + + Expand All Categories - Expandir todas as categorias + Expandir todas as categorias - + Collapse All Categories - Recolher todas as categorias + Recolher todas as categorias - + Fade Out Previous - Fade Anterior + Desvanecer Anterior - + Fade In - Aparecimento gradual + Aparecimento gradual - + Synchronize - Sincronizar + Sincronizar - + Default - Predeterminado + Predeterminado - + Reason: Razão: - + Call Moderator Chamar um Moderador - - + + Error Erro - + You must provide a reason. Você deve fornecer um motivo. - + The message is too long. A mensagem é muito longa. @@ -1255,81 +1305,81 @@ Casos que você pode carregar: %1 Present this piece of evidence to everyone on your next spoken message - Apresente essa evidência a todos na sua próxima mensagem falada + Apresente essa evidência a todos na sua próxima mensagem falada Save evidence to an .ini file. - Salve evidências em um arquivo .ini. + Salve evidências em um arquivo .ini. Load evidence from an .ini file. - Carregar evidências de um arquivo .ini. + Carregar evidências de um arquivo .ini. Destroy this piece of evidence - Destrua esta evidência + Destrua esta evidência Choose.. - Escolher.. + Escolher.. Close the evidence display/editing overlay. You will be prompted if there's any unsaved changes. - Feche a sobreposição para visualizar/editar evidências. + Feche a sobreposição para visualizar/editar evidências. Você será perguntado se existem alterações não salvas. Save any changes made to this piece of evidence and send them to server. - Salve as alterações feitas nesta evidência e envie-as para o servidor. + Salve as alterações feitas nesta evidência e envie-as para o servidor. Double-click to edit. Press [X] to update your changes. - Clique duas vezes para editar. Pressione [X] para atualizar suas alterações. + Clique duas vezes para editar. Pressione [X] para atualizar suas alterações. Bring up the Evidence screen. - Abra a tela para obter evidências. + Abra a tela de evidências. Switch evidence to private inventory. - Alterar evidência para inventário privado. + Enviar evidência para inventário privado. Switch evidence to global inventory. - Mude a evidência para o inventário global. + Mude a evidência para o inventário global. Transfer evidence to private inventory. - Transfira evidências para o inventário privado. + Transfira evidências para o inventário privado. Transfer evidence to global inventory. - Transfira evidências para o inventário global. + Transfira evidências para o inventário global. The piece of evidence you've been editing has changed. - A evidência que você está editando mudou. + A evidência que você está editando mudou. Do you wish to keep your changes? - Deseja manter suas alterações? + Deseja manter suas alterações? @@ -1337,7 +1387,7 @@ Você será perguntado se existem alterações não salvas. Image: %2 Description: %3 - Nome: %1 + Nome: %1 Imagem: %2 Descrição: %3 @@ -1352,7 +1402,7 @@ Descrição: Double-click to edit... - Clique duas vezes para editar... + Clique duas vezes para editar... @@ -1362,111 +1412,125 @@ Descrição: Evidence has been modified. - A evidência foi modificada. + A evidência foi modificada. Do you want to save your changes? - ¿Quieres guardar tus cambios? + Você quer salvar suas mudanças? Current evidence is global. Click to switch to private. - A evidência atual é global. Clique para mudar para privado. + A evidência atual é global. Clique para mudar para privado. Current evidence is private. Click to switch to global. - A evidência atual é privada. Clique para mudar para global. + A evidência atual é privada. Clique para mudar para global. "%1" has been transferred. - "%1" foi transferido. + "%1" foi transferido. Save Inventory - Salvar inventário + Salvar inventário Ini Files (*.ini) - Arquivos INI (* .ini) + Arquivos INI (* .ini) Open Inventory - Abrir inventário + Abrir inventário Lobby - + Attorney Online 2 - + Search Pesquisar - + Name Nome - + It doesn't look like your client is set up correctly. Did you download all resources correctly from tiny.cc/getao, including the large 'base' folder? Seu cliente não parece estar configurado corretamente. Você baixou todos os recursos corretamente do tiny.cc/getao, incluindo a grande pasta 'base'? - + Version: %1 Versão: %1 - + Settings Configurações - + Allows you to change various aspects of the client. Permite alterar vários aspectos do cliente. - - + + Offline Offline - + Loading Carregando - + Cancel Cancelar - + + <h2>Attorney Online %1</h2>The courtroom drama simulator<p><b>Source code:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Major development:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Client development:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>QA testing:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Special thanks:</b><br>CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!<p>The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.<p>Running on Qt version %2 with the BASS audio engine.<br>APNG plugin loaded: %3<p>Built on %4 + <h2>Attorney Online %1</h2>O simulador de drama jurídico<p><b>Código fonte:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Desenvolvimento principal:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Desenvolvimento de cliente:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>Teste de controle de qualidade:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Agradecimentos especiais:</b><br>CrazyJC y MaximumVolty (versão 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, criadores de conteúdo e toda a comunidade AO2.<p>O projeto Attorney Online possui direitos autorais (c) 2016-2020 Attorney Online developers. Aplicam-se licenças de código aberto. Todos os outros ativos são de propriedade de seus respectivos proprietários.<p>Usando a versão Qt %2 com o mecanismo de áudio BASS..<br>Plugin APNG carregado: %3<p>Compilado em %4 + + + + Yes + Sim + + + + No + Não + + <h2>Attorney Online %1</h2>The courtroom drama simulator<p><b>Source code:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Major development:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Client development:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>QA testing:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Special thanks:</b><br>CrazyJC (2.8 release director) and MaximumVolty (2.8 release promotion); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!<p>The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.<p>Running on Qt version %2 with the %3 audio engine.<p>Built on %4 - <h2>Attorney Online %1</h2>O simulador de drama jurídico<p><b>Código fonte:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Desenvolvimento principal:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Desenvolvimento de cliente:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>Teste de controle de qualidade:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Agradecimentos especiais:</b><br>CrazyJC y MaximumVolty (versão 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, criadores de conteúdo e toda a comunidade AO2.<p>O projeto Attorney Online possui direitos autorais (c) 2016-2020 Attorney Online developers. Aplicam-se licenças de código aberto. Todos os outros ativos são de propriedade de seus respectivos proprietários.<p>Usando a versão Qt %2 com o mecanismo de áudio %3.<p>Compilado em %4 + <h2>Attorney Online %1</h2>O simulador de drama jurídico<p><b>Código fonte:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Desenvolvimento principal:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Desenvolvimento de cliente:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>Teste de controle de qualidade:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Agradecimentos especiais:</b><br>CrazyJC y MaximumVolty (versão 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, criadores de conteúdo e toda a comunidade AO2.<p>O projeto Attorney Online possui direitos autorais (c) 2016-2020 Attorney Online developers. Aplicam-se licenças de código aberto. Todos os outros ativos são de propriedade de seus respectivos proprietários.<p>Usando a versão Qt %2 com o mecanismo de áudio %3.<p>Compilado em %4 <h2>Attorney Online %1</h2>The courtroom drama simulator<p><b>Source code:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Major development:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Client development:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>QA testing:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Special thanks:</b><br>CrazyJC and MaximumVolty (2.8 release); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, and FanatSors (AO1); server hosts, game masters, case makers, content creators, and the whole AO2 community!<p>The Attorney Online networked visual novel project is copyright (c) 2016-2020 Attorney Online developers. Open-source licenses apply. All other assets are the property of their respective owners.<p>Running on Qt version %2 with the %3 audio engine.<p>Built on %4 <h2>Attorney Online %1</h2>O simulador de drama jurídico<p><b>Código fonte:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Desenvolvimento principal:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter, Crystalwarrior, Iamgoofball<p><b>Desenvolvimento de cliente:</b><br>Cents02, in1tiate, raidensnake, windrammer<p><b>Teste de controle de qualidade:</b><br>CaseyCazy, CedricDewitt, Chewable Tablets, CrazyJC, Fantos, Fury McFlurry, Geck, Gin-Gi, Jamania, Minx, Pandae, Robotic Overlord, Shadowlions (aka Shali), Sierra, SomeGuy, Veritas, Wiso<p><b>Agradecimentos especiais:</b><br>CrazyJC y MaximumVolty (versão 2.8); Remy, Hibiki, court-records.net (sprites); Qubrick (webAO); Rue (website); Draxirch (UI design); Lewdton and Argoneus (tsuserver); Fiercy, Noevain, Cronnicossy, y FanatSors (AO1); server hosts, game masters, case makers, criadores de conteúdo e toda a comunidade AO2.<p>O projeto Attorney Online possui direitos autorais (c) 2016-2020 Attorney Online developers. Aplicam-se licenças de código aberto. Todos os outros ativos são de propriedade de seus respectivos proprietários.<p>Usando a versão Qt %2 com o mecanismo de áudio %3.<p>Compilado em %4 - + About Sobre @@ -1479,7 +1543,7 @@ Você baixou todos os recursos corretamente do tiny.cc/getao, incluindo a grande <h2>Attorney Online %1</h2>O simulador de drama jurídico<p><b>Código fonte:</b> <a href='https://github.com/AttorneyOnline/AO2-Client'>https://github.com/AttorneyOnline/AO2-Client</a><p><b>Desenvolvimento principal:</b><br>OmniTroid, stonedDiscord, longbyte1, gameboyprinter, Cerapter<p><b>Agradecimentos especiais:</b><br>Remy, Iamgoofball, Hibiki, Qubrick (webAO), Ruekasu (UI design), Draxirch (UI design), Unishred, Argoneus (tsuserver), Fiercy, Noevain, Cronnicossy - + Online: %1/%2 Online: %1/%2 @@ -1494,9 +1558,8 @@ Você baixou todos os recursos corretamente do tiny.cc/getao, incluindo a grande - has played a song: - tocou a música: + tocou a música: