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 diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e0b0886..0230d40 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 @@ -15,7 +13,7 @@ before_script: - echo Current working directory is $(pwd) build linux x86_64: - image: ubuntu + image: ubuntu:18.04 stage: build tags: - docker @@ -34,15 +32,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 @@ -53,21 +51,32 @@ 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 - - qmake -spec linux-clang "DEFINES += DISCORD QTAUDIO" + - qmake -spec linux-clang "DEFINES += DISCORD" - make -j4 # Post-processing - upx --lzma -9 --force bin/Attorney_Online artifacts: paths: + - lib/ - bin/ build windows i686: @@ -109,19 +118,21 @@ 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 - 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 | diff --git a/Attorney_Online.pro b/Attorney_Online.pro index 28a1e7c..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 @@ -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/base/serverlist.txt b/base/serverlist.sample.txt similarity index 100% rename from base/serverlist.txt rename to base/serverlist.sample.txt diff --git a/base/themes b/base/themes index 8de30fc..15b0cc4 160000 --- a/base/themes +++ b/base/themes @@ -1 +1 @@ -Subproject commit 8de30fc0fa0e1492a29dad0e839764ca44168cb3 +Subproject commit 15b0cc4aa1241a9b740fb1ce8a61c7f699a80de5 diff --git a/include/aoapplication.h b/include/aoapplication.h index f4685ec..60d945e 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 @@ -213,14 +214,20 @@ 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(); // 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(); @@ -433,10 +440,16 @@ 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; - const int MINOR_VERSION = 4; + const int MINOR_VERSION = 5; QString current_theme = "default"; 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/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/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/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 182c2a6..5b5ff6c 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(); @@ -118,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); @@ -128,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); @@ -217,11 +218,14 @@ 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 // 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 @@ -260,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 = @@ -313,14 +316,23 @@ 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; // 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; @@ -349,9 +361,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]; - bool chatmessage_is_empty = false; + // 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]; QString previous_ic_message = ""; QString additive_previous = ""; @@ -458,6 +471,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; @@ -639,6 +660,10 @@ private: void refresh_evidence(); void set_evidence_page(); + void reset_ic(); + void reset_ui(); + + void regenerate_ic_chatlog(); public slots: void objection_done(); void preanim_done(); @@ -803,8 +828,6 @@ private slots: void on_casing_clicked(); void ping_server(); - - void load_bass_opus_plugin(); }; #endif // COURTROOM_H diff --git a/resource/translations/ao_es.qm b/resource/translations/ao_es.qm index 7b238e7..7b5e6f2 100644 Binary files a/resource/translations/ao_es.qm and b/resource/translations/ao_es.qm differ diff --git a/resource/translations/ao_es.ts b/resource/translations/ao_es.ts index 8e43d8e..ec15abe 100644 --- a/resource/translations/ao_es.ts +++ b/resource/translations/ao_es.ts @@ -45,44 +45,44 @@ Que tengas un buen día. 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: diff --git a/resource/translations/ao_pt.qm b/resource/translations/ao_pt.qm index dc8bc70..1ff0239 100644 Binary files a/resource/translations/ao_pt.qm and b/resource/translations/ao_pt.qm differ 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: 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 - На заметку + Уведомление 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 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 6cedee8..6fc4d03 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); @@ -402,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); @@ -410,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); @@ -726,6 +759,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()); @@ -770,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/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 98b6a9c..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)); @@ -109,6 +74,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 +550,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); @@ -636,6 +617,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"); @@ -934,6 +916,20 @@ 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")); + 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(); } @@ -957,28 +953,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); @@ -1129,8 +1126,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]); } } @@ -1237,6 +1234,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; @@ -1282,8 +1281,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); @@ -1301,8 +1299,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(); } @@ -1433,16 +1430,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; for (int n_area = 0; n_area < area_list.size(); ++n_area) { @@ -1532,7 +1519,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) @@ -1611,7 +1598,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) @@ -1760,24 +1747,52 @@ 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() +{ + 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 // 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)) { + (n_string < MS_MINIMUM || ao_app->cccc_ic_support_enabled)) { m_chatmessage[n_string] = p_contents->at(n_string); } else { @@ -1786,99 +1801,65 @@ 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; - QString f_showname; - if (f_char_id > -1 && + QString f_displayname; + if (!is_spectator && (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) { - f_showname = ao_app->get_showname(char_list.at(f_char_id).name); + // 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 { - f_showname = m_chatmessage[SHOWNAME]; + // Otherwise, use the 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'; - // 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. + // 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. } - // Stop the chat arrow from animating - 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) { - 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"); + else { + objection_mod = m_chatmessage[OBJECTION_MOD].toInt(); } - // Let the server handle actually checking if they're allowed to do this. - is_additive = m_chatmessage[ADDITIVE].toInt() == 1; + // Reset IC display + reset_ic(); + + // Reset UI elements after client message gets sent + if (m_chatmessage[CHAR_ID].toInt() == m_cid) { + reset_ui(); + } 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_showname, 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); - - while (ic_chatlog_history.size() > log_maximum_blocks && - log_maximum_blocks > 0) { - ic_chatlog_history.removeFirst(); + if (m_chatmessage[MESSAGE].trimmed().isEmpty()) // User-created blankpost + { + m_chatmessage[MESSAGE] = ""; // Turn it into true blankpost } - append_ic_text(m_chatmessage[MESSAGE], f_showname, "", m_chatmessage[TEXT_COLOR].toInt()); + if (!m_chatmessage[MESSAGE].isEmpty() || ic_chatlog_history.isEmpty() || ic_chatlog_history.last().get_message() != "") + { + log_ic_text(f_charname, f_displayname, m_chatmessage[MESSAGE], "", + 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); @@ -1914,15 +1895,10 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) shout_stay_time); objection_player->play("custom", f_char, f_custom_theme); } + m_chatmessage[EMOTE_MOD] = 1; break; - default: - qDebug() << "W: Logic error in objection switch statement!"; } 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(); @@ -2011,11 +1987,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") @@ -2047,8 +2022,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()); } } @@ -2070,6 +2044,15 @@ 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 != 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) ui_vp_player_char->set_flipped(true); @@ -2264,13 +2247,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(); @@ -2574,107 +2560,107 @@ 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::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()); } } @@ -2756,16 +2742,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 = ""; @@ -2782,11 +2777,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; } @@ -2810,8 +2800,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); } @@ -2914,6 +2903,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 +2937,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) { @@ -3174,16 +3163,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); @@ -4100,8 +4081,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 +4137,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 +4384,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 +4561,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() { @@ -4645,29 +4625,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()) { @@ -4745,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); } diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index b543cfb..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); @@ -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") { diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 39754f3..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 = @@ -435,7 +455,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/" + 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 +470,10 @@ 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); @@ -908,6 +930,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; } @@ -1051,7 +1078,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"); }