From 040898feff5d15f7236afb5e41c3bcc47e703a2a Mon Sep 17 00:00:00 2001 From: Crystalwarrior Date: Fri, 13 Sep 2019 15:11:30 +0300 Subject: [PATCH] Set up screenshake button ui Rewrite Goofball's doScreenshake() function to be much more modular and multi-purpose (also rename to do_screenshake() to match other functions) Add networking needed to make screenshake work. Works with AOV version of tsuserver3 (button screenshake only so far). Add get_theme_pos helper function, currently unused. --- include/aoapplication.h | 1 + include/courtroom.h | 15 +++- include/datatypes.h | 7 +- src/courtroom.cpp | 132 +++++++++++++++++++++++++++++++++++- src/packet_distribution.cpp | 3 + 5 files changed, 155 insertions(+), 3 deletions(-) diff --git a/include/aoapplication.h b/include/aoapplication.h index 4a3c669..8d998f4 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -78,6 +78,7 @@ public: bool arup_enabled = false; bool casing_alerts_enabled = false; bool modcall_reason_enabled = false; + bool looping_sfx_support_enabled = false; ///////////////loading info/////////////////// diff --git a/include/courtroom.h b/include/courtroom.h index b330337..682e12a 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -49,6 +49,9 @@ #include #include #include +#include +#include +#include #include @@ -124,6 +127,9 @@ public: //reads theme inis and sets size and pos based on the identifier void set_size_and_pos(QWidget *p_widget, QString p_identifier); + //reads theme inis and returns the size and pos as defined by it + QPoint get_theme_pos(QString p_identifier); + //sets status as taken on character with cid n_char and places proper shading on charselect void set_taken(int n_char, bool p_taken); @@ -213,6 +219,8 @@ public: void announce_case(QString title, bool def, bool pro, bool jud, bool jur, bool steno); void check_connection_received(); + void do_screenshake(); + void doRealization(); ~Courtroom(); @@ -231,6 +239,8 @@ private: bool first_message_sent = false; int maximumMessages = 0; + QParallelAnimationGroup *screenshake_animation_group; + // This is for inline message-colouring. enum INLINE_COLOURS { @@ -320,7 +330,7 @@ private: //the amount of time non-animated witness testimony/cross-examination images stay onscreen for in ms const int wtce_stay_time = 1500; - static const int chatmessage_size = 23; + static const int chatmessage_size = 28; QString m_chatmessage[chatmessage_size]; bool chatmessage_is_empty = false; @@ -346,6 +356,7 @@ private: int objection_state = 0; int realization_state = 0; + int screenshake_state = 0; int text_color = 0; bool is_presenting_evidence = false; @@ -472,6 +483,7 @@ private: AOButton *ui_custom_objection; AOButton *ui_realization; + AOButton *ui_screenshake; AOButton *ui_mute; AOButton *ui_defense_plus; @@ -595,6 +607,7 @@ private slots: void on_custom_objection_clicked(); void on_realization_clicked(); + void on_screenshake_clicked(); void on_mute_clicked(); void on_pair_clicked(); diff --git a/include/datatypes.h b/include/datatypes.h index aaa5de5..1b76f72 100644 --- a/include/datatypes.h +++ b/include/datatypes.h @@ -100,7 +100,12 @@ enum CHAT_MESSAGE SELF_OFFSET, OTHER_OFFSET, OTHER_FLIP, - NONINTERRUPTING_PRE + NONINTERRUPTING_PRE, + LOOPING_SFX, + SCREENSHAKE, + FRAME_SCREENSHAKE, + FRAME_REALIZATION, + FRAME_SFX }; enum COLOR diff --git a/src/courtroom.cpp b/src/courtroom.cpp index 5ae71f8..04c2f86 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -211,6 +211,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_custom_objection = new AOButton(this, ao_app); ui_realization = new AOButton(this, ao_app); + ui_screenshake = new AOButton(this, ao_app); ui_mute = new AOButton(this, ao_app); ui_defense_plus = new AOButton(this, ao_app); @@ -291,6 +292,7 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() connect(ui_custom_objection, SIGNAL(clicked()), this, SLOT(on_custom_objection_clicked())); connect(ui_realization, SIGNAL(clicked()), this, SLOT(on_realization_clicked())); + connect(ui_screenshake, SIGNAL(clicked()), this, SLOT(on_screenshake_clicked())); connect(ui_mute, SIGNAL(clicked()), this, SLOT(on_mute_clicked())); @@ -625,6 +627,9 @@ void Courtroom::set_widgets() set_size_and_pos(ui_realization, "realization"); ui_realization->set_image("realization.png"); + set_size_and_pos(ui_screenshake, "screenshake"); + ui_screenshake->set_image("screenshake.png"); + set_size_and_pos(ui_mute, "mute_button"); ui_mute->set_image("mute.png"); @@ -784,6 +789,23 @@ void Courtroom::set_taken(int n_char, bool p_taken) char_list.replace(n_char, f_char); } +QPoint Courtroom::get_theme_pos(QString p_identifier) +{ + QString filename = "courtroom_design.ini"; + + pos_size_type design_ini_result = ao_app->get_element_dimensions(p_identifier, filename); + + if (design_ini_result.width < 0 || design_ini_result.height < 0) + { + qDebug() << "W: could not find \"" << p_identifier << "\" in " << filename; + return QPoint(0,0); + } + else + { + return QPoint(design_ini_result.x, design_ini_result.y); + } +} + void Courtroom::done_received() { m_cid = -1; @@ -1232,6 +1254,50 @@ void Courtroom::on_chat_return_pressed() } } + // If the server we're on supports Looping SFX and Screenshake, use it if the emote uses it. + if (ao_app->looping_sfx_support_enabled) + { + packet_contents.append("0"); //ao_app->get_sfx_looping(current_char, current_emote)); +// qDebug() << "Are we looping this? " << ao_app->get_sfx_looping(current_char, current_emote); + packet_contents.append(QString::number(screenshake_state)); + qDebug() << "Are we screen shaking this one? " << screenshake_state; + + QString frame_screenshake = ""; + QString frame_realization = ""; + QString frame_sfx = ""; + + QString preemote_sfx = ao_app->get_pre_emote(current_char, current_emote) + "^"; + QString preemote_shake = ao_app->get_pre_emote(current_char, current_emote) + "^"; + QString preemote_flash = ao_app->get_pre_emote(current_char, current_emote) + "^"; + + QString talkemote_sfx = "(b)" + ao_app->get_emote(current_char, current_emote) + "^"; + QString talkemote_shake = "(b)" + ao_app->get_emote(current_char, current_emote) + "^"; + QString talkemote_flash = "(b)" + ao_app->get_emote(current_char, current_emote) + "^"; + + QString idleemote_sfx = "(a)" + ao_app->get_emote(current_char, current_emote) + "^"; + QString idleemote_shake = "(a)" + ao_app->get_emote(current_char, current_emote) + "^"; + QString idleemote_flash = "(a)" + ao_app->get_emote(current_char, current_emote) + "^"; + + frame_screenshake += preemote_shake; + frame_screenshake += talkemote_shake; + frame_screenshake += idleemote_shake; + + frame_realization += preemote_flash; + frame_realization += talkemote_flash; + frame_realization += idleemote_flash; + + frame_sfx += preemote_sfx; + frame_sfx += talkemote_sfx; + frame_sfx += idleemote_sfx; + qDebug() << "Final strings:"; + qDebug() << frame_screenshake; + qDebug() << frame_realization; + qDebug() << frame_sfx; + + packet_contents.append(frame_screenshake); + packet_contents.append(frame_realization); + packet_contents.append(frame_sfx); + } ao_app->send_server_packet(new AOPacket("MS", packet_contents)); } @@ -1300,6 +1366,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) ui_ic_chat_message->clear(); objection_state = 0; realization_state = 0; + screenshake_state = 0; is_presenting_evidence = false; ui_pre->setChecked(false); ui_hold_it->set_image("holdit.png"); @@ -1307,6 +1374,7 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) ui_take_that->set_image("takethat.png"); ui_custom_objection->set_image("custom.png"); ui_realization->set_image("realization.png"); + ui_screenshake->set_image("screenshake.png"); ui_evidence_present->set_image("present_disabled.png"); } @@ -1565,7 +1633,6 @@ void Courtroom::handle_chatmessage_2() } } } - switch (emote_mod) { case 1: case 2: case 6: @@ -1582,6 +1649,48 @@ void Courtroom::handle_chatmessage_2() } } +void Courtroom::do_screenshake() +{ + if (screenshake_animation_group && screenshake_animation_group->state() == QAbstractAnimation::Running) + screenshake_animation_group->setCurrentTime(screenshake_animation_group->duration()); //Force it to finish and delete itself + + screenshake_animation_group = new QParallelAnimationGroup; + + QList affected_list = { + ui_vp_background, + ui_vp_player_char, + ui_vp_sideplayer_char, + ui_vp_chatbox, + }; + + //I would prefer if this was its own "shake" function to be honest. + foreach (QWidget* ui_element, affected_list) + { + QPropertyAnimation *screenshake_animation = new QPropertyAnimation(ui_element, "pos", this); + QPoint pos_default = QPoint(ui_element->x(), ui_element->y()); + + int duration = 300; //How long does the screenshake last + int frequency = 20; //How often in ms is there a "jolt" frame + int maxframes = duration/frequency; + int max_x = 7; //Max deviation from origin on x axis + int max_y = 7; //Max deviation from origin on y axis + screenshake_animation->setDuration(duration); + for (int frame=0; frame < maxframes; frame++) + { + double fraction = double(frame*frequency)/duration; + quint32 rng = QRandomGenerator::global()->generate(); + int rand_x = int(rng) % max_x; + int rand_y = int(rng+100) % max_y; + screenshake_animation->setKeyValueAt(fraction, QPoint(pos_default.x() + rand_x, pos_default.y() + rand_y)); + } + screenshake_animation->setEndValue(pos_default); + screenshake_animation->setEasingCurve(QEasingCurve::Linear); + screenshake_animation_group->addAnimation(screenshake_animation); + } + + screenshake_animation_group->start(QAbstractAnimation::DeletionPolicy::DeleteWhenStopped); +} + void Courtroom::handle_chatmessage_3() { start_chat_ticking(); @@ -1978,6 +2087,11 @@ void Courtroom::start_chat_ticking() sfx_player->play(ao_app->get_custom_realization(m_chatmessage[CHAR_NAME])); } + if (m_chatmessage[SCREENSHAKE] == "1") + { + this->do_screenshake(); + } + ui_vp_message->clear(); set_text_color(); rainbow_counter = 0; @@ -3184,6 +3298,22 @@ void Courtroom::on_realization_clicked() ui_ic_chat_message->setFocus(); } +void Courtroom::on_screenshake_clicked() +{ + if (screenshake_state == 0) + { + screenshake_state = 1; + ui_screenshake->set_image("screenshake_pressed.png"); + } + else + { + screenshake_state = 0; + ui_screenshake->set_image("screenshake.png"); + } + + ui_ic_chat_message->setFocus(); +} + void Courtroom::on_mute_clicked() { if (ui_mute_list->isHidden()) diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index cfd6d8c..420aea2 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -156,6 +156,7 @@ void AOApplication::server_packet_received(AOPacket *p_packet) arup_enabled = false; casing_alerts_enabled = false; modcall_reason_enabled = false; + looping_sfx_support_enabled = false; //workaround for tsuserver4 if (f_contents.at(0) == "NOENCRYPT") @@ -216,6 +217,8 @@ void AOApplication::server_packet_received(AOPacket *p_packet) casing_alerts_enabled = true; if (f_packet.contains("modcall_reason",Qt::CaseInsensitive)) modcall_reason_enabled = true; + if (f_packet.contains("looping_sfx",Qt::CaseInsensitive)) + looping_sfx_support_enabled = true; } else if (header == "PN") {