diff --git a/Attorney_Online.pro b/Attorney_Online.pro index 39366c0..73d3534 100644 --- a/Attorney_Online.pro +++ b/Attorney_Online.pro @@ -11,7 +11,7 @@ OBJECTS_DIR = $$PWD/build MOC_DIR = $$PWD/build SOURCES += $$files($$PWD/src/*.cpp) -HEADERS += $$files($$PWD/include/*.h) +HEADERS += $$files($$PWD/include/*.h) $$PWD/include/aomusicplayer.h $$PWD/include/aosfxplayer.h LIBS += -L$$PWD/lib -lbass -ldiscord-rpc CONFIG += c++11 diff --git a/base/themes/default/courtroom_design.ini b/base/themes/default/courtroom_design.ini index 960d6e4..fe8fadf 100644 --- a/base/themes/default/courtroom_design.ini +++ b/base/themes/default/courtroom_design.ini @@ -132,6 +132,9 @@ call_mod = 104, 637, 64, 23 ; Mute button mute_button = 150, 515, 42, 42 +; Screenshake +screenshake = 51, 515, 42, 42 + ; Where the Mute list pops up when you click Mute mute_list = 280, 469, 210, 198 diff --git a/base/themes/default/screenshake.png b/base/themes/default/screenshake.png new file mode 100644 index 0000000..5b71e3b Binary files /dev/null and b/base/themes/default/screenshake.png differ diff --git a/base/themes/default/screenshake_pressed.png b/base/themes/default/screenshake_pressed.png new file mode 100644 index 0000000..43e01c8 Binary files /dev/null and b/base/themes/default/screenshake_pressed.png differ diff --git a/include/aoapplication.h b/include/aoapplication.h index 44aef7a..cff0afb 100644 --- a/include/aoapplication.h +++ b/include/aoapplication.h @@ -74,6 +74,7 @@ public: bool arup_enabled = false; bool casing_alerts_enabled = false; bool modcall_reason_enabled = false; + bool looping_sfx_support_enabled = false; ///////////////loading info/////////////////// @@ -94,9 +95,9 @@ public: //////////////////versioning/////////////// - constexpr int get_release() const { return RELEASE; } - constexpr int get_major_version() const { return MAJOR_VERSION; } - constexpr int get_minor_version() const { return MINOR_VERSION; } + int get_release() const { return RELEASE; } + int get_major_version() const { return MAJOR_VERSION; } + int get_minor_version() const { return MINOR_VERSION; } QString get_version_string(); /////////////////////////////////////////// @@ -146,6 +147,12 @@ public: //Returns true if blank blips is enabled in config.ini and false otherwise bool get_blank_blip(); + //Returns true if looping sound effects are enabled in the config.ini + bool get_looping_sfx(); + + //Returns true if kill music on object is enabled in the config.ini + bool get_objectmusic(); + //Returns the value of default_music in config.ini int get_default_music(); @@ -257,6 +264,18 @@ public: //Returns the sfx of p_char's p_emote QString get_sfx_name(QString p_char, int p_emote); + //Returns if an emote loops it's SFX + QString get_sfx_looping(QString p_char, int p_emote); + + //Returns if an emote has a frame specific SFX for it + QString get_frame_sfx_name(QString p_char, QString p_emote, int n_frame); + + //Returns if an emote has a frame specific SFX for it + QString get_realization_frame(QString p_char, QString p_emote, int n_frame); + + //Returns if an emote has a frame specific SFX for it + QString get_screenshake_frame(QString p_char, QString p_emote, int n_frame); + //Not in use int get_sfx_delay(QString p_char, int p_emote); @@ -299,8 +318,8 @@ public: private: const int RELEASE = 2; - const int MAJOR_VERSION = 6; - const int MINOR_VERSION = 1; + const int MAJOR_VERSION = 7; + const int MINOR_VERSION = 0; QString current_theme = "default"; diff --git a/include/aocharmovie.h b/include/aocharmovie.h index 7ef7da3..94e242b 100644 --- a/include/aocharmovie.h +++ b/include/aocharmovie.h @@ -6,9 +6,12 @@ #include #include #include +#include +#include "include/aosfxplayer.h" +#include "include/courtroom.h" + class AOApplication; - class AOCharMovie : public QLabel { Q_OBJECT @@ -22,25 +25,41 @@ public: void play_idle(QString p_char, QString p_emote); void set_flipped(bool p_flipped) {m_flipped = p_flipped;} - + void LoadImageWithStupidMethodForFlipSupport(QImage image); void stop(); void move(int ax, int ay); - void combo_resize(int w, int h); + void play_frame_sfx(); + void sfx_two_network_boogaloo(); + void screenshake_two_network_boogaloo(); + void realization_two_network_boogaloo(); + + AOSfxPlayer *frame_specific_sfx_player; + Courtroom *mycourtroom; + QString frame_sfx_hellstring = ""; + QString frame_screenshake_hellstring = ""; + QString frame_realization_hellstring = ""; + bool use_networked_framehell = false; private: AOApplication *ao_app; QMovie *m_movie; QVector movie_frames; QTimer *preanim_timer; + QTimer *ticker; + QString last_path; + QString current_emote; + QString current_char; const int time_mod = 62; // These are the X and Y values before they are fixed based on the sprite's width. int x = 0; int y = 0; + int default_w; + int default_h; bool m_flipped = false; @@ -50,8 +69,7 @@ signals: void done(); private slots: - void frame_change(int n_frame); void timer_done(); + void movie_ticker(); }; - #endif // AOCHARMOVIE_H diff --git a/include/aomusicplayer.h b/include/aomusicplayer.h index 560a7f9..54f3b5f 100644 --- a/include/aomusicplayer.h +++ b/include/aomusicplayer.h @@ -7,22 +7,32 @@ #include #include #include +#include +#include -class AOMusicPlayer +class AOMusicPlayer : public QObject { + Q_OBJECT public: AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app); - ~AOMusicPlayer(); - + virtual ~AOMusicPlayer(); void play(QString p_song); void set_volume(int p_value); + void kill_loop(); + QString get_path(); + private: QWidget *m_parent; AOApplication *ao_app; - + QTimer *music_loop_timer; int m_volume = 0; + QString f_path; + HSTREAM m_stream; + +private slots: + void restart_loop(); }; #endif // AOMUSICPLAYER_H diff --git a/include/aooptionsdialog.h b/include/aooptionsdialog.h index a65e3f5..03b1e71 100644 --- a/include/aooptionsdialog.h +++ b/include/aooptionsdialog.h @@ -80,6 +80,10 @@ private: QLabel *ui_bliprate_lbl; QCheckBox *ui_blank_blips_cb; QLabel *ui_blank_blips_lbl; + QLabel *ui_loopsfx_lbl; + QCheckBox *ui_loopsfx_cb; + QLabel *ui_objectmusic_lbl; + QCheckBox *ui_objectmusic_cb; QDialogButtonBox *ui_settings_buttons; QWidget *ui_casing_tab; diff --git a/include/aosfxplayer.h b/include/aosfxplayer.h index 30cbe9d..5c6f108 100644 --- a/include/aosfxplayer.h +++ b/include/aosfxplayer.h @@ -7,22 +7,28 @@ #include #include #include +#include -class AOSfxPlayer +class AOSfxPlayer : public QObject { + Q_OBJECT public: AOSfxPlayer(QWidget *parent, AOApplication *p_ao_app); void play(QString p_sfx, QString p_char = "", QString shout = ""); void stop(); void set_volume(int p_volume); - + void setLooping(bool is_looping); private: QWidget *m_parent; AOApplication *ao_app; + QTimer *sfx_loop_timer; int m_volume = 0; + bool looping_sfx = false; HSTREAM m_stream; +private slots: + void restart_loop(); }; #endif // AOSFXPLAYER_H diff --git a/include/courtroom.h b/include/courtroom.h index ec9f9ef..3f93e4c 100644 --- a/include/courtroom.h +++ b/include/courtroom.h @@ -25,6 +25,7 @@ #include "datatypes.h" #include "debug_functions.h" #include "chatlogpiece.h" +#include "aocharmovie.h" #include #include @@ -48,11 +49,15 @@ #include #include #include +#include +#include +#include +#include #include class AOApplication; - +class AOCharMovie; class Courtroom : public QMainWindow { Q_OBJECT @@ -63,7 +68,6 @@ public: void append_evidence(evi_type p_evi){evidence_list.append(p_evi);} void append_music(QString f_music){music_list.append(f_music);} void append_area(QString f_area){area_list.append(f_area);} - void fix_last_area() { if (area_list.size() > 0) @@ -210,6 +214,8 @@ public: void announce_case(QString title, bool def, bool pro, bool jud, bool jur, bool steno); void check_connection_received(); + void doScreenShake(); + void doRealization(); ~Courtroom(); @@ -227,7 +233,10 @@ private: bool first_message_sent = false; int maximumMessages = 0; - + QPropertyAnimation *screenshake_animation; + QPropertyAnimation *chatbox_screenshake_animation; + QParallelAnimationGroup *screenshake_group; + QImageReader *frame_emote_checker; // This is for inline message-colouring. enum INLINE_COLOURS { @@ -318,7 +327,7 @@ private: //every time point in char.inis times this equals the final time const int time_mod = 40; - static const int chatmessage_size = 23; + static const int chatmessage_size = 28; QString m_chatmessage[chatmessage_size]; bool chatmessage_is_empty = false; @@ -352,6 +361,7 @@ private: int objection_state = 0; int realization_state = 0; + int screenshake_state = 0; int text_color = 0; bool is_presenting_evidence = false; @@ -390,6 +400,9 @@ private: AOMusicPlayer *music_player; AOSfxPlayer *sfx_player; + AOSfxPlayer *misc_sfx_player; + AOSfxPlayer *frame_emote_sfx_player; + AOSfxPlayer *pair_frame_emote_sfx_player; AOSfxPlayer *objection_player; AOBlipPlayer *blip_player; @@ -478,6 +491,7 @@ private: AOButton *ui_custom_objection; AOButton *ui_realization; + AOButton *ui_screenshake; AOButton *ui_mute; AOButton *ui_defense_plus; @@ -605,6 +619,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/aocharmovie.cpp b/src/aocharmovie.cpp index 5748723..a5beefb 100644 --- a/src/aocharmovie.cpp +++ b/src/aocharmovie.cpp @@ -7,25 +7,26 @@ AOCharMovie::AOCharMovie(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent) { ao_app = p_ao_app; - m_movie = new QMovie(this); - preanim_timer = new QTimer(this); + ticker = new QTimer(this); preanim_timer->setSingleShot(true); - - connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frame_change(int))); + ticker->setSingleShot(true); + connect(ticker, SIGNAL(timeout()), this, SLOT(movie_ticker())); connect(preanim_timer, SIGNAL(timeout()), this, SLOT(timer_done())); + this->setUpdatesEnabled(true); } void AOCharMovie::play(QString p_char, QString p_emote, QString emote_prefix) { QString original_path = ao_app->get_character_path(p_char, emote_prefix + p_emote + ".gif"); - QString alt_path = ao_app->get_character_path(p_char, p_emote + ".png"); + QString alt_path = ao_app->get_character_path(p_char, emote_prefix + p_emote + ".png"); QString apng_path = ao_app->get_character_path(p_char, emote_prefix + p_emote + ".apng"); QString placeholder_path = ao_app->get_theme_path("placeholder.gif"); QString placeholder_default_path = ao_app->get_default_theme_path("placeholder.gif"); QString gif_path; - + current_emote = emote_prefix + p_emote; + current_char = p_char; if (file_exists(apng_path)) gif_path = apng_path; else if (file_exists(original_path)) @@ -36,138 +37,128 @@ void AOCharMovie::play(QString p_char, QString p_emote, QString emote_prefix) gif_path = placeholder_path; else gif_path = placeholder_default_path; - - m_movie->stop(); - m_movie->setFileName(gif_path); - - QImageReader *reader = new QImageReader(gif_path); - - movie_frames.clear(); - QImage f_image = reader->read(); - while (!f_image.isNull()) - { - if (m_flipped) - movie_frames.append(f_image.mirrored(true, false)); - else - movie_frames.append(f_image); - f_image = reader->read(); - } - - delete reader; - - this->show(); - m_movie->start(); -} - -void AOCharMovie::play_pre(QString p_char, QString p_emote, int duration) -{ - QString gif_path = ao_app->get_character_path(p_char, p_emote); - + delete m_movie; + m_movie = new QMovie(this); m_movie->stop(); this->clear(); m_movie->setFileName(gif_path); m_movie->jumpToFrame(0); + this->LoadImageWithStupidMethodForFlipSupport(m_movie->currentImage()); + qDebug() << "playing file path: " << gif_path; + this->show(); + this->play_frame_sfx(); + ticker->start(m_movie->nextFrameDelay()); +} - int full_duration = duration * time_mod; - int real_duration = 0; - - play_once = false; - - for (int n_frame = 0 ; n_frame < m_movie->frameCount() ; ++n_frame) +void AOCharMovie::play_frame_sfx() +{ + int current_frame = m_movie->currentFrameNumber(); + QString sfx_to_play = ao_app->get_frame_sfx_name(current_char, current_emote, current_frame); + QString screenshake_to_play = ao_app->get_screenshake_frame(current_char, current_emote, current_frame); + QString realization_to_play = ao_app->get_realization_frame(current_char, current_emote, current_frame); + if(sfx_to_play != "" && !use_networked_framehell) { - real_duration += m_movie->nextFrameDelay(); - m_movie->jumpToFrame(n_frame + 1); + frame_specific_sfx_player->play(ao_app->get_sfx_suffix(sfx_to_play)); } - -#ifdef DEBUG_GIF - qDebug() << "full_duration: " << full_duration; - qDebug() << "real_duration: " << real_duration; -#endif - - double percentage_modifier = 100.0; - - if (real_duration != 0 && duration != 0) + else if(use_networked_framehell) { - double modifier = full_duration / static_cast(real_duration); - percentage_modifier = 100 / modifier; - - if (percentage_modifier > 100.0) - percentage_modifier = 100.0; + this->sfx_two_network_boogaloo(); } - -#ifdef DEBUG_GIF - qDebug() << "% mod: " << percentage_modifier; -#endif - - if (full_duration == 0 || full_duration >= real_duration) + if(screenshake_to_play != "" && !use_networked_framehell) { - play_once = true; + mycourtroom->doScreenShake(); } - else + else if(use_networked_framehell) { - play_once = false; - preanim_timer->start(full_duration); + this->screenshake_two_network_boogaloo(); } - - - m_movie->setSpeed(static_cast(percentage_modifier)); - play(p_char, p_emote, ""); -} - -void AOCharMovie::play_talking(QString p_char, QString p_emote) -{ - QString gif_path = ao_app->get_character_path(p_char, "(b)" + p_emote); - - m_movie->stop(); - this->clear(); - m_movie->setFileName(gif_path); - - play_once = false; - m_movie->setSpeed(100); - play(p_char, p_emote, "(b)"); -} - -void AOCharMovie::play_idle(QString p_char, QString p_emote) -{ - QString gif_path = ao_app->get_character_path(p_char, "(a)" + p_emote); - - m_movie->stop(); - this->clear(); - m_movie->setFileName(gif_path); - - play_once = false; - m_movie->setSpeed(100); - play(p_char, p_emote, "(a)"); -} - -void AOCharMovie::stop() -{ - //for all intents and purposes, stopping is the same as hiding. at no point do we want a frozen gif to display - m_movie->stop(); - preanim_timer->stop(); - this->hide(); -} - -void AOCharMovie::combo_resize(int w, int h) -{ - QSize f_size(w, h); - this->resize(f_size); - m_movie->setScaledSize(f_size); -} - -void AOCharMovie::move(int ax, int ay) -{ - x = ax; - y = ay; - QLabel::move(x, y); -} - -void AOCharMovie::frame_change(int n_frame) -{ - - if (movie_frames.size() > n_frame) + if(realization_to_play != "" && !use_networked_framehell) { - QPixmap f_pixmap = QPixmap::fromImage(movie_frames.at(n_frame)); + mycourtroom->doRealization(); + } + else if(use_networked_framehell) + { + this->realization_two_network_boogaloo(); + } +} + +void AOCharMovie::realization_two_network_boogaloo() +{ + int current_frame = m_movie->currentFrameNumber(); + QStringList fucking_garbage = this->frame_realization_hellstring.split("^"); + for (int i = 0; i < fucking_garbage.length(); i++) { + QString fucking_christ = fucking_garbage.at(i); + QStringList extra_garbage = fucking_christ.split("|"); + if(extra_garbage.at(0) != current_emote){ + continue; + } + for (int ii = 1; ii < extra_garbage.length(); ii++) { + QString levels_of_garbage = extra_garbage.at(ii); + QStringList that_shouldnt_be_possible = levels_of_garbage.split("="); + if(that_shouldnt_be_possible.at(0).toInt() == current_frame && that_shouldnt_be_possible.at(1) != "") { + mycourtroom->doRealization(); + } + } + } +} + +void AOCharMovie::screenshake_two_network_boogaloo() +{ + int current_frame = m_movie->currentFrameNumber(); + QStringList fucking_garbage = this->frame_screenshake_hellstring.split("^"); + for (int i = 0; i < fucking_garbage.length(); i++) { + QString fucking_christ = fucking_garbage.at(i); + QStringList extra_garbage = fucking_christ.split("|"); + if(extra_garbage.at(0) != current_emote){ + continue; + } + for (int ii = 1; ii < extra_garbage.length(); ii++) { + QString levels_of_garbage = extra_garbage.at(ii); + QStringList that_shouldnt_be_possible = levels_of_garbage.split("="); + if(that_shouldnt_be_possible.at(0).toInt() == current_frame && that_shouldnt_be_possible.at(1) != "") { + mycourtroom->doScreenShake(); + } + } + } +} + +void AOCharMovie::sfx_two_network_boogaloo() +{ + int current_frame = m_movie->currentFrameNumber(); + QStringList fucking_garbage = this->frame_sfx_hellstring.split("^"); + for (int i = 0; i < fucking_garbage.length(); i++) { + QString fucking_christ = fucking_garbage.at(i); + QStringList extra_garbage = fucking_christ.split("|"); + if(extra_garbage.at(0) != current_emote){ + continue; + } + for (int ii = 1; ii < extra_garbage.length(); ii++) { + QString levels_of_garbage = extra_garbage.at(ii); + QStringList that_shouldnt_be_possible = levels_of_garbage.split("="); + if(that_shouldnt_be_possible.at(0).toInt() == current_frame && that_shouldnt_be_possible.at(1) != "") { + frame_specific_sfx_player->play(ao_app->get_sfx_suffix(that_shouldnt_be_possible.at(1))); + } + } + } +} + + +void AOCharMovie::movie_ticker() +{ + m_movie->jumpToNextFrame(); + this->LoadImageWithStupidMethodForFlipSupport(m_movie->currentImage()); // imagine if QT had sane stuff like "mirror on QMovie" or "resize the image on QT" or "interface with the current QMovie image" or anything else + // ps: fuck private functions/variables as a concept, freedom 2 do dangerous things 5ever + this->play_frame_sfx(); + ticker->start(m_movie->nextFrameDelay()); +} + +void AOCharMovie::LoadImageWithStupidMethodForFlipSupport(QImage image) +{ + QPixmap f_pixmap; + if(m_flipped) // imagine if QT wasn't handicapped harder than people who think MLP is good + f_pixmap = QPixmap::fromImage(image.mirrored(true, false)); + else + f_pixmap = QPixmap::fromImage(image); auto aspect_ratio = Qt::KeepAspectRatio; if (f_pixmap.size().width() > f_pixmap.size().height()) @@ -179,17 +170,62 @@ void AOCharMovie::frame_change(int n_frame) this->setPixmap(f_pixmap.scaled(this->width(), this->height(), aspect_ratio, Qt::FastTransformation)); QLabel::move(x + (this->width() - this->pixmap()->width())/2, y); - } +} - if (m_movie->frameCount() - 1 == n_frame && play_once) +void AOCharMovie::play_pre(QString p_char, QString p_emote, int duration) +{ + QString gif_path = ao_app->get_character_path(p_char, p_emote); + + m_movie->stop(); + m_movie->setFileName(gif_path); + m_movie->jumpToFrame(0); + int real_duration = 0; + for (int n_frame = 0 ; n_frame < m_movie->frameCount() ; ++n_frame) { - preanim_timer->start(m_movie->nextFrameDelay()); - m_movie->stop(); + qDebug() << "frame " << n_frame << " delay of " << m_movie->nextFrameDelay(); + real_duration += m_movie->nextFrameDelay(); + m_movie->jumpToFrame(n_frame + 1); } + play_once = true; + preanim_timer->start(real_duration); + play(p_char, p_emote, ""); +} + +void AOCharMovie::play_talking(QString p_char, QString p_emote) +{ + play_once = false; + play(p_char, p_emote, "(b)"); +} + +void AOCharMovie::play_idle(QString p_char, QString p_emote) +{ + play_once = false; + play(p_char, p_emote, "(a)"); +} + +void AOCharMovie::stop() +{ + //for all intents and purposes, stopping is the same as hiding. at no point do we want a frozen gif to display + m_movie->stop(); + preanim_timer->stop(); + frame_specific_sfx_player->stop(); + this->hide(); +} + +void AOCharMovie::combo_resize(int w, int h) +{ + QSize f_size(w, h); + this->resize(f_size); + m_movie->setScaledSize(this->size()); +} +void AOCharMovie::move(int ax, int ay) +{ + x = ax; + y = ay; + QLabel::move(x, y); } void AOCharMovie::timer_done() { - done(); } diff --git a/src/aomusicplayer.cpp b/src/aomusicplayer.cpp index 997d82d..a52603c 100644 --- a/src/aomusicplayer.cpp +++ b/src/aomusicplayer.cpp @@ -1,21 +1,25 @@ #include "aomusicplayer.h" -AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app) + +AOMusicPlayer::AOMusicPlayer(QWidget *parent, AOApplication *p_ao_app): QObject() { m_parent = parent; ao_app = p_ao_app; + music_loop_timer = new QTimer(this); + music_loop_timer->setSingleShot(true); + connect(music_loop_timer, SIGNAL(timeout()), this, SLOT(restart_loop())); } AOMusicPlayer::~AOMusicPlayer() { - BASS_ChannelStop(m_stream); + kill_loop(); } void AOMusicPlayer::play(QString p_song) { BASS_ChannelStop(m_stream); - QString f_path = ao_app->get_music_path(p_song); + f_path = ao_app->get_music_path(p_song); m_stream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, BASS_STREAM_AUTOFREE | BASS_UNICODE | BASS_ASYNCFILE); @@ -24,6 +28,15 @@ void AOMusicPlayer::play(QString p_song) if (ao_app->get_audio_output_device() != "default") BASS_ChannelSetDevice(m_stream, BASS_GetDevice()); BASS_ChannelPlay(m_stream, false); + music_loop_timer->stop(); + QWORD len=BASS_ChannelGetLength(m_stream, BASS_POS_BYTE); // the length in bytes + double time=BASS_ChannelBytes2Seconds(m_stream, len); // the length in seconds + if(time > 0) + { + qDebug() << "Will loop in " << time << " seconds."; + music_loop_timer->start(time*1000); + } + } void AOMusicPlayer::set_volume(int p_value) @@ -32,3 +45,28 @@ void AOMusicPlayer::set_volume(int p_value) float volume = m_volume / 100.0f; BASS_ChannelSetAttribute(m_stream, BASS_ATTRIB_VOL, volume); } + +QString AOMusicPlayer::get_path() +{ + return f_path; +} + +void AOMusicPlayer::restart_loop() +{ + qDebug() << "Restarting Music"; + /* + m_stream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, BASS_STREAM_AUTOFREE | BASS_UNICODE | BASS_ASYNCFILE); + if (ao_app->get_audio_output_device() != "default") + BASS_ChannelSetDevice(m_stream, BASS_GetDevice());*/ + QWORD len=BASS_ChannelGetLength(m_stream, BASS_POS_BYTE); // the length in bytes + double time=BASS_ChannelBytes2Seconds(m_stream, len); // the length in seconds + music_loop_timer->start(time*1000); + BASS_ChannelPlay(m_stream, true); +} + +void AOMusicPlayer::kill_loop() +{ + music_loop_timer->stop(); + BASS_ChannelStop(m_stream); +} + diff --git a/src/aooptionsdialog.cpp b/src/aooptionsdialog.cpp index cd69c76..4d0e479 100644 --- a/src/aooptionsdialog.cpp +++ b/src/aooptionsdialog.cpp @@ -312,6 +312,29 @@ AOOptionsDialog::AOOptionsDialog(QWidget *parent, AOApplication *p_ao_app) : QDi ui_audio_layout->setWidget(7, QFormLayout::FieldRole, ui_blank_blips_cb); + ui_loopsfx_lbl = new QLabel(ui_audio_widget); + ui_loopsfx_lbl->setText(tr("Enable Looping SFX:")); + ui_loopsfx_lbl->setToolTip(tr("If true, the game will allow looping sound effects to play on preanimations.")); + + ui_audio_layout->setWidget(8, QFormLayout::LabelRole, ui_loopsfx_lbl); + + ui_loopsfx_cb = new QCheckBox(ui_audio_widget); + ui_loopsfx_cb->setChecked(p_ao_app->get_looping_sfx()); + + ui_audio_layout->setWidget(8, QFormLayout::FieldRole, ui_loopsfx_cb); + + + ui_objectmusic_lbl = new QLabel(ui_audio_widget); + ui_objectmusic_lbl->setText(tr("Kill Music On Objection:")); + ui_objectmusic_lbl->setToolTip(tr("If true, the game will stop music when someone objects, like in the actual games.")); + + ui_audio_layout->setWidget(9, QFormLayout::LabelRole, ui_objectmusic_lbl); + + ui_objectmusic_cb = new QCheckBox(ui_audio_widget); + ui_objectmusic_cb->setChecked(p_ao_app->get_objectmusic()); + + ui_audio_layout->setWidget(9, QFormLayout::FieldRole, ui_objectmusic_cb); + // The casing tab! ui_casing_tab = new QWidget(); ui_settings_tabs->addTab(ui_casing_tab, tr("Casing")); @@ -483,6 +506,8 @@ void AOOptionsDialog::save_pressed() configini->setValue("default_blip", ui_blips_volume_spinbox->value()); configini->setValue("blip_rate", ui_bliprate_spinbox->value()); configini->setValue("blank_blip", ui_blank_blips_cb->isChecked()); + configini->setValue("looping_sfx", ui_loopsfx_cb->isChecked()); + configini->setValue("kill_music_on_object", ui_objectmusic_cb->isChecked()); configini->setValue("casing_enabled", ui_casing_enabled_cb->isChecked()); configini->setValue("casing_defence_enabled", ui_casing_def_cb->isChecked()); diff --git a/src/aosfxplayer.cpp b/src/aosfxplayer.cpp index 7fe7987..e219c03 100644 --- a/src/aosfxplayer.cpp +++ b/src/aosfxplayer.cpp @@ -1,10 +1,13 @@ #include "aosfxplayer.h" #include "file_functions.h" -AOSfxPlayer::AOSfxPlayer(QWidget *parent, AOApplication *p_ao_app) +AOSfxPlayer::AOSfxPlayer(QWidget *parent, AOApplication *p_ao_app): QObject() { m_parent = parent; ao_app = p_ao_app; + sfx_loop_timer = new QTimer(this); + sfx_loop_timer->setSingleShot(true); + connect(sfx_loop_timer, SIGNAL(timeout()), this, SLOT(restart_loop())); } void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout) @@ -28,7 +31,7 @@ void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout) f_path = misc_path; else f_path = sound_path; - + BASS_ChannelStop(m_stream); m_stream = BASS_StreamCreateFile(FALSE, f_path.utf16(), 0, 0, BASS_STREAM_AUTOFREE | BASS_UNICODE | BASS_ASYNCFILE); set_volume(m_volume); @@ -36,11 +39,35 @@ void AOSfxPlayer::play(QString p_sfx, QString p_char, QString shout) if (ao_app->get_audio_output_device() != "default") BASS_ChannelSetDevice(m_stream, BASS_GetDevice()); BASS_ChannelPlay(m_stream, false); + sfx_loop_timer->stop(); + QWORD len=BASS_ChannelGetLength(m_stream, BASS_POS_BYTE); // the length in bytes + double time=BASS_ChannelBytes2Seconds(m_stream, len); // the length in seconds + if(time > 0 && looping_sfx && ao_app->get_looping_sfx()) + { + sfx_loop_timer->start(time*1000); + } +} + +void AOSfxPlayer::setLooping(bool is_looping) +{ + this->looping_sfx = is_looping; } void AOSfxPlayer::stop() { BASS_ChannelStop(m_stream); + sfx_loop_timer->stop(); +} + +void AOSfxPlayer::restart_loop() +{ + if(ao_app->get_looping_sfx() && looping_sfx) + { + QWORD len=BASS_ChannelGetLength(m_stream, BASS_POS_BYTE); // the length in bytes + double time=BASS_ChannelBytes2Seconds(m_stream, len); // the length in seconds + sfx_loop_timer->start(time*1000); + BASS_ChannelPlay(m_stream, true); + } } void AOSfxPlayer::set_volume(int p_value) diff --git a/src/courtroom.cpp b/src/courtroom.cpp index be7629b..ab387da 100644 --- a/src/courtroom.cpp +++ b/src/courtroom.cpp @@ -56,7 +56,13 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() sfx_player = new AOSfxPlayer(this, ao_app); sfx_player->set_volume(0); objection_player = new AOSfxPlayer(this, ao_app); - sfx_player->set_volume(0); + objection_player->set_volume(0); + misc_sfx_player = new AOSfxPlayer(this, ao_app); + misc_sfx_player->set_volume(0); + frame_emote_sfx_player = new AOSfxPlayer(this, ao_app); + frame_emote_sfx_player->set_volume(0); + pair_frame_emote_sfx_player = new AOSfxPlayer(this, ao_app); // todo: recode pair // todo: recode fucking everything + pair_frame_emote_sfx_player->set_volume(0); blip_player = new AOBlipPlayer(this, ao_app); blip_player->set_volume(0); @@ -70,7 +76,11 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow() ui_vp_speedlines = new AOMovie(ui_viewport, ao_app); ui_vp_speedlines->set_play_once(false); ui_vp_player_char = new AOCharMovie(ui_viewport, ao_app); + ui_vp_player_char->frame_specific_sfx_player = frame_emote_sfx_player; + ui_vp_player_char->mycourtroom = this; ui_vp_sideplayer_char = new AOCharMovie(ui_viewport, ao_app); + ui_vp_sideplayer_char->frame_specific_sfx_player = pair_frame_emote_sfx_player; + ui_vp_sideplayer_char->mycourtroom = this; ui_vp_sideplayer_char->hide(); ui_vp_desk = new AOScene(ui_viewport, ao_app); ui_vp_legacy_desk = new AOScene(ui_viewport, ao_app); @@ -200,6 +210,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); @@ -284,7 +295,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())); connect(ui_defense_minus, SIGNAL(clicked()), this, SLOT(on_defense_minus_clicked())); @@ -622,6 +633,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"); @@ -909,6 +923,9 @@ void Courtroom::enter_courtroom(int p_cid) music_player->set_volume(ui_music_slider->value()); sfx_player->set_volume(ui_sfx_slider->value()); objection_player->set_volume(ui_sfx_slider->value()); + misc_sfx_player->set_volume(ui_sfx_slider->value()); + frame_emote_sfx_player->set_volume(ui_sfx_slider->value()); + pair_frame_emote_sfx_player->set_volume(ui_sfx_slider->value()); blip_player->set_volume(ui_blip_slider->value()); testimony_in_progress = false; @@ -1227,7 +1244,126 @@ void Courtroom::on_chat_return_pressed() packet_contents.append("0"); } } + // 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(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 = ""; + QString preemote_shake = ""; + QString preemote_flash = ""; + + QString talkemote_sfx = ""; + QString talkemote_shake = ""; + QString talkemote_flash = ""; + + QString idleemote_sfx = ""; + QString idleemote_shake = ""; + QString idleemote_flash = ""; + + QString preemote = ao_app->get_image_suffix(ao_app->get_character_path(current_char, ao_app->get_pre_emote(current_char, current_emote))); + QString talkemote_to_check = ao_app->get_image_suffix(ao_app->get_character_path(current_char, "(b)" + ao_app->get_emote(current_char, current_emote))); + QString idleemote_to_check = ao_app->get_image_suffix(ao_app->get_character_path(current_char, "(a)" + ao_app->get_emote(current_char, current_emote))); + frame_emote_checker = new QImageReader(preemote); + preemote_sfx += ao_app->get_pre_emote(current_char, current_emote); + preemote_shake += ao_app->get_pre_emote(current_char, current_emote); + preemote_flash += ao_app->get_pre_emote(current_char, current_emote); + for (int i = 0; i < frame_emote_checker->imageCount(); i++) { + QString sfx_to_play = ao_app->get_frame_sfx_name(current_char, ao_app->get_pre_emote(current_char, current_emote), i); + QString screenshake_to_play = ao_app->get_screenshake_frame(current_char, ao_app->get_pre_emote(current_char, current_emote), i); + QString realization_to_play = ao_app->get_realization_frame(current_char, ao_app->get_pre_emote(current_char, current_emote), i); + if(sfx_to_play != "") + { + preemote_sfx += "|" + QString::number(i) + "=" + sfx_to_play; + } + if(screenshake_to_play != "") + { + preemote_shake += "|" + QString::number(i) + "=" + screenshake_to_play; + } + if(realization_to_play != "") + { + preemote_flash += "|" + QString::number(i) + "=" + realization_to_play; + } + } + preemote_sfx += "^"; + preemote_shake += "^"; + preemote_flash += "^"; + delete frame_emote_checker; + talkemote_sfx += "(b)" + ao_app->get_emote(current_char, current_emote); + talkemote_shake += "(b)" + ao_app->get_emote(current_char, current_emote); + talkemote_flash += "(b)" + ao_app->get_emote(current_char, current_emote); + frame_emote_checker = new QImageReader(talkemote_to_check); + for (int i = 0; i < frame_emote_checker->imageCount(); i++) { + QString sfx_to_play = ao_app->get_frame_sfx_name(current_char, "(b)" + ao_app->get_emote(current_char, current_emote), i); + QString screenshake_to_play = ao_app->get_screenshake_frame(current_char, "(b)" + ao_app->get_emote(current_char, current_emote), i); + QString realization_to_play = ao_app->get_realization_frame(current_char, "(b)" + ao_app->get_emote(current_char, current_emote), i); + if(sfx_to_play != "") + { + talkemote_sfx += "|" + QString::number(i) + "=" + sfx_to_play; + } + if(screenshake_to_play != "") + { + talkemote_shake += "|" + QString::number(i) + "=" + screenshake_to_play; + } + if(realization_to_play != "") + { + talkemote_flash += "|" + QString::number(i) + "=" + realization_to_play; + } + } + talkemote_sfx += "^"; + talkemote_shake += "^"; + talkemote_flash += "^"; + delete frame_emote_checker; + idleemote_sfx += "(a)" + ao_app->get_emote(current_char, current_emote); + idleemote_shake += "(a)" + ao_app->get_emote(current_char, current_emote); + idleemote_flash += "(a)" + ao_app->get_emote(current_char, current_emote); + frame_emote_checker = new QImageReader(idleemote_to_check); + for (int i = 0; i < frame_emote_checker->imageCount(); i++) { + QString sfx_to_play = ao_app->get_frame_sfx_name(current_char, "(a)" + ao_app->get_emote(current_char, current_emote), i); + QString screenshake_to_play = ao_app->get_screenshake_frame(current_char, "(a)" + ao_app->get_emote(current_char, current_emote), i); + QString realization_to_play = ao_app->get_realization_frame(current_char, "(a)" + ao_app->get_emote(current_char, current_emote), i); + if(sfx_to_play != "") + { + idleemote_sfx += "|" + QString::number(i) + "=" + sfx_to_play; + } + if(screenshake_to_play != "") + { + idleemote_shake += "|" + QString::number(i) + "=" + screenshake_to_play; + } + if(realization_to_play != "") + { + idleemote_flash += "|" + QString::number(i) + "=" + realization_to_play; + } + } + delete frame_emote_checker; + + 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)); } @@ -1296,6 +1432,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"); @@ -1303,6 +1440,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"); } @@ -1334,6 +1472,8 @@ void Courtroom::handle_chatmessage(QStringList *p_contents) case 2: ui_vp_objection->play("objection", f_char, f_custom_theme); objection_player->play("objection.wav", f_char, f_custom_theme); + if(ao_app->get_objectmusic()) + music_player->kill_loop(); break; case 3: ui_vp_objection->play("takethat", f_char, f_custom_theme); @@ -1366,7 +1506,10 @@ void Courtroom::handle_chatmessage_2() { ui_vp_speedlines->stop(); ui_vp_player_char->stop(); - + ui_vp_player_char->frame_sfx_hellstring = m_chatmessage[FRAME_SFX]; + ui_vp_player_char->frame_realization_hellstring = m_chatmessage[FRAME_REALIZATION]; + ui_vp_player_char->frame_screenshake_hellstring = m_chatmessage[FRAME_SCREENSHAKE]; + ui_vp_player_char->use_networked_framehell = true; if (m_chatmessage[SHOWNAME].isEmpty() || !ui_showname_enable->isChecked()) { QString real_name = char_list.at(m_chatmessage[CHAR_ID].toInt()).name; @@ -1548,6 +1691,7 @@ void Courtroom::handle_chatmessage_2() ui_vp_sideplayer_char->set_flipped(true); else ui_vp_sideplayer_char->set_flipped(false); + ui_vp_sideplayer_char->use_networked_framehell = false; ui_vp_sideplayer_char->play_idle(m_chatmessage[OTHER_NAME], m_chatmessage[OTHER_EMOTE]); } else @@ -1555,13 +1699,17 @@ void Courtroom::handle_chatmessage_2() // If the server understands other characters, but there // really is no second character, hide 'em, and center the first. ui_vp_sideplayer_char->hide(); + ui_vp_sideplayer_char->stop(); ui_vp_sideplayer_char->move(0,0); ui_vp_player_char->move(0,0); } } } - + if (m_chatmessage[SCREENSHAKE] == "1") + { + this->doScreenShake(); + } switch (emote_mod) { case 1: case 2: case 6: @@ -1578,6 +1726,53 @@ void Courtroom::handle_chatmessage_2() } } +void Courtroom::doScreenShake() +{ + screenshake_group = new QParallelAnimationGroup; + screenshake_animation = new QPropertyAnimation(ui_viewport, "pos", this); + chatbox_screenshake_animation = new QPropertyAnimation(ui_vp_chatbox, "pos", this); + int screen_x = ui_viewport->x(); + int screen_y = ui_viewport->y(); + QPoint pos_default = QPoint(screen_x, screen_y); + QPoint pos1 = QPoint(screen_x + 3, screen_y + -5); + QPoint pos2 = QPoint(screen_x + 3, screen_y + -5); + QPoint pos3 = QPoint(screen_x + -3, screen_y + 5); + QPoint pos4 = QPoint(screen_x + 3, screen_y + -5); + QPoint pos5 = QPoint(screen_x + -3,screen_y + -5); + + int chatbox_x = ui_vp_chatbox->x(); + int chatbox_y = ui_vp_chatbox->y(); + QPoint chatbox_pos_default = QPoint(chatbox_x, chatbox_y); + QPoint chatbox_pos1 = QPoint(chatbox_x + 3, chatbox_y + -5); + QPoint chatbox_pos2 = QPoint(chatbox_x + 3, chatbox_y + -5); + QPoint chatbox_pos3 = QPoint(chatbox_x + -3, chatbox_y + 5); + QPoint chatbox_pos4 = QPoint(chatbox_x + 3, chatbox_y + -5); + QPoint chatbox_pos5 = QPoint(chatbox_x + -3,chatbox_y + -5); + + screenshake_animation->setDuration(200); + screenshake_animation->setKeyValueAt(0, pos_default); + screenshake_animation->setKeyValueAt(0.1, pos1); + screenshake_animation->setKeyValueAt(0.3, pos2); + screenshake_animation->setKeyValueAt(0.5, pos3); + screenshake_animation->setKeyValueAt(0.7, pos4); + screenshake_animation->setKeyValueAt(0.9, pos5); + screenshake_animation->setEndValue(pos_default); + screenshake_animation->setEasingCurve(QEasingCurve::Linear); + chatbox_screenshake_animation->setDuration(200); + chatbox_screenshake_animation->setKeyValueAt(0, chatbox_pos_default); + chatbox_screenshake_animation->setKeyValueAt(0.1, chatbox_pos3); + chatbox_screenshake_animation->setKeyValueAt(0.3, chatbox_pos5); + chatbox_screenshake_animation->setKeyValueAt(0.5, chatbox_pos2); + chatbox_screenshake_animation->setKeyValueAt(0.7, chatbox_pos1); + chatbox_screenshake_animation->setKeyValueAt(0.9, chatbox_pos4); + chatbox_screenshake_animation->setEndValue(chatbox_pos_default); + chatbox_screenshake_animation->setEasingCurve(QEasingCurve::Linear); + + screenshake_group->addAnimation(screenshake_animation); + screenshake_group->addAnimation(chatbox_screenshake_animation); + screenshake_group->start(QAbstractAnimation::DeletionPolicy::DeleteWhenStopped); +} + void Courtroom::handle_chatmessage_3() { start_chat_ticking(); @@ -1709,6 +1904,17 @@ QString Courtroom::filter_ic_text(QString p_text) p_text.remove(trick_check_pos,1); } + else if (f_character == "$" and !ic_next_is_not_special) + { + p_text.remove(trick_check_pos,1); + } + + else if (f_character == "@" and !ic_next_is_not_special) + { + p_text.remove(trick_check_pos,1); + } + + // Orange inline colourisation. else if (f_character == "|" and !ic_next_is_not_special) { @@ -1919,14 +2125,14 @@ void Courtroom::play_preanim(bool noninterrupting) int ao2_duration = ao_app->get_ao2_preanim_duration(f_char, f_preanim); int text_delay = ao_app->get_text_delay(f_char, f_preanim) * time_mod; int sfx_delay = m_chatmessage[SFX_DELAY].toInt() * 60; - + bool looping_sfx = m_chatmessage[LOOPING_SFX] == "1"; int preanim_duration; if (ao2_duration < 0) preanim_duration = ao_app->get_preanim_duration(f_char, f_preanim); else preanim_duration = ao2_duration; - + sfx_player->setLooping(looping_sfx); sfx_delay_timer->start(sfx_delay); QString anim_to_find = ao_app->get_image_suffix(ao_app->get_character_path(f_char, f_preanim)); if (!file_exists(anim_to_find) || @@ -1942,7 +2148,6 @@ void Courtroom::play_preanim(bool noninterrupting) } ui_vp_player_char->play_pre(f_char, f_preanim, preanim_duration); - if (noninterrupting) anim_state = 4; else @@ -1966,6 +2171,13 @@ void Courtroom::realization_done() ui_vp_realization->hide(); } +void Courtroom::doRealization() +{ + realization_timer->start(60); + ui_vp_realization->show(); + +} + void Courtroom::start_chat_ticking() { //we need to ensure that the text isn't already ticking because this function can be called by two logic paths @@ -1974,11 +2186,9 @@ void Courtroom::start_chat_ticking() if (m_chatmessage[REALIZATION] == "1") { - realization_timer->start(60); - ui_vp_realization->show(); - sfx_player->play(ao_app->get_custom_realization(m_chatmessage[CHAR_NAME])); + this->doRealization(); + misc_sfx_player->play(ao_app->get_custom_realization(m_chatmessage[CHAR_NAME])); } - ui_vp_message->clear(); set_text_color(); rainbow_counter = 0; @@ -2076,6 +2286,18 @@ void Courtroom::chat_tick() formatting_char = true; } + else if (f_character == "@" and !next_character_is_not_special) + { + this->doScreenShake(); + formatting_char = true; + } + + else if (f_character == "$" and !next_character_is_not_special) + { + this->doRealization(); + formatting_char = true; + } + // Orange inline colourisation. else if (f_character == "|" and !next_character_is_not_special) { @@ -2541,7 +2763,7 @@ void Courtroom::handle_wtce(QString p_wtce, int variant) //witness testimony if (p_wtce == "testimony1") { - sfx_player->play(ao_app->get_sfx("witness_testimony")); + misc_sfx_player->play(ao_app->get_sfx("witness_testimony")); ui_vp_wtce->play("witnesstestimony"); testimony_in_progress = true; show_testimony(); @@ -2549,7 +2771,7 @@ void Courtroom::handle_wtce(QString p_wtce, int variant) //cross examination else if (p_wtce == "testimony2") { - sfx_player->play(ao_app->get_sfx("cross_examination")); + misc_sfx_player->play(ao_app->get_sfx("cross_examination")); ui_vp_wtce->play("crossexamination"); testimony_in_progress = false; } @@ -2557,12 +2779,12 @@ void Courtroom::handle_wtce(QString p_wtce, int variant) { if (variant == 0) { - sfx_player->play(ao_app->get_sfx("not_guilty")); + misc_sfx_player->play(ao_app->get_sfx("not_guilty")); ui_vp_wtce->play("notguilty"); testimony_in_progress = false; } else if (variant == 1) { - sfx_player->play(ao_app->get_sfx("guilty")); + misc_sfx_player->play(ao_app->get_sfx("guilty")); ui_vp_wtce->play("guilty"); testimony_in_progress = false; } @@ -3140,6 +3362,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()) @@ -3223,6 +3461,9 @@ void Courtroom::on_sfx_slider_moved(int p_value) { sfx_player->set_volume(p_value); objection_player->set_volume(p_value); + misc_sfx_player->set_volume(p_value); + frame_emote_sfx_player->set_volume(p_value); + pair_frame_emote_sfx_player->set_volume(p_value); ui_ic_chat_message->setFocus(); } diff --git a/src/packet_distribution.cpp b/src/packet_distribution.cpp index 68d2fb9..f8adb12 100644 --- a/src/packet_distribution.cpp +++ b/src/packet_distribution.cpp @@ -151,6 +151,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") @@ -209,6 +210,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; w_lobby->enable_connect_button(); } diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp index 1e920d7..e8cfeba 100644 --- a/src/text_file_functions.cpp +++ b/src/text_file_functions.cpp @@ -555,6 +555,42 @@ QString AOApplication::get_sfx_name(QString p_char, int p_emote) else return f_result; } +QString AOApplication::get_sfx_looping(QString p_char, int p_emote) +{ + QString f_result = read_char_ini(p_char, QString::number(p_emote + 1), "SoundL"); + + if (f_result == "") + return "0"; + else return f_result; +} + +QString AOApplication::get_frame_sfx_name(QString p_char, QString p_emote, int n_frame) +{ + QString f_result = read_char_ini(p_char, QString::number(n_frame), p_emote.append("_FrameSFX")); + if (f_result == "") + return ""; + else return f_result; +} + +QString AOApplication::get_screenshake_frame(QString p_char, QString p_emote, int n_frame) +{ + QString f_result = read_char_ini(p_char, QString::number(n_frame), p_emote.append("_FrameScreenshake")); + if (f_result == "") + return ""; + else return f_result; +} + + +QString AOApplication::get_realization_frame(QString p_char, QString p_emote, int n_frame) +{ + QString f_result = read_char_ini(p_char, QString::number(n_frame), p_emote.append("_FrameRealization")); + if (f_result == "") + return ""; + else return f_result; +} + + + int AOApplication::get_sfx_delay(QString p_char, int p_emote) { QString f_result = read_char_ini(p_char, QString::number(p_emote + 1), "SoundT"); @@ -588,6 +624,18 @@ bool AOApplication::get_blank_blip() return result.startsWith("true"); } +bool AOApplication::get_looping_sfx() +{ + QString result = configini->value("looping_sfx", "true").value(); + return result.startsWith("true"); +} + +bool AOApplication::get_objectmusic() +{ + QString result = configini->value("kill_music_on_object", "true").value(); + return result.startsWith("true"); +} + bool AOApplication::is_discord_enabled() { QString result = configini->value("discord", "true").value();