Merge branch 'master' into crystalwarrior/demo-reload

This commit is contained in:
Crystalwarrior 2021-04-23 16:12:35 +03:00
commit de4115e20a
15 changed files with 220 additions and 156 deletions

@ -1 +1 @@
Subproject commit c9acb90137361ea8c29bc4cf2bf530d14b52b23a Subproject commit 7c036c09ddfadc2680a2c5dbfa188dc98142a427

View File

@ -11,7 +11,7 @@
class AOImage : public QLabel { class AOImage : public QLabel {
public: public:
AOImage(QWidget *parent, AOApplication *p_ao_app); AOImage(QWidget *parent, AOApplication *p_ao_app, bool make_static = false);
~AOImage(); ~AOImage();
QWidget *m_parent; QWidget *m_parent;
@ -20,6 +20,8 @@ public:
QString path; QString path;
bool is_static = false;
bool set_image(QString p_image, QString p_misc = ""); bool set_image(QString p_image, QString p_misc = "");
void set_size_and_pos(QString identifier); void set_size_and_pos(QString identifier);
}; };

View File

@ -52,6 +52,7 @@ public:
bool force_continuous = false; bool force_continuous = false;
Qt::TransformationMode transform_mode = Qt::FastTransformation; // transformation mode to use for this image 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 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. // Set the movie's image to provided paths, preparing for playback.
void start_playback(QString p_image); void start_playback(QString p_image);

View File

@ -235,7 +235,7 @@ public:
DISPLAY_AND_IO DISPLAY_AND_IO
}; };
// Log the message contents and information such as evidence presenting etc. into the log file, the IC log, or both. // 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 // Log the message contents and information such as evidence presenting etc. into the IC logs
void handle_callwords(); void handle_callwords();
@ -755,7 +755,6 @@ private:
QVector<AOCharButton *> ui_char_button_list; QVector<AOCharButton *> ui_char_button_list;
QVector<AOCharButton *> ui_char_button_list_filtered; QVector<AOCharButton *> ui_char_button_list_filtered;
AOImage *ui_selector;
AOButton *ui_back_to_lobby; AOButton *ui_back_to_lobby;

View File

