aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/aoapplication.h12
-rw-r--r--include/aocharmovie.h12
-rw-r--r--include/aomovie.h1
-rw-r--r--include/courtroom.h7
-rw-r--r--src/aocharmovie.cpp57
-rw-r--r--src/aomovie.cpp16
-rw-r--r--src/courtroom.cpp114
-rw-r--r--src/text_file_functions.cpp36
8 files changed, 200 insertions, 55 deletions
diff --git a/include/aoapplication.h b/include/aoapplication.h
index 8d998f46..8164e166 100644
--- a/include/aoapplication.h
+++ b/include/aoapplication.h
@@ -271,6 +271,18 @@ public:
//Returns the sfx of p_char's p_emote
QString get_sfx_name(QString p_char, int p_emote);
+ //Returns if the sfx is defined as looping in char.ini
+ QString get_sfx_looping(QString p_char, QString p_sfx);
+
+ //Returns if an emote has a frame specific SFX for it
+ QString get_sfx_frame(QString p_char, QString p_emote, int n_frame);
+
+ //Returns if an emote has a frame specific SFX for it
+ QString get_flash_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);
diff --git a/include/aocharmovie.h b/include/aocharmovie.h
index b8b73b7e..5eaafaf6 100644
--- a/include/aocharmovie.h
+++ b/include/aocharmovie.h
@@ -32,6 +32,9 @@ public:
//Play an (a)normal.gif - style animation (not talking)
void play_idle(QString p_char, QString p_emote);
+ //Play a frame-specific effect, if there's any defined for that specific frame.
+ void play_frame_effect(int frame);
+
//Retreive a pixmap adjused for mirroring/aspect ratio shenanigans from a provided QImage
QPixmap get_pixmap(QImage image);
@@ -61,6 +64,12 @@ private:
QVector<QPixmap> movie_frames;
QVector<int> movie_delays;
+
+ //Effects such as sfx, screenshakes and realization flashes are stored in here.
+ //QString entry format: "sfx^[sfx_name]", "shake", "flash".
+ //The program uses the QVector index as reference.
+ QVector<QVector<QString>> movie_effects;
+
QTimer *preanim_timer;
QTimer *ticker;
QString last_path;
@@ -83,6 +92,9 @@ private:
signals:
void done();
+ void shake();
+ void flash();
+ void play_sfx(QString sfx);
private slots:
void preanim_done();
diff --git a/include/aomovie.h b/include/aomovie.h
index 974559d2..a5af735e 100644
--- a/include/aomovie.h
+++ b/include/aomovie.h
@@ -15,7 +15,6 @@ public:
AOMovie(QWidget *p_parent, AOApplication *p_ao_app);
void set_play_once(bool p_play_once);
- void start_timer(int delay);
void play(QString p_gif, QString p_char = "", QString p_custom_theme = "", int default_duration = 0);
void combo_resize(int w, int h);
void stop();
diff --git a/include/courtroom.h b/include/courtroom.h
index 9c79a3e3..7fbde274 100644
--- a/include/courtroom.h
+++ b/include/courtroom.h
@@ -219,8 +219,6 @@ 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();
@@ -239,7 +237,7 @@ private:
bool first_message_sent = false;
int maximumMessages = 0;
- QParallelAnimationGroup *screenshake_animation_group;
+ QParallelAnimationGroup *screenshake_animation_group = new QParallelAnimationGroup;
// This is for inline message-colouring.
@@ -557,6 +555,9 @@ private:
public slots:
void objection_done();
void preanim_done();
+ void do_screenshake();
+ void do_flash();
+ void play_char_sfx(QString sfx_name);
void mod_called(QString p_ip);
diff --git a/src/aocharmovie.cpp b/src/aocharmovie.cpp
index 0c389b1e..efe24735 100644
--- a/src/aocharmovie.cpp
+++ b/src/aocharmovie.cpp
@@ -47,6 +47,7 @@ void AOCharMovie::load_image(QString p_char, QString p_emote, QString emote_pref
preanim_timer->stop();
movie_frames.clear();
movie_delays.clear();
+ movie_effects.clear();
m_reader->setFileName(emote_path);
QPixmap f_pixmap = this->get_pixmap(m_reader->read());
@@ -62,6 +63,32 @@ void AOCharMovie::load_image(QString p_char, QString p_emote, QString emote_pref
movie_frames.append(f_pixmap);
movie_delays.append(f_delay);
}
+
+ movie_effects.resize(max_frames);
+ for (int e_frame = 0; e_frame < max_frames; ++e_frame)
+ {
+ qDebug() << p_char << p_emote << e_frame;
+ QString effect = ao_app->get_screenshake_frame(p_char, emote_prefix + p_emote, e_frame);
+ if (effect != "")
+ {
+ movie_effects[e_frame].append("shake");
+ qDebug() << e_frame << "shake";
+ }
+
+ effect = ao_app->get_flash_frame(p_char, emote_prefix + p_emote, e_frame);
+ if (effect != "")
+ {
+ movie_effects[e_frame].append("flash");
+ qDebug() << e_frame << "flash";
+ }
+
+ effect = ao_app->get_sfx_frame(p_char, emote_prefix + p_emote, e_frame);
+ if (effect != "")
+ {
+ movie_effects[e_frame].append("sfx^"+effect);
+ qDebug() << e_frame << effect;
+ }
+ }
#ifdef DEBUG_CHARMOVIE
qDebug() << max_frames << "Setting image to " << emote_path << "Time taken to process image:" << actual_time.elapsed();
@@ -71,6 +98,7 @@ void AOCharMovie::load_image(QString p_char, QString p_emote, QString emote_pref
void AOCharMovie::play()
{
+ play_frame_effect(frame);
if (max_frames <= 1)
return;
ticker->start(this->get_frame_delay(movie_delays[frame]));
@@ -101,6 +129,34 @@ void AOCharMovie::play_idle(QString p_char, QString p_emote)
play();
}
+void AOCharMovie::play_frame_effect(int frame)
+{
+ if(frame < max_frames)
+ {
+ foreach (QString effect, movie_effects[frame])
+ {
+ if(effect == "shake")
+ {
+ shake();
+ qDebug() << "Attempting to play shake on frame" << frame;
+ }
+
+ if(effect == "flash")
+ {
+ flash();
+ qDebug() << "Attempting to play flash on frame" << frame;
+ }
+
+ if(effect.startsWith("sfx^"))
+ {
+ QString sfx = effect.section("^", 1);
+ play_sfx(sfx);
+ qDebug() << "Attempting to play sfx" << sfx << "on frame" << frame;
+ }
+ }
+ }
+}
+
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
@@ -182,6 +238,7 @@ void AOCharMovie::movie_ticker()
#endif
this->set_frame(movie_frames[frame]);
+ play_frame_effect(frame);
ticker->setInterval(this->get_frame_delay(movie_delays[frame]));
}
diff --git a/src/aomovie.cpp b/src/aomovie.cpp
index 851ae570..7f7fb205 100644
--- a/src/aomovie.cpp
+++ b/src/aomovie.cpp
@@ -13,6 +13,7 @@ AOMovie::AOMovie(QWidget *p_parent, AOApplication *p_ao_app) : QLabel(p_parent)
this->setMovie(m_movie);
timer = new QTimer(this);
+ timer->setTimerType(Qt::PreciseTimer);
timer->setSingleShot(true);
connect(m_movie, SIGNAL(frameChanged(int)), this, SLOT(frame_change(int)));
@@ -24,11 +25,6 @@ void AOMovie::set_play_once(bool p_play_once)
play_once = p_play_once;
}
-void AOMovie::start_timer(int delay)
-{
- timer->start(delay);
-}
-
void AOMovie::play(QString p_image, QString p_char, QString p_custom_theme, int duration)
{
m_movie->stop();
@@ -65,7 +61,7 @@ void AOMovie::play(QString p_image, QString p_char, QString p_custom_theme, int
this->show();
m_movie->start();
if (m_movie->frameCount() == 0 && duration > 0)
- this->start_timer(duration);
+ timer->start(duration);
}
void AOMovie::stop()
@@ -81,17 +77,13 @@ void AOMovie::frame_change(int n_frame)
if (m_movie->frameCount() == 0 || n_frame < (m_movie->frameCount() - 1) || !play_once)
return;
//we need this or else the last frame wont show
- delay(m_movie->nextFrameDelay());
-
- this->stop();
-
- //signal connected to courtroom object, let it figure out what to do
- done();
+ timer->start(m_movie->nextFrameDelay());
}
void AOMovie::timer_done()
{
this->stop();
+ //signal connected to courtroom object, let it figure out what to do
done();
}
diff --git a/src/courtroom.cpp b/src/courtroom.cpp
index 47e3a0e7..30921d84 100644
--- a/src/courtroom.cpp
+++ b/src/courtroom.cpp
@@ -265,6 +265,9 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
connect(ui_vp_objection, SIGNAL(done()), this, SLOT(objection_done()));
connect(ui_vp_player_char, SIGNAL(done()), this, SLOT(preanim_done()));
+ connect(ui_vp_player_char, SIGNAL(shake()), this, SLOT(do_screenshake()));
+ connect(ui_vp_player_char, SIGNAL(flash()), this, SLOT(do_flash()));
+ connect(ui_vp_player_char, SIGNAL(play_sfx(QString)), this, SLOT(play_char_sfx(QString)));
connect(text_delay_timer, SIGNAL(timeout()), this, SLOT(start_chat_ticking()));
connect(sfx_delay_timer, SIGNAL(timeout()), this, SLOT(play_sfx()));
@@ -1655,47 +1658,58 @@ void Courtroom::handle_chatmessage_2()
void Courtroom::do_screenshake()
{
-//Code below causes segfault, do not uncomment unless you know what you're doing.
-// if (screenshake_animation_group != nullptr && 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<QWidget *> affected_list = {
- ui_vp_background,
- ui_vp_player_char,
- ui_vp_sideplayer_char,
- ui_vp_chatbox
- };
-
- int i = 0;
- //I would prefer if this was its own "shake" function to be honest.
- foreach (QWidget* ui_element, affected_list)
+ //This way, the animation is reset in such a way that last played screenshake would return to its "final frame" properly.
+ //This properly resets all UI elements without having to bother keeping track of "origin" positions.
+ //Works great wit the chat text being detached from the chat box!
+ screenshake_animation_group->setCurrentTime(screenshake_animation_group->duration());
+ screenshake_animation_group->clear();
+
+ QList<QWidget *> affected_list = {
+ ui_vp_background,
+ ui_vp_player_char,
+ ui_vp_sideplayer_char,
+ ui_vp_chatbox
+ };
+
+ int i = 0;
+ //I would prefer if this was its own "shake" function to be honest.
+ foreach (QWidget* ui_element, affected_list)
+ {
+ qDebug() << ++i;
+ 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++)
{
- qDebug() << ++i;
- 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);
+ 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);
+ screenshake_animation_group->start();
+}
+
+void Courtroom::do_flash()
+{
+ ui_vp_realization->play("realizationflash", "", "", 60);
+}
+
+void Courtroom::play_char_sfx(QString sfx_name)
+{
+ sfx_player->play(ao_app->get_sfx_suffix(sfx_name));
+ sfx_player->set_looping(ao_app->get_sfx_looping(current_char, sfx_name)!="0");
}
void Courtroom::handle_chatmessage_3()
@@ -1829,6 +1843,16 @@ 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)
{
@@ -2089,7 +2113,7 @@ void Courtroom::start_chat_ticking()
if (m_chatmessage[REALIZATION] == "1")
{
- ui_vp_realization->play("realizationflash", "", "", 60);
+ this->do_flash();
sfx_player->play(ao_app->get_custom_realization(m_chatmessage[CHAR_NAME]));
}
@@ -2208,6 +2232,18 @@ void Courtroom::chat_tick()
formatting_char = true;
}
+ else if (f_character == "@" and !next_character_is_not_special)
+ {
+ this->do_screenshake();
+ formatting_char = true;
+ }
+
+ else if (f_character == "$" and !next_character_is_not_special)
+ {
+ this->do_flash();
+ formatting_char = true;
+ }
+
// Orange inline colourisation.
else if (f_character == "|" and !next_character_is_not_special)
{
diff --git a/src/text_file_functions.cpp b/src/text_file_functions.cpp
index 9a0cd2fe..0944040c 100644
--- a/src/text_file_functions.cpp
+++ b/src/text_file_functions.cpp
@@ -578,6 +578,42 @@ int AOApplication::get_sfx_delay(QString p_char, int p_emote)
else return f_result.toInt();
}
+QString AOApplication::get_sfx_looping(QString p_char, QString p_sfx)
+{
+ QString f_result = read_char_ini(p_char, p_sfx, "SoundL");
+
+ if (f_result == "")
+ return "0";
+ else return f_result;
+}
+
+QString AOApplication::get_sfx_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("_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_flash_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_text_delay(QString p_char, QString p_emote)
{
QString f_result = read_char_ini(p_char, p_emote, "TextDelay");