From a7b208b92daa134ee6ed1a31c3bf1bb85ae7c70d Mon Sep 17 00:00:00 2001 From: Salanto Date: Sun, 21 Mar 2021 04:59:15 +0100 Subject: [PATCH 01/61] small refactor handle_music --- src/courtroom.cpp | 90 +++++++++++++++-------------------------------- 1 file changed, 29 insertions(+), 61 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index fe5f74d..6446387 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3677,6 +3677,10 @@ void Courtroom::handle_song(QStringList *p_contents) if (f_contents.size() < 2) return; + bool looping = false; // No loop due to outdated server using serverside looping + int channel = 0; // Channel 0 is 'master music', other for ambient + int effect_flags = 0; // No effects by default - vanilla functionality + QString f_song = f_contents.at(0); QString f_song_clear = f_song.left(f_song.lastIndexOf(".")); if (f_song.startsWith("http")) { @@ -3684,69 +3688,31 @@ void Courtroom::handle_song(QStringList *p_contents) QString f_song_decoded = QUrl::fromPercentEncoding(f_song_bytearray); f_song_clear = f_song_decoded.left(f_song_decoded.lastIndexOf(".")); } - f_song_clear = f_song_clear.right(f_song_clear.length() - - (f_song_clear.lastIndexOf("/") + 1)); + f_song_clear = f_song_clear.right(f_song_clear.length() - (f_song_clear.lastIndexOf("/") + 1)); + int n_char = f_contents.at(1).toInt(); - // Assume the song doesn't loop unless told otherwise (due to most outdated - // servers handling looping through serverside) - bool looping = false; - // Channel 0 is the 'master music', other channels would commonly be used for - // ambience - int channel = 0; - // No effects assumed by default - vanilla functionality - int effect_flags = 0; + if (p_contents->length() > 3 && p_contents->at(3) == "1") + looping = true; - if (n_char < 0 || n_char >= char_list.size()) { - int channel = 0; - if (p_contents->length() > 3 && p_contents->at(3) == "1") - looping = true; + if (p_contents->length() > 4) // eyyy we want to change this song's CHANNEL huh + channel = p_contents->at(4).toInt(); // let the music player handle it if + // it's bigger than the channel list - if (p_contents->length() > - 4) // eyyy we want to change this song's CHANNEL huh - channel = p_contents->at(4).toInt(); // let the music player handle it if - // it's bigger than the channel list - - if (p_contents->length() > 5) // Flags provided to us by server such as Fade + if (p_contents->length() > 5) { // Flags provided to us by server such as Fade // In, Fade Out, Sync Pos etc. - { - effect_flags = p_contents->at(5).toInt(); - } - music_player->play(f_song, channel, looping, effect_flags); - if (f_song == "~stop.mp3") - ui_music_name->setText(tr("None")); - else if (channel == 0) { - if (file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))) && !f_song.startsWith("http")) - ui_music_name->setText(f_song_clear); - else if (f_song.startsWith("http")) - ui_music_name->setText(tr("[STREAM] %1").arg(f_song_clear)); - else - ui_music_name->setText(tr("[MISSING] %1").arg(f_song_clear)); - } + effect_flags = p_contents->at(5).toInt(); } - else { + + bool is_stop = (f_song == "~stop.mp3"); + if (!(n_char < 0) && !(n_char >= char_list.size())) { QString str_char = char_list.at(n_char).name; QString str_show = ao_app->get_showname(str_char); - if (p_contents->length() > 2) { if (p_contents->at(2) != "") { str_show = p_contents->at(2); } } - if (p_contents->length() > 3 && p_contents->at(3) == "1") { - looping = true; - } - if (p_contents->length() > - 4) // eyyy we want to change this song's CHANNEL huh - channel = p_contents->at(4).toInt(); // let the music player handle it if - // it's bigger than the channel list - - if (p_contents->length() > 5) // Flags provided to us by server such as Fade - // In, Fade Out, Sync Pos etc. - { - effect_flags = p_contents->at(5).toInt(); - } - bool is_stop = f_song == "~stop.mp3"; if (!mute_map.value(n_char)) { if (is_stop) { log_ic_text(str_char, str_show, "", tr("has stopped the music")); @@ -3756,19 +3722,21 @@ void Courtroom::handle_song(QStringList *p_contents) log_ic_text(str_char, str_show, f_song, tr("has played a song")); append_ic_text(f_song_clear, str_show, tr("has played a song")); } - music_player->play(f_song, channel, looping, effect_flags); - if (is_stop) - ui_music_name->setText(tr("None")); - else if (channel == 0) { - if (file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))) && !f_song.startsWith("http")) - ui_music_name->setText(f_song_clear); - else if (f_song.startsWith("http")) - ui_music_name->setText(tr("[STREAM] %1").arg(f_song_clear)); - else - ui_music_name->setText(tr("[MISSING] %1").arg(f_song_clear)); - } } } + + music_player->play(f_song, channel, looping, effect_flags); + if(is_stop) { + ui_music_name->setText(tr("None")); + } + else if (channel == 0) { + if (file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))) && !f_song.startsWith("http")) + ui_music_name->setText(f_song_clear); + else if (f_song.startsWith("http")) + ui_music_name->setText(tr("[STREAM] %1").arg(f_song_clear)); + else + ui_music_name->setText(tr("[MISSING] %1").arg(f_song_clear)); + } } void Courtroom::handle_wtce(QString p_wtce, int variant) From 2c5da36992ce4320964b3b2e3b2eaa709ac1be0b Mon Sep 17 00:00:00 2001 From: Salanto Date: Sun, 21 Mar 2021 21:17:52 +0100 Subject: [PATCH 02/61] Apply suggested changes --- src/courtroom.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 6446387..36ed19f 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3677,6 +3677,7 @@ void Courtroom::handle_song(QStringList *p_contents) if (f_contents.size() < 2) return; + bool ok, ok2, ok3; //CharID,Channel, Effect bool looping = false; // No loop due to outdated server using serverside looping int channel = 0; // Channel 0 is 'master music', other for ambient int effect_flags = 0; // No effects by default - vanilla functionality @@ -3690,18 +3691,25 @@ void Courtroom::handle_song(QStringList *p_contents) } f_song_clear = f_song_clear.right(f_song_clear.length() - (f_song_clear.lastIndexOf("/") + 1)); - int n_char = f_contents.at(1).toInt(); + int n_char = f_contents.at(1).toInt(&ok); + if (!ok) + return; if (p_contents->length() > 3 && p_contents->at(3) == "1") looping = true; - if (p_contents->length() > 4) // eyyy we want to change this song's CHANNEL huh - channel = p_contents->at(4).toInt(); // let the music player handle it if - // it's bigger than the channel list - - if (p_contents->length() > 5) { // Flags provided to us by server such as Fade - // In, Fade Out, Sync Pos etc. - effect_flags = p_contents->at(5).toInt(); + if (p_contents->length() > 4) { + // eyyy we want to change this song's CHANNEL huh + // let the music player handle it if it's bigger than the channel list + channel = p_contents->at(4).toInt(&ok2); + if (!ok2) + return; + } + if (p_contents->length() > 5) { + // Flags provided to us by server such as Fade In, Fade Out, Sync Pos etc. + effect_flags = p_contents->at(5).toInt(&ok3); + if (!ok3) + return; } bool is_stop = (f_song == "~stop.mp3"); @@ -3726,7 +3734,7 @@ void Courtroom::handle_song(QStringList *p_contents) } music_player->play(f_song, channel, looping, effect_flags); - if(is_stop) { + if (is_stop) { ui_music_name->setText(tr("None")); } else if (channel == 0) { From 106d9f3097bfbb85008b59d5d56470642a403682 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Mon, 22 Mar 2021 01:59:21 +0300 Subject: [PATCH 03/61] Fix blankposting forcing the message queue to sleep up until another message is received --- src/courtroom.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index fe5f74d..754208e 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3231,6 +3231,10 @@ void Courtroom::start_chat_ticking() ui_vp_chatbox->show(); ui_vp_message->show(); } + // If we're not already waiting on the next message, start the timer. We could be overriden if there's an objection planned. + int delay = ao_app->stay_time(); + if (delay > 0 && !text_queue_timer->isActive()) + text_queue_timer->start(delay); return; } From 702b2758985d77750e905c7eadc88f6511ac58dd Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Mon, 22 Mar 2021 02:10:06 +0300 Subject: [PATCH 04/61] Fix chat messages being lost to the Ether if instant objection was used, or you switched an area during queue being parsed. (Your IC logs will be caught up to speed instead) --- include/courtroom.h | 3 +++ src/courtroom.cpp | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/include/courtroom.h b/include/courtroom.h index 21191e5..9e0ae58 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -226,6 +226,9 @@ public: // Parse the chat message packet and unpack it into the m_chatmessage[ITEM] format void unpack_chatmessage(QStringList p_contents); + // Skip the current queue, adding all the queue messages to the logs if desynchronized logs are disabled + void skip_chatmessage_queue(); + enum LogMode { IO_ONLY, DISPLAY_ONLY, diff --git a/src/courtroom.cpp b/src/courtroom.cpp index fe5f74d..c656930 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1247,7 +1247,7 @@ void Courtroom::set_background(QString p_background, bool display) // Clear the message queue text_queue_timer->stop(); - chatmessage_queue.clear(); + skip_chatmessage_queue(); text_state = 2; anim_state = 3; @@ -1961,8 +1961,10 @@ void Courtroom::chatmessage_enqueue(QStringList p_contents) int objection_mod = p_contents[OBJECTION_MOD].split("&")[0].toInt(); is_objection = objection_mod >= 1 && objection_mod <= 5; // If this is an objection, nuke the queue - if (is_objection) - chatmessage_queue.clear(); + if (is_objection) { + text_queue_timer->stop(); + skip_chatmessage_queue(); + } } // Record the log I/O, log files should be accurate. @@ -2008,6 +2010,34 @@ void Courtroom::chatmessage_dequeue() unpack_chatmessage(chatmessage_queue.dequeue()); } +void Courtroom::skip_chatmessage_queue() +{ + if (ao_app->is_desyncrhonized_logs_enabled()) { + chatmessage_queue.clear(); + return; + } + + while (!chatmessage_queue.isEmpty()) { + QStringList p_contents = chatmessage_queue.dequeue(); + 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 < MS_MINIMUM || ao_app->cccc_ic_support_enabled)) { + m_chatmessage[n_string] = p_contents.at(n_string); + } + else { + m_chatmessage[n_string] = ""; + } + // We have logs displaying as soon as we reach the message in our queue, which is a less confusing but also less accurate experience for the user. + log_chatmessage(m_chatmessage[MESSAGE], m_chatmessage[CHAR_ID].toInt(), m_chatmessage[SHOWNAME], m_chatmessage[TEXT_COLOR].toInt(), DISPLAY_ONLY); + } + } +} + void Courtroom::unpack_chatmessage(QStringList p_contents) { for (int n_string = 0; n_string < MS_MAXIMUM; ++n_string) { From ba36356a8869c1d22802dc0e8c4706dc2ba0f54e Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Mon, 22 Mar 2021 03:38:51 +0300 Subject: [PATCH 05/61] Fix log_chatmessage being called for the same message like 24 or more times causing insane spam Reduce needless copy-pasting for shit that doesn't even need to be there I actually made this fix but I stashed the older version when splitting the branches so you got the bugged verison instead. --- src/courtroom.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index c656930..307499f 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -2019,22 +2019,7 @@ void Courtroom::skip_chatmessage_queue() while (!chatmessage_queue.isEmpty()) { QStringList p_contents = chatmessage_queue.dequeue(); - 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 < MS_MINIMUM || ao_app->cccc_ic_support_enabled)) { - m_chatmessage[n_string] = p_contents.at(n_string); - } - else { - m_chatmessage[n_string] = ""; - } - // We have logs displaying as soon as we reach the message in our queue, which is a less confusing but also less accurate experience for the user. - log_chatmessage(m_chatmessage[MESSAGE], m_chatmessage[CHAR_ID].toInt(), m_chatmessage[SHOWNAME], m_chatmessage[TEXT_COLOR].toInt(), DISPLAY_ONLY); - } + log_chatmessage(p_contents[MESSAGE], p_contents[CHAR_ID].toInt(), p_contents[SHOWNAME], p_contents[TEXT_COLOR].toInt(), DISPLAY_ONLY); } } From 298422d45344b8e92ca5a8dd7002ecf92e185ea6 Mon Sep 17 00:00:00 2001 From: Salanto Date: Mon, 22 Mar 2021 20:45:10 +0100 Subject: [PATCH 06/61] Update courtroom.cpp to apply change requests --- src/courtroom.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 36ed19f..e6bd57b 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3677,7 +3677,7 @@ void Courtroom::handle_song(QStringList *p_contents) if (f_contents.size() < 2) return; - bool ok, ok2, ok3; //CharID,Channel, Effect + bool ok; // Used for charID, channel, effect check bool looping = false; // No loop due to outdated server using serverside looping int channel = 0; // Channel 0 is 'master music', other for ambient int effect_flags = 0; // No effects by default - vanilla functionality @@ -3701,19 +3701,19 @@ void Courtroom::handle_song(QStringList *p_contents) if (p_contents->length() > 4) { // eyyy we want to change this song's CHANNEL huh // let the music player handle it if it's bigger than the channel list - channel = p_contents->at(4).toInt(&ok2); - if (!ok2) + channel = p_contents->at(4).toInt(&ok); + if (!ok) return; } if (p_contents->length() > 5) { // Flags provided to us by server such as Fade In, Fade Out, Sync Pos etc. - effect_flags = p_contents->at(5).toInt(&ok3); - if (!ok3) + effect_flags = p_contents->at(5).toInt(&ok); + if (!ok) return; } bool is_stop = (f_song == "~stop.mp3"); - if (!(n_char < 0) && !(n_char >= char_list.size())) { + if (n_char > 0 && n_char < char_list.size()) { QString str_char = char_list.at(n_char).name; QString str_show = ao_app->get_showname(str_char); if (p_contents->length() > 2) { From d4c0b7a740b2f265efe0b61b52777cd6c073ed58 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 24 Mar 2021 21:31:29 +0300 Subject: [PATCH 07/61] Fix desynchronized logs options checkbox not loading properly (is still properly saved tho) --- src/aooptionsdialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp index 091528a..a0d2e7d 100644 --- a/src/aooptionsdialog.cpp +++ b/src/aooptionsdialog.cpp @@ -909,7 +909,7 @@ void AOOptionsDialog::update_values() { ui_log_newline_cb->setChecked(ao_app->get_log_newline()); ui_log_timestamp_cb->setChecked(ao_app->get_log_timestamp()); ui_log_ic_actions_cb->setChecked(ao_app->get_log_ic_actions()); - ui_desync_logs_cb->setChecked(ao_app->get_log_timestamp()); + ui_desync_logs_cb->setChecked(ao_app->is_desyncrhonized_logs_enabled()); ui_instant_objection_cb->setChecked(ao_app->is_instant_objection_enabled()); ui_showname_cb->setChecked(ao_app->get_showname_enabled_by_default()); ui_discord_cb->setChecked(ao_app->is_discord_enabled()); From 37de947a3df3c90b27562515f5d3a1e05ad40de5 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 24 Mar 2021 23:05:09 +0300 Subject: [PATCH 08/61] Mark ui_selector, ui_passworded, ui_taken for evidence and character select as static-only due to massice performance overhead for no substantial benefit --- include/aoimage.h | 4 +++- src/aocharbutton.cpp | 6 +++--- src/aoevidencebutton.cpp | 4 ++-- src/aoimage.cpp | 5 +++-- src/charselect.cpp | 2 +- 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/aoimage.h b/include/aoimage.h index 70ff1fc..b75eee1 100644 --- a/include/aoimage.h +++ b/include/aoimage.h @@ -11,7 +11,7 @@ class AOImage : public QLabel { public: - AOImage(QWidget *parent, AOApplication *p_ao_app); + AOImage(QWidget *parent, AOApplication *p_ao_app, bool make_static = false); ~AOImage(); QWidget *m_parent; @@ -20,6 +20,8 @@ public: QString path; + bool is_static = false; + bool set_image(QString p_image, QString p_misc = ""); void set_size_and_pos(QString identifier); }; diff --git a/src/aocharbutton.cpp b/src/aocharbutton.cpp index 3b384f3..5b48e50 100644 --- a/src/aocharbutton.cpp +++ b/src/aocharbutton.cpp @@ -15,19 +15,19 @@ AOCharButton::AOCharButton(QWidget *parent, AOApplication *p_ao_app, int x_pos, this->resize(60, 60); this->move(x_pos, y_pos); - ui_taken = new AOImage(this, ao_app); + ui_taken = new AOImage(this, ao_app, true); ui_taken->resize(60, 60); ui_taken->set_image("char_taken"); ui_taken->setAttribute(Qt::WA_TransparentForMouseEvents); ui_taken->hide(); - ui_passworded = new AOImage(this, ao_app); + ui_passworded = new AOImage(this, ao_app, true); ui_passworded->resize(60, 60); ui_passworded->set_image("char_passworded"); ui_passworded->setAttribute(Qt::WA_TransparentForMouseEvents); ui_passworded->hide(); - ui_selector = new AOImage(parent, ao_app); + ui_selector = new AOImage(parent, ao_app, true); ui_selector->resize(62, 62); ui_selector->move(x_pos - 1, y_pos - 1); ui_selector->set_image("char_selector"); diff --git a/src/aoevidencebutton.cpp b/src/aoevidencebutton.cpp index aea903a..fee7327 100644 --- a/src/aoevidencebutton.cpp +++ b/src/aoevidencebutton.cpp @@ -9,14 +9,14 @@ AOEvidenceButton::AOEvidenceButton(QWidget *p_parent, AOApplication *p_ao_app, ao_app = p_ao_app; m_parent = p_parent; - ui_selected = new AOImage(this, ao_app); + ui_selected = new AOImage(this, ao_app, true); ui_selected->resize(p_w, p_h); // ui_selected->move(p_x, p_y); ui_selected->set_image("evidence_selected"); ui_selected->setAttribute(Qt::WA_TransparentForMouseEvents); ui_selected->hide(); - ui_selector = new AOImage(this, ao_app); + ui_selector = new AOImage(this, ao_app, true); ui_selector->resize(p_w, p_h); // ui_selector->move(p_x - 1, p_y - 1); ui_selector->set_image("evidence_selector"); diff --git a/src/aoimage.cpp b/src/aoimage.cpp index e1bd8b8..142189c 100644 --- a/src/aoimage.cpp +++ b/src/aoimage.cpp @@ -4,11 +4,12 @@ #include -AOImage::AOImage(QWidget *parent, AOApplication *p_ao_app) : QLabel(parent) +AOImage::AOImage(QWidget *parent, AOApplication *p_ao_app, bool make_static) : QLabel(parent) { m_parent = parent; ao_app = p_ao_app; movie = new QMovie(); + is_static = make_static; connect(movie, &QMovie::frameChanged, [=]{ QPixmap f_pixmap = movie->currentPixmap(); f_pixmap = @@ -23,7 +24,7 @@ AOImage::~AOImage() {} bool AOImage::set_image(QString p_path, QString p_misc) { // Check if the user wants animated themes - if (ao_app->get_animated_theme()) + if (!is_static && ao_app->get_animated_theme()) // We want an animated image p_path = ao_app->get_image(p_path, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_misc); else diff --git a/src/charselect.cpp b/src/charselect.cpp index 510d8c0..d45e875 100644 --- a/src/charselect.cpp +++ b/src/charselect.cpp @@ -21,7 +21,7 @@ void Courtroom::construct_char_select() ui_char_buttons = new QWidget(ui_char_select_background); - ui_selector = new AOImage(ui_char_select_background, ao_app); + ui_selector = new AOImage(ui_char_select_background, ao_app, true); ui_selector->setAttribute(Qt::WA_TransparentForMouseEvents); ui_selector->resize(62, 62); From 48093c3f2b7068f3dd20baa101614a52b855bc04 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 24 Mar 2021 23:05:46 +0300 Subject: [PATCH 09/61] Remove useless code for extra ui_selector that is not used --- include/courtroom.h | 1 - src/charselect.cpp | 4 ---- src/courtroom.cpp | 3 --- 3 files changed, 8 deletions(-) diff --git a/include/courtroom.h b/include/courtroom.h index 9e0ae58..7e31b73 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -755,7 +755,6 @@ private: QVector ui_char_button_list; QVector ui_char_button_list_filtered; - AOImage *ui_selector; AOButton *ui_back_to_lobby; diff --git a/src/charselect.cpp b/src/charselect.cpp index d45e875..0a2659e 100644 --- a/src/charselect.cpp +++ b/src/charselect.cpp @@ -21,10 +21,6 @@ void Courtroom::construct_char_select() ui_char_buttons = new QWidget(ui_char_select_background); - ui_selector = new AOImage(ui_char_select_background, ao_app, true); - ui_selector->setAttribute(Qt::WA_TransparentForMouseEvents); - ui_selector->resize(62, 62); - ui_back_to_lobby = new AOButton(ui_char_select_background, ao_app); ui_char_password = new QLineEdit(ui_char_select_background); diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 2d63487..507acc1 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -972,9 +972,6 @@ void Courtroom::set_widgets() set_size_and_pos(ui_sfx_slider, "sfx_slider"); set_size_and_pos(ui_blip_slider, "blip_slider"); - ui_selector->set_image("char_selector"); - ui_selector->hide(); - set_size_and_pos(ui_back_to_lobby, "back_to_lobby"); ui_back_to_lobby->setText(tr("Back to Lobby")); ui_back_to_lobby->setToolTip(tr("Return back to the server list.")); From 6ec4e032e09a6e6135fed3faad76cc46598ee96f Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Wed, 24 Mar 2021 18:52:11 -0500 Subject: [PATCH 10/61] Version bump aoapplication.h --- include/aoapplication.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/aoapplication.h b/include/aoapplication.h index 9fa8c75..493f1c9 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -511,7 +511,7 @@ public: private: const int RELEASE = 2; const int MAJOR_VERSION = 9; - const int MINOR_VERSION = 0; + const int MINOR_VERSION = 1; QVector server_list; QVector favorite_list; From e89178bc4d596bae4d4b7b2eec16ef5c4b788284 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Wed, 24 Mar 2021 18:53:10 -0500 Subject: [PATCH 11/61] Version bump Attorney_Online.pro --- Attorney_Online.pro | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Attorney_Online.pro b/Attorney_Online.pro index ba1c80a..2a5c1e1 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.9.0.0 +VERSION = 2.9.1.0 INCLUDEPATH += $$PWD/include DESTDIR = $$PWD/bin From 3f651d069d52a5f4dc8f98fa0e3f44ccfd72667e Mon Sep 17 00:00:00 2001 From: in1tiate Date: Sat, 27 Mar 2021 23:01:35 -0500 Subject: [PATCH 12/61] add songs with no parent to clist --- src/courtroom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 2d63487..e506395 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -4802,7 +4802,7 @@ void Courtroom::music_random() QTreeWidgetItemIterator::NotHidden | QTreeWidgetItemIterator::NoChildren); while (*it) { - if ((*it)->parent()->isExpanded()) { + if (!(*it)->parent() || (*it)->parent()->isExpanded()) { // add top level songs and songs in expanded categories clist += (*it); } ++it; From 4140a3339aad886be0287c17bd4eabe7597af8e9 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Sun, 28 Mar 2021 23:11:22 -0500 Subject: [PATCH 13/61] fix packets containing unencoded newlines being incorrectly split into multiple entries --- src/demoserver.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/demoserver.cpp b/src/demoserver.cpp index 88dfdb4..509a356 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -233,8 +233,9 @@ void DemoServer::load_demo(QString filename) demo_stream.setCodec("UTF-8"); QString line = demo_stream.readLine(); while (!line.isNull()) { - if (!line.endsWith("%")) { + while (!line.endsWith("%")) { line += "\n"; + line += demo_stream.readLine(); } demo_data.enqueue(line); line = demo_stream.readLine(); From 05ff6b08a2d7a812ae128e23c97a516f2492cfe9 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Sun, 28 Mar 2021 23:11:54 -0500 Subject: [PATCH 14/61] add exception for LE packets in demos, which encode ampersand separators --- src/packet_distribution.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index f3810ca..0a99b9d 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -542,7 +542,11 @@ void AOApplication::server_packet_received(AOPacket *p_packet) QVector f_evi_list; for (QString f_string : f_contents_encoded) { - QStringList sub_contents = f_string.split("&"); + QStringList sub_contents; + if (f_contents_encoded.contains("&")) + sub_contents = f_string.split("&"); + else + sub_contents = f_string.split(""); // demos incorrectly encode the separator so we have to account for that if (sub_contents.size() < 3) continue; From fcc593112aeb6292fe13120ece40f7d6584bea6b Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Sun, 28 Mar 2021 23:13:38 -0500 Subject: [PATCH 15/61] Update themes submodule --- base/themes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/themes b/base/themes index 1264474..c9acb90 160000 --- a/base/themes +++ b/base/themes @@ -1 +1 @@ -Subproject commit 126447457906992e0096c4c9416f2b1f7986ff40 +Subproject commit c9acb90137361ea8c29bc4cf2bf530d14b52b23a From 73395f057bde3f6ca9700de1e22a997f7d53d286 Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Tue, 30 Mar 2021 05:49:28 -0500 Subject: [PATCH 16/61] use a string and not a boolean (stupid) --- src/aolayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aolayer.cpp b/src/aolayer.cpp index f0d5779..18213ce 100644 --- a/src/aolayer.cpp +++ b/src/aolayer.cpp @@ -156,7 +156,7 @@ void CharLayer::load_image(QString p_filename, QString p_charname, transform_mode = ao_app->get_scaling( ao_app->get_emote_property(p_charname, p_filename, "scaling")); stretch = ao_app->get_emote_property(p_charname, p_filename, "stretch") - .startsWith(true); + .startsWith("true"); if ((p_charname == last_char) && ((p_filename == last_emote) || (p_filename.mid(3, -1) == last_emote.mid(3, -1))) && From 1d83fae23dace8fb1b7d79dc6cbf715f687d0f4e Mon Sep 17 00:00:00 2001 From: in1tiate Date: Tue, 30 Mar 2021 06:59:35 -0500 Subject: [PATCH 17/61] fix chat arrow being loaded when it doesnt need to be --- src/courtroom.cpp | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index e506395..5eafe60 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1990,15 +1990,6 @@ void Courtroom::chatmessage_enqueue(QStringList p_contents) void Courtroom::chatmessage_dequeue() { - // Chat stopped being processed, indicate that the user can post their message now. - QString f_custom_theme; - if (ao_app->is_customchat_enabled()) { - QString f_char = m_chatmessage[CHAR_NAME]; - f_custom_theme = ao_app->get_chat(f_char); - } - ui_vp_chat_arrow->transform_mode = ao_app->get_misc_scaling(f_custom_theme); - ui_vp_chat_arrow->load_image("chat_arrow", f_custom_theme); - // Nothing to parse in the queue if (chatmessage_queue.isEmpty()) return; From 6b267e8fdc831032bd53b9b98a49b57d794b2043 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Tue, 30 Mar 2021 11:00:13 -0500 Subject: [PATCH 18/61] fix demo server not being added if serverlist.txt is absent --- src/text_file_functions.cpp | 34 ++++++++++++++++------------------ 1 file changed, 16 insertions(+), 18 deletions(-) diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index f6a5d6c..a671d61 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -243,33 +243,31 @@ QVector AOApplication::read_serverlist_txt() serverlist_txt.setFileName(serverlist_txt_path); - if (!serverlist_txt.open(QIODevice::ReadOnly)) { - return f_server_list; - } + if (serverlist_txt.open(QIODevice::ReadOnly)) { + QTextStream in(&serverlist_txt); - QTextStream in(&serverlist_txt); + while (!in.atEnd()) { + QString line = in.readLine(); + server_type f_server; + QStringList line_contents = line.split(":"); - while (!in.atEnd()) { - QString line = in.readLine(); - server_type f_server; - QStringList line_contents = line.split(":"); + if (line_contents.size() < 3) + continue; - if (line_contents.size() < 3) - continue; + f_server.ip = line_contents.at(0); + f_server.port = line_contents.at(1).toInt(); + f_server.name = line_contents.at(2); + f_server.desc = ""; - f_server.ip = line_contents.at(0); - f_server.port = line_contents.at(1).toInt(); - f_server.name = line_contents.at(2); - f_server.desc = ""; - - f_server_list.append(f_server); + f_server_list.append(f_server); + } } server_type demo_server; demo_server.ip = "127.0.0.1"; demo_server.port = 99999; - demo_server.name = "Demo playback"; - demo_server.desc = "Play back demos you have previously recorded"; + demo_server.name = tr("Demo playback"); + demo_server.desc = tr("Play back demos you have previously recorded"); f_server_list.append(demo_server); return f_server_list; From b15e669beed1fae103fba9f16b746e5fb76e2267 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Tue, 30 Mar 2021 11:00:25 -0500 Subject: [PATCH 19/61] add translation support to demo server messages --- src/demoserver.cpp | 47 +++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) diff --git a/src/demoserver.cpp b/src/demoserver.cpp index 509a356..fe296e6 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -150,7 +150,8 @@ void DemoServer::handle_packet(AOPacket packet) } else if (header == "CC") { client_sock->write("PV#0#CID#-1#%"); - client_sock->write("CT#DEMO#Demo file loaded. Send /play or > in OOC to begin playback.#1#%"); + QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%"; + client_sock->write(packet.toUtf8()); } else if (header == "CT") { if (contents[1].startsWith("/load")) @@ -159,14 +160,16 @@ void DemoServer::handle_packet(AOPacket packet) if (path.isEmpty()) return; load_demo(path); - client_sock->write("CT#DEMO#Demo file loaded. Send /play or > in OOC to begin playback.#1#%"); + QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%"; + client_sock->write(packet.toUtf8()); } else if (contents[1].startsWith("/play") || contents[1] == ">") { if (timer->interval() != 0 && !timer->isActive()) { timer->start(); - client_sock->write("CT#DEMO#Resuming playback.#1#%"); + QString packet = "CT#DEMO#" + tr("Resuming playback.") + "#1#%"; + client_sock->write(packet.toUtf8()); } else { @@ -180,7 +183,8 @@ void DemoServer::handle_packet(AOPacket packet) int timeleft = timer->remainingTime(); timer->stop(); timer->setInterval(timeleft); - client_sock->write("CT#DEMO#Pausing playback.#1#%"); + QString packet = "CT#DEMO#" + tr("Pausing playback.") + "#1#%"; + client_sock->write(packet.toUtf8()); } else if (contents[1].startsWith("/max_wait")) { @@ -194,29 +198,38 @@ void DemoServer::handle_packet(AOPacket packet) if (p_max_wait < 0) p_max_wait = -1; max_wait = p_max_wait; - client_sock->write("CT#DEMO#Setting max_wait to "); + QString packet = "CT#DEMO#" + tr("Setting max_wait to") + " "; + client_sock->write(packet.toUtf8()); client_sock->write(QString::number(max_wait).toUtf8()); - client_sock->write(" milliseconds.#1#%"); + packet = " " + tr("milliseconds.") + "#1#%"; + client_sock->write(packet.toUtf8()); } else { - client_sock->write("CT#DEMO#Not a valid integer!#1#%"); + QString packet = "CT#DEMO#" + tr("Not a valid integer!") + "#1#%"; + client_sock->write(packet.toUtf8()); } } else { - client_sock->write("CT#DEMO#Current max_wait is "); - client_sock->write(QString::number(max_wait).toUtf8()); - client_sock->write(" milliseconds.#1#%"); + + QString packet = "CT#DEMO#" + tr("Current max_wait is") + " "; + client_sock->write(packet.toUtf8()); + client_sock->write(QString::number(max_wait).toUtf8()); + packet = " " + tr("milliseconds.") + "#1#%"; + client_sock->write(packet.toUtf8()); + } } } else if (contents[1].startsWith("/min_wait")) { - client_sock->write("CT#DEMO#min_wait is deprecated. Use the client Settings for minimum wait instead!"); + QString packet = "CT#DEMO#" + tr("min_wait is deprecated. Use the client Settings for minimum wait instead!") + "#1#%"; + client_sock->write(packet.toUtf8()); } else if (contents[1].startsWith("/help")) { - client_sock->write("CT#DEMO#Available commands:\nload, play, pause, max_wait, help#1#%"); + QString packet = "CT#DEMO#" + tr("Available commands:\nload, play, pause, max_wait, help") + "#1#%"; + client_sock->write(packet.toUtf8()); } } } @@ -265,12 +278,16 @@ void DemoServer::playback() // Skip the difference on the timers emit skip_timers(wait_packet.get_contents().at(0).toInt() - duration); } + else if (timer->interval() != 0 && duration + elapsed_time > timer->interval()) { + duration = qMax(0, timer->interval() - elapsed_time); + emit skip_timers(wait_packet.get_contents().at(0).toInt() - duration); + } elapsed_time += duration; timer->start(duration); } - else - { - client_sock->write("CT#DEMO#Reached the end of the demo file. Send /play or > in OOC to restart, or /load to open a new file.#1#%"); + else { + QString end_packet = "CT#DEMO#" + tr("Reached the end of the demo file. Send /play or > in OOC to restart, or /load to open a new file.") + "#1#%"; + client_sock->write(end_packet.toUtf8()); timer->setInterval(0); } } From 9707753777c9a7d5ea429391f307201fde11db27 Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Tue, 30 Mar 2021 22:10:29 -0500 Subject: [PATCH 20/61] Update src/demoserver.cpp Co-authored-by: oldmud0 --- src/demoserver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/demoserver.cpp b/src/demoserver.cpp index fe296e6..764cf22 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -218,7 +218,6 @@ void DemoServer::handle_packet(AOPacket packet) client_sock->write(QString::number(max_wait).toUtf8()); packet = " " + tr("milliseconds.") + "#1#%"; client_sock->write(packet.toUtf8()); - } } } else if (contents[1].startsWith("/min_wait")) From 2a1905d009aafaf571b9c2cd50fdc3326194def3 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Tue, 30 Mar 2021 22:48:10 -0500 Subject: [PATCH 21/61] Trivial bounds check fix --- src/courtroom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index e6bd57b..fabcac8 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3713,7 +3713,7 @@ void Courtroom::handle_song(QStringList *p_contents) } bool is_stop = (f_song == "~stop.mp3"); - if (n_char > 0 && n_char < char_list.size()) { + if (n_char >= 0 && n_char < char_list.size()) { QString str_char = char_list.at(n_char).name; QString str_show = ao_app->get_showname(str_char); if (p_contents->length() > 2) { From ac82b83517480ffc1076d1dd2c4b7855ddd28279 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Wed, 31 Mar 2021 05:11:48 -0500 Subject: [PATCH 22/61] set Qt::ElideLeft for dropdowns --- src/courtroom.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index e506395..91ddee4 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -171,17 +171,21 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() initialize_emotes(); ui_pos_dropdown = new QComboBox(this); + ui_pos_dropdown->view()->setTextElideMode(Qt::ElideLeft); ui_pos_remove = new AOButton(this, ao_app); ui_iniswap_dropdown = new QComboBox(this); ui_iniswap_dropdown->setContextMenuPolicy(Qt::CustomContextMenu); + ui_iniswap_dropdown->view()->setTextElideMode(Qt::ElideLeft); ui_iniswap_remove = new AOButton(this, ao_app); ui_sfx_dropdown = new QComboBox(this); ui_sfx_dropdown->setContextMenuPolicy(Qt::CustomContextMenu); + ui_sfx_dropdown->view()->setTextElideMode(Qt::ElideLeft); ui_sfx_remove = new AOButton(this, ao_app); ui_effects_dropdown = new QComboBox(this); + ui_effects_dropdown->view()->setTextElideMode(Qt::ElideLeft); ui_effects_dropdown->setContextMenuPolicy(Qt::CustomContextMenu); ui_defense_bar = new AOImage(this, ao_app); From c82dc8dec7f41d91792de8ac8a69548a1266e66c Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Sat, 3 Apr 2021 15:27:46 -0500 Subject: [PATCH 23/61] move code outside if/else block (#518) --- src/courtroom.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 494d69f..e5318b9 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -2552,19 +2552,6 @@ void Courtroom::initialize_chatbox() if (!ui_vp_chatbox->set_image("chat", p_misc)) ui_vp_chatbox->set_image("chatbox", p_misc); - // This should probably be called only if any change from the last chat - // arrow was actually detected. - pos_size_type design_ini_result = ao_app->get_element_dimensions( - "chat_arrow", "courtroom_design.ini", p_misc); - if (design_ini_result.width < 0 || design_ini_result.height < 0) { - qDebug() << "W: could not find \"chat_arrow\" in courtroom_design.ini"; - ui_vp_chat_arrow->hide(); - } - else { - ui_vp_chat_arrow->move(design_ini_result.x + ui_vp_chatbox->x(), design_ini_result.y + ui_vp_chatbox->y()); - ui_vp_chat_arrow->combo_resize(design_ini_result.width, - design_ini_result.height); - } // Remember to set the showname font before the font metrics check. set_font(ui_vp_showname, "", "showname", customchar); @@ -2620,6 +2607,20 @@ void Courtroom::initialize_chatbox() } } + // This should probably be called only if any change from the last chat + // arrow was actually detected. + pos_size_type design_ini_result = ao_app->get_element_dimensions( + "chat_arrow", "courtroom_design.ini", p_misc); + if (design_ini_result.width < 0 || design_ini_result.height < 0) { + qDebug() << "W: could not find \"chat_arrow\" in courtroom_design.ini"; + ui_vp_chat_arrow->hide(); + } + else { + ui_vp_chat_arrow->move(design_ini_result.x + ui_vp_chatbox->x(), design_ini_result.y + ui_vp_chatbox->y()); + ui_vp_chat_arrow->combo_resize(design_ini_result.width, + design_ini_result.height); + } + QString font_name; QString chatfont = ao_app->get_chat_font(m_chatmessage[CHAR_NAME]); if (chatfont != "") From 132bf9b9d93071b7f4b3bc04d3d29ef50cb1162b Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 7 Apr 2021 02:09:41 +0300 Subject: [PATCH 24/61] Don't generate QMovie() at all if we're told we're a static AOImage --- src/aoimage.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/aoimage.cpp b/src/aoimage.cpp index 142189c..6f1b84f 100644 --- a/src/aoimage.cpp +++ b/src/aoimage.cpp @@ -8,15 +8,18 @@ AOImage::AOImage(QWidget *parent, AOApplication *p_ao_app, bool make_static) : Q { m_parent = parent; ao_app = p_ao_app; - movie = new QMovie(); is_static = make_static; - connect(movie, &QMovie::frameChanged, [=]{ - QPixmap f_pixmap = movie->currentPixmap(); - f_pixmap = - f_pixmap.scaled(this->size(), Qt::IgnoreAspectRatio); - this->setPixmap(f_pixmap); - this->setMask(f_pixmap.mask()); - }); + if (!is_static) // Only create the QMovie if we're non-static + { + movie = new QMovie(); + connect(movie, &QMovie::frameChanged, [=]{ + QPixmap f_pixmap = movie->currentPixmap(); + f_pixmap = + f_pixmap.scaled(this->size(), Qt::IgnoreAspectRatio); + this->setPixmap(f_pixmap); + this->setMask(f_pixmap.mask()); + }); + } } AOImage::~AOImage() {} @@ -36,12 +39,14 @@ bool AOImage::set_image(QString p_path, QString p_misc) return false; } path = p_path; - movie->stop(); - movie->setFileName(path); - if (ao_app->get_animated_theme() && movie->frameCount() > 1) { - movie->start(); + if (!is_static) { + movie->stop(); + movie->setFileName(path); + if (ao_app->get_animated_theme() && movie->frameCount() > 1) { + movie->start(); + } } - else { + if (is_static || !ao_app->get_animated_theme() || movie->frameCount() <= 1) { QPixmap f_pixmap(path); f_pixmap = From d5c1273518a2eccbeff87d0c5dafa52885a1af2b Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 7 Apr 2021 15:25:18 +0300 Subject: [PATCH 25/61] Fix demos incorrectly saving the packets (breaking encoding for things such as evidence by recording instead of &) ACTUALLY fix encoding errors, stop supporting the absolutely bonkers exceptions just to support the previous bug instead of fixing the root issue --- src/packet_distribution.cpp | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index 0a99b9d..a3b12c8 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -121,6 +121,7 @@ void AOApplication::append_to_demofile(QString packet_string) void AOApplication::server_packet_received(AOPacket *p_packet) { QStringList f_contents_encoded = p_packet->get_contents(); + QString f_packet_encoded = p_packet->to_string(); p_packet->net_decode(); QString header = p_packet->get_header(); @@ -182,7 +183,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_courtroom->append_server_chatmessage(f_contents.at(0), f_contents.at(1), "0"); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } } else if (header == "FL") { @@ -368,7 +369,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) } send_server_packet(new AOPacket("RM#%")); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } else if (header == "SM") { if (!courtroom_constructed || courtroom_loaded) @@ -471,7 +472,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) 2) // We have a pos included in the background packet! w_courtroom->set_side(f_contents.at(1)); w_courtroom->set_background(f_contents.at(0), f_contents.size() >= 2); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } } else if (header == "SP") { @@ -481,7 +482,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) if (courtroom_constructed) // We were sent a "set position" packet { w_courtroom->set_side(f_contents.at(0)); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } } else if (header == "SD") // Send pos dropdown @@ -507,14 +508,14 @@ void AOApplication::server_packet_received(AOPacket *p_packet) if (courtroom_constructed && courtroom_loaded) { w_courtroom->chatmessage_enqueue(p_packet->get_contents()); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } } else if (header == "MC") { if (courtroom_constructed && courtroom_loaded) { w_courtroom->handle_song(&p_packet->get_contents()); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } } else if (header == "RT") { @@ -525,7 +526,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_courtroom->handle_wtce(f_contents.at(0), 0); else if (f_contents.size() == 2) { w_courtroom->handle_wtce(f_contents.at(0), f_contents.at(1).toInt()); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } } } @@ -534,7 +535,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) { w_courtroom->set_hp_bar(f_contents.at(0).toInt(), f_contents.at(1).toInt()); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } } else if (header == "LE") { @@ -542,11 +543,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) QVector f_evi_list; for (QString f_string : f_contents_encoded) { - QStringList sub_contents; - if (f_contents_encoded.contains("&")) - sub_contents = f_string.split("&"); - else - sub_contents = f_string.split(""); // demos incorrectly encode the separator so we have to account for that + QStringList sub_contents = f_string.split("&"); if (sub_contents.size() < 3) continue; @@ -564,7 +561,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) } w_courtroom->set_evidence_list(f_evi_list); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } } else if (header == "ARUP") { @@ -669,7 +666,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_courtroom->set_clock_visibility(id, true); else if (type == 3) w_courtroom->set_clock_visibility(id, false); - append_to_demofile(p_packet->to_string(true)); + append_to_demofile(f_packet_encoded); } else if (header == "CHECK") { if (!courtroom_constructed) From 33cf6dea262188ae7d9ca198ff4f3837234b8952 Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Sun, 11 Apr 2021 15:36:32 -0500 Subject: [PATCH 26/61] Send "CC" packet when selecting "Spectator" from the character selection screen (#511) If n_char is -1, don't wait for a server response. --- src/charselect.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/charselect.cpp b/src/charselect.cpp index 510d8c0..d35f0ca 100644 --- a/src/charselect.cpp +++ b/src/charselect.cpp @@ -168,14 +168,14 @@ void Courtroom::char_clicked(int n_char) } } - if (n_char != m_cid) { + if (n_char != m_cid || n_char == -1) { ao_app->send_server_packet( new AOPacket("PW#" + ui_char_password->text() + "#%")); ao_app->send_server_packet( new AOPacket("CC#" + QString::number(ao_app->s_pv) + "#" + QString::number(n_char) + "#" + get_hdid() + "#%")); } - else { + if (n_char == m_cid || n_char == -1) { update_character(n_char); enter_courtroom(); set_courtroom_size(); From a5e1cc41733859e4d5aa79a56b3b0cc887b6fdb6 Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Fri, 16 Apr 2021 00:42:43 -0500 Subject: [PATCH 27/61] Fix CASEA failing to validate packets with exactly six arguments (#521) --- src/packet_distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index a3b12c8..cf51002 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -616,7 +616,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_courtroom->mod_called(f_contents.at(0)); } else if (header == "CASEA") { - if (courtroom_constructed && f_contents.size() > 6) + if (courtroom_constructed && f_contents.size() >= 6) w_courtroom->case_called(f_contents.at(0), f_contents.at(1) == "1", f_contents.at(2) == "1", f_contents.at(3) == "1", f_contents.at(4) == "1", From 9b8945f21ae08dc3fff59775d735573a60d9ec4f Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Mon, 19 Apr 2021 00:45:11 -0500 Subject: [PATCH 28/61] Fix character-specific color list not being properly regenerated on a theme reload (#525) --- src/courtroom.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index e5318b9..7ea39df 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -5258,6 +5258,7 @@ void Courtroom::on_reload_theme_clicked() set_widgets(); update_character(m_cid); enter_courtroom(); + gen_char_rgb_list(ao_app->get_chat(current_char)); anim_state = 4; text_state = 3; From 79d1abb48ecaa68940d5c72f34e67c9b97f25bfb Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Mon, 19 Apr 2021 23:08:20 +0300 Subject: [PATCH 29/61] Add a /reload command that quickly reloads the current demo --- src/demoserver.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/demoserver.cpp b/src/demoserver.cpp index 764cf22..866f32d 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -220,6 +220,12 @@ void DemoServer::handle_packet(AOPacket packet) client_sock->write(packet.toUtf8()); } } + else if (contents[1].startsWith("/reload")) + { + load_demo(p_path); + QString packet = "CT#DEMO#" + tr("Current demo file reloaded. Send /play or > in OOC to begin playback.") + "#1#%"; + client_sock->write(packet.toUtf8()); + } else if (contents[1].startsWith("/min_wait")) { QString packet = "CT#DEMO#" + tr("min_wait is deprecated. Use the client Settings for minimum wait instead!") + "#1#%"; @@ -227,7 +233,7 @@ void DemoServer::handle_packet(AOPacket packet) } else if (contents[1].startsWith("/help")) { - QString packet = "CT#DEMO#" + tr("Available commands:\nload, play, pause, max_wait, help") + "#1#%"; + QString packet = "CT#DEMO#" + tr("Available commands:\nload, reload, play, pause, max_wait, help") + "#1#%"; client_sock->write(packet.toUtf8()); } } From 97ea1a6ad419790279d1730bf33b740c66269f73 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Mon, 19 Apr 2021 23:11:17 +0300 Subject: [PATCH 30/61] Fix potential memory leak due to QMovie not being parented to anything --- src/aoimage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aoimage.cpp b/src/aoimage.cpp index 6f1b84f..656528e 100644 --- a/src/aoimage.cpp +++ b/src/aoimage.cpp @@ -11,7 +11,7 @@ AOImage::AOImage(QWidget *parent, AOApplication *p_ao_app, bool make_static) : Q is_static = make_static; if (!is_static) // Only create the QMovie if we're non-static { - movie = new QMovie(); + movie = new QMovie(this); connect(movie, &QMovie::frameChanged, [=]{ QPixmap f_pixmap = movie->currentPixmap(); f_pixmap = From 8f0913d30e5ed1cd6a9ee5f7f8b82d68f7630395 Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Mon, 19 Apr 2021 15:18:39 -0500 Subject: [PATCH 31/61] euthanize morton (#522) --- src/courtroom.cpp | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 7ea39df..8ffd2b5 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3891,14 +3891,8 @@ void Courtroom::case_called(QString msg, bool def, bool pro, bool jud, bool jur, { if (ui_casing->isChecked()) { ui_server_chatlog->append(msg); - if ((ao_app->get_casing_defence_enabled() && def) || - (ao_app->get_casing_prosecution_enabled() && pro) || - (ao_app->get_casing_judge_enabled() && jud) || - (ao_app->get_casing_juror_enabled() && jur) || - (ao_app->get_casing_steno_enabled() && steno)) { - modcall_player->play(ao_app->get_court_sfx("case_call")); - ao_app->alert(this); - } + modcall_player->play(ao_app->get_court_sfx("case_call")); + ao_app->alert(this); } } From 9a20143e222cab8ddce8d0f8e47421e4805b285e Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Tue, 20 Apr 2021 00:24:14 +0300 Subject: [PATCH 32/61] Fix ~~, ~> and <> breaking tick pos --- src/courtroom.cpp | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 8ffd2b5..3950cb6 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3361,21 +3361,8 @@ void Courtroom::chat_tick() // Alignment characters if (tick_pos < 2) { - if (f_rest.startsWith("~~")) { - tick_pos = f_rest.indexOf("~~"); - f_rest.remove(tick_pos, 2); + if (f_rest.startsWith("~~") || f_rest.startsWith("~>") || f_rest.startsWith("<>")) tick_pos += 2; - } - else if (f_rest.startsWith("~>")) { - tick_pos = f_rest.indexOf("~>"); - f_rest.remove(tick_pos, 2); - tick_pos += 2; - } - else if (f_rest.startsWith("<>")) { - tick_pos = f_rest.indexOf("<>"); - f_rest.remove(tick_pos, 2); - tick_pos += 2; - } } f_rest.remove(0, tick_pos); QTextBoundaryFinder tbf(QTextBoundaryFinder::Grapheme, f_rest); From e36ac916a96a285e20e0f31308e52b97a595f92a Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Tue, 20 Apr 2021 02:36:15 +0300 Subject: [PATCH 33/61] Fix anim_state deciding whether you're allowed to send a message or not (the only thing that should decide that is if text is done processing or not) Fix objections forcing a missingno to appear when you object to someone mid-preanim, and their preanim ends before objection shout finishes. This also resolves a crapton of other bugs related to preanim_done() signal. Move evidence display from handle_ic_speaking to start_chat_ticking (makes more sense over here) Remove a misplaced set_static_duration for ui_vp_player_char (must've got here over a strange merge conflict or smth) Remove useless anim_state and text_state setters in reload_theme func, the func that calls the BG to display already handles everything needed for IC reset --- src/courtroom.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 8ffd2b5..9fe8441 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1667,7 +1667,7 @@ void Courtroom::on_chat_return_pressed() if (is_muted) return; - if ((anim_state < 3 || text_state < 2) && objection_state == 0) + if (text_state < 2 && objection_state == 0) return; ui_ic_chat_message->blockSignals(true); @@ -2186,8 +2186,6 @@ bool Courtroom::handle_objection() objection_mod = m_chatmessage[OBJECTION_MOD].toInt(); } - - // if an objection is used if (objection_mod <= 4 && objection_mod >= 1) { ui_vp_objection->set_static_duration(shout_static_time); @@ -2523,7 +2521,6 @@ void Courtroom::initialize_chatbox() if (f_charid >= 0 && f_charid < char_list.size() && (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) { QString real_name = char_list.at(f_charid).name; - ui_vp_player_char->set_static_duration(0); QString f_showname = ao_app->get_showname(real_name); ui_vp_showname->setText(f_showname); @@ -2671,8 +2668,6 @@ void Courtroom::display_evidence_image() void Courtroom::handle_ic_speaking() { - // Display the evidence - display_evidence_image(); QString side = m_chatmessage[SIDE]; int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); // emote_mod 5 is zoom and emote_mod 6 is zoom w/ preanim. @@ -3182,6 +3177,9 @@ void Courtroom::play_preanim(bool immediate) void Courtroom::preanim_done() { + // Currently, someone's talking over us mid-preanim... + if (anim_state != 1 && anim_state != 4) + return; anim_state = 1; switch(m_chatmessage[DESK_MOD].toInt()) { case 4: @@ -3211,6 +3209,9 @@ void Courtroom::start_chat_ticking() if (text_state != 0) return; + // Display the evidence + display_evidence_image(); + if (m_chatmessage[EFFECTS] != "") { QStringList fx_list = m_chatmessage[EFFECTS].split("|"); QString fx = fx_list[0]; @@ -5254,8 +5255,6 @@ void Courtroom::on_reload_theme_clicked() enter_courtroom(); gen_char_rgb_list(ao_app->get_chat(current_char)); - anim_state = 4; - text_state = 3; objection_custom = ""; // to update status on the background From 1edb5d9ae199d7b4512b862e994e4f5b89decb7c Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Tue, 20 Apr 2021 02:38:42 +0300 Subject: [PATCH 34/61] Add support for narrator chat (??!!) which does not affect the state of IC in any way, rather the only thing it affects is the IC chat box. INSANELY useful for GMs to play sound effects, talk over the situation, etc. without causing the IC viewport to reset. Stress-tested with preanims, non-interrupting preanims, idle chat, talking chat, evidence presenting --- src/courtroom.cpp | 125 ++++++++++++++++++++++++++-------------------- 1 file changed, 71 insertions(+), 54 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 9fe8441..2314c99 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -2231,6 +2231,7 @@ bool Courtroom::handle_objection() sfx_player->clear(); // Objection played! Cut all sfx. return true; } + if (m_chatmessage[EMOTE] != "") display_character(); return false; } @@ -2389,22 +2390,31 @@ void Courtroom::handle_ic_message() // Update the chatbox information initialize_chatbox(); - // Display our own character - display_character(); - - // Reset the pair character - ui_vp_sideplayer_char->stop(); - ui_vp_sideplayer_char->move(0, 0); - - // If the emote_mod is not zooming int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); - if (emote_mod != 5 && emote_mod != 6) { - // Display the pair character - display_pair_character(m_chatmessage[OTHER_CHARID], m_chatmessage[OTHER_OFFSET]); - } + bool immediate = m_chatmessage[IMMEDIATE].toInt() == 1; + if (m_chatmessage[EMOTE] != "") { + // Display our own character + display_character(); - // Parse the emote_mod part of the chat message - handle_emote_mod(m_chatmessage[EMOTE_MOD].toInt(), m_chatmessage[IMMEDIATE].toInt() == 1); + // Reset the pair character + ui_vp_sideplayer_char->stop(); + ui_vp_sideplayer_char->move(0, 0); + + // If the emote_mod is not zooming + if (emote_mod != 5 && emote_mod != 6) { + // Display the pair character + display_pair_character(m_chatmessage[OTHER_CHARID], m_chatmessage[OTHER_OFFSET]); + } + + // Parse the emote_mod part of the chat message + handle_emote_mod(emote_mod, immediate); + } + else + { + start_chat_ticking(); + if (emote_mod == 1 || emote_mod == 2 || emote_mod == 6 || immediate) + play_sfx(); + } // if we have instant objections disabled, and queue is not empty, check if next message after this is an objection. if (!ao_app->is_instant_objection_enabled() && chatmessage_queue.size() > 0) @@ -3300,26 +3310,31 @@ void Courtroom::chat_tick() if (tick_pos >= f_message.size()) { text_state = 2; - if (anim_state < 3) { - QStringList c_paths = { - ao_app->get_image_suffix(ao_app->get_character_path(m_chatmessage[CHAR_NAME], "(c)" + m_chatmessage[EMOTE])), - ao_app->get_image_suffix(ao_app->get_character_path(m_chatmessage[CHAR_NAME], "(c)/" + m_chatmessage[EMOTE])) - }; - // if there is a (c) animation for this emote and we haven't played it already - if (file_exists(ui_vp_player_char->find_image(c_paths)) &&(!c_played)) { - anim_state = 5; - ui_vp_player_char->set_play_once(true); - filename = "(c)" + m_chatmessage[EMOTE]; - c_played = true; + // Check if we're a narrator msg + if (m_chatmessage[EMOTE] != "") { + if (anim_state < 3) { + QStringList c_paths = { + ao_app->get_image_suffix(ao_app->get_character_path(m_chatmessage[CHAR_NAME], "(c)" + m_chatmessage[EMOTE])), + ao_app->get_image_suffix(ao_app->get_character_path(m_chatmessage[CHAR_NAME], "(c)/" + m_chatmessage[EMOTE])) + }; + // if there is a (c) animation for this emote and we haven't played it already + if (file_exists(ui_vp_player_char->find_image(c_paths)) &&(!c_played)) { + anim_state = 5; + ui_vp_player_char->set_play_once(true); + filename = "(c)" + m_chatmessage[EMOTE]; + c_played = true; + } + else { + anim_state = 3; + ui_vp_player_char->set_play_once(false); + filename = "(a)" + m_chatmessage[EMOTE]; + } + ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0, + false); } - else { - anim_state = 3; - ui_vp_player_char->set_play_once(false); - filename = "(a)" + m_chatmessage[EMOTE]; - } - ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0, - false); } + else // We're a narrator msg + anim_state = 3; QString f_char; QString f_custom_theme; if (ao_app->is_customchat_enabled()) { @@ -3520,28 +3535,30 @@ void Courtroom::chat_tick() msg_delay = qMin(max_delay, msg_delay * punctuation_modifier); } - // If this color is talking - if (color_is_talking && anim_state != 2 && - anim_state < - 4) // Set it to talking as we're not on that already (though we have - // to avoid interrupting a non-interrupted preanim) - { - ui_vp_player_char->stop(); - ui_vp_player_char->set_play_once(false); - filename = "(b)" + m_chatmessage[EMOTE]; - ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0, - false); - anim_state = 2; - } - else if (!color_is_talking && anim_state < 3 && - anim_state != 3) // Set it to idle as we're not on that already - { - ui_vp_player_char->stop(); - ui_vp_player_char->set_play_once(false); - filename = "(a)" + m_chatmessage[EMOTE]; - ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0, - false); - anim_state = 3; + if (m_chatmessage[EMOTE] != "") { + // If this color is talking + if (color_is_talking && anim_state != 2 && + anim_state < + 4) // Set it to talking as we're not on that already (though we have + // to avoid interrupting a non-interrupted preanim) + { + ui_vp_player_char->stop(); + ui_vp_player_char->set_play_once(false); + filename = "(b)" + m_chatmessage[EMOTE]; + ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0, + false); + anim_state = 2; + } + else if (!color_is_talking && anim_state < 3 && + anim_state != 3) // Set it to idle as we're not on that already + { + ui_vp_player_char->stop(); + ui_vp_player_char->set_play_once(false); + filename = "(a)" + m_chatmessage[EMOTE]; + ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0, + false); + anim_state = 3; + } } // Continue ticking chat_tick_timer->start(msg_delay); From a1abe8abfa9aaf6ff0fbb7197555d1c97f6b5cdd Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Tue, 20 Apr 2021 02:50:42 +0300 Subject: [PATCH 35/61] Fix blankposting when narrating not hiding the chatbox Fix using objections against talking players not causing them to stop talking (with this method, they will only finish their current animation cycle unitl freezing in place) --- src/courtroom.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 2314c99..a29788a 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -2229,6 +2229,7 @@ bool Courtroom::handle_objection() filename, m_chatmessage[CHAR_NAME], ao_app->get_chat(m_chatmessage[CHAR_NAME])); sfx_player->clear(); // Objection played! Cut all sfx. + ui_vp_player_char->set_play_once(true); return true; } if (m_chatmessage[EMOTE] != "") @@ -3253,6 +3254,10 @@ void Courtroom::start_chat_ticking() ui_vp_chatbox->show(); ui_vp_message->show(); } + else { + ui_vp_chatbox->hide(); + ui_vp_message->hide(); + } // If we're not already waiting on the next message, start the timer. We could be overriden if there's an objection planned. int delay = ao_app->stay_time(); if (delay > 0 && !text_queue_timer->isActive()) From e517a365d59a46f213e5f053404ecb1904f63ab6 Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Mon, 19 Apr 2021 19:27:25 -0500 Subject: [PATCH 36/61] don't set a mask on elements affected by offsets (#524) --- include/aolayer.h | 1 + src/aolayer.cpp | 7 ++++--- src/courtroom.cpp | 2 ++ 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/aolayer.h b/include/aolayer.h index 1984b77..f42642c 100644 --- a/include/aolayer.h +++ b/include/aolayer.h @@ -52,6 +52,7 @@ public: bool force_continuous = false; Qt::TransformationMode transform_mode = Qt::FastTransformation; // transformation mode to use for this image bool stretch = false; // Should we stretch/squash this image to fill the screen? + bool masked = true; // Set a mask to the dimensions of the widget? // Set the movie's image to provided paths, preparing for playback. void start_playback(QString p_image); diff --git a/src/aolayer.cpp b/src/aolayer.cpp index 18213ce..e4db75a 100644 --- a/src/aolayer.cpp +++ b/src/aolayer.cpp @@ -98,9 +98,10 @@ void AOLayer::center_pixmap(QPixmap f_pixmap) { x + (f_w - f_pixmap.width()) / 2, y + (f_h - f_pixmap.height())); // Always center horizontally, always put // at the bottom vertically - this->setMask( - QRegion((f_pixmap.width() - f_w) / 2, (f_pixmap.height() - f_h) / 2, f_w, - f_h)); // make sure we don't escape the area we've been given + if (masked) + this->setMask( + QRegion((f_pixmap.width() - f_w) / 2, (f_pixmap.height() - f_h) / 2, f_w, + f_h)); // make sure we don't escape the area we've been given } void AOLayer::combo_resize(int w, int h) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 8ffd2b5..aafc16d 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -46,7 +46,9 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_vp_background = new BackgroundLayer(ui_viewport, ao_app); ui_vp_speedlines = new SplashLayer(ui_viewport, ao_app); ui_vp_player_char = new CharLayer(ui_viewport, ao_app); + ui_vp_player_char->masked = false; ui_vp_sideplayer_char = new CharLayer(ui_viewport, ao_app); + ui_vp_sideplayer_char->masked = false; ui_vp_sideplayer_char->hide(); ui_vp_desk = new BackgroundLayer(ui_viewport, ao_app); From 81c0f9a569eaee58a28ca521b15ab397c03a4890 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Tue, 20 Apr 2021 08:13:56 +0300 Subject: [PATCH 37/61] Better logs with OOC logging, [IC] and [OOC] tags (#519) * Add OOC logging to the .log files, making them infinitely more precious to GMs especially of ambitious multi-area RPs Add [IC] and [OOC] tags to distinguish between the types of msg * minor wording change for .log top line to make it clearer that it's the server address and not the user address Co-authored-by: oldmud0 --- src/courtroom.cpp | 5 +++++ src/packet_distribution.cpp | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index fd0e1ca..9a6fd08 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1647,6 +1647,11 @@ void Courtroom::append_server_chatmessage(QString p_name, QString p_message, ui_server_chatlog->append_chatmessage(p_name, p_message, color); + + if (ao_app->get_auto_logging_enabled() && !ao_app->log_filename.isEmpty()) { + QString full = "[OOC][" + QDateTime::currentDateTime().toUTC().toString() + "] " + p_name + ": " + p_message; + ao_app->append_to_file(full, ao_app->log_filename, true); + } } void Courtroom::on_authentication_state_received(int p_state) diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index cf51002..dc76ec1 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -308,7 +308,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) this->log_filename = QDateTime::currentDateTime().toUTC().toString( "'logs/" + server_name.remove(QRegExp("[\\\\/:*?\"<>|\']")) + "/'yyyy-MM-dd hh-mm-ss t'.log'"); - this->write_to_file("Joined server " + server_name + " on address " + + this->write_to_file("Joined server " + server_name + " hosted on address " + server_address + " on " + QDateTime::currentDateTime().toUTC().toString(), log_filename, true); From 86b342badcbf15469fc827a7fbec5baf8be8fa30 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Tue, 20 Apr 2021 15:08:24 +0300 Subject: [PATCH 38/61] Reset timers, evidence list and background whenever /load or /reload is used --- src/demoserver.cpp | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/demoserver.cpp b/src/demoserver.cpp index 866f32d..8b82d75 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -162,6 +162,23 @@ void DemoServer::handle_packet(AOPacket packet) load_demo(path); QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%"; client_sock->write(packet.toUtf8()); + // Reset evidence list + client_sock->write("LE##%"); + // Reset timers + client_sock->write("TI#0#3#0#%"); + client_sock->write("TI#0#1#0#%"); + client_sock->write("TI#1#1#0#%"); + client_sock->write("TI#1#3#0#%"); + client_sock->write("TI#2#1#0#%"); + client_sock->write("TI#2#3#0#%"); + client_sock->write("TI#3#1#0#%"); + client_sock->write("TI#3#3#0#%"); + client_sock->write("TI#4#1#0#%"); + client_sock->write("TI#4#3#0#%"); + // Set the BG to default (also breaks up the message queue) + client_sock->write("BN#default#wit#%"); + // Stop the wait packet timer + timer->stop(); } else if (contents[1].startsWith("/play") || contents[1] == ">") { @@ -225,6 +242,23 @@ void DemoServer::handle_packet(AOPacket packet) load_demo(p_path); QString packet = "CT#DEMO#" + tr("Current demo file reloaded. Send /play or > in OOC to begin playback.") + "#1#%"; client_sock->write(packet.toUtf8()); + // Reset evidence list + client_sock->write("LE##%"); + // Reset timers + client_sock->write("TI#0#3#0#%"); + client_sock->write("TI#0#1#0#%"); + client_sock->write("TI#1#1#0#%"); + client_sock->write("TI#1#3#0#%"); + client_sock->write("TI#2#1#0#%"); + client_sock->write("TI#2#3#0#%"); + client_sock->write("TI#3#1#0#%"); + client_sock->write("TI#3#3#0#%"); + client_sock->write("TI#4#1#0#%"); + client_sock->write("TI#4#3#0#%"); + // Set the BG to default (also breaks up the message queue) + client_sock->write("BN#default#wit#%"); + // Stop the wait packet timer + timer->stop(); } else if (contents[1].startsWith("/min_wait")) { @@ -245,8 +279,11 @@ void DemoServer::load_demo(QString filename) demo_file.open(QIODevice::ReadOnly); if (!demo_file.isOpen()) return; + // Clear demo data demo_data.clear(); + // Set the demo filepath p_path = filename; + // Process the demo file QTextStream demo_stream(&demo_file); demo_stream.setCodec("UTF-8"); QString line = demo_stream.readLine(); From 7b058d1401ddc1721304516f5cc7cdbdb15fee5d Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 21 Apr 2021 02:14:49 +0300 Subject: [PATCH 39/61] Fix last line in the .demo file not being processed Fix timings for OOC being really busted if max_wait is -1 (dunno at which point this bug was introduced) --- src/demoserver.cpp | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/demoserver.cpp b/src/demoserver.cpp index 764cf22..09741fd 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -264,22 +264,26 @@ void DemoServer::playback() if (current_packet.startsWith("MS#")) elapsed_time = 0; - while (!current_packet.startsWith("wait") && !demo_data.isEmpty()) { + while (!current_packet.startsWith("wait#")) { client_sock->write(current_packet.toUtf8()); + if (demo_data.isEmpty()) + break; current_packet = demo_data.dequeue(); } if (!demo_data.isEmpty()) { AOPacket wait_packet = AOPacket(current_packet); int duration = wait_packet.get_contents().at(0).toInt(); - if (max_wait != -1 && duration + elapsed_time > max_wait) { - duration = qMax(0, max_wait - elapsed_time); - // Skip the difference on the timers - emit skip_timers(wait_packet.get_contents().at(0).toInt() - duration); - } - else if (timer->interval() != 0 && duration + elapsed_time > timer->interval()) { - duration = qMax(0, timer->interval() - elapsed_time); + if (max_wait != -1) { + if (duration + elapsed_time > max_wait) { + duration = qMax(0, max_wait - elapsed_time); + // Skip the difference on the timers emit skip_timers(wait_packet.get_contents().at(0).toInt() - duration); + } + else if (timer->interval() != 0 && duration + elapsed_time > timer->interval()) { + duration = qMax(0, timer->interval() - elapsed_time); + emit skip_timers(wait_packet.get_contents().at(0).toInt() - duration); + } } elapsed_time += duration; timer->start(duration); From fb4a5e0656cf1ad023b761139f30ecf3a584f56e Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Wed, 21 Apr 2021 02:54:08 +0300 Subject: [PATCH 40/61] Fix log_chatmessage referring to the global m_chatmessage instead of the local variables that should be sent to it at the point of the func being called. (#530) --- include/courtroom.h | 2 +- src/courtroom.cpp | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/include/courtroom.h b/include/courtroom.h index 7e31b73..9da465a 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -235,7 +235,7 @@ public: DISPLAY_AND_IO }; // Log the message contents and information such as evidence presenting etc. into the log file, the IC log, or both. - void log_chatmessage(QString f_message, int f_char_id, QString f_showname = "", int f_color = 0, LogMode f_log_mode=IO_ONLY); + void log_chatmessage(QString f_message, int f_char_id, QString f_showname = "", QString f_char = "", QString f_objection_mod = "", int f_evi_id = 0, int f_color = 0, LogMode f_log_mode=IO_ONLY); // Log the message contents and information such as evidence presenting etc. into the IC logs void handle_callwords(); diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 8a346a2..776c0c9 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -1984,7 +1984,7 @@ void Courtroom::chatmessage_enqueue(QStringList p_contents) if (SHOWNAME < p_contents.size()) showname = p_contents[SHOWNAME]; - log_chatmessage(p_contents[MESSAGE], f_char_id, showname, p_contents[TEXT_COLOR].toInt(), log_mode); + log_chatmessage(p_contents[MESSAGE], f_char_id, showname, p_contents[CHAR_NAME], p_contents[OBJECTION_MOD], p_contents[EVIDENCE_ID].toInt(), p_contents[TEXT_COLOR].toInt(), log_mode); // Send this boi into the queue chatmessage_queue.enqueue(p_contents); @@ -2018,7 +2018,7 @@ void Courtroom::skip_chatmessage_queue() while (!chatmessage_queue.isEmpty()) { QStringList p_contents = chatmessage_queue.dequeue(); - log_chatmessage(p_contents[MESSAGE], p_contents[CHAR_ID].toInt(), p_contents[SHOWNAME], p_contents[TEXT_COLOR].toInt(), DISPLAY_ONLY); + log_chatmessage(p_contents[MESSAGE], p_contents[CHAR_ID].toInt(), p_contents[SHOWNAME], p_contents[CHAR_NAME], p_contents[OBJECTION_MOD], p_contents[EVIDENCE_ID].toInt(), p_contents[TEXT_COLOR].toInt(), DISPLAY_ONLY); } } @@ -2041,7 +2041,7 @@ void Courtroom::unpack_chatmessage(QStringList p_contents) if (!ao_app->is_desyncrhonized_logs_enabled()) { // We have logs displaying as soon as we reach the message in our queue, which is a less confusing but also less accurate experience for the user. - log_chatmessage(m_chatmessage[MESSAGE], m_chatmessage[CHAR_ID].toInt(), m_chatmessage[SHOWNAME], m_chatmessage[TEXT_COLOR].toInt(), DISPLAY_ONLY); + log_chatmessage(m_chatmessage[MESSAGE], m_chatmessage[CHAR_ID].toInt(), m_chatmessage[SHOWNAME], m_chatmessage[CHAR_NAME], m_chatmessage[OBJECTION_MOD], m_chatmessage[EVIDENCE_ID].toInt(), m_chatmessage[TEXT_COLOR].toInt(), DISPLAY_ONLY); } // Process the callwords for this message @@ -2060,7 +2060,7 @@ void Courtroom::unpack_chatmessage(QStringList p_contents) handle_ic_message(); } -void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_showname, int f_color, LogMode f_log_mode) +void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_showname, QString f_char, QString f_objection_mod, int f_evi_id, int f_color, LogMode f_log_mode) { // Display name will use the showname QString f_displayname = f_showname; @@ -2081,16 +2081,15 @@ void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_show // Check if a custom objection is in use int objection_mod = 0; QString custom_objection = ""; - if (m_chatmessage[OBJECTION_MOD].contains("4&")) { + if (f_objection_mod.contains("4&")) { objection_mod = 4; - custom_objection = m_chatmessage[OBJECTION_MOD].split( + custom_objection = f_objection_mod.split( "4&")[1]; // takes the name of custom objection. } else { - objection_mod = m_chatmessage[OBJECTION_MOD].toInt(); + objection_mod = f_objection_mod.toInt(); } - QString f_char = m_chatmessage[CHAR_NAME]; QString f_custom_theme = ao_app->get_chat(f_char); if (objection_mod <= 4 && objection_mod >= 1) { QString shout_message; @@ -2137,8 +2136,6 @@ void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_show } } - // Obtain evidence ID we're trying to work with - int f_evi_id = m_chatmessage[EVIDENCE_ID].toInt(); // If the evidence ID is in the valid range if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) { // Obtain the evidence name From d2c0c4fa0dfdef2534fcc0826f8c36bc4568a631 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Thu, 22 Apr 2021 19:02:07 +0300 Subject: [PATCH 41/61] Fix charlayer regression not allowing us to *directly* refer to an emote we want to use with a file path (base/misc/blank for example) Actually use the helper funcs for searching images instead of reimplementing the same thing --- src/aolayer.cpp | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/aolayer.cpp b/src/aolayer.cpp index e4db75a..ccf2d63 100644 --- a/src/aolayer.cpp +++ b/src/aolayer.cpp @@ -197,20 +197,20 @@ void CharLayer::load_image(QString p_filename, QString p_charname, << " continuous: " << continuous; #endif QStringList pathlist = { - ao_app->get_image_suffix(ao_app->get_character_path( - p_charname, prefix + current_emote)), // Default path - ao_app->get_image_suffix(ao_app->get_character_path( + current_emote, // The path by itself + ao_app->get_character_path( + p_charname, prefix + current_emote), // Default path + ao_app->get_character_path( p_charname, - prefix + "/" + current_emote)), // Path check if it's categorized + prefix + "/" + current_emote), // Path check if it's categorized // into a folder - ao_app->get_image_suffix(ao_app->get_character_path( + ao_app->get_character_path( p_charname, - current_emote)), // Just use the non-prefixed image, animated or not - ao_app->get_image_suffix( - ao_app->get_theme_path("placeholder")), // Theme placeholder path - ao_app->get_image_suffix(ao_app->get_theme_path( - "placeholder", ao_app->default_theme))}; // Default theme placeholder path - start_playback(find_image(pathlist)); + current_emote), // Just use the non-prefixed image, animated or not + ao_app->get_theme_path("placeholder"), // Theme placeholder path + ao_app->get_theme_path( + "placeholder", ao_app->default_theme)}; // Default theme placeholder path + start_playback(ao_app->get_image_path(pathlist)); } void SplashLayer::load_image(QString p_filename, QString p_charname, From d3e5cb933cd91d5393943ab3385bac0fc233cdc9 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Thu, 22 Apr 2021 19:09:44 +0300 Subject: [PATCH 42/61] Charlayer - only check for direct path after the previous checks fail but before missingno --- src/aolayer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/aolayer.cpp b/src/aolayer.cpp index ccf2d63..795274f 100644 --- a/src/aolayer.cpp +++ b/src/aolayer.cpp @@ -197,7 +197,6 @@ void CharLayer::load_image(QString p_filename, QString p_charname, << " continuous: " << continuous; #endif QStringList pathlist = { - current_emote, // The path by itself ao_app->get_character_path( p_charname, prefix + current_emote), // Default path ao_app->get_character_path( @@ -207,6 +206,7 @@ void CharLayer::load_image(QString p_filename, QString p_charname, ao_app->get_character_path( p_charname, current_emote), // Just use the non-prefixed image, animated or not + current_emote, // The path by itself after the above fail ao_app->get_theme_path("placeholder"), // Theme placeholder path ao_app->get_theme_path( "placeholder", ao_app->default_theme)}; // Default theme placeholder path From 2c259a6337c66eb5900d2c46534c75e9d77586c1 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Thu, 22 Apr 2021 19:11:39 +0300 Subject: [PATCH 43/61] Do the same as previous commit for the get_asset_paths func - only check for the direct file path before missingno --- src/path_functions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/path_functions.cpp b/src/path_functions.cpp index 5107349..79851c1 100644 --- a/src/path_functions.cpp +++ b/src/path_functions.cpp @@ -105,7 +105,6 @@ QString AOApplication::get_evidence_path(QString p_file) QStringList AOApplication::get_asset_paths(QString p_element, QString p_theme, QString p_subtheme, QString p_default_theme, QString p_misc, QString p_character, QString p_placeholder) { QStringList pathlist; - pathlist += p_element; // The path by itself if (p_character != "") pathlist += get_character_path(p_character, p_element); // Character folder if (p_misc != "" && p_theme != "" && p_subtheme != "") @@ -120,6 +119,7 @@ QStringList AOApplication::get_asset_paths(QString p_element, QString p_theme, Q pathlist += get_theme_path(p_element, p_theme); // Theme path if (p_default_theme != "") pathlist += get_theme_path(p_element, p_default_theme); // Default theme path + pathlist += p_element; // The path by itself if (p_placeholder != "" && p_theme != "") pathlist += get_theme_path(p_placeholder, p_theme); // Placeholder path if (p_placeholder != "" && p_default_theme != "") From 43340e88695b2adc7b8fc8141540178727fd8869 Mon Sep 17 00:00:00 2001 From: in1tiate Date: Thu, 22 Apr 2021 23:46:55 -0500 Subject: [PATCH 44/61] move timer reset to its own method --- include/demoserver.h | 1 + src/demoserver.cpp | 38 ++++++++++++++++---------------------- 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/include/demoserver.h b/include/demoserver.h index 3dc645b..0d4f0e4 100644 --- a/include/demoserver.h +++ b/include/demoserver.h @@ -24,6 +24,7 @@ public: private: void handle_packet(AOPacket packet); void load_demo(QString filename); + void reset_all_timers(); QTcpServer* tcp_server; QTcpSocket* client_sock = nullptr; diff --git a/src/demoserver.cpp b/src/demoserver.cpp index 8b82d75..b9721bf 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -164,17 +164,7 @@ void DemoServer::handle_packet(AOPacket packet) client_sock->write(packet.toUtf8()); // Reset evidence list client_sock->write("LE##%"); - // Reset timers - client_sock->write("TI#0#3#0#%"); - client_sock->write("TI#0#1#0#%"); - client_sock->write("TI#1#1#0#%"); - client_sock->write("TI#1#3#0#%"); - client_sock->write("TI#2#1#0#%"); - client_sock->write("TI#2#3#0#%"); - client_sock->write("TI#3#1#0#%"); - client_sock->write("TI#3#3#0#%"); - client_sock->write("TI#4#1#0#%"); - client_sock->write("TI#4#3#0#%"); + reset_all_timers(); // Set the BG to default (also breaks up the message queue) client_sock->write("BN#default#wit#%"); // Stop the wait packet timer @@ -244,17 +234,7 @@ void DemoServer::handle_packet(AOPacket packet) client_sock->write(packet.toUtf8()); // Reset evidence list client_sock->write("LE##%"); - // Reset timers - client_sock->write("TI#0#3#0#%"); - client_sock->write("TI#0#1#0#%"); - client_sock->write("TI#1#1#0#%"); - client_sock->write("TI#1#3#0#%"); - client_sock->write("TI#2#1#0#%"); - client_sock->write("TI#2#3#0#%"); - client_sock->write("TI#3#1#0#%"); - client_sock->write("TI#3#3#0#%"); - client_sock->write("TI#4#1#0#%"); - client_sock->write("TI#4#3#0#%"); + reset_all_timers(); // Set the BG to default (also breaks up the message queue) client_sock->write("BN#default#wit#%"); // Stop the wait packet timer @@ -297,6 +277,20 @@ void DemoServer::load_demo(QString filename) } } +void DemoServer::reset_all_timers() +{ + client_sock->write("TI#0#3#0#%"); + client_sock->write("TI#0#1#0#%"); + client_sock->write("TI#1#1#0#%"); + client_sock->write("TI#1#3#0#%"); + client_sock->write("TI#2#1#0#%"); + client_sock->write("TI#2#3#0#%"); + client_sock->write("TI#3#1#0#%"); + client_sock->write("TI#3#3#0#%"); + client_sock->write("TI#4#1#0#%"); + client_sock->write("TI#4#3#0#%"); +} + void DemoServer::playback() { if (demo_data.isEmpty()) From 9359ed7f54dd996d879e465c87d5b9631bc6d6bb Mon Sep 17 00:00:00 2001 From: in1tiate Date: Fri, 23 Apr 2021 00:30:50 -0500 Subject: [PATCH 45/61] make sure we save the shownames even when theyre disabled --- src/courtroom.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 776c0c9..8bbaaa9 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -2067,11 +2067,6 @@ void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_show if (f_char_id != -1) { // Grab the char.ini showname f_showname = ao_app->get_showname(char_list.at(f_char_id).name); - // If custom serversided shownames are not enabled - if (!ui_showname_enable->isChecked()) { - // Set the display name to the char.ini showname - f_displayname = f_showname; - } } // If display name is just whitespace, use the char.ini showname. if (f_displayname.trimmed().isEmpty()) @@ -2171,6 +2166,8 @@ void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_show append_ic_text(f_message, f_displayname, "",f_color); break; } + if (!ui_showname_enable->isChecked()) + regenerate_ic_chatlog(); } bool Courtroom::handle_objection() From 9fbe899c0e6ff464d91c2b2171eebb8fb879facb Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Fri, 23 Apr 2021 09:55:04 +0300 Subject: [PATCH 46/61] Automatically fix desynced demo files with issues pre-#496 PR (#532) * Implement a demo auto-fixing solution. If the client detects a pre-2.9.1 demo file, it will prompt the user if they wish to correct it, since otherwise the demo will be desynched from reality. The aforementioned issue was fixed in https://github.com/AttorneyOnline/AO2-Client/pull/496 however 2.9.0 still has incorrect demo recording. Fix potential memory leak by not flushing and closing the demo file after opening it for reading. * backup broken demo file before fixing it * comments ahoy Co-authored-by: in1tiate --- include/demoserver.h | 1 + src/demoserver.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/include/demoserver.h b/include/demoserver.h index 3dc645b..f41084e 100644 --- a/include/demoserver.h +++ b/include/demoserver.h @@ -10,6 +10,7 @@ #include #include #include +#include class DemoServer : public QObject { diff --git a/src/demoserver.cpp b/src/demoserver.cpp index 09741fd..d6927a5 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -252,6 +252,56 @@ void DemoServer::load_demo(QString filename) demo_data.enqueue(line); line = demo_stream.readLine(); } + demo_file.flush(); + demo_file.close(); + + // No-shenanigans 2.9.0 demo file with the dreaded demo desync bug detected https://github.com/AttorneyOnline/AO2-Client/pull/496 + // If we don't start with the SC packet this means user-edited weirdo shenanigans. Don't screw around with those. + if (demo_data.head().startsWith("SC#") && demo_data.last().startsWith("wait#")) { + qDebug() << "Loaded a broken pre-2.9.1 demo file, with the wait desync issue!"; + QMessageBox *msgBox = new QMessageBox; + msgBox->setAttribute(Qt::WA_DeleteOnClose); + msgBox->setTextFormat(Qt::RichText); + msgBox->setText("This appears to be a broken pre-2.9.1 demo file with the wait desync issue!
Do you want to correct this file? If you refuse, this demo will be desynchronized!"); + msgBox->setWindowTitle("Pre-2.9.1 demo detected!"); + msgBox->setStandardButtons(QMessageBox::NoButton); + QTimer::singleShot(2000, msgBox, std::bind(&QMessageBox::setStandardButtons,msgBox,QMessageBox::Yes|QMessageBox::No)); + int ret = msgBox->exec(); + QQueue p_demo_data; + switch (ret) { + case QMessageBox::Yes: + qDebug() << "Making a backup of the broken demo..."; + QFile::copy(filename, filename + ".backup"); + while (!demo_data.isEmpty()) { + QString current_packet = demo_data.dequeue(); + // TODO: faster way of doing this, maybe with QtConcurrent's MapReduce methods? + if (!current_packet.startsWith("SC#") && current_packet.startsWith("wait#")) { + p_demo_data.insert(qMax(1, p_demo_data.size()-1), current_packet); + continue; + } + p_demo_data.enqueue(current_packet); + } + if (demo_file.open(QIODevice::WriteOnly | QIODevice::Text | + QIODevice::Truncate)) { + QTextStream out(&demo_file); + out.setCodec("UTF-8"); + out << p_demo_data.dequeue(); + for (QString line : p_demo_data) { + out << "\n" << line; + } + demo_file.flush(); + demo_file.close(); + } + load_demo(filename); + break; + case QMessageBox::No: + // No was clicked + break; + default: + // should never be reached + break; + } + } } void DemoServer::playback() From 66f2369af2c4e15ef3eb605f2eefcbc10b576455 Mon Sep 17 00:00:00 2001 From: in1tiate <32779090+in1tiate@users.noreply.github.com> Date: Fri, 23 Apr 2021 02:18:56 -0500 Subject: [PATCH 47/61] Fix Cyrillic characters not being read correctly from QSettings inis (#535) * set ini codecs to utf8 * fix color config reading in Latin1 rather than Utf8 --- src/path_functions.cpp | 1 + src/text_file_functions.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/path_functions.cpp b/src/path_functions.cpp index 79851c1..dbf1cc4 100644 --- a/src/path_functions.cpp +++ b/src/path_functions.cpp @@ -173,6 +173,7 @@ QString AOApplication::get_config_value(QString p_identifier, QString p_config, p = get_case_sensitive_path(p); if (file_exists(p)) { QSettings settings(p, QSettings::IniFormat); + settings.setIniCodec("UTF-8"); QVariant value = settings.value(p_identifier); if (value.type() == QVariant::StringList) { // qDebug() << "got" << p << "is a string list, returning" << value.toStringList().join(","); diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index a671d61..af4c232 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -277,6 +277,7 @@ QString AOApplication::read_design_ini(QString p_identifier, QString p_design_path) { QSettings settings(p_design_path, QSettings::IniFormat); + settings.setIniCodec("UTF-8"); QVariant value = settings.value(p_identifier); if (value.type() == QVariant::StringList) { return value.toStringList().join(","); @@ -435,7 +436,7 @@ QString AOApplication::get_chat_markup(QString p_identifier, QString p_chat) // New Chadly method QString value = get_config_value(p_identifier, "chat_config.ini", current_theme, get_subtheme(), default_theme, p_chat); if (!value.isEmpty()) - return value.toLatin1(); + return value.toUtf8(); // Backwards ass compatibility QStringList backwards_paths{get_theme_path("misc/" + p_chat + "/config.ini"), @@ -446,7 +447,7 @@ QString AOApplication::get_chat_markup(QString p_identifier, QString p_chat) for (const QString &p : backwards_paths) { QString value = read_design_ini(p_identifier, p); if (!value.isEmpty()) { - return value.toLatin1(); + return value.toUtf8(); } } @@ -521,6 +522,7 @@ QString AOApplication::read_char_ini(QString p_char, QString p_search_line, QSettings settings(get_character_path(p_char, "char.ini"), QSettings::IniFormat); settings.beginGroup(target_tag); + settings.setIniCodec("UTF-8"); QString value = settings.value(p_search_line).value(); settings.endGroup(); return value; @@ -541,6 +543,7 @@ QStringList AOApplication::read_ini_tags(QString p_path, QString target_tag) { QStringList r_values; QSettings settings(p_path, QSettings::IniFormat); + settings.setIniCodec("UTF-8"); if (!target_tag.isEmpty()) settings.beginGroup(target_tag); QStringList keys = settings.allKeys(); From 5fca08537b6f2c6c581156c4dc07bc9ba61b17ef Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Fri, 23 Apr 2021 07:53:59 -0500 Subject: [PATCH 48/61] Update themes submodule (#539) --- base/themes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/themes b/base/themes index c9acb90..7c036c0 160000 --- a/base/themes +++ b/base/themes @@ -1 +1 @@ -Subproject commit c9acb90137361ea8c29bc4cf2bf530d14b52b23a +Subproject commit 7c036c09ddfadc2680a2c5dbfa188dc98142a427 From 31abe0c84845556d038cdd4a67bd871448adffd1 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Fri, 23 Apr 2021 22:17:45 +0300 Subject: [PATCH 49/61] Fix get_court_sfx using latin1 instead of utf-8 (#540) Co-authored-by: in1tiate <32779090+in1tiate@users.noreply.github.com> --- src/text_file_functions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index af4c232..1df1e41 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -477,7 +477,7 @@ QString AOApplication::get_court_sfx(QString p_identifier, QString p_misc) { QString value = get_config_value(p_identifier, "courtroom_sounds.ini", current_theme, get_subtheme(), default_theme, p_misc); if (!value.isEmpty()) - return value.toLatin1(); + return value.toUtf8(); return ""; } From 0a1a47c920a10fe5960f990c48102d8bde08a6fe Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Fri, 23 Apr 2021 22:20:31 +0300 Subject: [PATCH 50/61] Expand .css power by giving object names to all AO UI elements (#534) * Fix ic chatlog placeholder text not being translated * Fix inconsistent/nonsensical path resolution for the backwards-compatibility misc/default/config.ini vs themes/current_theme/misc/default/config.ini Co-authored-by: in1tiate <32779090+in1tiate@users.noreply.github.com> --- src/charselect.cpp | 11 ++++ src/courtroom.cpp | 120 +++++++++++++++++++++++++++++++++--- src/emotes.cpp | 4 ++ src/evidence.cpp | 17 +++++ src/lobby.cpp | 26 ++++++-- src/text_file_functions.cpp | 4 +- 6 files changed, 168 insertions(+), 14 deletions(-) diff --git a/src/charselect.cpp b/src/charselect.cpp index 820abf5..53269b5 100644 --- a/src/charselect.cpp +++ b/src/charselect.cpp @@ -10,6 +10,7 @@ void Courtroom::construct_char_select() this->setWindowFlags( (this->windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowMaximizeButtonHint); ui_char_select_background = new AOImage(this, ao_app); + ui_char_select_background->setObjectName("ui_char_select_background"); ui_char_list = new QTreeWidget(ui_char_select_background); ui_char_list->setColumnCount(2); @@ -18,28 +19,38 @@ void Courtroom::construct_char_select() ui_char_list->header()->setSectionResizeMode(QHeaderView::ResizeToContents); ui_char_list->hideColumn(1); ui_char_list->setDropIndicatorShown(true); + ui_char_list->setObjectName("ui_char_list"); ui_char_buttons = new QWidget(ui_char_select_background); + ui_char_buttons->setObjectName("ui_char_buttons"); ui_back_to_lobby = new AOButton(ui_char_select_background, ao_app); + ui_back_to_lobby->setObjectName("ui_back_to_lobby"); ui_char_password = new QLineEdit(ui_char_select_background); ui_char_password->setPlaceholderText(tr("Password")); + ui_char_password->setObjectName("ui_char_password"); ui_char_select_left = new AOButton(ui_char_select_background, ao_app); + ui_char_select_left->setObjectName("ui_char_select_left"); ui_char_select_right = new AOButton(ui_char_select_background, ao_app); + ui_char_select_right->setObjectName("ui_char_select_right"); ui_spectator = new AOButton(ui_char_select_background, ao_app); ui_spectator->setText(tr("Spectator")); + ui_spectator->setObjectName("ui_spectator"); ui_char_search = new QLineEdit(ui_char_select_background); ui_char_search->setPlaceholderText(tr("Search")); + ui_char_search->setObjectName("ui_char_search"); ui_char_passworded = new QCheckBox(ui_char_select_background); ui_char_passworded->setText(tr("Passworded")); + ui_char_passworded->setObjectName("ui_char_passworded"); ui_char_taken = new QCheckBox(ui_char_select_background); ui_char_taken->setText(tr("Taken")); + ui_char_taken->setObjectName("ui_char_taken"); connect(ui_char_list, SIGNAL(itemDoubleClicked(QTreeWidgetItem *, int)), this, SLOT(on_char_list_double_clicked(QTreeWidgetItem *, int))); diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 8bbaaa9..301b82e 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -41,50 +41,67 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() modcall_player->set_volume(50); ui_background = new AOImage(this, ao_app); + ui_background->setObjectName("ui_background"); ui_viewport = new QWidget(this); + ui_viewport->setObjectName("ui_viewport"); ui_vp_background = new BackgroundLayer(ui_viewport, ao_app); + ui_vp_background->setObjectName("ui_vp_background"); ui_vp_speedlines = new SplashLayer(ui_viewport, ao_app); + ui_vp_speedlines->setObjectName("ui_vp_speedlines"); ui_vp_player_char = new CharLayer(ui_viewport, ao_app); + ui_vp_player_char->setObjectName("ui_vp_player_char"); ui_vp_player_char->masked = false; ui_vp_sideplayer_char = new CharLayer(ui_viewport, ao_app); + ui_vp_sideplayer_char->setObjectName("ui_vp_sideplayer_char"); ui_vp_sideplayer_char->masked = false; ui_vp_sideplayer_char->hide(); ui_vp_desk = new BackgroundLayer(ui_viewport, ao_app); + ui_vp_desk->setObjectName("ui_vp_desk"); ui_vp_effect = new EffectLayer(this, ao_app); ui_vp_effect->setAttribute(Qt::WA_TransparentForMouseEvents); + ui_vp_effect->setObjectName("ui_vp_effect"); ui_vp_evidence_display = new AOEvidenceDisplay(ui_viewport, ao_app); + ui_vp_evidence_display->setObjectName("ui_vp_evidence_display"); ui_vp_chatbox = new AOImage(this, ao_app); + ui_vp_chatbox->setObjectName("ui_vp_chatbox"); ui_vp_showname = new QLabel(ui_vp_chatbox); + ui_vp_showname->setObjectName("ui_vp_showname"); ui_vp_showname->setAlignment(Qt::AlignLeft); ui_vp_chat_arrow = new InterfaceLayer(this, ao_app); ui_vp_chat_arrow->set_play_once(false); + ui_vp_chat_arrow->setObjectName("ui_vp_chat_arrow"); ui_vp_message = new QTextEdit(this); ui_vp_message->setFrameStyle(QFrame::NoFrame); ui_vp_message->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ui_vp_message->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); ui_vp_message->setReadOnly(true); + ui_vp_message->setObjectName("ui_vp_message"); ui_vp_testimony = new SplashLayer(this, ao_app); ui_vp_testimony->set_play_once(false); ui_vp_testimony->setAttribute(Qt::WA_TransparentForMouseEvents); + ui_vp_testimony->setObjectName("ui_vp_testimony"); ui_vp_wtce = new SplashLayer(this, ao_app); ui_vp_wtce->set_play_once(true); ui_vp_wtce->continuous = false; ui_vp_wtce->force_continuous = true; ui_vp_wtce->setAttribute(Qt::WA_TransparentForMouseEvents); + ui_vp_wtce->setObjectName("ui_vp_wtce"); ui_vp_objection = new SplashLayer(this, ao_app); ui_vp_objection->set_play_once(true); ui_vp_objection->continuous = false; ui_vp_objection->force_continuous = true; ui_vp_objection->setAttribute(Qt::WA_TransparentForMouseEvents); + ui_vp_objection->setObjectName("ui_vp_objection"); ui_ic_chatlog = new QTextEdit(this); ui_ic_chatlog->setReadOnly(true); + ui_ic_chatlog->setObjectName("ui_ic_chatlog"); log_maximum_blocks = ao_app->get_max_log_size(); log_goes_downwards = ao_app->get_log_goes_downwards(); @@ -97,10 +114,12 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_ms_chatlog->setReadOnly(true); ui_ms_chatlog->setOpenExternalLinks(true); ui_ms_chatlog->hide(); + ui_ms_chatlog->setObjectName("ui_ms_chatlog"); ui_server_chatlog = new AOTextArea(this); ui_server_chatlog->setReadOnly(true); ui_server_chatlog->setOpenExternalLinks(true); + ui_server_chatlog->setObjectName("ui_server_chatlog"); ui_area_list = new QTreeWidget(this); ui_area_list->setColumnCount(2); @@ -109,6 +128,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_area_list->header()->setStretchLastSection(false); ui_area_list->header()->setSectionResizeMode(QHeaderView::ResizeToContents); ui_area_list->hide(); + ui_area_list->setObjectName("ui_area_list"); ui_music_list = new QTreeWidget(this); ui_music_list->setColumnCount(2); @@ -118,174 +138,258 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_music_list->header()->setSectionResizeMode(QHeaderView::ResizeToContents); ui_music_list->setContextMenuPolicy(Qt::CustomContextMenu); ui_music_list->setUniformRowHeights(true); - + ui_music_list->setObjectName("ui_music_list"); ui_music_display = new InterfaceLayer(this, ao_app); ui_music_display->set_play_once(false); ui_music_display->transform_mode = Qt::SmoothTransformation; ui_music_display->setAttribute(Qt::WA_TransparentForMouseEvents); + ui_music_display->setObjectName("ui_music_display"); ui_music_name = new ScrollText(ui_music_display); ui_music_name->setText(tr("None")); ui_music_name->setAttribute(Qt::WA_TransparentForMouseEvents); + ui_music_name->setObjectName("ui_music_name"); for (int i = 0; i < max_clocks; i++) { ui_clock[i] = new AOClockLabel(this); ui_clock[i]->setAttribute(Qt::WA_TransparentForMouseEvents); ui_clock[i]->hide(); + ui_clock[i]->setObjectName("ui_clock" + QString::number(i)); } ui_ic_chat_name = new QLineEdit(this); ui_ic_chat_name->setFrame(false); ui_ic_chat_name->setPlaceholderText(tr("Showname")); + ui_ic_chat_name->setObjectName("ui_ic_chat_name"); ui_ic_chat_message = new AOLineEdit(this); ui_ic_chat_message->setFrame(false); ui_ic_chat_message->setPlaceholderText(tr("Message")); ui_ic_chat_message->preserve_selection(true); - // ui_ic_chat_message->setValidator(new QRegExpValidator(QRegExp("^\\S+(?: - // \\S+)*$"), ui_ic_chat_message)); - // todo: filter out \n from showing up as that commonly breaks the chatlog and - // can be spammed to hell + ui_ic_chat_message->setObjectName("ui_ic_chat_message"); ui_vp_sticker = new StickerLayer(ui_viewport, ao_app); ui_vp_sticker->set_play_once(false); ui_vp_sticker->setAttribute(Qt::WA_TransparentForMouseEvents); + ui_vp_sticker->setObjectName("ui_vp_sticker"); ui_muted = new AOImage(ui_ic_chat_message, ao_app); ui_muted->hide(); + ui_muted->setObjectName("ui_muted"); ui_ooc_chat_message = new QLineEdit(this); ui_ooc_chat_message->setFrame(false); + ui_ooc_chat_message->setObjectName("ui_ooc_chat_message"); ui_ooc_chat_name = new QLineEdit(this); ui_ooc_chat_name->setFrame(false); ui_ooc_chat_name->setPlaceholderText(tr("Name")); ui_ooc_chat_name->setMaxLength(30); ui_ooc_chat_name->setText(p_ao_app->get_default_username()); + ui_ooc_chat_name->setObjectName("ui_ooc_chat_name"); // ui_area_password = new QLineEdit(this); // ui_area_password->setFrame(false); ui_music_search = new QLineEdit(this); ui_music_search->setFrame(false); ui_music_search->setPlaceholderText(tr("Search")); + ui_music_search->setObjectName("ui_music_search"); initialize_emotes(); ui_pos_dropdown = new QComboBox(this); ui_pos_dropdown->view()->setTextElideMode(Qt::ElideLeft); + ui_pos_dropdown->setObjectName("ui_pos_dropdown"); + ui_pos_remove = new AOButton(this, ao_app); + ui_pos_remove->setObjectName("ui_pos_remove"); ui_iniswap_dropdown = new QComboBox(this); ui_iniswap_dropdown->setContextMenuPolicy(Qt::CustomContextMenu); ui_iniswap_dropdown->view()->setTextElideMode(Qt::ElideLeft); + ui_iniswap_dropdown->setObjectName("ui_iniswap_dropdown"); + ui_iniswap_remove = new AOButton(this, ao_app); + ui_iniswap_remove->setObjectName("ui_iniswap_remove"); ui_sfx_dropdown = new QComboBox(this); ui_sfx_dropdown->setContextMenuPolicy(Qt::CustomContextMenu); ui_sfx_dropdown->view()->setTextElideMode(Qt::ElideLeft); + ui_sfx_dropdown->setObjectName("ui_sfx_dropdown"); + ui_sfx_remove = new AOButton(this, ao_app); + ui_sfx_remove->setObjectName("ui_sfx_remove"); ui_effects_dropdown = new QComboBox(this); ui_effects_dropdown->view()->setTextElideMode(Qt::ElideLeft); ui_effects_dropdown->setContextMenuPolicy(Qt::CustomContextMenu); + ui_effects_dropdown->setObjectName("ui_effects_dropdown"); ui_defense_bar = new AOImage(this, ao_app); + ui_defense_bar->setObjectName("ui_defense_bar"); + ui_prosecution_bar = new AOImage(this, ao_app); + ui_prosecution_bar->setObjectName("ui_prosecution_bar"); ui_music_label = new QLabel(this); + ui_music_label->setObjectName("ui_music_label"); + ui_sfx_label = new QLabel(this); + ui_sfx_label->setObjectName("ui_sfx_label"); + ui_blip_label = new QLabel(this); + ui_blip_label->setObjectName("ui_blip_label"); ui_hold_it = new AOButton(this, ao_app); + ui_hold_it->setObjectName("ui_hold_it"); + ui_objection = new AOButton(this, ao_app); + ui_objection->setObjectName("ui_objection"); + ui_take_that = new AOButton(this, ao_app); + ui_take_that->setObjectName("ui_take_that"); ui_ooc_toggle = new AOButton(this, ao_app); + ui_ooc_toggle->setObjectName("ui_ooc_toggle"); + ui_witness_testimony = new AOButton(this, ao_app); + ui_witness_testimony->setObjectName("ui_witness_testimony"); + ui_cross_examination = new AOButton(this, ao_app); + ui_cross_examination->setObjectName("ui_cross_examination"); + ui_guilty = new AOButton(this, ao_app); + ui_guilty->setObjectName("ui_guilty"); + ui_not_guilty = new AOButton(this, ao_app); + ui_not_guilty->setObjectName("ui_not_guilty"); ui_change_character = new AOButton(this, ao_app); + ui_change_character->setObjectName("ui_change_character"); + ui_reload_theme = new AOButton(this, ao_app); + ui_reload_theme->setObjectName("ui_reload_theme"); + ui_call_mod = new AOButton(this, ao_app); + ui_call_mod->setObjectName("ui_call_mod"); + ui_settings = new AOButton(this, ao_app); + ui_settings->setObjectName("ui_settings"); + ui_announce_casing = new AOButton(this, ao_app); + ui_announce_casing->setObjectName("ui_announce_casing"); + ui_switch_area_music = new AOButton(this, ao_app); + ui_switch_area_music->setObjectName("ui_switch_area_music"); ui_pre = new QCheckBox(this); ui_pre->setText(tr("Pre")); + ui_pre->setObjectName("ui_pre"); ui_flip = new QCheckBox(this); ui_flip->setText(tr("Flip")); ui_flip->hide(); + ui_flip->setObjectName("ui_flip"); ui_guard = new QCheckBox(this); ui_guard->setText(tr("Guard")); ui_guard->hide(); + ui_guard->setObjectName("ui_guard"); ui_additive = new QCheckBox(this); ui_additive->setText(tr("Additive")); ui_additive->hide(); + ui_additive->setObjectName("ui_additive"); ui_casing = new QCheckBox(this); ui_casing->setChecked(ao_app->get_casing_enabled()); ui_casing->setText(tr("Casing")); ui_casing->hide(); + ui_casing->setObjectName("ui_casing"); ui_showname_enable = new QCheckBox(this); ui_showname_enable->setChecked(ao_app->get_showname_enabled_by_default()); ui_showname_enable->setText(tr("Shownames")); + ui_showname_enable->setObjectName("ui_showname_enable"); ui_immediate = new QCheckBox(this); ui_immediate->setText(tr("Immediate")); ui_immediate->hide(); + ui_immediate->setObjectName("ui_immediate"); ui_custom_objection = new AOButton(this, ao_app); ui_custom_objection->setContextMenuPolicy(Qt::CustomContextMenu); + ui_custom_objection->setObjectName("ui_custom_objection"); + custom_obj_menu = new QMenu(this); + custom_obj_menu->setObjectName("ui_custom_obj_menu"); + ui_realization = new AOButton(this, ao_app); + ui_realization->setObjectName("ui_realization"); + ui_screenshake = new AOButton(this, ao_app); + ui_screenshake->setObjectName("ui_screenshake"); + ui_mute = new AOButton(this, ao_app); + ui_mute->setObjectName("ui_mute"); ui_defense_plus = new AOButton(this, ao_app); + ui_defense_plus->setObjectName("ui_defense_plus"); + ui_defense_minus = new AOButton(this, ao_app); + ui_defense_minus->setObjectName("ui_defense_minus"); ui_prosecution_plus = new AOButton(this, ao_app); + ui_prosecution_plus->setObjectName("ui_prosecution_plus"); + ui_prosecution_minus = new AOButton(this, ao_app); + ui_prosecution_minus->setObjectName("ui_prosecution_minus"); ui_text_color = new QComboBox(this); + ui_text_color->setObjectName("ui_text_color"); ui_music_slider = new QSlider(Qt::Horizontal, this); ui_music_slider->setRange(0, 100); ui_music_slider->setValue(ao_app->get_default_music()); + ui_music_slider->setObjectName("ui_music_slider"); ui_sfx_slider = new QSlider(Qt::Horizontal, this); ui_sfx_slider->setRange(0, 100); ui_sfx_slider->setValue(ao_app->get_default_sfx()); + ui_sfx_slider->setObjectName("ui_sfx_slider"); ui_blip_slider = new QSlider(Qt::Horizontal, this); ui_blip_slider->setRange(0, 100); ui_blip_slider->setValue(ao_app->get_default_blip()); + ui_blip_slider->setObjectName("ui_blip_slider"); ui_mute_list = new QListWidget(this); + ui_mute_list->setObjectName("ui_mute_list"); ui_pair_list = new QListWidget(this); + ui_pair_list->setObjectName("ui_pair_list"); + ui_pair_offset_spinbox = new QSpinBox(this); ui_pair_offset_spinbox->setRange(-100, 100); ui_pair_offset_spinbox->setSuffix(tr("% x offset")); + ui_pair_offset_spinbox->setObjectName("ui_pair_offset_spinbox"); + ui_pair_vert_offset_spinbox = new QSpinBox(this); ui_pair_vert_offset_spinbox->setRange(-100, 100); ui_pair_vert_offset_spinbox->setSuffix(tr("% y offset")); + ui_pair_vert_offset_spinbox->setObjectName("ui_pair_vert_offset_spinbox"); ui_pair_order_dropdown = new QComboBox(this); ui_pair_order_dropdown->addItem(tr("To front")); ui_pair_order_dropdown->addItem(tr("To behind")); + ui_pair_order_dropdown->setObjectName("ui_pair_order_dropdown"); ui_pair_button = new AOButton(this, ao_app); + ui_pair_button->setObjectName("ui_pair_button"); ui_evidence_button = new AOButton(this, ao_app); + ui_evidence_button->setObjectName("ui_evidence_button"); initialize_evidence(); @@ -612,8 +716,8 @@ void Courtroom::set_widgets() 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 ▲"); + ui_ic_chatlog->setPlaceholderText(log_goes_downwards ? "▼ " + tr("Log goes down") + " ▼" + : "▲ " + tr("Log goes up") + " ▲"); set_size_and_pos(ui_ms_chatlog, "ms_chatlog"); ui_ms_chatlog->setFrameShape(QFrame::NoFrame); @@ -5120,7 +5224,7 @@ void Courtroom::set_text_color_dropdown() color_row_to_number.append(c); } for (int c = 0; c < max_colors; ++c) { - QColor color = ao_app->get_chat_color("c" + QString::number(c), "default"); + QColor color = ao_app->get_chat_color("c" + QString::number(c), ""); default_color_rgb_list.append(color); } } diff --git a/src/emotes.cpp b/src/emotes.cpp index 38250c9..8272007 100644 --- a/src/emotes.cpp +++ b/src/emotes.cpp @@ -5,11 +5,15 @@ void Courtroom::initialize_emotes() { ui_emotes = new QWidget(this); + ui_emotes->setObjectName("ui_emotes"); ui_emote_left = new AOButton(this, ao_app); + ui_emote_left->setObjectName("ui_emote_left"); ui_emote_right = new AOButton(this, ao_app); + ui_emote_right->setObjectName("ui_emote_right"); ui_emote_dropdown = new QComboBox(this); + ui_emote_dropdown->setObjectName("ui_emote_dropdown"); connect(ui_emote_left, SIGNAL(clicked()), this, SLOT(on_emote_left_clicked())); diff --git a/src/evidence.cpp b/src/evidence.cpp index ec1fa7e..2cc1d75 100644 --- a/src/evidence.cpp +++ b/src/evidence.cpp @@ -3,47 +3,64 @@ void Courtroom::initialize_evidence() { ui_evidence = new AOImage(this, ao_app); + ui_evidence->setObjectName("ui_evidence"); // ui_evidence_name = new QLabel(ui_evidence); ui_evidence_name = new AOLineEdit(ui_evidence); ui_evidence_name->setAlignment(Qt::AlignCenter); ui_evidence_name->setFrame(false); + ui_evidence_name->setObjectName("ui_evidence_name"); ui_evidence_buttons = new QWidget(ui_evidence); + ui_evidence_buttons->setObjectName("ui_evidence_buttons"); ui_evidence_left = new AOButton(ui_evidence, ao_app); + ui_evidence_left->setObjectName("ui_evidence_left"); ui_evidence_right = new AOButton(ui_evidence, ao_app); + ui_evidence_right->setObjectName("ui_evidence_right"); ui_evidence_present = new AOButton(ui_evidence, ao_app); ui_evidence_present->setToolTip(tr("Present this piece of evidence to " "everyone on your next spoken message")); + ui_evidence_present->setObjectName("ui_evidence_present"); ui_evidence_switch = new AOButton(ui_evidence, ao_app); + ui_evidence_switch->setObjectName("ui_evidence_switch"); ui_evidence_transfer = new AOButton(ui_evidence, ao_app); + ui_evidence_transfer->setObjectName("ui_evidence_transfer"); ui_evidence_save = new AOButton(ui_evidence, ao_app); ui_evidence_save->setToolTip(tr("Save evidence to an .ini file.")); + ui_evidence_save->setObjectName("ui_evidence_save"); ui_evidence_load = new AOButton(ui_evidence, ao_app); ui_evidence_load->setToolTip(tr("Load evidence from an .ini file.")); + ui_evidence_load->setObjectName("ui_evidence_load"); ui_evidence_overlay = new AOImage(ui_evidence, ao_app); + ui_evidence_overlay->setObjectName("ui_evidence_overlay"); ui_evidence_delete = new AOButton(ui_evidence_overlay, ao_app); ui_evidence_delete->setToolTip(tr("Destroy this piece of evidence")); + ui_evidence_delete->setObjectName("ui_evidence_delete"); ui_evidence_image_name = new AOLineEdit(ui_evidence_overlay); + ui_evidence_image_name->setObjectName("ui_evidence_image_name"); ui_evidence_image_button = new AOButton(ui_evidence_overlay, ao_app); ui_evidence_image_button->setText(tr("Choose..")); + ui_evidence_image_button->setObjectName("ui_evidence_image_button"); ui_evidence_x = new AOButton(ui_evidence_overlay, ao_app); ui_evidence_x->setToolTip( tr("Close the evidence display/editing overlay.\n" "You will be prompted if there's any unsaved changes.")); + ui_evidence_x->setObjectName("ui_evidence_x"); ui_evidence_ok = new AOButton(ui_evidence_overlay, ao_app); ui_evidence_ok->setToolTip(tr("Save any changes made to this piece of " "evidence and send them to server.")); + ui_evidence_ok->setObjectName("ui_evidence_ok"); ui_evidence_description = new AOTextEdit(ui_evidence_overlay); ui_evidence_description->setFrameStyle(QFrame::NoFrame); ui_evidence_description->setToolTip( tr("Double-click to edit. Press [X] to update your changes.")); + ui_evidence_description->setObjectName("ui_evidence_description"); connect(ui_evidence_name, SIGNAL(returnPressed()), this, SLOT(on_evidence_name_edited())); diff --git a/src/lobby.cpp b/src/lobby.cpp index 616e520..5cdb94a 100644 --- a/src/lobby.cpp +++ b/src/lobby.cpp @@ -12,50 +12,68 @@ Lobby::Lobby(AOApplication *p_ao_app) : QMainWindow() { ao_app = p_ao_app; + // this->setWindowTitle(tr("Attorney Online 2")); this->setWindowIcon(QIcon(":/logo.png")); this->setWindowFlags( (this->windowFlags() | Qt::CustomizeWindowHint) & ~Qt::WindowMaximizeButtonHint); ui_background = new AOImage(this, ao_app); + ui_background->setObjectName("ui_background"); ui_public_servers = new AOButton(this, ao_app); + ui_public_servers->setObjectName("ui_public_servers"); ui_favorites = new AOButton(this, ao_app); + ui_favorites->setObjectName("ui_favorites"); ui_refresh = new AOButton(this, ao_app); + ui_refresh->setObjectName("ui_refresh"); ui_add_to_fav = new AOButton(this, ao_app); + ui_add_to_fav->setObjectName("ui_add_to_fav"); ui_connect = new AOButton(this, ao_app); + ui_connect->setObjectName("ui_connect"); ui_version = new QLabel(this); + ui_version->setObjectName("ui_version"); ui_about = new AOButton(this, ao_app); + ui_about->setObjectName("ui_about"); ui_settings = new AOButton(this, ao_app); + ui_settings->setObjectName("ui_settings"); ui_server_list = new QTreeWidget(this); - ui_server_list->setHeaderLabels({"#", "Name"}); //, "Players"}); + ui_server_list->setHeaderLabels({"#", "Name"}); ui_server_list->setTextElideMode(Qt::ElideNone); ui_server_list->header()->setMinimumSectionSize(24); ui_server_list->header()->setSectionsMovable(false); ui_server_list->setColumnWidth(0, 0); ui_server_list->setIndentation(0); -// ui_server_list->hideColumn(0); -// ui_server_list->setHeaderHidden(true); + ui_server_list->setObjectName("ui_server_list"); ui_server_search = new QLineEdit(this); ui_server_search->setFrame(false); ui_server_search->setPlaceholderText(tr("Search")); + ui_server_search->setObjectName("ui_server_search"); ui_player_count = new QLabel(this); + ui_player_count->setObjectName("ui_player_count"); ui_description = new AOTextArea(this); ui_description->setOpenExternalLinks(true); + ui_description->setObjectName("ui_description"); ui_chatbox = new AOTextArea(this); ui_chatbox->setOpenExternalLinks(true); + ui_chatbox->setObjectName("ui_chatbox"); ui_chatname = new QLineEdit(this); ui_chatname->setPlaceholderText(tr("Name")); ui_chatname->setText(ao_app->get_ooc_name()); + ui_chatname->setObjectName("ui_chatname"); ui_chatmessage = new QLineEdit(this); + ui_chatmessage->setObjectName("ui_chatmessage"); ui_loading_background = new AOImage(this, ao_app); + ui_loading_background->setObjectName("ui_loading_background"); ui_loading_text = new QTextEdit(ui_loading_background); + ui_loading_text->setObjectName("ui_loading_text"); ui_progress_bar = new QProgressBar(ui_loading_background); ui_progress_bar->setMinimum(0); ui_progress_bar->setMaximum(100); - ui_progress_bar->setStyleSheet("QProgressBar{ color: white; }"); + ui_progress_bar->setObjectName("ui_progress_bar"); ui_cancel = new AOButton(ui_loading_background, ao_app); + ui_cancel->setObjectName("ui_cancel"); connect(ui_public_servers, SIGNAL(clicked()), this, SLOT(on_public_servers_clicked())); diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 1df1e41..cd6802e 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -442,8 +442,8 @@ QString AOApplication::get_chat_markup(QString p_identifier, QString p_chat) QStringList backwards_paths{get_theme_path("misc/" + p_chat + "/config.ini"), get_base_path() + "misc/" + p_chat + "/config.ini", - get_base_path() + "misc/default/config.ini", - get_theme_path("misc/default/config.ini")}; + get_theme_path("misc/default/config.ini"), + get_base_path() + "misc/default/config.ini"}; for (const QString &p : backwards_paths) { QString value = read_design_ini(p_identifier, p); if (!value.isEmpty()) { From 60daac3823735dace691f7a065c3759dc535f60a Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Fri, 23 Apr 2021 14:29:16 -0500 Subject: [PATCH 51/61] Move other duplicate reset calls to their own method --- include/demoserver.h | 2 +- src/demoserver.cpp | 28 +++++++++++++--------------- 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/include/demoserver.h b/include/demoserver.h index e5d5712..cadc52d 100644 --- a/include/demoserver.h +++ b/include/demoserver.h @@ -25,7 +25,7 @@ public: private: void handle_packet(AOPacket packet); void load_demo(QString filename); - void reset_all_timers(); + void reset_state(); QTcpServer* tcp_server; QTcpSocket* client_sock = nullptr; diff --git a/src/demoserver.cpp b/src/demoserver.cpp index 5a0d579..ee0fcf2 100644 --- a/src/demoserver.cpp +++ b/src/demoserver.cpp @@ -162,13 +162,7 @@ void DemoServer::handle_packet(AOPacket packet) load_demo(path); QString packet = "CT#DEMO#" + tr("Demo file loaded. Send /play or > in OOC to begin playback.") + "#1#%"; client_sock->write(packet.toUtf8()); - // Reset evidence list - client_sock->write("LE##%"); - reset_all_timers(); - // Set the BG to default (also breaks up the message queue) - client_sock->write("BN#default#wit#%"); - // Stop the wait packet timer - timer->stop(); + reset_state(); } else if (contents[1].startsWith("/play") || contents[1] == ">") { @@ -232,13 +226,7 @@ void DemoServer::handle_packet(AOPacket packet) load_demo(p_path); QString packet = "CT#DEMO#" + tr("Current demo file reloaded. Send /play or > in OOC to begin playback.") + "#1#%"; client_sock->write(packet.toUtf8()); - // Reset evidence list - client_sock->write("LE##%"); - reset_all_timers(); - // Set the BG to default (also breaks up the message queue) - client_sock->write("BN#default#wit#%"); - // Stop the wait packet timer - timer->stop(); + reset_state(); } else if (contents[1].startsWith("/min_wait")) { @@ -327,8 +315,12 @@ void DemoServer::load_demo(QString filename) } } -void DemoServer::reset_all_timers() +void DemoServer::reset_state() { + // Reset evidence list + client_sock->write("LE##%"); + + // Reset timers client_sock->write("TI#0#3#0#%"); client_sock->write("TI#0#1#0#%"); client_sock->write("TI#1#1#0#%"); @@ -339,6 +331,12 @@ void DemoServer::reset_all_timers() client_sock->write("TI#3#3#0#%"); client_sock->write("TI#4#1#0#%"); client_sock->write("TI#4#3#0#%"); + + // Set the BG to default (also breaks up the message queue) + client_sock->write("BN#default#wit#%"); + + // Stop the wait packet timer + timer->stop(); } void DemoServer::playback() From 6e3435ddba0bc9a2ca71109cb75aa4edbaedfce2 Mon Sep 17 00:00:00 2001 From: oldmud0 Date: Fri, 23 Apr 2021 16:09:25 -0500 Subject: [PATCH 52/61] Add setting for default scaling method --- include/aoapplication.h | 3 +++ include/aooptionsdialog.h | 2 ++ src/aooptionsdialog.cpp | 18 ++++++++++++++++++ src/text_file_functions.cpp | 8 ++++++++ 4 files changed, 31 insertions(+) diff --git a/include/aoapplication.h b/include/aoapplication.h index 493f1c9..16bbb9f 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -490,6 +490,9 @@ public: // Get if the theme is animated bool get_animated_theme(); + // Get the default scaling method + QString get_default_scaling(); + // Currently defined subtheme QString subtheme; diff --git a/include/aooptionsdialog.h b/include/aooptionsdialog.h index e88ce54..45fc86c 100644 --- a/include/aooptionsdialog.h +++ b/include/aooptionsdialog.h @@ -85,6 +85,8 @@ private: QCheckBox *ui_discord_cb; QLabel *ui_language_label; QComboBox *ui_language_combobox; + QLabel *ui_scaling_label; + QComboBox *ui_scaling_combobox; QLabel *ui_shake_lbl; QCheckBox *ui_shake_cb; diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp index a0d2e7d..1eb99ba 100644 --- a/src/aooptionsdialog.cpp +++ b/src/aooptionsdialog.cpp @@ -381,6 +381,20 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app) ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_language_combobox); + row += 1; + ui_scaling_label = new QLabel(ui_form_layout_widget); + ui_scaling_label->setText(tr("Scaling:")); + ui_scaling_label->setToolTip( + tr("Sets the default scaling method, if there is not one already defined " + "specifically for the character.")); + ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_scaling_label); + + ui_scaling_combobox = new QComboBox(ui_form_layout_widget); + // Corresponds with Qt::TransformationMode enum. Please don't change the order. + ui_scaling_combobox->addItem(tr("Pixel"), "fast"); + ui_scaling_combobox->addItem(tr("Smooth"), "smooth"); + ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_scaling_combobox); + row += 1; ui_shake_lbl = new QLabel(ui_form_layout_widget); ui_shake_lbl->setText(tr("Allow Screenshake:")); @@ -896,6 +910,9 @@ void AOOptionsDialog::update_values() { break; } } + Qt::TransformationMode scaling = ao_app->get_scaling(ao_app->get_default_scaling()); + ui_scaling_combobox->setCurrentIndex(scaling); + // Let's fill the callwords text edit with the already present callwords. ui_callwords_textbox->document()->clear(); foreach (QString callword, ao_app->get_call_words()) { @@ -973,6 +990,7 @@ void AOOptionsDialog::save_pressed() configini->setValue("master", ui_ms_textbox->text()); configini->setValue("discord", ui_discord_cb->isChecked()); configini->setValue("language", ui_language_combobox->currentText().left(2)); + configini->setValue("default_scaling", ui_scaling_combobox->currentData()); configini->setValue("shake", ui_shake_cb->isChecked()); configini->setValue("effects", ui_effects_cb->isChecked()); configini->setValue("framenetwork", ui_framenetwork_cb->isChecked()); diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index cd6802e..1f34945 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -290,6 +290,9 @@ QString AOApplication::read_design_ini(QString p_identifier, Qt::TransformationMode AOApplication::get_scaling(QString p_scaling) { + if (p_scaling.isEmpty()) + p_scaling = get_default_scaling(); + if (p_scaling == "smooth") return Qt::SmoothTransformation; return Qt::FastTransformation; @@ -1085,3 +1088,8 @@ bool AOApplication::get_animated_theme() configini->value("animated_theme", "true").value(); return result.startsWith("true"); } + +QString AOApplication::get_default_scaling() +{ + return configini->value("default_scaling", "fast").value(); +} From 433b7f33159b9ee86b2ea0192869ea0bdbeb2f05 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Sat, 24 Apr 2021 01:44:52 +0300 Subject: [PATCH 53/61] Deprecate tick_ms and use actual milliseconds rather than arbitrary 60ms ticks for char.ini [Time] Fix an extremely weird case where CharLayer::Play() was not called even on the CharLayer class (I don't understand why inheritance was straight up just ignored) Fix using preanims with static images just breaking everything Deprecate weird insanity [Time] with the % sign BS (What was this for again? Literally no one used this nor was aware of it) Fix text_stay_time timer firing even if we're immediate Just in case, stop the text delay timer when start_chat_ticking is called --- include/aoapplication.h | 4 ---- include/aolayer.h | 4 ---- src/aolayer.cpp | 27 +++++++++++++++++++++------ src/courtroom.cpp | 34 +++++++++------------------------- src/text_file_functions.cpp | 9 --------- 5 files changed, 30 insertions(+), 48 deletions(-) diff --git a/include/aoapplication.h b/include/aoapplication.h index 493f1c9..b0f7e08 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -378,10 +378,6 @@ public: // Returns the preanim duration of p_char's p_emote int get_preanim_duration(QString p_char, QString p_emote); - // Same as above, but only returns if it has a % in front(refer to Preanims - // section in the manual) - int get_ao2_preanim_duration(QString p_char, QString p_emote); - // Not in use int get_text_delay(QString p_char, QString p_emote); diff --git a/include/aolayer.h b/include/aolayer.h index f42642c..f3ecebf 100644 --- a/include/aolayer.h +++ b/include/aolayer.h @@ -104,10 +104,6 @@ protected: QElapsedTimer actual_time; - // Usually used to turn seconds into milliseconds such as for [Time] tag in - // char.ini (which is no longer used) - const int tick_ms = 60; - // These are the X and Y values before they are fixed based on the sprite's // width. int x = 0; diff --git a/src/aolayer.cpp b/src/aolayer.cpp index 795274f..ebd8d67 100644 --- a/src/aolayer.cpp +++ b/src/aolayer.cpp @@ -146,6 +146,7 @@ void BackgroundLayer::load_image(QString p_filename) qDebug() << "[BackgroundLayer] BG loaded: " << p_filename; #endif start_playback(ao_app->get_image_suffix(ao_app->get_background_path(p_filename))); + play(); } void CharLayer::load_image(QString p_filename, QString p_charname, @@ -189,7 +190,7 @@ void CharLayer::load_image(QString p_filename, QString p_charname, } is_preanim = true; play_once = true; - preanim_timer->start(duration * tick_ms); + preanim_timer->start(duration); } #ifdef DEBUG_MOVIE qDebug() << "[CharLayer] anim loaded: prefix " << prefix << " filename " @@ -211,6 +212,7 @@ void CharLayer::load_image(QString p_filename, QString p_charname, ao_app->get_theme_path( "placeholder", ao_app->default_theme)}; // Default theme placeholder path start_playback(ao_app->get_image_path(pathlist)); + play(); } void SplashLayer::load_image(QString p_filename, QString p_charname, @@ -219,6 +221,7 @@ void SplashLayer::load_image(QString p_filename, QString p_charname, transform_mode = ao_app->get_misc_scaling(p_miscname); QString final_image = ao_app->get_image(p_filename, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_miscname, p_charname, "placeholder"); start_playback(final_image); + play(); } void EffectLayer::load_image(QString p_filename, bool p_looping) @@ -230,6 +233,7 @@ void EffectLayer::load_image(QString p_filename, bool p_looping) continuous = false; force_continuous = true; start_playback(p_filename); // handled in its own file before we see it + play(); } void InterfaceLayer::load_image(QString p_filename, QString p_miscname) @@ -237,6 +241,7 @@ void InterfaceLayer::load_image(QString p_filename, QString p_miscname) stretch = true; QString final_image = ao_app->get_image(p_filename, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_miscname); start_playback(final_image); + play(); } void StickerLayer::load_image(QString p_charname) @@ -247,6 +252,7 @@ void StickerLayer::load_image(QString p_charname) transform_mode = ao_app->get_misc_scaling(p_miscname); QString final_image = ao_app->get_image("sticker/" + p_charname, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_miscname); start_playback(final_image); + play(); } void CharLayer::start_playback(QString p_image) @@ -257,6 +263,7 @@ void CharLayer::start_playback(QString p_image) load_network_effects(); else // Use default ini FX load_effects(); + play(); } void AOLayer::start_playback(QString p_image) @@ -275,7 +282,7 @@ void AOLayer::start_playback(QString p_image) actual_time.restart(); #endif this->clear(); - freeze(); + this->freeze(); movie_frames.clear(); movie_delays.clear(); QString scaling_override = @@ -329,14 +336,12 @@ void AOLayer::start_playback(QString p_image) } else if (max_frames <= 1) { duration = static_duration; - play_once = false; #ifdef DEBUG_MOVIE qDebug() << "max_frames is <= 1, using static duration"; #endif } if (duration > 0 && cull_image == true) shfx_timer->start(duration); - play(); #ifdef DEBUG_MOVIE qDebug() << max_frames << "Setting image to " << image_path << "Time taken to process image:" << actual_time.elapsed(); @@ -347,6 +352,12 @@ void AOLayer::start_playback(QString p_image) void CharLayer::play() { + if (max_frames <= 1) { + if (play_once) { + preanim_timer->start(qMax(0, duration)); + } + return; + } play_frame_effect(frame); AOLayer::play(); } @@ -354,8 +365,12 @@ void CharLayer::play() void AOLayer::play() { if (max_frames <= 1) { - if (play_once) - ticker->start(tick_ms); + if (play_once) { + if (duration > 0) + ticker->start(duration); + else + preanim_done(); + } else this->freeze(); } diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 301b82e..dcc1c1e 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3223,17 +3223,10 @@ void Courtroom::play_preanim(bool immediate) QString f_preanim = m_chatmessage[PRE_EMOTE]; // all time values in char.inis are multiplied by a constant(time_mod) to get // the actual time - int ao2_duration = ao_app->get_ao2_preanim_duration(f_char, f_preanim); + int preanim_duration = ao_app->get_preanim_duration(f_char, f_preanim); int stay_time = ao_app->get_text_delay(f_char, f_preanim) * time_mod; int sfx_delay = m_chatmessage[SFX_DELAY].toInt() * time_mod; - int preanim_duration; - - if (ao2_duration < 0) - preanim_duration = ao_app->get_preanim_duration(f_char, f_preanim); - else - preanim_duration = ao2_duration; - sfx_delay_timer->start(sfx_delay); QString anim_to_find = ao_app->get_image_suffix(ao_app->get_character_path(f_char, f_preanim)); @@ -3246,15 +3239,6 @@ void Courtroom::play_preanim(bool immediate) qDebug() << "W: could not find " + anim_to_find; return; } - else { - QImageReader s_reader(anim_to_find); - int image_count = s_reader.imageCount(); - if (image_count <= 1) { - preanim_done(); - qDebug() << "W: tried to play static preanim " + anim_to_find; - return; - } - } ui_vp_player_char->set_static_duration(preanim_duration); ui_vp_player_char->set_play_once(true); ui_vp_player_char->load_image(f_preanim, f_char, preanim_duration, true); @@ -3276,16 +3260,15 @@ void Courtroom::play_preanim(bool immediate) break; } - if (immediate) + if (immediate) { anim_state = 4; - else - anim_state = 1; - - if (stay_time >= 0) - text_delay_timer->start(stay_time); - - if (immediate) handle_ic_speaking(); + } + else { + anim_state = 1; + if (stay_time >= 0) + text_delay_timer->start(stay_time); + } } void Courtroom::preanim_done() @@ -3317,6 +3300,7 @@ void Courtroom::preanim_done() void Courtroom::start_chat_ticking() { + text_delay_timer->stop(); // we need to ensure that the text isn't already ticking because this function // can be called by two logic paths if (text_state != 0) diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index cd6802e..b26fbee 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -669,15 +669,6 @@ int AOApplication::get_preanim_duration(QString p_char, QString p_emote) return f_result.toInt(); } -int AOApplication::get_ao2_preanim_duration(QString p_char, QString p_emote) -{ - QString f_result = read_char_ini(p_char, "%" + p_emote, "Time"); - - if (f_result == "") - return -1; - return f_result.toInt(); -} - int AOApplication::get_emote_number(QString p_char) { QString f_result = read_char_ini(p_char, "number", "Emotions"); From 8d9331a3ea71fa3309260515c04b3691064bb8f2 Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Sat, 24 Apr 2021 02:28:24 +0300 Subject: [PATCH 54/61] fix interfacelayer not applying stretching when load_image is called (reload theme, chat arrows, etc.) --- src/aolayer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/aolayer.cpp b/src/aolayer.cpp index ebd8d67..2c6c911 100644 --- a/src/aolayer.cpp +++ b/src/aolayer.cpp @@ -238,6 +238,7 @@ void EffectLayer::load_image(QString p_filename, bool p_looping) void InterfaceLayer::load_image(QString p_filename, QString p_miscname) { + last_path = ""; stretch = true; QString final_image = ao_app->get_image(p_filename, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_miscname); start_playback(final_image); From 0ced99c966aefb365694a1137c9adccd3721712e Mon Sep 17 00:00:00 2001 From: in1tiate Date: Mon, 26 Apr 2021 12:14:16 -0500 Subject: [PATCH 55/61] check for effects without path in p_misc --- src/text_file_functions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 1f34945..39ebb7e 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -848,7 +848,7 @@ QStringList AOApplication::get_effects(QString p_char) { QString p_misc = read_char_ini(p_char, "effects", "Options"); QString p_path = get_asset("effects/effects.ini", current_theme, get_subtheme(), default_theme, ""); - QString p_misc_path = get_asset("effects/effects.ini", current_theme, get_subtheme(), default_theme, p_misc); + QString p_misc_path = get_asset("effects.ini", current_theme, get_subtheme(), default_theme, p_misc); QStringList effects; QStringList lines = read_file(p_path).split("\n"); From 99d083d114844ce3f8274663da212784595421ed Mon Sep 17 00:00:00 2001 From: MangosArentLiterature <58055358+MangosArentLiterature@users.noreply.github.com> Date: Wed, 28 Apr 2021 00:43:06 -0500 Subject: [PATCH 56/61] Add default shownames Adds a new setting to config.ini to set a default showname. This works similarly to default username, but for IC shownames, setting the client's showname automatically. Like default username, this has a 30 character limit. * Adds a new option to config.ini, default_showname. * Adds this setting to the options dialog. * Adds get_default_showname() for retrieving this showname. * Sets the showname box to this value upon joining a server. --- include/aoapplication.h | 3 +++ include/aooptionsdialog.h | 2 ++ src/aooptionsdialog.cpp | 16 ++++++++++++++++ src/courtroom.cpp | 1 + src/text_file_functions.cpp | 6 ++++++ 5 files changed, 28 insertions(+) diff --git a/include/aoapplication.h b/include/aoapplication.h index 16bbb9f..7715475 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -278,6 +278,9 @@ public: // Returns whether the user would like to have custom shownames on by default. bool get_showname_enabled_by_default(); + //Returns the showname the user may have set in config.ini. + QString get_default_showname(); + // Returns the list of words in callwords.ini QStringList get_call_words(); diff --git a/include/aooptionsdialog.h b/include/aooptionsdialog.h index 45fc86c..a6c8b8e 100644 --- a/include/aooptionsdialog.h +++ b/include/aooptionsdialog.h @@ -78,6 +78,8 @@ private: QLabel *ui_username_lbl; QLabel *ui_showname_lbl; QCheckBox *ui_showname_cb; + QLabel *ui_default_showname_lbl; + QLineEdit *ui_default_showname_textbox; QFrame *ui_net_divider; QLabel *ui_ms_lbl; QLineEdit *ui_ms_textbox; diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp index 1eb99ba..1db0dec 100644 --- a/src/aooptionsdialog.cpp +++ b/src/aooptionsdialog.cpp @@ -325,6 +325,20 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app) ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_showname_cb); + row +=1; + ui_default_showname_lbl = new QLabel(ui_form_layout_widget); + ui_default_showname_lbl->setText(tr("Default showname:")); + ui_default_showname_lbl->setToolTip( + tr("Your showname will be automatically set to this value " + "when you join a server.")); + + ui_gameplay_form->setWidget(row, QFormLayout::LabelRole, ui_default_showname_lbl); + + ui_default_showname_textbox = new QLineEdit(ui_form_layout_widget); + ui_default_showname_textbox->setMaxLength(30); + + ui_gameplay_form->setWidget(row, QFormLayout::FieldRole, ui_default_showname_textbox); + row += 1; ui_net_divider = new QFrame(ui_form_layout_widget); ui_net_divider->setFrameShape(QFrame::HLine); @@ -961,6 +975,7 @@ void AOOptionsDialog::update_values() { ui_sfx_volume_spinbox->setValue(ao_app->get_default_sfx()); ui_blips_volume_spinbox->setValue(ao_app->get_default_blip()); ui_bliprate_spinbox->setValue(ao_app->read_blip_rate()); + ui_default_showname_textbox->setText(ao_app->get_default_showname()); } void AOOptionsDialog::save_pressed() @@ -987,6 +1002,7 @@ void AOOptionsDialog::save_pressed() configini->setValue("chat_ratelimit", ui_chat_ratelimit_spinbox->value()); configini->setValue("default_username", ui_username_textbox->text()); configini->setValue("show_custom_shownames", ui_showname_cb->isChecked()); + configini->setValue("default_showname", ui_default_showname_textbox->text()); configini->setValue("master", ui_ms_textbox->text()); configini->setValue("discord", ui_discord_cb->isChecked()); configini->setValue("language", ui_language_combobox->currentText().left(2)); diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 301b82e..71fa828 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -161,6 +161,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_ic_chat_name = new QLineEdit(this); ui_ic_chat_name->setFrame(false); ui_ic_chat_name->setPlaceholderText(tr("Showname")); + ui_ic_chat_name->setText(p_ao_app->get_default_showname()); ui_ic_chat_name->setObjectName("ui_ic_chat_name"); ui_ic_chat_message = new AOLineEdit(this); diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 39ebb7e..2c50e17 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -112,6 +112,12 @@ QString AOApplication::get_default_username() return result; } +QString AOApplication::get_default_showname() +{ + QString result = configini->value("default_showname", "").value(); + return result; +} + QString AOApplication::get_audio_output_device() { QString result = From 8a9bb6dc6923a3a9a77bb8a0f397edeac8407a8a Mon Sep 17 00:00:00 2001 From: Salanto Date: Tue, 4 May 2021 05:39:50 +0200 Subject: [PATCH 57/61] Add Asset Packet This packet is used to send the client the URL of an online content repository, if available. --- include/aoapplication.h | 10 ++++++++++ src/packet_distribution.cpp | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/include/aoapplication.h b/include/aoapplication.h index 7f7f3e1..835c7fd 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -501,6 +501,16 @@ public: // The file name of the log file in base/logs. QString log_filename; + /** + * @brief A QString of an URL that defines the content repository + * send by the server. + * + * @details Introduced in Version 2.9.2. + * Addresses the issue of contenturl devlivery for WebAO + * without relying on someone adding the link manually. + */ + QString asset_url; + void initBASS(); static void load_bass_opus_plugin(); static void CALLBACK BASSreset(HSTREAM handle, DWORD channel, DWORD data, diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index dc76ec1..2860720 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -703,6 +703,16 @@ void AOApplication::server_packet_received(AOPacket *p_packet) w_courtroom->on_authentication_state_received(authenticated); } + //AssetURL Packet + else if (header == "ASS") { + if (f_contents.size() > 1) { // This can never be more than one link. + goto end; + } + QUrl t_asset_url = QUrl::fromPercentEncoding(f_contents.at(0).toUtf8()); + if (t_asset_url.isValid()) + asset_url = t_asset_url.toString(); + } + end: delete p_packet; From b8b6d3cbb32801fed87052e60fce73ea24cc684d Mon Sep 17 00:00:00 2001 From: Salanto Date: Wed, 5 May 2021 00:42:48 +0200 Subject: [PATCH 58/61] Add musclist streaming support Attempt Nr. 2 - Based on #548 and #501 + Allows client to use a remote source as a last resort if the file can't be found locally. + Adds a check if the target file is missing. This implementation assumed the streaming source to be structured like a webao content respository --- include/aomusicplayer.h | 2 +- src/aomusicplayer.cpp | 5 +++-- src/courtroom.cpp | 30 ++++++++++++++++++++++-------- 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/include/aomusicplayer.h b/include/aomusicplayer.h index 36031f1..f899b9a 100644 --- a/include/aomusicplayer.h +++ b/include/aomusicplayer.h @@ -25,7 +25,7 @@ public: int loop_end[4] = {0, 0, 0, 0}; public slots: - void play(QString p_song, int channel = 0, bool loop = false, + int play(QString p_song, int channel = 0, bool loop = false, int effect_flags = 0); void stop(int channel = 0); diff --git a/src/aomusicplayer.cpp b/src/aomusicplayer.cpp index 8a3142e..e8bd690 100644 --- a/src/aomusicplayer.cpp +++ b/src/aomusicplayer.cpp @@ -13,12 +13,12 @@ AOMusicPlayer::~AOMusicPlayer() } } -void AOMusicPlayer::play(QString p_song, int channel, bool loop, +int AOMusicPlayer::play(QString p_song, int channel, bool loop, int effect_flags) { channel = channel % m_channelmax; if (channel < 0) // wtf? - return; + return BASS_ERROR_NOCHAN; QString f_path = ao_app->get_music_path(p_song); unsigned int flags = BASS_STREAM_PRESCAN | BASS_STREAM_AUTOFREE | @@ -125,6 +125,7 @@ void AOMusicPlayer::play(QString p_song, int channel, bool loop, this->set_looping(loop, channel); // Have to do this here due to any // crossfading-related changes, etc. + return BASS_ErrorGetCode(); } void AOMusicPlayer::stop(int channel) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 82b98e3..a2dca89 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3824,6 +3824,11 @@ void Courtroom::handle_song(QStringList *p_contents) return; } + if(!file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))) && !f_song.startsWith("http") + && f_song != "~stop.mp3" && ao_app->asset_url != NULL) { + f_song = (ao_app->asset_url + "sounds/music/" + f_song).toLower(); + } + bool is_stop = (f_song == "~stop.mp3"); if (n_char >= 0 && n_char < char_list.size()) { QString str_char = char_list.at(n_char).name; @@ -3845,17 +3850,26 @@ void Courtroom::handle_song(QStringList *p_contents) } } - music_player->play(f_song, channel, looping, effect_flags); + int error_code = music_player->play(f_song, channel, looping, effect_flags); + if (is_stop) { ui_music_name->setText(tr("None")); + return; } - else if (channel == 0) { - if (file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))) && !f_song.startsWith("http")) - ui_music_name->setText(f_song_clear); - else if (f_song.startsWith("http")) - ui_music_name->setText(tr("[STREAM] %1").arg(f_song_clear)); - else - ui_music_name->setText(tr("[MISSING] %1").arg(f_song_clear)); + + if (error_code == BASS_ERROR_HANDLE) { // Cheap hack to see if file missing + ui_music_name->setText(tr("[MISSING] %1").arg(f_song_clear)); + return; + } + + if (f_song.startsWith("http") && channel == 0) { + ui_music_name->setText(tr("[STREAM] %1").arg(f_song_clear)); + return; + } + + if (channel == 0){ + ui_music_name->setText(f_song_clear); + return; } } From 8fc75f29a7888a6db5db641421b0020ed561406e Mon Sep 17 00:00:00 2001 From: Salanto Date: Wed, 12 May 2021 01:56:15 +0200 Subject: [PATCH 59/61] Prevent crash when sending empty ASS packet --- src/packet_distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index 2860720..dfe28f4 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -705,7 +705,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) //AssetURL Packet else if (header == "ASS") { - if (f_contents.size() > 1) { // This can never be more than one link. + if (f_contents.size() > 1 || f_contents.size() == 0) { // This can never be more than one link. goto end; } QUrl t_asset_url = QUrl::fromPercentEncoding(f_contents.at(0).toUtf8()); From c6207a5478099176e1a5091d2adb31c52bdc2501 Mon Sep 17 00:00:00 2001 From: Salanto Date: Wed, 12 May 2021 13:42:41 +0200 Subject: [PATCH 60/61] Commit suggestion --- src/courtroom.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index a2dca89..a29ebe2 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -3825,7 +3825,7 @@ void Courtroom::handle_song(QStringList *p_contents) } if(!file_exists(ao_app->get_sfx_suffix(ao_app->get_music_path(f_song))) && !f_song.startsWith("http") - && f_song != "~stop.mp3" && ao_app->asset_url != NULL) { + && f_song != "~stop.mp3" && !ao_app->asset_url.isEmpty()) { f_song = (ao_app->asset_url + "sounds/music/" + f_song).toLower(); } From 167aae750f969cf00f64216ce7839366793c294f Mon Sep 17 00:00:00 2001 From: in1tiate Date: Sun, 16 May 2021 00:41:41 -0500 Subject: [PATCH 61/61] account for both theme and misc pathing which are different because this program is well made and does not make me want to pull my hair out --- src/text_file_functions.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 712a63d..1d36689 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -868,10 +868,13 @@ QString AOApplication::get_effect(QString effect, QString p_char, if (p_folder == "") p_folder = read_char_ini(p_char, "effects", "Options"); - QString p_path = get_image("effects/" + effect, current_theme, get_subtheme(), default_theme, p_folder); + QString p_path = get_image("effects/" + effect, current_theme, get_subtheme(), default_theme, ""); + QString p_misc_path = get_image(effect, current_theme, get_subtheme(), default_theme, p_folder); - if (!file_exists(p_path)) + if (!file_exists(p_misc_path) && !file_exists(p_path)) return ""; + else if (file_exists(p_misc_path)) + return p_misc_path; return p_path; } @@ -884,7 +887,9 @@ QString AOApplication::get_effect_property(QString fx_name, QString p_char, else f_property = fx_name + "_" + p_property; - QString f_result = get_config_value(f_property, "effects/effects.ini", current_theme, get_subtheme(), default_theme, read_char_ini(p_char, "effects", "Options")); + QString f_result = get_config_value(f_property, "effects.ini", current_theme, get_subtheme(), default_theme, read_char_ini(p_char, "effects", "Options")); + if (f_result == "") + f_result = get_config_value(f_property, "effects/effects.ini", current_theme, get_subtheme(), default_theme, ""); if (fx_name == "realization" && p_property == "sound") { f_result = get_custom_realization(p_char); }