@ -10,6 +10,7 @@
#include <QTcpSocket> #include <QTcpSocket>
#include <QTimer> #include <QTimer>
#include <QFileDialog> #include <QFileDialog>
#include <QMessageBox>
class DemoServer : public QObject class DemoServer : public QObject
{ {

View File

@ -15,19 +15,19 @@ AOCharButton::AOCharButton(QWidget *parent, AOApplication *p_ao_app, int x_pos,
this->resize(60, 60); this->resize(60, 60);
this->move(x_pos, y_pos); 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->resize(60, 60);
ui_taken->set_image("char_taken"); ui_taken->set_image("char_taken");
ui_taken->setAttribute(Qt::WA_TransparentForMouseEvents); ui_taken->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_taken->hide(); 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->resize(60, 60);
ui_passworded->set_image("char_passworded"); ui_passworded->set_image("char_passworded");
ui_passworded->setAttribute(Qt::WA_TransparentForMouseEvents); ui_passworded->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_passworded->hide(); 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->resize(62, 62);
ui_selector->move(x_pos - 1, y_pos - 1); ui_selector->move(x_pos - 1, y_pos - 1);
ui_selector->set_image("char_selector"); ui_selector->set_image("char_selector");

View File

@ -9,14 +9,14 @@ AOEvidenceButton::AOEvidenceButton(QWidget *p_parent, AOApplication *p_ao_app,
ao_app = p_ao_app; ao_app = p_ao_app;
m_parent = p_parent; 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->resize(p_w, p_h);
// ui_selected->move(p_x, p_y); // ui_selected->move(p_x, p_y);
ui_selected->set_image("evidence_selected"); ui_selected->set_image("evidence_selected");
ui_selected->setAttribute(Qt::WA_TransparentForMouseEvents); ui_selected->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_selected->hide(); 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->resize(p_w, p_h);
// ui_selector->move(p_x - 1, p_y - 1); // ui_selector->move(p_x - 1, p_y - 1);
ui_selector->set_image("evidence_selector"); ui_selector->set_image("evidence_selector");

View File

@ -4,11 +4,14 @@
#include <QBitmap> #include <QBitmap>
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; m_parent = parent;
ao_app = p_ao_app; ao_app = p_ao_app;
movie = new QMovie(); is_static = make_static;
if (!is_static) // Only create the QMovie if we're non-static
{
movie = new QMovie(this);
connect(movie, &QMovie::frameChanged, [=]{ connect(movie, &QMovie::frameChanged, [=]{
QPixmap f_pixmap = movie->currentPixmap(); QPixmap f_pixmap = movie->currentPixmap();
f_pixmap = f_pixmap =
@ -16,6 +19,7 @@ AOImage::AOImage(QWidget *parent, AOApplication *p_ao_app) : QLabel(parent)
this->setPixmap(f_pixmap); this->setPixmap(f_pixmap);
this->setMask(f_pixmap.mask()); this->setMask(f_pixmap.mask());
}); });
}
} }
AOImage::~AOImage() {} AOImage::~AOImage() {}
@ -23,7 +27,7 @@ AOImage::~AOImage() {}
bool AOImage::set_image(QString p_path, QString p_misc) bool AOImage::set_image(QString p_path, QString p_misc)
{ {
// Check if the user wants animated themes // 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 // 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); p_path = ao_app->get_image(p_path, ao_app->current_theme, ao_app->get_subtheme(), ao_app->default_theme, p_misc);
else else
@ -35,12 +39,14 @@ bool AOImage::set_image(QString p_path, QString p_misc)
return false; return false;
} }
path = p_path; path = p_path;
if (!is_static) {
movie->stop(); movie->stop();
movie->setFileName(path); movie->setFileName(path);
if (ao_app->get_animated_theme() && movie->frameCount() > 1) { if (ao_app->get_animated_theme() && movie->frameCount() > 1) {
movie->start(); movie->start();
} }
else { }
if (is_static || !ao_app->get_animated_theme() || movie->frameCount() <= 1) {
QPixmap f_pixmap(path); QPixmap f_pixmap(path);
f_pixmap = f_pixmap =

View File

@ -98,6 +98,7 @@ void AOLayer::center_pixmap(QPixmap f_pixmap) {
x + (f_w - f_pixmap.width()) / 2, x + (f_w - f_pixmap.width()) / 2,
y + (f_h - f_pixmap.height())); // Always center horizontally, always put y + (f_h - f_pixmap.height())); // Always center horizontally, always put
// at the bottom vertically // at the bottom vertically
if (masked)
this->setMask( this->setMask(
QRegion((f_pixmap.width() - f_w) / 2, (f_pixmap.height() - f_h) / 2, f_w, 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 f_h)); // make sure we don't escape the area we've been given
@ -196,20 +197,20 @@ void CharLayer::load_image(QString p_filename, QString p_charname,
<< " continuous: " << continuous; << " continuous: " << continuous;
#endif #endif
QStringList pathlist = { QStringList pathlist = {
ao_app->get_image_suffix(ao_app->get_character_path( ao_app->get_character_path(
p_charname, prefix + current_emote)), // Default path p_charname, prefix + current_emote), // Default path
ao_app->get_image_suffix(ao_app->get_character_path( ao_app->get_character_path(
p_charname, p_charname,
prefix + "/" + current_emote)), // Path check if it's categorized prefix + "/" + current_emote), // Path check if it's categorized
// into a folder // into a folder
ao_app->get_image_suffix(ao_app->get_character_path( ao_app->get_character_path(
p_charname, p_charname,
current_emote)), // Just use the non-prefixed image, animated or not current_emote), // Just use the non-prefixed image, animated or not
ao_app->get_image_suffix( 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"), // Theme placeholder path
ao_app->get_image_suffix(ao_app->get_theme_path( ao_app->get_theme_path(
"placeholder", ao_app->default_theme))}; // Default theme placeholder path "placeholder", ao_app->default_theme)}; // Default theme placeholder path
start_playback(find_image(pathlist)); start_playback(ao_app->get_image_path(pathlist));
} }
void SplashLayer::load_image(QString p_filename, QString p_charname, void SplashLayer::load_image(QString p_filename, QString p_charname,

View File

@ -21,10 +21,6 @@ void Courtroom::construct_char_select()
ui_char_buttons = new QWidget(ui_char_select_background); ui_char_buttons = new QWidget(ui_char_select_background);
ui_selector = new AOImage(ui_char_select_background, ao_app);
ui_selector->setAttribute(Qt::WA_TransparentForMouseEvents);
ui_selector->resize(62, 62);
ui_back_to_lobby = new AOButton(ui_char_select_background, ao_app); ui_back_to_lobby = new AOButton(ui_char_select_background, ao_app);
ui_char_password = new QLineEdit(ui_char_select_background); ui_char_password = new QLineEdit(ui_char_select_background);

View File

@ -46,7 +46,9 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
ui_vp_background = new BackgroundLayer(ui_viewport, ao_app); ui_vp_background = new BackgroundLayer(ui_viewport, ao_app);
ui_vp_speedlines = new SplashLayer(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 = 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 = new CharLayer(ui_viewport, ao_app);
ui_vp_sideplayer_char->masked = false;
ui_vp_sideplayer_char->hide(); ui_vp_sideplayer_char->hide();
ui_vp_desk = new BackgroundLayer(ui_viewport, ao_app); ui_vp_desk = new BackgroundLayer(ui_viewport, ao_app);
@ -976,9 +978,6 @@ void Courtroom::set_widgets()
set_size_and_pos(ui_sfx_slider, "sfx_slider"); set_size_and_pos(ui_sfx_slider, "sfx_slider");
set_size_and_pos(ui_blip_slider, "blip_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"); set_size_and_pos(ui_back_to_lobby, "back_to_lobby");
ui_back_to_lobby->setText(tr("Back to Lobby")); ui_back_to_lobby->setText(tr("Back to Lobby"));
ui_back_to_lobby->setToolTip(tr("Return back to the server list.")); ui_back_to_lobby->setToolTip(tr("Return back to the server list."));
@ -1645,6 +1644,11 @@ void Courtroom::append_server_chatmessage(QString p_name, QString p_message,
ui_server_chatlog->append_chatmessage(p_name, p_message, color); 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) void Courtroom::on_authentication_state_received(int p_state)
@ -1667,7 +1671,7 @@ void Courtroom::on_chat_return_pressed()
if (is_muted) if (is_muted)
return; return;
if ((anim_state < 3 || text_state < 2) && objection_state == 0) if (text_state < 2 && objection_state == 0)
return; return;
ui_ic_chat_message->blockSignals(true); ui_ic_chat_message->blockSignals(true);
@ -1980,7 +1984,7 @@ void Courtroom::chatmessage_enqueue(QStringList p_contents)
if (SHOWNAME < p_contents.size()) if (SHOWNAME < p_contents.size())
showname = p_contents[SHOWNAME]; 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 // Send this boi into the queue
chatmessage_queue.enqueue(p_contents); chatmessage_queue.enqueue(p_contents);
@ -2014,7 +2018,7 @@ void Courtroom::skip_chatmessage_queue()
while (!chatmessage_queue.isEmpty()) { while (!chatmessage_queue.isEmpty()) {
QStringList p_contents = chatmessage_queue.dequeue(); 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);
} }
} }
@ -2037,7 +2041,7 @@ void Courtroom::unpack_chatmessage(QStringList p_contents)
if (!ao_app->is_desyncrhonized_logs_enabled()) { 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. // 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 // Process the callwords for this message
@ -2056,18 +2060,13 @@ void Courtroom::unpack_chatmessage(QStringList p_contents)
handle_ic_message(); 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 // Display name will use the showname
QString f_displayname = f_showname; QString f_displayname = f_showname;
if (f_char_id != -1) { if (f_char_id != -1) {
// Grab the char.ini showname // Grab the char.ini showname
f_showname = ao_app->get_showname(char_list.at(f_char_id).name); 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 display name is just whitespace, use the char.ini showname.
if (f_displayname.trimmed().isEmpty()) if (f_displayname.trimmed().isEmpty())
@ -2077,16 +2076,15 @@ void Courtroom::log_chatmessage(QString f_message, int f_char_id, QString f_show
// Check if a custom objection is in use // Check if a custom objection is in use
int objection_mod = 0; int objection_mod = 0;
QString custom_objection = ""; QString custom_objection = "";
if (m_chatmessage[OBJECTION_MOD].contains("4&")) { if (f_objection_mod.contains("4&")) {
objection_mod = 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. "4&")[1]; // takes the name of custom objection.
} }
else { 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); QString f_custom_theme = ao_app->get_chat(f_char);
if (objection_mod <= 4 && objection_mod >= 1) { if (objection_mod <= 4 && objection_mod >= 1) {
QString shout_message; QString shout_message;
@ -2133,8 +2131,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 the evidence ID is in the valid range
if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) { if (f_evi_id > 0 && f_evi_id <= local_evidence_list.size()) {
// Obtain the evidence name // Obtain the evidence name
@ -2170,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); append_ic_text(f_message, f_displayname, "",f_color);
break; break;
} }
if (!ui_showname_enable->isChecked())
regenerate_ic_chatlog();
} }
bool Courtroom::handle_objection() bool Courtroom::handle_objection()
@ -2186,8 +2184,6 @@ bool Courtroom::handle_objection()
objection_mod = m_chatmessage[OBJECTION_MOD].toInt(); objection_mod = m_chatmessage[OBJECTION_MOD].toInt();
} }
// if an objection is used // if an objection is used
if (objection_mod <= 4 && objection_mod >= 1) { if (objection_mod <= 4 && objection_mod >= 1) {
ui_vp_objection->set_static_duration(shout_static_time); ui_vp_objection->set_static_duration(shout_static_time);
@ -2231,8 +2227,10 @@ bool Courtroom::handle_objection()
filename, m_chatmessage[CHAR_NAME], filename, m_chatmessage[CHAR_NAME],
ao_app->get_chat(m_chatmessage[CHAR_NAME])); ao_app->get_chat(m_chatmessage[CHAR_NAME]));
sfx_player->clear(); // Objection played! Cut all sfx. sfx_player->clear(); // Objection played! Cut all sfx.
ui_vp_player_char->set_play_once(true);
return true; return true;
} }
if (m_chatmessage[EMOTE] != "")
display_character(); display_character();
return false; return false;
} }
@ -2391,6 +2389,9 @@ void Courtroom::handle_ic_message()
// Update the chatbox information // Update the chatbox information
initialize_chatbox(); initialize_chatbox();
int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
bool immediate = m_chatmessage[IMMEDIATE].toInt() == 1;
if (m_chatmessage[EMOTE] != "") {
// Display our own character // Display our own character
display_character(); display_character();
@ -2399,14 +2400,20 @@ void Courtroom::handle_ic_message()
ui_vp_sideplayer_char->move(0, 0); ui_vp_sideplayer_char->move(0, 0);
// If the emote_mod is not zooming // If the emote_mod is not zooming
int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
if (emote_mod != 5 && emote_mod != 6) { if (emote_mod != 5 && emote_mod != 6) {
// Display the pair character // Display the pair character
display_pair_character(m_chatmessage[OTHER_CHARID], m_chatmessage[OTHER_OFFSET]); display_pair_character(m_chatmessage[OTHER_CHARID], m_chatmessage[OTHER_OFFSET]);
} }
// Parse the emote_mod part of the chat message // Parse the emote_mod part of the chat message
handle_emote_mod(m_chatmessage[EMOTE_MOD].toInt(), m_chatmessage[IMMEDIATE].toInt() == 1); 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 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) if (!ao_app->is_instant_objection_enabled() && chatmessage_queue.size() > 0)
@ -2523,7 +2530,6 @@ void Courtroom::initialize_chatbox()
if (f_charid >= 0 && f_charid < char_list.size() && if (f_charid >= 0 && f_charid < char_list.size() &&
(m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) { (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked())) {
QString real_name = char_list.at(f_charid).name; 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); QString f_showname = ao_app->get_showname(real_name);
ui_vp_showname->setText(f_showname); ui_vp_showname->setText(f_showname);
@ -2671,8 +2677,6 @@ void Courtroom::display_evidence_image()
void Courtroom::handle_ic_speaking() void Courtroom::handle_ic_speaking()
{ {
// Display the evidence
display_evidence_image();
QString side = m_chatmessage[SIDE]; QString side = m_chatmessage[SIDE];
int emote_mod = m_chatmessage[EMOTE_MOD].toInt(); int emote_mod = m_chatmessage[EMOTE_MOD].toInt();
// emote_mod 5 is zoom and emote_mod 6 is zoom w/ preanim. // emote_mod 5 is zoom and emote_mod 6 is zoom w/ preanim.
@ -3182,6 +3186,9 @@ void Courtroom::play_preanim(bool immediate)
void Courtroom::preanim_done() void Courtroom::preanim_done()
{ {
// Currently, someone's talking over us mid-preanim...
if (anim_state != 1 && anim_state != 4)
return;
anim_state = 1; anim_state = 1;
switch(m_chatmessage[DESK_MOD].toInt()) { switch(m_chatmessage[DESK_MOD].toInt()) {
case 4: case 4:
@ -3211,6 +3218,9 @@ void Courtroom::start_chat_ticking()
if (text_state != 0) if (text_state != 0)
return; return;
// Display the evidence
display_evidence_image();
if (m_chatmessage[EFFECTS] != "") { if (m_chatmessage[EFFECTS] != "") {
QStringList fx_list = m_chatmessage[EFFECTS].split("|"); QStringList fx_list = m_chatmessage[EFFECTS].split("|");
QString fx = fx_list[0]; QString fx = fx_list[0];
@ -3242,6 +3252,10 @@ void Courtroom::start_chat_ticking()
ui_vp_chatbox->show(); ui_vp_chatbox->show();
ui_vp_message->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. // 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(); int delay = ao_app->stay_time();
if (delay > 0 && !text_queue_timer->isActive()) if (delay > 0 && !text_queue_timer->isActive())
@ -3299,6 +3313,8 @@ void Courtroom::chat_tick()
if (tick_pos >= f_message.size()) { if (tick_pos >= f_message.size()) {
text_state = 2; text_state = 2;
// Check if we're a narrator msg
if (m_chatmessage[EMOTE] != "") {
if (anim_state < 3) { if (anim_state < 3) {
QStringList c_paths = { 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])),
@ -3319,6 +3335,9 @@ void Courtroom::chat_tick()
ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0, ui_vp_player_char->load_image(filename, m_chatmessage[CHAR_NAME], 0,
false); false);
} }
}
else // We're a narrator msg
anim_state = 3;
QString f_char; QString f_char;
QString f_custom_theme; QString f_custom_theme;
if (ao_app->is_customchat_enabled()) { if (ao_app->is_customchat_enabled()) {
@ -3361,22 +3380,9 @@ void Courtroom::chat_tick()
// Alignment characters // Alignment characters
if (tick_pos < 2) { if (tick_pos < 2) {
if (f_rest.startsWith("~~")) { if (f_rest.startsWith("~~") || f_rest.startsWith("~>") || f_rest.startsWith("<>"))
tick_pos = f_rest.indexOf("~~");
f_rest.remove(tick_pos, 2);
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;
}
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); f_rest.remove(0, tick_pos);
QTextBoundaryFinder tbf(QTextBoundaryFinder::Grapheme, f_rest); QTextBoundaryFinder tbf(QTextBoundaryFinder::Grapheme, f_rest);
QString f_character; QString f_character;
@ -3519,6 +3525,7 @@ void Courtroom::chat_tick()
msg_delay = qMin(max_delay, msg_delay * punctuation_modifier); msg_delay = qMin(max_delay, msg_delay * punctuation_modifier);
} }
if (m_chatmessage[EMOTE] != "") {
// If this color is talking // If this color is talking
if (color_is_talking && anim_state != 2 && if (color_is_talking && anim_state != 2 &&
anim_state < anim_state <
@ -3542,6 +3549,7 @@ void Courtroom::chat_tick()
false); false);
anim_state = 3; anim_state = 3;
} }
}
// Continue ticking // Continue ticking
chat_tick_timer->start(msg_delay); chat_tick_timer->start(msg_delay);
} }
@ -3891,15 +3899,9 @@ void Courtroom::case_called(QString msg, bool def, bool pro, bool jud, bool jur,
{ {
if (ui_casing->isChecked()) { if (ui_casing->isChecked()) {
ui_server_chatlog->append(msg); 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")); modcall_player->play(ao_app->get_court_sfx("case_call"));
ao_app->alert(this); ao_app->alert(this);
} }
}
} }
void Courtroom::on_ooc_return_pressed() void Courtroom::on_ooc_return_pressed()
@ -5260,8 +5262,6 @@ void Courtroom::on_reload_theme_clicked()
enter_courtroom(); enter_courtroom();
gen_char_rgb_list(ao_app->get_chat(current_char)); gen_char_rgb_list(ao_app->get_chat(current_char));
anim_state = 4;
text_state = 3;
objection_custom = ""; objection_custom = "";
// to update status on the background // to update status on the background

View File

@ -275,6 +275,56 @@ void DemoServer::load_demo(QString filename)
demo_data.enqueue(line); demo_data.enqueue(line);
line = demo_stream.readLine(); 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 <b>broken</b> pre-2.9.1 demo file with the <a href=https://github.com/AttorneyOnline/AO2-Client/pull/496>wait desync issue</a>!<br>Do you want to correct this file? <i>If you refuse, this demo will be desynchronized!</i>");
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 <QString> 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::reset_all_timers() void DemoServer::reset_all_timers()
@ -301,15 +351,18 @@ void DemoServer::playback()
if (current_packet.startsWith("MS#")) if (current_packet.startsWith("MS#"))
elapsed_time = 0; elapsed_time = 0;
while (!current_packet.startsWith("wait") && !demo_data.isEmpty()) { while (!current_packet.startsWith("wait#")) {
client_sock->write(current_packet.toUtf8()); client_sock->write(current_packet.toUtf8());
if (demo_data.isEmpty())
break;
current_packet = demo_data.dequeue(); current_packet = demo_data.dequeue();
} }
if (!demo_data.isEmpty()) { if (!demo_data.isEmpty()) {
AOPacket wait_packet = AOPacket(current_packet); AOPacket wait_packet = AOPacket(current_packet);
int duration = wait_packet.get_contents().at(0).toInt(); int duration = wait_packet.get_contents().at(0).toInt();
if (max_wait != -1 && duration + elapsed_time > max_wait) { if (max_wait != -1) {
if (duration + elapsed_time > max_wait) {
duration = qMax(0, max_wait - elapsed_time); duration = qMax(0, max_wait - elapsed_time);
// Skip the difference on the timers // Skip the difference on the timers
emit skip_timers(wait_packet.get_contents().at(0).toInt() - duration); emit skip_timers(wait_packet.get_contents().at(0).toInt() - duration);
@ -318,6 +371,7 @@ void DemoServer::playback()
duration = qMax(0, timer->interval() - elapsed_time); duration = qMax(0, timer->interval() - elapsed_time);
emit skip_timers(wait_packet.get_contents().at(0).toInt() - duration); emit skip_timers(wait_packet.get_contents().at(0).toInt() - duration);
} }
}
elapsed_time += duration; elapsed_time += duration;
timer->start(duration); timer->start(duration);
} }

View File

@ -308,7 +308,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet)
this->log_filename = QDateTime::currentDateTime().toUTC().toString( this->log_filename = QDateTime::currentDateTime().toUTC().toString(
"'logs/" + server_name.remove(QRegExp("[\\\\/:*?\"<>|\']")) + "'logs/" + server_name.remove(QRegExp("[\\\\/:*?\"<>|\']")) +
"/'yyyy-MM-dd hh-mm-ss t'.log'"); "/'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 " + server_address + " on " +
QDateTime::currentDateTime().toUTC().toString(), QDateTime::currentDateTime().toUTC().toString(),
log_filename, true); log_filename, true);

View File

@ -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 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; QStringList pathlist;
pathlist += p_element; // The path by itself
if (p_character != "") if (p_character != "")
pathlist += get_character_path(p_character, p_element); // Character folder pathlist += get_character_path(p_character, p_element); // Character folder
if (p_misc != "" && p_theme != "" && p_subtheme != "") 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 pathlist += get_theme_path(p_element, p_theme); // Theme path
if (p_default_theme != "") if (p_default_theme != "")
pathlist += get_theme_path(p_element, p_default_theme); // Default theme path pathlist += get_theme_path(p_element, p_default_theme); // Default theme path
pathlist += p_element; // The path by itself
if (p_placeholder != "" && p_theme != "") if (p_placeholder != "" && p_theme != "")
pathlist += get_theme_path(p_placeholder, p_theme); // Placeholder path pathlist += get_theme_path(p_placeholder, p_theme); // Placeholder path
if (p_placeholder != "" && p_default_theme != "") if (p_placeholder != "" && p_default_theme != "")
@ -173,6 +173,7 @@ QString AOApplication::get_config_value(QString p_identifier, QString p_config,
p = get_case_sensitive_path(p); p = get_case_sensitive_path(p);
if (file_exists(p)) { if (file_exists(p)) {
QSettings settings(p, QSettings::IniFormat); QSettings settings(p, QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QVariant value = settings.value(p_identifier); QVariant value = settings.value(p_identifier);
if (value.type() == QVariant::StringList) { if (value.type() == QVariant::StringList) {
// qDebug() << "got" << p << "is a string list, returning" << value.toStringList().join(","); // qDebug() << "got" << p << "is a string list, returning" << value.toStringList().join(",");

View File

@ -277,6 +277,7 @@ QString AOApplication::read_design_ini(QString p_identifier,
QString p_design_path) QString p_design_path)
{ {
QSettings settings(p_design_path, QSettings::IniFormat); QSettings settings(p_design_path, QSettings::IniFormat);
settings.setIniCodec("UTF-8");
QVariant value = settings.value(p_identifier); QVariant value = settings.value(p_identifier);
if (value.type() == QVariant::StringList) { if (value.type() == QVariant::StringList) {
return value.toStringList().join(","); return value.toStringList().join(",");
@ -435,7 +436,7 @@ QString AOApplication::get_chat_markup(QString p_identifier, QString p_chat)
// New Chadly method // New Chadly method
QString value = get_config_value(p_identifier, "chat_config.ini", current_theme, get_subtheme(), default_theme, p_chat); QString value = get_config_value(p_identifier, "chat_config.ini", current_theme, get_subtheme(), default_theme, p_chat);
if (!value.isEmpty()) if (!value.isEmpty())
return value.toLatin1(); return value.toUtf8();
// Backwards ass compatibility // Backwards ass compatibility
QStringList backwards_paths{get_theme_path("misc/" + p_chat + "/config.ini"), 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) { for (const QString &p : backwards_paths) {
QString value = read_design_ini(p_identifier, p); QString value = read_design_ini(p_identifier, p);
if (!value.isEmpty()) { 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 settings(get_character_path(p_char, "char.ini"),
QSettings::IniFormat); QSettings::IniFormat);
settings.beginGroup(target_tag); settings.beginGroup(target_tag);
settings.setIniCodec("UTF-8");
QString value = settings.value(p_search_line).value<QString>(); QString value = settings.value(p_search_line).value<QString>();
settings.endGroup(); settings.endGroup();
return value; return value;
@ -541,6 +543,7 @@ QStringList AOApplication::read_ini_tags(QString p_path, QString target_tag)
{ {
QStringList r_values; QStringList r_values;
QSettings settings(p_path, QSettings::IniFormat); QSettings settings(p_path, QSettings::IniFormat);
settings.setIniCodec("UTF-8");
if (!target_tag.isEmpty()) if (!target_tag.isEmpty())
settings.beginGroup(target_tag); settings.beginGroup(target_tag);
QStringList keys = settings.allKeys(); QStringList keys = settings.allKeys();