Add effect layering under the character, flippable effects and more (#701)
* Fix effect offsets only applying after the effect already plays Add "_layer" property which can be "behind", "character" or default "chat". This deprecates the "under_chatbox" property * Add a "sticky" effect property which is the same as "stickyeffects" setting being enabled but just for that 1 effect * Clang is tidy, clang is caring * make character layer actually stack over the character but under the desk add new "over" layer which is over everything in the viewport but under the chat box * Switch "ignore_offset" to "respect_offset" so effects only respect character offsets if explicitly told to * Appease clang tidy... mostly. I don't understand the last thing it's talking about. * Appease clang tidy further * Remove "effect_done" due to it overwriting the AOLayers behavior Add "loop" effect property so you set up in the ini if the effect should loop rather than it using the file's loop settings Add "max_duration" effect property Add "cull" effect property which decides whether to clear the effect or not when it's done (if loop is false) * Fix effects not allowed to have underscores (_) in them without breaking * Change the way effects.ini looks and is parsed to be more sane and doable. However, since order may or may not matter, you can optionally include index:name and it orders it properly. * Appeal to clang * Fix a dumb way I created QSettings in get_effects * Fix effect properties being broken due to optional index * Fix get_effect_property not getting the current theme properties if a misc theme exists * If sound list has a sound effect selected, if pre is not checked, don't play effect sound and prefer the sfx we chose instead. * Fix \f not using the theme's realization effect * Add missing curly bracket * Yolo Co-authored-by: Salanto <62221668+Salanto@users.noreply.github.com> Co-authored-by: stonedDiscord <Tukz@gmx.de>
This commit is contained in:
parent
9849ce2610
commit
c8914c9302
@ -188,8 +188,7 @@ public:
|
|||||||
void set_scene(QString f_desk_mod, QString f_side);
|
void set_scene(QString f_desk_mod, QString f_side);
|
||||||
|
|
||||||
// sets ui_vp_player_char according to SELF_OFFSET, only a function bc it's used with desk_mod 4 and 5
|
// sets ui_vp_player_char according to SELF_OFFSET, only a function bc it's used with desk_mod 4 and 5
|
||||||
// sets ui_effects_layer according to the SELF_OFFSET, unless it is overwritten by effects.ini
|
void set_self_offset(const QString& p_list);
|
||||||
void set_self_offset(QString p_list, QString p_effect);
|
|
||||||
|
|
||||||
// takes in serverD-formatted IP list as prints a converted version to server
|
// takes in serverD-formatted IP list as prints a converted version to server
|
||||||
// OOC admittedly poorly named
|
// OOC admittedly poorly named
|
||||||
@ -821,7 +820,6 @@ private:
|
|||||||
void regenerate_ic_chatlog();
|
void regenerate_ic_chatlog();
|
||||||
public slots:
|
public slots:
|
||||||
void objection_done();
|
void objection_done();
|
||||||
void effect_done();
|
|
||||||
void preanim_done();
|
void preanim_done();
|
||||||
void do_screenshake();
|
void do_screenshake();
|
||||||
void do_flash();
|
void do_flash();
|
||||||
|
@ -411,8 +411,6 @@ Courtroom::Courtroom(AOApplication *p_ao_app) : QMainWindow()
|
|||||||
connect(keepalive_timer, &QTimer::timeout, this, &Courtroom::ping_server);
|
connect(keepalive_timer, &QTimer::timeout, this, &Courtroom::ping_server);
|
||||||
|
|
||||||
connect(ui_vp_objection, &SplashLayer::done, this, &Courtroom::objection_done);
|
connect(ui_vp_objection, &SplashLayer::done, this, &Courtroom::objection_done);
|
||||||
connect(ui_vp_effect, &EffectLayer::done, this, &Courtroom::effect_done);
|
|
||||||
connect(ui_vp_wtce, &SplashLayer::done, this, &Courtroom::effect_done);
|
|
||||||
connect(ui_vp_player_char, &CharLayer::done, this, &Courtroom::preanim_done);
|
connect(ui_vp_player_char, &CharLayer::done, this, &Courtroom::preanim_done);
|
||||||
connect(ui_vp_player_char, &CharLayer::shake, this, &Courtroom::do_screenshake);
|
connect(ui_vp_player_char, &CharLayer::shake, this, &Courtroom::do_screenshake);
|
||||||
connect(ui_vp_player_char, &CharLayer::flash, this, &Courtroom::do_flash);
|
connect(ui_vp_player_char, &CharLayer::flash, this, &Courtroom::do_flash);
|
||||||
@ -2056,8 +2054,14 @@ void Courtroom::on_chat_return_pressed()
|
|||||||
ao_app->get_effect_property(effect, current_char, "sound");
|
ao_app->get_effect_property(effect, current_char, "sound");
|
||||||
QString p_effect =
|
QString p_effect =
|
||||||
ao_app->read_char_ini(current_char, "effects", "Options");
|
ao_app->read_char_ini(current_char, "effects", "Options");
|
||||||
|
|
||||||
|
// Don't overlap the two sfx
|
||||||
|
if (!ui_pre->isChecked() && (!custom_sfx.isEmpty() || ui_sfx_dropdown->currentIndex() == 1)) {
|
||||||
|
fx_sound = "0";
|
||||||
|
}
|
||||||
|
|
||||||
packet_contents.append(effect + "|" + p_effect + "|" + fx_sound);
|
packet_contents.append(effect + "|" + p_effect + "|" + fx_sound);
|
||||||
if (!ao_app->is_stickyeffects_enabled()) {
|
if (!ao_app->is_stickyeffects_enabled() && !ao_app->get_effect_property(effect, current_char, "sticky").startsWith("true")) {
|
||||||
ui_effects_dropdown->blockSignals(true);
|
ui_effects_dropdown->blockSignals(true);
|
||||||
ui_effects_dropdown->setCurrentIndex(0);
|
ui_effects_dropdown->setCurrentIndex(0);
|
||||||
ui_effects_dropdown->blockSignals(false);
|
ui_effects_dropdown->blockSignals(false);
|
||||||
@ -2396,12 +2400,6 @@ bool Courtroom::handle_objection()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Courtroom::effect_done()
|
|
||||||
{
|
|
||||||
ui_vp_effect->stop();
|
|
||||||
ui_vp_wtce->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Courtroom::display_character()
|
void Courtroom::display_character()
|
||||||
{
|
{
|
||||||
// Stop all previously playing animations, effects etc.
|
// Stop all previously playing animations, effects etc.
|
||||||
@ -2436,13 +2434,10 @@ void Courtroom::display_character()
|
|||||||
else
|
else
|
||||||
ui_vp_player_char->network_strings.clear();
|
ui_vp_player_char->network_strings.clear();
|
||||||
|
|
||||||
// Determine if we should flip the character or not (what servers don't support flipping at this point?)
|
// Determine if we should flip the character or not
|
||||||
if (ao_app->flipping_enabled && m_chatmessage[FLIP].toInt() == 1)
|
ui_vp_player_char->set_flipped(m_chatmessage[FLIP].toInt() == 1);
|
||||||
ui_vp_player_char->set_flipped(true);
|
|
||||||
else
|
|
||||||
ui_vp_player_char->set_flipped(false);
|
|
||||||
// Move the character on the viewport according to the offsets
|
// Move the character on the viewport according to the offsets
|
||||||
set_self_offset(m_chatmessage[SELF_OFFSET], m_chatmessage[EFFECTS]);
|
set_self_offset(m_chatmessage[SELF_OFFSET]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Courtroom::display_pair_character(QString other_charid, QString other_offset)
|
void Courtroom::display_pair_character(QString other_charid, QString other_offset)
|
||||||
@ -2652,45 +2647,100 @@ void Courtroom::do_flash()
|
|||||||
|
|
||||||
QString f_char = m_chatmessage[CHAR_NAME];
|
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);
|
||||||
ui_vp_effect->stretch = true;
|
do_effect("realization", "", f_char, f_custom_theme);
|
||||||
ui_vp_effect->set_static_duration(60);
|
|
||||||
ui_vp_effect->set_max_duration(60);
|
|
||||||
ui_vp_player_char->stackUnder(ui_vp_objection); // go above the chatbox
|
|
||||||
ui_vp_effect->load_image(
|
|
||||||
ao_app->get_effect("realization", f_char, f_custom_theme), false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Courtroom::do_effect(QString fx_name, QString fx_sound, QString p_char,
|
void Courtroom::do_effect(QString fx_path, QString fx_sound, QString p_char,
|
||||||
QString p_folder)
|
QString p_folder)
|
||||||
{
|
{
|
||||||
if (fx_name == "")
|
if (fx_path == "") {
|
||||||
return;
|
return;
|
||||||
QString effect = ao_app->get_effect(fx_name, p_char, p_folder);
|
}
|
||||||
if (effect == "")
|
QString effect = ao_app->get_effect(fx_path, p_char, p_folder);
|
||||||
|
if (effect == "") {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (fx_sound != "")
|
if (fx_sound != "") {
|
||||||
sfx_player->play(fx_sound);
|
sfx_player->play(fx_sound);
|
||||||
|
}
|
||||||
|
|
||||||
// Only check if effects are disabled after playing the sound if it exists
|
// Only check if effects are disabled after playing the sound if it exists
|
||||||
if (!ao_app->is_effects_enabled())
|
if (!ao_app->is_effects_enabled()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
ui_vp_effect->transform_mode = ao_app->get_scaling(
|
ui_vp_effect->transform_mode = ao_app->get_scaling(
|
||||||
ao_app->get_effect_property(fx_name, p_char, "scaling"));
|
ao_app->get_effect_property(fx_path, p_char, "scaling"));
|
||||||
ui_vp_effect->stretch =
|
ui_vp_effect->stretch =
|
||||||
ao_app->get_effect_property(fx_name, p_char, "stretch")
|
ao_app->get_effect_property(fx_path, p_char, "stretch")
|
||||||
.startsWith("true");
|
.startsWith("true");
|
||||||
bool under_chatbox = ao_app->get_effect_property(fx_name, p_char, "under_chatbox").startsWith("true");
|
ui_vp_effect->set_flipped(ao_app->get_effect_property(fx_path, p_char, "respect_flip").startsWith("true") && m_chatmessage[FLIP].toInt() == 1);
|
||||||
if (under_chatbox)
|
|
||||||
ui_vp_effect->stackUnder(ui_vp_chatbox);
|
|
||||||
else
|
|
||||||
ui_vp_effect->stackUnder(ui_vp_objection);
|
|
||||||
ui_vp_effect->set_play_once(
|
ui_vp_effect->set_play_once(
|
||||||
false); // The effects themselves dictate whether or not they're looping.
|
false); // The effects themselves dictate whether or not they're looping.
|
||||||
// Static effects will linger.
|
// Static effects will linger.
|
||||||
ui_vp_effect->set_static_duration(0);
|
|
||||||
ui_vp_effect->set_max_duration(0);
|
bool looping =
|
||||||
ui_vp_effect->load_image(effect, true);
|
ao_app->get_effect_property(fx_path, p_char, "loop")
|
||||||
|
.startsWith("true");
|
||||||
|
|
||||||
|
int max_duration =
|
||||||
|
ao_app->get_effect_property(fx_path, p_char, "max_duration")
|
||||||
|
.toInt();
|
||||||
|
|
||||||
|
bool cull =
|
||||||
|
ao_app->get_effect_property(fx_path, p_char, "cull")
|
||||||
|
.startsWith("true");
|
||||||
|
|
||||||
|
// Possible values: "chat", "character", "behind"
|
||||||
|
QString layer = ao_app->get_effect_property(fx_path, p_char, "layer").toLower();
|
||||||
|
if (layer == "behind"){
|
||||||
|
ui_vp_effect->setParent(ui_viewport);
|
||||||
|
ui_vp_effect->stackUnder(ui_vp_player_char);
|
||||||
|
}
|
||||||
|
else if (layer == "character") {
|
||||||
|
ui_vp_effect->setParent(ui_viewport);
|
||||||
|
ui_vp_effect->stackUnder(ui_vp_desk);
|
||||||
|
}
|
||||||
|
else if (layer == "over") {
|
||||||
|
ui_vp_effect->setParent(ui_viewport);
|
||||||
|
ui_vp_effect->raise();
|
||||||
|
}
|
||||||
|
else { // if (layer == "chat") {
|
||||||
|
ui_vp_effect->setParent(this);
|
||||||
|
ui_vp_effect->stackUnder(ui_vp_objection);
|
||||||
|
}
|
||||||
|
|
||||||
|
int effect_x = 0;
|
||||||
|
int effect_y = 0;
|
||||||
|
// The effect is not parented to viewport, meaning we're overlaying ui elements
|
||||||
|
if (ui_vp_effect->parentWidget() != ui_viewport) {
|
||||||
|
//We need to add the viewport as an offset as effects are not bound to it.
|
||||||
|
effect_x = ui_viewport->x();
|
||||||
|
effect_y = ui_viewport->y();
|
||||||
|
}
|
||||||
|
// This effect respects the character offset settings
|
||||||
|
if (ao_app->get_effect_property(fx_path, p_char, "respect_offset") == "true") {
|
||||||
|
QStringList self_offsets = m_chatmessage[SELF_OFFSET].split("&");
|
||||||
|
int self_offset = self_offsets[0].toInt();
|
||||||
|
int self_offset_v;
|
||||||
|
if (self_offsets.length() <= 1) {
|
||||||
|
self_offset_v = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
self_offset_v = self_offsets[1].toInt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move the effects layer to match the position of our character
|
||||||
|
const int percent = 100;
|
||||||
|
effect_x += ui_viewport->width() * self_offset / percent;
|
||||||
|
effect_y += ui_viewport->height() * self_offset_v / percent;
|
||||||
|
}
|
||||||
|
ui_vp_effect->move(effect_x, effect_y);
|
||||||
|
|
||||||
|
ui_vp_effect->set_static_duration(max_duration);
|
||||||
|
ui_vp_effect->set_max_duration(max_duration);
|
||||||
|
ui_vp_effect->load_image(effect, looping);
|
||||||
|
ui_vp_effect->set_cull_image(cull);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Courtroom::play_char_sfx(QString sfx_name)
|
void Courtroom::play_char_sfx(QString sfx_name)
|
||||||
@ -3385,7 +3435,7 @@ void Courtroom::start_chat_ticking()
|
|||||||
// handle expanded desk mods
|
// handle expanded desk mods
|
||||||
switch(m_chatmessage[DESK_MOD].toInt()) {
|
switch(m_chatmessage[DESK_MOD].toInt()) {
|
||||||
case 4:
|
case 4:
|
||||||
set_self_offset(m_chatmessage[SELF_OFFSET], QString("||"));
|
set_self_offset(m_chatmessage[SELF_OFFSET]);
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case 2:
|
case 2:
|
||||||
set_scene("1", m_chatmessage[SIDE]);
|
set_scene("1", m_chatmessage[SIDE]);
|
||||||
@ -3785,28 +3835,19 @@ void Courtroom::set_scene(const QString f_desk_mod, const QString f_side)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Courtroom::set_self_offset(QString p_list, QString p_effect) {
|
void Courtroom::set_self_offset(const QString& p_list) {
|
||||||
QStringList self_offsets = p_list.split("&");
|
QStringList self_offsets = p_list.split("&");
|
||||||
QStringList play_effect = p_effect.split("|");
|
|
||||||
int self_offset = self_offsets[0].toInt();
|
int self_offset = self_offsets[0].toInt();
|
||||||
int self_offset_v;
|
int self_offset_v;
|
||||||
if (self_offsets.length() <= 1)
|
if (self_offsets.length() <= 1) {
|
||||||
self_offset_v = 0;
|
self_offset_v = 0;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
self_offset_v = self_offsets[1].toInt();
|
self_offset_v = self_offsets[1].toInt();
|
||||||
ui_vp_player_char->move_and_center(ui_viewport->width() * self_offset / 100, ui_viewport->height() * self_offset_v / 100);
|
ui_vp_player_char->move_and_center(ui_viewport->width() * self_offset / 100, ui_viewport->height() * self_offset_v / 100);
|
||||||
|
const int percent = 100;
|
||||||
//If an effect is ignoring the users offset, we force it to the default position of the viewport.
|
ui_vp_player_char->move(ui_viewport->width() * self_offset / percent, ui_viewport->height() * self_offset_v / percent);
|
||||||
if (ao_app->get_effect_property(play_effect[0], current_char, "ignore_offset") == "true") {
|
|
||||||
ui_vp_effect->move(ui_viewport->x(), ui_viewport->y());
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Offset is not disabled, we move the effects layer to match the position of our character
|
|
||||||
//We need to add the viewport as an offset as effects are not bound to it.
|
|
||||||
int effect_x = (ui_viewport->width() * self_offset / 100) + ui_viewport->x();
|
|
||||||
int effect_y = (ui_viewport->height() * self_offset_v / 100) + ui_viewport->y();
|
|
||||||
ui_vp_effect->move(effect_x, effect_y);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Courtroom::set_ip_list(QString p_list)
|
void Courtroom::set_ip_list(QString p_list)
|
||||||
@ -4607,9 +4648,17 @@ void Courtroom::set_effects_dropdown()
|
|||||||
ui_effects_dropdown->hide();
|
ui_effects_dropdown->hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QStringList effectslist = ao_app->get_effects(current_char);
|
QStringList effectslist;
|
||||||
|
QStringList char_effects = ao_app->get_effects(current_char);
|
||||||
|
for (int i = 0; i < char_effects.size(); ++i) {
|
||||||
|
QString effect = char_effects[i];
|
||||||
|
if (effect.contains(":")) {
|
||||||
|
effect = effect.section(':', 1);
|
||||||
|
}
|
||||||
|
effectslist.append(effect);
|
||||||
|
}
|
||||||
|
|
||||||
if (effectslist.size() <= 0) {
|
if (effectslist.empty()) {
|
||||||
ui_effects_dropdown->hide();
|
ui_effects_dropdown->hide();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -877,19 +877,18 @@ QStringList AOApplication::get_effects(QString p_char)
|
|||||||
QString p_misc = read_char_ini(p_char, "effects", "Options");
|
QString p_misc = read_char_ini(p_char, "effects", "Options");
|
||||||
QString p_path = get_asset("effects/effects.ini", current_theme, get_subtheme(), default_theme, "");
|
QString p_path = get_asset("effects/effects.ini", current_theme, get_subtheme(), default_theme, "");
|
||||||
QString p_misc_path = get_asset("effects.ini", current_theme, get_subtheme(), default_theme, p_misc);
|
QString p_misc_path = get_asset("effects.ini", current_theme, get_subtheme(), default_theme, p_misc);
|
||||||
QStringList effects;
|
QSettings effects_config(p_path, QSettings::IniFormat);
|
||||||
|
effects_config.setIniCodec("UTF-8");
|
||||||
QStringList lines = read_file(p_path).split("\n");
|
QStringList effects = effects_config.childGroups();
|
||||||
// Misc path different from default path, stack the new miscs on top of the defaults
|
std::sort(effects.begin(), effects.end(), [] (const QString &a, const QString &b) {return a.split(":")[0].toInt() < b.split(":")[0].toInt();});
|
||||||
if (p_misc_path != p_path) {
|
if (p_path != p_misc_path) {
|
||||||
lines << read_file(p_misc_path).split("\n");
|
// If misc path is different from default path, stack the new miscs on top of the defaults
|
||||||
|
QSettings effects_config_misc(p_misc_path, QSettings::IniFormat);
|
||||||
|
effects_config_misc.setIniCodec("UTF-8");
|
||||||
|
QStringList misc_effects = effects_config_misc.childGroups();
|
||||||
|
std::sort(misc_effects.begin(), misc_effects.end(), [] (const QString &a, const QString &b) {return a.split(":")[0].toInt() < b.split(":")[0].toInt();});
|
||||||
|
effects += misc_effects;
|
||||||
}
|
}
|
||||||
foreach (QString effect, lines) {
|
|
||||||
effect = effect.split("=")[0].trimmed().split("_")[0];
|
|
||||||
if (!effect.isEmpty() && !effects.contains(effect))
|
|
||||||
effects.append(effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
return effects;
|
return effects;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -913,15 +912,31 @@ QString AOApplication::get_effect(QString effect, QString p_char,
|
|||||||
QString AOApplication::get_effect_property(QString fx_name, QString p_char,
|
QString AOApplication::get_effect_property(QString fx_name, QString p_char,
|
||||||
QString p_property)
|
QString p_property)
|
||||||
{
|
{
|
||||||
QString f_property;
|
const auto paths = get_asset_paths("effects/effects.ini", current_theme, get_subtheme(), default_theme, "");
|
||||||
if (p_property == "sound")
|
const auto misc_paths = get_asset_paths("effects.ini", current_theme, get_subtheme(), default_theme, read_char_ini(p_char, "effects", "Options"));
|
||||||
f_property = fx_name;
|
QString path;
|
||||||
else
|
QString f_result;
|
||||||
f_property = fx_name + "_" + p_property;
|
for (const VPath &p : paths + misc_paths) {
|
||||||
|
path = get_real_path(p);
|
||||||
QString f_result = get_config_value(f_property, "effects.ini", current_theme, get_subtheme(), default_theme, read_char_ini(p_char, "effects", "Options"));
|
if (!path.isEmpty()) {
|
||||||
if (f_result == "")
|
QSettings settings(path, QSettings::IniFormat);
|
||||||
f_result = get_config_value(f_property, "effects/effects.ini", current_theme, get_subtheme(), default_theme, "");
|
settings.setIniCodec("UTF-8");
|
||||||
|
QStringList char_effects = settings.childGroups();
|
||||||
|
for (int i = 0; i < char_effects.size(); ++i) {
|
||||||
|
QString effect = char_effects[i];
|
||||||
|
if (effect.contains(":")) {
|
||||||
|
effect = effect.section(':', 1);
|
||||||
|
}
|
||||||
|
if (effect.toLower() == fx_name.toLower()) {
|
||||||
|
f_result = settings.value(char_effects[i] + "/" + p_property).toString();
|
||||||
|
if (!f_result.isEmpty()) {
|
||||||
|
// Only break the loop if we get a non-empty result, continue the search otherwise
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (fx_name == "realization" && p_property == "sound") {
|
if (fx_name == "realization" && p_property == "sound") {
|
||||||
f_result = get_custom_realization(p_char);
|
f_result = get_custom_realization(p_char);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user